88 lines
2.2 KiB
JavaScript
88 lines
2.2 KiB
JavaScript
import React from 'react';
|
|
import { Map } from 'immutable';
|
|
|
|
const reflowable = Component => {
|
|
Object.assign(Component.prototype, {
|
|
_currentBBox() {
|
|
return this.tempBBox ? this.tempBBox : (this.state || {}).bbox;
|
|
},
|
|
|
|
setStateAsync(state) {
|
|
return new Promise(resolve => {
|
|
this.setState(state, resolve);
|
|
});
|
|
},
|
|
|
|
async setBBox(box, recalculate = {}) {
|
|
const bbox = (this._currentBBox() || Map({ width: 0, height: 0})).withMutations(bbox => {
|
|
bbox.merge(box);
|
|
|
|
if (!bbox.has('axisY') || recalculate.axisY) {
|
|
bbox.set('axisY', bbox.get('height') / 2);
|
|
}
|
|
|
|
if (!bbox.has('axisX1') || recalculate.axisX1) {
|
|
bbox.set('axisX1', 0);
|
|
}
|
|
|
|
if (!bbox.has('axisX2') || recalculate.axisX2) {
|
|
bbox.set('axisX2', bbox.get('width'));
|
|
}
|
|
});
|
|
|
|
this.tempBBox = bbox; // Want to get the updated bbox while setState is pending
|
|
await this.setStateAsync({ bbox });
|
|
this.tempBBox = null;
|
|
},
|
|
|
|
getBBox() {
|
|
const bbox = this._currentBBox() || Map();
|
|
return {
|
|
width: 0,
|
|
height: 0,
|
|
axisY: 0,
|
|
axisX1: 0,
|
|
axisX2: 0,
|
|
...bbox.toJS()
|
|
};
|
|
},
|
|
|
|
makeRefCollection(collection, count) {
|
|
const diff = Math.abs(collection.length - count);
|
|
|
|
if (collection.length < count) {
|
|
const fill = Array.apply(null, new Array(diff)).map(() => React.createRef());
|
|
collection.splice.apply(collection, [collection.length, diff, ...fill]);
|
|
} else if (collection.length > count) {
|
|
collection.splice(collection.length - diff, diff);
|
|
}
|
|
},
|
|
|
|
async reflowChildren() {
|
|
// No child components
|
|
if (this.children === undefined) {
|
|
return true;
|
|
}
|
|
|
|
const reflowed = await Promise.all(this.children.map(c => c.current.doReflow()));
|
|
|
|
return reflowed.reduce((memo, value) => memo || value, false);
|
|
},
|
|
|
|
async doReflow() {
|
|
const oldBBox = this._currentBBox();
|
|
const shouldReflow = await this.reflowChildren();
|
|
|
|
if (shouldReflow) {
|
|
this.reflow();
|
|
}
|
|
|
|
return this._currentBBox() !== oldBBox;
|
|
}
|
|
});
|
|
|
|
return Component;
|
|
};
|
|
|
|
export default reflowable;
|