@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.
- package/dist/cjs/createAnimations.cjs +503 -254
- package/dist/cjs/createAnimations.native.js +593 -319
- package/dist/cjs/createAnimations.native.js.map +1 -1
- package/dist/cjs/index.cjs +7 -5
- package/dist/cjs/index.native.js +21 -13
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/polyfill.cjs +3 -1
- package/dist/cjs/polyfill.native.js +3 -1
- package/dist/cjs/polyfill.native.js.map +1 -1
- package/dist/esm/createAnimations.mjs +473 -226
- package/dist/esm/createAnimations.mjs.map +1 -1
- package/dist/esm/createAnimations.native.js +563 -291
- package/dist/esm/createAnimations.native.js.map +1 -1
- package/dist/esm/index.native.js +9 -3
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/polyfill.mjs +3 -1
- package/dist/esm/polyfill.mjs.map +1 -1
- package/dist/esm/polyfill.native.js +3 -1
- package/dist/esm/polyfill.native.js.map +1 -1
- package/package.json +5 -5
- package/src/createAnimations.tsx +104 -18
- package/types/createAnimations.d.ts.map +2 -2
|
@@ -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
|
|
7
|
+
const isServer = typeof window === "undefined";
|
|
8
8
|
function useAnimateSSRSafe() {
|
|
9
|
-
|
|
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:
|
|
28
|
+
isReactNative: false,
|
|
19
29
|
inputStyle: "css",
|
|
20
30
|
outputStyle: "inline",
|
|
21
|
-
avoidReRenders:
|
|
31
|
+
avoidReRenders: true,
|
|
22
32
|
animations,
|
|
23
33
|
usePresence,
|
|
24
34
|
ResetPresence,
|
|
25
35
|
onMount() {
|
|
26
|
-
isHydratingGlobal =
|
|
36
|
+
isHydratingGlobal = false;
|
|
37
|
+
hydratingComponents.forEach(cb => cb());
|
|
27
38
|
},
|
|
28
39
|
useAnimations: animationProps => {
|
|
29
|
-
isHydratingGlobal === void 0 && !getConfig().settings.disableSSR
|
|
40
|
+
if (isHydratingGlobal === void 0 && !getConfig().settings.disableSSR) {
|
|
41
|
+
isHydratingGlobal = true;
|
|
42
|
+
}
|
|
30
43
|
const {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
refs.current.isExiting = isExiting
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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(() =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
120
|
+
const isCurrentlyExiting = refs.current.isExiting;
|
|
121
|
+
const currentSendExitComplete = refs.current.sendExitComplete;
|
|
94
122
|
let doAnimate2 = doAnimateRaw;
|
|
95
|
-
isCurrentlyExiting && 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
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
|
129
|
-
|
|
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 !== ""
|
|
204
|
+
if (val !== void 0 && val !== "") {
|
|
205
|
+
midFlightValues[key] = val;
|
|
206
|
+
}
|
|
140
207
|
}
|
|
141
208
|
} catch {}
|
|
142
|
-
if (isCurrentlyExiting
|
|
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)
|
|
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
|
|
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
|
-
} : {}
|
|
236
|
+
} : {};
|
|
237
|
+
refs.current.lastDoAnimate = doAnimate2 ? {
|
|
155
238
|
...doAnimate2
|
|
156
239
|
} : {};
|
|
157
240
|
} finally {
|
|
158
|
-
isCurrentlyExiting && currentSendExitComplete
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
|
|
259
|
+
useStyleEmitter?.((nextStyle, effectiveTransition) => {
|
|
166
260
|
const animationProps2 = getMotionAnimatedProps(props, nextStyle, disableAnimation, refs.current.animationState, effectiveTransition);
|
|
167
261
|
flushAnimation(animationProps2);
|
|
168
|
-
})
|
|
262
|
+
});
|
|
263
|
+
useIsomorphicLayoutEffect(() => {
|
|
169
264
|
if (refs.current.isFirstRender) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
} : {}
|
|
278
|
+
} : {};
|
|
279
|
+
refs.current.lastAnimateAt = Date.now();
|
|
178
280
|
return;
|
|
179
281
|
}
|
|
180
282
|
refs.current.lastDontAnimate = dontAnimate ? {
|
|
181
283
|
...dontAnimate
|
|
182
|
-
} : {}
|
|
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])
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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")
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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)
|
|
252
|
-
|
|
253
|
-
|
|
386
|
+
if (disable) {
|
|
387
|
+
return {
|
|
388
|
+
dontAnimate: style
|
|
389
|
+
};
|
|
390
|
+
}
|
|
254
391
|
const animationOptions = getAnimationOptions(transitionOverride ?? props.transition ?? null, animationState);
|
|
255
|
-
let dontAnimate
|
|
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)
|
|
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"
|
|
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)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
|
|
293
|
-
|
|
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
|
-
|
|
299
|
-
|
|
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
|
-
|
|
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)
|
|
310
|
-
if (
|
|
311
|
-
|
|
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
|
-
|
|
316
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
-
|
|
337
|
-
|
|
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
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
618
|
+
});
|
|
619
|
+
Component["acceptRenderProp"] = true;
|
|
620
|
+
return Component;
|
|
388
621
|
}
|
|
389
622
|
function getDiff(previous, next) {
|
|
390
|
-
if (!previous)
|
|
623
|
+
if (!previous) {
|
|
624
|
+
return next;
|
|
625
|
+
}
|
|
391
626
|
let diff = null;
|
|
392
|
-
for (const key in next)
|
|
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)
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
}
|