@tamagui/animations-motion 2.7.6 → 3.0.0-beta.637.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,797 +1,940 @@
1
1
  import { getEffectiveAnimation, normalizeTransition } from "@tamagui/animation-helpers";
2
2
  import { ResetPresence, usePresence } from "@tamagui/use-presence";
3
- import { fixStyles, getConfig, getSplitStyles, hooks, styleToCSS, Text, useComposedRefs, useIsomorphicLayoutEffect, useThemeWithState, View } from "@tamagui/web";
4
- import { animate as animateMotionValue, motionValue, useAnimate, useMotionValue, useMotionValueEvent } from "motion/react";
5
- import React, { forwardRef, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { Text, View, createRefComponent, fixStyles, getConfig, getSplitStyles, hooks, normalizeValueWithProperty, styleToCSS, transformsToString, useComposedRefs, useIsomorphicLayoutEffect, useThemeWithState } from "@tamagui/web";
4
+ import { animate, motionValue, useAnimate, useMotionValue, useMotionValueEvent } from "motion/react";
5
+ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
+
7
8
  const isServer = typeof window === "undefined";
8
9
  function useAnimateSSRSafe() {
9
- if (isServer) {
10
- return [useRef(null), () => {}];
11
- }
12
- return useAnimate();
10
+ if (isServer) {
11
+ return [useRef(null), (() => {})];
12
+ }
13
+ return useAnimate();
13
14
  }
14
- const MotionValueStrategy = /* @__PURE__ */new WeakMap();
15
- const PendingMotionOnFinish = /* @__PURE__ */new WeakMap();
15
+ const asStyleRecord = (style) => style && typeof style === "object" && !Array.isArray(style) ? style : {};
16
+ function assignInlineStyles(node, styles) {
17
+ for (const key in styles) {
18
+ node.style[key] = normalizeValueWithProperty(styles[key], key);
19
+ }
20
+ }
21
+ const MotionValueStrategy = /* @__PURE__ */ new WeakMap();
22
+ const PendingMotionOnFinish = /* @__PURE__ */ new WeakMap();
16
23
  function settlePendingMotionOnFinish(mv, controls) {
17
- const onFinish = PendingMotionOnFinish.get(mv);
18
- if (!onFinish) return;
19
- PendingMotionOnFinish.delete(mv);
20
- controls.then(() => onFinish()).catch(() => onFinish());
24
+ const onFinish = PendingMotionOnFinish.get(mv);
25
+ if (!onFinish) return;
26
+ PendingMotionOnFinish.delete(mv);
27
+ controls.then(() => onFinish()).catch(() => onFinish());
21
28
  }
22
- const PopperPositionAnims = /* @__PURE__ */new WeakMap();
29
+ const PopperPositionAnims = /* @__PURE__ */ new WeakMap();
23
30
  function parseTranslate(transform) {
24
- if (!transform || transform === "none") return {
25
- x: 0,
26
- y: 0
27
- };
28
- try {
29
- const m = new DOMMatrixReadOnly(transform);
30
- if (!m.is2D || m.a !== 1 || m.b !== 0 || m.c !== 0 || m.d !== 1) return null;
31
- return {
32
- x: m.e,
33
- y: m.f
34
- };
35
- } catch {
36
- return null;
37
- }
31
+ if (!transform || transform === "none") return {
32
+ x: 0,
33
+ y: 0
34
+ };
35
+ try {
36
+ const m = new DOMMatrixReadOnly(transform);
37
+ if (!m.is2D || m.a !== 1 || m.b !== 0 || m.c !== 0 || m.d !== 1) return null;
38
+ return {
39
+ x: m.e,
40
+ y: m.f
41
+ };
42
+ } catch {
43
+ return null;
44
+ }
38
45
  }
39
46
  function createAnimations(animations) {
40
- let isHydratingGlobal;
41
- const hydratingComponents = /* @__PURE__ */new Set();
42
- return {
43
- View: MotionView,
44
- Text: MotionText,
45
- isReactNative: false,
46
- inputStyle: "css",
47
- outputStyle: "inline",
48
- avoidReRenders: true,
49
- animations,
50
- usePresence,
51
- ResetPresence,
52
- onMount() {
53
- isHydratingGlobal = false;
54
- hydratingComponents.forEach(cb => cb());
55
- },
56
- useAnimations: animationProps => {
57
- if (isHydratingGlobal === void 0 && !getConfig().settings.disableSSR) {
58
- isHydratingGlobal = true;
59
- }
60
- const {
61
- props,
62
- style,
63
- componentState,
64
- stateRef,
65
- useStyleEmitter,
66
- presence,
67
- styleProps
68
- } = animationProps;
69
- const animationKey = Array.isArray(props.transition) ? props.transition[0] : props.transition;
70
- const isComponentHydrating = componentState.unmounted === true;
71
- const isMounting = componentState.unmounted === "should-enter";
72
- const isEntering = !!componentState.unmounted;
73
- const isExiting = presence?.[0] === false;
74
- const sendExitComplete = presence?.[1];
75
- const refs = useRef(null);
76
- if (!refs.current) {
77
- refs.current = {
78
- isFirstRender: true,
79
- lastDoAnimate: null,
80
- lastDontAnimate: null,
81
- controls: null,
82
- lastAnimateAt: 0,
83
- disposed: false,
84
- wasExiting: false,
85
- isExiting: false,
86
- sendExitComplete: void 0,
87
- animationState: "default",
88
- frozenExitTarget: null,
89
- exitCompleteScheduled: false,
90
- wasEntering: false,
91
- wasDisabled: false,
92
- wasNoClass: !!styleProps.noClass
93
- };
94
- }
95
- const justFinishedEntering = refs.current.wasEntering && !isEntering;
96
- useEffect(() => {
97
- refs.current.wasEntering = isEntering;
98
- });
99
- const animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default";
100
- const disableAnimation = isComponentHydrating || isMounting || !animationKey;
101
- const [scope, animate] = useAnimateSSRSafe();
102
- refs.current.isExiting = isExiting;
103
- refs.current.sendExitComplete = sendExitComplete;
104
- refs.current.animationState = animationState;
105
- const justStartedExiting = isExiting && !refs.current.wasExiting;
106
- const justStoppedExiting = !isExiting && refs.current.wasExiting;
107
- if (justStartedExiting || justStoppedExiting) {
108
- refs.current.frozenExitTarget = null;
109
- refs.current.exitCompleteScheduled = false;
110
- }
111
- useEffect(() => {
112
- refs.current.wasExiting = isExiting;
113
- });
114
- const {
115
- dontAnimate = {},
116
- doAnimate,
117
- animationOptions
118
- } = getMotionAnimatedProps(props, style, disableAnimation, animationState);
119
- const [firstRenderStyle] = useState(style);
120
- if (refs.current.isFirstRender) {
121
- refs.current.lastDontAnimate = firstRenderStyle;
122
- }
123
- const [isHydrating, setIsHydrating] = useState(isHydratingGlobal);
124
- useLayoutEffect(() => {
125
- if (isHydratingGlobal) {
126
- hydratingComponents.add(() => {
127
- setIsHydrating(false);
128
- });
129
- }
130
- return () => {
131
- refs.current.disposed = true;
132
- };
133
- }, []);
134
- const flushAnimation = ({
135
- doAnimate: doAnimateRaw = {},
136
- animationOptions: passedOptions = {},
137
- dontAnimate: dontAnimate2
138
- }) => {
139
- let startedControls = null;
140
- const isCurrentlyExiting = refs.current.isExiting;
141
- const currentSendExitComplete = refs.current.sendExitComplete;
142
- let doAnimate2 = doAnimateRaw;
143
- if (isCurrentlyExiting && refs.current.frozenExitTarget) {
144
- doAnimate2 = refs.current.frozenExitTarget;
145
- }
146
- const animationOptions2 = isCurrentlyExiting && currentSendExitComplete ? getAnimationOptions(props.transition ?? null, "exit") : passedOptions;
147
- try {
148
- const node = stateRef.current.host;
149
- if (refs.current.isFirstRender) {
150
- refs.current.lastDontAnimate = null;
151
- refs.current.lastDoAnimate = null;
152
- }
153
- if (process.env.NODE_ENV === "development") {
154
- if (props["debug"] && props["debug"] !== "profile") {
155
- console.groupCollapsed(`[motion] animate (${JSON.stringify(getDiff(refs.current.lastDoAnimate, doAnimate2), null, 2)})`);
156
- console.info({
157
- props,
158
- componentState,
159
- doAnimate: doAnimate2,
160
- dontAnimate: dontAnimate2,
161
- animationOptions: animationOptions2,
162
- animationProps,
163
- lastDoAnimate: {
164
- ...refs.current.lastDoAnimate
165
- },
166
- lastDontAnimate: {
167
- ...refs.current.lastDontAnimate
168
- },
169
- isExiting,
170
- style,
171
- node
172
- });
173
- console.groupCollapsed(`trace >`);
174
- console.trace();
175
- console.groupEnd();
176
- console.groupEnd();
177
- }
178
- }
179
- if (!(node instanceof HTMLElement)) {
180
- return;
181
- }
182
- const prevDont = refs.current.lastDontAnimate;
183
- if (dontAnimate2) {
184
- if (prevDont) {
185
- removeRemovedStyles(prevDont, dontAnimate2, node, doAnimate2);
186
- const changed = getDiff(prevDont, dontAnimate2);
187
- if (changed) {
188
- Object.assign(node.style, changed);
189
- }
190
- } else {
191
- Object.assign(node.style, dontAnimate2);
192
- }
193
- }
194
- if (doAnimate2) {
195
- if (prevDont) {
196
- for (const key in prevDont) {
197
- if (key in doAnimate2) {
198
- node.style[key] = prevDont[key];
199
- if (refs.current.lastDoAnimate) {
200
- refs.current.lastDoAnimate[key] = prevDont[key];
201
- }
202
- }
203
- }
204
- }
205
- const lastAnimated = refs.current.lastDoAnimate;
206
- if (lastAnimated) {
207
- removeRemovedStyles(lastAnimated, doAnimate2, node, dontAnimate2);
208
- }
209
- const diff = getDiff(refs.current.lastDoAnimate, doAnimate2);
210
- if (diff) {
211
- if (isCurrentlyExiting && !refs.current.frozenExitTarget) {
212
- refs.current.frozenExitTarget = {
213
- ...doAnimate2
214
- };
215
- }
216
- const isPopperPosition = node.hasAttribute("data-popper-animate-position");
217
- let popperHandledTransform = false;
218
- if (isPopperPosition && !isCurrentlyExiting && typeof diff.transform === "string") {
219
- const target = parseTranslate(diff.transform);
220
- if (target) {
221
- let entry = PopperPositionAnims.get(node);
222
- if (!entry) {
223
- let seed = target;
224
- try {
225
- seed = parseTranslate(getComputedStyle(node).transform) ?? target;
226
- } catch {}
227
- const x = motionValue(seed.x);
228
- const y = motionValue(seed.y);
229
- const write = () => {
230
- node.style.transform = `translate3d(${x.get()}px, ${y.get()}px, 0)`;
231
- };
232
- x.on("change", write);
233
- y.on("change", write);
234
- entry = {
235
- x,
236
- y,
237
- stop: null
238
- };
239
- PopperPositionAnims.set(node, entry);
240
- }
241
- if (!entry.stop) {
242
- try {
243
- const live = parseTranslate(getComputedStyle(node).transform);
244
- if (live) {
245
- entry.x.jump(live.x);
246
- entry.y.jump(live.y);
247
- }
248
- } catch {}
249
- }
250
- for (const anim of node.getAnimations()) {
251
- try {
252
- const kf = anim.effect?.getKeyframes?.();
253
- if (kf?.some(k => "transform" in k)) {
254
- anim.cancel();
255
- }
256
- } catch {}
257
- }
258
- const opts = animationOptions2;
259
- const positionTransition = opts.transform ?? opts.default ?? animationOptions2;
260
- const cx = animateMotionValue(entry.x, target.x, positionTransition);
261
- const cy = animateMotionValue(entry.y, target.y, positionTransition);
262
- entry.stop = () => {
263
- cx.stop();
264
- cy.stop();
265
- };
266
- popperHandledTransform = true;
267
- }
268
- }
269
- if (isCurrentlyExiting) {
270
- const entry = PopperPositionAnims.get(node);
271
- if (entry?.stop) {
272
- entry.stop();
273
- entry.stop = null;
274
- }
275
- }
276
- let midFlightValues = null;
277
- if (refs.current.controls) {
278
- try {
279
- const computed = getComputedStyle(node);
280
- midFlightValues = {};
281
- for (const key in diff) {
282
- const val = computed[key];
283
- if (val !== void 0 && val !== "") {
284
- midFlightValues[key] = val;
285
- }
286
- }
287
- } catch {}
288
- if (isCurrentlyExiting) {
289
- refs.current.controls.stop();
290
- }
291
- if (midFlightValues) {
292
- for (const key in midFlightValues) {
293
- if (key === "transform" && popperHandledTransform) continue;
294
- node.style[key] = midFlightValues[key];
295
- }
296
- }
297
- if (isPopperPosition && !popperHandledTransform) {
298
- const anims = node.getAnimations();
299
- for (const anim of anims) {
300
- anim.cancel();
301
- }
302
- }
303
- }
304
- const fixedDiff = fixTransparentColors(diff, refs.current.lastDoAnimate, doAnimate2);
305
- let waapiDiff = fixedDiff;
306
- if (popperHandledTransform && "transform" in waapiDiff) {
307
- waapiDiff = {
308
- ...waapiDiff
309
- };
310
- delete waapiDiff.transform;
311
- }
312
- if ((isPopperPosition || isCurrentlyExiting) && midFlightValues?.transform && waapiDiff.transform) {
313
- waapiDiff.transform = [midFlightValues.transform, waapiDiff.transform];
314
- }
315
- if (Object.keys(waapiDiff).length > 0) {
316
- startedControls = animate(scope.current, waapiDiff, animationOptions2);
317
- refs.current.controls = startedControls;
318
- }
319
- refs.current.lastAnimateAt = Date.now();
320
- }
321
- }
322
- refs.current.lastDontAnimate = dontAnimate2 ? {
323
- ...dontAnimate2
324
- } : {};
325
- refs.current.lastDoAnimate = doAnimate2 ? {
326
- ...doAnimate2
327
- } : {};
328
- } finally {
329
- if (isCurrentlyExiting && currentSendExitComplete) {
330
- if (startedControls) {
331
- refs.current.exitCompleteScheduled = true;
332
- startedControls.finished.then(() => {
333
- if (refs.current.isExiting) {
334
- currentSendExitComplete();
335
- }
336
- }).catch(() => {
337
- if (refs.current.isExiting) {
338
- currentSendExitComplete();
339
- }
340
- });
341
- } else if (!refs.current.exitCompleteScheduled) {
342
- currentSendExitComplete();
343
- }
344
- }
345
- }
346
- };
347
- useStyleEmitter?.((nextStyle, effectiveTransition) => {
348
- const animationProps2 = getMotionAnimatedProps(props, nextStyle, disableAnimation, refs.current.animationState, effectiveTransition);
349
- flushAnimation(animationProps2);
350
- });
351
- useIsomorphicLayoutEffect(() => {
352
- if (refs.current.isFirstRender) {
353
- refs.current.isFirstRender = false;
354
- refs.current.wasDisabled = disableAnimation;
355
- if (isHydrating) {
356
- if (doAnimate && Object.keys(doAnimate).length > 0) {
357
- refs.current.lastDoAnimate = {
358
- ...doAnimate
359
- };
360
- } else {
361
- refs.current.lastDoAnimate = dontAnimate ? {
362
- ...dontAnimate
363
- } : {};
364
- }
365
- refs.current.lastDontAnimate = dontAnimate ? {
366
- ...dontAnimate
367
- } : {};
368
- refs.current.lastAnimateAt = Date.now();
369
- return;
370
- }
371
- refs.current.lastDontAnimate = dontAnimate ? {
372
- ...dontAnimate
373
- } : {};
374
- refs.current.lastDoAnimate = doAnimate ? {
375
- ...doAnimate
376
- } : {};
377
- return;
378
- }
379
- const justEnabled = refs.current.wasDisabled && !disableAnimation;
380
- refs.current.wasDisabled = disableAnimation;
381
- const justStrippedClasses = !refs.current.wasNoClass && !!styleProps.noClass;
382
- refs.current.wasNoClass = !!styleProps.noClass;
383
- if ((justEnabled || justStrippedClasses) && animationState !== "enter") {
384
- const node = stateRef.current.host;
385
- if (node instanceof HTMLElement) {
386
- if (dontAnimate) Object.assign(node.style, dontAnimate);
387
- if (doAnimate) Object.assign(node.style, doAnimate);
388
- const entry = PopperPositionAnims.get(node);
389
- if (entry) {
390
- const target = parseTranslate(doAnimate?.transform ?? dontAnimate?.transform);
391
- if (target) {
392
- entry.stop?.();
393
- entry.stop = null;
394
- entry.x.jump(target.x);
395
- entry.y.jump(target.y);
396
- }
397
- }
398
- }
399
- refs.current.lastDontAnimate = dontAnimate ? {
400
- ...dontAnimate
401
- } : {};
402
- refs.current.lastDoAnimate = doAnimate ? {
403
- ...doAnimate
404
- } : {};
405
- return;
406
- }
407
- flushAnimation({
408
- doAnimate,
409
- dontAnimate,
410
- animationOptions
411
- });
412
- }, [style, isExiting, disableAnimation, styleProps.noClass]);
413
- if (process.env.NODE_ENV === "development") {
414
- if (props["debug"] && props["debug"] !== "profile") {
415
- console.groupCollapsed(`[motion] render`);
416
- console.info({
417
- style,
418
- doAnimate,
419
- dontAnimate,
420
- scope,
421
- animationOptions,
422
- isExiting,
423
- isFirstRender: refs.current.isFirstRender,
424
- animationProps
425
- });
426
- console.groupEnd();
427
- }
428
- }
429
- return {
430
- style: firstRenderStyle,
431
- ref: scope,
432
- render: "div"
433
- };
434
- },
435
- useAnimatedNumber(initial) {
436
- const motionValue2 = useMotionValue(initial);
437
- return React.useMemo(() => ({
438
- getInstance() {
439
- return motionValue2;
440
- },
441
- getValue() {
442
- return motionValue2.get();
443
- },
444
- setValue(next, config = {
445
- type: "spring"
446
- }, onFinish) {
447
- if (config.type === "direct") {
448
- MotionValueStrategy.set(motionValue2, {
449
- type: "direct"
450
- });
451
- motionValue2.set(next);
452
- onFinish?.();
453
- return;
454
- }
455
- MotionValueStrategy.set(motionValue2, config);
456
- if (onFinish) {
457
- const prior = PendingMotionOnFinish.get(motionValue2);
458
- if (prior) {
459
- PendingMotionOnFinish.delete(motionValue2);
460
- prior();
461
- }
462
- PendingMotionOnFinish.set(motionValue2, onFinish);
463
- }
464
- motionValue2.set(next);
465
- },
466
- stop() {
467
- motionValue2.stop();
468
- }
469
- }), [motionValue2]);
470
- },
471
- useAnimatedNumberReaction({
472
- value
473
- }, onValue) {
474
- const instance = value.getInstance();
475
- useMotionValueEvent(instance, "change", onValue);
476
- },
477
- useAnimatedNumberStyle(val, getStyleProp) {
478
- const motionValue2 = val.getInstance();
479
- const getStyleRef = useRef(getStyleProp);
480
- getStyleRef.current = getStyleProp;
481
- return useMemo(() => {
482
- return {
483
- getStyle: cur => {
484
- return getStyleRef.current(cur);
485
- },
486
- motionValue: motionValue2
487
- };
488
- }, []);
489
- },
490
- useAnimatedNumbersStyle(vals, getStyleProp) {
491
- const motionValues = vals.map(v => v.getInstance());
492
- const getStyleRef = useRef(getStyleProp);
493
- getStyleRef.current = getStyleProp;
494
- return useMemo(() => {
495
- return {
496
- getStyle: (...currentValues) => getStyleRef.current(...currentValues),
497
- motionValues
498
- };
499
- }, []);
500
- }
501
- };
502
- function getMotionAnimatedProps(props, style, disable, animationState = "default", transitionOverride) {
503
- if (disable) {
504
- return {
505
- dontAnimate: style
506
- };
507
- }
508
- const animationOptions = getAnimationOptions(transitionOverride ?? props.transition ?? null, animationState);
509
- let dontAnimate;
510
- let doAnimate;
511
- const animateOnly = props.animateOnly;
512
- for (const key in style) {
513
- const value = style[key];
514
- if (disableAnimationProps.has(key) || animateOnly && !animateOnly.includes(key)) {
515
- dontAnimate ||= {};
516
- dontAnimate[key] = value;
517
- } else {
518
- doAnimate ||= {};
519
- doAnimate[key] = value;
520
- }
521
- }
522
- return {
523
- dontAnimate,
524
- doAnimate,
525
- animationOptions
526
- };
527
- }
528
- function getAnimationOptions(transitionProp, animationState = "default") {
529
- const normalized = normalizeTransition(transitionProp);
530
- let effectiveKey = getEffectiveAnimation(normalized, animationState);
531
- if (!effectiveKey && animationState === "default") {
532
- effectiveKey = normalized.enter || normalized.exit || null;
533
- }
534
- const globalConfigOverride = normalized.config ? {
535
- ...normalized.config
536
- } : void 0;
537
- if (!effectiveKey && Object.keys(normalized.properties).length === 0 && !globalConfigOverride) {
538
- return {};
539
- }
540
- const defaultConfig = effectiveKey ? withInferredType(animations[effectiveKey]) : null;
541
- const delay = normalized.delay;
542
- const result = {};
543
- if (defaultConfig) {
544
- Object.assign(result, defaultConfig);
545
- }
546
- if (globalConfigOverride) {
547
- Object.assign(result, globalConfigOverride);
548
- if (result.type === void 0 && result.duration !== void 0 && result.damping === void 0 && result.stiffness === void 0 && result.mass === void 0) {
549
- result.type = "tween";
550
- }
551
- }
552
- if (delay) {
553
- result.delay = delay;
554
- }
555
- if (defaultConfig || globalConfigOverride || delay) {
556
- result.default = {
557
- ...defaultConfig,
558
- ...globalConfigOverride,
559
- ...(delay ? {
560
- delay
561
- } : null)
562
- };
563
- }
564
- for (const [propName, animationNameOrConfig] of Object.entries(normalized.properties)) {
565
- if (typeof animationNameOrConfig === "string") {
566
- result[propName] = withInferredType(animations[animationNameOrConfig]);
567
- } else if (animationNameOrConfig && typeof animationNameOrConfig === "object") {
568
- const baseConfig = animationNameOrConfig.type ? withInferredType(animations[animationNameOrConfig.type]) : defaultConfig;
569
- result[propName] = {
570
- ...baseConfig,
571
- ...animationNameOrConfig
572
- };
573
- }
574
- }
575
- convertMsToS(result);
576
- convertMsToS(result.default);
577
- for (const key in result) {
578
- if (key !== "default" && typeof result[key] === "object") {
579
- convertMsToS(result[key]);
580
- }
581
- }
582
- return result;
583
- }
47
+ let isHydratingGlobal;
48
+ const hydratingComponents = /* @__PURE__ */ new Set();
49
+ return {
50
+ View: MotionView,
51
+ Text: MotionText,
52
+ isReactNative: false,
53
+ inputStyle: "css",
54
+ outputStyle: "inline",
55
+ avoidReRenders: true,
56
+ animations,
57
+ usePresence,
58
+ ResetPresence,
59
+ onMount() {
60
+ isHydratingGlobal = false;
61
+ hydratingComponents.forEach((cb) => cb());
62
+ },
63
+ useAnimations: (animationProps) => {
64
+ if (isHydratingGlobal === void 0 && !getConfig().settings.disableSSR) {
65
+ isHydratingGlobal = true;
66
+ }
67
+ const { props, style, componentState, stateRef, useStyleEmitter, presence, onTransition, styleProps } = animationProps;
68
+ const animationKey = Array.isArray(props.transition) ? props.transition[0] : props.transition;
69
+ const isComponentHydrating = componentState.unmounted === true;
70
+ const isMounting = componentState.unmounted === "should-enter";
71
+ const isEntering = !!componentState.unmounted;
72
+ const isExiting = presence?.[0] === false;
73
+ const sendExitComplete = presence?.[1];
74
+ const refs = useRef(null);
75
+ if (!refs.current) {
76
+ refs.current = {
77
+ isFirstRender: true,
78
+ lastDoAnimate: null,
79
+ lastDontAnimate: null,
80
+ controls: null,
81
+ lastAnimateAt: 0,
82
+ disposed: false,
83
+ wasExiting: false,
84
+ isExiting: false,
85
+ sendExitComplete: void 0,
86
+ animationState: "default",
87
+ frozenExitTarget: null,
88
+ exitCompleteScheduled: false,
89
+ enterCompleteScheduled: false,
90
+ disableAnimation: true,
91
+ wasEntering: false,
92
+ wasDisabled: false,
93
+ onTransition: void 0,
94
+ enterStarted: false,
95
+ exitStarted: false,
96
+ updateInFlight: false,
97
+ updateControls: null,
98
+ wasNoClass: !!styleProps.noClass
99
+ };
100
+ }
101
+ const emit = (phase, cause, finished) => {
102
+ refs.current.onTransition?.(phase === "end" ? {
103
+ phase,
104
+ cause,
105
+ finished
106
+ } : {
107
+ phase,
108
+ cause
109
+ });
110
+ };
111
+ const justFinishedEntering = refs.current.wasEntering && !isEntering;
112
+ useEffect(() => {
113
+ refs.current.wasEntering = isEntering;
114
+ });
115
+ const animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default";
116
+ const disableAnimation = isComponentHydrating || isMounting || !animationKey;
117
+ const [scope] = useAnimateSSRSafe();
118
+ refs.current.isExiting = isExiting;
119
+ refs.current.sendExitComplete = sendExitComplete;
120
+ refs.current.animationState = animationState;
121
+ refs.current.disableAnimation = disableAnimation;
122
+ refs.current.onTransition = onTransition;
123
+ const justStartedExiting = isExiting && !refs.current.wasExiting;
124
+ const justStoppedExiting = !isExiting && refs.current.wasExiting;
125
+ if (justStartedExiting || justStoppedExiting) {
126
+ refs.current.frozenExitTarget = null;
127
+ refs.current.exitCompleteScheduled = false;
128
+ refs.current.enterCompleteScheduled = false;
129
+ }
130
+ useEffect(() => {
131
+ refs.current.wasExiting = isExiting;
132
+ });
133
+ useIsomorphicLayoutEffect(() => {
134
+ if (justStoppedExiting && refs.current.exitStarted) {
135
+ refs.current.exitStarted = false;
136
+ emit("end", "exit", false);
137
+ }
138
+ }, [justStoppedExiting]);
139
+ const { dontAnimate = {}, doAnimate, animationOptions } = getMotionAnimatedProps(props, style, disableAnimation, animationState);
140
+ const [firstRenderStyle] = useState(style);
141
+ if (refs.current.isFirstRender) {
142
+ refs.current.lastDontAnimate = firstRenderStyle;
143
+ }
144
+ const [isHydrating, setIsHydrating] = useState(isHydratingGlobal);
145
+ useLayoutEffect(() => {
146
+ if (isHydratingGlobal) {
147
+ hydratingComponents.add(() => {
148
+ setIsHydrating(false);
149
+ });
150
+ }
151
+ return () => {
152
+ refs.current.disposed = true;
153
+ };
154
+ }, []);
155
+ const flushAnimation = ({ doAnimate: doAnimateRaw = {}, animationOptions: passedOptions = {}, dontAnimate: dontAnimate2 }) => {
156
+ let startedControls = null;
157
+ const isCurrentlyExiting = refs.current.isExiting;
158
+ const currentSendExitComplete = refs.current.sendExitComplete;
159
+ const currentAnimationState = refs.current.animationState;
160
+ let doAnimate2 = doAnimateRaw;
161
+ if (isCurrentlyExiting && refs.current.frozenExitTarget) {
162
+ doAnimate2 = refs.current.frozenExitTarget;
163
+ }
164
+ const animationOptions2 = isCurrentlyExiting && currentSendExitComplete ? getAnimationOptions(props.transition ?? null, "exit") : passedOptions;
165
+ try {
166
+ const node = stateRef.current.host;
167
+ if (refs.current.isFirstRender) {
168
+ refs.current.lastDontAnimate = null;
169
+ refs.current.lastDoAnimate = null;
170
+ }
171
+ if (process.env.NODE_ENV === "development") {
172
+ if (props["debug"] && props["debug"] !== "profile") {
173
+ console.groupCollapsed(`[motion] animate (${JSON.stringify(getDiff(refs.current.lastDoAnimate, doAnimate2), null, 2)})`);
174
+ console.info({
175
+ props,
176
+ componentState,
177
+ doAnimate: doAnimate2,
178
+ dontAnimate: dontAnimate2,
179
+ animationOptions: animationOptions2,
180
+ animationProps,
181
+ lastDoAnimate: { ...refs.current.lastDoAnimate },
182
+ lastDontAnimate: { ...refs.current.lastDontAnimate },
183
+ isExiting,
184
+ style,
185
+ node
186
+ });
187
+ console.groupCollapsed(`trace >`);
188
+ console.trace();
189
+ console.groupEnd();
190
+ console.groupEnd();
191
+ }
192
+ }
193
+ if (!(node instanceof HTMLElement)) {
194
+ return;
195
+ }
196
+ const prevDont = refs.current.lastDontAnimate;
197
+ if (dontAnimate2) {
198
+ if (prevDont) {
199
+ removeRemovedStyles(prevDont, dontAnimate2, node, doAnimate2);
200
+ const changed = getDiff(prevDont, dontAnimate2);
201
+ if (changed) {
202
+ assignInlineStyles(node, changed);
203
+ }
204
+ } else {
205
+ assignInlineStyles(node, dontAnimate2);
206
+ }
207
+ }
208
+ if (doAnimate2) {
209
+ if (prevDont) {
210
+ for (const key in prevDont) {
211
+ if (key in doAnimate2) {
212
+ node.style[key] = normalizeValueWithProperty(prevDont[key], key);
213
+ if (refs.current.lastDoAnimate) {
214
+ refs.current.lastDoAnimate[key] = prevDont[key];
215
+ }
216
+ }
217
+ }
218
+ }
219
+ const lastAnimated = refs.current.lastDoAnimate;
220
+ if (lastAnimated) {
221
+ removeRemovedStyles(lastAnimated, doAnimate2, node, dontAnimate2);
222
+ }
223
+ const diff = getDiff(refs.current.lastDoAnimate, doAnimate2);
224
+ if (diff) {
225
+ if (isCurrentlyExiting && !refs.current.frozenExitTarget) {
226
+ refs.current.frozenExitTarget = { ...doAnimate2 };
227
+ }
228
+ const isPopperPosition = node.hasAttribute("data-popper-animate-position");
229
+ let popperHandledTransform = false;
230
+ if (isPopperPosition && !isCurrentlyExiting && typeof diff.transform === "string") {
231
+ const target = parseTranslate(diff.transform);
232
+ if (target) {
233
+ let entry = PopperPositionAnims.get(node);
234
+ if (!entry) {
235
+ let seed = target;
236
+ try {
237
+ seed = parseTranslate(getComputedStyle(node).transform) ?? target;
238
+ } catch {}
239
+ const x = motionValue(seed.x);
240
+ const y = motionValue(seed.y);
241
+ const write = () => {
242
+ node.style.transform = `translate3d(${x.get()}px, ${y.get()}px, 0)`;
243
+ };
244
+ x.on("change", write);
245
+ y.on("change", write);
246
+ entry = {
247
+ x,
248
+ y,
249
+ stop: null
250
+ };
251
+ PopperPositionAnims.set(node, entry);
252
+ }
253
+ if (!entry.stop) {
254
+ try {
255
+ const live = parseTranslate(getComputedStyle(node).transform);
256
+ if (live) {
257
+ entry.x.jump(live.x);
258
+ entry.y.jump(live.y);
259
+ }
260
+ } catch {}
261
+ }
262
+ for (const anim of node.getAnimations()) {
263
+ try {
264
+ const kf = anim.effect?.getKeyframes?.();
265
+ if (kf?.some((k) => "transform" in k)) {
266
+ anim.cancel();
267
+ }
268
+ } catch {}
269
+ }
270
+ const opts = animationOptions2;
271
+ const positionTransition = opts.transform ?? opts.default ?? animationOptions2;
272
+ const cx = animate(entry.x, target.x, positionTransition);
273
+ const cy = animate(entry.y, target.y, positionTransition);
274
+ entry.stop = () => {
275
+ cx.stop();
276
+ cy.stop();
277
+ };
278
+ popperHandledTransform = true;
279
+ }
280
+ }
281
+ if (isCurrentlyExiting) {
282
+ const entry = PopperPositionAnims.get(node);
283
+ if (entry?.stop) {
284
+ entry.stop();
285
+ entry.stop = null;
286
+ }
287
+ }
288
+ let midFlightValues = null;
289
+ if (refs.current.controls) {
290
+ try {
291
+ const computed = getComputedStyle(node);
292
+ midFlightValues = {};
293
+ for (const key in diff) {
294
+ const val = computed[key];
295
+ if (val !== void 0 && val !== "") {
296
+ midFlightValues[key] = val;
297
+ }
298
+ }
299
+ } catch {}
300
+ if (isCurrentlyExiting) {
301
+ refs.current.controls.stop();
302
+ }
303
+ if (midFlightValues) {
304
+ for (const key in midFlightValues) {
305
+ if (key === "transform" && popperHandledTransform) continue;
306
+ node.style[key] = midFlightValues[key];
307
+ }
308
+ }
309
+ if (isPopperPosition && !popperHandledTransform) {
310
+ const anims = node.getAnimations();
311
+ for (const anim of anims) {
312
+ anim.cancel();
313
+ }
314
+ }
315
+ }
316
+ const fixedDiff = fixTransparentColors(diff, refs.current.lastDoAnimate, doAnimate2);
317
+ let waapiDiff = Object.fromEntries(Object.entries(fixedDiff).map(([key, value]) => [key, Array.isArray(value) ? value.map((item) => normalizeValueWithProperty(item, key)) : normalizeValueWithProperty(value, key)]));
318
+ if (popperHandledTransform && "transform" in waapiDiff) {
319
+ waapiDiff = { ...waapiDiff };
320
+ delete waapiDiff.transform;
321
+ }
322
+ if ((isPopperPosition || isCurrentlyExiting) && midFlightValues?.transform && waapiDiff.transform) {
323
+ waapiDiff.transform = [midFlightValues.transform, waapiDiff.transform];
324
+ }
325
+ if (Object.keys(waapiDiff).length > 0) {
326
+ startedControls = animate(node, waapiDiff, animationOptions2);
327
+ refs.current.controls = startedControls;
328
+ }
329
+ refs.current.lastAnimateAt = Date.now();
330
+ }
331
+ }
332
+ refs.current.lastDontAnimate = dontAnimate2 ? { ...dontAnimate2 } : {};
333
+ refs.current.lastDoAnimate = doAnimate2 ? { ...doAnimate2 } : {};
334
+ } finally {
335
+ if (isCurrentlyExiting && currentSendExitComplete) {
336
+ if (refs.current.enterStarted) {
337
+ refs.current.enterStarted = false;
338
+ emit("end", "enter", false);
339
+ }
340
+ if (startedControls) {
341
+ if (!refs.current.exitStarted) {
342
+ refs.current.exitStarted = true;
343
+ emit("start", "exit");
344
+ }
345
+ refs.current.exitCompleteScheduled = true;
346
+ const complete = (finished) => {
347
+ if (!refs.current.isExiting) return;
348
+ if (refs.current.exitStarted) {
349
+ refs.current.exitStarted = false;
350
+ emit("end", "exit", finished);
351
+ }
352
+ currentSendExitComplete();
353
+ };
354
+ startedControls.finished.then(() => complete(true)).catch(() => complete(false));
355
+ } else if (!refs.current.exitCompleteScheduled) {
356
+ emit("start", "exit");
357
+ emit("end", "exit", true);
358
+ currentSendExitComplete();
359
+ }
360
+ } else if (currentAnimationState === "enter") {
361
+ if (startedControls) {
362
+ if (!refs.current.enterStarted) {
363
+ refs.current.enterStarted = true;
364
+ emit("start", "enter");
365
+ }
366
+ refs.current.enterCompleteScheduled = true;
367
+ const complete = (finished) => {
368
+ if (refs.current.disposed || refs.current.animationState !== "enter") return;
369
+ if (refs.current.enterStarted) {
370
+ refs.current.enterStarted = false;
371
+ emit("end", "enter", finished);
372
+ }
373
+ };
374
+ startedControls.finished.then(() => complete(true)).catch(() => complete(false));
375
+ } else if (!refs.current.enterCompleteScheduled && !refs.current.disableAnimation) {
376
+ emit("start", "enter");
377
+ emit("end", "enter", true);
378
+ }
379
+ } else if (startedControls) {
380
+ const controls = startedControls;
381
+ if (refs.current.updateInFlight) {
382
+ emit("end", "update", false);
383
+ }
384
+ refs.current.updateInFlight = true;
385
+ refs.current.updateControls = controls;
386
+ emit("start", "update");
387
+ const settle = (finished) => {
388
+ if (refs.current.updateControls !== controls) return;
389
+ refs.current.updateInFlight = false;
390
+ refs.current.updateControls = null;
391
+ emit("end", "update", finished);
392
+ };
393
+ controls.finished.then(() => settle(true)).catch(() => settle(false));
394
+ }
395
+ }
396
+ };
397
+ useStyleEmitter?.((nextStyle, effectiveTransition) => {
398
+ const animationProps2 = getMotionAnimatedProps(props, nextStyle, disableAnimation, refs.current.animationState, effectiveTransition);
399
+ flushAnimation(animationProps2);
400
+ });
401
+ useIsomorphicLayoutEffect(() => {
402
+ if (refs.current.isFirstRender) {
403
+ refs.current.isFirstRender = false;
404
+ refs.current.wasDisabled = disableAnimation;
405
+ if (isHydrating) {
406
+ if (doAnimate && Object.keys(doAnimate).length > 0) {
407
+ refs.current.lastDoAnimate = { ...doAnimate };
408
+ } else {
409
+ refs.current.lastDoAnimate = dontAnimate ? { ...dontAnimate } : {};
410
+ }
411
+ refs.current.lastDontAnimate = dontAnimate ? { ...dontAnimate } : {};
412
+ refs.current.lastAnimateAt = Date.now();
413
+ return;
414
+ }
415
+ refs.current.lastDontAnimate = dontAnimate ? { ...dontAnimate } : {};
416
+ refs.current.lastDoAnimate = doAnimate ? { ...doAnimate } : {};
417
+ return;
418
+ }
419
+ const justEnabled = refs.current.wasDisabled && !disableAnimation;
420
+ refs.current.wasDisabled = disableAnimation;
421
+ const justStrippedClasses = !refs.current.wasNoClass && !!styleProps.noClass;
422
+ refs.current.wasNoClass = !!styleProps.noClass;
423
+ if ((justEnabled || justStrippedClasses) && animationState !== "enter") {
424
+ const node = stateRef.current.host;
425
+ if (node instanceof HTMLElement) {
426
+ if (dontAnimate) assignInlineStyles(node, dontAnimate);
427
+ if (doAnimate) assignInlineStyles(node, doAnimate);
428
+ const entry = PopperPositionAnims.get(node);
429
+ if (entry) {
430
+ const target = parseTranslate(doAnimate?.transform ?? dontAnimate?.transform);
431
+ if (target) {
432
+ entry.stop?.();
433
+ entry.stop = null;
434
+ entry.x.jump(target.x);
435
+ entry.y.jump(target.y);
436
+ }
437
+ }
438
+ }
439
+ refs.current.lastDontAnimate = dontAnimate ? { ...dontAnimate } : {};
440
+ refs.current.lastDoAnimate = doAnimate ? { ...doAnimate } : {};
441
+ return;
442
+ }
443
+ flushAnimation({
444
+ doAnimate,
445
+ dontAnimate,
446
+ animationOptions
447
+ });
448
+ }, [
449
+ style,
450
+ isExiting,
451
+ disableAnimation,
452
+ styleProps.noClass
453
+ ]);
454
+ if (process.env.NODE_ENV === "development") {
455
+ if (props["debug"] && props["debug"] !== "profile") {
456
+ console.groupCollapsed(`[motion] render`);
457
+ console.info({
458
+ style,
459
+ doAnimate,
460
+ dontAnimate,
461
+ scope,
462
+ animationOptions,
463
+ isExiting,
464
+ isFirstRender: refs.current.isFirstRender,
465
+ animationProps
466
+ });
467
+ console.groupEnd();
468
+ }
469
+ }
470
+ return {
471
+ style: firstRenderStyle,
472
+ ref: scope,
473
+ render: "div"
474
+ };
475
+ },
476
+ useAnimatedNumber(initial) {
477
+ const motionValue2 = useMotionValue(initial);
478
+ return React.useMemo(() => ({
479
+ getInstance() {
480
+ return motionValue2;
481
+ },
482
+ getValue() {
483
+ return motionValue2.get();
484
+ },
485
+ setValue(next, config = { type: "spring" }, onFinish) {
486
+ if (config.type === "direct") {
487
+ MotionValueStrategy.set(motionValue2, { type: "direct" });
488
+ motionValue2.set(next);
489
+ onFinish?.();
490
+ return;
491
+ }
492
+ MotionValueStrategy.set(motionValue2, config);
493
+ if (onFinish) {
494
+ const prior = PendingMotionOnFinish.get(motionValue2);
495
+ if (prior) {
496
+ PendingMotionOnFinish.delete(motionValue2);
497
+ prior();
498
+ }
499
+ PendingMotionOnFinish.set(motionValue2, onFinish);
500
+ }
501
+ motionValue2.set(next);
502
+ },
503
+ stop() {
504
+ motionValue2.stop();
505
+ }
506
+ }), [motionValue2]);
507
+ },
508
+ useAnimatedNumberReaction({ value }, onValue) {
509
+ const instance = value.getInstance();
510
+ useMotionValueEvent(instance, "change", onValue);
511
+ },
512
+ useAnimatedNumberStyle(val, getStyleProp) {
513
+ const motionValue2 = val.getInstance();
514
+ const getStyleRef = useRef(getStyleProp);
515
+ getStyleRef.current = getStyleProp;
516
+ return useMemo(() => {
517
+ return {
518
+ getStyle: (cur) => {
519
+ return getStyleRef.current(cur);
520
+ },
521
+ motionValue: motionValue2
522
+ };
523
+ }, []);
524
+ },
525
+ useAnimatedNumbersStyle(vals, getStyleProp) {
526
+ const motionValues = vals.map((v) => v.getInstance());
527
+ const getStyleRef = useRef(getStyleProp);
528
+ getStyleRef.current = getStyleProp;
529
+ return useMemo(() => {
530
+ return {
531
+ getStyle: (...currentValues) => getStyleRef.current(...currentValues),
532
+ motionValues
533
+ };
534
+ }, []);
535
+ }
536
+ };
537
+ function getMotionAnimatedProps(props, style, disable, animationState = "default", transitionOverride) {
538
+ if (disable) {
539
+ return { dontAnimate: style };
540
+ }
541
+ const animationOptions = getAnimationOptions(transitionOverride ?? props.transition ?? null, animationState);
542
+ let dontAnimate;
543
+ let doAnimate;
544
+ const animateOnly = props.animateOnly;
545
+ for (const key in style) {
546
+ const value = style[key];
547
+ if (disableAnimationProps.has(key) || animateOnly && !animateOnly.includes(key)) {
548
+ dontAnimate ||= {};
549
+ dontAnimate[key] = value;
550
+ } else {
551
+ doAnimate ||= {};
552
+ doAnimate[key] = value;
553
+ }
554
+ }
555
+ return {
556
+ dontAnimate,
557
+ doAnimate,
558
+ animationOptions
559
+ };
560
+ }
561
+ function getAnimationOptions(transitionProp, animationState = "default") {
562
+ const normalized = normalizeTransition(transitionProp);
563
+ let effectiveKey = getEffectiveAnimation(normalized, animationState);
564
+ if (!effectiveKey && animationState === "default") {
565
+ effectiveKey = normalized.enter || normalized.exit || null;
566
+ }
567
+ const globalConfigOverride = normalized.config ? { ...normalized.config } : void 0;
568
+ if (!effectiveKey && Object.keys(normalized.properties).length === 0 && !globalConfigOverride) {
569
+ return {};
570
+ }
571
+ const defaultConfig = effectiveKey ? withInferredType(animations[effectiveKey]) : null;
572
+ const delay = normalized.delay;
573
+ const result = {};
574
+ if (defaultConfig) {
575
+ Object.assign(result, defaultConfig);
576
+ }
577
+ if (globalConfigOverride) {
578
+ Object.assign(result, globalConfigOverride);
579
+ if (result.type === void 0 && result.duration !== void 0 && result.damping === void 0 && result.stiffness === void 0 && result.mass === void 0) {
580
+ result.type = "tween";
581
+ }
582
+ }
583
+ if (delay) {
584
+ result.delay = delay;
585
+ }
586
+ if (defaultConfig || globalConfigOverride || delay) {
587
+ result.default = {
588
+ ...defaultConfig,
589
+ ...globalConfigOverride,
590
+ ...delay ? { delay } : null
591
+ };
592
+ }
593
+ for (const [propName, animationNameOrConfig] of Object.entries(normalized.properties)) {
594
+ if (typeof animationNameOrConfig === "string") {
595
+ result[propName] = withInferredType(animations[animationNameOrConfig]);
596
+ } else if (animationNameOrConfig && typeof animationNameOrConfig === "object") {
597
+ const baseConfig = animationNameOrConfig.type ? withInferredType(animations[animationNameOrConfig.type]) : defaultConfig;
598
+ result[propName] = {
599
+ ...baseConfig,
600
+ ...animationNameOrConfig
601
+ };
602
+ }
603
+ }
604
+ convertMsToS(result);
605
+ convertMsToS(result.default);
606
+ for (const key in result) {
607
+ if (key !== "default" && typeof result[key] === "object") {
608
+ convertMsToS(result[key]);
609
+ }
610
+ }
611
+ return result;
612
+ }
584
613
  }
585
614
  function withInferredType(config) {
586
- if (!config) {
587
- return {
588
- type: "spring"
589
- };
590
- }
591
- const isTimingBased = config.duration !== void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0;
592
- return {
593
- type: isTimingBased ? "tween" : "spring",
594
- ...config
595
- };
615
+ if (!config) {
616
+ return { type: "spring" };
617
+ }
618
+ const isTimingBased = config.duration !== void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0;
619
+ return {
620
+ type: isTimingBased ? "tween" : "spring",
621
+ ...config
622
+ };
596
623
  }
597
624
  function convertMsToS(config) {
598
- if (!config) return;
599
- if (typeof config.delay === "number") config.delay = config.delay / 1e3;
600
- if (typeof config.duration === "number") {
601
- const isTimingBased = config.type === "tween" || config.type === void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0;
602
- if (isTimingBased) {
603
- config.duration = config.duration / 1e3;
604
- }
605
- }
625
+ if (!config) return;
626
+ if (typeof config.delay === "number") config.delay = config.delay / 1e3;
627
+ if (typeof config.duration === "number") {
628
+ const isTimingBased = config.type === "tween" || config.type === void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0;
629
+ if (isTimingBased) {
630
+ config.duration = config.duration / 1e3;
631
+ }
632
+ }
606
633
  }
607
634
  function removeRemovedStyles(prev, next, node, dontClearIfIn) {
608
- for (const key in prev) {
609
- if (!(key in next)) {
610
- if (dontClearIfIn && key in dontClearIfIn) {
611
- continue;
612
- }
613
- node.style[key] = "";
614
- }
615
- }
635
+ for (const key in prev) {
636
+ if (!(key in next)) {
637
+ if (dontClearIfIn && key in dontClearIfIn) {
638
+ continue;
639
+ }
640
+ node.style[key] = "";
641
+ }
642
+ }
643
+ }
644
+ const disableAnimationProps = /* @__PURE__ */ new Set([
645
+ "alignContent",
646
+ "alignItems",
647
+ "boxSizing",
648
+ "contain",
649
+ "containerType",
650
+ "display",
651
+ "flexBasis",
652
+ "flexDirection",
653
+ "fontFamily",
654
+ "justifyContent",
655
+ "overflow",
656
+ "overflowX",
657
+ "overflowY",
658
+ "pointerEvents",
659
+ "position",
660
+ "textWrap",
661
+ "userSelect"
662
+ ]);
663
+ function motionPropsEqual(a, b) {
664
+ for (const key in a) {
665
+ if (!(key in b)) return false;
666
+ }
667
+ for (const key in b) {
668
+ if (key === "children") continue;
669
+ const av = a[key];
670
+ const bv = b[key];
671
+ if (typeof bv === "function" && typeof av === "function") continue;
672
+ if (!Object.is(av, bv)) return false;
673
+ }
674
+ return true;
675
+ }
676
+ function motionStylesEqual(a, b) {
677
+ if (a.length !== b.length) return false;
678
+ for (let i = 0; i < a.length; i++) {
679
+ const sa = a[i];
680
+ const sb = b[i];
681
+ if (sa === sb) continue;
682
+ if (!sa || !sb) return false;
683
+ let aCount = 0;
684
+ for (const key in sa) {
685
+ aCount++;
686
+ if (!Object.is(sa[key], sb[key])) return false;
687
+ }
688
+ let bCount = 0;
689
+ for (const _key in sb) {
690
+ bCount++;
691
+ }
692
+ if (aCount !== bCount) return false;
693
+ }
694
+ return true;
616
695
  }
617
- const disableAnimationProps = /* @__PURE__ */new Set(["alignContent", "alignItems", "boxSizing", "contain", "containerType", "display", "flexBasis", "flexDirection", "fontFamily", "justifyContent", "overflow", "overflowX", "overflowY", "pointerEvents", "position", "textWrap", "userSelect"]);
618
696
  const MotionView = createMotionView("div");
619
697
  const MotionText = createMotionView("span");
698
+ const transformAliases = {
699
+ x: "translateX",
700
+ y: "translateY",
701
+ scale: "scale",
702
+ scaleX: "scaleX",
703
+ scaleY: "scaleY",
704
+ rotate: "rotate",
705
+ rotateX: "rotateX",
706
+ rotateY: "rotateY",
707
+ rotateZ: "rotateZ",
708
+ skewX: "skewX",
709
+ skewY: "skewY"
710
+ };
711
+ function compileAnimatedStyle(initialSource, initialResolved) {
712
+ const shorthands = getConfig().shorthands;
713
+ const entries = Object.keys(initialSource).map((source) => ({
714
+ source,
715
+ target: shorthands?.[source] ?? source,
716
+ tokenValue: typeof initialSource[source] === "string" && initialResolved[shorthands?.[source] ?? source] !== initialSource[source] ? initialResolved[shorthands?.[source] ?? source] : void 0
717
+ }));
718
+ return (sourceStyle) => {
719
+ const resolved = {};
720
+ const transforms = [];
721
+ for (const entry of entries) {
722
+ const value = sourceStyle[entry.source];
723
+ if (value === void 0) continue;
724
+ if (entry.source === "transform" && Array.isArray(value)) {
725
+ resolved.transform = transformsToString(value);
726
+ } else if (entry.source in transformAliases) {
727
+ transforms.push({ [transformAliases[entry.source]]: value });
728
+ } else {
729
+ resolved[entry.target] = entry.tokenValue ?? normalizeValueWithProperty(value, entry.target);
730
+ }
731
+ }
732
+ if (transforms.length) resolved.transform = transformsToString(transforms);
733
+ return resolved;
734
+ };
735
+ }
620
736
  function createMotionView(defaultTag) {
621
- const isText = defaultTag === "span";
622
- const Component = forwardRef((propsIn, ref) => {
623
- const {
624
- forwardedRef,
625
- animation,
626
- render = defaultTag,
627
- style,
628
- ...propsRest
629
- } = propsIn;
630
- const [scope, animate] = useAnimateSSRSafe();
631
- const hostRef = useRef(null);
632
- const seededNode = useRef(null);
633
- const seededInCurrentFrame = useRef(false);
634
- const queuedAnimationFrames = useRef(/* @__PURE__ */new WeakMap());
635
- const composedRefs = useComposedRefs(forwardedRef, ref, hostRef, scope);
636
- const stateRef = useRef(null);
637
- if (!stateRef.current) {
638
- stateRef.current = {
639
- get host() {
640
- return hostRef.current;
641
- }
642
- };
643
- }
644
- const [_, state] = useThemeWithState({});
645
- const styles = Array.isArray(style) ? style : [style];
646
- const [animatedStyle, nonAnimatedStyles] = (() => {
647
- let animatedStyle2;
648
- const nonAnimatedStyles2 = [];
649
- for (const style2 of styles) {
650
- if (style2.getStyle) {
651
- animatedStyle2 = style2;
652
- } else {
653
- nonAnimatedStyles2.push(style2);
654
- }
655
- }
656
- return [animatedStyle2, nonAnimatedStyles2];
657
- })();
658
- function getProps(props2) {
659
- const out = getSplitStyles(props2, isText ? Text.staticConfig : View.staticConfig, state?.theme, state?.name, {
660
- unmounted: false
661
- }, {
662
- isAnimated: false,
663
- noClass: true,
664
- resolveValues: "auto"
665
- });
666
- if (!out) {
667
- return {};
668
- }
669
- if (out.viewProps.style) {
670
- fixStyles(out.viewProps.style);
671
- styleToCSS(out.viewProps.style);
672
- }
673
- return out.viewProps;
674
- }
675
- const props = getProps({
676
- ...propsRest,
677
- style: nonAnimatedStyles
678
- });
679
- const Element = render || "div";
680
- const transformedProps = hooks.usePropsTransform?.(render, props, stateRef, false);
681
- useIsomorphicLayoutEffect(() => {
682
- if (!animatedStyle) return;
683
- const node = hostRef.current;
684
- if (node instanceof HTMLElement && seededNode.current !== node) {
685
- const currentStyle = animatedStyle.motionValues ? animatedStyle.getStyle(...animatedStyle.motionValues.map(value => value.get())) : animatedStyle.motionValue ? animatedStyle.getStyle(animatedStyle.motionValue.get()) : null;
686
- const webStyle = currentStyle && getProps({
687
- style: currentStyle
688
- }).style;
689
- if (webStyle) {
690
- Object.assign(node.style, webStyle);
691
- seededNode.current = node;
692
- seededInCurrentFrame.current = true;
693
- requestAnimationFrame(() => {
694
- if (seededNode.current === node) {
695
- seededInCurrentFrame.current = false;
696
- }
697
- });
698
- }
699
- }
700
- const toTransition = animationConfig => animationConfig?.type === "timing" ? {
701
- type: "tween",
702
- duration: (animationConfig?.duration || 0) / 1e3
703
- } : animationConfig?.type === "direct" ? {
704
- type: "tween",
705
- duration: 0
706
- } : {
707
- type: "spring",
708
- ...animationConfig
709
- };
710
- const animateNodeTo = (nextStyle, transition, mv) => {
711
- if (!(node instanceof HTMLElement) || hostRef.current !== node) return;
712
- const webStyle = getProps({
713
- style: nextStyle
714
- }).style;
715
- if (!webStyle) return;
716
- settlePendingMotionOnFinish(mv, animate(node, webStyle, transition));
717
- };
718
- const animateChangedValue = (nextStyle, transition, mv) => {
719
- if (seededInCurrentFrame.current && seededNode.current === node) {
720
- const queuedFrame = queuedAnimationFrames.current.get(mv);
721
- if (queuedFrame !== void 0) {
722
- cancelAnimationFrame(queuedFrame);
723
- }
724
- const frame = requestAnimationFrame(() => {
725
- if (queuedAnimationFrames.current.get(mv) !== frame) return;
726
- queuedAnimationFrames.current.delete(mv);
727
- if (hostRef.current === node) {
728
- animateNodeTo(nextStyle, transition, mv);
729
- } else {
730
- const onFinish = PendingMotionOnFinish.get(mv);
731
- PendingMotionOnFinish.delete(mv);
732
- onFinish?.();
733
- }
734
- });
735
- queuedAnimationFrames.current.set(mv, frame);
736
- return;
737
- }
738
- animateNodeTo(nextStyle, transition, mv);
739
- };
740
- if (animatedStyle.motionValues) {
741
- const mvs = animatedStyle.motionValues;
742
- const styleForAll = () => animatedStyle.getStyle(...mvs.map(v => v.get()));
743
- const unsubs = mvs.map(mv => mv.on("change", () => animateChangedValue(styleForAll(), toTransition(MotionValueStrategy.get(mv)), mv)));
744
- return () => unsubs.forEach(fn => fn());
745
- }
746
- const motionValue2 = animatedStyle.motionValue;
747
- if (!motionValue2) return;
748
- return motionValue2.on("change", value => animateChangedValue(animatedStyle.getStyle(value), toTransition(MotionValueStrategy.get(motionValue2)), motionValue2));
749
- }, [animatedStyle]);
750
- return /* @__PURE__ */jsx(Element, {
751
- ...transformedProps,
752
- ref: composedRefs
753
- });
754
- });
755
- Component["acceptRenderProp"] = true;
756
- return Component;
737
+ const isText = defaultTag === "span";
738
+ const Component = createRefComponent((propsIn, ref) => {
739
+ const { forwardedRef, animation, render = defaultTag, style, ...propsRest } = propsIn;
740
+ const [scope, animate] = useAnimateSSRSafe();
741
+ const hostRef = useRef(null);
742
+ const seededNode = useRef(null);
743
+ const seededInCurrentFrame = useRef(false);
744
+ const queuedAnimationFrames = useRef(/* @__PURE__ */ new WeakMap());
745
+ const composedRefs = useComposedRefs(forwardedRef, ref, hostRef, scope);
746
+ const stateRef = useRef(null);
747
+ if (!stateRef.current) {
748
+ stateRef.current = { get host() {
749
+ return hostRef.current;
750
+ } };
751
+ }
752
+ const [_, state] = useThemeWithState({});
753
+ const styles = Array.isArray(style) ? style : [style];
754
+ const [animatedStyle, nonAnimatedStyles] = (() => {
755
+ let animatedStyle2;
756
+ const nonAnimatedStyles2 = [];
757
+ for (const style2 of styles) {
758
+ if (style2.getStyle) {
759
+ animatedStyle2 = style2;
760
+ } else {
761
+ nonAnimatedStyles2.push(style2);
762
+ }
763
+ }
764
+ return [animatedStyle2, nonAnimatedStyles2];
765
+ })();
766
+ function getProps(props2) {
767
+ if (process.env.NODE_ENV === "development" && propsIn.debug === "profile" && typeof performance !== "undefined") {
768
+ performance.mark("tamagui-motion-style-split");
769
+ }
770
+ const out = getSplitStyles(props2, isText ? Text.staticConfig : View.staticConfig, state?.theme, state?.name, { unmounted: false }, {
771
+ isAnimated: false,
772
+ noClass: true,
773
+ resolveValues: "auto"
774
+ });
775
+ if (!out) {
776
+ return {};
777
+ }
778
+ if (out.viewProps.style) {
779
+ fixStyles(out.viewProps.style);
780
+ styleToCSS(out.viewProps.style);
781
+ }
782
+ return out.viewProps;
783
+ }
784
+ const resolvedAnimatedStyle = useMemo(() => {
785
+ if (!animatedStyle) return null;
786
+ const currentValues = animatedStyle.motionValues ? animatedStyle.motionValues.map((value) => value.get()) : animatedStyle.motionValue ? [animatedStyle.motionValue.get()] : [];
787
+ const initialSource = animatedStyle.getStyle(...currentValues);
788
+ const initialResolved = asStyleRecord(getProps({ style: initialSource }).style);
789
+ return {
790
+ initial: initialResolved,
791
+ resolve: compileAnimatedStyle(initialSource, initialResolved)
792
+ };
793
+ }, [
794
+ animatedStyle,
795
+ state?.theme,
796
+ state?.name
797
+ ]);
798
+ const memoRef = useRef(null);
799
+ let props;
800
+ const cached = memoRef.current;
801
+ if (cached && cached.theme === state?.theme && cached.themeName === state?.name && motionStylesEqual(cached.styles, nonAnimatedStyles) && motionPropsEqual(cached.propsRest, propsRest)) {
802
+ props = { ...cached.result };
803
+ for (const key in propsRest) {
804
+ const val = propsRest[key];
805
+ if (key === "children" || typeof val === "function") {
806
+ props[key] = val;
807
+ }
808
+ }
809
+ } else {
810
+ props = getProps({
811
+ ...propsRest,
812
+ style: nonAnimatedStyles
813
+ });
814
+ memoRef.current = {
815
+ propsRest,
816
+ styles: nonAnimatedStyles,
817
+ theme: state?.theme,
818
+ themeName: state?.name,
819
+ result: props
820
+ };
821
+ }
822
+ if (resolvedAnimatedStyle) {
823
+ props = {
824
+ ...props,
825
+ style: {
826
+ ...asStyleRecord(props.style),
827
+ ...resolvedAnimatedStyle.initial
828
+ }
829
+ };
830
+ }
831
+ const Element = render || "div";
832
+ const transformedProps = hooks.usePropsTransform?.(render, props, stateRef, false);
833
+ useIsomorphicLayoutEffect(() => {
834
+ if (!animatedStyle) return;
835
+ const node = hostRef.current;
836
+ if (node instanceof HTMLElement && seededNode.current !== node) {
837
+ const currentStyle = animatedStyle.motionValues ? animatedStyle.getStyle(...animatedStyle.motionValues.map((value) => value.get())) : animatedStyle.motionValue ? animatedStyle.getStyle(animatedStyle.motionValue.get()) : null;
838
+ const webStyle = currentStyle && resolvedAnimatedStyle?.resolve(currentStyle);
839
+ if (webStyle) {
840
+ assignInlineStyles(node, webStyle);
841
+ seededNode.current = node;
842
+ seededInCurrentFrame.current = true;
843
+ requestAnimationFrame(() => {
844
+ if (seededNode.current === node) seededInCurrentFrame.current = false;
845
+ });
846
+ }
847
+ }
848
+ const toTransition = (animationConfig) => animationConfig?.type === "timing" ? {
849
+ type: "tween",
850
+ duration: (animationConfig.duration || 0) / 1e3
851
+ } : animationConfig?.type === "direct" ? {
852
+ type: "tween",
853
+ duration: 0
854
+ } : {
855
+ type: "spring",
856
+ ...animationConfig
857
+ };
858
+ const animateNodeTo = (nextStyle, transition, motionValue3) => {
859
+ if (!(node instanceof HTMLElement) || hostRef.current !== node) return;
860
+ const webStyle = resolvedAnimatedStyle?.resolve(nextStyle);
861
+ if (!webStyle) return;
862
+ settlePendingMotionOnFinish(motionValue3, animate(node, webStyle, transition));
863
+ };
864
+ const animateChangedValue = (nextStyle, transition, motionValue3) => {
865
+ if (seededInCurrentFrame.current && seededNode.current === node) {
866
+ const queuedFrame = queuedAnimationFrames.current.get(motionValue3);
867
+ if (queuedFrame !== void 0) cancelAnimationFrame(queuedFrame);
868
+ const frame = requestAnimationFrame(() => {
869
+ if (queuedAnimationFrames.current.get(motionValue3) !== frame) return;
870
+ queuedAnimationFrames.current.delete(motionValue3);
871
+ if (hostRef.current === node) {
872
+ animateNodeTo(nextStyle, transition, motionValue3);
873
+ } else {
874
+ const onFinish = PendingMotionOnFinish.get(motionValue3);
875
+ PendingMotionOnFinish.delete(motionValue3);
876
+ onFinish?.();
877
+ }
878
+ });
879
+ queuedAnimationFrames.current.set(motionValue3, frame);
880
+ return;
881
+ }
882
+ animateNodeTo(nextStyle, transition, motionValue3);
883
+ };
884
+ if (animatedStyle.motionValues) {
885
+ const mvs = animatedStyle.motionValues;
886
+ const styleForAll = () => animatedStyle.getStyle(...mvs.map((value) => value.get()));
887
+ const unsubs = mvs.map((mv) => mv.on("change", () => animateChangedValue(styleForAll(), toTransition(MotionValueStrategy.get(mv)), mv)));
888
+ return () => unsubs.forEach((fn) => fn());
889
+ }
890
+ const motionValue2 = animatedStyle.motionValue;
891
+ if (!motionValue2) return;
892
+ return motionValue2.on("change", (value) => animateChangedValue(animatedStyle.getStyle(value), toTransition(MotionValueStrategy.get(motionValue2)), motionValue2));
893
+ }, [animatedStyle, resolvedAnimatedStyle]);
894
+ return /* @__PURE__ */ jsx(Element, {
895
+ ...transformedProps,
896
+ ref: composedRefs
897
+ });
898
+ });
899
+ Component["acceptRenderProp"] = true;
900
+ return Component;
757
901
  }
758
902
  function getDiff(previous, next) {
759
- if (!previous) {
760
- return next;
761
- }
762
- let diff = null;
763
- for (const key in next) {
764
- if (next[key] !== previous[key]) {
765
- diff ||= {};
766
- diff[key] = next[key];
767
- }
768
- }
769
- return diff;
903
+ if (!previous) {
904
+ return next;
905
+ }
906
+ let diff = null;
907
+ for (const key in next) {
908
+ if (next[key] !== previous[key]) {
909
+ diff ||= {};
910
+ diff[key] = next[key];
911
+ }
912
+ }
913
+ return diff;
770
914
  }
771
915
  function fixTransparentColors(diff, previous, next) {
772
- let result = diff;
773
- for (const key in diff) {
774
- if (diff[key] === "transparent") {
775
- let fixed = "rgba(0, 0, 0, 0)";
776
- const candidates = [previous?.[key], next?.[key]];
777
- for (const candidate of candidates) {
778
- if (typeof candidate === "string" && candidate !== "transparent") {
779
- const rgbaMatch = candidate.match(/^rgba?\(([^,]+),\s*([^,]+),\s*([^,)]+)/);
780
- if (rgbaMatch) {
781
- fixed = `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, 0)`;
782
- break;
783
- }
784
- }
785
- }
786
- if (result === diff) {
787
- result = {
788
- ...diff
789
- };
790
- }
791
- result[key] = fixed;
792
- }
793
- }
794
- return result;
916
+ let result = diff;
917
+ for (const key in diff) {
918
+ if (diff[key] === "transparent") {
919
+ let fixed = "rgba(0, 0, 0, 0)";
920
+ const candidates = [previous?.[key], next?.[key]];
921
+ for (const candidate of candidates) {
922
+ if (typeof candidate === "string" && candidate !== "transparent") {
923
+ const rgbaMatch = candidate.match(/^rgba?\(([^,]+),\s*([^,]+),\s*([^,)]+)/);
924
+ if (rgbaMatch) {
925
+ fixed = `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, 0)`;
926
+ break;
927
+ }
928
+ }
929
+ }
930
+ if (result === diff) {
931
+ result = { ...diff };
932
+ }
933
+ result[key] = fixed;
934
+ }
935
+ }
936
+ return result;
795
937
  }
938
+
796
939
  export { createAnimations, disableAnimationProps };
797
940
  //# sourceMappingURL=createAnimations.mjs.map