UNPKG

react-archer

Version:

Draw arrows between DOM elements in React

84 lines (69 loc) 2.01 kB
// @flow import React from 'react'; import { type ArcherContainerContextType, ArcherContainerContextConsumer, } from './ArcherContainer'; type Props = { id: string, relations: Array<RelationType>, style?: Object, className?: string, children: React$Node, context: ArcherContainerContextType, }; const stringifyRelations = (relations: Array<RelationType>): string => { const relationsWithStringifiedLabels = (relations || []).map(r => { // $FlowFixMe TODO if (r.label && r.label.props) { return JSON.stringify(r.label.props); } return JSON.stringify(r.label); }); return JSON.stringify(relationsWithStringifiedLabels); }; export class ArcherElementNoContext extends React.Component<Props> { componentWillReceiveProps(nextProps: Props) { if ( stringifyRelations(this.props.relations) === stringifyRelations(nextProps.relations) ) { return; } this.registerAllTransitions(nextProps.relations); } componentDidMount() { if (!this.props.relations) { return; } this.registerAllTransitions(this.props.relations); } registerAllTransitions(relations: Array<RelationType>) { relations.forEach(relation => { if (!this.props.context.registerTransition) return; this.props.context.registerTransition(this.props.id, relation); }); } onRefUpdate = (ref: ?HTMLElement) => { if (!ref) return; if (!this.props.context.registerChild) return; this.props.context.registerChild(this.props.id, ref); }; render() { return ( <div style={{ ...this.props.style, position: 'relative' }} className={this.props.className} ref={this.onRefUpdate} > {this.props.children} </div> ); } } const ArcherElementWithContext = (props: Props) => ( <ArcherContainerContextConsumer> {context => <ArcherElementNoContext {...props} context={context} />} </ArcherContainerContextConsumer> ); export default ArcherElementWithContext;