UNPKG

victory-core

Version:
150 lines 6.05 kB
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import React from "react"; import defaults from "lodash/defaults"; import pick from "lodash/pick"; import isEqual from "react-fast-compare"; import { VictoryAnimation } from "../victory-animation/victory-animation"; import * as Collection from "../victory-util/collection"; import * as Helpers from "../victory-util/helpers"; import TimerContext from "../victory-util/timer-context"; import * as Transitions from "../victory-util/transitions"; export class VictoryTransition extends React.Component { static displayName = "VictoryTransition"; static contextType = TimerContext; constructor(props, context) { super(props, context); this.state = { nodesShouldLoad: false, nodesDoneLoad: false }; const child = this.props.children; const polar = child.props.polar; this.continuous = !polar && child.type && child.type.continuous === true; this.timer = this.context.transitionTimer; } componentDidMount() { this.setState({ nodesShouldLoad: true }); } shouldComponentUpdate(nextProps) { if (!isEqual(this.props, nextProps)) { this.timer.bypassAnimation(); this.setState(this.getTransitionState(this.props, nextProps), () => this.timer.resumeAnimation()); } return true; } componentWillUnmount() { this.timer.stop(); } getTransitionState(props, nextProps) { const { animate } = props; if (!animate) { return {}; } else if (animate.parentState) { const state = animate.parentState; const oldProps = state.nodesWillExit ? props : null; return { oldProps, nextProps }; } const oldChildren = React.Children.toArray(props.children); const nextChildren = React.Children.toArray(nextProps.children); const { nodesWillExit, nodesWillEnter, childrenTransitions, nodesShouldEnter } = Transitions.getInitialTransitionState(oldChildren, nextChildren); return { nodesWillExit, nodesWillEnter, childrenTransitions, nodesShouldEnter, oldProps: nodesWillExit ? props : null, nextProps }; } getDomainFromChildren(props, axis) { const getChildDomains = children => { return children.reduce((memo, child) => { if (child.type && Helpers.isFunction(child.type.getDomain)) { const childDomain = child.props && child.type.getDomain(child.props, axis); return childDomain ? memo.concat(childDomain) : memo; } else if (child.props && child.props.children) { return memo.concat(getChildDomains(React.Children.toArray(child.props.children))); } return memo; }, []); }; const child = React.Children.toArray(props.children)[0]; const childProps = child.props || {}; const domain = Array.isArray(childProps.domain) ? childProps.domain : childProps.domain && childProps.domain[axis]; if (!childProps.children && domain) { return domain; } const childDomains = getChildDomains([child]); return childDomains.length === 0 ? [0, 1] : [Collection.getMinValue(childDomains), Collection.getMaxValue(childDomains)]; } pickProps() { if (!this.state) { return this.props; } return this.state.nodesWillExit ? this.state.oldProps || this.props : this.props; } pickDomainProps(props) { const parentState = props.animate?.parentState; if (parentState && parentState.nodesWillExit) { return this.continuous || parentState.continuous ? parentState.nextProps || this.state.nextProps || props : props; } return this.continuous && this.state.nodesWillExit ? this.state.nextProps || props : props; } getClipWidth(props, child) { const getDefaultClipWidth = () => { const range = Helpers.getRange(child.props, "x"); return range ? Math.abs(range[1] - range[0]) : props.width; }; const clipWidth = this.transitionProps ? this.transitionProps.clipWidth : undefined; return clipWidth !== undefined ? clipWidth : getDefaultClipWidth(); } render() { const props = this.pickProps(); const getTransitionProps = this.props.animate?.getTransitions ? this.props.animate.getTransitions : Transitions.getTransitionPropsFactory(props, this.state, newState => this.setState(newState)); const child = React.Children.toArray(props.children)[0]; const transitionProps = getTransitionProps(child); this.transitionProps = transitionProps; const domain = { x: this.getDomainFromChildren(this.pickDomainProps(props), "x"), y: this.getDomainFromChildren(props, "y") }; const clipWidth = this.getClipWidth(props, child); const combinedProps = defaults({ domain, clipWidth }, transitionProps, child.props); const animationWhitelist = props.animationWhitelist || []; const whitelist = animationWhitelist.concat(["clipWidth"]); const propsToAnimate = whitelist.length ? pick(combinedProps, whitelist) : combinedProps; return /*#__PURE__*/React.createElement(VictoryAnimation, _extends({}, combinedProps.animate, { data: propsToAnimate }), newProps => { if (child.props.groupComponent) { const groupComponent = this.continuous ? /*#__PURE__*/React.cloneElement(child.props.groupComponent, { clipWidth: newProps.clipWidth || 0 }) : child.props.groupComponent; return /*#__PURE__*/React.cloneElement(child, defaults({ animate: null, animating: true, groupComponent }, newProps, combinedProps)); } return /*#__PURE__*/React.cloneElement(child, defaults({ animate: null, animating: true }, newProps, combinedProps)); }); } }