hc-components
Version:
基于react的通用组件库
149 lines (140 loc) • 4.25 kB
JSX
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
// see: https://github.com/STRML/react-grid-layout
import GridLayout from 'react-grid-layout';
export class FlexGridLayer extends React.PureComponent {
// static providers = ['resizer'];
static contextTypes = {
resizer: PropTypes.object,
layer: PropTypes.object
}
static propTypes = {
components: PropTypes.array,
LayerItem: PropTypes.any,
onLayerChange: PropTypes.func,
autoGrid: PropTypes.bool,
isResizable: PropTypes.bool,
style: PropTypes.object
};
state = {
width: 800
}
_nextVectors = [];
componentDidMount() {
/* eslint-disable react/no-find-dom-node */
const dom = ReactDOM.findDOMNode(this);
this.setState({
width: dom.offsetWidth
}, () => {
if (this.context.resizer) {
this._cancelResize = this.context.resizer.resize(dom, () => {
this.setState({
width: dom.offsetWidth
});
});
}
});
}
componentWillUnmount() {
this._cancelResize && this._cancelResize();
}
getGridVector(vectors) {
if (this._nextVectors.length) {
return this._nextVectors.shift();
}
const precedent = !!vectors[0];
// 一行分6个
const count = 12;
// 所有高度
const hArr = new Array(count);
// x轴只判断一遍
const xArr = [];
// 最低高度
let minHeight = precedent ? count : 0;
// 最低高度的下标
let minHkey = 0;
let tmpHeight;
for (let i = vectors.length; i--;) {
tmpHeight = vectors[i].y + vectors[i].h;
if (tmpHeight <= minHeight && !xArr[vectors[i].x]) {
minHeight = tmpHeight;
minHkey = i;
xArr[vectors[i].x] = true;
}
// 首行占用了多少位置
if (vectors[i].y === 0) {
for (let j = 0; j < vectors[i].w; j++) {
hArr[vectors[i].x + j] = true;
}
}
}
const minH = 3;
const minW = 4;
let k = 0;
// 已占有2个宽度为准
let fWidth = 0;
// 有占用时的下标
let fWkey = 0;
if (hArr.length) {
while (fWkey < count) {
if (hArr[fWkey]) {
fWkey++;
} else {
while (k < minW) {
if ((fWkey + k) < count && !hArr[fWkey + k]) {
fWidth++;
}
k++;
}
break;
}
}
}
// 未占满
let vector;
if (fWidth === minW) {
vector = {x: fWkey, y: 0, w: fWidth, h: minH};
} else if (precedent) {
// 重要,如果一个模块下,可以容纳2个,那么就加入2个
const mults = Math.floor(vectors[minHkey].w / minW);
if (mults > 1) {
vector = {x: vectors[minHkey].x, y: minHeight, w: minW, h: minH};
for (let z = 1; z < mults; z++) {
this._nextVectors.push({x: vectors[minHkey].x + minW * z, y: minHeight, w: minW * z, h: minH});
}
} else {
vector = {x: vectors[minHkey].x, y: minHeight, w: vectors[minHkey].w, h: minH};
}
} else {
vector = {x: 0, y: 0, w: minW, h: minH};
}
return vector;
}
render() {
const {components, LayerItem, onLayerChange, autoGrid, isResizable, style} = this.props;
const editable = this.context.layer.isEditable();
const enabled = isResizable || editable;
const vectors = [];
return (
<div style={Object.assign({position: 'relative'}, style)} className="o-layer o-layer-flexGrid" >
<GridLayout isDraggable={enabled} isResizable={enabled} cols={12} rowHeight={100} width={this.state.width} >
{components.map((item, index) => {
let vector = item.attrs.vector;
if (autoGrid) {
if (!vector) {
vector = item.attrs.vector = this.getGridVector(vectors);
}
vectors.push(vector);
}
return (<div key={item.key || index} data-tt={1} data-grid={vector}>
<LayerItem onChange={onLayerChange} {...item.attrs} >
{item && item.component ? (<item.component />) : null}
</LayerItem>
</div>);
})}
</GridLayout>
</div>
);
}
}