diff --git a/src/components/App/index.js b/src/components/App/index.js index e1d2395..6820117 100644 --- a/src/components/App/index.js +++ b/src/components/App/index.js @@ -114,8 +114,8 @@ class App extends React.PureComponent { expr }, async () => { await this.image.doReflow(); - this.setSvgUrl(this.image.svg); - this.setPngUrl(this.image.svg); + this.setSvgUrl(this.image.svg.current); + this.setPngUrl(this.image.svg.current); }); } diff --git a/src/components/SVG/Box.js b/src/components/SVG/Box.js index 0b17433..fc3b373 100644 --- a/src/components/SVG/Box.js +++ b/src/components/SVG/Box.js @@ -12,10 +12,14 @@ class Box extends React.PureComponent { radius: 3 } + label = React.createRef() + + children = [React.createRef()] + reflow() { const { padding, useAnchors } = this.props; - const box = this.children[0].getBBox(); - const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0}; + const box = this.children[0].current.getBBox(); + const labelBox = this.label.current ? this.label.current.getBBox() : { width: 0, height: 0}; this.setBBox({ width: Math.max(box.width + 2 * padding, labelBox.width), @@ -34,10 +38,6 @@ class Box extends React.PureComponent { }); } - containedRef = contained => this.children = [contained] - - labelRef = label => this.label = label - render() { const { theme, radius, label, children } = this.props; const { width, height, labelTransform, rectTransform, contentTransform } = this.state || {}; @@ -53,7 +53,7 @@ class Box extends React.PureComponent { const textProps = { transform: labelTransform, style: style.infoText, - ref: this.labelRef + ref: this.label }; return @@ -61,7 +61,7 @@ class Box extends React.PureComponent { { label && { label } } { React.cloneElement(React.Children.only(children), { - ref: this.containedRef + ref: this.children[0] }) } ; diff --git a/src/components/SVG/HorizontalLayout.js b/src/components/SVG/HorizontalLayout.js index 5a8fb4a..72ec955 100644 --- a/src/components/SVG/HorizontalLayout.js +++ b/src/components/SVG/HorizontalLayout.js @@ -18,6 +18,8 @@ class HorizontalLayout extends React.PureComponent { childTransforms: List() } + children = [] + updateChildTransforms(childBoxes) { return this.state.childTransforms.withMutations(transforms => ( childBoxes.forEach((box, i) => ( @@ -44,7 +46,7 @@ class HorizontalLayout extends React.PureComponent { reflow() { const { spacing, withConnectors } = this.props; - const childBoxes = this.children.map(child => child.getBBox()); + const childBoxes = this.children.map(child => child.current.getBBox()); const verticalCenter = childBoxes.reduce((center, box) => Math.max(center, box.axisY), 0); const width = childBoxes.reduce((width, box) => width + box.width, 0) + (childBoxes.length - 1) * spacing; const height = childBoxes.reduce((ascHeight, box) => Math.max(ascHeight, box.axisY), 0) + @@ -64,20 +66,18 @@ class HorizontalLayout extends React.PureComponent { }); } - childRef = i => child => this.children[i] = child - render() { const { children } = this.props; const { childTransforms, connectorPaths } = this.state; - this.children = []; + this.makeRefCollection(this.children, React.Children.count(children)); return { React.Children.map(children, (child, i) => ( { React.cloneElement(child, { - ref: this.childRef(i) + ref: this.children[i] }) } ))} diff --git a/src/components/SVG/Image.js b/src/components/SVG/Image.js index 6a55161..c13ee57 100644 --- a/src/components/SVG/Image.js +++ b/src/components/SVG/Image.js @@ -31,9 +31,13 @@ class Image extends React.PureComponent { height: 0 } + svg = React.createRef() + + children = [React.createRef()] + reflow() { const { padding } = this.props; - const box = this.children[0].getBBox(); + const box = this.children[0].current.getBBox(); this.setStateAsync({ width: Math.round(box.width + 2 * padding), @@ -41,10 +45,6 @@ class Image extends React.PureComponent { }); } - containedRef = contained => this.children = [contained] - - svgRef = svg => this.svg = svg - render() { const { width, height } = this.state; const { padding, children } = this.props; @@ -54,7 +54,7 @@ class Image extends React.PureComponent { height, viewBox: [0, 0, width, height].join(' '), style: style.image, - ref: this.svgRef, + ref: this.svg, ...namespaceProps }; @@ -62,7 +62,7 @@ class Image extends React.PureComponent { { React.cloneElement(React.Children.only(children), { - ref: this.containedRef + ref: this.children[0] }) } ; diff --git a/src/components/SVG/Loop.js b/src/components/SVG/Loop.js index bcb2839..a6f6310 100644 --- a/src/components/SVG/Loop.js +++ b/src/components/SVG/Loop.js @@ -57,6 +57,10 @@ const repeatPath = (box, greedy) => { @reflowable class Loop extends React.PureComponent { + label = React.createRef() + + children = [React.createRef()] + get contentOffset() { const { skip, repeat } = this.props; @@ -71,8 +75,8 @@ class Loop extends React.PureComponent { reflow() { const { skip, repeat, greedy } = this.props; - const box = this.children[0].getBBox(); - const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0 }; + const box = this.children[0].current.getBBox(); + const labelBox = this.label.current ? this.label.current.getBBox() : { width: 0, height: 0 }; let height = box.height + labelBox.height; if (skip) { @@ -102,10 +106,6 @@ class Loop extends React.PureComponent { }); } - containedRef = contained => this.children = [contained] - - labelRef = label => this.label = label - render() { const { label, children } = this.props; const { loopPaths, labelTransform } = this.state || {}; @@ -113,7 +113,7 @@ class Loop extends React.PureComponent { const textProps = { transform: labelTransform, style: style.infoText, - ref: this.labelRef + ref: this.label }; return @@ -121,7 +121,7 @@ class Loop extends React.PureComponent { { label && { label } } { React.cloneElement(React.Children.only(children), { - ref: this.containedRef + ref: this.children[0] }) } ; diff --git a/src/components/SVG/Text.js b/src/components/SVG/Text.js index b381e72..5d16427 100644 --- a/src/components/SVG/Text.js +++ b/src/components/SVG/Text.js @@ -7,8 +7,10 @@ import reflowable from './reflowable'; @reflowable class Text extends React.PureComponent { + text = React.createRef() + reflow() { - const box = this.text.getBBox(); + const box = this.text.current.getBBox(); this.setBBox({ width: box.width, @@ -20,8 +22,6 @@ class Text extends React.PureComponent { }); } - textRef = text => this.text = text - renderContent() { const { children, quoted } = this.props; if (!quoted) { @@ -42,7 +42,7 @@ class Text extends React.PureComponent { const textProps = { style: { ...style.text, ...style[theme] }, transform, - ref: this.textRef + ref: this.text }; return diff --git a/src/components/SVG/VerticalLayout.js b/src/components/SVG/VerticalLayout.js index 121b671..714f2f5 100644 --- a/src/components/SVG/VerticalLayout.js +++ b/src/components/SVG/VerticalLayout.js @@ -20,6 +20,8 @@ class VerticalLayout extends React.PureComponent { childTransforms: List() } + children = [] + updateChildTransforms(childBoxes) { return this.state.childTransforms.withMutations(transforms => ( childBoxes.forEach((box, i) => ( @@ -82,7 +84,7 @@ class VerticalLayout extends React.PureComponent { reflow() { const { spacing, withConnectors } = this.props; - const childBoxes = this.children.map(child => child.getBBox()); + const childBoxes = this.children.map(child => child.current.getBBox()); const horizontalCenter = childBoxes.reduce((center, box) => Math.max(center, box.width / 2), 0); const margin = withConnectors ? connectorMargin : 0; const width = childBoxes.reduce((width, box) => Math.max(width, box.width), 0) + 2 * margin; @@ -106,20 +108,18 @@ class VerticalLayout extends React.PureComponent { }); } - childRef = i => child => this.children[i] = child - render() { const { children } = this.props; const { childTransforms, connectorPaths } = this.state; - this.children = []; + this.makeRefCollection(this.children, React.Children.count(children)); return { React.Children.map(children, (child, i) => ( { React.cloneElement(child, { - ref: this.childRef(i) + ref: this.children[i] }) } )) } diff --git a/src/components/SVG/reflowable.js b/src/components/SVG/reflowable.js index 4ca6149..e4a29a8 100644 --- a/src/components/SVG/reflowable.js +++ b/src/components/SVG/reflowable.js @@ -1,3 +1,4 @@ +import React from 'react'; import { Map } from 'immutable'; const reflowable = Component => { @@ -46,13 +47,24 @@ const reflowable = Component => { }; }, + 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.doReflow())); + const reflowed = await Promise.all(this.children.map(c => c.current.doReflow())); return reflowed.reduce((memo, value) => memo || value, false); },