Moving to using a decorator mixin instead of base class for SVGs
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Base from 'components/SVG/Base';
|
||||
import reflowable from 'components/SVG/reflowable';
|
||||
|
||||
class SVGElement extends Base {
|
||||
@reflowable
|
||||
class SVGElement extends React.PureComponent {
|
||||
reflow() {
|
||||
return this.setBBox(this.props.bbox);
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Map } from 'immutable';
|
||||
|
||||
class Base extends React.PureComponent {
|
||||
_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()
|
||||
};
|
||||
}
|
||||
|
||||
async reflowChildren() {
|
||||
// No child components
|
||||
if (this.children === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const reflowed = await Promise.all(this.children.map(c => c.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;
|
||||
}
|
||||
|
||||
reflow() {
|
||||
// Implemented in subclasses
|
||||
}
|
||||
}
|
||||
|
||||
export default Base;
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class Box extends Base {
|
||||
import reflowable from './reflowable';
|
||||
|
||||
@reflowable
|
||||
class Box extends React.PureComponent {
|
||||
static defaultProps = {
|
||||
padding: 5,
|
||||
radius: 3
|
||||
|
||||
@@ -2,12 +2,13 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { List } from 'immutable';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
import reflowable from './reflowable';
|
||||
import Path from './path';
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class HorizontalLayout extends Base {
|
||||
@reflowable
|
||||
class HorizontalLayout extends React.PureComponent {
|
||||
static defaultProps = {
|
||||
withConnectors: false,
|
||||
spacing: 10
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
import reflowable from './reflowable';
|
||||
|
||||
const namespaceProps = {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlns:cc': 'http://creativecommons.org/ns#',
|
||||
@@ -19,8 +20,8 @@ const metadata = `<rdf:rdf>
|
||||
</cc:license>
|
||||
</rdf:rdf>`;
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class Image extends Base {
|
||||
@reflowable
|
||||
class Image extends React.PureComponent {
|
||||
static defaultProps = {
|
||||
padding: 10
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
import reflowable from './reflowable';
|
||||
import Path from './path';
|
||||
|
||||
const skipPath = (box, greedy) => {
|
||||
@@ -54,8 +55,8 @@ const repeatPath = (box, greedy) => {
|
||||
.quadraticCurveTo({ cx: 0, cy: -10, x: -10, y: -10 });
|
||||
};
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class Loop extends Base {
|
||||
@reflowable
|
||||
class Loop extends React.PureComponent {
|
||||
get contentOffset() {
|
||||
const { skip, repeat } = this.props;
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class Pin extends Base {
|
||||
import reflowable from './reflowable';
|
||||
|
||||
@reflowable
|
||||
class Pin extends React.PureComponent {
|
||||
static defaultProps = {
|
||||
radius: 5
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class Text extends Base {
|
||||
import reflowable from './reflowable';
|
||||
|
||||
@reflowable
|
||||
class Text extends React.PureComponent {
|
||||
reflow() {
|
||||
const box = this.text.getBBox();
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { List } from 'immutable';
|
||||
|
||||
import Base from './Base';
|
||||
import style from './style';
|
||||
|
||||
import reflowable from './reflowable';
|
||||
import Path from './path';
|
||||
|
||||
const connectorMargin = 20;
|
||||
|
||||
/** @extends React.PureComponent */
|
||||
class VerticalLayout extends Base {
|
||||
@reflowable
|
||||
class VerticalLayout extends React.PureComponent {
|
||||
static defaultProps = {
|
||||
withConnectors: false,
|
||||
spacing: 10
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
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()
|
||||
};
|
||||
},
|
||||
|
||||
async reflowChildren() {
|
||||
// No child components
|
||||
if (this.children === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const reflowed = await Promise.all(this.children.map(c => c.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;
|
||||
},
|
||||
|
||||
...Component.prototype
|
||||
});
|
||||
|
||||
return Component;
|
||||
};
|
||||
|
||||
export default reflowable;
|
||||
Reference in New Issue
Block a user