react-native-reanimated 4.3.0-rc.0 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.cpp +8 -5
- package/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.h +3 -5
- package/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.cpp +2 -3
- package/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.cpp +2 -3
- package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +7 -3
- package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +9 -2
- package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +6 -2
- package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +8 -2
- package/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp +2 -2
- package/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h +2 -2
- package/Common/cpp/reanimated/Compat/WorkletsApi.h +13 -0
- package/Common/cpp/reanimated/Events/UIEventHandler.cpp +1 -1
- package/Common/cpp/reanimated/Events/UIEventHandler.h +3 -4
- package/Common/cpp/reanimated/Events/UIEventHandlerRegistry.cpp +3 -2
- package/Common/cpp/reanimated/Events/UIEventHandlerRegistry.h +1 -1
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +2 -8
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +2 -6
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +1 -6
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +1 -8
- package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +12 -7
- package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +6 -3
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +4 -6
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +25 -7
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.h +1 -2
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +1 -1
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +9 -9
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h +2 -3
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +21 -21
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h +3 -3
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +3 -3
- package/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +24 -20
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +35 -53
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +1 -2
- package/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +22 -22
- package/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +10 -10
- package/Common/cpp/reanimated/Tools/ReaJSIUtils.h +5 -5
- package/README.md +1 -1
- package/android/build.gradle +0 -21
- package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +6 -10
- package/android/src/main/cpp/reanimated/android/NativeProxy.h +1 -2
- package/android/src/main/java/com/swmansion/reanimated/CopiedEvent.java +66 -9
- package/android/src/main/java/com/swmansion/reanimated/NodesManager.java +16 -11
- package/android/src/main/java/com/swmansion/reanimated/nativeProxy/EventHandler.java +34 -8
- package/android/src/main/java/com/swmansion/reanimated/nativeProxy/NoopEventHandler.java +27 -6
- package/apple/reanimated/apple/REANodesManager.mm +0 -8
- package/apple/reanimated/apple/ReanimatedModule.mm +6 -12
- package/apple/reanimated/apple/native/NativeProxy.h +1 -2
- package/apple/reanimated/apple/native/NativeProxy.mm +1 -1
- package/compatibility.json +7 -29
- package/lib/module/PropsRegistryGarbageCollector.js +3 -0
- package/lib/module/PropsRegistryGarbageCollector.js.map +1 -1
- package/lib/module/common/style/processors/colors.js +31 -4
- package/lib/module/common/style/processors/colors.js.map +1 -1
- package/lib/module/common/style/processors/filter.js +103 -61
- package/lib/module/common/style/processors/filter.js.map +1 -1
- package/lib/module/common/style/processors/font.js +7 -1
- package/lib/module/common/style/processors/font.js.map +1 -1
- package/lib/module/common/style/processors/insets.js +26 -14
- package/lib/module/common/style/processors/insets.js.map +1 -1
- package/lib/module/common/style/processors/others.js +15 -5
- package/lib/module/common/style/processors/others.js.map +1 -1
- package/lib/module/common/style/processors/shadows.js +14 -3
- package/lib/module/common/style/processors/shadows.js.map +1 -1
- package/lib/module/common/style/processors/transform.js +30 -1
- package/lib/module/common/style/processors/transform.js.map +1 -1
- package/lib/module/common/style/processors/transformOrigin.js +20 -3
- package/lib/module/common/style/processors/transformOrigin.js.map +1 -1
- package/lib/module/common/utils/guards.js +27 -7
- package/lib/module/common/utils/guards.js.map +1 -1
- package/lib/module/common/utils/parsers.js +2 -1
- package/lib/module/common/utils/parsers.js.map +1 -1
- package/lib/module/createAnimatedComponent/AnimatedComponent.js +1 -7
- package/lib/module/createAnimatedComponent/AnimatedComponent.js.map +1 -1
- package/lib/module/css/native/managers/CSSManager.js +16 -15
- package/lib/module/css/native/managers/CSSManager.js.map +1 -1
- package/lib/module/css/native/managers/CSSTransitionsManager.js +47 -44
- package/lib/module/css/native/managers/CSSTransitionsManager.js.map +1 -1
- package/lib/module/css/native/normalization/transition/config.js +35 -17
- package/lib/module/css/native/normalization/transition/config.js.map +1 -1
- package/lib/module/css/utils/props.js +6 -0
- package/lib/module/css/utils/props.js.map +1 -1
- package/lib/module/featureFlags/index.js +1 -1
- package/lib/module/featureFlags/staticFlags.json +1 -1
- package/lib/module/hook/useAnimatedRef.js +2 -2
- package/lib/module/hook/useAnimatedRef.js.map +1 -1
- package/lib/module/hook/useAnimatedStyle.js +7 -1
- package/lib/module/hook/useAnimatedStyle.js.map +1 -1
- package/lib/module/hook/useHandler.js +82 -28
- package/lib/module/hook/useHandler.js.map +1 -1
- package/lib/module/hook/utils.js +1 -74
- package/lib/module/hook/utils.js.map +1 -1
- package/lib/module/initializers.js +2 -0
- package/lib/module/initializers.js.map +1 -1
- package/lib/module/jestUtils/common.js +10 -0
- package/lib/module/jestUtils/common.js.map +1 -1
- package/lib/module/jestUtils/index.js +2 -5
- package/lib/module/jestUtils/index.js.map +1 -1
- package/lib/module/jestUtils/index.web.js +1 -1
- package/lib/module/jestUtils/index.web.js.map +1 -1
- package/lib/module/mutables.js +5 -1
- package/lib/module/mutables.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/module/platform-specific/jsVersion.js.map +1 -1
- package/lib/typescript/PropsRegistryGarbageCollector.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/colors.d.ts +3 -3
- package/lib/typescript/common/style/processors/colors.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/filter.d.ts +0 -4
- package/lib/typescript/common/style/processors/filter.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/font.d.ts +1 -1
- package/lib/typescript/common/style/processors/font.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/insets.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/others.d.ts +1 -1
- package/lib/typescript/common/style/processors/others.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/shadows.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/transform.d.ts.map +1 -1
- package/lib/typescript/common/style/processors/transformOrigin.d.ts +2 -2
- package/lib/typescript/common/style/processors/transformOrigin.d.ts.map +1 -1
- package/lib/typescript/common/utils/guards.d.ts +0 -1
- package/lib/typescript/common/utils/guards.d.ts.map +1 -1
- package/lib/typescript/common/utils/parsers.d.ts.map +1 -1
- package/lib/typescript/commonTypes.d.ts +1 -1
- package/lib/typescript/commonTypes.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/AnimatedComponent.d.ts.map +1 -1
- package/lib/typescript/css/native/managers/CSSManager.d.ts +7 -1
- package/lib/typescript/css/native/managers/CSSManager.d.ts.map +1 -1
- package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts +5 -4
- package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts.map +1 -1
- package/lib/typescript/css/native/normalization/transition/config.d.ts.map +1 -1
- package/lib/typescript/css/native/types/transition.d.ts +15 -1
- package/lib/typescript/css/native/types/transition.d.ts.map +1 -1
- package/lib/typescript/css/utils/props.d.ts.map +1 -1
- package/lib/typescript/featureFlags/index.d.ts +1 -1
- package/lib/typescript/hook/useAnimatedStyle.d.ts.map +1 -1
- package/lib/typescript/hook/useHandler.d.ts +8 -9
- package/lib/typescript/hook/useHandler.d.ts.map +1 -1
- package/lib/typescript/hook/utils.d.ts +0 -5
- package/lib/typescript/hook/utils.d.ts.map +1 -1
- package/lib/typescript/jestUtils/common.d.ts +2 -0
- package/lib/typescript/jestUtils/common.d.ts.map +1 -1
- package/lib/typescript/jestUtils/index.d.ts +4 -3
- package/lib/typescript/jestUtils/index.d.ts.map +1 -1
- package/lib/typescript/mutables.d.ts.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts.map +1 -1
- package/package.json +13 -10
- package/src/PropsRegistryGarbageCollector.ts +3 -0
- package/src/common/style/processors/colors.ts +20 -7
- package/src/common/style/processors/filter.ts +95 -70
- package/src/common/style/processors/font.ts +5 -2
- package/src/common/style/processors/insets.ts +23 -14
- package/src/common/style/processors/others.ts +12 -6
- package/src/common/style/processors/shadows.ts +10 -6
- package/src/common/style/processors/transform.ts +15 -1
- package/src/common/style/processors/transformOrigin.ts +40 -11
- package/src/common/utils/guards.ts +21 -16
- package/src/common/utils/parsers.ts +1 -1
- package/src/commonTypes.ts +1 -1
- package/src/createAnimatedComponent/AnimatedComponent.tsx +1 -7
- package/src/css/native/managers/CSSManager.ts +29 -14
- package/src/css/native/managers/CSSTransitionsManager.ts +52 -54
- package/src/css/native/normalization/transition/config.ts +35 -27
- package/src/css/native/types/transition.ts +15 -1
- package/src/css/utils/props.ts +7 -0
- package/src/featureFlags/index.ts +1 -1
- package/src/featureFlags/staticFlags.json +1 -1
- package/src/hook/useAnimatedRef.ts +2 -2
- package/src/hook/useAnimatedStyle.ts +15 -6
- package/src/hook/useHandler.ts +150 -64
- package/src/hook/utils.ts +1 -127
- package/src/initializers.ts +1 -0
- package/src/jestUtils/common.ts +10 -0
- package/src/jestUtils/index.ts +5 -8
- package/src/jestUtils/index.web.ts +1 -1
- package/src/mutables.ts +5 -1
- package/src/platform-specific/jsVersion.ts +1 -1
- package/src/privateGlobals.d.ts +4 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
'worklet';
|
|
3
2
|
import { ReanimatedError } from '../../errors';
|
|
4
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
NormalizedTransformOrigin,
|
|
5
|
+
TransformOrigin,
|
|
6
|
+
ValueProcessor,
|
|
7
|
+
} from '../../types';
|
|
5
8
|
|
|
6
9
|
type Axis = 'x' | 'y' | 'z';
|
|
7
10
|
type ConvertedValue = `${number}%` | number;
|
|
@@ -21,6 +24,7 @@ const VERTICAL_CONVERSIONS = {
|
|
|
21
24
|
} satisfies KeywordConversions;
|
|
22
25
|
|
|
23
26
|
function getAllowedValues(axis: Axis, isArray: boolean): string {
|
|
27
|
+
'worklet';
|
|
24
28
|
const allowed: string[] = [];
|
|
25
29
|
|
|
26
30
|
if (isArray) {
|
|
@@ -51,20 +55,25 @@ function getAllowedValues(axis: Axis, isArray: boolean): string {
|
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
export const ERROR_MESSAGES = {
|
|
54
|
-
invalidTransformOrigin: (value: Readonly<TransformOrigin>) =>
|
|
55
|
-
|
|
58
|
+
invalidTransformOrigin: (value: Readonly<TransformOrigin>) => {
|
|
59
|
+
'worklet';
|
|
60
|
+
return `Invalid transformOrigin: ${JSON.stringify(value)}. Expected 1-3 values.`;
|
|
61
|
+
},
|
|
56
62
|
invalidValue: (
|
|
57
63
|
value: string | number,
|
|
58
64
|
axis: Axis,
|
|
59
65
|
origin: Readonly<TransformOrigin>,
|
|
60
66
|
isArray: boolean
|
|
61
|
-
) =>
|
|
62
|
-
|
|
67
|
+
) => {
|
|
68
|
+
'worklet';
|
|
69
|
+
return `Invalid value "${value}" for the ${axis}-axis in transformOrigin ${JSON.stringify(
|
|
63
70
|
origin
|
|
64
|
-
)}. Allowed values: ${getAllowedValues(axis, isArray)}
|
|
71
|
+
)}. Allowed values: ${getAllowedValues(axis, isArray)}.`;
|
|
72
|
+
},
|
|
65
73
|
};
|
|
66
74
|
|
|
67
75
|
function maybeSwapComponents(components: ReadonlyArray<string | number>) {
|
|
76
|
+
'worklet';
|
|
68
77
|
if (
|
|
69
78
|
components[0] in VERTICAL_CONVERSIONS &&
|
|
70
79
|
(components[1] === undefined || components[1] in HORIZONTAL_CONVERSIONS)
|
|
@@ -77,13 +86,30 @@ function maybeSwapComponents(components: ReadonlyArray<string | number>) {
|
|
|
77
86
|
return components;
|
|
78
87
|
}
|
|
79
88
|
|
|
89
|
+
function parseValue(
|
|
90
|
+
value: string | number,
|
|
91
|
+
allowPercentages: true,
|
|
92
|
+
customParse: CustomParse,
|
|
93
|
+
getError: () => string,
|
|
94
|
+
keywordConversions?: KeywordConversions
|
|
95
|
+
): `${number}%` | number;
|
|
96
|
+
|
|
97
|
+
function parseValue(
|
|
98
|
+
value: string | number,
|
|
99
|
+
allowPercentages: false,
|
|
100
|
+
customParse: CustomParse,
|
|
101
|
+
getError: () => string,
|
|
102
|
+
keywordConversions?: KeywordConversions
|
|
103
|
+
): number;
|
|
104
|
+
|
|
80
105
|
function parseValue(
|
|
81
106
|
value: string | number,
|
|
82
107
|
allowPercentages: boolean,
|
|
83
108
|
customParse: CustomParse,
|
|
84
109
|
getError: () => string,
|
|
85
110
|
keywordConversions?: KeywordConversions
|
|
86
|
-
) {
|
|
111
|
+
): `${number}%` | number {
|
|
112
|
+
'worklet';
|
|
87
113
|
if (typeof value === 'number') {
|
|
88
114
|
return value;
|
|
89
115
|
}
|
|
@@ -109,6 +135,7 @@ function parseValue(
|
|
|
109
135
|
}
|
|
110
136
|
|
|
111
137
|
function parsePx(component: string) {
|
|
138
|
+
'worklet';
|
|
112
139
|
if (component.endsWith('px') || component === '0') {
|
|
113
140
|
const num = parseFloat(component);
|
|
114
141
|
if (!isNaN(num)) {
|
|
@@ -118,9 +145,11 @@ function parsePx(component: string) {
|
|
|
118
145
|
return null;
|
|
119
146
|
}
|
|
120
147
|
|
|
121
|
-
export const processTransformOrigin: ValueProcessor<
|
|
122
|
-
|
|
123
|
-
|
|
148
|
+
export const processTransformOrigin: ValueProcessor<
|
|
149
|
+
TransformOrigin,
|
|
150
|
+
NormalizedTransformOrigin
|
|
151
|
+
> = (value) => {
|
|
152
|
+
'worklet';
|
|
124
153
|
const isArray = Array.isArray(value);
|
|
125
154
|
let components = typeof value === 'string' ? value.split(/\s+/) : value;
|
|
126
155
|
const customParse = isArray ? () => null : parsePx;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
'worklet';
|
|
3
2
|
import type { AnyRecord, ConfigPropertyAlias, UnknownRecord } from '../types';
|
|
4
3
|
|
|
5
4
|
export const isDefined = <T>(value: T): value is NonNullable<T> =>
|
|
@@ -7,31 +6,37 @@ export const isDefined = <T>(value: T): value is NonNullable<T> =>
|
|
|
7
6
|
|
|
8
7
|
export const isAngle = (
|
|
9
8
|
value: string | number
|
|
10
|
-
): value is `${number}deg` | `${number}rad` =>
|
|
11
|
-
|
|
9
|
+
): value is `${number}deg` | `${number}rad` => {
|
|
10
|
+
'worklet';
|
|
11
|
+
return typeof value === 'string' && /^-?\d+(\.\d+)?(deg|rad)$/.test(value);
|
|
12
|
+
};
|
|
12
13
|
|
|
13
|
-
export const isNumber = (value: unknown): value is number =>
|
|
14
|
-
|
|
14
|
+
export const isNumber = (value: unknown): value is number => {
|
|
15
|
+
'worklet';
|
|
16
|
+
return typeof value === 'number' && !isNaN(value);
|
|
17
|
+
};
|
|
15
18
|
|
|
16
|
-
export const isNumberArray = (value: unknown): value is number[] =>
|
|
17
|
-
|
|
19
|
+
export const isNumberArray = (value: unknown): value is number[] => {
|
|
20
|
+
'worklet';
|
|
21
|
+
return Array.isArray(value) && value.every(isNumber);
|
|
22
|
+
};
|
|
18
23
|
|
|
19
24
|
export const isLength = (value: string) => {
|
|
25
|
+
'worklet';
|
|
20
26
|
return value.endsWith('px') || !isNaN(Number(value));
|
|
21
27
|
};
|
|
22
28
|
|
|
23
|
-
export const isPercentage = (value: unknown): value is `${number}%` =>
|
|
24
|
-
|
|
29
|
+
export const isPercentage = (value: unknown): value is `${number}%` => {
|
|
30
|
+
'worklet';
|
|
31
|
+
return typeof value === 'string' && /^-?\d+(\.\d+)?%$/.test(value);
|
|
32
|
+
};
|
|
25
33
|
|
|
26
34
|
export const isRecord = <T extends UnknownRecord = UnknownRecord>(
|
|
27
35
|
value: unknown
|
|
28
|
-
): value is T =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
obj: P,
|
|
33
|
-
key: K
|
|
34
|
-
): obj is P & Record<K, string> => key in obj;
|
|
36
|
+
): value is T => {
|
|
37
|
+
'worklet';
|
|
38
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
39
|
+
};
|
|
35
40
|
|
|
36
41
|
export const isConfigPropertyAlias = <P extends AnyRecord>(
|
|
37
42
|
value: unknown
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
'worklet';
|
|
3
2
|
import type { BoxShadowValue } from 'react-native';
|
|
4
3
|
|
|
5
4
|
import { isLength } from '../utils/guards';
|
|
@@ -15,6 +14,7 @@ const SHADOW_PARTS_REGEX = /(?:[^\s()]+|\([^()]*\))+/g;
|
|
|
15
14
|
const SHADOW_SPLIT_REGEX = /(?:[^,()]+|\([^)]*\))+(?=\s*,|$)/g;
|
|
16
15
|
|
|
17
16
|
export function parseBoxShadowString(value: string) {
|
|
17
|
+
'worklet';
|
|
18
18
|
if (value === 'none') {
|
|
19
19
|
return [];
|
|
20
20
|
}
|
package/src/commonTypes.ts
CHANGED
|
@@ -3,7 +3,6 @@ import '../layoutReanimation/animationsManager';
|
|
|
3
3
|
|
|
4
4
|
import type React from 'react';
|
|
5
5
|
import { Fragment } from 'react';
|
|
6
|
-
import { StyleSheet } from 'react-native';
|
|
7
6
|
|
|
8
7
|
import { checkStyleOverwriting, maybeBuild } from '../animationBuilder';
|
|
9
8
|
import { IS_JEST, IS_WEB, logger } from '../common';
|
|
@@ -536,16 +535,11 @@ export default class AnimatedComponent
|
|
|
536
535
|
}
|
|
537
536
|
|
|
538
537
|
if (FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS) {
|
|
539
|
-
const flatStyles = StyleSheet.flatten(filteredProps.style as object);
|
|
540
|
-
const mergedStyles = {
|
|
541
|
-
...flatStyles,
|
|
542
|
-
...this.state.settledProps,
|
|
543
|
-
};
|
|
544
538
|
return super.render({
|
|
545
539
|
nativeID,
|
|
546
540
|
...filteredProps,
|
|
547
541
|
...this.state.settledProps,
|
|
548
|
-
style:
|
|
542
|
+
style: [...flattenArray(filteredProps.style), this.state.settledProps],
|
|
549
543
|
...jestProps,
|
|
550
544
|
});
|
|
551
545
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getCompoundComponentName,
|
|
4
|
+
getPropsBuilder,
|
|
5
|
+
IS_ANDROID,
|
|
6
|
+
} from '../../../common';
|
|
3
7
|
import type { ShadowNodeWrapper } from '../../../commonTypes';
|
|
4
8
|
import type { ViewInfo } from '../../../createAnimatedComponent/commonTypes';
|
|
5
9
|
import type { CSSStyle } from '../../types';
|
|
@@ -14,7 +18,13 @@ export default class CSSManager implements ICSSManager {
|
|
|
14
18
|
private readonly cssTransitionsManager: CSSTransitionsManager;
|
|
15
19
|
private readonly viewTag: number;
|
|
16
20
|
private readonly propsBuilder: ReturnType<typeof getPropsBuilder>;
|
|
17
|
-
|
|
21
|
+
/**
|
|
22
|
+
* True if the previous update had CSS transition props attached. On the next
|
|
23
|
+
* update we still need to build `normalizedStyle` only on Android to revert
|
|
24
|
+
* props applied during the transition to correct current values. (fixes
|
|
25
|
+
* https://github.com/software-mansion/react-native-reanimated/issues/9218).
|
|
26
|
+
*/
|
|
27
|
+
private hadTransitionLastUpdate = false;
|
|
18
28
|
|
|
19
29
|
constructor(
|
|
20
30
|
{ shadowNodeWrapper, viewTag, reactViewName = 'RCTView' }: ViewInfo,
|
|
@@ -41,11 +51,23 @@ export default class CSSManager implements ICSSManager {
|
|
|
41
51
|
const [animationProperties, transitionProperties, filteredStyle] =
|
|
42
52
|
filterCSSAndStyleProperties(style);
|
|
43
53
|
|
|
44
|
-
const
|
|
54
|
+
const hasAnimation = animationProperties !== null;
|
|
55
|
+
const hasTransition = transitionProperties !== null;
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
const normalizedStyle =
|
|
58
|
+
hasAnimation ||
|
|
59
|
+
hasTransition ||
|
|
60
|
+
(IS_ANDROID && this.hadTransitionLastUpdate)
|
|
61
|
+
? this.propsBuilder.build(filteredStyle)
|
|
62
|
+
: undefined;
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
normalizedStyle &&
|
|
66
|
+
(hasAnimation ||
|
|
67
|
+
// We also need to update the current style on Android when the
|
|
68
|
+
// transition is detached.
|
|
69
|
+
(IS_ANDROID && !hasTransition && this.hadTransitionLastUpdate))
|
|
70
|
+
) {
|
|
49
71
|
setViewStyle(this.viewTag, normalizedStyle);
|
|
50
72
|
}
|
|
51
73
|
|
|
@@ -55,14 +77,7 @@ export default class CSSManager implements ICSSManager {
|
|
|
55
77
|
);
|
|
56
78
|
this.cssAnimationsManager.update(animationProperties);
|
|
57
79
|
|
|
58
|
-
|
|
59
|
-
// animations and transitions first and update the style then to make
|
|
60
|
-
// sure that the new transition is fired with new settings (like duration)
|
|
61
|
-
if (!this.isFirstUpdate && normalizedStyle) {
|
|
62
|
-
setViewStyle(this.viewTag, normalizedStyle);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this.isFirstUpdate = false;
|
|
80
|
+
this.hadTransitionLastUpdate = hasTransition;
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
unmountCleanup(): void {
|
|
@@ -17,7 +17,13 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
|
|
|
17
17
|
private readonly viewTag: number;
|
|
18
18
|
private readonly shadowNodeWrapper: ShadowNodeWrapper;
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// All props from the previous update
|
|
21
|
+
private prevProps: UnknownRecord | null = null;
|
|
22
|
+
// Stores all properties for which transition was triggered before
|
|
23
|
+
// and which haven't been cleaned up yet (null if no transition was attached before)
|
|
24
|
+
private propsWithTransitions = new Set<string>();
|
|
25
|
+
// Indicates whether a CSS transition is currently attached to the view
|
|
26
|
+
private hasTransition = false;
|
|
21
27
|
|
|
22
28
|
constructor(shadowNodeWrapper: ShadowNodeWrapper, viewTag: number) {
|
|
23
29
|
this.viewTag = viewTag;
|
|
@@ -26,38 +32,27 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
|
|
|
26
32
|
|
|
27
33
|
update(
|
|
28
34
|
transitionProperties: CSSTransitionProperties | null,
|
|
29
|
-
|
|
35
|
+
nextProps: UnknownRecord = {}
|
|
30
36
|
): void {
|
|
31
37
|
const transitionConfig =
|
|
32
38
|
transitionProperties &&
|
|
33
39
|
normalizeCSSTransitionProperties(transitionProperties);
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
41
|
+
const prevProps = this.prevProps;
|
|
42
|
+
this.prevProps = nextProps;
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} else {
|
|
47
|
-
for (const property of transitionConfig.properties) {
|
|
48
|
-
if (property in props) {
|
|
49
|
-
nextProps[property] = props[property];
|
|
50
|
-
}
|
|
44
|
+
// If there were no previous props, the view is just mounted so we
|
|
45
|
+
// don't trigger any transitions yet. Also, when there is no transition
|
|
46
|
+
// config, we don't trigger any transitions.
|
|
47
|
+
if (!prevProps || !transitionConfig) {
|
|
48
|
+
if (this.hasTransition) {
|
|
49
|
+
this.detach();
|
|
51
50
|
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
this.lastAppliedProps = nextProps;
|
|
55
|
-
|
|
56
|
-
if (!prevProps) {
|
|
57
51
|
return;
|
|
58
52
|
}
|
|
59
53
|
|
|
60
|
-
|
|
54
|
+
// Trigger transition for changed properties only
|
|
55
|
+
const config = this.processTransitionConfig(
|
|
61
56
|
prevProps,
|
|
62
57
|
nextProps,
|
|
63
58
|
transitionConfig
|
|
@@ -65,6 +60,7 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
|
|
|
65
60
|
|
|
66
61
|
if (Object.keys(config).length) {
|
|
67
62
|
runCSSTransition(this.shadowNodeWrapper, config);
|
|
63
|
+
this.hasTransition = true;
|
|
68
64
|
}
|
|
69
65
|
}
|
|
70
66
|
|
|
@@ -73,57 +69,59 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
|
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
private detach() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
72
|
+
unregisterCSSTransition(this.viewTag);
|
|
73
|
+
this.propsWithTransitions.clear();
|
|
74
|
+
this.hasTransition = false;
|
|
80
75
|
}
|
|
81
76
|
|
|
82
|
-
private
|
|
77
|
+
private processTransitionConfig(
|
|
83
78
|
oldProps: UnknownRecord,
|
|
84
79
|
newProps: UnknownRecord,
|
|
85
80
|
newTransitionConfig: NormalizedCSSTransitionConfig
|
|
86
81
|
): CSSTransitionConfig {
|
|
87
82
|
const result: CSSTransitionConfig = {};
|
|
88
83
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
const specificProperties = newTransitionConfig.specificProperties;
|
|
85
|
+
|
|
86
|
+
const isAllowedProperty = (property: string) =>
|
|
87
|
+
!specificProperties || specificProperties.has(property);
|
|
88
|
+
|
|
89
|
+
const getPropertySettings = (property: string) =>
|
|
90
|
+
newTransitionConfig.settings[property] ??
|
|
91
|
+
newTransitionConfig.settings.all;
|
|
92
|
+
|
|
93
|
+
const triggerTransition = (property: string) => {
|
|
94
|
+
result[property] = {
|
|
95
|
+
...getPropertySettings(property),
|
|
96
|
+
value: [oldProps[property], newProps[property]],
|
|
97
|
+
};
|
|
98
|
+
this.propsWithTransitions.add(property);
|
|
99
|
+
};
|
|
93
100
|
|
|
94
101
|
// Get property changes which we want to trigger transitions for
|
|
95
102
|
for (const key in newProps) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!deepEqual(oldValue, newValue)) {
|
|
100
|
-
result[key] = {
|
|
101
|
-
...this.getPropertySettings(key, newTransitionConfig),
|
|
102
|
-
value: [oldValue, newValue],
|
|
103
|
-
};
|
|
103
|
+
if (isAllowedProperty(key) && !deepEqual(newProps[key], oldProps[key])) {
|
|
104
|
+
triggerTransition(key);
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
//
|
|
108
|
+
// Handle old props; for no longer allowed ones, cancel the transition
|
|
109
|
+
// immediately; for ones that are allowed but were removed, trigger a transition
|
|
110
|
+
// to undefined (to the default value for the property).
|
|
108
111
|
for (const key in oldProps) {
|
|
109
|
-
if (
|
|
110
|
-
|
|
112
|
+
if (!isAllowedProperty(key)) {
|
|
113
|
+
if (this.propsWithTransitions.has(key)) {
|
|
114
|
+
// If a property was transitioned before but is no longer allowed,
|
|
115
|
+
// we need to clear it up immediately
|
|
116
|
+
result[key] = null;
|
|
117
|
+
this.propsWithTransitions.delete(key);
|
|
118
|
+
}
|
|
111
119
|
} else if (!(key in newProps)) {
|
|
112
120
|
// Property was removed from props but is still allowed
|
|
113
|
-
|
|
114
|
-
...this.getPropertySettings(key, newTransitionConfig),
|
|
115
|
-
value: [oldProps[key], undefined],
|
|
116
|
-
};
|
|
121
|
+
triggerTransition(key);
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
return result;
|
|
121
126
|
}
|
|
122
|
-
|
|
123
|
-
private getPropertySettings(
|
|
124
|
-
property: string,
|
|
125
|
-
config: NormalizedCSSTransitionConfig
|
|
126
|
-
) {
|
|
127
|
-
return config.settings[property] ?? config.settings.all;
|
|
128
|
-
}
|
|
129
127
|
}
|
|
@@ -79,9 +79,10 @@ export function normalizeCSSTransitionProperties(
|
|
|
79
79
|
transitionDelay,
|
|
80
80
|
transitionBehavior,
|
|
81
81
|
} = expandedProperties;
|
|
82
|
-
const specificProperties: string[] = [];
|
|
83
82
|
let allPropertiesTransition = false;
|
|
84
83
|
const settings: Record<string, NormalizedSingleCSSTransitionSettings> = {};
|
|
84
|
+
const specificProperties = new Set<string>();
|
|
85
|
+
const processedProperties = new Set<string>();
|
|
85
86
|
|
|
86
87
|
if (!transitionProperty.length) {
|
|
87
88
|
// For cases when transition property hasn't been explicitly specified
|
|
@@ -95,42 +96,49 @@ export function normalizeCSSTransitionProperties(
|
|
|
95
96
|
// occurrence and ignore remaining ones)
|
|
96
97
|
for (let i = transitionProperty.length - 1; i >= 0; i--) {
|
|
97
98
|
const property = transitionProperty[i];
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
if (
|
|
99
|
+
// We always respect the last occurrence of a property, even if it gets
|
|
100
|
+
// pruned as inactive. That means earlier occurrences must be ignored.
|
|
101
|
+
if (processedProperties.has(property)) {
|
|
101
102
|
continue;
|
|
102
103
|
}
|
|
104
|
+
processedProperties.add(property);
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
const duration = normalizeDuration(
|
|
107
|
+
transitionDuration[i % transitionDuration.length]
|
|
108
|
+
);
|
|
109
|
+
const delay = normalizeDelay(transitionDelay[i % transitionDelay.length]);
|
|
110
|
+
|
|
111
|
+
// Skip if effective duration is 0 (the transition would be immediate so there is no need
|
|
112
|
+
// to apply it and we can just treat it as a plain render without a transition)
|
|
113
|
+
if (duration + delay <= 0) {
|
|
114
|
+
continue;
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
allowDiscrete: normalizeTransitionBehavior(
|
|
119
|
-
transitionBehavior[i % transitionBehavior.length]
|
|
120
|
-
),
|
|
121
|
-
};
|
|
117
|
+
const timingFunction = normalizeTimingFunction(
|
|
118
|
+
transitionTimingFunction[i % transitionTimingFunction.length]
|
|
119
|
+
);
|
|
120
|
+
const allowDiscrete = normalizeTransitionBehavior(
|
|
121
|
+
transitionBehavior[i % transitionBehavior.length]
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
settings[property] = { duration, timingFunction, delay, allowDiscrete };
|
|
122
125
|
|
|
123
126
|
// 'all' transition property overrides all properties before it,
|
|
124
127
|
// so we don't need to process them
|
|
125
|
-
if (
|
|
128
|
+
if (property === 'all') {
|
|
129
|
+
allPropertiesTransition = true;
|
|
126
130
|
break;
|
|
127
131
|
}
|
|
132
|
+
|
|
133
|
+
specificProperties.add(property);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (allPropertiesTransition) {
|
|
137
|
+
return { specificProperties: undefined, settings };
|
|
138
|
+
}
|
|
139
|
+
if (specificProperties.size) {
|
|
140
|
+
return { specificProperties, settings };
|
|
128
141
|
}
|
|
129
142
|
|
|
130
|
-
return
|
|
131
|
-
properties: allPropertiesTransition
|
|
132
|
-
? undefined
|
|
133
|
-
: specificProperties.reverse(),
|
|
134
|
-
settings,
|
|
135
|
-
};
|
|
143
|
+
return null;
|
|
136
144
|
}
|
|
@@ -13,7 +13,21 @@ export type CSSTransitionConfig = Record<
|
|
|
13
13
|
(NormalizedSingleCSSTransitionSettings & { value: [unknown, unknown] }) | null
|
|
14
14
|
>;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* `specificProperties`
|
|
18
|
+
*
|
|
19
|
+
* - `undefined`: accept all props (equivalent to `transition-property: all`)
|
|
20
|
+
* - `Set<string>`: accept only props present in the set
|
|
21
|
+
*
|
|
22
|
+
* `settings`
|
|
23
|
+
*
|
|
24
|
+
* - Keys are prop names, plus an optional `all` fallback key
|
|
25
|
+
* - How to read it for a prop `propName`:
|
|
26
|
+
*
|
|
27
|
+
* - Primary: `settings[propName]` (if present)
|
|
28
|
+
* - Fallback: `settings.all` (otherwise)
|
|
29
|
+
*/
|
|
16
30
|
export type NormalizedCSSTransitionConfig = {
|
|
17
|
-
|
|
31
|
+
specificProperties: Set<string> | undefined;
|
|
18
32
|
settings: Record<string, NormalizedSingleCSSTransitionSettings>;
|
|
19
33
|
};
|
package/src/css/utils/props.ts
CHANGED
|
@@ -27,6 +27,13 @@ export function filterCSSAndStyleProperties<S extends AnyRecord>(
|
|
|
27
27
|
const filteredStyle: AnyRecord = {};
|
|
28
28
|
|
|
29
29
|
for (const [prop, value] of Object.entries(style)) {
|
|
30
|
+
if (value === undefined) {
|
|
31
|
+
// If the user explicitly sets a property to undefined (e.g. when they want
|
|
32
|
+
// to remove CSS transition or animation), we treat the property as if it was not
|
|
33
|
+
// present in the style object.
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
30
37
|
if (isAnimationProp(prop)) {
|
|
31
38
|
// TODO - add support for animation shorthand
|
|
32
39
|
animationProperties[prop] = value;
|
|
@@ -80,7 +80,7 @@ const DefaultStaticFeatureFlags = {
|
|
|
80
80
|
USE_SYNCHRONIZABLE_FOR_MUTABLES: true,
|
|
81
81
|
USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS: true,
|
|
82
82
|
ENABLE_SHARED_ELEMENT_TRANSITIONS: false,
|
|
83
|
-
FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS:
|
|
83
|
+
FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS: true,
|
|
84
84
|
} as const satisfies typeof StaticFeatureFlagsJSON;
|
|
85
85
|
|
|
86
86
|
type StaticFeatureFlagsSchema = {
|
|
@@ -37,8 +37,8 @@ function useAnimatedRefBase<TRef extends InstanceOrElement>(
|
|
|
37
37
|
wrapperRef.current = getWrapper(ref);
|
|
38
38
|
|
|
39
39
|
// We have to unwrap the tag from the shadow node wrapper.
|
|
40
|
-
//
|
|
41
|
-
fun.getTag = () => findNodeHandle(ref
|
|
40
|
+
// @ts-expect-error this can't be typed well.
|
|
41
|
+
fun.getTag = () => ref.getScrollableNode?.() || findNodeHandle(ref);
|
|
42
42
|
fun.current = ref;
|
|
43
43
|
|
|
44
44
|
if (observers.size) {
|
|
@@ -30,12 +30,7 @@ import type {
|
|
|
30
30
|
JestAnimatedStyleHandle,
|
|
31
31
|
} from './commonTypes';
|
|
32
32
|
import { useSharedValue } from './useSharedValue';
|
|
33
|
-
import {
|
|
34
|
-
buildWorkletsHash,
|
|
35
|
-
isAnimated,
|
|
36
|
-
shallowEqual,
|
|
37
|
-
validateAnimatedStyles,
|
|
38
|
-
} from './utils';
|
|
33
|
+
import { isAnimated, shallowEqual, validateAnimatedStyles } from './utils';
|
|
39
34
|
|
|
40
35
|
interface AnimatedState {
|
|
41
36
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -450,6 +445,20 @@ function checkSharedValueUsage(
|
|
|
450
445
|
}
|
|
451
446
|
}
|
|
452
447
|
|
|
448
|
+
// Builds one big hash from multiple worklets' hashes.
|
|
449
|
+
function buildWorkletsHash<Args extends unknown[], ReturnValue>(
|
|
450
|
+
worklets:
|
|
451
|
+
| Record<string, WorkletFunction<Args, ReturnValue>>
|
|
452
|
+
| WorkletFunction<Args, ReturnValue>[]
|
|
453
|
+
) {
|
|
454
|
+
// For arrays `Object.values` returns the array itself.
|
|
455
|
+
return Object.values(worklets).reduce(
|
|
456
|
+
(acc, worklet: WorkletFunction<Args, ReturnValue>) =>
|
|
457
|
+
acc + worklet.__workletHash.toString(),
|
|
458
|
+
''
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
|
|
453
462
|
/**
|
|
454
463
|
* Lets you create a styles object, similar to StyleSheet styles, which can be
|
|
455
464
|
* animated using shared values.
|