@hanzogui/animations-reanimated 3.0.6 → 4.4.0

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.
@@ -1,158 +1,189 @@
1
- import { normalizeTransition, getEffectiveAnimation } from "@hanzogui/animation-helpers";
1
+ import { getEffectiveAnimation, normalizeTransition } from "@hanzogui/animation-helpers";
2
2
  import { getSplitStyles, hooks, isWeb, Text, useComposedRefs, useEvent, useIsomorphicLayoutEffect, useThemeWithState, View } from "@hanzogui/core";
3
3
  import { ResetPresence, usePresence } from "@hanzogui/use-presence";
4
4
  import React, { forwardRef, useMemo, useRef } from "react";
5
- import Animated_, { cancelAnimation, runOnJS, useAnimatedReaction, useAnimatedStyle, useDerivedValue, useSharedValue, withDelay, withSpring, withTiming } from "react-native-reanimated";
5
+ import Animated_, { cancelAnimation, runOnJS, runOnUI, useAnimatedReaction, useAnimatedStyle, useDerivedValue, useSharedValue, withDelay, withSpring, withTiming } from "react-native-reanimated";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  const getDefaultExport = module => {
8
- const mod = module;
9
- return (mod.__esModule || mod[Symbol.toStringTag] === "Module") && mod.default || mod;
10
- },
11
- Animated = getDefaultExport(Animated_),
12
- resolveDynamicValue = (value, isDark) => {
13
- if (value !== null && typeof value == "object" && "dynamic" in value && typeof value.dynamic == "object") {
14
- const dynamic = value.dynamic;
15
- return isDark ? dynamic.dark : dynamic.light;
16
- }
17
- return value;
18
- },
19
- applyAnimation = (targetValue, config, callback) => {
20
- "worklet";
8
+ const mod = module;
9
+ if (mod.__esModule || mod[Symbol.toStringTag] === "Module") {
10
+ return mod.default || mod;
11
+ }
12
+ return mod;
13
+ };
14
+ const Animated = getDefaultExport(Animated_);
15
+ const resolveDynamicValue = (value, isDark) => {
16
+ if (value !== null && typeof value === "object" && "dynamic" in value && typeof value.dynamic === "object") {
17
+ const dynamic = value.dynamic;
18
+ return isDark ? dynamic.dark : dynamic.light;
19
+ }
20
+ return value;
21
+ };
22
+ const applyAnimation = (targetValue, config, callback) => {
23
+ "worklet";
21
24
 
22
- const delay = config.delay;
23
- let animatedValue;
24
- return config.type === "timing" ? animatedValue = withTiming(targetValue, config, callback) : animatedValue = withSpring(targetValue, config, callback), delay && delay > 0 && (animatedValue = withDelay(delay, animatedValue)), animatedValue;
25
- },
26
- ANIMATABLE_PROPERTIES = {
27
- // Transform
28
- transform: !0,
29
- // Opacity
30
- opacity: !0,
31
- // Dimensions
32
- height: !0,
33
- width: !0,
34
- minWidth: !0,
35
- minHeight: !0,
36
- maxWidth: !0,
37
- maxHeight: !0,
38
- // Background
39
- backgroundColor: !0,
40
- // Border colors
41
- borderColor: !0,
42
- borderLeftColor: !0,
43
- borderRightColor: !0,
44
- borderTopColor: !0,
45
- borderBottomColor: !0,
46
- // Border radius
47
- borderRadius: !0,
48
- borderTopLeftRadius: !0,
49
- borderTopRightRadius: !0,
50
- borderBottomLeftRadius: !0,
51
- borderBottomRightRadius: !0,
52
- // Border width
53
- borderWidth: !0,
54
- borderLeftWidth: !0,
55
- borderRightWidth: !0,
56
- borderTopWidth: !0,
57
- borderBottomWidth: !0,
58
- // Text
59
- color: !0,
60
- fontSize: !0,
61
- fontWeight: !0,
62
- lineHeight: !0,
63
- letterSpacing: !0,
64
- // Position
65
- left: !0,
66
- right: !0,
67
- top: !0,
68
- bottom: !0,
69
- // Margin
70
- margin: !0,
71
- marginTop: !0,
72
- marginBottom: !0,
73
- marginLeft: !0,
74
- marginRight: !0,
75
- marginHorizontal: !0,
76
- marginVertical: !0,
77
- // Padding
78
- padding: !0,
79
- paddingTop: !0,
80
- paddingBottom: !0,
81
- paddingLeft: !0,
82
- paddingRight: !0,
83
- paddingHorizontal: !0,
84
- paddingVertical: !0,
85
- // Flex/Gap
86
- gap: !0,
87
- rowGap: !0,
88
- columnGap: !0,
89
- flex: !0,
90
- flexGrow: !0,
91
- flexShrink: !0
92
- },
93
- canAnimateProperty = (key, value, animateOnly) => !(!ANIMATABLE_PROPERTIES[key] || value === "auto" || typeof value == "string" && value.startsWith("calc") || animateOnly && !animateOnly.includes(key));
25
+ const delay = config.delay;
26
+ let animatedValue;
27
+ if (config.type === "timing") {
28
+ animatedValue = withTiming(targetValue, config, callback);
29
+ } else {
30
+ animatedValue = withSpring(targetValue, config, callback);
31
+ }
32
+ if (delay && delay > 0) {
33
+ animatedValue = withDelay(delay, animatedValue);
34
+ }
35
+ return animatedValue;
36
+ };
37
+ const ANIMATABLE_PROPERTIES = {
38
+ // Transform
39
+ transform: true,
40
+ // Opacity
41
+ opacity: true,
42
+ // Dimensions
43
+ height: true,
44
+ width: true,
45
+ minWidth: true,
46
+ minHeight: true,
47
+ maxWidth: true,
48
+ maxHeight: true,
49
+ // Background
50
+ backgroundColor: true,
51
+ // Border colors
52
+ borderColor: true,
53
+ borderLeftColor: true,
54
+ borderRightColor: true,
55
+ borderTopColor: true,
56
+ borderBottomColor: true,
57
+ // Border radius
58
+ borderRadius: true,
59
+ borderTopLeftRadius: true,
60
+ borderTopRightRadius: true,
61
+ borderBottomLeftRadius: true,
62
+ borderBottomRightRadius: true,
63
+ // Border width
64
+ borderWidth: true,
65
+ borderLeftWidth: true,
66
+ borderRightWidth: true,
67
+ borderTopWidth: true,
68
+ borderBottomWidth: true,
69
+ // Text
70
+ color: true,
71
+ fontSize: true,
72
+ fontWeight: true,
73
+ lineHeight: true,
74
+ letterSpacing: true,
75
+ // Position
76
+ left: true,
77
+ right: true,
78
+ top: true,
79
+ bottom: true,
80
+ // Margin
81
+ margin: true,
82
+ marginTop: true,
83
+ marginBottom: true,
84
+ marginLeft: true,
85
+ marginRight: true,
86
+ marginHorizontal: true,
87
+ marginVertical: true,
88
+ // Padding
89
+ padding: true,
90
+ paddingTop: true,
91
+ paddingBottom: true,
92
+ paddingLeft: true,
93
+ paddingRight: true,
94
+ paddingHorizontal: true,
95
+ paddingVertical: true,
96
+ // Flex/Gap
97
+ gap: true,
98
+ rowGap: true,
99
+ columnGap: true,
100
+ flex: true,
101
+ flexGrow: true,
102
+ flexShrink: true
103
+ };
104
+ const canAnimateProperty = (key, value, animateOnly) => {
105
+ if (!ANIMATABLE_PROPERTIES[key]) return false;
106
+ if (value === "auto") return false;
107
+ if (typeof value === "string" && value.startsWith("calc")) return false;
108
+ if (animateOnly && !animateOnly.includes(key)) return false;
109
+ return true;
110
+ };
94
111
  function createWebAnimatedComponent(defaultTag) {
95
- const isText = defaultTag === "span",
96
- Component = Animated.createAnimatedComponent(forwardRef((propsIn, ref) => {
97
- const {
98
- forwardedRef,
99
- render = defaultTag,
100
- ...rest
101
- } = propsIn,
102
- hostRef = useRef(null),
103
- composedRefs = useComposedRefs(forwardedRef, ref, hostRef),
104
- stateRef = useRef({
105
- get host() {
106
- return hostRef.current;
107
- }
108
- }),
109
- [, themeState] = useThemeWithState({}),
110
- viewProps = getSplitStyles(rest, isText ? Text.staticConfig : View.staticConfig, themeState?.theme ?? {}, themeState?.name ?? "", {
111
- unmounted: !1
112
- }, {
113
- isAnimated: !1,
114
- noClass: !0
115
- })?.viewProps ?? {},
116
- Element = render,
117
- transformedProps = hooks.usePropsTransform?.(render, viewProps, stateRef, !1);
118
- return /* @__PURE__ */jsx(Element, {
119
- ...transformedProps,
120
- ref: composedRefs
121
- });
122
- }));
123
- return Component.acceptRenderProp = !0, Component;
112
+ const isText = defaultTag === "span";
113
+ const Component = Animated.createAnimatedComponent(forwardRef((propsIn, ref) => {
114
+ const {
115
+ forwardedRef,
116
+ render = defaultTag,
117
+ ...rest
118
+ } = propsIn;
119
+ const hostRef = useRef(null);
120
+ const composedRefs = useComposedRefs(forwardedRef, ref, hostRef);
121
+ const stateRef = useRef({
122
+ get host() {
123
+ return hostRef.current;
124
+ }
125
+ });
126
+ const [, themeState] = useThemeWithState({});
127
+ const result = getSplitStyles(rest, isText ? Text.staticConfig : View.staticConfig, themeState?.theme ?? {}, themeState?.name ?? "", {
128
+ unmounted: false
129
+ }, {
130
+ isAnimated: false,
131
+ noClass: true
132
+ });
133
+ const viewProps = result?.viewProps ?? {};
134
+ const Element = render;
135
+ const transformedProps = hooks.usePropsTransform?.(render, viewProps, stateRef, false);
136
+ return /* @__PURE__ */jsx(Element, {
137
+ ...transformedProps,
138
+ ref: composedRefs
139
+ });
140
+ }));
141
+ Component.acceptRenderProp = true;
142
+ return Component;
124
143
  }
125
- const AnimatedView = createWebAnimatedComponent("div"),
126
- AnimatedText = createWebAnimatedComponent("span");
144
+ const AnimatedView = createWebAnimatedComponent("div");
145
+ const AnimatedText = createWebAnimatedComponent("span");
127
146
  function buildTransitionConfig(transition, animations, animationState, styleKeys) {
128
- const normalized = normalizeTransition(transition),
129
- effectiveKey = getEffectiveAnimation(normalized, animationState);
147
+ const normalized = normalizeTransition(transition);
148
+ const effectiveKey = getEffectiveAnimation(normalized, animationState);
130
149
  let base = effectiveKey ? animations[effectiveKey] ?? {
131
150
  type: "spring"
132
151
  } : {
133
152
  type: "spring"
134
153
  };
135
- normalized.delay && (base = {
136
- ...base,
137
- delay: normalized.delay
138
- }), normalized.config && (base = {
139
- ...base,
140
- ...normalized.config
141
- }, base.type !== "timing" && normalized.config.duration !== void 0 && normalized.config.damping === void 0 && normalized.config.stiffness === void 0 && normalized.config.mass === void 0 && (base = {
142
- ...base,
143
- type: "timing"
144
- }));
154
+ if (normalized.delay) {
155
+ base = {
156
+ ...base,
157
+ delay: normalized.delay
158
+ };
159
+ }
160
+ if (normalized.config) {
161
+ base = {
162
+ ...base,
163
+ ...normalized.config
164
+ };
165
+ if (base.type !== "timing" && normalized.config.duration !== void 0 && normalized.config.damping === void 0 && normalized.config.stiffness === void 0 && normalized.config.mass === void 0) {
166
+ base = {
167
+ ...base,
168
+ type: "timing"
169
+ };
170
+ }
171
+ }
145
172
  const propertyConfigs = {};
146
173
  for (const key of styleKeys) {
147
174
  const propAnimation = normalized.properties[key];
148
- if (typeof propAnimation == "string") propertyConfigs[key] = animations[propAnimation] ?? base;else if (propAnimation && typeof propAnimation == "object") {
149
- const configType = propAnimation.type,
150
- baseForProp = configType ? animations[configType] ?? base : base;
175
+ if (typeof propAnimation === "string") {
176
+ propertyConfigs[key] = animations[propAnimation] ?? base;
177
+ } else if (propAnimation && typeof propAnimation === "object") {
178
+ const configType = propAnimation.type;
179
+ const baseForProp = configType ? animations[configType] ?? base : base;
151
180
  propertyConfigs[key] = {
152
181
  ...baseForProp,
153
182
  ...propAnimation
154
183
  };
155
- } else propertyConfigs[key] = base;
184
+ } else {
185
+ propertyConfigs[key] = base;
186
+ }
156
187
  }
157
188
  return {
158
189
  baseConfig: base,
@@ -161,23 +192,31 @@ function buildTransitionConfig(transition, animations, animationState, styleKeys
161
192
  }
162
193
  function getStyleKeys(style) {
163
194
  const keys = new Set(Object.keys(style));
164
- if (style.transform && Array.isArray(style.transform)) for (const t of style.transform) t && typeof t == "object" && keys.add(Object.keys(t)[0]);
195
+ if (style.transform && Array.isArray(style.transform)) {
196
+ for (const t of style.transform) {
197
+ if (t && typeof t === "object") {
198
+ keys.add(Object.keys(t)[0]);
199
+ }
200
+ }
201
+ }
165
202
  return keys;
166
203
  }
167
204
  function createAnimations(animationsConfig) {
168
205
  const animations = {};
169
- for (const key in animationsConfig) animations[key] = {
170
- type: "spring",
171
- ...animationsConfig[key]
172
- };
206
+ for (const key in animationsConfig) {
207
+ animations[key] = {
208
+ type: "spring",
209
+ ...animationsConfig[key]
210
+ };
211
+ }
173
212
  return {
174
- needsCustomComponent: !0,
213
+ needsCustomComponent: true,
175
214
  View: isWeb ? AnimatedView : Animated.View,
176
215
  Text: isWeb ? AnimatedText : Animated.Text,
177
- isReactNative: !0,
216
+ isReactNative: true,
178
217
  inputStyle: "value",
179
218
  outputStyle: "inline",
180
- avoidReRenders: !0,
219
+ avoidReRenders: true,
181
220
  animations,
182
221
  usePresence,
183
222
  ResetPresence,
@@ -200,18 +239,27 @@ function createAnimations(animationsConfig) {
200
239
  setValue(next, config = {
201
240
  type: "spring"
202
241
  }, onFinish) {
203
- "worklet";
242
+ if (config.type === "direct") {
243
+ sharedValue.value = next;
244
+ onFinish?.();
245
+ } else {
246
+ const cb = onFinish ? () => {
247
+ "worklet";
204
248
 
205
- const handleFinish = onFinish ? () => {
206
- "worklet";
249
+ runOnJS(onFinish)();
250
+ } : void 0;
251
+ if (isWeb) {
252
+ sharedValue.value = config.type === "spring" ? withSpring(next, config, cb) : withTiming(next, config, cb);
253
+ } else {
254
+ runOnUI(() => {
255
+ "worklet";
207
256
 
208
- runOnJS(onFinish)();
209
- } : void 0;
210
- config.type === "direct" ? (sharedValue.value = next, onFinish?.()) : config.type === "spring" ? sharedValue.value = withSpring(next, config, handleFinish) : sharedValue.value = withTiming(next, config, handleFinish);
257
+ sharedValue.value = config.type === "spring" ? withSpring(next, config, cb) : withTiming(next, config, cb);
258
+ })();
259
+ }
260
+ }
211
261
  },
212
262
  stop() {
213
- "worklet";
214
-
215
263
  cancelAnimation(sharedValue);
216
264
  }
217
265
  }), [sharedValue]);
@@ -224,106 +272,161 @@ function createAnimations(animationsConfig) {
224
272
  }, onValue) {
225
273
  const instance = value.getInstance();
226
274
  return useAnimatedReaction(() => instance.value, (next, prev) => {
227
- prev !== next && runOnJS(onValue)(next);
275
+ if (prev !== next) {
276
+ runOnJS(onValue)(next);
277
+ }
228
278
  }, [onValue, instance]);
229
279
  },
230
280
  // =========================================================================
231
281
  // useAnimatedNumberStyle - Create animated styles from values
232
282
  // =========================================================================
233
283
  useAnimatedNumberStyle(val, getStyle) {
234
- const instance = val.getInstance(),
235
- derivedValue = useDerivedValue(() => instance.value, [instance, getStyle]);
236
- return useAnimatedStyle(() => getStyle(derivedValue.value), [val, getStyle, derivedValue, instance]);
284
+ const instance = val.getInstance();
285
+ if (isWeb) {
286
+ return useAnimatedStyle(() => {
287
+ "worklet";
288
+
289
+ return getStyle(instance.value);
290
+ }, [instance, getStyle]);
291
+ }
292
+ const styleVal = useDerivedValue(() => {
293
+ "worklet";
294
+
295
+ return getStyle(instance.value);
296
+ });
297
+ return useAnimatedStyle(() => {
298
+ "worklet";
299
+
300
+ return styleVal.value;
301
+ });
302
+ },
303
+ useAnimatedNumbersStyle(vals, getStyle) {
304
+ const instances = vals.map(v => v.getInstance());
305
+ return useAnimatedStyle(() => {
306
+ "worklet";
307
+
308
+ const currentValues = instances.map(inst => inst.value);
309
+ return getStyle(...currentValues);
310
+ }, isWeb ? [getStyle, ...instances] : void 0);
237
311
  },
238
312
  // =========================================================================
239
313
  // useAnimations - Main animation hook for components
240
314
  // =========================================================================
241
315
  useAnimations(animationProps) {
242
316
  const {
243
- props,
244
- presence,
245
- style,
246
- componentState,
247
- useStyleEmitter,
248
- themeName,
249
- stateRef,
250
- styleState
251
- } = animationProps,
252
- isHydrating = componentState.unmounted === !0,
253
- isMounting = componentState.unmounted === "should-enter",
254
- isEntering = !!componentState.unmounted,
255
- isExiting = presence?.[0] === !1,
256
- wasEnteringRef = useRef(isEntering),
257
- justFinishedEntering = wasEnteringRef.current && !isEntering;
317
+ props,
318
+ presence,
319
+ style,
320
+ componentState,
321
+ useStyleEmitter,
322
+ themeName,
323
+ stateRef,
324
+ styleState
325
+ } = animationProps;
326
+ const isHydrating = componentState.unmounted === true;
327
+ const isMounting = componentState.unmounted === "should-enter";
328
+ const isEntering = !!componentState.unmounted;
329
+ const isExiting = presence?.[0] === false;
330
+ const wasEnteringRef = useRef(isEntering);
331
+ const justFinishedEntering = wasEnteringRef.current && !isEntering;
258
332
  React.useEffect(() => {
259
333
  wasEnteringRef.current = isEntering;
260
334
  });
261
- const effectiveTransition = styleState?.effectiveTransition ?? props.transition,
262
- normalized = normalizeTransition(effectiveTransition),
263
- animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default",
264
- animationKey = getEffectiveAnimation(normalized, animationState),
265
- disableAnimation = isHydrating || !animationKey,
266
- isDark = themeName?.startsWith("dark") || !1,
267
- sendExitComplete = presence?.[1],
268
- exitCycleIdRef = useRef(0),
269
- pendingExitKeysRef = useRef(/* @__PURE__ */new Set()),
270
- exitCompletedRef = useRef(!1),
271
- wasExitingRef = useRef(!1),
272
- justStartedExiting = isExiting && !wasExitingRef.current,
273
- justStoppedExiting = !isExiting && wasExitingRef.current,
274
- markExitKeyDone = useEvent((key, cycleId, finished) => {
275
- cycleId === exitCycleIdRef.current && (exitCompletedRef.current || (pendingExitKeysRef.current.delete(key), pendingExitKeysRef.current.size === 0 && (exitCompletedRef.current = !0, sendExitComplete?.())));
276
- }),
277
- isExitingRef = useSharedValue(isExiting),
278
- exitCycleIdShared = useSharedValue(exitCycleIdRef.current);
279
- justStartedExiting && (exitCycleIdRef.current++, exitCompletedRef.current = !1, pendingExitKeysRef.current.clear()), justStoppedExiting && (exitCycleIdRef.current++, pendingExitKeysRef.current.clear()), useIsomorphicLayoutEffect(() => {
280
- isExitingRef.value = isExiting, exitCycleIdShared.value = exitCycleIdRef.current;
281
- }, [isExiting, exitCycleIdRef.current]), React.useEffect(() => {
335
+ const effectiveTransition = styleState?.effectiveTransition ?? props.transition;
336
+ const normalized = normalizeTransition(effectiveTransition);
337
+ const animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default";
338
+ const animationKey = getEffectiveAnimation(normalized, animationState);
339
+ const disableAnimation = isHydrating || !animationKey;
340
+ const isDark = themeName?.startsWith("dark") || false;
341
+ const sendExitComplete = presence?.[1];
342
+ const exitCycleIdRef = useRef(0);
343
+ const pendingExitKeysRef = useRef(/* @__PURE__ */new Set());
344
+ const exitCompletedRef = useRef(false);
345
+ const wasExitingRef = useRef(false);
346
+ const justStartedExiting = isExiting && !wasExitingRef.current;
347
+ const justStoppedExiting = !isExiting && wasExitingRef.current;
348
+ const markExitKeyDone = useEvent((key, cycleId, finished) => {
349
+ if (cycleId !== exitCycleIdRef.current) return;
350
+ if (exitCompletedRef.current) return;
351
+ pendingExitKeysRef.current.delete(key);
352
+ if (pendingExitKeysRef.current.size === 0) {
353
+ exitCompletedRef.current = true;
354
+ sendExitComplete?.();
355
+ }
356
+ });
357
+ const isExitingRef = useSharedValue(isExiting);
358
+ const exitCycleIdShared = useSharedValue(exitCycleIdRef.current);
359
+ if (justStartedExiting) {
360
+ exitCycleIdRef.current++;
361
+ exitCompletedRef.current = false;
362
+ pendingExitKeysRef.current.clear();
363
+ }
364
+ if (justStoppedExiting) {
365
+ exitCycleIdRef.current++;
366
+ pendingExitKeysRef.current.clear();
367
+ }
368
+ useIsomorphicLayoutEffect(() => {
369
+ isExitingRef.value = isExiting;
370
+ exitCycleIdShared.value = exitCycleIdRef.current;
371
+ }, [isExiting, exitCycleIdRef.current]);
372
+ React.useEffect(() => {
282
373
  wasExitingRef.current = isExiting;
283
374
  });
284
- const animatedTargetsRef = useSharedValue(null),
285
- staticTargetsRef = useSharedValue(null),
286
- transformTargetsRef = useSharedValue(null),
287
- {
288
- animatedStyles,
289
- staticStyles
290
- } = useMemo(() => {
291
- const animated = {},
292
- staticStyles2 = {},
293
- animateOnly = props.animateOnly;
294
- for (const key in style) {
295
- const rawValue = style[key],
296
- value = resolveDynamicValue(rawValue, isDark);
297
- if (value !== void 0) {
298
- if (disableAnimation) {
299
- staticStyles2[key] = value;
300
- continue;
301
- }
302
- canAnimateProperty(key, value, animateOnly) ? animated[key] = value : staticStyles2[key] = value;
303
- }
375
+ const animatedTargetsRef = useSharedValue(null);
376
+ const staticTargetsRef = useSharedValue(null);
377
+ const transformTargetsRef = useSharedValue(null);
378
+ const {
379
+ animatedStyles,
380
+ staticStyles
381
+ } = useMemo(() => {
382
+ const animated = {};
383
+ const staticStyles2 = {};
384
+ const animateOnly = props.animateOnly;
385
+ for (const key in style) {
386
+ const rawValue = style[key];
387
+ const value = resolveDynamicValue(rawValue, isDark);
388
+ if (value === void 0) continue;
389
+ if (disableAnimation) {
390
+ staticStyles2[key] = value;
391
+ continue;
392
+ }
393
+ if (canAnimateProperty(key, value, animateOnly)) {
394
+ animated[key] = value;
395
+ } else {
396
+ staticStyles2[key] = value;
304
397
  }
305
- if (isMounting) for (const key in animated) staticStyles2[key] = animated[key];
398
+ }
399
+ if (isMounting) {
400
+ for (const key in animated) {
401
+ staticStyles2[key] = animated[key];
402
+ }
403
+ }
404
+ return {
405
+ animatedStyles: animated,
406
+ staticStyles: staticStyles2
407
+ };
408
+ }, [disableAnimation, style, isDark, isMounting, props.animateOnly]);
409
+ const {
410
+ baseConfig,
411
+ propertyConfigs
412
+ } = useMemo(() => {
413
+ if (isHydrating) {
306
414
  return {
307
- animatedStyles: animated,
308
- staticStyles: staticStyles2
415
+ baseConfig: {
416
+ type: "timing",
417
+ duration: 0
418
+ },
419
+ propertyConfigs: {}
309
420
  };
310
- }, [disableAnimation, style, isDark, isMounting, props.animateOnly]),
311
- {
312
- baseConfig,
313
- propertyConfigs
314
- } = useMemo(() => isHydrating ? {
315
- baseConfig: {
316
- type: "timing",
317
- duration: 0
318
- },
319
- propertyConfigs: {}
320
- } : buildTransitionConfig(props.transition, animations, animationState, getStyleKeys(animatedStyles)), [isHydrating, props.transition, animatedStyles, animationState]),
321
- configRef = useSharedValue({
322
- baseConfig,
323
- propertyConfigs,
324
- disableAnimation,
325
- isHydrating
326
- });
421
+ }
422
+ return buildTransitionConfig(props.transition, animations, animationState, getStyleKeys(animatedStyles));
423
+ }, [isHydrating, props.transition, animatedStyles, animationState]);
424
+ const configRef = useSharedValue({
425
+ baseConfig,
426
+ propertyConfigs,
427
+ disableAnimation,
428
+ isHydrating
429
+ });
327
430
  useIsomorphicLayoutEffect(() => {
328
431
  configRef.set({
329
432
  baseConfig,
@@ -331,16 +434,17 @@ function createAnimations(animationsConfig) {
331
434
  disableAnimation,
332
435
  isHydrating
333
436
  });
334
- }, [baseConfig, propertyConfigs, disableAnimation, isHydrating]), useStyleEmitter?.((nextStyle, effectiveTransition2) => {
335
- const animateOnly = props.animateOnly,
336
- animated = {},
337
- statics = {},
338
- transforms = [],
339
- transitionToUse = effectiveTransition2 ?? props.transition,
340
- {
341
- baseConfig: newBase,
342
- propertyConfigs: newPropertyConfigs
343
- } = buildTransitionConfig(transitionToUse, animations, animationState, getStyleKeys(nextStyle));
437
+ }, [baseConfig, propertyConfigs, disableAnimation, isHydrating]);
438
+ useStyleEmitter?.((nextStyle, effectiveTransition2) => {
439
+ const animateOnly = props.animateOnly;
440
+ const animated = {};
441
+ const statics = {};
442
+ const transforms = [];
443
+ const transitionToUse = effectiveTransition2 ?? props.transition;
444
+ const {
445
+ baseConfig: newBase,
446
+ propertyConfigs: newPropertyConfigs
447
+ } = buildTransitionConfig(transitionToUse, animations, animationState, getStyleKeys(nextStyle));
344
448
  configRef.set({
345
449
  baseConfig: newBase,
346
450
  propertyConfigs: newPropertyConfigs,
@@ -348,76 +452,108 @@ function createAnimations(animationsConfig) {
348
452
  isHydrating: configRef.get().isHydrating
349
453
  });
350
454
  for (const key in nextStyle) {
351
- const rawValue = nextStyle[key],
352
- value = resolveDynamicValue(rawValue, isDark);
353
- if (value != null) {
354
- if (configRef.get().disableAnimation) {
355
- statics[key] = value;
356
- continue;
357
- }
358
- if (key === "transform" && Array.isArray(value)) {
359
- for (const t of value) if (t && typeof t == "object") {
360
- const tKey = Object.keys(t)[0],
361
- tVal = t[tKey];
362
- (typeof tVal == "number" || typeof tVal == "string") && transforms.push(t);
455
+ const rawValue = nextStyle[key];
456
+ const value = resolveDynamicValue(rawValue, isDark);
457
+ if (value == void 0) continue;
458
+ if (configRef.get().disableAnimation) {
459
+ statics[key] = value;
460
+ continue;
461
+ }
462
+ if (key === "transform" && Array.isArray(value)) {
463
+ for (const t of value) {
464
+ if (t && typeof t === "object") {
465
+ const tKey = Object.keys(t)[0];
466
+ const tVal = t[tKey];
467
+ if (typeof tVal === "number" || typeof tVal === "string") {
468
+ transforms.push(t);
469
+ }
363
470
  }
364
- continue;
365
471
  }
366
- canAnimateProperty(key, value, animateOnly) ? animated[key] = value : statics[key] = value;
472
+ continue;
473
+ }
474
+ if (canAnimateProperty(key, value, animateOnly)) {
475
+ animated[key] = value;
476
+ } else {
477
+ statics[key] = value;
367
478
  }
368
479
  }
369
- animatedTargetsRef.set(animated), staticTargetsRef.set(statics), transformTargetsRef.set(transforms), process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile" && console.info("[animations-reanimated] useStyleEmitter update", {
370
- animated,
371
- statics,
372
- transforms
373
- });
480
+ animatedTargetsRef.set(animated);
481
+ staticTargetsRef.set(statics);
482
+ transformTargetsRef.set(transforms);
483
+ if (process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile") {
484
+ console.info("[animations-reanimated] useStyleEmitter update", {
485
+ animated,
486
+ statics,
487
+ transforms
488
+ });
489
+ }
374
490
  });
375
- const exitKeysRegistered = useRef(!1);
491
+ const exitKeysRegistered = useRef(false);
376
492
  if (justStartedExiting && sendExitComplete) {
377
- const exitKeys = [],
378
- animateOnly = props.animateOnly;
379
- for (const key in animatedStyles) key !== "transform" && canAnimateProperty(key, animatedStyles[key], animateOnly) && exitKeys.push(key);
493
+ const exitKeys = [];
494
+ const animateOnly = props.animateOnly;
495
+ for (const key in animatedStyles) {
496
+ if (key === "transform") continue;
497
+ if (canAnimateProperty(key, animatedStyles[key], animateOnly)) {
498
+ exitKeys.push(key);
499
+ }
500
+ }
380
501
  const transforms = animatedStyles.transform;
381
- if (transforms && Array.isArray(transforms)) for (const t of transforms) {
382
- if (!t) continue;
383
- const tKey = Object.keys(t)[0];
384
- if (tKey) {
385
- if (animateOnly && !animateOnly.includes(tKey)) continue;
386
- exitKeys.push(`transform:${tKey}`);
502
+ if (transforms && Array.isArray(transforms)) {
503
+ for (const t of transforms) {
504
+ if (!t) continue;
505
+ const tKey = Object.keys(t)[0];
506
+ if (tKey) {
507
+ if (animateOnly && !animateOnly.includes(tKey)) {
508
+ continue;
509
+ }
510
+ exitKeys.push(`transform:${tKey}`);
511
+ }
387
512
  }
388
513
  }
389
- pendingExitKeysRef.current = new Set(exitKeys), exitKeysRegistered.current = exitKeys.length > 0;
514
+ pendingExitKeysRef.current = new Set(exitKeys);
515
+ exitKeysRegistered.current = exitKeys.length > 0;
390
516
  }
391
517
  React.useEffect(() => {
392
- !justStartedExiting || !sendExitComplete || !exitKeysRegistered.current && pendingExitKeysRef.current.size === 0 && (exitCompletedRef.current || (exitCompletedRef.current = !0, sendExitComplete()));
518
+ if (!justStartedExiting || !sendExitComplete) return;
519
+ if (!exitKeysRegistered.current && pendingExitKeysRef.current.size === 0) {
520
+ if (!exitCompletedRef.current) {
521
+ exitCompletedRef.current = true;
522
+ sendExitComplete();
523
+ }
524
+ }
393
525
  }, [justStartedExiting, sendExitComplete]);
394
526
  const animatedStyle = useAnimatedStyle(() => {
395
527
  "worklet";
396
528
 
397
- if (disableAnimation || isHydrating) return {};
398
- const result = {},
399
- config = configRef.get(),
400
- emitterAnimated = animatedTargetsRef.value,
401
- emitterStatic = staticTargetsRef.value,
402
- emitterTransforms = transformTargetsRef.value,
403
- hasEmitterUpdates = emitterAnimated !== null,
404
- animatedValues = hasEmitterUpdates ? emitterAnimated : animatedStyles,
405
- staticValues = hasEmitterUpdates ? emitterStatic : {},
406
- currentlyExiting = isExitingRef.value,
407
- currentCycleId = exitCycleIdShared.value;
408
- for (const key in staticValues) result[key] = staticValues[key];
529
+ if (disableAnimation || isHydrating) {
530
+ return {};
531
+ }
532
+ const result = {};
533
+ const config = configRef.get();
534
+ const emitterAnimated = animatedTargetsRef.value;
535
+ const emitterStatic = staticTargetsRef.value;
536
+ const emitterTransforms = transformTargetsRef.value;
537
+ const hasEmitterUpdates = emitterAnimated !== null;
538
+ const animatedValues = hasEmitterUpdates ? emitterAnimated : animatedStyles;
539
+ const staticValues = hasEmitterUpdates ? emitterStatic : {};
540
+ const currentlyExiting = isExitingRef.value;
541
+ const currentCycleId = exitCycleIdShared.value;
542
+ for (const key in staticValues) {
543
+ result[key] = staticValues[key];
544
+ }
409
545
  for (const key in animatedValues) {
410
546
  if (key === "transform") continue;
411
- const targetValue = animatedValues[key],
412
- propConfig = config.propertyConfigs[key] ?? config.baseConfig;
547
+ const targetValue = animatedValues[key];
548
+ const propConfig = config.propertyConfigs[key] ?? config.baseConfig;
413
549
  let callback;
414
550
  if (currentlyExiting) {
415
- const capturedKey = key,
416
- capturedCycleId = currentCycleId;
551
+ const capturedKey = key;
552
+ const capturedCycleId = currentCycleId;
417
553
  callback = finished => {
418
554
  "worklet";
419
555
 
420
- runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? !1);
556
+ runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? false);
421
557
  };
422
558
  }
423
559
  result[key] = applyAnimation(targetValue, propConfig, callback);
@@ -430,18 +566,18 @@ function createAnimations(animationsConfig) {
430
566
  const keys = Object.keys(t);
431
567
  if (keys.length === 0) continue;
432
568
  const value = t[keys[0]];
433
- if (typeof value == "number" || typeof value == "string") {
434
- const transformKey = Object.keys(t)[0],
435
- targetValue = t[transformKey],
436
- propConfig = config.propertyConfigs[transformKey] ?? config.baseConfig;
569
+ if (typeof value === "number" || typeof value === "string") {
570
+ const transformKey = Object.keys(t)[0];
571
+ const targetValue = t[transformKey];
572
+ const propConfig = config.propertyConfigs[transformKey] ?? config.baseConfig;
437
573
  let callback;
438
574
  if (currentlyExiting) {
439
- const capturedKey = `transform:${transformKey}`,
440
- capturedCycleId = currentCycleId;
575
+ const capturedKey = `transform:${transformKey}`;
576
+ const capturedCycleId = currentCycleId;
441
577
  callback = finished => {
442
578
  "worklet";
443
579
 
444
- runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? !1);
580
+ runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? false);
445
581
  };
446
582
  }
447
583
  validTransforms.push({
@@ -449,21 +585,26 @@ function createAnimations(animationsConfig) {
449
585
  });
450
586
  }
451
587
  }
452
- validTransforms.length > 0 && (result.transform = validTransforms);
588
+ if (validTransforms.length > 0) {
589
+ result.transform = validTransforms;
590
+ }
453
591
  }
454
592
  return result;
455
- }, [animatedStyles, baseConfig, propertyConfigs, disableAnimation, isHydrating,
456
- // Pass SharedValues so the mapper watches them on web (see useAnimatedStyle.ts line 470-472)
457
- animatedTargetsRef, staticTargetsRef, transformTargetsRef, isExitingRef, exitCycleIdShared, markExitKeyDone]);
458
- return process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile" && console.info("[animations-reanimated] useAnimations", {
459
- animationKey,
460
- componentState,
461
- isExiting,
462
- animatedStyles,
463
- staticStyles,
464
- baseConfig,
465
- propertyConfigs
466
- }), {
593
+ }, isWeb ? [animatedStyles, baseConfig, propertyConfigs, disableAnimation, isHydrating,
594
+ // pass SharedValues so the mapper watches them on web (no babel plugin)
595
+ animatedTargetsRef, staticTargetsRef, transformTargetsRef, isExitingRef, exitCycleIdShared, markExitKeyDone] : void 0);
596
+ if (process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile") {
597
+ console.info("[animations-reanimated] useAnimations", {
598
+ animationKey,
599
+ componentState,
600
+ isExiting,
601
+ animatedStyles,
602
+ staticStyles,
603
+ baseConfig,
604
+ propertyConfigs
605
+ });
606
+ }
607
+ return {
467
608
  style: [staticStyles, animatedStyle]
468
609
  };
469
610
  }