UNPKG

react-native-reanimated

Version:

More powerful alternative to Animated library for React Native.

97 lines (93 loc) 3.72 kB
'use strict'; import { Children, cloneElement, Component, createContext, Fragment, isValidElement, useEffect, useRef } from 'react'; import { setShouldAnimateExitingForTag } from "../core.js"; import { getViewTagFromInstance } from "../createAnimatedComponent/getViewInfo.js"; import { findNodeHandle } from '../platformFunctions/findNodeHandle'; import { mergeRefs } from "../reactUtils.js"; import { jsx as _jsx } from "react/jsx-runtime"; export const SkipEnteringContext = /*#__PURE__*/createContext(null); // skipEntering - don't animate entering of children on wrapper mount // skipExiting - don't animate exiting of children on wrapper unmount function SkipEntering(props) { const skipValueRef = useRef(props.shouldSkip); useEffect(() => { skipValueRef.current = false; }, [skipValueRef]); return /*#__PURE__*/_jsx(SkipEnteringContext, { value: skipValueRef, children: props.children }); } // skipExiting (unlike skipEntering) cannot be done by conditionally // configuring the animation in `createAnimatedComponent`, since at this stage // we don't know if the wrapper is going to be unmounted or not. // That's why we need to pass the skipExiting flag to the native side // when the wrapper is unmounted to prevent the animation. // Since `ReactNode` can be a list of nodes, we wrap every child with our wrapper // so we are able to access its tag with `findNodeHandle`. /** * A component that lets you skip entering and exiting animations. * * @param skipEntering - A boolean indicating whether children's entering * animations should be skipped when `LayoutAnimationConfig` is mounted. * @param skipExiting - A boolean indicating whether children's exiting * animations should be skipped when LayoutAnimationConfig is unmounted. * @see https://docs.swmansion.com/react-native-reanimated/docs/layout-animations/layout-animation-config/ */ export class LayoutAnimationConfig extends Component { _childInstance = null; _setChildInstance = instance => { this._childInstance = instance; }; _getMergedRef(childRef) { if (!this._mergedRef || this._mergedRefSource !== childRef) { this._mergedRefSource = childRef; this._mergedRef = mergeRefs(childRef, this._setChildInstance); } return this._mergedRef; } getComponentViewTag() { return getViewTagFromInstance(this._childInstance) ?? -1; } getMaybeWrappedChildren() { return Children.count(this.props.children) > 1 && this.props.skipExiting ? Children.map(this.props.children, child => /*#__PURE__*/_jsx(LayoutAnimationConfig, { skipExiting: true, children: child })) : this.getMaybeRefTrackedChild(); } getMaybeRefTrackedChild() { const { children } = this.props; if (this.props.skipExiting === undefined || ! /*#__PURE__*/isValidElement(children) || children.type === Fragment) { return children; } return /*#__PURE__*/cloneElement(children, { ref: this._getMergedRef(children.props.ref) }); } setShouldAnimateExiting() { if (Children.count(this.props.children) === 1) { const tag = getViewTagFromInstance(this._childInstance) ?? findNodeHandle(this); if (tag) { setShouldAnimateExitingForTag(tag, !this.props.skipExiting); } } } componentWillUnmount() { if (this.props.skipExiting !== undefined) { this.setShouldAnimateExiting(); } } render() { const children = this.getMaybeWrappedChildren(); if (this.props.skipEntering === undefined) { return children; } return /*#__PURE__*/_jsx(SkipEntering, { shouldSkip: this.props.skipEntering, children: children }); } } //# sourceMappingURL=LayoutAnimationConfig.js.map