UNPKG

4.27 kBTypeScriptView Raw
1'use strict';
2
3import { shallowEqual } from '../reanimated2/hook/utils';
4import type { StyleProps } from '../reanimated2/commonTypes';
5import { isSharedValue } from '../reanimated2/isSharedValue';
6import { isChromeDebugger } from '../reanimated2/PlatformChecker';
7import { WorkletEventHandler } from '../reanimated2/WorkletEventHandler';
8import { initialUpdaterRun } from '../reanimated2/animation';
9import { hasInlineStyles, getInlineStyle } from './InlinePropManager';
10import type {
11 AnimatedComponentProps,
12 AnimatedProps,
13 InitialComponentProps,
14 IAnimatedComponentInternal,
15 IPropsFilter,
16} from './commonTypes';
17import { flattenArray, has } from './utils';
18import { StyleSheet } from 'react-native';
19
20function dummyListener() {
21 // empty listener we use to assign to listener properties for which animated
22 // event is used.
23}
24
25export class PropsFilter implements IPropsFilter {
26 private _initialStyle = {};
27 private _previousProps: React.Component['props'] | null = null;
28 private _requiresNewInitials = true;
29
30 public filterNonAnimatedProps(
31 component: React.Component<unknown, unknown> & IAnimatedComponentInternal
32 ): Record<string, unknown> {
33 const inputProps =
34 component.props as AnimatedComponentProps<InitialComponentProps>;
35
36 this._maybePrepareForNewInitials(inputProps);
37
38 const props: Record<string, unknown> = {};
39 for (const key in inputProps) {
40 const value = inputProps[key];
41 if (key === 'style') {
42 const styleProp = inputProps.style;
43 const styles = flattenArray<StyleProps>(styleProp ?? []);
44 if (this._requiresNewInitials) {
45 this._initialStyle = {};
46 }
47 const processedStyle: StyleProps = styles.map((style) => {
48 if (style && style.viewDescriptors) {
49 // this is how we recognize styles returned by useAnimatedStyle
50 // TODO - refactor, since `viewsRef` is only present on Web
51 style.viewsRef?.add(component);
52 if (this._requiresNewInitials) {
53 this._initialStyle = {
54 ...style.initial.value,
55 ...this._initialStyle,
56 ...initialUpdaterRun<StyleProps>(style.initial.updater),
57 };
58 }
59 return this._initialStyle;
60 } else if (hasInlineStyles(style)) {
61 return getInlineStyle(style, this._requiresNewInitials);
62 } else {
63 return style;
64 }
65 });
66 props[key] = StyleSheet.flatten(processedStyle);
67 } else if (key === 'animatedProps') {
68 const animatedProp = inputProps.animatedProps as Partial<
69 AnimatedComponentProps<AnimatedProps>
70 >;
71 if (animatedProp.initial !== undefined) {
72 Object.keys(animatedProp.initial.value).forEach((initialValueKey) => {
73 props[initialValueKey] =
74 animatedProp.initial?.value[initialValueKey];
75 // TODO - refacotr, since `viewsRef` is only present on Web
76 animatedProp.viewsRef?.add(component);
77 });
78 }
79 } else if (
80 has('workletEventHandler', value) &&
81 value.workletEventHandler instanceof WorkletEventHandler
82 ) {
83 if (value.workletEventHandler.eventNames.length > 0) {
84 value.workletEventHandler.eventNames.forEach((eventName) => {
85 props[eventName] = has('listeners', value.workletEventHandler)
86 ? (
87 value.workletEventHandler.listeners as Record<string, unknown>
88 )[eventName]
89 : dummyListener;
90 });
91 } else {
92 props[key] = dummyListener;
93 }
94 } else if (isSharedValue(value)) {
95 if (this._requiresNewInitials) {
96 props[key] = value.value;
97 }
98 } else if (key !== 'onGestureHandlerStateChange' || !isChromeDebugger()) {
99 props[key] = value;
100 }
101 }
102 this._requiresNewInitials = false;
103 return props;
104 }
105
106 private _maybePrepareForNewInitials(
107 inputProps: AnimatedComponentProps<InitialComponentProps>
108 ) {
109 if (this._previousProps && inputProps.style) {
110 this._requiresNewInitials = !shallowEqual(
111 this._previousProps,
112 inputProps
113 );
114 }
115 this._previousProps = inputProps;
116 }
117}