Support element rows

master
Vitaliy Filippov 2019-02-08 19:45:21 +03:00
parent 67297ccdce
commit 5880fa26ea
1 changed files with 81 additions and 59 deletions

View File

@ -37,7 +37,8 @@ export class FixedHeaderGridTable extends React.PureComponent
{
static propTypes = {
theme: PropTypes.object,
rows: PropTypes.arrayOf(PropTypes.array).isRequired,
rows: PropTypes.array.isRequired,
columnWidths: PropTypes.arrayOf(PropTypes.string),
isResizable: PropTypes.arrayOf(PropTypes.bool),
noWrapDefault: PropTypes.bool,
hasRowHover: PropTypes.bool,
@ -295,6 +296,73 @@ export class FixedHeaderGridTable extends React.PureComponent
this.rootNode = e;
}
decorateCells(row, decorateProps)
{
const css = this.props.theme || default_css;
let cells = [];
let j = 0;
for (let cell of row)
{
if (cell == null)
{
// Skip null or undefined cells
continue;
}
const isDiv = React.isValidElement(cell) && cell.type == 'div';
const className = ' ' + css.cell + ' ' +
(decorateProps.rowIndex == 0 ? ' '+css.first_row : '') +
(decorateProps.rowIndex == decorateProps.rowCount-1 ? ' '+css.last_row : '') +
(j == 0 && (!isDiv || !cell.props.style ||
!cell.props.style.gridColumn && !cell.props.style.gridColumnStart ||
cell.props.style.gridColumn == 1 || cell.props.style.gridColumnStart == 1) ? ' '+css.first_col : '') +
(j == row.length-1 ? ' '+css.last_col : '') +
(j & 1 ? ' '+css.even : '');
if (!isDiv)
{
cell = (<div className={className} row={decorateProps.rowIndex} col={j} key={decorateProps.rowIndex+'-'+j}>
{this.props.noWrapDefault
? <div className={css.ellipsis}>{cell}</div>
: cell}
</div>);
}
else
{
let spec = {};
let cls = cell.props.className
? cell.props.className.replace(/(^|\s)(wrap)(?=$|\s)/g, (m, m1, m2) => { spec[m2] = true; return ''; })
: '';
if (cell.props.sticky_col < 0)
cls = cls + ' ' + css.stick_right;
else if (cell.props.sticky_col > 0)
cls = cls + ' ' + css.stick_left;
if (cell.props.sticky_row < 0)
cls = cls + ' ' + css.stick_bottom;
else if (cell.props.sticky_row > 0)
cls = cls + ' ' + css.stick_top;
let props = {
row: decorateProps.rowIndex,
col: j,
key: decorateProps.rowIndex+'-'+j,
className: cls+className,
};
if (spec.wrap || !this.props.noWrapDefault)
{
cell = React.cloneElement(cell, props);
}
else
{
// By default cells are non-wrappable with text-overflow: ellipsis
cell = React.cloneElement(cell, props, (<div className={css.ellipsis}>
{cell.props.children}
</div>));
}
}
cells.push(cell);
j++;
}
return cells;
}
render()
{
const css = this.props.theme || default_css;
@ -303,65 +371,19 @@ export class FixedHeaderGridTable extends React.PureComponent
let i = 0;
for (let row of rows)
{
let j = 0;
for (let cell of row)
const rowProps = { rowIndex: i, rowCount: rows.length };
if (React.isValidElement(row))
{
if (cell == null)
{
// skip null or undefined cells
continue;
}
const isDiv = React.isValidElement(cell) && cell.type == 'div';
const className = ' ' + css.cell + ' ' +
(i == 0 ? ' '+css.first_row : '') +
(i == rows.length-1 ? ' '+css.last_row : '') +
(j == 0 && (!isDiv || !cell.props.style ||
!cell.props.style.gridColumn && !cell.props.style.gridColumnStart ||
cell.props.style.gridColumn == 1 || cell.props.style.gridColumnStart == 1) ? ' '+css.first_col : '') +
(j == row.length-1 ? ' '+css.last_col : '') +
(j & 1 ? ' '+css.even : '');
if (!isDiv)
{
cell = (<div className={className} row={i} col={j} key={i+'-'+j}>
{this.props.noWrapDefault
? <div className={css.ellipsis}>{cell}</div>
: cell}
</div>);
}
else
{
let spec = {};
let cls = cell.props.className
? cell.props.className.replace(/(^|\s)(wrap)(?=$|\s)/g, (m, m1, m2) => { spec[m2] = true; return ''; })
: '';
if (cell.props.sticky_col < 0)
cls = cls + ' ' + css.stick_right;
else if (cell.props.sticky_col > 0)
cls = cls + ' ' + css.stick_left;
if (cell.props.sticky_row < 0)
cls = cls + ' ' + css.stick_bottom;
else if (cell.props.sticky_row > 0)
cls = cls + ' ' + css.stick_top;
let props = {
row: i,
col: j,
key: i+'-'+j,
className: cls+className,
};
if (spec.wrap || !this.props.noWrapDefault)
{
cell = React.cloneElement(cell, props);
}
else
{
// By default cells are non-wrappable with text-overflow: ellipsis
cell = React.cloneElement(cell, props, (<div className={css.ellipsis}>
{cell.props.children}
</div>));
}
}
cells.push(cell);
j++;
// Allow element rows
// In fact, this should be the default use-case
rowProps.decorateCells = (cells) => this.decorateCells(cells, rowProps);
cells.push(React.cloneElement(row, rowProps));
}
else
{
// In other case just process cells in-place
// BUT this is slow, because such cells are reconciled on each render
cells.push.apply(cells, this.decorateCells(row, rowProps));
}
i++;
}