@hanzogui/animations-reanimated 3.0.6 → 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.
@@ -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, 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,168 @@ 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 = useSharedValue(getStyle(instance.value));
293
+ useAnimatedReaction(() => {
294
+ "worklet";
295
+
296
+ return instance.value;
297
+ }, (current, previous) => {
298
+ "worklet";
299
+
300
+ if (current !== previous) {
301
+ styleVal.value = getStyle(current);
302
+ }
303
+ });
304
+ return useAnimatedStyle(() => {
305
+ "worklet";
306
+
307
+ return styleVal.value;
308
+ });
309
+ },
310
+ useAnimatedNumbersStyle(vals, getStyle) {
311
+ const instances = vals.map(v => v.getInstance());
312
+ return useAnimatedStyle(() => {
313
+ "worklet";
314
+
315
+ const currentValues = instances.map(inst => inst.value);
316
+ return getStyle(...currentValues);
317
+ }, isWeb ? [getStyle, ...instances] : void 0);
237
318
  },
238
319
  // =========================================================================
239
320
  // useAnimations - Main animation hook for components
240
321
  // =========================================================================
241
322
  useAnimations(animationProps) {
242
323
  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;
324
+ props,
325
+ presence,
326
+ style,
327
+ componentState,
328
+ useStyleEmitter,
329
+ themeName,
330
+ stateRef,
331
+ styleState
332
+ } = animationProps;
333
+ const isHydrating = componentState.unmounted === true;
334
+ const isMounting = componentState.unmounted === "should-enter";
335
+ const isEntering = !!componentState.unmounted;
336
+ const isExiting = presence?.[0] === false;
337
+ const wasEnteringRef = useRef(isEntering);
338
+ const justFinishedEntering = wasEnteringRef.current && !isEntering;
258
339
  React.useEffect(() => {
259
340
  wasEnteringRef.current = isEntering;
260
341
  });
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(() => {
342
+ const effectiveTransition = styleState?.effectiveTransition ?? props.transition;
343
+ const normalized = normalizeTransition(effectiveTransition);
344
+ const animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default";
345
+ const animationKey = getEffectiveAnimation(normalized, animationState);
346
+ const disableAnimation = isHydrating || !animationKey;
347
+ const isDark = themeName?.startsWith("dark") || false;
348
+ const sendExitComplete = presence?.[1];
349
+ const exitCycleIdRef = useRef(0);
350
+ const pendingExitKeysRef = useRef(/* @__PURE__ */new Set());
351
+ const exitCompletedRef = useRef(false);
352
+ const wasExitingRef = useRef(false);
353
+ const justStartedExiting = isExiting && !wasExitingRef.current;
354
+ const justStoppedExiting = !isExiting && wasExitingRef.current;
355
+ const markExitKeyDone = useEvent((key, cycleId, finished) => {
356
+ if (cycleId !== exitCycleIdRef.current) return;
357
+ if (exitCompletedRef.current) return;
358
+ pendingExitKeysRef.current.delete(key);
359
+ if (pendingExitKeysRef.current.size === 0) {
360
+ exitCompletedRef.current = true;
361
+ sendExitComplete?.();
362
+ }
363
+ });
364
+ const isExitingRef = useSharedValue(isExiting);
365
+ const exitCycleIdShared = useSharedValue(exitCycleIdRef.current);
366
+ if (justStartedExiting) {
367
+ exitCycleIdRef.current++;
368
+ exitCompletedRef.current = false;
369
+ pendingExitKeysRef.current.clear();
370
+ }
371
+ if (justStoppedExiting) {
372
+ exitCycleIdRef.current++;
373
+ pendingExitKeysRef.current.clear();
374
+ }
375
+ useIsomorphicLayoutEffect(() => {
376
+ isExitingRef.value = isExiting;
377
+ exitCycleIdShared.value = exitCycleIdRef.current;
378
+ }, [isExiting, exitCycleIdRef.current]);
379
+ React.useEffect(() => {
282
380
  wasExitingRef.current = isExiting;
283
381
  });
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
- }
382
+ const animatedTargetsRef = useSharedValue(null);
383
+ const staticTargetsRef = useSharedValue(null);
384
+ const transformTargetsRef = useSharedValue(null);
385
+ const {
386
+ animatedStyles,
387
+ staticStyles
388
+ } = useMemo(() => {
389
+ const animated = {};
390
+ const staticStyles2 = {};
391
+ const animateOnly = props.animateOnly;
392
+ for (const key in style) {
393
+ const rawValue = style[key];
394
+ const value = resolveDynamicValue(rawValue, isDark);
395
+ if (value === void 0) continue;
396
+ if (disableAnimation) {
397
+ staticStyles2[key] = value;
398
+ continue;
399
+ }
400
+ if (canAnimateProperty(key, value, animateOnly)) {
401
+ animated[key] = value;
402
+ } else {
403
+ staticStyles2[key] = value;
304
404
  }
305
- if (isMounting) for (const key in animated) staticStyles2[key] = animated[key];
405
+ }
406
+ if (isMounting) {
407
+ for (const key in animated) {
408
+ staticStyles2[key] = animated[key];
409
+ }
410
+ }
411
+ return {
412
+ animatedStyles: animated,
413
+ staticStyles: staticStyles2
414
+ };
415
+ }, [disableAnimation, style, isDark, isMounting, props.animateOnly]);
416
+ const {
417
+ baseConfig,
418
+ propertyConfigs
419
+ } = useMemo(() => {
420
+ if (isHydrating) {
306
421
  return {
307
- animatedStyles: animated,
308
- staticStyles: staticStyles2
422
+ baseConfig: {
423
+ type: "timing",
424
+ duration: 0
425
+ },
426
+ propertyConfigs: {}
309
427
  };
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
- });
428
+ }
429
+ return buildTransitionConfig(props.transition, animations, animationState, getStyleKeys(animatedStyles));
430
+ }, [isHydrating, props.transition, animatedStyles, animationState]);
431
+ const configRef = useSharedValue({
432
+ baseConfig,
433
+ propertyConfigs,
434
+ disableAnimation,
435
+ isHydrating
436
+ });
327
437
  useIsomorphicLayoutEffect(() => {
328
438
  configRef.set({
329
439
  baseConfig,
@@ -331,16 +441,17 @@ function createAnimations(animationsConfig) {
331
441
  disableAnimation,
332
442
  isHydrating
333
443
  });
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));
444
+ }, [baseConfig, propertyConfigs, disableAnimation, isHydrating]);
445
+ useStyleEmitter?.((nextStyle, effectiveTransition2) => {
446
+ const animateOnly = props.animateOnly;
447
+ const animated = {};
448
+ const statics = {};
449
+ const transforms = [];
450
+ const transitionToUse = effectiveTransition2 ?? props.transition;
451
+ const {
452
+ baseConfig: newBase,
453
+ propertyConfigs: newPropertyConfigs
454
+ } = buildTransitionConfig(transitionToUse, animations, animationState, getStyleKeys(nextStyle));
344
455
  configRef.set({
345
456
  baseConfig: newBase,
346
457
  propertyConfigs: newPropertyConfigs,
@@ -348,76 +459,108 @@ function createAnimations(animationsConfig) {
348
459
  isHydrating: configRef.get().isHydrating
349
460
  });
350
461
  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);
462
+ const rawValue = nextStyle[key];
463
+ const value = resolveDynamicValue(rawValue, isDark);
464
+ if (value == void 0) continue;
465
+ if (configRef.get().disableAnimation) {
466
+ statics[key] = value;
467
+ continue;
468
+ }
469
+ if (key === "transform" && Array.isArray(value)) {
470
+ for (const t of value) {
471
+ if (t && typeof t === "object") {
472
+ const tKey = Object.keys(t)[0];
473
+ const tVal = t[tKey];
474
+ if (typeof tVal === "number" || typeof tVal === "string") {
475
+ transforms.push(t);
476
+ }
363
477
  }
364
- continue;
365
478
  }
366
- canAnimateProperty(key, value, animateOnly) ? animated[key] = value : statics[key] = value;
479
+ continue;
480
+ }
481
+ if (canAnimateProperty(key, value, animateOnly)) {
482
+ animated[key] = value;
483
+ } else {
484
+ statics[key] = value;
367
485
  }
368
486
  }
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
- });
487
+ animatedTargetsRef.set(animated);
488
+ staticTargetsRef.set(statics);
489
+ transformTargetsRef.set(transforms);
490
+ if (process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile") {
491
+ console.info("[animations-reanimated] useStyleEmitter update", {
492
+ animated,
493
+ statics,
494
+ transforms
495
+ });
496
+ }
374
497
  });
375
- const exitKeysRegistered = useRef(!1);
498
+ const exitKeysRegistered = useRef(false);
376
499
  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);
500
+ const exitKeys = [];
501
+ const animateOnly = props.animateOnly;
502
+ for (const key in animatedStyles) {
503
+ if (key === "transform") continue;
504
+ if (canAnimateProperty(key, animatedStyles[key], animateOnly)) {
505
+ exitKeys.push(key);
506
+ }
507
+ }
380
508
  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}`);
509
+ if (transforms && Array.isArray(transforms)) {
510
+ for (const t of transforms) {
511
+ if (!t) continue;
512
+ const tKey = Object.keys(t)[0];
513
+ if (tKey) {
514
+ if (animateOnly && !animateOnly.includes(tKey)) {
515
+ continue;
516
+ }
517
+ exitKeys.push(`transform:${tKey}`);
518
+ }
387
519
  }
388
520
  }
389
- pendingExitKeysRef.current = new Set(exitKeys), exitKeysRegistered.current = exitKeys.length > 0;
521
+ pendingExitKeysRef.current = new Set(exitKeys);
522
+ exitKeysRegistered.current = exitKeys.length > 0;
390
523
  }
391
524
  React.useEffect(() => {
392
- !justStartedExiting || !sendExitComplete || !exitKeysRegistered.current && pendingExitKeysRef.current.size === 0 && (exitCompletedRef.current || (exitCompletedRef.current = !0, sendExitComplete()));
525
+ if (!justStartedExiting || !sendExitComplete) return;
526
+ if (!exitKeysRegistered.current && pendingExitKeysRef.current.size === 0) {
527
+ if (!exitCompletedRef.current) {
528
+ exitCompletedRef.current = true;
529
+ sendExitComplete();
530
+ }
531
+ }
393
532
  }, [justStartedExiting, sendExitComplete]);
394
533
  const animatedStyle = useAnimatedStyle(() => {
395
534
  "worklet";
396
535
 
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];
536
+ if (disableAnimation || isHydrating) {
537
+ return {};
538
+ }
539
+ const result = {};
540
+ const config = configRef.get();
541
+ const emitterAnimated = animatedTargetsRef.value;
542
+ const emitterStatic = staticTargetsRef.value;
543
+ const emitterTransforms = transformTargetsRef.value;
544
+ const hasEmitterUpdates = emitterAnimated !== null;
545
+ const animatedValues = hasEmitterUpdates ? emitterAnimated : animatedStyles;
546
+ const staticValues = hasEmitterUpdates ? emitterStatic : {};
547
+ const currentlyExiting = isExitingRef.value;
548
+ const currentCycleId = exitCycleIdShared.value;
549
+ for (const key in staticValues) {
550
+ result[key] = staticValues[key];
551
+ }
409
552
  for (const key in animatedValues) {
410
553
  if (key === "transform") continue;
411
- const targetValue = animatedValues[key],
412
- propConfig = config.propertyConfigs[key] ?? config.baseConfig;
554
+ const targetValue = animatedValues[key];
555
+ const propConfig = config.propertyConfigs[key] ?? config.baseConfig;
413
556
  let callback;
414
557
  if (currentlyExiting) {
415
- const capturedKey = key,
416
- capturedCycleId = currentCycleId;
558
+ const capturedKey = key;
559
+ const capturedCycleId = currentCycleId;
417
560
  callback = finished => {
418
561
  "worklet";
419
562
 
420
- runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? !1);
563
+ runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? false);
421
564
  };
422
565
  }
423
566
  result[key] = applyAnimation(targetValue, propConfig, callback);
@@ -430,18 +573,18 @@ function createAnimations(animationsConfig) {
430
573
  const keys = Object.keys(t);
431
574
  if (keys.length === 0) continue;
432
575
  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;
576
+ if (typeof value === "number" || typeof value === "string") {
577
+ const transformKey = Object.keys(t)[0];
578
+ const targetValue = t[transformKey];
579
+ const propConfig = config.propertyConfigs[transformKey] ?? config.baseConfig;
437
580
  let callback;
438
581
  if (currentlyExiting) {
439
- const capturedKey = `transform:${transformKey}`,
440
- capturedCycleId = currentCycleId;
582
+ const capturedKey = `transform:${transformKey}`;
583
+ const capturedCycleId = currentCycleId;
441
584
  callback = finished => {
442
585
  "worklet";
443
586
 
444
- runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? !1);
587
+ runOnJS(markExitKeyDone)(capturedKey, capturedCycleId, finished ?? false);
445
588
  };
446
589
  }
447
590
  validTransforms.push({
@@ -449,21 +592,26 @@ function createAnimations(animationsConfig) {
449
592
  });
450
593
  }
451
594
  }
452
- validTransforms.length > 0 && (result.transform = validTransforms);
595
+ if (validTransforms.length > 0) {
596
+ result.transform = validTransforms;
597
+ }
453
598
  }
454
599
  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
- }), {
600
+ }, isWeb ? [animatedStyles, baseConfig, propertyConfigs, disableAnimation, isHydrating,
601
+ // pass SharedValues so the mapper watches them on web (no babel plugin)
602
+ animatedTargetsRef, staticTargetsRef, transformTargetsRef, isExitingRef, exitCycleIdShared, markExitKeyDone] : void 0);
603
+ if (process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile") {
604
+ console.info("[animations-reanimated] useAnimations", {
605
+ animationKey,
606
+ componentState,
607
+ isExiting,
608
+ animatedStyles,
609
+ staticStyles,
610
+ baseConfig,
611
+ propertyConfigs
612
+ });
613
+ }
614
+ return {
467
615
  style: [staticStyles, animatedStyle]
468
616
  };
469
617
  }