import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose"; var _leaveRenders, _enterRenders; import React from 'react'; import PropTypes from 'prop-types'; import { ENTERED, ENTERING, EXITING } from './Transition'; import TransitionGroupContext from './TransitionGroupContext'; function areChildrenDifferent(oldChildren, newChildren) { if (oldChildren === newChildren) return false; if (React.isValidElement(oldChildren) && React.isValidElement(newChildren) && oldChildren.key != null && oldChildren.key === newChildren.key) { return false; } return true; } /** * Enum of modes for SwitchTransition component * @enum { string } */ export var modes = { out: 'out-in', in: 'in-out' }; var callHook = function callHook(element, name, cb) { return function () { var _element$props; element.props[name] && (_element$props = element.props)[name].apply(_element$props, arguments); cb(); }; }; var leaveRenders = (_leaveRenders = {}, _leaveRenders[modes.out] = function (_ref) { var current = _ref.current, changeState = _ref.changeState; return React.cloneElement(current, { in: false, onExited: callHook(current, 'onExited', function () { changeState(ENTERING, null); }) }); }, _leaveRenders[modes.in] = function (_ref2) { var current = _ref2.current, changeState = _ref2.changeState, children = _ref2.children; return [current, React.cloneElement(children, { in: true, onEntered: callHook(children, 'onEntered', function () { changeState(ENTERING); }) })]; }, _leaveRenders); var enterRenders = (_enterRenders = {}, _enterRenders[modes.out] = function (_ref3) { var children = _ref3.children, changeState = _ref3.changeState; return React.cloneElement(children, { in: true, onEntered: callHook(children, 'onEntered', function () { changeState(ENTERED, React.cloneElement(children, { in: true })); }) }); }, _enterRenders[modes.in] = function (_ref4) { var current = _ref4.current, children = _ref4.children, changeState = _ref4.changeState; return [React.cloneElement(current, { in: false, onExited: callHook(current, 'onExited', function () { changeState(ENTERED, React.cloneElement(children, { in: true })); }) }), React.cloneElement(children, { in: true })]; }, _enterRenders); /** * A transition component inspired by the [vue transition modes](https://vuejs.org/v2/guide/transitions.html#Transition-Modes). * You can use it when you want to control the render between state transitions. * Based on the selected mode and the child's key which is the `Transition` or `CSSTransition` component, the `SwitchTransition` makes a consistent transition between them. * * If the `out-in` mode is selected, the `SwitchTransition` waits until the old child leaves and then inserts a new child. * If the `in-out` mode is selected, the `SwitchTransition` inserts a new child first, waits for the new child to enter and then removes the old child. * * **Note**: If you want the animation to happen simultaneously * (that is, to have the old child removed and a new child inserted **at the same time**), * you should use * [`TransitionGroup`](https://reactcommunity.org/react-transition-group/transition-group) * instead. * * ```jsx * function App() { * const [state, setState] = useState(false); * return ( * * node.addEventListener("transitionend", done, false)} * classNames='fade' * > * * * * ); * } * ``` * * ```css * .fade-enter{ * opacity: 0; * } * .fade-exit{ * opacity: 1; * } * .fade-enter-active{ * opacity: 1; * } * .fade-exit-active{ * opacity: 0; * } * .fade-enter-active, * .fade-exit-active{ * transition: opacity 500ms; * } * ``` */ var SwitchTransition = /*#__PURE__*/function (_React$Component) { _inheritsLoose(SwitchTransition, _React$Component); function SwitchTransition() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this; _this.state = { status: ENTERED, current: null }; _this.appeared = false; _this.changeState = function (status, current) { if (current === void 0) { current = _this.state.current; } _this.setState({ status: status, current: current }); }; return _this; } var _proto = SwitchTransition.prototype; _proto.componentDidMount = function componentDidMount() { this.appeared = true; }; SwitchTransition.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) { if (props.children == null) { return { current: null }; } if (state.status === ENTERING && props.mode === modes.in) { return { status: ENTERING }; } if (state.current && areChildrenDifferent(state.current, props.children)) { return { status: EXITING }; } return { current: React.cloneElement(props.children, { in: true }) }; }; _proto.render = function render() { var _this$props = this.props, children = _this$props.children, mode = _this$props.mode, _this$state = this.state, status = _this$state.status, current = _this$state.current; var data = { children: children, current: current, changeState: this.changeState, status: status }; var component; switch (status) { case ENTERING: component = enterRenders[mode](data); break; case EXITING: component = leaveRenders[mode](data); break; case ENTERED: component = current; } return /*#__PURE__*/React.createElement(TransitionGroupContext.Provider, { value: { isMounting: !this.appeared } }, component); }; return SwitchTransition; }(React.Component); SwitchTransition.propTypes = process.env.NODE_ENV !== "production" ? { /** * Transition modes. * `out-in`: Current element transitions out first, then when complete, the new element transitions in. * `in-out`: New element transitions in first, then when complete, the current element transitions out. * * @type {'out-in'|'in-out'} */ mode: PropTypes.oneOf([modes.in, modes.out]), /** * Any `Transition` or `CSSTransition` component. */ children: PropTypes.oneOfType([PropTypes.element.isRequired]) } : {}; SwitchTransition.defaultProps = { mode: modes.out }; export default SwitchTransition;