@hanzogui/animations-motion 3.0.6 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,130 +4,195 @@ import { fixStyles, getConfig, getSplitStyles, hooks, styleToCSS, Text, useCompo
4
4
  import { useAnimate, useMotionValue, useMotionValueEvent } from "motion/react";
5
5
  import React, { forwardRef, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
- const isServer = typeof window > "u";
7
+ const isServer = typeof window === "undefined";
8
8
  function useAnimateSSRSafe() {
9
- return isServer ? [useRef(null), () => {}] : useAnimate();
9
+ if (isServer) {
10
+ return [useRef(null), () => {}];
11
+ }
12
+ return useAnimate();
10
13
  }
11
14
  const MotionValueStrategy = /* @__PURE__ */new WeakMap();
15
+ const PendingMotionOnFinish = /* @__PURE__ */new WeakMap();
16
+ function settlePendingMotionOnFinish(mv, controls) {
17
+ const onFinish = PendingMotionOnFinish.get(mv);
18
+ if (!onFinish) return;
19
+ PendingMotionOnFinish.delete(mv);
20
+ controls.then(() => onFinish()).catch(() => onFinish());
21
+ }
12
22
  function createAnimations(animations) {
13
23
  let isHydratingGlobal;
14
24
  const hydratingComponents = /* @__PURE__ */new Set();
15
25
  return {
16
26
  View: MotionView,
17
27
  Text: MotionText,
18
- isReactNative: !1,
28
+ isReactNative: false,
19
29
  inputStyle: "css",
20
30
  outputStyle: "inline",
21
- avoidReRenders: !0,
31
+ avoidReRenders: true,
22
32
  animations,
23
33
  usePresence,
24
34
  ResetPresence,
25
35
  onMount() {
26
- isHydratingGlobal = !1, hydratingComponents.forEach(cb => cb());
36
+ isHydratingGlobal = false;
37
+ hydratingComponents.forEach(cb => cb());
27
38
  },
28
39
  useAnimations: animationProps => {
29
- isHydratingGlobal === void 0 && !getConfig().settings.disableSSR && (isHydratingGlobal = !0);
40
+ if (isHydratingGlobal === void 0 && !getConfig().settings.disableSSR) {
41
+ isHydratingGlobal = true;
42
+ }
30
43
  const {
31
- props,
32
- style,
33
- componentState,
34
- stateRef,
35
- useStyleEmitter,
36
- presence
37
- } = animationProps,
38
- animationKey = Array.isArray(props.transition) ? props.transition[0] : props.transition,
39
- isComponentHydrating = componentState.unmounted === !0,
40
- isMounting = componentState.unmounted === "should-enter",
41
- isEntering = !!componentState.unmounted,
42
- isExiting = presence?.[0] === !1,
43
- sendExitComplete = presence?.[1],
44
- refs = useRef(null);
45
- refs.current || (refs.current = {
46
- isFirstRender: !0,
47
- lastDoAnimate: null,
48
- lastDontAnimate: null,
49
- controls: null,
50
- lastAnimateAt: 0,
51
- disposed: !1,
52
- wasExiting: !1,
53
- isExiting: !1,
54
- sendExitComplete: void 0,
55
- animationState: "default",
56
- frozenExitTarget: null,
57
- exitCompleteScheduled: !1,
58
- wasEntering: !1
59
- });
44
+ props,
45
+ style,
46
+ componentState,
47
+ stateRef,
48
+ useStyleEmitter,
49
+ presence
50
+ } = animationProps;
51
+ const animationKey = Array.isArray(props.transition) ? props.transition[0] : props.transition;
52
+ const isComponentHydrating = componentState.unmounted === true;
53
+ const isMounting = componentState.unmounted === "should-enter";
54
+ const isEntering = !!componentState.unmounted;
55
+ const isExiting = presence?.[0] === false;
56
+ const sendExitComplete = presence?.[1];
57
+ const refs = useRef(null);
58
+ if (!refs.current) {
59
+ refs.current = {
60
+ isFirstRender: true,
61
+ lastDoAnimate: null,
62
+ lastDontAnimate: null,
63
+ controls: null,
64
+ lastAnimateAt: 0,
65
+ disposed: false,
66
+ wasExiting: false,
67
+ isExiting: false,
68
+ sendExitComplete: void 0,
69
+ animationState: "default",
70
+ frozenExitTarget: null,
71
+ exitCompleteScheduled: false,
72
+ wasEntering: false
73
+ };
74
+ }
60
75
  const justFinishedEntering = refs.current.wasEntering && !isEntering;
61
76
  useEffect(() => {
62
77
  refs.current.wasEntering = isEntering;
63
78
  });
64
- const animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default",
65
- disableAnimation = isComponentHydrating || isMounting || !animationKey,
66
- [scope, animate] = useAnimateSSRSafe();
67
- refs.current.isExiting = isExiting, refs.current.sendExitComplete = sendExitComplete, refs.current.animationState = animationState;
68
- const justStartedExiting = isExiting && !refs.current.wasExiting,
69
- justStoppedExiting = !isExiting && refs.current.wasExiting;
70
- (justStartedExiting || justStoppedExiting) && (refs.current.frozenExitTarget = null, refs.current.exitCompleteScheduled = !1), useEffect(() => {
79
+ const animationState = isExiting ? "exit" : isMounting || justFinishedEntering ? "enter" : "default";
80
+ const disableAnimation = isComponentHydrating || isMounting || !animationKey;
81
+ const [scope, animate] = useAnimateSSRSafe();
82
+ refs.current.isExiting = isExiting;
83
+ refs.current.sendExitComplete = sendExitComplete;
84
+ refs.current.animationState = animationState;
85
+ const justStartedExiting = isExiting && !refs.current.wasExiting;
86
+ const justStoppedExiting = !isExiting && refs.current.wasExiting;
87
+ if (justStartedExiting || justStoppedExiting) {
88
+ refs.current.frozenExitTarget = null;
89
+ refs.current.exitCompleteScheduled = false;
90
+ }
91
+ useEffect(() => {
71
92
  refs.current.wasExiting = isExiting;
72
93
  });
73
94
  const {
74
- dontAnimate = {},
75
- doAnimate,
76
- animationOptions
77
- } = getMotionAnimatedProps(props, style, disableAnimation, animationState),
78
- [firstRenderStyle] = useState(style);
79
- refs.current.isFirstRender && (refs.current.lastDontAnimate = firstRenderStyle);
95
+ dontAnimate = {},
96
+ doAnimate,
97
+ animationOptions
98
+ } = getMotionAnimatedProps(props, style, disableAnimation, animationState);
99
+ const [firstRenderStyle] = useState(style);
100
+ if (refs.current.isFirstRender) {
101
+ refs.current.lastDontAnimate = firstRenderStyle;
102
+ }
80
103
  const [isHydrating, setIsHydrating] = useState(isHydratingGlobal);
81
- useLayoutEffect(() => (isHydratingGlobal && hydratingComponents.add(() => {
82
- setIsHydrating(!1);
83
- }), () => {
84
- refs.current.disposed = !0;
85
- }), []);
104
+ useLayoutEffect(() => {
105
+ if (isHydratingGlobal) {
106
+ hydratingComponents.add(() => {
107
+ setIsHydrating(false);
108
+ });
109
+ }
110
+ return () => {
111
+ refs.current.disposed = true;
112
+ };
113
+ }, []);
86
114
  const flushAnimation = ({
87
115
  doAnimate: doAnimateRaw = {},
88
116
  animationOptions: passedOptions = {},
89
117
  dontAnimate: dontAnimate2
90
118
  }) => {
91
119
  let startedControls = null;
92
- const isCurrentlyExiting = refs.current.isExiting,
93
- currentSendExitComplete = refs.current.sendExitComplete;
120
+ const isCurrentlyExiting = refs.current.isExiting;
121
+ const currentSendExitComplete = refs.current.sendExitComplete;
94
122
  let doAnimate2 = doAnimateRaw;
95
- isCurrentlyExiting && refs.current.frozenExitTarget && (doAnimate2 = refs.current.frozenExitTarget);
123
+ if (isCurrentlyExiting && refs.current.frozenExitTarget) {
124
+ doAnimate2 = refs.current.frozenExitTarget;
125
+ }
96
126
  const animationOptions2 = isCurrentlyExiting && currentSendExitComplete ? getAnimationOptions(props.transition ?? null, "exit") : passedOptions;
97
127
  try {
98
128
  const node = stateRef.current.host;
99
- if (refs.current.isFirstRender && (refs.current.lastDontAnimate = null, refs.current.lastDoAnimate = null), process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile" && (console.groupCollapsed(`[motion] animate (${JSON.stringify(getDiff(refs.current.lastDoAnimate, doAnimate2), null, 2)})`), console.info({
100
- props,
101
- componentState,
102
- doAnimate: doAnimate2,
103
- dontAnimate: dontAnimate2,
104
- animationOptions: animationOptions2,
105
- animationProps,
106
- lastDoAnimate: {
107
- ...refs.current.lastDoAnimate
108
- },
109
- lastDontAnimate: {
110
- ...refs.current.lastDontAnimate
111
- },
112
- isExiting,
113
- style,
114
- node
115
- }), console.groupCollapsed("trace >"), console.trace(), console.groupEnd(), console.groupEnd()), !(node instanceof HTMLElement)) return;
129
+ if (refs.current.isFirstRender) {
130
+ refs.current.lastDontAnimate = null;
131
+ refs.current.lastDoAnimate = null;
132
+ }
133
+ if (process.env.NODE_ENV === "development") {
134
+ if (props["debug"] && props["debug"] !== "profile") {
135
+ console.groupCollapsed(`[motion] animate (${JSON.stringify(getDiff(refs.current.lastDoAnimate, doAnimate2), null, 2)})`);
136
+ console.info({
137
+ props,
138
+ componentState,
139
+ doAnimate: doAnimate2,
140
+ dontAnimate: dontAnimate2,
141
+ animationOptions: animationOptions2,
142
+ animationProps,
143
+ lastDoAnimate: {
144
+ ...refs.current.lastDoAnimate
145
+ },
146
+ lastDontAnimate: {
147
+ ...refs.current.lastDontAnimate
148
+ },
149
+ isExiting,
150
+ style,
151
+ node
152
+ });
153
+ console.groupCollapsed(`trace >`);
154
+ console.trace();
155
+ console.groupEnd();
156
+ console.groupEnd();
157
+ }
158
+ }
159
+ if (!(node instanceof HTMLElement)) {
160
+ return;
161
+ }
116
162
  const prevDont = refs.current.lastDontAnimate;
117
- if (dontAnimate2) if (prevDont) {
118
- removeRemovedStyles(prevDont, dontAnimate2, node, doAnimate2);
119
- const changed = getDiff(prevDont, dontAnimate2);
120
- changed && Object.assign(node.style, changed);
121
- } else Object.assign(node.style, dontAnimate2);
163
+ if (dontAnimate2) {
164
+ if (prevDont) {
165
+ removeRemovedStyles(prevDont, dontAnimate2, node, doAnimate2);
166
+ const changed = getDiff(prevDont, dontAnimate2);
167
+ if (changed) {
168
+ Object.assign(node.style, changed);
169
+ }
170
+ } else {
171
+ Object.assign(node.style, dontAnimate2);
172
+ }
173
+ }
122
174
  if (doAnimate2) {
123
- if (prevDont) for (const key in prevDont) key in doAnimate2 && (node.style[key] = prevDont[key], refs.current.lastDoAnimate && (refs.current.lastDoAnimate[key] = prevDont[key]));
175
+ if (prevDont) {
176
+ for (const key in prevDont) {
177
+ if (key in doAnimate2) {
178
+ node.style[key] = prevDont[key];
179
+ if (refs.current.lastDoAnimate) {
180
+ refs.current.lastDoAnimate[key] = prevDont[key];
181
+ }
182
+ }
183
+ }
184
+ }
124
185
  const lastAnimated = refs.current.lastDoAnimate;
125
- lastAnimated && removeRemovedStyles(lastAnimated, doAnimate2, node, dontAnimate2);
186
+ if (lastAnimated) {
187
+ removeRemovedStyles(lastAnimated, doAnimate2, node, dontAnimate2);
188
+ }
126
189
  const diff = getDiff(refs.current.lastDoAnimate, doAnimate2);
127
190
  if (diff) {
128
- isCurrentlyExiting && !refs.current.frozenExitTarget && (refs.current.frozenExitTarget = {
129
- ...doAnimate2
130
- });
191
+ if (isCurrentlyExiting && !refs.current.frozenExitTarget) {
192
+ refs.current.frozenExitTarget = {
193
+ ...doAnimate2
194
+ };
195
+ }
131
196
  const isPopperPosition = node.hasAttribute("data-popper-animate-position");
132
197
  let midFlightValues = null;
133
198
  if (refs.current.controls) {
@@ -136,50 +201,88 @@ function createAnimations(animations) {
136
201
  midFlightValues = {};
137
202
  for (const key in diff) {
138
203
  const val = computed[key];
139
- val !== void 0 && val !== "" && (midFlightValues[key] = val);
204
+ if (val !== void 0 && val !== "") {
205
+ midFlightValues[key] = val;
206
+ }
140
207
  }
141
208
  } catch {}
142
- if (isCurrentlyExiting && refs.current.controls.stop(), midFlightValues) for (const key in midFlightValues) node.style[key] = midFlightValues[key];
209
+ if (isCurrentlyExiting) {
210
+ refs.current.controls.stop();
211
+ }
212
+ if (midFlightValues) {
213
+ for (const key in midFlightValues) {
214
+ ;
215
+ node.style[key] = midFlightValues[key];
216
+ }
217
+ }
143
218
  if (isPopperPosition) {
144
219
  const anims = node.getAnimations();
145
- for (const anim of anims) anim.cancel();
220
+ for (const anim of anims) {
221
+ anim.cancel();
222
+ }
146
223
  }
147
224
  }
148
225
  const fixedDiff = fixTransparentColors(diff, refs.current.lastDoAnimate, doAnimate2);
149
- midFlightValues?.transform && fixedDiff.transform && (fixedDiff.transform = [midFlightValues.transform, fixedDiff.transform]), startedControls = animate(scope.current, fixedDiff, animationOptions2), refs.current.controls = startedControls, refs.current.lastAnimateAt = Date.now();
226
+ if (midFlightValues?.transform && fixedDiff.transform) {
227
+ fixedDiff.transform = [midFlightValues.transform, fixedDiff.transform];
228
+ }
229
+ startedControls = animate(scope.current, fixedDiff, animationOptions2);
230
+ refs.current.controls = startedControls;
231
+ refs.current.lastAnimateAt = Date.now();
150
232
  }
151
233
  }
152
234
  refs.current.lastDontAnimate = dontAnimate2 ? {
153
235
  ...dontAnimate2
154
- } : {}, refs.current.lastDoAnimate = doAnimate2 ? {
236
+ } : {};
237
+ refs.current.lastDoAnimate = doAnimate2 ? {
155
238
  ...doAnimate2
156
239
  } : {};
157
240
  } finally {
158
- isCurrentlyExiting && currentSendExitComplete && (startedControls ? (refs.current.exitCompleteScheduled = !0, startedControls.finished.then(() => {
159
- refs.current.isExiting && currentSendExitComplete();
160
- }).catch(() => {
161
- refs.current.isExiting && currentSendExitComplete();
162
- })) : refs.current.exitCompleteScheduled || currentSendExitComplete());
241
+ if (isCurrentlyExiting && currentSendExitComplete) {
242
+ if (startedControls) {
243
+ refs.current.exitCompleteScheduled = true;
244
+ startedControls.finished.then(() => {
245
+ if (refs.current.isExiting) {
246
+ currentSendExitComplete();
247
+ }
248
+ }).catch(() => {
249
+ if (refs.current.isExiting) {
250
+ currentSendExitComplete();
251
+ }
252
+ });
253
+ } else if (!refs.current.exitCompleteScheduled) {
254
+ currentSendExitComplete();
255
+ }
256
+ }
163
257
  }
164
258
  };
165
- return useStyleEmitter?.((nextStyle, effectiveTransition) => {
259
+ useStyleEmitter?.((nextStyle, effectiveTransition) => {
166
260
  const animationProps2 = getMotionAnimatedProps(props, nextStyle, disableAnimation, refs.current.animationState, effectiveTransition);
167
261
  flushAnimation(animationProps2);
168
- }), useIsomorphicLayoutEffect(() => {
262
+ });
263
+ useIsomorphicLayoutEffect(() => {
169
264
  if (refs.current.isFirstRender) {
170
- if (refs.current.isFirstRender = !1, isHydrating) {
171
- doAnimate && Object.keys(doAnimate).length > 0 ? refs.current.lastDoAnimate = {
172
- ...doAnimate
173
- } : refs.current.lastDoAnimate = dontAnimate ? {
174
- ...dontAnimate
175
- } : {}, refs.current.lastDontAnimate = dontAnimate ? {
265
+ refs.current.isFirstRender = false;
266
+ if (isHydrating) {
267
+ if (doAnimate && Object.keys(doAnimate).length > 0) {
268
+ refs.current.lastDoAnimate = {
269
+ ...doAnimate
270
+ };
271
+ } else {
272
+ refs.current.lastDoAnimate = dontAnimate ? {
273
+ ...dontAnimate
274
+ } : {};
275
+ }
276
+ refs.current.lastDontAnimate = dontAnimate ? {
176
277
  ...dontAnimate
177
- } : {}, refs.current.lastAnimateAt = Date.now();
278
+ } : {};
279
+ refs.current.lastAnimateAt = Date.now();
178
280
  return;
179
281
  }
180
282
  refs.current.lastDontAnimate = dontAnimate ? {
181
283
  ...dontAnimate
182
- } : {}, refs.current.lastDoAnimate = doAnimate ? {
284
+ } : {};
285
+ refs.current.lastDoAnimate = doAnimate ? {
183
286
  ...doAnimate
184
287
  } : {};
185
288
  return;
@@ -189,16 +292,24 @@ function createAnimations(animations) {
189
292
  dontAnimate,
190
293
  animationOptions
191
294
  });
192
- }, [style, isExiting, disableAnimation]), process.env.NODE_ENV === "development" && props.debug && props.debug !== "profile" && (console.groupCollapsed("[motion] render"), console.info({
193
- style,
194
- doAnimate,
195
- dontAnimate,
196
- scope,
197
- animationOptions,
198
- isExiting,
199
- isFirstRender: refs.current.isFirstRender,
200
- animationProps
201
- }), console.groupEnd()), {
295
+ }, [style, isExiting, disableAnimation]);
296
+ if (process.env.NODE_ENV === "development") {
297
+ if (props["debug"] && props["debug"] !== "profile") {
298
+ console.groupCollapsed(`[motion] render`);
299
+ console.info({
300
+ style,
301
+ doAnimate,
302
+ dontAnimate,
303
+ scope,
304
+ animationOptions,
305
+ isExiting,
306
+ isFirstRender: refs.current.isFirstRender,
307
+ animationProps
308
+ });
309
+ console.groupEnd();
310
+ }
311
+ }
312
+ return {
202
313
  style: firstRenderStyle,
203
314
  ref: scope,
204
315
  render: "div"
@@ -216,16 +327,24 @@ function createAnimations(animations) {
216
327
  setValue(next, config = {
217
328
  type: "spring"
218
329
  }, onFinish) {
219
- if (config.type === "direct") MotionValueStrategy.set(motionValue, {
220
- type: "direct"
221
- }), motionValue.set(next), onFinish?.();else {
222
- if (MotionValueStrategy.set(motionValue, config), onFinish) {
223
- const unsubscribe = motionValue.on("change", value => {
224
- Math.abs(value - next) < 0.01 && (unsubscribe(), onFinish());
225
- });
226
- }
330
+ if (config.type === "direct") {
331
+ MotionValueStrategy.set(motionValue, {
332
+ type: "direct"
333
+ });
227
334
  motionValue.set(next);
335
+ onFinish?.();
336
+ return;
228
337
  }
338
+ MotionValueStrategy.set(motionValue, config);
339
+ if (onFinish) {
340
+ const prior = PendingMotionOnFinish.get(motionValue);
341
+ if (prior) {
342
+ PendingMotionOnFinish.delete(motionValue);
343
+ prior();
344
+ }
345
+ PendingMotionOnFinish.set(motionValue, onFinish);
346
+ }
347
+ motionValue.set(next);
229
348
  },
230
349
  stop() {
231
350
  motionValue.stop();
@@ -239,24 +358,49 @@ function createAnimations(animations) {
239
358
  useMotionValueEvent(instance, "change", onValue);
240
359
  },
241
360
  useAnimatedNumberStyle(val, getStyleProp) {
242
- const motionValue = val.getInstance(),
243
- getStyleRef = useRef(getStyleProp);
244
- return getStyleRef.current = getStyleProp, useMemo(() => ({
245
- getStyle: cur => getStyleRef.current(cur),
246
- motionValue
247
- }), []);
361
+ const motionValue = val.getInstance();
362
+ const getStyleRef = useRef(getStyleProp);
363
+ getStyleRef.current = getStyleProp;
364
+ return useMemo(() => {
365
+ return {
366
+ getStyle: cur => {
367
+ return getStyleRef.current(cur);
368
+ },
369
+ motionValue
370
+ };
371
+ }, []);
372
+ },
373
+ useAnimatedNumbersStyle(vals, getStyleProp) {
374
+ const motionValues = vals.map(v => v.getInstance());
375
+ const getStyleRef = useRef(getStyleProp);
376
+ getStyleRef.current = getStyleProp;
377
+ return useMemo(() => {
378
+ return {
379
+ getStyle: (...currentValues) => getStyleRef.current(...currentValues),
380
+ motionValues
381
+ };
382
+ }, []);
248
383
  }
249
384
  };
250
385
  function getMotionAnimatedProps(props, style, disable, animationState = "default", transitionOverride) {
251
- if (disable) return {
252
- dontAnimate: style
253
- };
386
+ if (disable) {
387
+ return {
388
+ dontAnimate: style
389
+ };
390
+ }
254
391
  const animationOptions = getAnimationOptions(transitionOverride ?? props.transition ?? null, animationState);
255
- let dontAnimate, doAnimate;
392
+ let dontAnimate;
393
+ let doAnimate;
256
394
  const animateOnly = props.animateOnly;
257
395
  for (const key in style) {
258
396
  const value = style[key];
259
- disableAnimationProps.has(key) || animateOnly && !animateOnly.includes(key) ? (dontAnimate ||= {}, dontAnimate[key] = value) : (doAnimate ||= {}, doAnimate[key] = value);
397
+ if (disableAnimationProps.has(key) || animateOnly && !animateOnly.includes(key)) {
398
+ dontAnimate ||= {};
399
+ dontAnimate[key] = value;
400
+ } else {
401
+ doAnimate ||= {};
402
+ doAnimate[key] = value;
403
+ }
260
404
  }
261
405
  return {
262
406
  dontAnimate,
@@ -267,104 +411,165 @@ function createAnimations(animations) {
267
411
  function getAnimationOptions(transitionProp, animationState = "default") {
268
412
  const normalized = normalizeTransition(transitionProp);
269
413
  let effectiveKey = getEffectiveAnimation(normalized, animationState);
270
- !effectiveKey && animationState === "default" && (effectiveKey = normalized.enter || normalized.exit || null);
414
+ if (!effectiveKey && animationState === "default") {
415
+ effectiveKey = normalized.enter || normalized.exit || null;
416
+ }
271
417
  const globalConfigOverride = normalized.config ? {
272
418
  ...normalized.config
273
419
  } : void 0;
274
- if (!effectiveKey && Object.keys(normalized.properties).length === 0 && !globalConfigOverride) return {};
275
- const defaultConfig = effectiveKey ? withInferredType(animations[effectiveKey]) : null,
276
- delay = normalized.delay,
277
- result = {};
278
- defaultConfig && Object.assign(result, defaultConfig), globalConfigOverride && (Object.assign(result, globalConfigOverride), result.type === void 0 && result.duration !== void 0 && result.damping === void 0 && result.stiffness === void 0 && result.mass === void 0 && (result.type = "tween")), delay && (result.delay = delay), (defaultConfig || globalConfigOverride || delay) && (result.default = {
279
- ...defaultConfig,
280
- ...globalConfigOverride,
281
- ...(delay ? {
282
- delay
283
- } : null)
284
- });
285
- for (const [propName, animationNameOrConfig] of Object.entries(normalized.properties)) if (typeof animationNameOrConfig == "string") result[propName] = withInferredType(animations[animationNameOrConfig]);else if (animationNameOrConfig && typeof animationNameOrConfig == "object") {
286
- const baseConfig = animationNameOrConfig.type ? withInferredType(animations[animationNameOrConfig.type]) : defaultConfig;
287
- result[propName] = {
288
- ...baseConfig,
289
- ...animationNameOrConfig
420
+ if (!effectiveKey && Object.keys(normalized.properties).length === 0 && !globalConfigOverride) {
421
+ return {};
422
+ }
423
+ const defaultConfig = effectiveKey ? withInferredType(animations[effectiveKey]) : null;
424
+ const delay = normalized.delay;
425
+ const result = {};
426
+ if (defaultConfig) {
427
+ Object.assign(result, defaultConfig);
428
+ }
429
+ if (globalConfigOverride) {
430
+ Object.assign(result, globalConfigOverride);
431
+ if (result.type === void 0 && result.duration !== void 0 && result.damping === void 0 && result.stiffness === void 0 && result.mass === void 0) {
432
+ result.type = "tween";
433
+ }
434
+ }
435
+ if (delay) {
436
+ result.delay = delay;
437
+ }
438
+ if (defaultConfig || globalConfigOverride || delay) {
439
+ result.default = {
440
+ ...defaultConfig,
441
+ ...globalConfigOverride,
442
+ ...(delay ? {
443
+ delay
444
+ } : null)
290
445
  };
291
446
  }
292
- convertMsToS(result), convertMsToS(result.default);
293
- for (const key in result) key !== "default" && typeof result[key] == "object" && convertMsToS(result[key]);
447
+ for (const [propName, animationNameOrConfig] of Object.entries(normalized.properties)) {
448
+ if (typeof animationNameOrConfig === "string") {
449
+ result[propName] = withInferredType(animations[animationNameOrConfig]);
450
+ } else if (animationNameOrConfig && typeof animationNameOrConfig === "object") {
451
+ const baseConfig = animationNameOrConfig.type ? withInferredType(animations[animationNameOrConfig.type]) : defaultConfig;
452
+ result[propName] = {
453
+ ...baseConfig,
454
+ ...animationNameOrConfig
455
+ };
456
+ }
457
+ }
458
+ convertMsToS(result);
459
+ convertMsToS(result.default);
460
+ for (const key in result) {
461
+ if (key !== "default" && typeof result[key] === "object") {
462
+ convertMsToS(result[key]);
463
+ }
464
+ }
294
465
  return result;
295
466
  }
296
467
  }
297
468
  function withInferredType(config) {
298
- return config ? {
299
- type: config.duration !== void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0 ? "tween" : "spring",
469
+ if (!config) {
470
+ return {
471
+ type: "spring"
472
+ };
473
+ }
474
+ const isTimingBased = config.duration !== void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0;
475
+ return {
476
+ type: isTimingBased ? "tween" : "spring",
300
477
  ...config
301
- } : {
302
- type: "spring"
303
478
  };
304
479
  }
305
480
  function convertMsToS(config) {
306
- config && (typeof config.delay == "number" && (config.delay = config.delay / 1e3), typeof config.duration == "number" && (config.type === "tween" || config.type === void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0) && (config.duration = config.duration / 1e3));
481
+ if (!config) return;
482
+ if (typeof config.delay === "number") config.delay = config.delay / 1e3;
483
+ if (typeof config.duration === "number") {
484
+ const isTimingBased = config.type === "tween" || config.type === void 0 && config.damping === void 0 && config.stiffness === void 0 && config.mass === void 0;
485
+ if (isTimingBased) {
486
+ config.duration = config.duration / 1e3;
487
+ }
488
+ }
307
489
  }
308
490
  function removeRemovedStyles(prev, next, node, dontClearIfIn) {
309
- for (const key in prev) if (!(key in next)) {
310
- if (dontClearIfIn && key in dontClearIfIn) continue;
311
- node.style[key] = "";
491
+ for (const key in prev) {
492
+ if (!(key in next)) {
493
+ if (dontClearIfIn && key in dontClearIfIn) {
494
+ continue;
495
+ }
496
+ node.style[key] = "";
497
+ }
312
498
  }
313
499
  }
314
- const disableAnimationProps = /* @__PURE__ */new Set(["alignContent", "alignItems", "boxSizing", "contain", "containerType", "display", "flexBasis", "flexDirection", "fontFamily", "justifyContent", "overflow", "overflowX", "overflowY", "pointerEvents", "position", "textWrap", "userSelect"]),
315
- MotionView = createMotionView("div"),
316
- MotionText = createMotionView("span");
500
+ const disableAnimationProps = /* @__PURE__ */new Set(["alignContent", "alignItems", "boxSizing", "contain", "containerType", "display", "flexBasis", "flexDirection", "fontFamily", "justifyContent", "overflow", "overflowX", "overflowY", "pointerEvents", "position", "textWrap", "userSelect"]);
501
+ const MotionView = createMotionView("div");
502
+ const MotionText = createMotionView("span");
317
503
  function createMotionView(defaultTag) {
318
- const isText = defaultTag === "span",
319
- Component = forwardRef((propsIn, ref) => {
320
- const {
321
- forwardedRef,
322
- animation,
323
- render = defaultTag,
324
- style,
325
- ...propsRest
326
- } = propsIn,
327
- [scope, animate] = useAnimateSSRSafe(),
328
- hostRef = useRef(null),
329
- composedRefs = useComposedRefs(forwardedRef, ref, hostRef, scope),
330
- stateRef = useRef(null);
331
- stateRef.current || (stateRef.current = {
504
+ const isText = defaultTag === "span";
505
+ const Component = forwardRef((propsIn, ref) => {
506
+ const {
507
+ forwardedRef,
508
+ animation,
509
+ render = defaultTag,
510
+ style,
511
+ ...propsRest
512
+ } = propsIn;
513
+ const [scope, animate] = useAnimateSSRSafe();
514
+ const hostRef = useRef(null);
515
+ const composedRefs = useComposedRefs(forwardedRef, ref, hostRef, scope);
516
+ const stateRef = useRef(null);
517
+ if (!stateRef.current) {
518
+ stateRef.current = {
332
519
  get host() {
333
520
  return hostRef.current;
334
521
  }
522
+ };
523
+ }
524
+ const [_, state] = useThemeWithState({});
525
+ const styles = Array.isArray(style) ? style : [style];
526
+ const [animatedStyle, nonAnimatedStyles] = (() => {
527
+ let animatedStyle2;
528
+ const nonAnimatedStyles2 = [];
529
+ for (const style2 of styles) {
530
+ if (style2.getStyle) {
531
+ animatedStyle2 = style2;
532
+ } else {
533
+ nonAnimatedStyles2.push(style2);
534
+ }
535
+ }
536
+ return [animatedStyle2, nonAnimatedStyles2];
537
+ })();
538
+ function getProps(props2) {
539
+ const out = getSplitStyles(props2, isText ? Text.staticConfig : View.staticConfig, state?.theme, state?.name, {
540
+ unmounted: false
541
+ }, {
542
+ isAnimated: false,
543
+ noClass: true,
544
+ resolveValues: "auto"
335
545
  });
336
- const [_, state] = useThemeWithState({}),
337
- styles = Array.isArray(style) ? style : [style],
338
- [animatedStyle, nonAnimatedStyles] = (() => {
339
- let animatedStyle2;
340
- const nonAnimatedStyles2 = [];
341
- for (const style2 of styles) style2.getStyle ? animatedStyle2 = style2 : nonAnimatedStyles2.push(style2);
342
- return [animatedStyle2, nonAnimatedStyles2];
343
- })();
344
- function getProps(props2) {
345
- const out = getSplitStyles(props2, isText ? Text.staticConfig : View.staticConfig, state?.theme, state?.name, {
346
- unmounted: !1
347
- }, {
348
- isAnimated: !1,
349
- noClass: !0,
350
- resolveValues: "auto"
351
- });
352
- return out ? (out.viewProps.style && (fixStyles(out.viewProps.style), styleToCSS(out.viewProps.style)), out.viewProps) : {};
546
+ if (!out) {
547
+ return {};
353
548
  }
354
- const props = getProps({
355
- ...propsRest,
356
- style: nonAnimatedStyles
357
- }),
358
- Element = render || "div",
359
- transformedProps = hooks.usePropsTransform?.(render, props, stateRef, !1);
360
- return useEffect(() => {
361
- if (animatedStyle) return animatedStyle.motionValue.on("change", value => {
362
- const nextStyle = animatedStyle.getStyle(value),
363
- animationConfig = MotionValueStrategy.get(animatedStyle.motionValue),
364
- node = hostRef.current,
365
- webStyle = getProps({
366
- style: nextStyle
367
- }).style;
549
+ if (out.viewProps.style) {
550
+ fixStyles(out.viewProps.style);
551
+ styleToCSS(out.viewProps.style);
552
+ }
553
+ return out.viewProps;
554
+ }
555
+ const props = getProps({
556
+ ...propsRest,
557
+ style: nonAnimatedStyles
558
+ });
559
+ const Element = render || "div";
560
+ const transformedProps = hooks.usePropsTransform?.(render, props, stateRef, false);
561
+ useEffect(() => {
562
+ if (!animatedStyle) return;
563
+ if (animatedStyle.motionValues) {
564
+ const mvs = animatedStyle.motionValues;
565
+ const unsubs = mvs.map(mv => mv.on("change", () => {
566
+ const currentValues = mvs.map(v => v.get());
567
+ const nextStyle = animatedStyle.getStyle(...currentValues);
568
+ const animationConfig = MotionValueStrategy.get(mv);
569
+ const node = hostRef.current;
570
+ const webStyle = getProps({
571
+ style: nextStyle
572
+ }).style;
368
573
  if (webStyle && node instanceof HTMLElement) {
369
574
  const motionAnimationConfig = animationConfig?.type === "timing" ? {
370
575
  type: "tween",
@@ -376,37 +581,79 @@ function createMotionView(defaultTag) {
376
581
  type: "spring",
377
582
  ...animationConfig
378
583
  };
379
- animate(node, webStyle, motionAnimationConfig);
584
+ const controls = animate(node, webStyle, motionAnimationConfig);
585
+ settlePendingMotionOnFinish(mv, controls);
380
586
  }
381
- });
382
- }, [animatedStyle]), /* @__PURE__ */jsx(Element, {
383
- ...transformedProps,
384
- ref: composedRefs
587
+ }));
588
+ return () => unsubs.forEach(fn => fn());
589
+ }
590
+ if (!animatedStyle.motionValue) return;
591
+ return animatedStyle.motionValue.on("change", value => {
592
+ const nextStyle = animatedStyle.getStyle(value);
593
+ const animationConfig = MotionValueStrategy.get(animatedStyle.motionValue);
594
+ const node = hostRef.current;
595
+ const webStyle = getProps({
596
+ style: nextStyle
597
+ }).style;
598
+ if (webStyle && node instanceof HTMLElement) {
599
+ const motionAnimationConfig = animationConfig?.type === "timing" ? {
600
+ type: "tween",
601
+ duration: (animationConfig?.duration || 0) / 1e3
602
+ } : animationConfig?.type === "direct" ? {
603
+ type: "tween",
604
+ duration: 0
605
+ } : {
606
+ type: "spring",
607
+ ...animationConfig
608
+ };
609
+ const controls = animate(node, webStyle, motionAnimationConfig);
610
+ settlePendingMotionOnFinish(animatedStyle.motionValue, controls);
611
+ }
385
612
  });
613
+ }, [animatedStyle]);
614
+ return /* @__PURE__ */jsx(Element, {
615
+ ...transformedProps,
616
+ ref: composedRefs
386
617
  });
387
- return Component.acceptRenderProp = !0, Component;
618
+ });
619
+ Component["acceptRenderProp"] = true;
620
+ return Component;
388
621
  }
389
622
  function getDiff(previous, next) {
390
- if (!previous) return next;
623
+ if (!previous) {
624
+ return next;
625
+ }
391
626
  let diff = null;
392
- for (const key in next) next[key] !== previous[key] && (diff ||= {}, diff[key] = next[key]);
627
+ for (const key in next) {
628
+ if (next[key] !== previous[key]) {
629
+ diff ||= {};
630
+ diff[key] = next[key];
631
+ }
632
+ }
393
633
  return diff;
394
634
  }
395
635
  function fixTransparentColors(diff, previous, next) {
396
636
  let result = diff;
397
- for (const key in diff) if (diff[key] === "transparent") {
398
- let fixed = "rgba(0, 0, 0, 0)";
399
- const candidates = [previous?.[key], next?.[key]];
400
- for (const candidate of candidates) if (typeof candidate == "string" && candidate !== "transparent") {
401
- const rgbaMatch = candidate.match(/^rgba?\(([^,]+),\s*([^,]+),\s*([^,)]+)/);
402
- if (rgbaMatch) {
403
- fixed = `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, 0)`;
404
- break;
637
+ for (const key in diff) {
638
+ if (diff[key] === "transparent") {
639
+ let fixed = "rgba(0, 0, 0, 0)";
640
+ const candidates = [previous?.[key], next?.[key]];
641
+ for (const candidate of candidates) {
642
+ if (typeof candidate === "string" && candidate !== "transparent") {
643
+ const rgbaMatch = candidate.match(/^rgba?\(([^,]+),\s*([^,]+),\s*([^,)]+)/);
644
+ if (rgbaMatch) {
645
+ fixed = `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, 0)`;
646
+ break;
647
+ }
648
+ }
649
+ }
650
+ if (result === diff) {
651
+ result = {
652
+ ...diff
653
+ };
405
654
  }
655
+ result[key] = fixed;
406
656
  }
407
- result === diff && (result = {
408
- ...diff
409
- }), result[key] = fixed;
410
657
  }
411
658
  return result;
412
659
  }