145 lines
3.5 KiB
JavaScript
145 lines
3.5 KiB
JavaScript
import React, {Component} from 'react';
|
|
import './Grid.css';
|
|
import GridComponent from './GridComponent/GridComponent';
|
|
|
|
const DEFAULT_GRID_SIZE = 4;
|
|
|
|
export default class Grid extends Component {
|
|
resizeTimeout;
|
|
state = {
|
|
calculated: false,
|
|
dimensions: {
|
|
columns: 0,
|
|
rows: 0
|
|
}
|
|
};
|
|
|
|
calculateDimensions = size => {
|
|
return {
|
|
columns: Math.floor(size.width / this.getGridSize()),
|
|
rows: Math.floor(size.height / this.getGridSize())
|
|
};
|
|
};
|
|
|
|
componentDidMount() {
|
|
window.addEventListener('resize', this.handleResize);
|
|
this.updateSizeAsync();
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
window.removeEventListener('resize', this.handleResize);
|
|
clearInterval(this.resizeTimeout);
|
|
};
|
|
|
|
getGridSize = () => {
|
|
return this.props.gridSize || DEFAULT_GRID_SIZE;
|
|
};
|
|
|
|
getGridSizePx = () => {
|
|
return this.getGridSize() + 'px ';
|
|
};
|
|
|
|
getSize = () => {
|
|
const elem = this.refs.GridOwner;
|
|
return {
|
|
height: elem ? elem.offsetHeight : 0,
|
|
width: elem ? elem.offsetWidth : 0
|
|
};
|
|
};
|
|
|
|
handleResize = () => {
|
|
clearTimeout(this.resizeTimeout);
|
|
this.resizeTimeout = setTimeout(this.updateSizeAsync, 10);
|
|
};
|
|
|
|
updateSize = () => {
|
|
const state = {
|
|
...this.state
|
|
};
|
|
const size = this.getSize();
|
|
const dimensions = this.calculateDimensions(size);
|
|
if (state.dimensions !== dimensions) {
|
|
this.setState({
|
|
calculated: true,
|
|
dimensions: dimensions
|
|
})
|
|
}
|
|
};
|
|
|
|
updateSizeAsync = () => {
|
|
return new Promise(() => {
|
|
this.updateSize();
|
|
});
|
|
};
|
|
|
|
render() {
|
|
let children = null;
|
|
const dimensions = this.state.dimensions;
|
|
if (this.state.calculated) {
|
|
children = React.Children.map(this.props.children, (child, i) => {
|
|
if (child) {
|
|
let row = child.props.row || 0;
|
|
if (typeof(row) === 'function') {
|
|
row = row(dimensions);
|
|
}
|
|
|
|
let col = child.props.col || 0;
|
|
if (typeof(col) === 'function') {
|
|
col = col(dimensions);
|
|
}
|
|
|
|
let rowSpan = child.props.rowSpan;
|
|
if (typeof(rowSpan) === 'function') {
|
|
rowSpan = rowSpan(dimensions.rows - row, dimensions.rows);
|
|
}
|
|
|
|
let colSpan = child.props.colSpan;
|
|
if (typeof(colSpan) === 'function') {
|
|
colSpan = colSpan(dimensions.columns - col, dimensions.columns);
|
|
}
|
|
|
|
rowSpan = rowSpan ? (rowSpan === 'remain' ? (dimensions.rows - row) : rowSpan) : null;
|
|
colSpan = colSpan ? (colSpan === 'remain' ? dimensions.columns - col : colSpan) : null;
|
|
|
|
return (
|
|
<GridComponent row={row}
|
|
col={col}
|
|
rowSpan={rowSpan}
|
|
colSpan={colSpan}
|
|
key={'gc_' + i}>
|
|
{child}
|
|
</GridComponent>
|
|
);
|
|
} else {
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
const gridSizePx = this.getGridSizePx();
|
|
let style = {
|
|
style: {
|
|
gridTemplateColumns: gridSizePx.repeat(dimensions.columns),
|
|
gridTemplateRows: gridSizePx.repeat(dimensions.rows),
|
|
gridAutoColumns: gridSizePx,
|
|
gridAutoRows: gridSizePx,
|
|
}
|
|
};
|
|
|
|
if (this.props.noScroll) {
|
|
style['style'].overflowX = 'visible';
|
|
style['style'].overflowY = 'visible';
|
|
}
|
|
|
|
return (
|
|
<div
|
|
ref='GridOwner'
|
|
className={'GridOwner'}>
|
|
<div className={'Grid'} {...style}>
|
|
{children}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
};
|