@tamagui/animations-reanimated 2.4.5 → 2.5.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.
@@ -42,6 +42,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
42
42
  var import_animation_helpers = require("@tamagui/animation-helpers");
43
43
  var import_core = require("@tamagui/core");
44
44
  var import_use_presence = require("@tamagui/use-presence");
45
+ var import_normalize_colors = __toESM(require("@react-native/normalize-colors"), 1);
45
46
  var import_react = __toESM(require("react"), 1);
46
47
  var import_react_native_reanimated = __toESM(require("react-native-reanimated"), 1);
47
48
  function _type_of(obj) {
@@ -87,9 +88,284 @@ var cloneAnimationValue = function (value) {
87
88
  }
88
89
  return value;
89
90
  };
91
+ var cloneStyleRecord = function (style) {
92
+ var next = {};
93
+ for (var key in style) {
94
+ next[key] = cloneAnimationValue(style[key]);
95
+ }
96
+ return next;
97
+ };
90
98
  var cloneTransitionConfig = function (config) {
91
99
  return cloneAnimationValue(config);
92
100
  };
101
+ var getAnimatedTransforms = function (value) {
102
+ if (!Array.isArray(value)) return [];
103
+ return value.filter(function (item) {
104
+ return item !== null && (typeof item === "undefined" ? "undefined" : _type_of(item)) === "object" && !Array.isArray(item);
105
+ });
106
+ };
107
+ var getRemovedAnimatedKeys = function (current, previous) {
108
+ var removedKeys = {};
109
+ var _iteratorNormalCompletion = true,
110
+ _didIteratorError = false,
111
+ _iteratorError = void 0;
112
+ try {
113
+ for (var _iterator = previous[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
114
+ var key = _step.value;
115
+ if (!current.has(key)) removedKeys[key] = true;
116
+ }
117
+ } catch (err) {
118
+ _didIteratorError = true;
119
+ _iteratorError = err;
120
+ } finally {
121
+ try {
122
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
123
+ _iterator.return();
124
+ }
125
+ } finally {
126
+ if (_didIteratorError) {
127
+ throw _iteratorError;
128
+ }
129
+ }
130
+ }
131
+ return removedKeys;
132
+ };
133
+ var getImplicitDefault = function (key, targetValue) {
134
+ "worklet";
135
+
136
+ var value = key === "opacity" || key === "scale" || key === "scaleX" || key === "scaleY" ? 1 : 0;
137
+ if (typeof targetValue !== "string") return value;
138
+ var suffixIndex = 0;
139
+ while (suffixIndex < targetValue.length) {
140
+ var character = targetValue[suffixIndex];
141
+ var code = character.charCodeAt(0);
142
+ if (code >= 48 && code <= 57 || character === "." || character === "-" || character === "+") {
143
+ suffixIndex++;
144
+ } else {
145
+ break;
146
+ }
147
+ }
148
+ return suffixIndex > 0 ? `${value}${targetValue.slice(suffixIndex)}` : value;
149
+ };
150
+ var COLOR_STYLE_KEYS = {
151
+ backgroundColor: true,
152
+ borderColor: true,
153
+ borderLeftColor: true,
154
+ borderRightColor: true,
155
+ borderTopColor: true,
156
+ borderBottomColor: true,
157
+ color: true
158
+ };
159
+ var toReanimatedColor = function (value) {
160
+ "worklet";
161
+
162
+ if (typeof value === "number") {
163
+ var color = value >>> 0;
164
+ var alpha = (color >>> 24 & 255) / 255;
165
+ var red = color >>> 16 & 255;
166
+ var green = color >>> 8 & 255;
167
+ var blue = color & 255;
168
+ return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
169
+ }
170
+ if (typeof value !== "string") return value;
171
+ var trimmed = value.trim();
172
+ if (trimmed === "transparent") return "rgba(0, 0, 0, 0)";
173
+ return trimmed;
174
+ };
175
+ var isReanimatedColorHistory = function (value) {
176
+ "worklet";
177
+
178
+ var normalized = toReanimatedColor(value);
179
+ return typeof normalized === "string" && normalized.startsWith("rgba(");
180
+ };
181
+ var normalizeAnimationColor = function (value) {
182
+ if (typeof value === "number") {
183
+ return toReanimatedColor(value);
184
+ }
185
+ if (typeof value !== "string") return;
186
+ var color = (0, import_normalize_colors.default)(value);
187
+ if (color == null) return;
188
+ var red = Math.round((color & 4278190080) >>> 24);
189
+ var green = Math.round((color & 16711680) >>> 16);
190
+ var blue = Math.round((color & 65280) >>> 8);
191
+ var alpha = (color & 255) / 255;
192
+ return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
193
+ };
194
+ var buildSnapshot = function (animated, statics, transforms, previousKeys, lastPainted) {
195
+ var snapshotAnimated = {};
196
+ var snapshotStatics = cloneStyleRecord(statics);
197
+ for (var key in snapshotStatics) {
198
+ if (!COLOR_STYLE_KEYS[key]) continue;
199
+ var normalized = normalizeAnimationColor(snapshotStatics[key]);
200
+ if (normalized !== void 0) snapshotStatics[key] = normalized;
201
+ }
202
+ for (var key1 in animated) {
203
+ if (key1 === "transform") continue;
204
+ var value = animated[key1];
205
+ if (COLOR_STYLE_KEYS[key1]) {
206
+ var normalized1 = normalizeAnimationColor(value);
207
+ if (normalized1 === void 0) {
208
+ snapshotStatics[key1] = cloneAnimationValue(value);
209
+ continue;
210
+ }
211
+ snapshotAnimated[key1] = normalized1;
212
+ } else {
213
+ snapshotAnimated[key1] = cloneAnimationValue(value);
214
+ }
215
+ }
216
+ var snapshotTransforms = transforms.map(cloneStyleRecord);
217
+ var keys = new Set(Object.keys(snapshotAnimated));
218
+ var _iteratorNormalCompletion = true,
219
+ _didIteratorError = false,
220
+ _iteratorError = void 0;
221
+ try {
222
+ for (var _iterator = snapshotTransforms[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
223
+ var transform = _step.value;
224
+ var key2 = Object.keys(transform)[0];
225
+ var value1 = key2 ? transform[key2] : void 0;
226
+ if (key2 && (typeof value1 === "number" || typeof value1 === "string")) {
227
+ keys.add(`transform:${key2}`);
228
+ }
229
+ }
230
+ } catch (err) {
231
+ _didIteratorError = true;
232
+ _iteratorError = err;
233
+ } finally {
234
+ try {
235
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
236
+ _iterator.return();
237
+ }
238
+ } finally {
239
+ if (_didIteratorError) {
240
+ throw _iteratorError;
241
+ }
242
+ }
243
+ }
244
+ var seeds = {};
245
+ var _iteratorNormalCompletion1 = true,
246
+ _didIteratorError1 = false,
247
+ _iteratorError1 = void 0;
248
+ try {
249
+ for (var _iterator1 = keys[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
250
+ var key3 = _step1.value;
251
+ var value2 = lastPainted[key3];
252
+ if (typeof value2 !== "number" && typeof value2 !== "string") continue;
253
+ if (value2 === "auto" || typeof value2 === "string" && value2.startsWith("calc")) {
254
+ continue;
255
+ }
256
+ if (COLOR_STYLE_KEYS[key3]) value2 = normalizeAnimationColor(value2);
257
+ if (value2 !== void 0) seeds[key3] = value2;
258
+ }
259
+ } catch (err) {
260
+ _didIteratorError1 = true;
261
+ _iteratorError1 = err;
262
+ } finally {
263
+ try {
264
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
265
+ _iterator1.return();
266
+ }
267
+ } finally {
268
+ if (_didIteratorError1) {
269
+ throw _iteratorError1;
270
+ }
271
+ }
272
+ }
273
+ var gatedKeys = {};
274
+ var _iteratorNormalCompletion2 = true,
275
+ _didIteratorError2 = false,
276
+ _iteratorError2 = void 0;
277
+ try {
278
+ for (var _iterator2 = keys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
279
+ var key4 = _step2.value;
280
+ gatedKeys[key4] = true;
281
+ }
282
+ } catch (err) {
283
+ _didIteratorError2 = true;
284
+ _iteratorError2 = err;
285
+ } finally {
286
+ try {
287
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
288
+ _iterator2.return();
289
+ }
290
+ } finally {
291
+ if (_didIteratorError2) {
292
+ throw _iteratorError2;
293
+ }
294
+ }
295
+ }
296
+ var removedKeys = getRemovedAnimatedKeys(keys, previousKeys);
297
+ var painted = {
298
+ ...snapshotStatics,
299
+ ...snapshotAnimated
300
+ };
301
+ var staticTransforms = getAnimatedTransforms(snapshotStatics.transform);
302
+ delete painted.transform;
303
+ var _iteratorNormalCompletion3 = true,
304
+ _didIteratorError3 = false,
305
+ _iteratorError3 = void 0;
306
+ try {
307
+ for (var _iterator3 = staticTransforms[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
308
+ var transform1 = _step3.value;
309
+ var key5 = Object.keys(transform1)[0];
310
+ if (key5) painted[`transform:${key5}`] = transform1[key5];
311
+ }
312
+ } catch (err) {
313
+ _didIteratorError3 = true;
314
+ _iteratorError3 = err;
315
+ } finally {
316
+ try {
317
+ if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
318
+ _iterator3.return();
319
+ }
320
+ } finally {
321
+ if (_didIteratorError3) {
322
+ throw _iteratorError3;
323
+ }
324
+ }
325
+ }
326
+ var _iteratorNormalCompletion4 = true,
327
+ _didIteratorError4 = false,
328
+ _iteratorError4 = void 0;
329
+ try {
330
+ for (var _iterator4 = snapshotTransforms[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
331
+ var transform2 = _step4.value;
332
+ var key6 = Object.keys(transform2)[0];
333
+ if (key6) painted[`transform:${key6}`] = transform2[key6];
334
+ }
335
+ } catch (err) {
336
+ _didIteratorError4 = true;
337
+ _iteratorError4 = err;
338
+ } finally {
339
+ try {
340
+ if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
341
+ _iterator4.return();
342
+ }
343
+ } finally {
344
+ if (_didIteratorError4) {
345
+ throw _iteratorError4;
346
+ }
347
+ }
348
+ }
349
+ return {
350
+ value: {
351
+ animated: snapshotAnimated,
352
+ statics: snapshotStatics,
353
+ transforms: snapshotTransforms,
354
+ gatedKeys,
355
+ seeds,
356
+ removedKeys,
357
+ removeTransform: Object.keys(removedKeys).some(function (key7) {
358
+ return key7.startsWith("transform:");
359
+ }),
360
+ clearValue: import_core.isWeb ? "" : null
361
+ },
362
+ painted,
363
+ keys
364
+ };
365
+ };
366
+ var getGatedKeys = function (snapshot) {
367
+ return Object.keys(snapshot.gatedKeys);
368
+ };
93
369
  var createReanimatedConfig = function (config) {
94
370
  "worklet";
95
371
 
@@ -104,9 +380,10 @@ var createReanimatedConfig = function (config) {
104
380
  }
105
381
  return next;
106
382
  };
107
- var applyAnimation = function (targetValue, config, callback) {
383
+ var applyAnimation = function (targetValue, config, callback, seedValue) {
108
384
  "worklet";
109
385
 
386
+ var validateStartAsColor = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : false;
110
387
  var delay = config.delay;
111
388
  var reanimatedConfig = createReanimatedConfig(config);
112
389
  var animatedValue;
@@ -115,11 +392,44 @@ var applyAnimation = function (targetValue, config, callback) {
115
392
  } else {
116
393
  animatedValue = (0, import_react_native_reanimated.withSpring)(targetValue, reanimatedConfig, callback);
117
394
  }
395
+ if (seedValue !== void 0 || validateStartAsColor) {
396
+ var innerOnStart = animatedValue.onStart;
397
+ animatedValue.onStart = function (animation, value, timestamp, previousAnimation) {
398
+ "worklet";
399
+
400
+ var startValue = validateStartAsColor ? isReanimatedColorHistory(value) ? toReanimatedColor(value) : seedValue !== null && seedValue !== void 0 ? seedValue : targetValue : seedValue;
401
+ innerOnStart(animation, startValue, timestamp, previousAnimation);
402
+ };
403
+ }
118
404
  if (delay && delay > 0) {
119
405
  animatedValue = (0, import_react_native_reanimated.withDelay)(delay, animatedValue);
120
406
  }
121
407
  return animatedValue;
122
408
  };
409
+ var animateSnapshotValue = function (key, implicitKey, targetValue, config, previouslyEmitted, seedValue, gated, currentlyExiting, exitCycleId, currentlyCompletingAnimation, didAnimateCycleId, markExitKeyDone, markDidAnimateKeyDone) {
410
+ "worklet";
411
+
412
+ var validateStartAsColor = arguments.length > 13 && arguments[13] !== void 0 ? arguments[13] : false;
413
+ var cycleGated = gated && (currentlyExiting || currentlyCompletingAnimation);
414
+ if (!previouslyEmitted && seedValue === void 0 && !cycleGated) {
415
+ return targetValue;
416
+ }
417
+ var callback;
418
+ if (gated && currentlyExiting) {
419
+ callback = function (finished) {
420
+ "worklet";
421
+
422
+ (0, import_react_native_reanimated.runOnJS)(markExitKeyDone)(key, exitCycleId, finished !== null && finished !== void 0 ? finished : false);
423
+ };
424
+ } else if (gated && currentlyCompletingAnimation) {
425
+ callback = function (finished) {
426
+ "worklet";
427
+
428
+ (0, import_react_native_reanimated.runOnJS)(markDidAnimateKeyDone)(key, didAnimateCycleId, finished !== null && finished !== void 0 ? finished : false);
429
+ };
430
+ }
431
+ return applyAnimation(targetValue, config, callback, previouslyEmitted ? void 0 : seedValue !== null && seedValue !== void 0 ? seedValue : getImplicitDefault(implicitKey, targetValue), validateStartAsColor);
432
+ };
123
433
  var ANIMATABLE_PROPERTIES = {
124
434
  // Transform
125
435
  transform: true,
@@ -194,6 +504,23 @@ var canAnimateProperty = function (key, value, animateOnly) {
194
504
  if (animateOnly && !animateOnly.includes(key)) return false;
195
505
  return true;
196
506
  };
507
+ var splitAnimationStyles = function (style, isDark, disableAnimation, animateOnly) {
508
+ var animated = {};
509
+ var statics = {};
510
+ for (var key in style) {
511
+ var value = resolveDynamicValue(style[key], isDark);
512
+ if (value === void 0) continue;
513
+ if (!disableAnimation && canAnimateProperty(key, value, animateOnly)) {
514
+ animated[key] = cloneAnimationValue(value);
515
+ } else {
516
+ statics[key] = cloneAnimationValue(value);
517
+ }
518
+ }
519
+ return {
520
+ animated,
521
+ statics
522
+ };
523
+ };
197
524
  function createWebAnimatedComponent(defaultTag) {
198
525
  var isText = defaultTag === "span";
199
526
  var Component = Animated.createAnimatedComponent(/* @__PURE__ */(0, import_react.forwardRef)(function (propsIn, ref) {
@@ -469,7 +796,8 @@ function createAnimations(animationsConfig) {
469
796
  useStyleEmitter,
470
797
  themeName,
471
798
  stateRef,
472
- styleState
799
+ styleState,
800
+ onDidAnimate
473
801
  } = animationProps;
474
802
  var isHydrating = componentState.unmounted === true;
475
803
  var isMounting = componentState.unmounted === "should-enter";
@@ -488,16 +816,36 @@ function createAnimations(animationsConfig) {
488
816
  var disableAnimation = isHydrating || !animationKey;
489
817
  var isDark = (themeName === null || themeName === void 0 ? void 0 : themeName.startsWith("dark")) || false;
490
818
  var sendExitComplete = presence === null || presence === void 0 ? void 0 : presence[1];
819
+ var onDidAnimateRef = (0, import_react.useRef)(onDidAnimate);
820
+ (0, import_core.useIsomorphicLayoutEffect)(function () {
821
+ onDidAnimateRef.current = onDidAnimate;
822
+ }, [onDidAnimate]);
823
+ var didAnimateCycleIdRef = (0, import_react.useRef)(0);
824
+ var pendingDidAnimateKeysRef = (0, import_react.useRef)(/* @__PURE__ */new Set());
825
+ var didAnimateCompletedRef = (0, import_react.useRef)(false);
826
+ var isCompletingAnimationRef = (0, import_react_native_reanimated.useSharedValue)(false);
827
+ var didAnimateCycleIdShared = (0, import_react_native_reanimated.useSharedValue)(0);
828
+ var markDidAnimateKeyDone = (0, import_core.useEvent)(function (key2, cycleId, finished) {
829
+ if (!finished || cycleId !== didAnimateCycleIdRef.current) return;
830
+ if (didAnimateCompletedRef.current) return;
831
+ pendingDidAnimateKeysRef.current.delete(key2);
832
+ if (pendingDidAnimateKeysRef.current.size === 0) {
833
+ var _onDidAnimateRef_current;
834
+ didAnimateCompletedRef.current = true;
835
+ isCompletingAnimationRef.value = false;
836
+ (_onDidAnimateRef_current = onDidAnimateRef.current) === null || _onDidAnimateRef_current === void 0 ? void 0 : _onDidAnimateRef_current.call(onDidAnimateRef);
837
+ }
838
+ });
491
839
  var exitCycleIdRef = (0, import_react.useRef)(0);
492
840
  var pendingExitKeysRef = (0, import_react.useRef)(/* @__PURE__ */new Set());
493
841
  var exitCompletedRef = (0, import_react.useRef)(false);
494
842
  var wasExitingRef = (0, import_react.useRef)(false);
495
843
  var justStartedExiting = isExiting && !wasExitingRef.current;
496
844
  var justStoppedExiting = !isExiting && wasExitingRef.current;
497
- var markExitKeyDone = (0, import_core.useEvent)(function (key3, cycleId, finished) {
845
+ var markExitKeyDone = (0, import_core.useEvent)(function (key2, cycleId, finished) {
498
846
  if (cycleId !== exitCycleIdRef.current) return;
499
847
  if (exitCompletedRef.current) return;
500
- pendingExitKeysRef.current.delete(key3);
848
+ pendingExitKeysRef.current.delete(key2);
501
849
  if (pendingExitKeysRef.current.size === 0) {
502
850
  exitCompletedRef.current = true;
503
851
  sendExitComplete === null || sendExitComplete === void 0 ? void 0 : sendExitComplete();
@@ -509,6 +857,9 @@ function createAnimations(animationsConfig) {
509
857
  exitCycleIdRef.current++;
510
858
  exitCompletedRef.current = false;
511
859
  pendingExitKeysRef.current.clear();
860
+ didAnimateCycleIdRef.current++;
861
+ pendingDidAnimateKeysRef.current.clear();
862
+ didAnimateCompletedRef.current = true;
512
863
  }
513
864
  if (justStoppedExiting) {
514
865
  exitCycleIdRef.current++;
@@ -517,52 +868,87 @@ function createAnimations(animationsConfig) {
517
868
  (0, import_core.useIsomorphicLayoutEffect)(function () {
518
869
  isExitingRef.value = isExiting;
519
870
  exitCycleIdShared.value = exitCycleIdRef.current;
520
- }, [isExiting, exitCycleIdRef.current]);
871
+ if (justStartedExiting) {
872
+ isCompletingAnimationRef.value = false;
873
+ didAnimateCycleIdShared.value = didAnimateCycleIdRef.current;
874
+ }
875
+ }, [isExiting, exitCycleIdRef.current, justStartedExiting]);
521
876
  import_react.default.useEffect(function () {
522
877
  wasExitingRef.current = isExiting;
523
878
  });
524
- var animatedTargetsRef = (0, import_react_native_reanimated.useSharedValue)(null);
525
- var staticTargetsRef = (0, import_react_native_reanimated.useSharedValue)(null);
526
- var transformTargetsRef = (0, import_react_native_reanimated.useSharedValue)(null);
879
+ var committedRenderKeysRef = (0, import_react.useRef)(/* @__PURE__ */new Set());
880
+ var lastPaintedRef = (0, import_react.useRef)({});
881
+ var carryRef = (0, import_react.useRef)({});
527
882
  var {
528
883
  animatedStyles,
529
- staticStyles
884
+ staticStyles,
885
+ nextCarry
530
886
  } = (0, import_react.useMemo)(function () {
531
- var animated = {};
532
- var staticStyles2 = {};
533
- var animateOnly2 = props.animateOnly;
534
- for (var key3 in style) {
535
- var rawValue = style[key3];
536
- var value = resolveDynamicValue(rawValue, isDark);
537
- if (value === void 0) continue;
538
- if (disableAnimation) {
539
- staticStyles2[key3] = cloneAnimationValue(value);
540
- continue;
541
- }
542
- if (canAnimateProperty(key3, value, animateOnly2)) {
543
- animated[key3] = cloneAnimationValue(value);
544
- } else {
545
- staticStyles2[key3] = cloneAnimationValue(value);
546
- }
887
+ var animateOnly = props.animateOnly;
888
+ var {
889
+ animated,
890
+ statics
891
+ } = splitAnimationStyles(style, isDark, disableAnimation, animateOnly);
892
+ var nextCarry2 = cloneStyleRecord(carryRef.current);
893
+ for (var key2 in nextCarry2) {
894
+ if (!(key2 in animated)) delete nextCarry2[key2];
547
895
  }
548
- if (isMounting) {
549
- for (var key1 in animated) {
550
- staticStyles2[key1] = animated[key1];
896
+ for (var key1 in animated) {
897
+ if (!(key1 in nextCarry2)) {
898
+ nextCarry2[key1] = cloneAnimationValue(animated[key1]);
551
899
  }
900
+ statics[key1] = nextCarry2[key1];
552
901
  }
553
902
  return {
554
903
  animatedStyles: animated,
555
- staticStyles: staticStyles2
904
+ staticStyles: statics,
905
+ nextCarry: nextCarry2
556
906
  };
557
- }, [disableAnimation, style, isDark, isMounting, props.animateOnly]);
907
+ }, [disableAnimation, style, isDark, props.animateOnly]);
908
+ var renderSnapshot = (0, import_react.useMemo)(function () {
909
+ return buildSnapshot(animatedStyles, staticStyles, getAnimatedTransforms(animatedStyles.transform), committedRenderKeysRef.current, lastPaintedRef.current);
910
+ }, [animatedStyles, staticStyles]);
911
+ var renderSnapshotRef = (0, import_react_native_reanimated.useSharedValue)({
912
+ animated: {},
913
+ statics: {},
914
+ transforms: [],
915
+ gatedKeys: {},
916
+ seeds: {},
917
+ removedKeys: {},
918
+ removeTransform: false,
919
+ clearValue: import_core.isWeb ? "" : null
920
+ });
921
+ var emitterSnapshotRef = (0, import_react_native_reanimated.useSharedValue)(null);
922
+ var emitterKeysRef = (0, import_react.useRef)(null);
923
+ (0, import_core.useIsomorphicLayoutEffect)(function () {
924
+ carryRef.current = nextCarry;
925
+ committedRenderKeysRef.current = renderSnapshot.keys;
926
+ lastPaintedRef.current = renderSnapshot.painted;
927
+ }, [nextCarry, renderSnapshot]);
558
928
  var pseudoActiveRef = (0, import_react.useRef)(false);
559
929
  var isExitingJSRef = (0, import_react.useRef)(false);
560
930
  isExitingJSRef.current = isExiting;
931
+ var publishedSnapshotRef = (0, import_react.useRef)(null);
561
932
  (0, import_core.useIsomorphicLayoutEffect)(function () {
562
- if ((isExiting || !pseudoActiveRef.current) && animatedTargetsRef.value !== null) {
563
- animatedTargetsRef.value = null;
564
- staticTargetsRef.value = null;
565
- transformTargetsRef.value = null;
933
+ var droppingLatch = (isExiting || !pseudoActiveRef.current) && emitterSnapshotRef.value !== null;
934
+ var emitterKeys = droppingLatch ? emitterKeysRef.current : null;
935
+ if (droppingLatch || publishedSnapshotRef.current !== renderSnapshot.value) {
936
+ var removedKeys = emitterKeys ? {
937
+ ...renderSnapshot.value.removedKeys,
938
+ ...getRemovedAnimatedKeys(renderSnapshot.keys, emitterKeys)
939
+ } : renderSnapshot.value.removedKeys;
940
+ renderSnapshotRef.value = {
941
+ ...renderSnapshot.value,
942
+ removedKeys,
943
+ removeTransform: Object.keys(removedKeys).some(function (key2) {
944
+ return key2.startsWith("transform:");
945
+ })
946
+ };
947
+ publishedSnapshotRef.current = renderSnapshot.value;
948
+ }
949
+ if (droppingLatch) {
950
+ emitterSnapshotRef.value = null;
951
+ emitterKeysRef.current = null;
566
952
  }
567
953
  });
568
954
  var {
@@ -597,10 +983,7 @@ function createAnimations(animationsConfig) {
597
983
  useStyleEmitter === null || useStyleEmitter === void 0 ? void 0 : useStyleEmitter(function (nextStyle, effectiveTransition2, pseudoActive) {
598
984
  if (isExitingJSRef.current) return;
599
985
  pseudoActiveRef.current = pseudoActive === true;
600
- var animateOnly2 = props.animateOnly;
601
- var animated = {};
602
- var statics = {};
603
- var transforms2 = [];
986
+ var animateOnly = props.animateOnly;
604
987
  var transitionToUse = effectiveTransition2 !== null && effectiveTransition2 !== void 0 ? effectiveTransition2 : props.transition;
605
988
  var {
606
989
  baseConfig: newBase,
@@ -612,107 +995,54 @@ function createAnimations(animationsConfig) {
612
995
  disableAnimation: configRef.value.disableAnimation,
613
996
  isHydrating: configRef.value.isHydrating
614
997
  };
615
- for (var key3 in nextStyle) {
616
- var rawValue = nextStyle[key3];
617
- var value = resolveDynamicValue(rawValue, isDark);
618
- if (value == void 0) continue;
619
- if (configRef.value.disableAnimation) {
620
- statics[key3] = cloneAnimationValue(value);
621
- continue;
622
- }
623
- if (key3 === "transform" && Array.isArray(value)) {
624
- var _iteratorNormalCompletion2 = true,
625
- _didIteratorError2 = false,
626
- _iteratorError2 = void 0;
627
- try {
628
- for (var _iterator2 = value[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
629
- var t2 = _step2.value;
630
- if (t2 && (typeof t2 === "undefined" ? "undefined" : _type_of(t2)) === "object") {
631
- var tKey2 = Object.keys(t2)[0];
632
- var tVal = t2[tKey2];
633
- if (typeof tVal === "number" || typeof tVal === "string") {
634
- transforms2.push(cloneAnimationValue(t2));
635
- }
636
- }
637
- }
638
- } catch (err) {
639
- _didIteratorError2 = true;
640
- _iteratorError2 = err;
641
- } finally {
642
- try {
643
- if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
644
- _iterator2.return();
645
- }
646
- } finally {
647
- if (_didIteratorError2) {
648
- throw _iteratorError2;
649
- }
650
- }
651
- }
652
- continue;
653
- }
654
- if (canAnimateProperty(key3, value, animateOnly2)) {
655
- animated[key3] = cloneAnimationValue(value);
656
- } else {
657
- statics[key3] = cloneAnimationValue(value);
658
- }
659
- }
660
- animatedTargetsRef.value = animated;
661
- staticTargetsRef.value = statics;
662
- transformTargetsRef.value = transforms2;
998
+ var _emitterKeysRef_current;
999
+ var previousKeys = (_emitterKeysRef_current = emitterKeysRef.current) !== null && _emitterKeysRef_current !== void 0 ? _emitterKeysRef_current : committedRenderKeysRef.current;
1000
+ var {
1001
+ animated,
1002
+ statics
1003
+ } = splitAnimationStyles(nextStyle, isDark, configRef.value.disableAnimation, animateOnly);
1004
+ var snapshot = buildSnapshot(animated, statics, getAnimatedTransforms(animated.transform), previousKeys, lastPaintedRef.current);
1005
+ emitterSnapshotRef.value = snapshot.value;
1006
+ emitterKeysRef.current = snapshot.keys;
1007
+ lastPaintedRef.current = snapshot.painted;
663
1008
  if (process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile") {
664
1009
  console.info("[animations-reanimated] useStyleEmitter update", {
665
1010
  animated,
666
1011
  statics,
667
- transforms: transforms2
1012
+ transforms: snapshot.value.transforms
668
1013
  });
669
1014
  }
670
1015
  });
671
1016
  var exitKeysRegistered = (0, import_react.useRef)(false);
672
1017
  if (justStartedExiting && sendExitComplete) {
673
- var exitKeys = [];
674
- var animateOnly = props.animateOnly;
675
- for (var key2 in animatedStyles) {
676
- if (key2 === "transform") continue;
677
- if (canAnimateProperty(key2, animatedStyles[key2], animateOnly)) {
678
- exitKeys.push(key2);
679
- }
680
- }
681
- var transforms = animatedStyles.transform;
682
- if (transforms && Array.isArray(transforms)) {
683
- var _iteratorNormalCompletion = true,
684
- _didIteratorError = false,
685
- _iteratorError = void 0;
686
- try {
687
- for (var _iterator = transforms[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
688
- var t = _step.value;
689
- if (!t) continue;
690
- var tKey = Object.keys(t)[0];
691
- if (tKey) {
692
- if (animateOnly && !animateOnly.includes(tKey)) {
693
- continue;
694
- }
695
- exitKeys.push(`transform:${tKey}`);
696
- }
697
- }
698
- } catch (err) {
699
- _didIteratorError = true;
700
- _iteratorError = err;
701
- } finally {
702
- try {
703
- if (!_iteratorNormalCompletion && _iterator.return != null) {
704
- _iterator.return();
705
- }
706
- } finally {
707
- if (_didIteratorError) {
708
- throw _iteratorError;
709
- }
710
- }
711
- }
712
- }
1018
+ var exitKeys = getGatedKeys(renderSnapshot.value);
713
1019
  pendingExitKeysRef.current = new Set(exitKeys);
714
1020
  exitKeysRegistered.current = exitKeys.length > 0;
715
1021
  }
1022
+ var previousDidAnimateStyleRef = (0, import_react.useRef)(null);
1023
+ var didAnimateStyle = onDidAnimate ? JSON.stringify(style) : null;
1024
+ var previousDidAnimateStyle = previousDidAnimateStyleRef.current;
1025
+ var shouldRegisterDidAnimate = didAnimateStyle !== null && previousDidAnimateStyle !== null && previousDidAnimateStyle !== didAnimateStyle && !isExiting && !isEntering && !justFinishedEntering;
1026
+ var didAnimateKeys = shouldRegisterDidAnimate ? getGatedKeys(renderSnapshot.value) : [];
1027
+ (0, import_core.useIsomorphicLayoutEffect)(function () {
1028
+ if (didAnimateStyle === null) {
1029
+ previousDidAnimateStyleRef.current = null;
1030
+ isCompletingAnimationRef.value = false;
1031
+ return;
1032
+ }
1033
+ var previousStyleStillCurrent = previousDidAnimateStyleRef.current === previousDidAnimateStyle;
1034
+ previousDidAnimateStyleRef.current = didAnimateStyle;
1035
+ if (!shouldRegisterDidAnimate || !previousStyleStillCurrent) return;
1036
+ var cycleId = ++didAnimateCycleIdRef.current;
1037
+ pendingDidAnimateKeysRef.current = new Set(didAnimateKeys);
1038
+ didAnimateCompletedRef.current = didAnimateKeys.length === 0;
1039
+ isCompletingAnimationRef.value = didAnimateKeys.length > 0;
1040
+ didAnimateCycleIdShared.value = cycleId;
1041
+ if (didAnimateKeys.length === 0) {
1042
+ var _onDidAnimateRef_current;
1043
+ (_onDidAnimateRef_current = onDidAnimateRef.current) === null || _onDidAnimateRef_current === void 0 ? void 0 : _onDidAnimateRef_current.call(onDidAnimateRef);
1044
+ }
1045
+ }, [didAnimateStyle, shouldRegisterDidAnimate]);
716
1046
  import_react.default.useEffect(function () {
717
1047
  if (!justStartedExiting || !sendExitComplete) return;
718
1048
  if (!exitKeysRegistered.current && pendingExitKeysRef.current.size === 0) {
@@ -722,99 +1052,97 @@ function createAnimations(animationsConfig) {
722
1052
  }
723
1053
  }
724
1054
  }, [justStartedExiting, sendExitComplete]);
1055
+ var mapperStateRef = (0, import_react_native_reanimated.useSharedValue)({
1056
+ emitted: {}
1057
+ });
725
1058
  var animatedStyle = (0, import_react_native_reanimated.useAnimatedStyle)(function () {
726
1059
  "worklet";
727
1060
 
728
- var _loop = function (key12) {
729
- if (key12 === "transform") return "continue";
730
- var targetValue = animatedValues[key12];
731
- var _config_propertyConfigs_key;
732
- var propConfig = (_config_propertyConfigs_key = config.propertyConfigs[key12]) !== null && _config_propertyConfigs_key !== void 0 ? _config_propertyConfigs_key : config.baseConfig;
733
- var callback = void 0;
734
- if (currentlyExiting) {
735
- var capturedKey = key12;
736
- var capturedCycleId = currentCycleId;
737
- callback = function (finished) {
738
- "worklet";
739
-
740
- (0, import_react_native_reanimated.runOnJS)(markExitKeyDone)(capturedKey, capturedCycleId, finished !== null && finished !== void 0 ? finished : false);
741
- };
742
- }
743
- result[key12] = applyAnimation(targetValue, propConfig, callback);
744
- };
745
- if (disableAnimation || isHydrating) {
1061
+ var mapperState = mapperStateRef.value;
1062
+ var config = configRef.value;
1063
+ if (config.disableAnimation || config.isHydrating) {
1064
+ mapperState.emitted = {};
746
1065
  return {};
747
1066
  }
1067
+ var previouslyEmitted = mapperState.emitted;
1068
+ var emitted = {};
748
1069
  var result = {};
749
- var config = configRef.value;
750
- var emitterAnimated = animatedTargetsRef.value;
751
- var emitterStatic = staticTargetsRef.value;
752
- var emitterTransforms = transformTargetsRef.value;
753
- var hasEmitterUpdates = emitterAnimated !== null;
754
- var animatedValues = hasEmitterUpdates ? emitterAnimated : animatedStyles;
755
- var staticValues = hasEmitterUpdates ? emitterStatic : staticStyles;
1070
+ var emitterSnapshot = emitterSnapshotRef.value;
1071
+ var snapshot = emitterSnapshot !== null && emitterSnapshot !== void 0 ? emitterSnapshot : renderSnapshotRef.value;
1072
+ var animatedValues = snapshot.animated;
1073
+ var staticValues = snapshot.statics;
756
1074
  var currentlyExiting = isExitingRef.value;
757
1075
  var currentCycleId = exitCycleIdShared.value;
758
- for (var key3 in staticValues) {
759
- result[key3] = staticValues[key3];
1076
+ var currentlyCompletingAnimation = isCompletingAnimationRef.value;
1077
+ var currentDidAnimateCycleId = didAnimateCycleIdShared.value;
1078
+ for (var key2 in staticValues) {
1079
+ result[key2] = staticValues[key2];
1080
+ }
1081
+ for (var key1 in snapshot.removedKeys) {
1082
+ if (!key1.startsWith("transform:") && !(key1 in staticValues)) {
1083
+ result[key1] = snapshot.clearValue;
1084
+ }
760
1085
  }
761
- for (var key1 in animatedValues) _loop(key1);
762
- var transforms2 = hasEmitterUpdates ? emitterTransforms : animatedStyles.transform;
763
- if (transforms2 && Array.isArray(transforms2)) {
1086
+ for (var key22 in animatedValues) {
1087
+ if (key22 === "transform") continue;
1088
+ var targetValue = animatedValues[key22];
1089
+ emitted[key22] = true;
1090
+ if (typeof targetValue !== "number" && typeof targetValue !== "string") {
1091
+ result[key22] = targetValue;
1092
+ continue;
1093
+ }
1094
+ var _config_propertyConfigs_key;
1095
+ result[key22] = animateSnapshotValue(key22, key22, targetValue, (_config_propertyConfigs_key = config.propertyConfigs[key22]) !== null && _config_propertyConfigs_key !== void 0 ? _config_propertyConfigs_key : config.baseConfig, !!previouslyEmitted[key22], snapshot.seeds[key22], !!snapshot.gatedKeys[key22], currentlyExiting, currentCycleId, currentlyCompletingAnimation, currentDidAnimateCycleId, markExitKeyDone, markDidAnimateKeyDone, !!COLOR_STYLE_KEYS[key22]);
1096
+ }
1097
+ var transforms = snapshot.transforms;
1098
+ if (transforms.length > 0 || snapshot.removeTransform) {
764
1099
  var validTransforms = [];
765
- var _iteratorNormalCompletion2 = true,
766
- _didIteratorError2 = false,
767
- _iteratorError2 = void 0;
1100
+ var _iteratorNormalCompletion = true,
1101
+ _didIteratorError = false,
1102
+ _iteratorError = void 0;
768
1103
  try {
769
- var _loop1 = function () {
770
- var t2 = _step2.value;
771
- if (!t2) return "continue";
772
- var keys = Object.keys(t2);
773
- if (keys.length === 0) return "continue";
774
- var value = t2[keys[0]];
1104
+ for (var _iterator = transforms[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
1105
+ var t = _step.value;
1106
+ if (!t) continue;
1107
+ var keys = Object.keys(t);
1108
+ if (keys.length === 0) continue;
1109
+ var transformKey = keys[0];
1110
+ var value = t[transformKey];
775
1111
  if (typeof value === "number" || typeof value === "string") {
776
- var transformKey = Object.keys(t2)[0];
777
- var targetValue = t2[transformKey];
778
1112
  var _config_propertyConfigs_transformKey;
779
1113
  var propConfig = (_config_propertyConfigs_transformKey = config.propertyConfigs[transformKey]) !== null && _config_propertyConfigs_transformKey !== void 0 ? _config_propertyConfigs_transformKey : config.baseConfig;
780
- var callback = void 0;
781
- if (currentlyExiting) {
782
- var capturedKey = `transform:${transformKey}`;
783
- var capturedCycleId = currentCycleId;
784
- callback = function (finished) {
785
- "worklet";
786
-
787
- (0, import_react_native_reanimated.runOnJS)(markExitKeyDone)(capturedKey, capturedCycleId, finished !== null && finished !== void 0 ? finished : false);
788
- };
789
- }
1114
+ var subKey = `transform:${transformKey}`;
1115
+ emitted[subKey] = true;
790
1116
  validTransforms.push({
791
- [transformKey]: applyAnimation(targetValue, propConfig, callback)
1117
+ [transformKey]: animateSnapshotValue(subKey, transformKey, value, propConfig, !!previouslyEmitted[subKey], snapshot.seeds[subKey], !!snapshot.gatedKeys[subKey], currentlyExiting, currentCycleId, currentlyCompletingAnimation, currentDidAnimateCycleId, markExitKeyDone, markDidAnimateKeyDone)
792
1118
  });
1119
+ } else {
1120
+ validTransforms.push(t);
793
1121
  }
794
- };
795
- for (var _iterator2 = transforms2[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) _loop1();
1122
+ }
796
1123
  } catch (err) {
797
- _didIteratorError2 = true;
798
- _iteratorError2 = err;
1124
+ _didIteratorError = true;
1125
+ _iteratorError = err;
799
1126
  } finally {
800
1127
  try {
801
- if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
802
- _iterator2.return();
1128
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1129
+ _iterator.return();
803
1130
  }
804
1131
  } finally {
805
- if (_didIteratorError2) {
806
- throw _iteratorError2;
1132
+ if (_didIteratorError) {
1133
+ throw _iteratorError;
807
1134
  }
808
1135
  }
809
1136
  }
810
- if (validTransforms.length > 0) {
1137
+ if (validTransforms.length > 0 || !("transform" in staticValues)) {
811
1138
  result.transform = validTransforms;
812
1139
  }
813
1140
  }
1141
+ mapperState.emitted = emitted;
814
1142
  return result;
815
- }, import_core.isWeb ? [animatedStyles, staticStyles, baseConfig, propertyConfigs, disableAnimation, isHydrating,
816
- // pass SharedValues so the mapper watches them on web (no babel plugin)
817
- animatedTargetsRef, staticTargetsRef, transformTargetsRef, isExitingRef, exitCycleIdShared, markExitKeyDone] : void 0);
1143
+ }, import_core.isWeb ? [
1144
+ // pass SharedValues so the stable mapper watches them on web (no babel plugin)
1145
+ renderSnapshotRef, emitterSnapshotRef, configRef, isExitingRef, exitCycleIdShared, markExitKeyDone, isCompletingAnimationRef, didAnimateCycleIdShared, markDidAnimateKeyDone] : void 0);
818
1146
  silenceAnimatedComponentDevCheck(animatedStyle);
819
1147
  if (process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile") {
820
1148
  console.info("[animations-reanimated] useAnimations", {