jiuyiUniapp/service/node_modules/react-native/Libraries/Animated/createAnimatedComponent.js

102 lines
3.2 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps';
import composeStyles from '../../src/private/styles/composeStyles';
import View from '../Components/View/View';
import useMergeRefs from '../Utilities/useMergeRefs';
import useAnimatedProps from './useAnimatedProps';
import * as React from 'react';
import {useMemo} from 'react';
export type AnimatedProps<Props: {...}> = {
// eslint-disable-next-line no-unused-vars
+[_K in keyof (Props &
$ReadOnly<{
passthroughAnimatedPropExplicitValues?: React.ElementConfig<
typeof View,
>,
}>)]: any,
};
// We could use a mapped type here to introduce acceptable Animated variants
// of properties, instead of doing so in the core StyleSheetTypes
// Inexact Props are not supported, they'll be made exact here.
export type StrictAnimatedProps<Props: {...}> = $ReadOnly<{
...$Exact<Props>,
passthroughAnimatedPropExplicitValues?: ?Props,
}>;
export type AnimatedComponentType<Props: {...}, +Instance = mixed> = component(
ref: React.RefSetter<Instance>,
...AnimatedProps<Props>
);
export type StrictAnimatedComponentType<
Props: {...},
+Instance = mixed,
> = component(ref: React.RefSetter<Instance>, ...StrictAnimatedProps<Props>);
export default function createAnimatedComponent<TProps: {...}, TInstance>(
Component: component(ref: React.RefSetter<TInstance>, ...TProps),
): AnimatedComponentType<TProps, TInstance> {
return unstable_createAnimatedComponentWithAllowlist(Component, null);
}
export function unstable_createAnimatedComponentWithAllowlist<
TProps: {...},
TInstance,
>(
Component: component(ref: React.RefSetter<TInstance>, ...TProps),
allowlist: ?AnimatedPropsAllowlist,
): StrictAnimatedComponentType<TProps, TInstance> {
const AnimatedComponent = React.forwardRef<
StrictAnimatedProps<TProps>,
TInstance,
>((props, forwardedRef) => {
const [reducedProps, callbackRef] = useAnimatedProps<TProps, TInstance>(
// $FlowFixMe[incompatible-call]
props,
allowlist,
);
const ref = useMergeRefs<TInstance>(callbackRef, forwardedRef);
// Some components require explicit passthrough values for animation
// to work properly. For example, if an animated component is
// transformed and Pressable, onPress will not work after transform
// without these passthrough values.
// $FlowFixMe[prop-missing]
const {passthroughAnimatedPropExplicitValues, style} = reducedProps;
const passthroughStyle = passthroughAnimatedPropExplicitValues?.style;
const mergedStyle = useMemo(
() => composeStyles(style, passthroughStyle),
[passthroughStyle, style],
);
// NOTE: It is important that `passthroughAnimatedPropExplicitValues` is
// spread after `reducedProps` but before `style`.
return (
<Component
{...reducedProps}
{...passthroughAnimatedPropExplicitValues}
style={mergedStyle}
ref={ref}
/>
);
});
AnimatedComponent.displayName = `Animated(${
Component.displayName || 'Anonymous'
})`;
return AnimatedComponent;
}