@helsenorge/designsystem-react 10.0.2 → 10.2.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/AnchorLink.js +2 -2
- package/AnchorLink.js.map +1 -1
- package/Avatar.js +2 -2
- package/Avatar.js.map +1 -1
- package/Badge.js +3 -3
- package/Badge.js.map +1 -1
- package/Button.js +4 -4
- package/Button.js.map +1 -1
- package/CHANGELOG.md +38 -0
- package/Checkbox.js +2 -2
- package/Checkbox.js.map +1 -1
- package/Close.js +2 -2
- package/Close.js.map +1 -1
- package/ErrorBoundary.js +2 -2
- package/ErrorBoundary.js.map +1 -1
- package/Expander.js +2 -2
- package/Expander.js.map +1 -1
- package/FormGroup.js +12 -12
- package/FormGroup.js.map +1 -1
- package/FormLayout.js +3 -3
- package/FormLayout.js.map +1 -1
- package/HelpBubble.js +2 -2
- package/HelpBubble.js.map +1 -1
- package/HighlightPanel.js +2 -2
- package/HighlightPanel.js.map +1 -1
- package/Icon.js +3 -3
- package/Icon.js.map +1 -1
- package/Illustration.js +3 -3
- package/Illustration.js.map +1 -1
- package/Input.js +2 -2
- package/Input.js.map +1 -1
- package/Label.js +8 -8
- package/Label.js.map +1 -1
- package/LazyIcon.js +1 -1
- package/LazyIllustration.js +3 -3
- package/LazyIllustration.js.map +1 -1
- package/LinkList.js +6 -6
- package/LinkList.js.map +1 -1
- package/ListHeader.js +7 -7
- package/ListHeader.js.map +1 -1
- package/Panel.js +2 -2
- package/Panel.js.map +1 -1
- package/PopOver.js +2 -2
- package/PopOver.js.map +1 -1
- package/RadioButton.js +2 -2
- package/RadioButton.js.map +1 -1
- package/Select.js +2 -2
- package/Select.js.map +1 -1
- package/Slider.js +3 -3
- package/Slider.js.map +1 -1
- package/Spacer.js +2 -2
- package/Spacer.js.map +1 -1
- package/StatusDot.js +1 -1
- package/StepButtons.js +4 -4
- package/StepButtons.js.map +1 -1
- package/TabList.js +4 -4
- package/TabList.js.map +1 -1
- package/Table.js +2 -2
- package/Table.js.map +1 -1
- package/TableBody.js +2 -2
- package/TableBody.js.map +1 -1
- package/TableExpandedRow.js +2 -2
- package/TableExpandedRow.js.map +1 -1
- package/TableHead.js +2 -2
- package/TableHead.js.map +1 -1
- package/TableRow.js +2 -2
- package/TableRow.js.map +1 -1
- package/Textarea.js +2 -2
- package/Textarea.js.map +1 -1
- package/Title.js +2 -2
- package/Title.js.map +1 -1
- package/TooltipWord.js +2 -2
- package/TooltipWord.js.map +1 -1
- package/Trigger.js +3 -3
- package/Trigger.js.map +1 -1
- package/components/Button/styles.module.scss +5 -0
- package/components/DictionaryTrigger/index.js +2 -2
- package/components/DictionaryTrigger/index.js.map +1 -1
- package/components/Drawer/Drawer.d.ts +41 -0
- package/components/Drawer/Drawer.test.d.ts +1 -0
- package/components/Drawer/index.d.ts +3 -0
- package/components/Drawer/index.js +350 -0
- package/components/Drawer/index.js.map +1 -0
- package/components/Drawer/styles.module.scss +127 -0
- package/components/Drawer/styles.module.scss.d.ts +16 -0
- package/components/Dropdown/index.js +3 -3
- package/components/Dropdown/index.js.map +1 -1
- package/components/Duolist/index.js +4 -4
- package/components/Duolist/index.js.map +1 -1
- package/components/ExpanderHierarchy/index.js +5 -5
- package/components/ExpanderHierarchy/index.js.map +1 -1
- package/components/ExpanderList/index.js +8 -8
- package/components/ExpanderList/index.js.map +1 -1
- package/components/HelpQuestion/index.js +2 -2
- package/components/HelpQuestion/index.js.map +1 -1
- package/components/HighlightPanel/styles.module.scss +4 -36
- package/components/HighlightPanel/styles.module.scss.d.ts +1 -2
- package/components/Icons/EuropeanHealthCard.js +1 -1
- package/components/Icons/GroupTwins.js +1 -1
- package/components/Icons/Inbox.js +1 -1
- package/components/Icons/LawBook.js +1 -1
- package/components/Icons/PersonCancel.js +1 -1
- package/components/Icons/PersonWithBrain.js +1 -1
- package/components/Icons/Puzzle.js +1 -1
- package/components/Icons/Snapchat.js +1 -1
- package/components/Illustrations/IllustrationNames.d.ts +1 -1
- package/components/Illustrations/IllustrationNames.js +4 -2
- package/components/Illustrations/IllustrationNames.js.map +1 -1
- package/components/Illustrations/ReadLetters.d.ts +9 -0
- package/components/Illustrations/ReadLetters.js +11 -0
- package/components/Illustrations/ReadLetters.js.map +1 -0
- package/components/Illustrations/ReadLettersMedium.d.ts +4 -0
- package/components/Illustrations/ReadLettersMedium.js +110 -0
- package/components/Illustrations/ReadLettersMedium.js.map +1 -0
- package/components/Illustrations/Support2.d.ts +9 -0
- package/components/Illustrations/Support2.js +11 -0
- package/components/Illustrations/Support2.js.map +1 -0
- package/components/Illustrations/Support2Medium.d.ts +4 -0
- package/components/Illustrations/Support2Medium.js +232 -0
- package/components/Illustrations/Support2Medium.js.map +1 -0
- package/components/Label/styles.module.scss +16 -12
- package/components/Label/styles.module.scss.d.ts +3 -1
- package/components/List/styles.module.scss +7 -7
- package/components/Modal/index.js +71 -82
- package/components/Modal/index.js.map +1 -1
- package/components/Modal/styles.module.scss +12 -6
- package/components/NotificationPanel/index.js +3 -3
- package/components/NotificationPanel/index.js.map +1 -1
- package/components/PanelList/index.js +5 -5
- package/components/PanelList/index.js.map +1 -1
- package/components/PopMenu/index.js +5 -5
- package/components/PopMenu/index.js.map +1 -1
- package/components/Portal/index.js +3 -3
- package/components/Portal/index.js.map +1 -1
- package/components/PromoPanel/index.js +2 -2
- package/components/PromoPanel/index.js.map +1 -1
- package/components/StickyNote/index.js +12 -6
- package/components/StickyNote/index.js.map +1 -1
- package/components/Tabs/Tabs.d.ts +2 -0
- package/components/Tabs/index.js +8 -4
- package/components/Tabs/index.js.map +1 -1
- package/components/TagList/index.js +2 -2
- package/components/TagList/index.js.map +1 -1
- package/components/Tile/index.js +6 -6
- package/components/Tile/index.js.map +1 -1
- package/components/Toggle/index.js +3 -3910
- package/components/Toggle/index.js.map +1 -1
- package/components/Tooltip/index.js +2 -2
- package/components/Tooltip/index.js.map +1 -1
- package/components/Validation/index.js +6 -6
- package/components/Validation/index.js.map +1 -1
- package/constants.d.ts +1 -0
- package/constants.js +1 -0
- package/constants.js.map +1 -1
- package/hoc/withBreakpoint/withBreakpoint.js +2 -2
- package/hoc/withBreakpoint/withBreakpoint.js.map +1 -1
- package/hooks/useBreakpoint.d.ts +0 -4
- package/hooks/useBreakpoint.js +23 -18
- package/hooks/useBreakpoint.js.map +1 -1
- package/hooks/useEventListenerState.js +3 -3
- package/hooks/useEventListenerState.js.map +1 -1
- package/hooks/useOutsideEvent.d.ts +4 -4
- package/hooks/useOutsideEvent.js +5 -4
- package/hooks/useOutsideEvent.js.map +1 -1
- package/hooks/useReturnFocusOnUnmount.d.ts +5 -0
- package/hooks/useReturnFocusOnUnmount.js +20 -0
- package/hooks/useReturnFocusOnUnmount.js.map +1 -0
- package/package.json +1 -1
- package/scss/_breakpoints.scss +6 -0
- package/scss/_font-mixins.scss +55 -0
- package/scss/typography.module.scss +24 -0
- package/scss/typography.module.scss.d.ts +6 -0
- package/scss/typography.stories.tsx +24 -0
- package/theme/index.js +2 -2
- package/use-animate.js +3952 -0
- package/use-animate.js.map +1 -0
- package/utils/accessibility.d.ts +1 -0
- package/utils/accessibility.js +6 -1
- package/utils/accessibility.js.map +1 -1
- package/utils/component.js +4 -4
- package/utils/component.js.map +1 -1
package/use-animate.js
ADDED
|
@@ -0,0 +1,3952 @@
|
|
|
1
|
+
import { useRef, useEffect } from "react";
|
|
2
|
+
function useConstant(init) {
|
|
3
|
+
const ref = useRef(null);
|
|
4
|
+
if (ref.current === null) {
|
|
5
|
+
ref.current = init();
|
|
6
|
+
}
|
|
7
|
+
return ref.current;
|
|
8
|
+
}
|
|
9
|
+
const isBrowser = typeof window !== "undefined";
|
|
10
|
+
const noop = /* @__NO_SIDE_EFFECTS__ */ (any) => any;
|
|
11
|
+
let warning = noop;
|
|
12
|
+
let invariant = noop;
|
|
13
|
+
if (process.env.NODE_ENV !== "production") {
|
|
14
|
+
warning = (check, message) => {
|
|
15
|
+
if (!check && typeof console !== "undefined") {
|
|
16
|
+
console.warn(message);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
invariant = (check, message) => {
|
|
20
|
+
if (!check) {
|
|
21
|
+
throw new Error(message);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const MotionGlobalConfig = {
|
|
26
|
+
useManualTiming: false
|
|
27
|
+
};
|
|
28
|
+
function createRenderStep(runNextFrame) {
|
|
29
|
+
let thisFrame = /* @__PURE__ */ new Set();
|
|
30
|
+
let nextFrame = /* @__PURE__ */ new Set();
|
|
31
|
+
let isProcessing = false;
|
|
32
|
+
let flushNextFrame = false;
|
|
33
|
+
const toKeepAlive = /* @__PURE__ */ new WeakSet();
|
|
34
|
+
let latestFrameData = {
|
|
35
|
+
delta: 0,
|
|
36
|
+
timestamp: 0,
|
|
37
|
+
isProcessing: false
|
|
38
|
+
};
|
|
39
|
+
function triggerCallback(callback) {
|
|
40
|
+
if (toKeepAlive.has(callback)) {
|
|
41
|
+
step.schedule(callback);
|
|
42
|
+
runNextFrame();
|
|
43
|
+
}
|
|
44
|
+
callback(latestFrameData);
|
|
45
|
+
}
|
|
46
|
+
const step = {
|
|
47
|
+
/**
|
|
48
|
+
* Schedule a process to run on the next frame.
|
|
49
|
+
*/
|
|
50
|
+
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
51
|
+
const addToCurrentFrame = immediate && isProcessing;
|
|
52
|
+
const queue = addToCurrentFrame ? thisFrame : nextFrame;
|
|
53
|
+
if (keepAlive)
|
|
54
|
+
toKeepAlive.add(callback);
|
|
55
|
+
if (!queue.has(callback))
|
|
56
|
+
queue.add(callback);
|
|
57
|
+
return callback;
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* Cancel the provided callback from running on the next frame.
|
|
61
|
+
*/
|
|
62
|
+
cancel: (callback) => {
|
|
63
|
+
nextFrame.delete(callback);
|
|
64
|
+
toKeepAlive.delete(callback);
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* Execute all schedule callbacks.
|
|
68
|
+
*/
|
|
69
|
+
process: (frameData2) => {
|
|
70
|
+
latestFrameData = frameData2;
|
|
71
|
+
if (isProcessing) {
|
|
72
|
+
flushNextFrame = true;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
isProcessing = true;
|
|
76
|
+
[thisFrame, nextFrame] = [nextFrame, thisFrame];
|
|
77
|
+
thisFrame.forEach(triggerCallback);
|
|
78
|
+
thisFrame.clear();
|
|
79
|
+
isProcessing = false;
|
|
80
|
+
if (flushNextFrame) {
|
|
81
|
+
flushNextFrame = false;
|
|
82
|
+
step.process(frameData2);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
return step;
|
|
87
|
+
}
|
|
88
|
+
const stepsOrder = [
|
|
89
|
+
"read",
|
|
90
|
+
// Read
|
|
91
|
+
"resolveKeyframes",
|
|
92
|
+
// Write/Read/Write/Read
|
|
93
|
+
"update",
|
|
94
|
+
// Compute
|
|
95
|
+
"preRender",
|
|
96
|
+
// Compute
|
|
97
|
+
"render",
|
|
98
|
+
// Write
|
|
99
|
+
"postRender"
|
|
100
|
+
// Compute
|
|
101
|
+
];
|
|
102
|
+
const maxElapsed = 40;
|
|
103
|
+
function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
|
|
104
|
+
let runNextFrame = false;
|
|
105
|
+
let useDefaultElapsed = true;
|
|
106
|
+
const state = {
|
|
107
|
+
delta: 0,
|
|
108
|
+
timestamp: 0,
|
|
109
|
+
isProcessing: false
|
|
110
|
+
};
|
|
111
|
+
const flagRunNextFrame = () => runNextFrame = true;
|
|
112
|
+
const steps = stepsOrder.reduce((acc, key) => {
|
|
113
|
+
acc[key] = createRenderStep(flagRunNextFrame);
|
|
114
|
+
return acc;
|
|
115
|
+
}, {});
|
|
116
|
+
const { read, resolveKeyframes, update, preRender, render, postRender } = steps;
|
|
117
|
+
const processBatch = () => {
|
|
118
|
+
const timestamp = performance.now();
|
|
119
|
+
runNextFrame = false;
|
|
120
|
+
state.delta = useDefaultElapsed ? 1e3 / 60 : Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);
|
|
121
|
+
state.timestamp = timestamp;
|
|
122
|
+
state.isProcessing = true;
|
|
123
|
+
read.process(state);
|
|
124
|
+
resolveKeyframes.process(state);
|
|
125
|
+
update.process(state);
|
|
126
|
+
preRender.process(state);
|
|
127
|
+
render.process(state);
|
|
128
|
+
postRender.process(state);
|
|
129
|
+
state.isProcessing = false;
|
|
130
|
+
if (runNextFrame && allowKeepAlive) {
|
|
131
|
+
useDefaultElapsed = false;
|
|
132
|
+
scheduleNextBatch(processBatch);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const wake = () => {
|
|
136
|
+
runNextFrame = true;
|
|
137
|
+
useDefaultElapsed = true;
|
|
138
|
+
if (!state.isProcessing) {
|
|
139
|
+
scheduleNextBatch(processBatch);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
const schedule = stepsOrder.reduce((acc, key) => {
|
|
143
|
+
const step = steps[key];
|
|
144
|
+
acc[key] = (process2, keepAlive = false, immediate = false) => {
|
|
145
|
+
if (!runNextFrame)
|
|
146
|
+
wake();
|
|
147
|
+
return step.schedule(process2, keepAlive, immediate);
|
|
148
|
+
};
|
|
149
|
+
return acc;
|
|
150
|
+
}, {});
|
|
151
|
+
const cancel = (process2) => {
|
|
152
|
+
for (let i = 0; i < stepsOrder.length; i++) {
|
|
153
|
+
steps[stepsOrder[i]].cancel(process2);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
return { schedule, cancel, state, steps };
|
|
157
|
+
}
|
|
158
|
+
const { schedule: frame, cancel: cancelFrame, state: frameData } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
|
|
159
|
+
const featureProps = {
|
|
160
|
+
animation: [
|
|
161
|
+
"animate",
|
|
162
|
+
"variants",
|
|
163
|
+
"whileHover",
|
|
164
|
+
"whileTap",
|
|
165
|
+
"exit",
|
|
166
|
+
"whileInView",
|
|
167
|
+
"whileFocus",
|
|
168
|
+
"whileDrag"
|
|
169
|
+
],
|
|
170
|
+
exit: ["exit"],
|
|
171
|
+
drag: ["drag", "dragControls"],
|
|
172
|
+
focus: ["whileFocus"],
|
|
173
|
+
hover: ["whileHover", "onHoverStart", "onHoverEnd"],
|
|
174
|
+
tap: ["whileTap", "onTap", "onTapStart", "onTapCancel"],
|
|
175
|
+
pan: ["onPan", "onPanStart", "onPanSessionStart", "onPanEnd"],
|
|
176
|
+
inView: ["whileInView", "onViewportEnter", "onViewportLeave"],
|
|
177
|
+
layout: ["layout", "layoutId"]
|
|
178
|
+
};
|
|
179
|
+
const featureDefinitions = {};
|
|
180
|
+
for (const key in featureProps) {
|
|
181
|
+
featureDefinitions[key] = {
|
|
182
|
+
isEnabled: (props) => featureProps[key].some((name) => !!props[name])
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const warned = /* @__PURE__ */ new Set();
|
|
186
|
+
function warnOnce(condition, message, element) {
|
|
187
|
+
if (condition || warned.has(message))
|
|
188
|
+
return;
|
|
189
|
+
console.warn(message);
|
|
190
|
+
warned.add(message);
|
|
191
|
+
}
|
|
192
|
+
function isVariantLabel(v) {
|
|
193
|
+
return typeof v === "string" || Array.isArray(v);
|
|
194
|
+
}
|
|
195
|
+
function isAnimationControls(v) {
|
|
196
|
+
return v !== null && typeof v === "object" && typeof v.start === "function";
|
|
197
|
+
}
|
|
198
|
+
const variantPriorityOrder = [
|
|
199
|
+
"animate",
|
|
200
|
+
"whileInView",
|
|
201
|
+
"whileFocus",
|
|
202
|
+
"whileHover",
|
|
203
|
+
"whileTap",
|
|
204
|
+
"whileDrag",
|
|
205
|
+
"exit"
|
|
206
|
+
];
|
|
207
|
+
const variantProps = ["initial", ...variantPriorityOrder];
|
|
208
|
+
function isControllingVariants(props) {
|
|
209
|
+
return isAnimationControls(props.animate) || variantProps.some((name) => isVariantLabel(props[name]));
|
|
210
|
+
}
|
|
211
|
+
function isVariantNode(props) {
|
|
212
|
+
return Boolean(isControllingVariants(props) || props.variants);
|
|
213
|
+
}
|
|
214
|
+
const camelToDash = (str) => str.replace(/([a-z])([A-Z])/gu, "$1-$2").toLowerCase();
|
|
215
|
+
const optimizedAppearDataId = "framerAppearId";
|
|
216
|
+
const optimizedAppearDataAttribute = "data-" + camelToDash(optimizedAppearDataId);
|
|
217
|
+
function getValueState(visualElement) {
|
|
218
|
+
const state = [{}, {}];
|
|
219
|
+
visualElement === null || visualElement === void 0 ? void 0 : visualElement.values.forEach((value, key) => {
|
|
220
|
+
state[0][key] = value.get();
|
|
221
|
+
state[1][key] = value.getVelocity();
|
|
222
|
+
});
|
|
223
|
+
return state;
|
|
224
|
+
}
|
|
225
|
+
function resolveVariantFromProps(props, definition, custom, visualElement) {
|
|
226
|
+
if (typeof definition === "function") {
|
|
227
|
+
const [current, velocity] = getValueState(visualElement);
|
|
228
|
+
definition = definition(custom !== void 0 ? custom : props.custom, current, velocity);
|
|
229
|
+
}
|
|
230
|
+
if (typeof definition === "string") {
|
|
231
|
+
definition = props.variants && props.variants[definition];
|
|
232
|
+
}
|
|
233
|
+
if (typeof definition === "function") {
|
|
234
|
+
const [current, velocity] = getValueState(visualElement);
|
|
235
|
+
definition = definition(custom !== void 0 ? custom : props.custom, current, velocity);
|
|
236
|
+
}
|
|
237
|
+
return definition;
|
|
238
|
+
}
|
|
239
|
+
const isKeyframesTarget = (v) => {
|
|
240
|
+
return Array.isArray(v);
|
|
241
|
+
};
|
|
242
|
+
const resolveFinalValueInKeyframes = (v) => {
|
|
243
|
+
return isKeyframesTarget(v) ? v[v.length - 1] || 0 : v;
|
|
244
|
+
};
|
|
245
|
+
const isMotionValue = (value) => Boolean(value && value.getVelocity);
|
|
246
|
+
const transformPropOrder = [
|
|
247
|
+
"transformPerspective",
|
|
248
|
+
"x",
|
|
249
|
+
"y",
|
|
250
|
+
"z",
|
|
251
|
+
"translateX",
|
|
252
|
+
"translateY",
|
|
253
|
+
"translateZ",
|
|
254
|
+
"scale",
|
|
255
|
+
"scaleX",
|
|
256
|
+
"scaleY",
|
|
257
|
+
"rotate",
|
|
258
|
+
"rotateX",
|
|
259
|
+
"rotateY",
|
|
260
|
+
"rotateZ",
|
|
261
|
+
"skew",
|
|
262
|
+
"skewX",
|
|
263
|
+
"skewY"
|
|
264
|
+
];
|
|
265
|
+
const transformProps = new Set(transformPropOrder);
|
|
266
|
+
const checkStringStartsWith = (token) => (key) => typeof key === "string" && key.startsWith(token);
|
|
267
|
+
const isCSSVariableName = /* @__PURE__ */ checkStringStartsWith("--");
|
|
268
|
+
const startsAsVariableToken = /* @__PURE__ */ checkStringStartsWith("var(--");
|
|
269
|
+
const isCSSVariableToken = (value) => {
|
|
270
|
+
const startsWithToken = startsAsVariableToken(value);
|
|
271
|
+
if (!startsWithToken)
|
|
272
|
+
return false;
|
|
273
|
+
return singleCssVariableRegex.test(value.split("/*")[0].trim());
|
|
274
|
+
};
|
|
275
|
+
const singleCssVariableRegex = /var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu;
|
|
276
|
+
const getValueAsType = (value, type) => {
|
|
277
|
+
return type && typeof value === "number" ? type.transform(value) : value;
|
|
278
|
+
};
|
|
279
|
+
const clamp = (min, max, v) => {
|
|
280
|
+
if (v > max)
|
|
281
|
+
return max;
|
|
282
|
+
if (v < min)
|
|
283
|
+
return min;
|
|
284
|
+
return v;
|
|
285
|
+
};
|
|
286
|
+
const number = {
|
|
287
|
+
test: (v) => typeof v === "number",
|
|
288
|
+
parse: parseFloat,
|
|
289
|
+
transform: (v) => v
|
|
290
|
+
};
|
|
291
|
+
const alpha = {
|
|
292
|
+
...number,
|
|
293
|
+
transform: (v) => clamp(0, 1, v)
|
|
294
|
+
};
|
|
295
|
+
const scale = {
|
|
296
|
+
...number,
|
|
297
|
+
default: 1
|
|
298
|
+
};
|
|
299
|
+
const createUnitType = (unit) => ({
|
|
300
|
+
test: (v) => typeof v === "string" && v.endsWith(unit) && v.split(" ").length === 1,
|
|
301
|
+
parse: parseFloat,
|
|
302
|
+
transform: (v) => `${v}${unit}`
|
|
303
|
+
});
|
|
304
|
+
const degrees = /* @__PURE__ */ createUnitType("deg");
|
|
305
|
+
const percent = /* @__PURE__ */ createUnitType("%");
|
|
306
|
+
const px = /* @__PURE__ */ createUnitType("px");
|
|
307
|
+
const vh = /* @__PURE__ */ createUnitType("vh");
|
|
308
|
+
const vw = /* @__PURE__ */ createUnitType("vw");
|
|
309
|
+
const progressPercentage = {
|
|
310
|
+
...percent,
|
|
311
|
+
parse: (v) => percent.parse(v) / 100,
|
|
312
|
+
transform: (v) => percent.transform(v * 100)
|
|
313
|
+
};
|
|
314
|
+
const browserNumberValueTypes = {
|
|
315
|
+
// Border props
|
|
316
|
+
borderWidth: px,
|
|
317
|
+
borderTopWidth: px,
|
|
318
|
+
borderRightWidth: px,
|
|
319
|
+
borderBottomWidth: px,
|
|
320
|
+
borderLeftWidth: px,
|
|
321
|
+
borderRadius: px,
|
|
322
|
+
radius: px,
|
|
323
|
+
borderTopLeftRadius: px,
|
|
324
|
+
borderTopRightRadius: px,
|
|
325
|
+
borderBottomRightRadius: px,
|
|
326
|
+
borderBottomLeftRadius: px,
|
|
327
|
+
// Positioning props
|
|
328
|
+
width: px,
|
|
329
|
+
maxWidth: px,
|
|
330
|
+
height: px,
|
|
331
|
+
maxHeight: px,
|
|
332
|
+
top: px,
|
|
333
|
+
right: px,
|
|
334
|
+
bottom: px,
|
|
335
|
+
left: px,
|
|
336
|
+
// Spacing props
|
|
337
|
+
padding: px,
|
|
338
|
+
paddingTop: px,
|
|
339
|
+
paddingRight: px,
|
|
340
|
+
paddingBottom: px,
|
|
341
|
+
paddingLeft: px,
|
|
342
|
+
margin: px,
|
|
343
|
+
marginTop: px,
|
|
344
|
+
marginRight: px,
|
|
345
|
+
marginBottom: px,
|
|
346
|
+
marginLeft: px,
|
|
347
|
+
// Misc
|
|
348
|
+
backgroundPositionX: px,
|
|
349
|
+
backgroundPositionY: px
|
|
350
|
+
};
|
|
351
|
+
const transformValueTypes = {
|
|
352
|
+
rotate: degrees,
|
|
353
|
+
rotateX: degrees,
|
|
354
|
+
rotateY: degrees,
|
|
355
|
+
rotateZ: degrees,
|
|
356
|
+
scale,
|
|
357
|
+
scaleX: scale,
|
|
358
|
+
scaleY: scale,
|
|
359
|
+
scaleZ: scale,
|
|
360
|
+
skew: degrees,
|
|
361
|
+
skewX: degrees,
|
|
362
|
+
skewY: degrees,
|
|
363
|
+
distance: px,
|
|
364
|
+
translateX: px,
|
|
365
|
+
translateY: px,
|
|
366
|
+
translateZ: px,
|
|
367
|
+
x: px,
|
|
368
|
+
y: px,
|
|
369
|
+
z: px,
|
|
370
|
+
perspective: px,
|
|
371
|
+
transformPerspective: px,
|
|
372
|
+
opacity: alpha,
|
|
373
|
+
originX: progressPercentage,
|
|
374
|
+
originY: progressPercentage,
|
|
375
|
+
originZ: px
|
|
376
|
+
};
|
|
377
|
+
const int = {
|
|
378
|
+
...number,
|
|
379
|
+
transform: Math.round
|
|
380
|
+
};
|
|
381
|
+
const numberValueTypes = {
|
|
382
|
+
...browserNumberValueTypes,
|
|
383
|
+
...transformValueTypes,
|
|
384
|
+
zIndex: int,
|
|
385
|
+
size: px,
|
|
386
|
+
// SVG
|
|
387
|
+
fillOpacity: alpha,
|
|
388
|
+
strokeOpacity: alpha,
|
|
389
|
+
numOctaves: int
|
|
390
|
+
};
|
|
391
|
+
const translateAlias = {
|
|
392
|
+
x: "translateX",
|
|
393
|
+
y: "translateY",
|
|
394
|
+
z: "translateZ",
|
|
395
|
+
transformPerspective: "perspective"
|
|
396
|
+
};
|
|
397
|
+
const numTransforms = transformPropOrder.length;
|
|
398
|
+
function buildTransform(latestValues, transform, transformTemplate) {
|
|
399
|
+
let transformString = "";
|
|
400
|
+
let transformIsDefault = true;
|
|
401
|
+
for (let i = 0; i < numTransforms; i++) {
|
|
402
|
+
const key = transformPropOrder[i];
|
|
403
|
+
const value = latestValues[key];
|
|
404
|
+
if (value === void 0)
|
|
405
|
+
continue;
|
|
406
|
+
let valueIsDefault = true;
|
|
407
|
+
if (typeof value === "number") {
|
|
408
|
+
valueIsDefault = value === (key.startsWith("scale") ? 1 : 0);
|
|
409
|
+
} else {
|
|
410
|
+
valueIsDefault = parseFloat(value) === 0;
|
|
411
|
+
}
|
|
412
|
+
if (!valueIsDefault || transformTemplate) {
|
|
413
|
+
const valueAsType = getValueAsType(value, numberValueTypes[key]);
|
|
414
|
+
if (!valueIsDefault) {
|
|
415
|
+
transformIsDefault = false;
|
|
416
|
+
const transformName = translateAlias[key] || key;
|
|
417
|
+
transformString += `${transformName}(${valueAsType}) `;
|
|
418
|
+
}
|
|
419
|
+
if (transformTemplate) {
|
|
420
|
+
transform[key] = valueAsType;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
transformString = transformString.trim();
|
|
425
|
+
if (transformTemplate) {
|
|
426
|
+
transformString = transformTemplate(transform, transformIsDefault ? "" : transformString);
|
|
427
|
+
} else if (transformIsDefault) {
|
|
428
|
+
transformString = "none";
|
|
429
|
+
}
|
|
430
|
+
return transformString;
|
|
431
|
+
}
|
|
432
|
+
function buildHTMLStyles(state, latestValues, transformTemplate) {
|
|
433
|
+
const { style, vars, transformOrigin } = state;
|
|
434
|
+
let hasTransform = false;
|
|
435
|
+
let hasTransformOrigin = false;
|
|
436
|
+
for (const key in latestValues) {
|
|
437
|
+
const value = latestValues[key];
|
|
438
|
+
if (transformProps.has(key)) {
|
|
439
|
+
hasTransform = true;
|
|
440
|
+
continue;
|
|
441
|
+
} else if (isCSSVariableName(key)) {
|
|
442
|
+
vars[key] = value;
|
|
443
|
+
continue;
|
|
444
|
+
} else {
|
|
445
|
+
const valueAsType = getValueAsType(value, numberValueTypes[key]);
|
|
446
|
+
if (key.startsWith("origin")) {
|
|
447
|
+
hasTransformOrigin = true;
|
|
448
|
+
transformOrigin[key] = valueAsType;
|
|
449
|
+
} else {
|
|
450
|
+
style[key] = valueAsType;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (!latestValues.transform) {
|
|
455
|
+
if (hasTransform || transformTemplate) {
|
|
456
|
+
style.transform = buildTransform(latestValues, state.transform, transformTemplate);
|
|
457
|
+
} else if (style.transform) {
|
|
458
|
+
style.transform = "none";
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (hasTransformOrigin) {
|
|
462
|
+
const { originX = "50%", originY = "50%", originZ = 0 } = transformOrigin;
|
|
463
|
+
style.transformOrigin = `${originX} ${originY} ${originZ}`;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
const dashKeys = {
|
|
467
|
+
offset: "stroke-dashoffset",
|
|
468
|
+
array: "stroke-dasharray"
|
|
469
|
+
};
|
|
470
|
+
const camelKeys = {
|
|
471
|
+
offset: "strokeDashoffset",
|
|
472
|
+
array: "strokeDasharray"
|
|
473
|
+
};
|
|
474
|
+
function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true) {
|
|
475
|
+
attrs.pathLength = 1;
|
|
476
|
+
const keys = useDashCase ? dashKeys : camelKeys;
|
|
477
|
+
attrs[keys.offset] = px.transform(-offset);
|
|
478
|
+
const pathLength = px.transform(length);
|
|
479
|
+
const pathSpacing = px.transform(spacing);
|
|
480
|
+
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
481
|
+
}
|
|
482
|
+
function calcOrigin(origin, offset, size) {
|
|
483
|
+
return typeof origin === "string" ? origin : px.transform(offset + size * origin);
|
|
484
|
+
}
|
|
485
|
+
function calcSVGTransformOrigin(dimensions, originX, originY) {
|
|
486
|
+
const pxOriginX = calcOrigin(originX, dimensions.x, dimensions.width);
|
|
487
|
+
const pxOriginY = calcOrigin(originY, dimensions.y, dimensions.height);
|
|
488
|
+
return `${pxOriginX} ${pxOriginY}`;
|
|
489
|
+
}
|
|
490
|
+
function buildSVGAttrs(state, {
|
|
491
|
+
attrX,
|
|
492
|
+
attrY,
|
|
493
|
+
attrScale,
|
|
494
|
+
originX,
|
|
495
|
+
originY,
|
|
496
|
+
pathLength,
|
|
497
|
+
pathSpacing = 1,
|
|
498
|
+
pathOffset = 0,
|
|
499
|
+
// This is object creation, which we try to avoid per-frame.
|
|
500
|
+
...latest
|
|
501
|
+
}, isSVGTag2, transformTemplate) {
|
|
502
|
+
buildHTMLStyles(state, latest, transformTemplate);
|
|
503
|
+
if (isSVGTag2) {
|
|
504
|
+
if (state.style.viewBox) {
|
|
505
|
+
state.attrs.viewBox = state.style.viewBox;
|
|
506
|
+
}
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
state.attrs = state.style;
|
|
510
|
+
state.style = {};
|
|
511
|
+
const { attrs, style, dimensions } = state;
|
|
512
|
+
if (attrs.transform) {
|
|
513
|
+
if (dimensions)
|
|
514
|
+
style.transform = attrs.transform;
|
|
515
|
+
delete attrs.transform;
|
|
516
|
+
}
|
|
517
|
+
if (dimensions && (originX !== void 0 || originY !== void 0 || style.transform)) {
|
|
518
|
+
style.transformOrigin = calcSVGTransformOrigin(dimensions, originX !== void 0 ? originX : 0.5, originY !== void 0 ? originY : 0.5);
|
|
519
|
+
}
|
|
520
|
+
if (attrX !== void 0)
|
|
521
|
+
attrs.x = attrX;
|
|
522
|
+
if (attrY !== void 0)
|
|
523
|
+
attrs.y = attrY;
|
|
524
|
+
if (attrScale !== void 0)
|
|
525
|
+
attrs.scale = attrScale;
|
|
526
|
+
if (pathLength !== void 0) {
|
|
527
|
+
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const isSVGTag = (tag) => typeof tag === "string" && tag.toLowerCase() === "svg";
|
|
531
|
+
function renderHTML(element, { style, vars }, styleProp, projection) {
|
|
532
|
+
Object.assign(element.style, style, projection && projection.getProjectionStyles(styleProp));
|
|
533
|
+
for (const key in vars) {
|
|
534
|
+
element.style.setProperty(key, vars[key]);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
const camelCaseAttributes = /* @__PURE__ */ new Set([
|
|
538
|
+
"baseFrequency",
|
|
539
|
+
"diffuseConstant",
|
|
540
|
+
"kernelMatrix",
|
|
541
|
+
"kernelUnitLength",
|
|
542
|
+
"keySplines",
|
|
543
|
+
"keyTimes",
|
|
544
|
+
"limitingConeAngle",
|
|
545
|
+
"markerHeight",
|
|
546
|
+
"markerWidth",
|
|
547
|
+
"numOctaves",
|
|
548
|
+
"targetX",
|
|
549
|
+
"targetY",
|
|
550
|
+
"surfaceScale",
|
|
551
|
+
"specularConstant",
|
|
552
|
+
"specularExponent",
|
|
553
|
+
"stdDeviation",
|
|
554
|
+
"tableValues",
|
|
555
|
+
"viewBox",
|
|
556
|
+
"gradientTransform",
|
|
557
|
+
"pathLength",
|
|
558
|
+
"startOffset",
|
|
559
|
+
"textLength",
|
|
560
|
+
"lengthAdjust"
|
|
561
|
+
]);
|
|
562
|
+
function renderSVG(element, renderState, _styleProp, projection) {
|
|
563
|
+
renderHTML(element, renderState, void 0, projection);
|
|
564
|
+
for (const key in renderState.attrs) {
|
|
565
|
+
element.setAttribute(!camelCaseAttributes.has(key) ? camelToDash(key) : key, renderState.attrs[key]);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const scaleCorrectors = {};
|
|
569
|
+
function isForcedMotionValue(key, { layout, layoutId }) {
|
|
570
|
+
return transformProps.has(key) || key.startsWith("origin") || (layout || layoutId !== void 0) && (!!scaleCorrectors[key] || key === "opacity");
|
|
571
|
+
}
|
|
572
|
+
function scrapeMotionValuesFromProps$1(props, prevProps, visualElement) {
|
|
573
|
+
var _a;
|
|
574
|
+
const { style } = props;
|
|
575
|
+
const newValues = {};
|
|
576
|
+
for (const key in style) {
|
|
577
|
+
if (isMotionValue(style[key]) || prevProps.style && isMotionValue(prevProps.style[key]) || isForcedMotionValue(key, props) || ((_a = visualElement === null || visualElement === void 0 ? void 0 : visualElement.getValue(key)) === null || _a === void 0 ? void 0 : _a.liveStyle) !== void 0) {
|
|
578
|
+
newValues[key] = style[key];
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return newValues;
|
|
582
|
+
}
|
|
583
|
+
function scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
584
|
+
const newValues = scrapeMotionValuesFromProps$1(props, prevProps, visualElement);
|
|
585
|
+
for (const key in props) {
|
|
586
|
+
if (isMotionValue(props[key]) || isMotionValue(prevProps[key])) {
|
|
587
|
+
const targetKey = transformPropOrder.indexOf(key) !== -1 ? "attr" + key.charAt(0).toUpperCase() + key.substring(1) : key;
|
|
588
|
+
newValues[targetKey] = props[key];
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return newValues;
|
|
592
|
+
}
|
|
593
|
+
function resolveVariant(visualElement, definition, custom) {
|
|
594
|
+
const props = visualElement.getProps();
|
|
595
|
+
return resolveVariantFromProps(props, definition, props.custom, visualElement);
|
|
596
|
+
}
|
|
597
|
+
function getValueTransition$1(transition, key) {
|
|
598
|
+
return transition ? transition[key] || transition["default"] || transition : void 0;
|
|
599
|
+
}
|
|
600
|
+
const positionalKeys = /* @__PURE__ */ new Set([
|
|
601
|
+
"width",
|
|
602
|
+
"height",
|
|
603
|
+
"top",
|
|
604
|
+
"left",
|
|
605
|
+
"right",
|
|
606
|
+
"bottom",
|
|
607
|
+
...transformPropOrder
|
|
608
|
+
]);
|
|
609
|
+
let now;
|
|
610
|
+
function clearTime() {
|
|
611
|
+
now = void 0;
|
|
612
|
+
}
|
|
613
|
+
const time = {
|
|
614
|
+
now: () => {
|
|
615
|
+
if (now === void 0) {
|
|
616
|
+
time.set(frameData.isProcessing || MotionGlobalConfig.useManualTiming ? frameData.timestamp : performance.now());
|
|
617
|
+
}
|
|
618
|
+
return now;
|
|
619
|
+
},
|
|
620
|
+
set: (newTime) => {
|
|
621
|
+
now = newTime;
|
|
622
|
+
queueMicrotask(clearTime);
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
function addUniqueItem(arr, item) {
|
|
626
|
+
if (arr.indexOf(item) === -1)
|
|
627
|
+
arr.push(item);
|
|
628
|
+
}
|
|
629
|
+
function removeItem(arr, item) {
|
|
630
|
+
const index = arr.indexOf(item);
|
|
631
|
+
if (index > -1)
|
|
632
|
+
arr.splice(index, 1);
|
|
633
|
+
}
|
|
634
|
+
class SubscriptionManager {
|
|
635
|
+
constructor() {
|
|
636
|
+
this.subscriptions = [];
|
|
637
|
+
}
|
|
638
|
+
add(handler) {
|
|
639
|
+
addUniqueItem(this.subscriptions, handler);
|
|
640
|
+
return () => removeItem(this.subscriptions, handler);
|
|
641
|
+
}
|
|
642
|
+
notify(a, b, c) {
|
|
643
|
+
const numSubscriptions = this.subscriptions.length;
|
|
644
|
+
if (!numSubscriptions)
|
|
645
|
+
return;
|
|
646
|
+
if (numSubscriptions === 1) {
|
|
647
|
+
this.subscriptions[0](a, b, c);
|
|
648
|
+
} else {
|
|
649
|
+
for (let i = 0; i < numSubscriptions; i++) {
|
|
650
|
+
const handler = this.subscriptions[i];
|
|
651
|
+
handler && handler(a, b, c);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
getSize() {
|
|
656
|
+
return this.subscriptions.length;
|
|
657
|
+
}
|
|
658
|
+
clear() {
|
|
659
|
+
this.subscriptions.length = 0;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function velocityPerSecond(velocity, frameDuration) {
|
|
663
|
+
return frameDuration ? velocity * (1e3 / frameDuration) : 0;
|
|
664
|
+
}
|
|
665
|
+
const MAX_VELOCITY_DELTA = 30;
|
|
666
|
+
const isFloat = (value) => {
|
|
667
|
+
return !isNaN(parseFloat(value));
|
|
668
|
+
};
|
|
669
|
+
class MotionValue {
|
|
670
|
+
/**
|
|
671
|
+
* @param init - The initiating value
|
|
672
|
+
* @param config - Optional configuration options
|
|
673
|
+
*
|
|
674
|
+
* - `transformer`: A function to transform incoming values with.
|
|
675
|
+
*
|
|
676
|
+
* @internal
|
|
677
|
+
*/
|
|
678
|
+
constructor(init, options = {}) {
|
|
679
|
+
this.version = "11.18.2";
|
|
680
|
+
this.canTrackVelocity = null;
|
|
681
|
+
this.events = {};
|
|
682
|
+
this.updateAndNotify = (v, render = true) => {
|
|
683
|
+
const currentTime = time.now();
|
|
684
|
+
if (this.updatedAt !== currentTime) {
|
|
685
|
+
this.setPrevFrameValue();
|
|
686
|
+
}
|
|
687
|
+
this.prev = this.current;
|
|
688
|
+
this.setCurrent(v);
|
|
689
|
+
if (this.current !== this.prev && this.events.change) {
|
|
690
|
+
this.events.change.notify(this.current);
|
|
691
|
+
}
|
|
692
|
+
if (render && this.events.renderRequest) {
|
|
693
|
+
this.events.renderRequest.notify(this.current);
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
this.hasAnimated = false;
|
|
697
|
+
this.setCurrent(init);
|
|
698
|
+
this.owner = options.owner;
|
|
699
|
+
}
|
|
700
|
+
setCurrent(current) {
|
|
701
|
+
this.current = current;
|
|
702
|
+
this.updatedAt = time.now();
|
|
703
|
+
if (this.canTrackVelocity === null && current !== void 0) {
|
|
704
|
+
this.canTrackVelocity = isFloat(this.current);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
setPrevFrameValue(prevFrameValue = this.current) {
|
|
708
|
+
this.prevFrameValue = prevFrameValue;
|
|
709
|
+
this.prevUpdatedAt = this.updatedAt;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Adds a function that will be notified when the `MotionValue` is updated.
|
|
713
|
+
*
|
|
714
|
+
* It returns a function that, when called, will cancel the subscription.
|
|
715
|
+
*
|
|
716
|
+
* When calling `onChange` inside a React component, it should be wrapped with the
|
|
717
|
+
* `useEffect` hook. As it returns an unsubscribe function, this should be returned
|
|
718
|
+
* from the `useEffect` function to ensure you don't add duplicate subscribers..
|
|
719
|
+
*
|
|
720
|
+
* ```jsx
|
|
721
|
+
* export const MyComponent = () => {
|
|
722
|
+
* const x = useMotionValue(0)
|
|
723
|
+
* const y = useMotionValue(0)
|
|
724
|
+
* const opacity = useMotionValue(1)
|
|
725
|
+
*
|
|
726
|
+
* useEffect(() => {
|
|
727
|
+
* function updateOpacity() {
|
|
728
|
+
* const maxXY = Math.max(x.get(), y.get())
|
|
729
|
+
* const newOpacity = transform(maxXY, [0, 100], [1, 0])
|
|
730
|
+
* opacity.set(newOpacity)
|
|
731
|
+
* }
|
|
732
|
+
*
|
|
733
|
+
* const unsubscribeX = x.on("change", updateOpacity)
|
|
734
|
+
* const unsubscribeY = y.on("change", updateOpacity)
|
|
735
|
+
*
|
|
736
|
+
* return () => {
|
|
737
|
+
* unsubscribeX()
|
|
738
|
+
* unsubscribeY()
|
|
739
|
+
* }
|
|
740
|
+
* }, [])
|
|
741
|
+
*
|
|
742
|
+
* return <motion.div style={{ x }} />
|
|
743
|
+
* }
|
|
744
|
+
* ```
|
|
745
|
+
*
|
|
746
|
+
* @param subscriber - A function that receives the latest value.
|
|
747
|
+
* @returns A function that, when called, will cancel this subscription.
|
|
748
|
+
*
|
|
749
|
+
* @deprecated
|
|
750
|
+
*/
|
|
751
|
+
onChange(subscription) {
|
|
752
|
+
if (process.env.NODE_ENV !== "production") {
|
|
753
|
+
warnOnce(false, `value.onChange(callback) is deprecated. Switch to value.on("change", callback).`);
|
|
754
|
+
}
|
|
755
|
+
return this.on("change", subscription);
|
|
756
|
+
}
|
|
757
|
+
on(eventName, callback) {
|
|
758
|
+
if (!this.events[eventName]) {
|
|
759
|
+
this.events[eventName] = new SubscriptionManager();
|
|
760
|
+
}
|
|
761
|
+
const unsubscribe = this.events[eventName].add(callback);
|
|
762
|
+
if (eventName === "change") {
|
|
763
|
+
return () => {
|
|
764
|
+
unsubscribe();
|
|
765
|
+
frame.read(() => {
|
|
766
|
+
if (!this.events.change.getSize()) {
|
|
767
|
+
this.stop();
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
return unsubscribe;
|
|
773
|
+
}
|
|
774
|
+
clearListeners() {
|
|
775
|
+
for (const eventManagers in this.events) {
|
|
776
|
+
this.events[eventManagers].clear();
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Attaches a passive effect to the `MotionValue`.
|
|
781
|
+
*
|
|
782
|
+
* @internal
|
|
783
|
+
*/
|
|
784
|
+
attach(passiveEffect, stopPassiveEffect) {
|
|
785
|
+
this.passiveEffect = passiveEffect;
|
|
786
|
+
this.stopPassiveEffect = stopPassiveEffect;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Sets the state of the `MotionValue`.
|
|
790
|
+
*
|
|
791
|
+
* @remarks
|
|
792
|
+
*
|
|
793
|
+
* ```jsx
|
|
794
|
+
* const x = useMotionValue(0)
|
|
795
|
+
* x.set(10)
|
|
796
|
+
* ```
|
|
797
|
+
*
|
|
798
|
+
* @param latest - Latest value to set.
|
|
799
|
+
* @param render - Whether to notify render subscribers. Defaults to `true`
|
|
800
|
+
*
|
|
801
|
+
* @public
|
|
802
|
+
*/
|
|
803
|
+
set(v, render = true) {
|
|
804
|
+
if (!render || !this.passiveEffect) {
|
|
805
|
+
this.updateAndNotify(v, render);
|
|
806
|
+
} else {
|
|
807
|
+
this.passiveEffect(v, this.updateAndNotify);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
setWithVelocity(prev, current, delta) {
|
|
811
|
+
this.set(current);
|
|
812
|
+
this.prev = void 0;
|
|
813
|
+
this.prevFrameValue = prev;
|
|
814
|
+
this.prevUpdatedAt = this.updatedAt - delta;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Set the state of the `MotionValue`, stopping any active animations,
|
|
818
|
+
* effects, and resets velocity to `0`.
|
|
819
|
+
*/
|
|
820
|
+
jump(v, endAnimation = true) {
|
|
821
|
+
this.updateAndNotify(v);
|
|
822
|
+
this.prev = v;
|
|
823
|
+
this.prevUpdatedAt = this.prevFrameValue = void 0;
|
|
824
|
+
endAnimation && this.stop();
|
|
825
|
+
if (this.stopPassiveEffect)
|
|
826
|
+
this.stopPassiveEffect();
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Returns the latest state of `MotionValue`
|
|
830
|
+
*
|
|
831
|
+
* @returns - The latest state of `MotionValue`
|
|
832
|
+
*
|
|
833
|
+
* @public
|
|
834
|
+
*/
|
|
835
|
+
get() {
|
|
836
|
+
return this.current;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* @public
|
|
840
|
+
*/
|
|
841
|
+
getPrevious() {
|
|
842
|
+
return this.prev;
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Returns the latest velocity of `MotionValue`
|
|
846
|
+
*
|
|
847
|
+
* @returns - The latest velocity of `MotionValue`. Returns `0` if the state is non-numerical.
|
|
848
|
+
*
|
|
849
|
+
* @public
|
|
850
|
+
*/
|
|
851
|
+
getVelocity() {
|
|
852
|
+
const currentTime = time.now();
|
|
853
|
+
if (!this.canTrackVelocity || this.prevFrameValue === void 0 || currentTime - this.updatedAt > MAX_VELOCITY_DELTA) {
|
|
854
|
+
return 0;
|
|
855
|
+
}
|
|
856
|
+
const delta = Math.min(this.updatedAt - this.prevUpdatedAt, MAX_VELOCITY_DELTA);
|
|
857
|
+
return velocityPerSecond(parseFloat(this.current) - parseFloat(this.prevFrameValue), delta);
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Registers a new animation to control this `MotionValue`. Only one
|
|
861
|
+
* animation can drive a `MotionValue` at one time.
|
|
862
|
+
*
|
|
863
|
+
* ```jsx
|
|
864
|
+
* value.start()
|
|
865
|
+
* ```
|
|
866
|
+
*
|
|
867
|
+
* @param animation - A function that starts the provided animation
|
|
868
|
+
*
|
|
869
|
+
* @internal
|
|
870
|
+
*/
|
|
871
|
+
start(startAnimation) {
|
|
872
|
+
this.stop();
|
|
873
|
+
return new Promise((resolve) => {
|
|
874
|
+
this.hasAnimated = true;
|
|
875
|
+
this.animation = startAnimation(resolve);
|
|
876
|
+
if (this.events.animationStart) {
|
|
877
|
+
this.events.animationStart.notify();
|
|
878
|
+
}
|
|
879
|
+
}).then(() => {
|
|
880
|
+
if (this.events.animationComplete) {
|
|
881
|
+
this.events.animationComplete.notify();
|
|
882
|
+
}
|
|
883
|
+
this.clearAnimation();
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Stop the currently active animation.
|
|
888
|
+
*
|
|
889
|
+
* @public
|
|
890
|
+
*/
|
|
891
|
+
stop() {
|
|
892
|
+
if (this.animation) {
|
|
893
|
+
this.animation.stop();
|
|
894
|
+
if (this.events.animationCancel) {
|
|
895
|
+
this.events.animationCancel.notify();
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
this.clearAnimation();
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Returns `true` if this value is currently animating.
|
|
902
|
+
*
|
|
903
|
+
* @public
|
|
904
|
+
*/
|
|
905
|
+
isAnimating() {
|
|
906
|
+
return !!this.animation;
|
|
907
|
+
}
|
|
908
|
+
clearAnimation() {
|
|
909
|
+
delete this.animation;
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Destroy and clean up subscribers to this `MotionValue`.
|
|
913
|
+
*
|
|
914
|
+
* The `MotionValue` hooks like `useMotionValue` and `useTransform` automatically
|
|
915
|
+
* handle the lifecycle of the returned `MotionValue`, so this method is only necessary if you've manually
|
|
916
|
+
* created a `MotionValue` via the `motionValue` function.
|
|
917
|
+
*
|
|
918
|
+
* @public
|
|
919
|
+
*/
|
|
920
|
+
destroy() {
|
|
921
|
+
this.clearListeners();
|
|
922
|
+
this.stop();
|
|
923
|
+
if (this.stopPassiveEffect) {
|
|
924
|
+
this.stopPassiveEffect();
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
function motionValue(init, options) {
|
|
929
|
+
return new MotionValue(init, options);
|
|
930
|
+
}
|
|
931
|
+
function setMotionValue(visualElement, key, value) {
|
|
932
|
+
if (visualElement.hasValue(key)) {
|
|
933
|
+
visualElement.getValue(key).set(value);
|
|
934
|
+
} else {
|
|
935
|
+
visualElement.addValue(key, motionValue(value));
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function setTarget(visualElement, definition) {
|
|
939
|
+
const resolved = resolveVariant(visualElement, definition);
|
|
940
|
+
let { transitionEnd = {}, transition = {}, ...target } = resolved || {};
|
|
941
|
+
target = { ...target, ...transitionEnd };
|
|
942
|
+
for (const key in target) {
|
|
943
|
+
const value = resolveFinalValueInKeyframes(target[key]);
|
|
944
|
+
setMotionValue(visualElement, key, value);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
function isWillChangeMotionValue(value) {
|
|
948
|
+
return Boolean(isMotionValue(value) && value.add);
|
|
949
|
+
}
|
|
950
|
+
function addValueToWillChange(visualElement, key) {
|
|
951
|
+
const willChange = visualElement.getValue("willChange");
|
|
952
|
+
if (isWillChangeMotionValue(willChange)) {
|
|
953
|
+
return willChange.add(key);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
function getOptimisedAppearId(visualElement) {
|
|
957
|
+
return visualElement.props[optimizedAppearDataAttribute];
|
|
958
|
+
}
|
|
959
|
+
// @__NO_SIDE_EFFECTS__
|
|
960
|
+
function memo(callback) {
|
|
961
|
+
let result;
|
|
962
|
+
return () => {
|
|
963
|
+
if (result === void 0)
|
|
964
|
+
result = callback();
|
|
965
|
+
return result;
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
const supportsScrollTimeline = /* @__PURE__ */ memo(() => window.ScrollTimeline !== void 0);
|
|
969
|
+
class BaseGroupPlaybackControls {
|
|
970
|
+
constructor(animations) {
|
|
971
|
+
this.stop = () => this.runAll("stop");
|
|
972
|
+
this.animations = animations.filter(Boolean);
|
|
973
|
+
}
|
|
974
|
+
get finished() {
|
|
975
|
+
return Promise.all(this.animations.map((animation) => "finished" in animation ? animation.finished : animation));
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* TODO: Filter out cancelled or stopped animations before returning
|
|
979
|
+
*/
|
|
980
|
+
getAll(propName) {
|
|
981
|
+
return this.animations[0][propName];
|
|
982
|
+
}
|
|
983
|
+
setAll(propName, newValue) {
|
|
984
|
+
for (let i = 0; i < this.animations.length; i++) {
|
|
985
|
+
this.animations[i][propName] = newValue;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
attachTimeline(timeline, fallback) {
|
|
989
|
+
const subscriptions = this.animations.map((animation) => {
|
|
990
|
+
if (supportsScrollTimeline() && animation.attachTimeline) {
|
|
991
|
+
return animation.attachTimeline(timeline);
|
|
992
|
+
} else if (typeof fallback === "function") {
|
|
993
|
+
return fallback(animation);
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
return () => {
|
|
997
|
+
subscriptions.forEach((cancel, i) => {
|
|
998
|
+
cancel && cancel();
|
|
999
|
+
this.animations[i].stop();
|
|
1000
|
+
});
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
get time() {
|
|
1004
|
+
return this.getAll("time");
|
|
1005
|
+
}
|
|
1006
|
+
set time(time2) {
|
|
1007
|
+
this.setAll("time", time2);
|
|
1008
|
+
}
|
|
1009
|
+
get speed() {
|
|
1010
|
+
return this.getAll("speed");
|
|
1011
|
+
}
|
|
1012
|
+
set speed(speed) {
|
|
1013
|
+
this.setAll("speed", speed);
|
|
1014
|
+
}
|
|
1015
|
+
get startTime() {
|
|
1016
|
+
return this.getAll("startTime");
|
|
1017
|
+
}
|
|
1018
|
+
get duration() {
|
|
1019
|
+
let max = 0;
|
|
1020
|
+
for (let i = 0; i < this.animations.length; i++) {
|
|
1021
|
+
max = Math.max(max, this.animations[i].duration);
|
|
1022
|
+
}
|
|
1023
|
+
return max;
|
|
1024
|
+
}
|
|
1025
|
+
runAll(methodName) {
|
|
1026
|
+
this.animations.forEach((controls) => controls[methodName]());
|
|
1027
|
+
}
|
|
1028
|
+
flatten() {
|
|
1029
|
+
this.runAll("flatten");
|
|
1030
|
+
}
|
|
1031
|
+
play() {
|
|
1032
|
+
this.runAll("play");
|
|
1033
|
+
}
|
|
1034
|
+
pause() {
|
|
1035
|
+
this.runAll("pause");
|
|
1036
|
+
}
|
|
1037
|
+
cancel() {
|
|
1038
|
+
this.runAll("cancel");
|
|
1039
|
+
}
|
|
1040
|
+
complete() {
|
|
1041
|
+
this.runAll("complete");
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
class GroupPlaybackControls extends BaseGroupPlaybackControls {
|
|
1045
|
+
then(onResolve, onReject) {
|
|
1046
|
+
return Promise.all(this.animations).then(onResolve).catch(onReject);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
const secondsToMilliseconds = /* @__NO_SIDE_EFFECTS__ */ (seconds) => seconds * 1e3;
|
|
1050
|
+
const millisecondsToSeconds = /* @__NO_SIDE_EFFECTS__ */ (milliseconds) => milliseconds / 1e3;
|
|
1051
|
+
function isGenerator(type) {
|
|
1052
|
+
return typeof type === "function";
|
|
1053
|
+
}
|
|
1054
|
+
function attachTimeline(animation, timeline) {
|
|
1055
|
+
animation.timeline = timeline;
|
|
1056
|
+
animation.onfinish = null;
|
|
1057
|
+
}
|
|
1058
|
+
const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
|
|
1059
|
+
const supportsFlags = {
|
|
1060
|
+
linearEasing: void 0
|
|
1061
|
+
};
|
|
1062
|
+
function memoSupports(callback, supportsFlag) {
|
|
1063
|
+
const memoized = /* @__PURE__ */ memo(callback);
|
|
1064
|
+
return () => {
|
|
1065
|
+
var _a;
|
|
1066
|
+
return (_a = supportsFlags[supportsFlag]) !== null && _a !== void 0 ? _a : memoized();
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
const supportsLinearEasing = /* @__PURE__ */ memoSupports(() => {
|
|
1070
|
+
try {
|
|
1071
|
+
document.createElement("div").animate({ opacity: 0 }, { easing: "linear(0, 1)" });
|
|
1072
|
+
} catch (e) {
|
|
1073
|
+
return false;
|
|
1074
|
+
}
|
|
1075
|
+
return true;
|
|
1076
|
+
}, "linearEasing");
|
|
1077
|
+
const progress = /* @__NO_SIDE_EFFECTS__ */ (from, to, value) => {
|
|
1078
|
+
const toFromDifference = to - from;
|
|
1079
|
+
return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
|
|
1080
|
+
};
|
|
1081
|
+
const generateLinearEasing = (easing, duration, resolution = 10) => {
|
|
1082
|
+
let points = "";
|
|
1083
|
+
const numPoints = Math.max(Math.round(duration / resolution), 2);
|
|
1084
|
+
for (let i = 0; i < numPoints; i++) {
|
|
1085
|
+
points += easing(/* @__PURE__ */ progress(0, numPoints - 1, i)) + ", ";
|
|
1086
|
+
}
|
|
1087
|
+
return `linear(${points.substring(0, points.length - 2)})`;
|
|
1088
|
+
};
|
|
1089
|
+
function isWaapiSupportedEasing(easing) {
|
|
1090
|
+
return Boolean(typeof easing === "function" && supportsLinearEasing() || !easing || typeof easing === "string" && (easing in supportedWaapiEasing || supportsLinearEasing()) || isBezierDefinition(easing) || Array.isArray(easing) && easing.every(isWaapiSupportedEasing));
|
|
1091
|
+
}
|
|
1092
|
+
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
1093
|
+
const supportedWaapiEasing = {
|
|
1094
|
+
linear: "linear",
|
|
1095
|
+
ease: "ease",
|
|
1096
|
+
easeIn: "ease-in",
|
|
1097
|
+
easeOut: "ease-out",
|
|
1098
|
+
easeInOut: "ease-in-out",
|
|
1099
|
+
circIn: /* @__PURE__ */ cubicBezierAsString([0, 0.65, 0.55, 1]),
|
|
1100
|
+
circOut: /* @__PURE__ */ cubicBezierAsString([0.55, 0, 1, 0.45]),
|
|
1101
|
+
backIn: /* @__PURE__ */ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
|
|
1102
|
+
backOut: /* @__PURE__ */ cubicBezierAsString([0.33, 1.53, 0.69, 0.99])
|
|
1103
|
+
};
|
|
1104
|
+
function mapEasingToNativeEasing(easing, duration) {
|
|
1105
|
+
if (!easing) {
|
|
1106
|
+
return void 0;
|
|
1107
|
+
} else if (typeof easing === "function" && supportsLinearEasing()) {
|
|
1108
|
+
return generateLinearEasing(easing, duration);
|
|
1109
|
+
} else if (isBezierDefinition(easing)) {
|
|
1110
|
+
return cubicBezierAsString(easing);
|
|
1111
|
+
} else if (Array.isArray(easing)) {
|
|
1112
|
+
return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) || supportedWaapiEasing.easeOut);
|
|
1113
|
+
} else {
|
|
1114
|
+
return supportedWaapiEasing[easing];
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
const calcBezier = (t, a1, a2) => (((1 - 3 * a2 + 3 * a1) * t + (3 * a2 - 6 * a1)) * t + 3 * a1) * t;
|
|
1118
|
+
const subdivisionPrecision = 1e-7;
|
|
1119
|
+
const subdivisionMaxIterations = 12;
|
|
1120
|
+
function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
|
|
1121
|
+
let currentX;
|
|
1122
|
+
let currentT;
|
|
1123
|
+
let i = 0;
|
|
1124
|
+
do {
|
|
1125
|
+
currentT = lowerBound + (upperBound - lowerBound) / 2;
|
|
1126
|
+
currentX = calcBezier(currentT, mX1, mX2) - x;
|
|
1127
|
+
if (currentX > 0) {
|
|
1128
|
+
upperBound = currentT;
|
|
1129
|
+
} else {
|
|
1130
|
+
lowerBound = currentT;
|
|
1131
|
+
}
|
|
1132
|
+
} while (Math.abs(currentX) > subdivisionPrecision && ++i < subdivisionMaxIterations);
|
|
1133
|
+
return currentT;
|
|
1134
|
+
}
|
|
1135
|
+
function cubicBezier(mX1, mY1, mX2, mY2) {
|
|
1136
|
+
if (mX1 === mY1 && mX2 === mY2)
|
|
1137
|
+
return noop;
|
|
1138
|
+
const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
|
|
1139
|
+
return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
|
|
1140
|
+
}
|
|
1141
|
+
const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
|
|
1142
|
+
const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
|
|
1143
|
+
const backOut = /* @__PURE__ */ cubicBezier(0.33, 1.53, 0.69, 0.99);
|
|
1144
|
+
const backIn = /* @__PURE__ */ reverseEasing(backOut);
|
|
1145
|
+
const backInOut = /* @__PURE__ */ mirrorEasing(backIn);
|
|
1146
|
+
const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
|
|
1147
|
+
const circIn = (p) => 1 - Math.sin(Math.acos(p));
|
|
1148
|
+
const circOut = reverseEasing(circIn);
|
|
1149
|
+
const circInOut = mirrorEasing(circIn);
|
|
1150
|
+
const isZeroValueString = (v) => /^0[^.\s]+$/u.test(v);
|
|
1151
|
+
function isNone(value) {
|
|
1152
|
+
if (typeof value === "number") {
|
|
1153
|
+
return value === 0;
|
|
1154
|
+
} else if (value !== null) {
|
|
1155
|
+
return value === "none" || value === "0" || isZeroValueString(value);
|
|
1156
|
+
} else {
|
|
1157
|
+
return true;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
const sanitize = (v) => Math.round(v * 1e5) / 1e5;
|
|
1161
|
+
const floatRegex = /-?(?:\d+(?:\.\d+)?|\.\d+)/gu;
|
|
1162
|
+
function isNullish(v) {
|
|
1163
|
+
return v == null;
|
|
1164
|
+
}
|
|
1165
|
+
const singleColorRegex = /^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu;
|
|
1166
|
+
const isColorString = (type, testProp) => (v) => {
|
|
1167
|
+
return Boolean(typeof v === "string" && singleColorRegex.test(v) && v.startsWith(type) || testProp && !isNullish(v) && Object.prototype.hasOwnProperty.call(v, testProp));
|
|
1168
|
+
};
|
|
1169
|
+
const splitColor = (aName, bName, cName) => (v) => {
|
|
1170
|
+
if (typeof v !== "string")
|
|
1171
|
+
return v;
|
|
1172
|
+
const [a, b, c, alpha2] = v.match(floatRegex);
|
|
1173
|
+
return {
|
|
1174
|
+
[aName]: parseFloat(a),
|
|
1175
|
+
[bName]: parseFloat(b),
|
|
1176
|
+
[cName]: parseFloat(c),
|
|
1177
|
+
alpha: alpha2 !== void 0 ? parseFloat(alpha2) : 1
|
|
1178
|
+
};
|
|
1179
|
+
};
|
|
1180
|
+
const clampRgbUnit = (v) => clamp(0, 255, v);
|
|
1181
|
+
const rgbUnit = {
|
|
1182
|
+
...number,
|
|
1183
|
+
transform: (v) => Math.round(clampRgbUnit(v))
|
|
1184
|
+
};
|
|
1185
|
+
const rgba = {
|
|
1186
|
+
test: /* @__PURE__ */ isColorString("rgb", "red"),
|
|
1187
|
+
parse: /* @__PURE__ */ splitColor("red", "green", "blue"),
|
|
1188
|
+
transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => "rgba(" + rgbUnit.transform(red) + ", " + rgbUnit.transform(green) + ", " + rgbUnit.transform(blue) + ", " + sanitize(alpha.transform(alpha$1)) + ")"
|
|
1189
|
+
};
|
|
1190
|
+
function parseHex(v) {
|
|
1191
|
+
let r = "";
|
|
1192
|
+
let g = "";
|
|
1193
|
+
let b = "";
|
|
1194
|
+
let a = "";
|
|
1195
|
+
if (v.length > 5) {
|
|
1196
|
+
r = v.substring(1, 3);
|
|
1197
|
+
g = v.substring(3, 5);
|
|
1198
|
+
b = v.substring(5, 7);
|
|
1199
|
+
a = v.substring(7, 9);
|
|
1200
|
+
} else {
|
|
1201
|
+
r = v.substring(1, 2);
|
|
1202
|
+
g = v.substring(2, 3);
|
|
1203
|
+
b = v.substring(3, 4);
|
|
1204
|
+
a = v.substring(4, 5);
|
|
1205
|
+
r += r;
|
|
1206
|
+
g += g;
|
|
1207
|
+
b += b;
|
|
1208
|
+
a += a;
|
|
1209
|
+
}
|
|
1210
|
+
return {
|
|
1211
|
+
red: parseInt(r, 16),
|
|
1212
|
+
green: parseInt(g, 16),
|
|
1213
|
+
blue: parseInt(b, 16),
|
|
1214
|
+
alpha: a ? parseInt(a, 16) / 255 : 1
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
const hex = {
|
|
1218
|
+
test: /* @__PURE__ */ isColorString("#"),
|
|
1219
|
+
parse: parseHex,
|
|
1220
|
+
transform: rgba.transform
|
|
1221
|
+
};
|
|
1222
|
+
const hsla = {
|
|
1223
|
+
test: /* @__PURE__ */ isColorString("hsl", "hue"),
|
|
1224
|
+
parse: /* @__PURE__ */ splitColor("hue", "saturation", "lightness"),
|
|
1225
|
+
transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
|
|
1226
|
+
return "hsla(" + Math.round(hue) + ", " + percent.transform(sanitize(saturation)) + ", " + percent.transform(sanitize(lightness)) + ", " + sanitize(alpha.transform(alpha$1)) + ")";
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
const color = {
|
|
1230
|
+
test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
|
|
1231
|
+
parse: (v) => {
|
|
1232
|
+
if (rgba.test(v)) {
|
|
1233
|
+
return rgba.parse(v);
|
|
1234
|
+
} else if (hsla.test(v)) {
|
|
1235
|
+
return hsla.parse(v);
|
|
1236
|
+
} else {
|
|
1237
|
+
return hex.parse(v);
|
|
1238
|
+
}
|
|
1239
|
+
},
|
|
1240
|
+
transform: (v) => {
|
|
1241
|
+
return typeof v === "string" ? v : v.hasOwnProperty("red") ? rgba.transform(v) : hsla.transform(v);
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
const colorRegex = /(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;
|
|
1245
|
+
function test(v) {
|
|
1246
|
+
var _a, _b;
|
|
1247
|
+
return isNaN(v) && typeof v === "string" && (((_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) || 0) + (((_b = v.match(colorRegex)) === null || _b === void 0 ? void 0 : _b.length) || 0) > 0;
|
|
1248
|
+
}
|
|
1249
|
+
const NUMBER_TOKEN = "number";
|
|
1250
|
+
const COLOR_TOKEN = "color";
|
|
1251
|
+
const VAR_TOKEN = "var";
|
|
1252
|
+
const VAR_FUNCTION_TOKEN = "var(";
|
|
1253
|
+
const SPLIT_TOKEN = "${}";
|
|
1254
|
+
const complexRegex = /var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;
|
|
1255
|
+
function analyseComplexValue(value) {
|
|
1256
|
+
const originalValue = value.toString();
|
|
1257
|
+
const values = [];
|
|
1258
|
+
const indexes = {
|
|
1259
|
+
color: [],
|
|
1260
|
+
number: [],
|
|
1261
|
+
var: []
|
|
1262
|
+
};
|
|
1263
|
+
const types = [];
|
|
1264
|
+
let i = 0;
|
|
1265
|
+
const tokenised = originalValue.replace(complexRegex, (parsedValue) => {
|
|
1266
|
+
if (color.test(parsedValue)) {
|
|
1267
|
+
indexes.color.push(i);
|
|
1268
|
+
types.push(COLOR_TOKEN);
|
|
1269
|
+
values.push(color.parse(parsedValue));
|
|
1270
|
+
} else if (parsedValue.startsWith(VAR_FUNCTION_TOKEN)) {
|
|
1271
|
+
indexes.var.push(i);
|
|
1272
|
+
types.push(VAR_TOKEN);
|
|
1273
|
+
values.push(parsedValue);
|
|
1274
|
+
} else {
|
|
1275
|
+
indexes.number.push(i);
|
|
1276
|
+
types.push(NUMBER_TOKEN);
|
|
1277
|
+
values.push(parseFloat(parsedValue));
|
|
1278
|
+
}
|
|
1279
|
+
++i;
|
|
1280
|
+
return SPLIT_TOKEN;
|
|
1281
|
+
});
|
|
1282
|
+
const split = tokenised.split(SPLIT_TOKEN);
|
|
1283
|
+
return { values, split, indexes, types };
|
|
1284
|
+
}
|
|
1285
|
+
function parseComplexValue(v) {
|
|
1286
|
+
return analyseComplexValue(v).values;
|
|
1287
|
+
}
|
|
1288
|
+
function createTransformer(source) {
|
|
1289
|
+
const { split, types } = analyseComplexValue(source);
|
|
1290
|
+
const numSections = split.length;
|
|
1291
|
+
return (v) => {
|
|
1292
|
+
let output = "";
|
|
1293
|
+
for (let i = 0; i < numSections; i++) {
|
|
1294
|
+
output += split[i];
|
|
1295
|
+
if (v[i] !== void 0) {
|
|
1296
|
+
const type = types[i];
|
|
1297
|
+
if (type === NUMBER_TOKEN) {
|
|
1298
|
+
output += sanitize(v[i]);
|
|
1299
|
+
} else if (type === COLOR_TOKEN) {
|
|
1300
|
+
output += color.transform(v[i]);
|
|
1301
|
+
} else {
|
|
1302
|
+
output += v[i];
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
return output;
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
const convertNumbersToZero = (v) => typeof v === "number" ? 0 : v;
|
|
1310
|
+
function getAnimatableNone$1(v) {
|
|
1311
|
+
const parsed = parseComplexValue(v);
|
|
1312
|
+
const transformer = createTransformer(v);
|
|
1313
|
+
return transformer(parsed.map(convertNumbersToZero));
|
|
1314
|
+
}
|
|
1315
|
+
const complex = {
|
|
1316
|
+
test,
|
|
1317
|
+
parse: parseComplexValue,
|
|
1318
|
+
createTransformer,
|
|
1319
|
+
getAnimatableNone: getAnimatableNone$1
|
|
1320
|
+
};
|
|
1321
|
+
const maxDefaults = /* @__PURE__ */ new Set(["brightness", "contrast", "saturate", "opacity"]);
|
|
1322
|
+
function applyDefaultFilter(v) {
|
|
1323
|
+
const [name, value] = v.slice(0, -1).split("(");
|
|
1324
|
+
if (name === "drop-shadow")
|
|
1325
|
+
return v;
|
|
1326
|
+
const [number2] = value.match(floatRegex) || [];
|
|
1327
|
+
if (!number2)
|
|
1328
|
+
return v;
|
|
1329
|
+
const unit = value.replace(number2, "");
|
|
1330
|
+
let defaultValue = maxDefaults.has(name) ? 1 : 0;
|
|
1331
|
+
if (number2 !== value)
|
|
1332
|
+
defaultValue *= 100;
|
|
1333
|
+
return name + "(" + defaultValue + unit + ")";
|
|
1334
|
+
}
|
|
1335
|
+
const functionRegex = /\b([a-z-]*)\(.*?\)/gu;
|
|
1336
|
+
const filter = {
|
|
1337
|
+
...complex,
|
|
1338
|
+
getAnimatableNone: (v) => {
|
|
1339
|
+
const functions = v.match(functionRegex);
|
|
1340
|
+
return functions ? functions.map(applyDefaultFilter).join(" ") : v;
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
const defaultValueTypes = {
|
|
1344
|
+
...numberValueTypes,
|
|
1345
|
+
// Color props
|
|
1346
|
+
color,
|
|
1347
|
+
backgroundColor: color,
|
|
1348
|
+
outlineColor: color,
|
|
1349
|
+
fill: color,
|
|
1350
|
+
stroke: color,
|
|
1351
|
+
// Border props
|
|
1352
|
+
borderColor: color,
|
|
1353
|
+
borderTopColor: color,
|
|
1354
|
+
borderRightColor: color,
|
|
1355
|
+
borderBottomColor: color,
|
|
1356
|
+
borderLeftColor: color,
|
|
1357
|
+
filter,
|
|
1358
|
+
WebkitFilter: filter
|
|
1359
|
+
};
|
|
1360
|
+
const getDefaultValueType = (key) => defaultValueTypes[key];
|
|
1361
|
+
function getAnimatableNone(key, value) {
|
|
1362
|
+
let defaultValueType = getDefaultValueType(key);
|
|
1363
|
+
if (defaultValueType !== filter)
|
|
1364
|
+
defaultValueType = complex;
|
|
1365
|
+
return defaultValueType.getAnimatableNone ? defaultValueType.getAnimatableNone(value) : void 0;
|
|
1366
|
+
}
|
|
1367
|
+
const invalidTemplates = /* @__PURE__ */ new Set(["auto", "none", "0"]);
|
|
1368
|
+
function makeNoneKeyframesAnimatable(unresolvedKeyframes, noneKeyframeIndexes, name) {
|
|
1369
|
+
let i = 0;
|
|
1370
|
+
let animatableTemplate = void 0;
|
|
1371
|
+
while (i < unresolvedKeyframes.length && !animatableTemplate) {
|
|
1372
|
+
const keyframe = unresolvedKeyframes[i];
|
|
1373
|
+
if (typeof keyframe === "string" && !invalidTemplates.has(keyframe) && analyseComplexValue(keyframe).values.length) {
|
|
1374
|
+
animatableTemplate = unresolvedKeyframes[i];
|
|
1375
|
+
}
|
|
1376
|
+
i++;
|
|
1377
|
+
}
|
|
1378
|
+
if (animatableTemplate && name) {
|
|
1379
|
+
for (const noneIndex of noneKeyframeIndexes) {
|
|
1380
|
+
unresolvedKeyframes[noneIndex] = getAnimatableNone(name, animatableTemplate);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
const isNumOrPxType = (v) => v === number || v === px;
|
|
1385
|
+
const getPosFromMatrix = (matrix, pos) => parseFloat(matrix.split(", ")[pos]);
|
|
1386
|
+
const getTranslateFromMatrix = (pos2, pos3) => (_bbox, { transform }) => {
|
|
1387
|
+
if (transform === "none" || !transform)
|
|
1388
|
+
return 0;
|
|
1389
|
+
const matrix3d = transform.match(/^matrix3d\((.+)\)$/u);
|
|
1390
|
+
if (matrix3d) {
|
|
1391
|
+
return getPosFromMatrix(matrix3d[1], pos3);
|
|
1392
|
+
} else {
|
|
1393
|
+
const matrix = transform.match(/^matrix\((.+)\)$/u);
|
|
1394
|
+
if (matrix) {
|
|
1395
|
+
return getPosFromMatrix(matrix[1], pos2);
|
|
1396
|
+
} else {
|
|
1397
|
+
return 0;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
const transformKeys = /* @__PURE__ */ new Set(["x", "y", "z"]);
|
|
1402
|
+
const nonTranslationalTransformKeys = transformPropOrder.filter((key) => !transformKeys.has(key));
|
|
1403
|
+
function removeNonTranslationalTransform(visualElement) {
|
|
1404
|
+
const removedTransforms = [];
|
|
1405
|
+
nonTranslationalTransformKeys.forEach((key) => {
|
|
1406
|
+
const value = visualElement.getValue(key);
|
|
1407
|
+
if (value !== void 0) {
|
|
1408
|
+
removedTransforms.push([key, value.get()]);
|
|
1409
|
+
value.set(key.startsWith("scale") ? 1 : 0);
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
return removedTransforms;
|
|
1413
|
+
}
|
|
1414
|
+
const positionalValues = {
|
|
1415
|
+
// Dimensions
|
|
1416
|
+
width: ({ x }, { paddingLeft = "0", paddingRight = "0" }) => x.max - x.min - parseFloat(paddingLeft) - parseFloat(paddingRight),
|
|
1417
|
+
height: ({ y }, { paddingTop = "0", paddingBottom = "0" }) => y.max - y.min - parseFloat(paddingTop) - parseFloat(paddingBottom),
|
|
1418
|
+
top: (_bbox, { top }) => parseFloat(top),
|
|
1419
|
+
left: (_bbox, { left }) => parseFloat(left),
|
|
1420
|
+
bottom: ({ y }, { top }) => parseFloat(top) + (y.max - y.min),
|
|
1421
|
+
right: ({ x }, { left }) => parseFloat(left) + (x.max - x.min),
|
|
1422
|
+
// Transform
|
|
1423
|
+
x: getTranslateFromMatrix(4, 13),
|
|
1424
|
+
y: getTranslateFromMatrix(5, 14)
|
|
1425
|
+
};
|
|
1426
|
+
positionalValues.translateX = positionalValues.x;
|
|
1427
|
+
positionalValues.translateY = positionalValues.y;
|
|
1428
|
+
const toResolve = /* @__PURE__ */ new Set();
|
|
1429
|
+
let isScheduled = false;
|
|
1430
|
+
let anyNeedsMeasurement = false;
|
|
1431
|
+
function measureAllKeyframes() {
|
|
1432
|
+
if (anyNeedsMeasurement) {
|
|
1433
|
+
const resolversToMeasure = Array.from(toResolve).filter((resolver) => resolver.needsMeasurement);
|
|
1434
|
+
const elementsToMeasure = new Set(resolversToMeasure.map((resolver) => resolver.element));
|
|
1435
|
+
const transformsToRestore = /* @__PURE__ */ new Map();
|
|
1436
|
+
elementsToMeasure.forEach((element) => {
|
|
1437
|
+
const removedTransforms = removeNonTranslationalTransform(element);
|
|
1438
|
+
if (!removedTransforms.length)
|
|
1439
|
+
return;
|
|
1440
|
+
transformsToRestore.set(element, removedTransforms);
|
|
1441
|
+
element.render();
|
|
1442
|
+
});
|
|
1443
|
+
resolversToMeasure.forEach((resolver) => resolver.measureInitialState());
|
|
1444
|
+
elementsToMeasure.forEach((element) => {
|
|
1445
|
+
element.render();
|
|
1446
|
+
const restore = transformsToRestore.get(element);
|
|
1447
|
+
if (restore) {
|
|
1448
|
+
restore.forEach(([key, value]) => {
|
|
1449
|
+
var _a;
|
|
1450
|
+
(_a = element.getValue(key)) === null || _a === void 0 ? void 0 : _a.set(value);
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
});
|
|
1454
|
+
resolversToMeasure.forEach((resolver) => resolver.measureEndState());
|
|
1455
|
+
resolversToMeasure.forEach((resolver) => {
|
|
1456
|
+
if (resolver.suspendedScrollY !== void 0) {
|
|
1457
|
+
window.scrollTo(0, resolver.suspendedScrollY);
|
|
1458
|
+
}
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
anyNeedsMeasurement = false;
|
|
1462
|
+
isScheduled = false;
|
|
1463
|
+
toResolve.forEach((resolver) => resolver.complete());
|
|
1464
|
+
toResolve.clear();
|
|
1465
|
+
}
|
|
1466
|
+
function readAllKeyframes() {
|
|
1467
|
+
toResolve.forEach((resolver) => {
|
|
1468
|
+
resolver.readKeyframes();
|
|
1469
|
+
if (resolver.needsMeasurement) {
|
|
1470
|
+
anyNeedsMeasurement = true;
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
function flushKeyframeResolvers() {
|
|
1475
|
+
readAllKeyframes();
|
|
1476
|
+
measureAllKeyframes();
|
|
1477
|
+
}
|
|
1478
|
+
class KeyframeResolver {
|
|
1479
|
+
constructor(unresolvedKeyframes, onComplete, name, motionValue2, element, isAsync = false) {
|
|
1480
|
+
this.isComplete = false;
|
|
1481
|
+
this.isAsync = false;
|
|
1482
|
+
this.needsMeasurement = false;
|
|
1483
|
+
this.isScheduled = false;
|
|
1484
|
+
this.unresolvedKeyframes = [...unresolvedKeyframes];
|
|
1485
|
+
this.onComplete = onComplete;
|
|
1486
|
+
this.name = name;
|
|
1487
|
+
this.motionValue = motionValue2;
|
|
1488
|
+
this.element = element;
|
|
1489
|
+
this.isAsync = isAsync;
|
|
1490
|
+
}
|
|
1491
|
+
scheduleResolve() {
|
|
1492
|
+
this.isScheduled = true;
|
|
1493
|
+
if (this.isAsync) {
|
|
1494
|
+
toResolve.add(this);
|
|
1495
|
+
if (!isScheduled) {
|
|
1496
|
+
isScheduled = true;
|
|
1497
|
+
frame.read(readAllKeyframes);
|
|
1498
|
+
frame.resolveKeyframes(measureAllKeyframes);
|
|
1499
|
+
}
|
|
1500
|
+
} else {
|
|
1501
|
+
this.readKeyframes();
|
|
1502
|
+
this.complete();
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
readKeyframes() {
|
|
1506
|
+
const { unresolvedKeyframes, name, element, motionValue: motionValue2 } = this;
|
|
1507
|
+
for (let i = 0; i < unresolvedKeyframes.length; i++) {
|
|
1508
|
+
if (unresolvedKeyframes[i] === null) {
|
|
1509
|
+
if (i === 0) {
|
|
1510
|
+
const currentValue = motionValue2 === null || motionValue2 === void 0 ? void 0 : motionValue2.get();
|
|
1511
|
+
const finalKeyframe = unresolvedKeyframes[unresolvedKeyframes.length - 1];
|
|
1512
|
+
if (currentValue !== void 0) {
|
|
1513
|
+
unresolvedKeyframes[0] = currentValue;
|
|
1514
|
+
} else if (element && name) {
|
|
1515
|
+
const valueAsRead = element.readValue(name, finalKeyframe);
|
|
1516
|
+
if (valueAsRead !== void 0 && valueAsRead !== null) {
|
|
1517
|
+
unresolvedKeyframes[0] = valueAsRead;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
if (unresolvedKeyframes[0] === void 0) {
|
|
1521
|
+
unresolvedKeyframes[0] = finalKeyframe;
|
|
1522
|
+
}
|
|
1523
|
+
if (motionValue2 && currentValue === void 0) {
|
|
1524
|
+
motionValue2.set(unresolvedKeyframes[0]);
|
|
1525
|
+
}
|
|
1526
|
+
} else {
|
|
1527
|
+
unresolvedKeyframes[i] = unresolvedKeyframes[i - 1];
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
setFinalKeyframe() {
|
|
1533
|
+
}
|
|
1534
|
+
measureInitialState() {
|
|
1535
|
+
}
|
|
1536
|
+
renderEndStyles() {
|
|
1537
|
+
}
|
|
1538
|
+
measureEndState() {
|
|
1539
|
+
}
|
|
1540
|
+
complete() {
|
|
1541
|
+
this.isComplete = true;
|
|
1542
|
+
this.onComplete(this.unresolvedKeyframes, this.finalKeyframe);
|
|
1543
|
+
toResolve.delete(this);
|
|
1544
|
+
}
|
|
1545
|
+
cancel() {
|
|
1546
|
+
if (!this.isComplete) {
|
|
1547
|
+
this.isScheduled = false;
|
|
1548
|
+
toResolve.delete(this);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
resume() {
|
|
1552
|
+
if (!this.isComplete)
|
|
1553
|
+
this.scheduleResolve();
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
const isNumericalString = (v) => /^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(v);
|
|
1557
|
+
const splitCSSVariableRegex = (
|
|
1558
|
+
// eslint-disable-next-line redos-detector/no-unsafe-regex -- false positive, as it can match a lot of words
|
|
1559
|
+
/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u
|
|
1560
|
+
);
|
|
1561
|
+
function parseCSSVariable(current) {
|
|
1562
|
+
const match = splitCSSVariableRegex.exec(current);
|
|
1563
|
+
if (!match)
|
|
1564
|
+
return [,];
|
|
1565
|
+
const [, token1, token2, fallback] = match;
|
|
1566
|
+
return [`--${token1 !== null && token1 !== void 0 ? token1 : token2}`, fallback];
|
|
1567
|
+
}
|
|
1568
|
+
const maxDepth = 4;
|
|
1569
|
+
function getVariableValue(current, element, depth = 1) {
|
|
1570
|
+
invariant(depth <= maxDepth, `Max CSS variable fallback depth detected in property "${current}". This may indicate a circular fallback dependency.`);
|
|
1571
|
+
const [token, fallback] = parseCSSVariable(current);
|
|
1572
|
+
if (!token)
|
|
1573
|
+
return;
|
|
1574
|
+
const resolved = window.getComputedStyle(element).getPropertyValue(token);
|
|
1575
|
+
if (resolved) {
|
|
1576
|
+
const trimmed = resolved.trim();
|
|
1577
|
+
return isNumericalString(trimmed) ? parseFloat(trimmed) : trimmed;
|
|
1578
|
+
}
|
|
1579
|
+
return isCSSVariableToken(fallback) ? getVariableValue(fallback, element, depth + 1) : fallback;
|
|
1580
|
+
}
|
|
1581
|
+
const testValueType = (v) => (type) => type.test(v);
|
|
1582
|
+
const auto = {
|
|
1583
|
+
test: (v) => v === "auto",
|
|
1584
|
+
parse: (v) => v
|
|
1585
|
+
};
|
|
1586
|
+
const dimensionValueTypes = [number, px, percent, degrees, vw, vh, auto];
|
|
1587
|
+
const findDimensionValueType = (v) => dimensionValueTypes.find(testValueType(v));
|
|
1588
|
+
class DOMKeyframesResolver extends KeyframeResolver {
|
|
1589
|
+
constructor(unresolvedKeyframes, onComplete, name, motionValue2, element) {
|
|
1590
|
+
super(unresolvedKeyframes, onComplete, name, motionValue2, element, true);
|
|
1591
|
+
}
|
|
1592
|
+
readKeyframes() {
|
|
1593
|
+
const { unresolvedKeyframes, element, name } = this;
|
|
1594
|
+
if (!element || !element.current)
|
|
1595
|
+
return;
|
|
1596
|
+
super.readKeyframes();
|
|
1597
|
+
for (let i = 0; i < unresolvedKeyframes.length; i++) {
|
|
1598
|
+
let keyframe = unresolvedKeyframes[i];
|
|
1599
|
+
if (typeof keyframe === "string") {
|
|
1600
|
+
keyframe = keyframe.trim();
|
|
1601
|
+
if (isCSSVariableToken(keyframe)) {
|
|
1602
|
+
const resolved = getVariableValue(keyframe, element.current);
|
|
1603
|
+
if (resolved !== void 0) {
|
|
1604
|
+
unresolvedKeyframes[i] = resolved;
|
|
1605
|
+
}
|
|
1606
|
+
if (i === unresolvedKeyframes.length - 1) {
|
|
1607
|
+
this.finalKeyframe = keyframe;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
this.resolveNoneKeyframes();
|
|
1613
|
+
if (!positionalKeys.has(name) || unresolvedKeyframes.length !== 2) {
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
const [origin, target] = unresolvedKeyframes;
|
|
1617
|
+
const originType = findDimensionValueType(origin);
|
|
1618
|
+
const targetType = findDimensionValueType(target);
|
|
1619
|
+
if (originType === targetType)
|
|
1620
|
+
return;
|
|
1621
|
+
if (isNumOrPxType(originType) && isNumOrPxType(targetType)) {
|
|
1622
|
+
for (let i = 0; i < unresolvedKeyframes.length; i++) {
|
|
1623
|
+
const value = unresolvedKeyframes[i];
|
|
1624
|
+
if (typeof value === "string") {
|
|
1625
|
+
unresolvedKeyframes[i] = parseFloat(value);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
} else {
|
|
1629
|
+
this.needsMeasurement = true;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
resolveNoneKeyframes() {
|
|
1633
|
+
const { unresolvedKeyframes, name } = this;
|
|
1634
|
+
const noneKeyframeIndexes = [];
|
|
1635
|
+
for (let i = 0; i < unresolvedKeyframes.length; i++) {
|
|
1636
|
+
if (isNone(unresolvedKeyframes[i])) {
|
|
1637
|
+
noneKeyframeIndexes.push(i);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
if (noneKeyframeIndexes.length) {
|
|
1641
|
+
makeNoneKeyframesAnimatable(unresolvedKeyframes, noneKeyframeIndexes, name);
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
measureInitialState() {
|
|
1645
|
+
const { element, unresolvedKeyframes, name } = this;
|
|
1646
|
+
if (!element || !element.current)
|
|
1647
|
+
return;
|
|
1648
|
+
if (name === "height") {
|
|
1649
|
+
this.suspendedScrollY = window.pageYOffset;
|
|
1650
|
+
}
|
|
1651
|
+
this.measuredOrigin = positionalValues[name](element.measureViewportBox(), window.getComputedStyle(element.current));
|
|
1652
|
+
unresolvedKeyframes[0] = this.measuredOrigin;
|
|
1653
|
+
const measureKeyframe = unresolvedKeyframes[unresolvedKeyframes.length - 1];
|
|
1654
|
+
if (measureKeyframe !== void 0) {
|
|
1655
|
+
element.getValue(name, measureKeyframe).jump(measureKeyframe, false);
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
measureEndState() {
|
|
1659
|
+
var _a;
|
|
1660
|
+
const { element, name, unresolvedKeyframes } = this;
|
|
1661
|
+
if (!element || !element.current)
|
|
1662
|
+
return;
|
|
1663
|
+
const value = element.getValue(name);
|
|
1664
|
+
value && value.jump(this.measuredOrigin, false);
|
|
1665
|
+
const finalKeyframeIndex = unresolvedKeyframes.length - 1;
|
|
1666
|
+
const finalKeyframe = unresolvedKeyframes[finalKeyframeIndex];
|
|
1667
|
+
unresolvedKeyframes[finalKeyframeIndex] = positionalValues[name](element.measureViewportBox(), window.getComputedStyle(element.current));
|
|
1668
|
+
if (finalKeyframe !== null && this.finalKeyframe === void 0) {
|
|
1669
|
+
this.finalKeyframe = finalKeyframe;
|
|
1670
|
+
}
|
|
1671
|
+
if ((_a = this.removedTransforms) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1672
|
+
this.removedTransforms.forEach(([unsetTransformName, unsetTransformValue]) => {
|
|
1673
|
+
element.getValue(unsetTransformName).set(unsetTransformValue);
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
this.resolveNoneKeyframes();
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
const isAnimatable = (value, name) => {
|
|
1680
|
+
if (name === "zIndex")
|
|
1681
|
+
return false;
|
|
1682
|
+
if (typeof value === "number" || Array.isArray(value))
|
|
1683
|
+
return true;
|
|
1684
|
+
if (typeof value === "string" && // It's animatable if we have a string
|
|
1685
|
+
(complex.test(value) || value === "0") && // And it contains numbers and/or colors
|
|
1686
|
+
!value.startsWith("url(")) {
|
|
1687
|
+
return true;
|
|
1688
|
+
}
|
|
1689
|
+
return false;
|
|
1690
|
+
};
|
|
1691
|
+
function hasKeyframesChanged(keyframes2) {
|
|
1692
|
+
const current = keyframes2[0];
|
|
1693
|
+
if (keyframes2.length === 1)
|
|
1694
|
+
return true;
|
|
1695
|
+
for (let i = 0; i < keyframes2.length; i++) {
|
|
1696
|
+
if (keyframes2[i] !== current)
|
|
1697
|
+
return true;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
function canAnimate(keyframes2, name, type, velocity) {
|
|
1701
|
+
const originKeyframe = keyframes2[0];
|
|
1702
|
+
if (originKeyframe === null)
|
|
1703
|
+
return false;
|
|
1704
|
+
if (name === "display" || name === "visibility")
|
|
1705
|
+
return true;
|
|
1706
|
+
const targetKeyframe = keyframes2[keyframes2.length - 1];
|
|
1707
|
+
const isOriginAnimatable = isAnimatable(originKeyframe, name);
|
|
1708
|
+
const isTargetAnimatable = isAnimatable(targetKeyframe, name);
|
|
1709
|
+
warning(isOriginAnimatable === isTargetAnimatable, `You are trying to animate ${name} from "${originKeyframe}" to "${targetKeyframe}". ${originKeyframe} is not an animatable value - to enable this animation set ${originKeyframe} to a value animatable to ${targetKeyframe} via the \`style\` property.`);
|
|
1710
|
+
if (!isOriginAnimatable || !isTargetAnimatable) {
|
|
1711
|
+
return false;
|
|
1712
|
+
}
|
|
1713
|
+
return hasKeyframesChanged(keyframes2) || (type === "spring" || isGenerator(type)) && velocity;
|
|
1714
|
+
}
|
|
1715
|
+
const isNotNull = (value) => value !== null;
|
|
1716
|
+
function getFinalKeyframe(keyframes2, { repeat, repeatType = "loop" }, finalKeyframe) {
|
|
1717
|
+
const resolvedKeyframes = keyframes2.filter(isNotNull);
|
|
1718
|
+
const index = repeat && repeatType !== "loop" && repeat % 2 === 1 ? 0 : resolvedKeyframes.length - 1;
|
|
1719
|
+
return !index || finalKeyframe === void 0 ? resolvedKeyframes[index] : finalKeyframe;
|
|
1720
|
+
}
|
|
1721
|
+
const MAX_RESOLVE_DELAY = 40;
|
|
1722
|
+
class BaseAnimation {
|
|
1723
|
+
constructor({ autoplay = true, delay = 0, type = "keyframes", repeat = 0, repeatDelay = 0, repeatType = "loop", ...options }) {
|
|
1724
|
+
this.isStopped = false;
|
|
1725
|
+
this.hasAttemptedResolve = false;
|
|
1726
|
+
this.createdAt = time.now();
|
|
1727
|
+
this.options = {
|
|
1728
|
+
autoplay,
|
|
1729
|
+
delay,
|
|
1730
|
+
type,
|
|
1731
|
+
repeat,
|
|
1732
|
+
repeatDelay,
|
|
1733
|
+
repeatType,
|
|
1734
|
+
...options
|
|
1735
|
+
};
|
|
1736
|
+
this.updateFinishedPromise();
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1739
|
+
* This method uses the createdAt and resolvedAt to calculate the
|
|
1740
|
+
* animation startTime. *Ideally*, we would use the createdAt time as t=0
|
|
1741
|
+
* as the following frame would then be the first frame of the animation in
|
|
1742
|
+
* progress, which would feel snappier.
|
|
1743
|
+
*
|
|
1744
|
+
* However, if there's a delay (main thread work) between the creation of
|
|
1745
|
+
* the animation and the first commited frame, we prefer to use resolvedAt
|
|
1746
|
+
* to avoid a sudden jump into the animation.
|
|
1747
|
+
*/
|
|
1748
|
+
calcStartTime() {
|
|
1749
|
+
if (!this.resolvedAt)
|
|
1750
|
+
return this.createdAt;
|
|
1751
|
+
return this.resolvedAt - this.createdAt > MAX_RESOLVE_DELAY ? this.resolvedAt : this.createdAt;
|
|
1752
|
+
}
|
|
1753
|
+
/**
|
|
1754
|
+
* A getter for resolved data. If keyframes are not yet resolved, accessing
|
|
1755
|
+
* this.resolved will synchronously flush all pending keyframe resolvers.
|
|
1756
|
+
* This is a deoptimisation, but at its worst still batches read/writes.
|
|
1757
|
+
*/
|
|
1758
|
+
get resolved() {
|
|
1759
|
+
if (!this._resolved && !this.hasAttemptedResolve) {
|
|
1760
|
+
flushKeyframeResolvers();
|
|
1761
|
+
}
|
|
1762
|
+
return this._resolved;
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* A method to be called when the keyframes resolver completes. This method
|
|
1766
|
+
* will check if its possible to run the animation and, if not, skip it.
|
|
1767
|
+
* Otherwise, it will call initPlayback on the implementing class.
|
|
1768
|
+
*/
|
|
1769
|
+
onKeyframesResolved(keyframes2, finalKeyframe) {
|
|
1770
|
+
this.resolvedAt = time.now();
|
|
1771
|
+
this.hasAttemptedResolve = true;
|
|
1772
|
+
const { name, type, velocity, delay, onComplete, onUpdate, isGenerator: isGenerator2 } = this.options;
|
|
1773
|
+
if (!isGenerator2 && !canAnimate(keyframes2, name, type, velocity)) {
|
|
1774
|
+
if (!delay) {
|
|
1775
|
+
onUpdate && onUpdate(getFinalKeyframe(keyframes2, this.options, finalKeyframe));
|
|
1776
|
+
onComplete && onComplete();
|
|
1777
|
+
this.resolveFinishedPromise();
|
|
1778
|
+
return;
|
|
1779
|
+
} else {
|
|
1780
|
+
this.options.duration = 0;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
const resolvedAnimation = this.initPlayback(keyframes2, finalKeyframe);
|
|
1784
|
+
if (resolvedAnimation === false)
|
|
1785
|
+
return;
|
|
1786
|
+
this._resolved = {
|
|
1787
|
+
keyframes: keyframes2,
|
|
1788
|
+
finalKeyframe,
|
|
1789
|
+
...resolvedAnimation
|
|
1790
|
+
};
|
|
1791
|
+
this.onPostResolved();
|
|
1792
|
+
}
|
|
1793
|
+
onPostResolved() {
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* Allows the returned animation to be awaited or promise-chained. Currently
|
|
1797
|
+
* resolves when the animation finishes at all but in a future update could/should
|
|
1798
|
+
* reject if its cancels.
|
|
1799
|
+
*/
|
|
1800
|
+
then(resolve, reject) {
|
|
1801
|
+
return this.currentFinishedPromise.then(resolve, reject);
|
|
1802
|
+
}
|
|
1803
|
+
flatten() {
|
|
1804
|
+
this.options.type = "keyframes";
|
|
1805
|
+
this.options.ease = "linear";
|
|
1806
|
+
}
|
|
1807
|
+
updateFinishedPromise() {
|
|
1808
|
+
this.currentFinishedPromise = new Promise((resolve) => {
|
|
1809
|
+
this.resolveFinishedPromise = resolve;
|
|
1810
|
+
});
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
const maxGeneratorDuration = 2e4;
|
|
1814
|
+
function calcGeneratorDuration(generator) {
|
|
1815
|
+
let duration = 0;
|
|
1816
|
+
const timeStep = 50;
|
|
1817
|
+
let state = generator.next(duration);
|
|
1818
|
+
while (!state.done && duration < maxGeneratorDuration) {
|
|
1819
|
+
duration += timeStep;
|
|
1820
|
+
state = generator.next(duration);
|
|
1821
|
+
}
|
|
1822
|
+
return duration >= maxGeneratorDuration ? Infinity : duration;
|
|
1823
|
+
}
|
|
1824
|
+
const mixNumber$1 = (from, to, progress2) => {
|
|
1825
|
+
return from + (to - from) * progress2;
|
|
1826
|
+
};
|
|
1827
|
+
function hueToRgb(p, q, t) {
|
|
1828
|
+
if (t < 0)
|
|
1829
|
+
t += 1;
|
|
1830
|
+
if (t > 1)
|
|
1831
|
+
t -= 1;
|
|
1832
|
+
if (t < 1 / 6)
|
|
1833
|
+
return p + (q - p) * 6 * t;
|
|
1834
|
+
if (t < 1 / 2)
|
|
1835
|
+
return q;
|
|
1836
|
+
if (t < 2 / 3)
|
|
1837
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
1838
|
+
return p;
|
|
1839
|
+
}
|
|
1840
|
+
function hslaToRgba({ hue, saturation, lightness, alpha: alpha2 }) {
|
|
1841
|
+
hue /= 360;
|
|
1842
|
+
saturation /= 100;
|
|
1843
|
+
lightness /= 100;
|
|
1844
|
+
let red = 0;
|
|
1845
|
+
let green = 0;
|
|
1846
|
+
let blue = 0;
|
|
1847
|
+
if (!saturation) {
|
|
1848
|
+
red = green = blue = lightness;
|
|
1849
|
+
} else {
|
|
1850
|
+
const q = lightness < 0.5 ? lightness * (1 + saturation) : lightness + saturation - lightness * saturation;
|
|
1851
|
+
const p = 2 * lightness - q;
|
|
1852
|
+
red = hueToRgb(p, q, hue + 1 / 3);
|
|
1853
|
+
green = hueToRgb(p, q, hue);
|
|
1854
|
+
blue = hueToRgb(p, q, hue - 1 / 3);
|
|
1855
|
+
}
|
|
1856
|
+
return {
|
|
1857
|
+
red: Math.round(red * 255),
|
|
1858
|
+
green: Math.round(green * 255),
|
|
1859
|
+
blue: Math.round(blue * 255),
|
|
1860
|
+
alpha: alpha2
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
function mixImmediate(a, b) {
|
|
1864
|
+
return (p) => p > 0 ? b : a;
|
|
1865
|
+
}
|
|
1866
|
+
const mixLinearColor = (from, to, v) => {
|
|
1867
|
+
const fromExpo = from * from;
|
|
1868
|
+
const expo = v * (to * to - fromExpo) + fromExpo;
|
|
1869
|
+
return expo < 0 ? 0 : Math.sqrt(expo);
|
|
1870
|
+
};
|
|
1871
|
+
const colorTypes = [hex, rgba, hsla];
|
|
1872
|
+
const getColorType = (v) => colorTypes.find((type) => type.test(v));
|
|
1873
|
+
function asRGBA(color2) {
|
|
1874
|
+
const type = getColorType(color2);
|
|
1875
|
+
warning(Boolean(type), `'${color2}' is not an animatable color. Use the equivalent color code instead.`);
|
|
1876
|
+
if (!Boolean(type))
|
|
1877
|
+
return false;
|
|
1878
|
+
let model = type.parse(color2);
|
|
1879
|
+
if (type === hsla) {
|
|
1880
|
+
model = hslaToRgba(model);
|
|
1881
|
+
}
|
|
1882
|
+
return model;
|
|
1883
|
+
}
|
|
1884
|
+
const mixColor = (from, to) => {
|
|
1885
|
+
const fromRGBA = asRGBA(from);
|
|
1886
|
+
const toRGBA = asRGBA(to);
|
|
1887
|
+
if (!fromRGBA || !toRGBA) {
|
|
1888
|
+
return mixImmediate(from, to);
|
|
1889
|
+
}
|
|
1890
|
+
const blended = { ...fromRGBA };
|
|
1891
|
+
return (v) => {
|
|
1892
|
+
blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
|
|
1893
|
+
blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
|
|
1894
|
+
blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
|
|
1895
|
+
blended.alpha = mixNumber$1(fromRGBA.alpha, toRGBA.alpha, v);
|
|
1896
|
+
return rgba.transform(blended);
|
|
1897
|
+
};
|
|
1898
|
+
};
|
|
1899
|
+
const combineFunctions = (a, b) => (v) => b(a(v));
|
|
1900
|
+
const pipe = (...transformers) => transformers.reduce(combineFunctions);
|
|
1901
|
+
const invisibleValues = /* @__PURE__ */ new Set(["none", "hidden"]);
|
|
1902
|
+
function mixVisibility(origin, target) {
|
|
1903
|
+
if (invisibleValues.has(origin)) {
|
|
1904
|
+
return (p) => p <= 0 ? origin : target;
|
|
1905
|
+
} else {
|
|
1906
|
+
return (p) => p >= 1 ? target : origin;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
function mixNumber(a, b) {
|
|
1910
|
+
return (p) => mixNumber$1(a, b, p);
|
|
1911
|
+
}
|
|
1912
|
+
function getMixer(a) {
|
|
1913
|
+
if (typeof a === "number") {
|
|
1914
|
+
return mixNumber;
|
|
1915
|
+
} else if (typeof a === "string") {
|
|
1916
|
+
return isCSSVariableToken(a) ? mixImmediate : color.test(a) ? mixColor : mixComplex;
|
|
1917
|
+
} else if (Array.isArray(a)) {
|
|
1918
|
+
return mixArray;
|
|
1919
|
+
} else if (typeof a === "object") {
|
|
1920
|
+
return color.test(a) ? mixColor : mixObject;
|
|
1921
|
+
}
|
|
1922
|
+
return mixImmediate;
|
|
1923
|
+
}
|
|
1924
|
+
function mixArray(a, b) {
|
|
1925
|
+
const output = [...a];
|
|
1926
|
+
const numValues = output.length;
|
|
1927
|
+
const blendValue = a.map((v, i) => getMixer(v)(v, b[i]));
|
|
1928
|
+
return (p) => {
|
|
1929
|
+
for (let i = 0; i < numValues; i++) {
|
|
1930
|
+
output[i] = blendValue[i](p);
|
|
1931
|
+
}
|
|
1932
|
+
return output;
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
function mixObject(a, b) {
|
|
1936
|
+
const output = { ...a, ...b };
|
|
1937
|
+
const blendValue = {};
|
|
1938
|
+
for (const key in output) {
|
|
1939
|
+
if (a[key] !== void 0 && b[key] !== void 0) {
|
|
1940
|
+
blendValue[key] = getMixer(a[key])(a[key], b[key]);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
return (v) => {
|
|
1944
|
+
for (const key in blendValue) {
|
|
1945
|
+
output[key] = blendValue[key](v);
|
|
1946
|
+
}
|
|
1947
|
+
return output;
|
|
1948
|
+
};
|
|
1949
|
+
}
|
|
1950
|
+
function matchOrder(origin, target) {
|
|
1951
|
+
var _a;
|
|
1952
|
+
const orderedOrigin = [];
|
|
1953
|
+
const pointers = { color: 0, var: 0, number: 0 };
|
|
1954
|
+
for (let i = 0; i < target.values.length; i++) {
|
|
1955
|
+
const type = target.types[i];
|
|
1956
|
+
const originIndex = origin.indexes[type][pointers[type]];
|
|
1957
|
+
const originValue = (_a = origin.values[originIndex]) !== null && _a !== void 0 ? _a : 0;
|
|
1958
|
+
orderedOrigin[i] = originValue;
|
|
1959
|
+
pointers[type]++;
|
|
1960
|
+
}
|
|
1961
|
+
return orderedOrigin;
|
|
1962
|
+
}
|
|
1963
|
+
const mixComplex = (origin, target) => {
|
|
1964
|
+
const template = complex.createTransformer(target);
|
|
1965
|
+
const originStats = analyseComplexValue(origin);
|
|
1966
|
+
const targetStats = analyseComplexValue(target);
|
|
1967
|
+
const canInterpolate = originStats.indexes.var.length === targetStats.indexes.var.length && originStats.indexes.color.length === targetStats.indexes.color.length && originStats.indexes.number.length >= targetStats.indexes.number.length;
|
|
1968
|
+
if (canInterpolate) {
|
|
1969
|
+
if (invisibleValues.has(origin) && !targetStats.values.length || invisibleValues.has(target) && !originStats.values.length) {
|
|
1970
|
+
return mixVisibility(origin, target);
|
|
1971
|
+
}
|
|
1972
|
+
return pipe(mixArray(matchOrder(originStats, targetStats), targetStats.values), template);
|
|
1973
|
+
} else {
|
|
1974
|
+
warning(true, `Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`);
|
|
1975
|
+
return mixImmediate(origin, target);
|
|
1976
|
+
}
|
|
1977
|
+
};
|
|
1978
|
+
function mix(from, to, p) {
|
|
1979
|
+
if (typeof from === "number" && typeof to === "number" && typeof p === "number") {
|
|
1980
|
+
return mixNumber$1(from, to, p);
|
|
1981
|
+
}
|
|
1982
|
+
const mixer = getMixer(from);
|
|
1983
|
+
return mixer(from, to);
|
|
1984
|
+
}
|
|
1985
|
+
const velocitySampleDuration = 5;
|
|
1986
|
+
function calcGeneratorVelocity(resolveValue, t, current) {
|
|
1987
|
+
const prevT = Math.max(t - velocitySampleDuration, 0);
|
|
1988
|
+
return velocityPerSecond(current - resolveValue(prevT), t - prevT);
|
|
1989
|
+
}
|
|
1990
|
+
const springDefaults = {
|
|
1991
|
+
// Default spring physics
|
|
1992
|
+
stiffness: 100,
|
|
1993
|
+
damping: 10,
|
|
1994
|
+
mass: 1,
|
|
1995
|
+
velocity: 0,
|
|
1996
|
+
// Default duration/bounce-based options
|
|
1997
|
+
duration: 800,
|
|
1998
|
+
// in ms
|
|
1999
|
+
bounce: 0.3,
|
|
2000
|
+
visualDuration: 0.3,
|
|
2001
|
+
// in seconds
|
|
2002
|
+
// Rest thresholds
|
|
2003
|
+
restSpeed: {
|
|
2004
|
+
granular: 0.01,
|
|
2005
|
+
default: 2
|
|
2006
|
+
},
|
|
2007
|
+
restDelta: {
|
|
2008
|
+
granular: 5e-3,
|
|
2009
|
+
default: 0.5
|
|
2010
|
+
},
|
|
2011
|
+
// Limits
|
|
2012
|
+
minDuration: 0.01,
|
|
2013
|
+
// in seconds
|
|
2014
|
+
maxDuration: 10,
|
|
2015
|
+
// in seconds
|
|
2016
|
+
minDamping: 0.05,
|
|
2017
|
+
maxDamping: 1
|
|
2018
|
+
};
|
|
2019
|
+
const safeMin = 1e-3;
|
|
2020
|
+
function findSpring({ duration = springDefaults.duration, bounce = springDefaults.bounce, velocity = springDefaults.velocity, mass = springDefaults.mass }) {
|
|
2021
|
+
let envelope;
|
|
2022
|
+
let derivative;
|
|
2023
|
+
warning(duration <= /* @__PURE__ */ secondsToMilliseconds(springDefaults.maxDuration), "Spring duration must be 10 seconds or less");
|
|
2024
|
+
let dampingRatio = 1 - bounce;
|
|
2025
|
+
dampingRatio = clamp(springDefaults.minDamping, springDefaults.maxDamping, dampingRatio);
|
|
2026
|
+
duration = clamp(springDefaults.minDuration, springDefaults.maxDuration, /* @__PURE__ */ millisecondsToSeconds(duration));
|
|
2027
|
+
if (dampingRatio < 1) {
|
|
2028
|
+
envelope = (undampedFreq2) => {
|
|
2029
|
+
const exponentialDecay = undampedFreq2 * dampingRatio;
|
|
2030
|
+
const delta = exponentialDecay * duration;
|
|
2031
|
+
const a = exponentialDecay - velocity;
|
|
2032
|
+
const b = calcAngularFreq(undampedFreq2, dampingRatio);
|
|
2033
|
+
const c = Math.exp(-delta);
|
|
2034
|
+
return safeMin - a / b * c;
|
|
2035
|
+
};
|
|
2036
|
+
derivative = (undampedFreq2) => {
|
|
2037
|
+
const exponentialDecay = undampedFreq2 * dampingRatio;
|
|
2038
|
+
const delta = exponentialDecay * duration;
|
|
2039
|
+
const d = delta * velocity + velocity;
|
|
2040
|
+
const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq2, 2) * duration;
|
|
2041
|
+
const f = Math.exp(-delta);
|
|
2042
|
+
const g = calcAngularFreq(Math.pow(undampedFreq2, 2), dampingRatio);
|
|
2043
|
+
const factor = -envelope(undampedFreq2) + safeMin > 0 ? -1 : 1;
|
|
2044
|
+
return factor * ((d - e) * f) / g;
|
|
2045
|
+
};
|
|
2046
|
+
} else {
|
|
2047
|
+
envelope = (undampedFreq2) => {
|
|
2048
|
+
const a = Math.exp(-undampedFreq2 * duration);
|
|
2049
|
+
const b = (undampedFreq2 - velocity) * duration + 1;
|
|
2050
|
+
return -1e-3 + a * b;
|
|
2051
|
+
};
|
|
2052
|
+
derivative = (undampedFreq2) => {
|
|
2053
|
+
const a = Math.exp(-undampedFreq2 * duration);
|
|
2054
|
+
const b = (velocity - undampedFreq2) * (duration * duration);
|
|
2055
|
+
return a * b;
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
2058
|
+
const initialGuess = 5 / duration;
|
|
2059
|
+
const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
|
|
2060
|
+
duration = /* @__PURE__ */ secondsToMilliseconds(duration);
|
|
2061
|
+
if (isNaN(undampedFreq)) {
|
|
2062
|
+
return {
|
|
2063
|
+
stiffness: springDefaults.stiffness,
|
|
2064
|
+
damping: springDefaults.damping,
|
|
2065
|
+
duration
|
|
2066
|
+
};
|
|
2067
|
+
} else {
|
|
2068
|
+
const stiffness = Math.pow(undampedFreq, 2) * mass;
|
|
2069
|
+
return {
|
|
2070
|
+
stiffness,
|
|
2071
|
+
damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
|
|
2072
|
+
duration
|
|
2073
|
+
};
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
const rootIterations = 12;
|
|
2077
|
+
function approximateRoot(envelope, derivative, initialGuess) {
|
|
2078
|
+
let result = initialGuess;
|
|
2079
|
+
for (let i = 1; i < rootIterations; i++) {
|
|
2080
|
+
result = result - envelope(result) / derivative(result);
|
|
2081
|
+
}
|
|
2082
|
+
return result;
|
|
2083
|
+
}
|
|
2084
|
+
function calcAngularFreq(undampedFreq, dampingRatio) {
|
|
2085
|
+
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
2086
|
+
}
|
|
2087
|
+
const durationKeys = ["duration", "bounce"];
|
|
2088
|
+
const physicsKeys = ["stiffness", "damping", "mass"];
|
|
2089
|
+
function isSpringType(options, keys) {
|
|
2090
|
+
return keys.some((key) => options[key] !== void 0);
|
|
2091
|
+
}
|
|
2092
|
+
function getSpringOptions(options) {
|
|
2093
|
+
let springOptions = {
|
|
2094
|
+
velocity: springDefaults.velocity,
|
|
2095
|
+
stiffness: springDefaults.stiffness,
|
|
2096
|
+
damping: springDefaults.damping,
|
|
2097
|
+
mass: springDefaults.mass,
|
|
2098
|
+
isResolvedFromDuration: false,
|
|
2099
|
+
...options
|
|
2100
|
+
};
|
|
2101
|
+
if (!isSpringType(options, physicsKeys) && isSpringType(options, durationKeys)) {
|
|
2102
|
+
if (options.visualDuration) {
|
|
2103
|
+
const visualDuration = options.visualDuration;
|
|
2104
|
+
const root = 2 * Math.PI / (visualDuration * 1.2);
|
|
2105
|
+
const stiffness = root * root;
|
|
2106
|
+
const damping = 2 * clamp(0.05, 1, 1 - (options.bounce || 0)) * Math.sqrt(stiffness);
|
|
2107
|
+
springOptions = {
|
|
2108
|
+
...springOptions,
|
|
2109
|
+
mass: springDefaults.mass,
|
|
2110
|
+
stiffness,
|
|
2111
|
+
damping
|
|
2112
|
+
};
|
|
2113
|
+
} else {
|
|
2114
|
+
const derived = findSpring(options);
|
|
2115
|
+
springOptions = {
|
|
2116
|
+
...springOptions,
|
|
2117
|
+
...derived,
|
|
2118
|
+
mass: springDefaults.mass
|
|
2119
|
+
};
|
|
2120
|
+
springOptions.isResolvedFromDuration = true;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
return springOptions;
|
|
2124
|
+
}
|
|
2125
|
+
function spring(optionsOrVisualDuration = springDefaults.visualDuration, bounce = springDefaults.bounce) {
|
|
2126
|
+
const options = typeof optionsOrVisualDuration !== "object" ? {
|
|
2127
|
+
visualDuration: optionsOrVisualDuration,
|
|
2128
|
+
keyframes: [0, 1],
|
|
2129
|
+
bounce
|
|
2130
|
+
} : optionsOrVisualDuration;
|
|
2131
|
+
let { restSpeed, restDelta } = options;
|
|
2132
|
+
const origin = options.keyframes[0];
|
|
2133
|
+
const target = options.keyframes[options.keyframes.length - 1];
|
|
2134
|
+
const state = { done: false, value: origin };
|
|
2135
|
+
const { stiffness, damping, mass, duration, velocity, isResolvedFromDuration } = getSpringOptions({
|
|
2136
|
+
...options,
|
|
2137
|
+
velocity: -/* @__PURE__ */ millisecondsToSeconds(options.velocity || 0)
|
|
2138
|
+
});
|
|
2139
|
+
const initialVelocity = velocity || 0;
|
|
2140
|
+
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
|
|
2141
|
+
const initialDelta = target - origin;
|
|
2142
|
+
const undampedAngularFreq = /* @__PURE__ */ millisecondsToSeconds(Math.sqrt(stiffness / mass));
|
|
2143
|
+
const isGranularScale = Math.abs(initialDelta) < 5;
|
|
2144
|
+
restSpeed || (restSpeed = isGranularScale ? springDefaults.restSpeed.granular : springDefaults.restSpeed.default);
|
|
2145
|
+
restDelta || (restDelta = isGranularScale ? springDefaults.restDelta.granular : springDefaults.restDelta.default);
|
|
2146
|
+
let resolveSpring;
|
|
2147
|
+
if (dampingRatio < 1) {
|
|
2148
|
+
const angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
|
|
2149
|
+
resolveSpring = (t) => {
|
|
2150
|
+
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2151
|
+
return target - envelope * ((initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) / angularFreq * Math.sin(angularFreq * t) + initialDelta * Math.cos(angularFreq * t));
|
|
2152
|
+
};
|
|
2153
|
+
} else if (dampingRatio === 1) {
|
|
2154
|
+
resolveSpring = (t) => target - Math.exp(-undampedAngularFreq * t) * (initialDelta + (initialVelocity + undampedAngularFreq * initialDelta) * t);
|
|
2155
|
+
} else {
|
|
2156
|
+
const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
|
|
2157
|
+
resolveSpring = (t) => {
|
|
2158
|
+
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2159
|
+
const freqForT = Math.min(dampedAngularFreq * t, 300);
|
|
2160
|
+
return target - envelope * ((initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) * Math.sinh(freqForT) + dampedAngularFreq * initialDelta * Math.cosh(freqForT)) / dampedAngularFreq;
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
const generator = {
|
|
2164
|
+
calculatedDuration: isResolvedFromDuration ? duration || null : null,
|
|
2165
|
+
next: (t) => {
|
|
2166
|
+
const current = resolveSpring(t);
|
|
2167
|
+
if (!isResolvedFromDuration) {
|
|
2168
|
+
let currentVelocity = 0;
|
|
2169
|
+
if (dampingRatio < 1) {
|
|
2170
|
+
currentVelocity = t === 0 ? /* @__PURE__ */ secondsToMilliseconds(initialVelocity) : calcGeneratorVelocity(resolveSpring, t, current);
|
|
2171
|
+
}
|
|
2172
|
+
const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
|
|
2173
|
+
const isBelowDisplacementThreshold = Math.abs(target - current) <= restDelta;
|
|
2174
|
+
state.done = isBelowVelocityThreshold && isBelowDisplacementThreshold;
|
|
2175
|
+
} else {
|
|
2176
|
+
state.done = t >= duration;
|
|
2177
|
+
}
|
|
2178
|
+
state.value = state.done ? target : current;
|
|
2179
|
+
return state;
|
|
2180
|
+
},
|
|
2181
|
+
toString: () => {
|
|
2182
|
+
const calculatedDuration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
|
|
2183
|
+
const easing = generateLinearEasing((progress2) => generator.next(calculatedDuration * progress2).value, calculatedDuration, 30);
|
|
2184
|
+
return calculatedDuration + "ms " + easing;
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
2187
|
+
return generator;
|
|
2188
|
+
}
|
|
2189
|
+
function inertia({ keyframes: keyframes2, velocity = 0, power = 0.8, timeConstant = 325, bounceDamping = 10, bounceStiffness = 500, modifyTarget, min, max, restDelta = 0.5, restSpeed }) {
|
|
2190
|
+
const origin = keyframes2[0];
|
|
2191
|
+
const state = {
|
|
2192
|
+
done: false,
|
|
2193
|
+
value: origin
|
|
2194
|
+
};
|
|
2195
|
+
const isOutOfBounds = (v) => min !== void 0 && v < min || max !== void 0 && v > max;
|
|
2196
|
+
const nearestBoundary = (v) => {
|
|
2197
|
+
if (min === void 0)
|
|
2198
|
+
return max;
|
|
2199
|
+
if (max === void 0)
|
|
2200
|
+
return min;
|
|
2201
|
+
return Math.abs(min - v) < Math.abs(max - v) ? min : max;
|
|
2202
|
+
};
|
|
2203
|
+
let amplitude = power * velocity;
|
|
2204
|
+
const ideal = origin + amplitude;
|
|
2205
|
+
const target = modifyTarget === void 0 ? ideal : modifyTarget(ideal);
|
|
2206
|
+
if (target !== ideal)
|
|
2207
|
+
amplitude = target - origin;
|
|
2208
|
+
const calcDelta = (t) => -amplitude * Math.exp(-t / timeConstant);
|
|
2209
|
+
const calcLatest = (t) => target + calcDelta(t);
|
|
2210
|
+
const applyFriction = (t) => {
|
|
2211
|
+
const delta = calcDelta(t);
|
|
2212
|
+
const latest = calcLatest(t);
|
|
2213
|
+
state.done = Math.abs(delta) <= restDelta;
|
|
2214
|
+
state.value = state.done ? target : latest;
|
|
2215
|
+
};
|
|
2216
|
+
let timeReachedBoundary;
|
|
2217
|
+
let spring$1;
|
|
2218
|
+
const checkCatchBoundary = (t) => {
|
|
2219
|
+
if (!isOutOfBounds(state.value))
|
|
2220
|
+
return;
|
|
2221
|
+
timeReachedBoundary = t;
|
|
2222
|
+
spring$1 = spring({
|
|
2223
|
+
keyframes: [state.value, nearestBoundary(state.value)],
|
|
2224
|
+
velocity: calcGeneratorVelocity(calcLatest, t, state.value),
|
|
2225
|
+
// TODO: This should be passing * 1000
|
|
2226
|
+
damping: bounceDamping,
|
|
2227
|
+
stiffness: bounceStiffness,
|
|
2228
|
+
restDelta,
|
|
2229
|
+
restSpeed
|
|
2230
|
+
});
|
|
2231
|
+
};
|
|
2232
|
+
checkCatchBoundary(0);
|
|
2233
|
+
return {
|
|
2234
|
+
calculatedDuration: null,
|
|
2235
|
+
next: (t) => {
|
|
2236
|
+
let hasUpdatedFrame = false;
|
|
2237
|
+
if (!spring$1 && timeReachedBoundary === void 0) {
|
|
2238
|
+
hasUpdatedFrame = true;
|
|
2239
|
+
applyFriction(t);
|
|
2240
|
+
checkCatchBoundary(t);
|
|
2241
|
+
}
|
|
2242
|
+
if (timeReachedBoundary !== void 0 && t >= timeReachedBoundary) {
|
|
2243
|
+
return spring$1.next(t - timeReachedBoundary);
|
|
2244
|
+
} else {
|
|
2245
|
+
!hasUpdatedFrame && applyFriction(t);
|
|
2246
|
+
return state;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
};
|
|
2250
|
+
}
|
|
2251
|
+
const easeIn = /* @__PURE__ */ cubicBezier(0.42, 0, 1, 1);
|
|
2252
|
+
const easeOut = /* @__PURE__ */ cubicBezier(0, 0, 0.58, 1);
|
|
2253
|
+
const easeInOut = /* @__PURE__ */ cubicBezier(0.42, 0, 0.58, 1);
|
|
2254
|
+
const isEasingArray = (ease2) => {
|
|
2255
|
+
return Array.isArray(ease2) && typeof ease2[0] !== "number";
|
|
2256
|
+
};
|
|
2257
|
+
const easingLookup = {
|
|
2258
|
+
linear: noop,
|
|
2259
|
+
easeIn,
|
|
2260
|
+
easeInOut,
|
|
2261
|
+
easeOut,
|
|
2262
|
+
circIn,
|
|
2263
|
+
circInOut,
|
|
2264
|
+
circOut,
|
|
2265
|
+
backIn,
|
|
2266
|
+
backInOut,
|
|
2267
|
+
backOut,
|
|
2268
|
+
anticipate
|
|
2269
|
+
};
|
|
2270
|
+
const easingDefinitionToFunction = (definition) => {
|
|
2271
|
+
if (isBezierDefinition(definition)) {
|
|
2272
|
+
invariant(definition.length === 4, `Cubic bezier arrays must contain four numerical values.`);
|
|
2273
|
+
const [x1, y1, x2, y2] = definition;
|
|
2274
|
+
return cubicBezier(x1, y1, x2, y2);
|
|
2275
|
+
} else if (typeof definition === "string") {
|
|
2276
|
+
invariant(easingLookup[definition] !== void 0, `Invalid easing type '${definition}'`);
|
|
2277
|
+
return easingLookup[definition];
|
|
2278
|
+
}
|
|
2279
|
+
return definition;
|
|
2280
|
+
};
|
|
2281
|
+
function createMixers(output, ease2, customMixer) {
|
|
2282
|
+
const mixers = [];
|
|
2283
|
+
const mixerFactory = customMixer || mix;
|
|
2284
|
+
const numMixers = output.length - 1;
|
|
2285
|
+
for (let i = 0; i < numMixers; i++) {
|
|
2286
|
+
let mixer = mixerFactory(output[i], output[i + 1]);
|
|
2287
|
+
if (ease2) {
|
|
2288
|
+
const easingFunction = Array.isArray(ease2) ? ease2[i] || noop : ease2;
|
|
2289
|
+
mixer = pipe(easingFunction, mixer);
|
|
2290
|
+
}
|
|
2291
|
+
mixers.push(mixer);
|
|
2292
|
+
}
|
|
2293
|
+
return mixers;
|
|
2294
|
+
}
|
|
2295
|
+
function interpolate(input, output, { clamp: isClamp = true, ease: ease2, mixer } = {}) {
|
|
2296
|
+
const inputLength = input.length;
|
|
2297
|
+
invariant(inputLength === output.length, "Both input and output ranges must be the same length");
|
|
2298
|
+
if (inputLength === 1)
|
|
2299
|
+
return () => output[0];
|
|
2300
|
+
if (inputLength === 2 && output[0] === output[1])
|
|
2301
|
+
return () => output[1];
|
|
2302
|
+
const isZeroDeltaRange = input[0] === input[1];
|
|
2303
|
+
if (input[0] > input[inputLength - 1]) {
|
|
2304
|
+
input = [...input].reverse();
|
|
2305
|
+
output = [...output].reverse();
|
|
2306
|
+
}
|
|
2307
|
+
const mixers = createMixers(output, ease2, mixer);
|
|
2308
|
+
const numMixers = mixers.length;
|
|
2309
|
+
const interpolator = (v) => {
|
|
2310
|
+
if (isZeroDeltaRange && v < input[0])
|
|
2311
|
+
return output[0];
|
|
2312
|
+
let i = 0;
|
|
2313
|
+
if (numMixers > 1) {
|
|
2314
|
+
for (; i < input.length - 2; i++) {
|
|
2315
|
+
if (v < input[i + 1])
|
|
2316
|
+
break;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
const progressInRange = /* @__PURE__ */ progress(input[i], input[i + 1], v);
|
|
2320
|
+
return mixers[i](progressInRange);
|
|
2321
|
+
};
|
|
2322
|
+
return isClamp ? (v) => interpolator(clamp(input[0], input[inputLength - 1], v)) : interpolator;
|
|
2323
|
+
}
|
|
2324
|
+
function fillOffset(offset, remaining) {
|
|
2325
|
+
const min = offset[offset.length - 1];
|
|
2326
|
+
for (let i = 1; i <= remaining; i++) {
|
|
2327
|
+
const offsetProgress = /* @__PURE__ */ progress(0, remaining, i);
|
|
2328
|
+
offset.push(mixNumber$1(min, 1, offsetProgress));
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
function defaultOffset(arr) {
|
|
2332
|
+
const offset = [0];
|
|
2333
|
+
fillOffset(offset, arr.length - 1);
|
|
2334
|
+
return offset;
|
|
2335
|
+
}
|
|
2336
|
+
function convertOffsetToTimes(offset, duration) {
|
|
2337
|
+
return offset.map((o) => o * duration);
|
|
2338
|
+
}
|
|
2339
|
+
function defaultEasing(values, easing) {
|
|
2340
|
+
return values.map(() => easing || easeInOut).splice(0, values.length - 1);
|
|
2341
|
+
}
|
|
2342
|
+
function keyframes({ duration = 300, keyframes: keyframeValues, times, ease: ease2 = "easeInOut" }) {
|
|
2343
|
+
const easingFunctions = isEasingArray(ease2) ? ease2.map(easingDefinitionToFunction) : easingDefinitionToFunction(ease2);
|
|
2344
|
+
const state = {
|
|
2345
|
+
done: false,
|
|
2346
|
+
value: keyframeValues[0]
|
|
2347
|
+
};
|
|
2348
|
+
const absoluteTimes = convertOffsetToTimes(
|
|
2349
|
+
// Only use the provided offsets if they're the correct length
|
|
2350
|
+
// TODO Maybe we should warn here if there's a length mismatch
|
|
2351
|
+
times && times.length === keyframeValues.length ? times : defaultOffset(keyframeValues),
|
|
2352
|
+
duration
|
|
2353
|
+
);
|
|
2354
|
+
const mapTimeToKeyframe = interpolate(absoluteTimes, keyframeValues, {
|
|
2355
|
+
ease: Array.isArray(easingFunctions) ? easingFunctions : defaultEasing(keyframeValues, easingFunctions)
|
|
2356
|
+
});
|
|
2357
|
+
return {
|
|
2358
|
+
calculatedDuration: duration,
|
|
2359
|
+
next: (t) => {
|
|
2360
|
+
state.value = mapTimeToKeyframe(t);
|
|
2361
|
+
state.done = t >= duration;
|
|
2362
|
+
return state;
|
|
2363
|
+
}
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
const frameloopDriver = (update) => {
|
|
2367
|
+
const passTimestamp = ({ timestamp }) => update(timestamp);
|
|
2368
|
+
return {
|
|
2369
|
+
start: () => frame.update(passTimestamp, true),
|
|
2370
|
+
stop: () => cancelFrame(passTimestamp),
|
|
2371
|
+
/**
|
|
2372
|
+
* If we're processing this frame we can use the
|
|
2373
|
+
* framelocked timestamp to keep things in sync.
|
|
2374
|
+
*/
|
|
2375
|
+
now: () => frameData.isProcessing ? frameData.timestamp : time.now()
|
|
2376
|
+
};
|
|
2377
|
+
};
|
|
2378
|
+
const generators = {
|
|
2379
|
+
decay: inertia,
|
|
2380
|
+
inertia,
|
|
2381
|
+
tween: keyframes,
|
|
2382
|
+
keyframes,
|
|
2383
|
+
spring
|
|
2384
|
+
};
|
|
2385
|
+
const percentToProgress = (percent2) => percent2 / 100;
|
|
2386
|
+
class MainThreadAnimation extends BaseAnimation {
|
|
2387
|
+
constructor(options) {
|
|
2388
|
+
super(options);
|
|
2389
|
+
this.holdTime = null;
|
|
2390
|
+
this.cancelTime = null;
|
|
2391
|
+
this.currentTime = 0;
|
|
2392
|
+
this.playbackSpeed = 1;
|
|
2393
|
+
this.pendingPlayState = "running";
|
|
2394
|
+
this.startTime = null;
|
|
2395
|
+
this.state = "idle";
|
|
2396
|
+
this.stop = () => {
|
|
2397
|
+
this.resolver.cancel();
|
|
2398
|
+
this.isStopped = true;
|
|
2399
|
+
if (this.state === "idle")
|
|
2400
|
+
return;
|
|
2401
|
+
this.teardown();
|
|
2402
|
+
const { onStop } = this.options;
|
|
2403
|
+
onStop && onStop();
|
|
2404
|
+
};
|
|
2405
|
+
const { name, motionValue: motionValue2, element, keyframes: keyframes2 } = this.options;
|
|
2406
|
+
const KeyframeResolver$1 = (element === null || element === void 0 ? void 0 : element.KeyframeResolver) || KeyframeResolver;
|
|
2407
|
+
const onResolved = (resolvedKeyframes, finalKeyframe) => this.onKeyframesResolved(resolvedKeyframes, finalKeyframe);
|
|
2408
|
+
this.resolver = new KeyframeResolver$1(keyframes2, onResolved, name, motionValue2, element);
|
|
2409
|
+
this.resolver.scheduleResolve();
|
|
2410
|
+
}
|
|
2411
|
+
flatten() {
|
|
2412
|
+
super.flatten();
|
|
2413
|
+
if (this._resolved) {
|
|
2414
|
+
Object.assign(this._resolved, this.initPlayback(this._resolved.keyframes));
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
initPlayback(keyframes$1) {
|
|
2418
|
+
const { type = "keyframes", repeat = 0, repeatDelay = 0, repeatType, velocity = 0 } = this.options;
|
|
2419
|
+
const generatorFactory = isGenerator(type) ? type : generators[type] || keyframes;
|
|
2420
|
+
let mapPercentToKeyframes;
|
|
2421
|
+
let mirroredGenerator;
|
|
2422
|
+
if (generatorFactory !== keyframes && typeof keyframes$1[0] !== "number") {
|
|
2423
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2424
|
+
invariant(keyframes$1.length === 2, `Only two keyframes currently supported with spring and inertia animations. Trying to animate ${keyframes$1}`);
|
|
2425
|
+
}
|
|
2426
|
+
mapPercentToKeyframes = pipe(percentToProgress, mix(keyframes$1[0], keyframes$1[1]));
|
|
2427
|
+
keyframes$1 = [0, 100];
|
|
2428
|
+
}
|
|
2429
|
+
const generator = generatorFactory({ ...this.options, keyframes: keyframes$1 });
|
|
2430
|
+
if (repeatType === "mirror") {
|
|
2431
|
+
mirroredGenerator = generatorFactory({
|
|
2432
|
+
...this.options,
|
|
2433
|
+
keyframes: [...keyframes$1].reverse(),
|
|
2434
|
+
velocity: -velocity
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
if (generator.calculatedDuration === null) {
|
|
2438
|
+
generator.calculatedDuration = calcGeneratorDuration(generator);
|
|
2439
|
+
}
|
|
2440
|
+
const { calculatedDuration } = generator;
|
|
2441
|
+
const resolvedDuration = calculatedDuration + repeatDelay;
|
|
2442
|
+
const totalDuration = resolvedDuration * (repeat + 1) - repeatDelay;
|
|
2443
|
+
return {
|
|
2444
|
+
generator,
|
|
2445
|
+
mirroredGenerator,
|
|
2446
|
+
mapPercentToKeyframes,
|
|
2447
|
+
calculatedDuration,
|
|
2448
|
+
resolvedDuration,
|
|
2449
|
+
totalDuration
|
|
2450
|
+
};
|
|
2451
|
+
}
|
|
2452
|
+
onPostResolved() {
|
|
2453
|
+
const { autoplay = true } = this.options;
|
|
2454
|
+
this.play();
|
|
2455
|
+
if (this.pendingPlayState === "paused" || !autoplay) {
|
|
2456
|
+
this.pause();
|
|
2457
|
+
} else {
|
|
2458
|
+
this.state = this.pendingPlayState;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
tick(timestamp, sample = false) {
|
|
2462
|
+
const { resolved } = this;
|
|
2463
|
+
if (!resolved) {
|
|
2464
|
+
const { keyframes: keyframes3 } = this.options;
|
|
2465
|
+
return { done: true, value: keyframes3[keyframes3.length - 1] };
|
|
2466
|
+
}
|
|
2467
|
+
const { finalKeyframe, generator, mirroredGenerator, mapPercentToKeyframes, keyframes: keyframes2, calculatedDuration, totalDuration, resolvedDuration } = resolved;
|
|
2468
|
+
if (this.startTime === null)
|
|
2469
|
+
return generator.next(0);
|
|
2470
|
+
const { delay, repeat, repeatType, repeatDelay, onUpdate } = this.options;
|
|
2471
|
+
if (this.speed > 0) {
|
|
2472
|
+
this.startTime = Math.min(this.startTime, timestamp);
|
|
2473
|
+
} else if (this.speed < 0) {
|
|
2474
|
+
this.startTime = Math.min(timestamp - totalDuration / this.speed, this.startTime);
|
|
2475
|
+
}
|
|
2476
|
+
if (sample) {
|
|
2477
|
+
this.currentTime = timestamp;
|
|
2478
|
+
} else if (this.holdTime !== null) {
|
|
2479
|
+
this.currentTime = this.holdTime;
|
|
2480
|
+
} else {
|
|
2481
|
+
this.currentTime = Math.round(timestamp - this.startTime) * this.speed;
|
|
2482
|
+
}
|
|
2483
|
+
const timeWithoutDelay = this.currentTime - delay * (this.speed >= 0 ? 1 : -1);
|
|
2484
|
+
const isInDelayPhase = this.speed >= 0 ? timeWithoutDelay < 0 : timeWithoutDelay > totalDuration;
|
|
2485
|
+
this.currentTime = Math.max(timeWithoutDelay, 0);
|
|
2486
|
+
if (this.state === "finished" && this.holdTime === null) {
|
|
2487
|
+
this.currentTime = totalDuration;
|
|
2488
|
+
}
|
|
2489
|
+
let elapsed = this.currentTime;
|
|
2490
|
+
let frameGenerator = generator;
|
|
2491
|
+
if (repeat) {
|
|
2492
|
+
const progress2 = Math.min(this.currentTime, totalDuration) / resolvedDuration;
|
|
2493
|
+
let currentIteration = Math.floor(progress2);
|
|
2494
|
+
let iterationProgress = progress2 % 1;
|
|
2495
|
+
if (!iterationProgress && progress2 >= 1) {
|
|
2496
|
+
iterationProgress = 1;
|
|
2497
|
+
}
|
|
2498
|
+
iterationProgress === 1 && currentIteration--;
|
|
2499
|
+
currentIteration = Math.min(currentIteration, repeat + 1);
|
|
2500
|
+
const isOddIteration = Boolean(currentIteration % 2);
|
|
2501
|
+
if (isOddIteration) {
|
|
2502
|
+
if (repeatType === "reverse") {
|
|
2503
|
+
iterationProgress = 1 - iterationProgress;
|
|
2504
|
+
if (repeatDelay) {
|
|
2505
|
+
iterationProgress -= repeatDelay / resolvedDuration;
|
|
2506
|
+
}
|
|
2507
|
+
} else if (repeatType === "mirror") {
|
|
2508
|
+
frameGenerator = mirroredGenerator;
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
elapsed = clamp(0, 1, iterationProgress) * resolvedDuration;
|
|
2512
|
+
}
|
|
2513
|
+
const state = isInDelayPhase ? { done: false, value: keyframes2[0] } : frameGenerator.next(elapsed);
|
|
2514
|
+
if (mapPercentToKeyframes) {
|
|
2515
|
+
state.value = mapPercentToKeyframes(state.value);
|
|
2516
|
+
}
|
|
2517
|
+
let { done } = state;
|
|
2518
|
+
if (!isInDelayPhase && calculatedDuration !== null) {
|
|
2519
|
+
done = this.speed >= 0 ? this.currentTime >= totalDuration : this.currentTime <= 0;
|
|
2520
|
+
}
|
|
2521
|
+
const isAnimationFinished = this.holdTime === null && (this.state === "finished" || this.state === "running" && done);
|
|
2522
|
+
if (isAnimationFinished && finalKeyframe !== void 0) {
|
|
2523
|
+
state.value = getFinalKeyframe(keyframes2, this.options, finalKeyframe);
|
|
2524
|
+
}
|
|
2525
|
+
if (onUpdate) {
|
|
2526
|
+
onUpdate(state.value);
|
|
2527
|
+
}
|
|
2528
|
+
if (isAnimationFinished) {
|
|
2529
|
+
this.finish();
|
|
2530
|
+
}
|
|
2531
|
+
return state;
|
|
2532
|
+
}
|
|
2533
|
+
get duration() {
|
|
2534
|
+
const { resolved } = this;
|
|
2535
|
+
return resolved ? /* @__PURE__ */ millisecondsToSeconds(resolved.calculatedDuration) : 0;
|
|
2536
|
+
}
|
|
2537
|
+
get time() {
|
|
2538
|
+
return /* @__PURE__ */ millisecondsToSeconds(this.currentTime);
|
|
2539
|
+
}
|
|
2540
|
+
set time(newTime) {
|
|
2541
|
+
newTime = /* @__PURE__ */ secondsToMilliseconds(newTime);
|
|
2542
|
+
this.currentTime = newTime;
|
|
2543
|
+
if (this.holdTime !== null || this.speed === 0) {
|
|
2544
|
+
this.holdTime = newTime;
|
|
2545
|
+
} else if (this.driver) {
|
|
2546
|
+
this.startTime = this.driver.now() - newTime / this.speed;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
get speed() {
|
|
2550
|
+
return this.playbackSpeed;
|
|
2551
|
+
}
|
|
2552
|
+
set speed(newSpeed) {
|
|
2553
|
+
const hasChanged = this.playbackSpeed !== newSpeed;
|
|
2554
|
+
this.playbackSpeed = newSpeed;
|
|
2555
|
+
if (hasChanged) {
|
|
2556
|
+
this.time = /* @__PURE__ */ millisecondsToSeconds(this.currentTime);
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
play() {
|
|
2560
|
+
if (!this.resolver.isScheduled) {
|
|
2561
|
+
this.resolver.resume();
|
|
2562
|
+
}
|
|
2563
|
+
if (!this._resolved) {
|
|
2564
|
+
this.pendingPlayState = "running";
|
|
2565
|
+
return;
|
|
2566
|
+
}
|
|
2567
|
+
if (this.isStopped)
|
|
2568
|
+
return;
|
|
2569
|
+
const { driver = frameloopDriver, onPlay, startTime } = this.options;
|
|
2570
|
+
if (!this.driver) {
|
|
2571
|
+
this.driver = driver((timestamp) => this.tick(timestamp));
|
|
2572
|
+
}
|
|
2573
|
+
onPlay && onPlay();
|
|
2574
|
+
const now2 = this.driver.now();
|
|
2575
|
+
if (this.holdTime !== null) {
|
|
2576
|
+
this.startTime = now2 - this.holdTime;
|
|
2577
|
+
} else if (!this.startTime) {
|
|
2578
|
+
this.startTime = startTime !== null && startTime !== void 0 ? startTime : this.calcStartTime();
|
|
2579
|
+
} else if (this.state === "finished") {
|
|
2580
|
+
this.startTime = now2;
|
|
2581
|
+
}
|
|
2582
|
+
if (this.state === "finished") {
|
|
2583
|
+
this.updateFinishedPromise();
|
|
2584
|
+
}
|
|
2585
|
+
this.cancelTime = this.startTime;
|
|
2586
|
+
this.holdTime = null;
|
|
2587
|
+
this.state = "running";
|
|
2588
|
+
this.driver.start();
|
|
2589
|
+
}
|
|
2590
|
+
pause() {
|
|
2591
|
+
var _a;
|
|
2592
|
+
if (!this._resolved) {
|
|
2593
|
+
this.pendingPlayState = "paused";
|
|
2594
|
+
return;
|
|
2595
|
+
}
|
|
2596
|
+
this.state = "paused";
|
|
2597
|
+
this.holdTime = (_a = this.currentTime) !== null && _a !== void 0 ? _a : 0;
|
|
2598
|
+
}
|
|
2599
|
+
complete() {
|
|
2600
|
+
if (this.state !== "running") {
|
|
2601
|
+
this.play();
|
|
2602
|
+
}
|
|
2603
|
+
this.pendingPlayState = this.state = "finished";
|
|
2604
|
+
this.holdTime = null;
|
|
2605
|
+
}
|
|
2606
|
+
finish() {
|
|
2607
|
+
this.teardown();
|
|
2608
|
+
this.state = "finished";
|
|
2609
|
+
const { onComplete } = this.options;
|
|
2610
|
+
onComplete && onComplete();
|
|
2611
|
+
}
|
|
2612
|
+
cancel() {
|
|
2613
|
+
if (this.cancelTime !== null) {
|
|
2614
|
+
this.tick(this.cancelTime);
|
|
2615
|
+
}
|
|
2616
|
+
this.teardown();
|
|
2617
|
+
this.updateFinishedPromise();
|
|
2618
|
+
}
|
|
2619
|
+
teardown() {
|
|
2620
|
+
this.state = "idle";
|
|
2621
|
+
this.stopDriver();
|
|
2622
|
+
this.resolveFinishedPromise();
|
|
2623
|
+
this.updateFinishedPromise();
|
|
2624
|
+
this.startTime = this.cancelTime = null;
|
|
2625
|
+
this.resolver.cancel();
|
|
2626
|
+
}
|
|
2627
|
+
stopDriver() {
|
|
2628
|
+
if (!this.driver)
|
|
2629
|
+
return;
|
|
2630
|
+
this.driver.stop();
|
|
2631
|
+
this.driver = void 0;
|
|
2632
|
+
}
|
|
2633
|
+
sample(time2) {
|
|
2634
|
+
this.startTime = 0;
|
|
2635
|
+
return this.tick(time2, true);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
const acceleratedValues = /* @__PURE__ */ new Set([
|
|
2639
|
+
"opacity",
|
|
2640
|
+
"clipPath",
|
|
2641
|
+
"filter",
|
|
2642
|
+
"transform"
|
|
2643
|
+
// TODO: Can be accelerated but currently disabled until https://issues.chromium.org/issues/41491098 is resolved
|
|
2644
|
+
// or until we implement support for linear() easing.
|
|
2645
|
+
// "background-color"
|
|
2646
|
+
]);
|
|
2647
|
+
function startWaapiAnimation(element, valueName, keyframes2, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease: ease2 = "easeInOut", times } = {}) {
|
|
2648
|
+
const keyframeOptions = { [valueName]: keyframes2 };
|
|
2649
|
+
if (times)
|
|
2650
|
+
keyframeOptions.offset = times;
|
|
2651
|
+
const easing = mapEasingToNativeEasing(ease2, duration);
|
|
2652
|
+
if (Array.isArray(easing))
|
|
2653
|
+
keyframeOptions.easing = easing;
|
|
2654
|
+
return element.animate(keyframeOptions, {
|
|
2655
|
+
delay,
|
|
2656
|
+
duration,
|
|
2657
|
+
easing: !Array.isArray(easing) ? easing : "linear",
|
|
2658
|
+
fill: "both",
|
|
2659
|
+
iterations: repeat + 1,
|
|
2660
|
+
direction: repeatType === "reverse" ? "alternate" : "normal"
|
|
2661
|
+
});
|
|
2662
|
+
}
|
|
2663
|
+
const supportsWaapi = /* @__PURE__ */ memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
|
|
2664
|
+
const sampleDelta = 10;
|
|
2665
|
+
const maxDuration = 2e4;
|
|
2666
|
+
function requiresPregeneratedKeyframes(options) {
|
|
2667
|
+
return isGenerator(options.type) || options.type === "spring" || !isWaapiSupportedEasing(options.ease);
|
|
2668
|
+
}
|
|
2669
|
+
function pregenerateKeyframes(keyframes2, options) {
|
|
2670
|
+
const sampleAnimation = new MainThreadAnimation({
|
|
2671
|
+
...options,
|
|
2672
|
+
keyframes: keyframes2,
|
|
2673
|
+
repeat: 0,
|
|
2674
|
+
delay: 0,
|
|
2675
|
+
isGenerator: true
|
|
2676
|
+
});
|
|
2677
|
+
let state = { done: false, value: keyframes2[0] };
|
|
2678
|
+
const pregeneratedKeyframes = [];
|
|
2679
|
+
let t = 0;
|
|
2680
|
+
while (!state.done && t < maxDuration) {
|
|
2681
|
+
state = sampleAnimation.sample(t);
|
|
2682
|
+
pregeneratedKeyframes.push(state.value);
|
|
2683
|
+
t += sampleDelta;
|
|
2684
|
+
}
|
|
2685
|
+
return {
|
|
2686
|
+
times: void 0,
|
|
2687
|
+
keyframes: pregeneratedKeyframes,
|
|
2688
|
+
duration: t - sampleDelta,
|
|
2689
|
+
ease: "linear"
|
|
2690
|
+
};
|
|
2691
|
+
}
|
|
2692
|
+
const unsupportedEasingFunctions = {
|
|
2693
|
+
anticipate,
|
|
2694
|
+
backInOut,
|
|
2695
|
+
circInOut
|
|
2696
|
+
};
|
|
2697
|
+
function isUnsupportedEase(key) {
|
|
2698
|
+
return key in unsupportedEasingFunctions;
|
|
2699
|
+
}
|
|
2700
|
+
class AcceleratedAnimation extends BaseAnimation {
|
|
2701
|
+
constructor(options) {
|
|
2702
|
+
super(options);
|
|
2703
|
+
const { name, motionValue: motionValue2, element, keyframes: keyframes2 } = this.options;
|
|
2704
|
+
this.resolver = new DOMKeyframesResolver(keyframes2, (resolvedKeyframes, finalKeyframe) => this.onKeyframesResolved(resolvedKeyframes, finalKeyframe), name, motionValue2, element);
|
|
2705
|
+
this.resolver.scheduleResolve();
|
|
2706
|
+
}
|
|
2707
|
+
initPlayback(keyframes2, finalKeyframe) {
|
|
2708
|
+
let { duration = 300, times, ease: ease2, type, motionValue: motionValue2, name, startTime } = this.options;
|
|
2709
|
+
if (!motionValue2.owner || !motionValue2.owner.current) {
|
|
2710
|
+
return false;
|
|
2711
|
+
}
|
|
2712
|
+
if (typeof ease2 === "string" && supportsLinearEasing() && isUnsupportedEase(ease2)) {
|
|
2713
|
+
ease2 = unsupportedEasingFunctions[ease2];
|
|
2714
|
+
}
|
|
2715
|
+
if (requiresPregeneratedKeyframes(this.options)) {
|
|
2716
|
+
const { onComplete, onUpdate, motionValue: motionValue3, element, ...options } = this.options;
|
|
2717
|
+
const pregeneratedAnimation = pregenerateKeyframes(keyframes2, options);
|
|
2718
|
+
keyframes2 = pregeneratedAnimation.keyframes;
|
|
2719
|
+
if (keyframes2.length === 1) {
|
|
2720
|
+
keyframes2[1] = keyframes2[0];
|
|
2721
|
+
}
|
|
2722
|
+
duration = pregeneratedAnimation.duration;
|
|
2723
|
+
times = pregeneratedAnimation.times;
|
|
2724
|
+
ease2 = pregeneratedAnimation.ease;
|
|
2725
|
+
type = "keyframes";
|
|
2726
|
+
}
|
|
2727
|
+
const animation = startWaapiAnimation(motionValue2.owner.current, name, keyframes2, { ...this.options, duration, times, ease: ease2 });
|
|
2728
|
+
animation.startTime = startTime !== null && startTime !== void 0 ? startTime : this.calcStartTime();
|
|
2729
|
+
if (this.pendingTimeline) {
|
|
2730
|
+
attachTimeline(animation, this.pendingTimeline);
|
|
2731
|
+
this.pendingTimeline = void 0;
|
|
2732
|
+
} else {
|
|
2733
|
+
animation.onfinish = () => {
|
|
2734
|
+
const { onComplete } = this.options;
|
|
2735
|
+
motionValue2.set(getFinalKeyframe(keyframes2, this.options, finalKeyframe));
|
|
2736
|
+
onComplete && onComplete();
|
|
2737
|
+
this.cancel();
|
|
2738
|
+
this.resolveFinishedPromise();
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
return {
|
|
2742
|
+
animation,
|
|
2743
|
+
duration,
|
|
2744
|
+
times,
|
|
2745
|
+
type,
|
|
2746
|
+
ease: ease2,
|
|
2747
|
+
keyframes: keyframes2
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
get duration() {
|
|
2751
|
+
const { resolved } = this;
|
|
2752
|
+
if (!resolved)
|
|
2753
|
+
return 0;
|
|
2754
|
+
const { duration } = resolved;
|
|
2755
|
+
return /* @__PURE__ */ millisecondsToSeconds(duration);
|
|
2756
|
+
}
|
|
2757
|
+
get time() {
|
|
2758
|
+
const { resolved } = this;
|
|
2759
|
+
if (!resolved)
|
|
2760
|
+
return 0;
|
|
2761
|
+
const { animation } = resolved;
|
|
2762
|
+
return /* @__PURE__ */ millisecondsToSeconds(animation.currentTime || 0);
|
|
2763
|
+
}
|
|
2764
|
+
set time(newTime) {
|
|
2765
|
+
const { resolved } = this;
|
|
2766
|
+
if (!resolved)
|
|
2767
|
+
return;
|
|
2768
|
+
const { animation } = resolved;
|
|
2769
|
+
animation.currentTime = /* @__PURE__ */ secondsToMilliseconds(newTime);
|
|
2770
|
+
}
|
|
2771
|
+
get speed() {
|
|
2772
|
+
const { resolved } = this;
|
|
2773
|
+
if (!resolved)
|
|
2774
|
+
return 1;
|
|
2775
|
+
const { animation } = resolved;
|
|
2776
|
+
return animation.playbackRate;
|
|
2777
|
+
}
|
|
2778
|
+
set speed(newSpeed) {
|
|
2779
|
+
const { resolved } = this;
|
|
2780
|
+
if (!resolved)
|
|
2781
|
+
return;
|
|
2782
|
+
const { animation } = resolved;
|
|
2783
|
+
animation.playbackRate = newSpeed;
|
|
2784
|
+
}
|
|
2785
|
+
get state() {
|
|
2786
|
+
const { resolved } = this;
|
|
2787
|
+
if (!resolved)
|
|
2788
|
+
return "idle";
|
|
2789
|
+
const { animation } = resolved;
|
|
2790
|
+
return animation.playState;
|
|
2791
|
+
}
|
|
2792
|
+
get startTime() {
|
|
2793
|
+
const { resolved } = this;
|
|
2794
|
+
if (!resolved)
|
|
2795
|
+
return null;
|
|
2796
|
+
const { animation } = resolved;
|
|
2797
|
+
return animation.startTime;
|
|
2798
|
+
}
|
|
2799
|
+
/**
|
|
2800
|
+
* Replace the default DocumentTimeline with another AnimationTimeline.
|
|
2801
|
+
* Currently used for scroll animations.
|
|
2802
|
+
*/
|
|
2803
|
+
attachTimeline(timeline) {
|
|
2804
|
+
if (!this._resolved) {
|
|
2805
|
+
this.pendingTimeline = timeline;
|
|
2806
|
+
} else {
|
|
2807
|
+
const { resolved } = this;
|
|
2808
|
+
if (!resolved)
|
|
2809
|
+
return noop;
|
|
2810
|
+
const { animation } = resolved;
|
|
2811
|
+
attachTimeline(animation, timeline);
|
|
2812
|
+
}
|
|
2813
|
+
return noop;
|
|
2814
|
+
}
|
|
2815
|
+
play() {
|
|
2816
|
+
if (this.isStopped)
|
|
2817
|
+
return;
|
|
2818
|
+
const { resolved } = this;
|
|
2819
|
+
if (!resolved)
|
|
2820
|
+
return;
|
|
2821
|
+
const { animation } = resolved;
|
|
2822
|
+
if (animation.playState === "finished") {
|
|
2823
|
+
this.updateFinishedPromise();
|
|
2824
|
+
}
|
|
2825
|
+
animation.play();
|
|
2826
|
+
}
|
|
2827
|
+
pause() {
|
|
2828
|
+
const { resolved } = this;
|
|
2829
|
+
if (!resolved)
|
|
2830
|
+
return;
|
|
2831
|
+
const { animation } = resolved;
|
|
2832
|
+
animation.pause();
|
|
2833
|
+
}
|
|
2834
|
+
stop() {
|
|
2835
|
+
this.resolver.cancel();
|
|
2836
|
+
this.isStopped = true;
|
|
2837
|
+
if (this.state === "idle")
|
|
2838
|
+
return;
|
|
2839
|
+
this.resolveFinishedPromise();
|
|
2840
|
+
this.updateFinishedPromise();
|
|
2841
|
+
const { resolved } = this;
|
|
2842
|
+
if (!resolved)
|
|
2843
|
+
return;
|
|
2844
|
+
const { animation, keyframes: keyframes2, duration, type, ease: ease2, times } = resolved;
|
|
2845
|
+
if (animation.playState === "idle" || animation.playState === "finished") {
|
|
2846
|
+
return;
|
|
2847
|
+
}
|
|
2848
|
+
if (this.time) {
|
|
2849
|
+
const { motionValue: motionValue2, onUpdate, onComplete, element, ...options } = this.options;
|
|
2850
|
+
const sampleAnimation = new MainThreadAnimation({
|
|
2851
|
+
...options,
|
|
2852
|
+
keyframes: keyframes2,
|
|
2853
|
+
duration,
|
|
2854
|
+
type,
|
|
2855
|
+
ease: ease2,
|
|
2856
|
+
times,
|
|
2857
|
+
isGenerator: true
|
|
2858
|
+
});
|
|
2859
|
+
const sampleTime = /* @__PURE__ */ secondsToMilliseconds(this.time);
|
|
2860
|
+
motionValue2.setWithVelocity(sampleAnimation.sample(sampleTime - sampleDelta).value, sampleAnimation.sample(sampleTime).value, sampleDelta);
|
|
2861
|
+
}
|
|
2862
|
+
const { onStop } = this.options;
|
|
2863
|
+
onStop && onStop();
|
|
2864
|
+
this.cancel();
|
|
2865
|
+
}
|
|
2866
|
+
complete() {
|
|
2867
|
+
const { resolved } = this;
|
|
2868
|
+
if (!resolved)
|
|
2869
|
+
return;
|
|
2870
|
+
resolved.animation.finish();
|
|
2871
|
+
}
|
|
2872
|
+
cancel() {
|
|
2873
|
+
const { resolved } = this;
|
|
2874
|
+
if (!resolved)
|
|
2875
|
+
return;
|
|
2876
|
+
resolved.animation.cancel();
|
|
2877
|
+
}
|
|
2878
|
+
static supports(options) {
|
|
2879
|
+
const { motionValue: motionValue2, name, repeatDelay, repeatType, damping, type } = options;
|
|
2880
|
+
if (!motionValue2 || !motionValue2.owner || !(motionValue2.owner.current instanceof HTMLElement)) {
|
|
2881
|
+
return false;
|
|
2882
|
+
}
|
|
2883
|
+
const { onUpdate, transformTemplate } = motionValue2.owner.getProps();
|
|
2884
|
+
return supportsWaapi() && name && acceleratedValues.has(name) && /**
|
|
2885
|
+
* If we're outputting values to onUpdate then we can't use WAAPI as there's
|
|
2886
|
+
* no way to read the value from WAAPI every frame.
|
|
2887
|
+
*/
|
|
2888
|
+
!onUpdate && !transformTemplate && !repeatDelay && repeatType !== "mirror" && damping !== 0 && type !== "inertia";
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
const underDampedSpring = {
|
|
2892
|
+
type: "spring",
|
|
2893
|
+
stiffness: 500,
|
|
2894
|
+
damping: 25,
|
|
2895
|
+
restSpeed: 10
|
|
2896
|
+
};
|
|
2897
|
+
const criticallyDampedSpring = (target) => ({
|
|
2898
|
+
type: "spring",
|
|
2899
|
+
stiffness: 550,
|
|
2900
|
+
damping: target === 0 ? 2 * Math.sqrt(550) : 30,
|
|
2901
|
+
restSpeed: 10
|
|
2902
|
+
});
|
|
2903
|
+
const keyframesTransition = {
|
|
2904
|
+
type: "keyframes",
|
|
2905
|
+
duration: 0.8
|
|
2906
|
+
};
|
|
2907
|
+
const ease = {
|
|
2908
|
+
type: "keyframes",
|
|
2909
|
+
ease: [0.25, 0.1, 0.35, 1],
|
|
2910
|
+
duration: 0.3
|
|
2911
|
+
};
|
|
2912
|
+
const getDefaultTransition = (valueKey, { keyframes: keyframes2 }) => {
|
|
2913
|
+
if (keyframes2.length > 2) {
|
|
2914
|
+
return keyframesTransition;
|
|
2915
|
+
} else if (transformProps.has(valueKey)) {
|
|
2916
|
+
return valueKey.startsWith("scale") ? criticallyDampedSpring(keyframes2[1]) : underDampedSpring;
|
|
2917
|
+
}
|
|
2918
|
+
return ease;
|
|
2919
|
+
};
|
|
2920
|
+
function isTransitionDefined({ when, delay: _delay, delayChildren, staggerChildren, staggerDirection, repeat, repeatType, repeatDelay, from, elapsed, ...transition }) {
|
|
2921
|
+
return !!Object.keys(transition).length;
|
|
2922
|
+
}
|
|
2923
|
+
const animateMotionValue = (name, value, target, transition = {}, element, isHandoff) => (onComplete) => {
|
|
2924
|
+
const valueTransition = getValueTransition$1(transition, name) || {};
|
|
2925
|
+
const delay = valueTransition.delay || transition.delay || 0;
|
|
2926
|
+
let { elapsed = 0 } = transition;
|
|
2927
|
+
elapsed = elapsed - /* @__PURE__ */ secondsToMilliseconds(delay);
|
|
2928
|
+
let options = {
|
|
2929
|
+
keyframes: Array.isArray(target) ? target : [null, target],
|
|
2930
|
+
ease: "easeOut",
|
|
2931
|
+
velocity: value.getVelocity(),
|
|
2932
|
+
...valueTransition,
|
|
2933
|
+
delay: -elapsed,
|
|
2934
|
+
onUpdate: (v) => {
|
|
2935
|
+
value.set(v);
|
|
2936
|
+
valueTransition.onUpdate && valueTransition.onUpdate(v);
|
|
2937
|
+
},
|
|
2938
|
+
onComplete: () => {
|
|
2939
|
+
onComplete();
|
|
2940
|
+
valueTransition.onComplete && valueTransition.onComplete();
|
|
2941
|
+
},
|
|
2942
|
+
name,
|
|
2943
|
+
motionValue: value,
|
|
2944
|
+
element: isHandoff ? void 0 : element
|
|
2945
|
+
};
|
|
2946
|
+
if (!isTransitionDefined(valueTransition)) {
|
|
2947
|
+
options = {
|
|
2948
|
+
...options,
|
|
2949
|
+
...getDefaultTransition(name, options)
|
|
2950
|
+
};
|
|
2951
|
+
}
|
|
2952
|
+
if (options.duration) {
|
|
2953
|
+
options.duration = /* @__PURE__ */ secondsToMilliseconds(options.duration);
|
|
2954
|
+
}
|
|
2955
|
+
if (options.repeatDelay) {
|
|
2956
|
+
options.repeatDelay = /* @__PURE__ */ secondsToMilliseconds(options.repeatDelay);
|
|
2957
|
+
}
|
|
2958
|
+
if (options.from !== void 0) {
|
|
2959
|
+
options.keyframes[0] = options.from;
|
|
2960
|
+
}
|
|
2961
|
+
let shouldSkip = false;
|
|
2962
|
+
if (options.type === false || options.duration === 0 && !options.repeatDelay) {
|
|
2963
|
+
options.duration = 0;
|
|
2964
|
+
if (options.delay === 0) {
|
|
2965
|
+
shouldSkip = true;
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
if (shouldSkip && !isHandoff && value.get() !== void 0) {
|
|
2969
|
+
const finalKeyframe = getFinalKeyframe(options.keyframes, valueTransition);
|
|
2970
|
+
if (finalKeyframe !== void 0) {
|
|
2971
|
+
frame.update(() => {
|
|
2972
|
+
options.onUpdate(finalKeyframe);
|
|
2973
|
+
options.onComplete();
|
|
2974
|
+
});
|
|
2975
|
+
return new GroupPlaybackControls([]);
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
if (!isHandoff && AcceleratedAnimation.supports(options)) {
|
|
2979
|
+
return new AcceleratedAnimation(options);
|
|
2980
|
+
} else {
|
|
2981
|
+
return new MainThreadAnimation(options);
|
|
2982
|
+
}
|
|
2983
|
+
};
|
|
2984
|
+
function shouldBlockAnimation({ protectedKeys, needsAnimating }, key) {
|
|
2985
|
+
const shouldBlock = protectedKeys.hasOwnProperty(key) && needsAnimating[key] !== true;
|
|
2986
|
+
needsAnimating[key] = false;
|
|
2987
|
+
return shouldBlock;
|
|
2988
|
+
}
|
|
2989
|
+
function animateTarget(visualElement, targetAndTransition, { delay = 0, transitionOverride, type } = {}) {
|
|
2990
|
+
var _a;
|
|
2991
|
+
let { transition = visualElement.getDefaultTransition(), transitionEnd, ...target } = targetAndTransition;
|
|
2992
|
+
if (transitionOverride)
|
|
2993
|
+
transition = transitionOverride;
|
|
2994
|
+
const animations = [];
|
|
2995
|
+
const animationTypeState = type && visualElement.animationState && visualElement.animationState.getState()[type];
|
|
2996
|
+
for (const key in target) {
|
|
2997
|
+
const value = visualElement.getValue(key, (_a = visualElement.latestValues[key]) !== null && _a !== void 0 ? _a : null);
|
|
2998
|
+
const valueTarget = target[key];
|
|
2999
|
+
if (valueTarget === void 0 || animationTypeState && shouldBlockAnimation(animationTypeState, key)) {
|
|
3000
|
+
continue;
|
|
3001
|
+
}
|
|
3002
|
+
const valueTransition = {
|
|
3003
|
+
delay,
|
|
3004
|
+
...getValueTransition$1(transition || {}, key)
|
|
3005
|
+
};
|
|
3006
|
+
let isHandoff = false;
|
|
3007
|
+
if (window.MotionHandoffAnimation) {
|
|
3008
|
+
const appearId = getOptimisedAppearId(visualElement);
|
|
3009
|
+
if (appearId) {
|
|
3010
|
+
const startTime = window.MotionHandoffAnimation(appearId, key, frame);
|
|
3011
|
+
if (startTime !== null) {
|
|
3012
|
+
valueTransition.startTime = startTime;
|
|
3013
|
+
isHandoff = true;
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
addValueToWillChange(visualElement, key);
|
|
3018
|
+
value.start(animateMotionValue(key, value, valueTarget, visualElement.shouldReduceMotion && positionalKeys.has(key) ? { type: false } : valueTransition, visualElement, isHandoff));
|
|
3019
|
+
const animation = value.animation;
|
|
3020
|
+
if (animation) {
|
|
3021
|
+
animations.push(animation);
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
if (transitionEnd) {
|
|
3025
|
+
Promise.all(animations).then(() => {
|
|
3026
|
+
frame.update(() => {
|
|
3027
|
+
transitionEnd && setTarget(visualElement, transitionEnd);
|
|
3028
|
+
});
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
return animations;
|
|
3032
|
+
}
|
|
3033
|
+
const createAxis = () => ({ min: 0, max: 0 });
|
|
3034
|
+
const createBox = () => ({
|
|
3035
|
+
x: createAxis(),
|
|
3036
|
+
y: createAxis()
|
|
3037
|
+
});
|
|
3038
|
+
function convertBoundingBoxToBox({ top, left, right, bottom }) {
|
|
3039
|
+
return {
|
|
3040
|
+
x: { min: left, max: right },
|
|
3041
|
+
y: { min: top, max: bottom }
|
|
3042
|
+
};
|
|
3043
|
+
}
|
|
3044
|
+
function transformBoxPoints(point, transformPoint) {
|
|
3045
|
+
if (!transformPoint)
|
|
3046
|
+
return point;
|
|
3047
|
+
const topLeft = transformPoint({ x: point.left, y: point.top });
|
|
3048
|
+
const bottomRight = transformPoint({ x: point.right, y: point.bottom });
|
|
3049
|
+
return {
|
|
3050
|
+
top: topLeft.y,
|
|
3051
|
+
left: topLeft.x,
|
|
3052
|
+
bottom: bottomRight.y,
|
|
3053
|
+
right: bottomRight.x
|
|
3054
|
+
};
|
|
3055
|
+
}
|
|
3056
|
+
function measureViewportBox(instance, transformPoint) {
|
|
3057
|
+
return convertBoundingBoxToBox(transformBoxPoints(instance.getBoundingClientRect(), transformPoint));
|
|
3058
|
+
}
|
|
3059
|
+
function animateSingleValue(value, keyframes2, options) {
|
|
3060
|
+
const motionValue$1 = isMotionValue(value) ? value : motionValue(value);
|
|
3061
|
+
motionValue$1.start(animateMotionValue("", motionValue$1, keyframes2, options));
|
|
3062
|
+
return motionValue$1.animation;
|
|
3063
|
+
}
|
|
3064
|
+
function isSVGElement(element) {
|
|
3065
|
+
return element instanceof SVGElement && element.tagName !== "svg";
|
|
3066
|
+
}
|
|
3067
|
+
function resolveElements(elementOrSelector, scope, selectorCache) {
|
|
3068
|
+
var _a;
|
|
3069
|
+
if (elementOrSelector instanceof Element) {
|
|
3070
|
+
return [elementOrSelector];
|
|
3071
|
+
} else if (typeof elementOrSelector === "string") {
|
|
3072
|
+
let root = document;
|
|
3073
|
+
if (scope) {
|
|
3074
|
+
root = scope.current;
|
|
3075
|
+
}
|
|
3076
|
+
const elements = (_a = selectorCache === null || selectorCache === void 0 ? void 0 : selectorCache[elementOrSelector]) !== null && _a !== void 0 ? _a : root.querySelectorAll(elementOrSelector);
|
|
3077
|
+
return elements ? Array.from(elements) : [];
|
|
3078
|
+
}
|
|
3079
|
+
return Array.from(elementOrSelector);
|
|
3080
|
+
}
|
|
3081
|
+
const prefersReducedMotion = { current: null };
|
|
3082
|
+
const hasReducedMotionListener = { current: false };
|
|
3083
|
+
function initPrefersReducedMotion() {
|
|
3084
|
+
hasReducedMotionListener.current = true;
|
|
3085
|
+
if (!isBrowser)
|
|
3086
|
+
return;
|
|
3087
|
+
if (window.matchMedia) {
|
|
3088
|
+
const motionMediaQuery = window.matchMedia("(prefers-reduced-motion)");
|
|
3089
|
+
const setReducedMotionPreferences = () => prefersReducedMotion.current = motionMediaQuery.matches;
|
|
3090
|
+
motionMediaQuery.addListener(setReducedMotionPreferences);
|
|
3091
|
+
setReducedMotionPreferences();
|
|
3092
|
+
} else {
|
|
3093
|
+
prefersReducedMotion.current = false;
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
const valueTypes = [...dimensionValueTypes, color, complex];
|
|
3097
|
+
const findValueType = (v) => valueTypes.find(testValueType(v));
|
|
3098
|
+
const visualElementStore = /* @__PURE__ */ new WeakMap();
|
|
3099
|
+
function updateMotionValuesFromProps(element, next, prev) {
|
|
3100
|
+
for (const key in next) {
|
|
3101
|
+
const nextValue = next[key];
|
|
3102
|
+
const prevValue = prev[key];
|
|
3103
|
+
if (isMotionValue(nextValue)) {
|
|
3104
|
+
element.addValue(key, nextValue);
|
|
3105
|
+
if (process.env.NODE_ENV === "development") {
|
|
3106
|
+
warnOnce(nextValue.version === "11.18.2", `Attempting to mix Motion versions ${nextValue.version} with 11.18.2 may not work as expected.`);
|
|
3107
|
+
}
|
|
3108
|
+
} else if (isMotionValue(prevValue)) {
|
|
3109
|
+
element.addValue(key, motionValue(nextValue, { owner: element }));
|
|
3110
|
+
} else if (prevValue !== nextValue) {
|
|
3111
|
+
if (element.hasValue(key)) {
|
|
3112
|
+
const existingValue = element.getValue(key);
|
|
3113
|
+
if (existingValue.liveStyle === true) {
|
|
3114
|
+
existingValue.jump(nextValue);
|
|
3115
|
+
} else if (!existingValue.hasAnimated) {
|
|
3116
|
+
existingValue.set(nextValue);
|
|
3117
|
+
}
|
|
3118
|
+
} else {
|
|
3119
|
+
const latestValue = element.getStaticValue(key);
|
|
3120
|
+
element.addValue(key, motionValue(latestValue !== void 0 ? latestValue : nextValue, { owner: element }));
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
for (const key in prev) {
|
|
3125
|
+
if (next[key] === void 0)
|
|
3126
|
+
element.removeValue(key);
|
|
3127
|
+
}
|
|
3128
|
+
return next;
|
|
3129
|
+
}
|
|
3130
|
+
const propEventHandlers = [
|
|
3131
|
+
"AnimationStart",
|
|
3132
|
+
"AnimationComplete",
|
|
3133
|
+
"Update",
|
|
3134
|
+
"BeforeLayoutMeasure",
|
|
3135
|
+
"LayoutMeasure",
|
|
3136
|
+
"LayoutAnimationStart",
|
|
3137
|
+
"LayoutAnimationComplete"
|
|
3138
|
+
];
|
|
3139
|
+
class VisualElement {
|
|
3140
|
+
/**
|
|
3141
|
+
* This method takes React props and returns found MotionValues. For example, HTML
|
|
3142
|
+
* MotionValues will be found within the style prop, whereas for Three.js within attribute arrays.
|
|
3143
|
+
*
|
|
3144
|
+
* This isn't an abstract method as it needs calling in the constructor, but it is
|
|
3145
|
+
* intended to be one.
|
|
3146
|
+
*/
|
|
3147
|
+
scrapeMotionValuesFromProps(_props, _prevProps, _visualElement) {
|
|
3148
|
+
return {};
|
|
3149
|
+
}
|
|
3150
|
+
constructor({ parent, props, presenceContext, reducedMotionConfig, blockInitialAnimation, visualState }, options = {}) {
|
|
3151
|
+
this.current = null;
|
|
3152
|
+
this.children = /* @__PURE__ */ new Set();
|
|
3153
|
+
this.isVariantNode = false;
|
|
3154
|
+
this.isControllingVariants = false;
|
|
3155
|
+
this.shouldReduceMotion = null;
|
|
3156
|
+
this.values = /* @__PURE__ */ new Map();
|
|
3157
|
+
this.KeyframeResolver = KeyframeResolver;
|
|
3158
|
+
this.features = {};
|
|
3159
|
+
this.valueSubscriptions = /* @__PURE__ */ new Map();
|
|
3160
|
+
this.prevMotionValues = {};
|
|
3161
|
+
this.events = {};
|
|
3162
|
+
this.propEventSubscriptions = {};
|
|
3163
|
+
this.notifyUpdate = () => this.notify("Update", this.latestValues);
|
|
3164
|
+
this.render = () => {
|
|
3165
|
+
if (!this.current)
|
|
3166
|
+
return;
|
|
3167
|
+
this.triggerBuild();
|
|
3168
|
+
this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
|
|
3169
|
+
};
|
|
3170
|
+
this.renderScheduledAt = 0;
|
|
3171
|
+
this.scheduleRender = () => {
|
|
3172
|
+
const now2 = time.now();
|
|
3173
|
+
if (this.renderScheduledAt < now2) {
|
|
3174
|
+
this.renderScheduledAt = now2;
|
|
3175
|
+
frame.render(this.render, false, true);
|
|
3176
|
+
}
|
|
3177
|
+
};
|
|
3178
|
+
const { latestValues, renderState, onUpdate } = visualState;
|
|
3179
|
+
this.onUpdate = onUpdate;
|
|
3180
|
+
this.latestValues = latestValues;
|
|
3181
|
+
this.baseTarget = { ...latestValues };
|
|
3182
|
+
this.initialValues = props.initial ? { ...latestValues } : {};
|
|
3183
|
+
this.renderState = renderState;
|
|
3184
|
+
this.parent = parent;
|
|
3185
|
+
this.props = props;
|
|
3186
|
+
this.presenceContext = presenceContext;
|
|
3187
|
+
this.depth = parent ? parent.depth + 1 : 0;
|
|
3188
|
+
this.reducedMotionConfig = reducedMotionConfig;
|
|
3189
|
+
this.options = options;
|
|
3190
|
+
this.blockInitialAnimation = Boolean(blockInitialAnimation);
|
|
3191
|
+
this.isControllingVariants = isControllingVariants(props);
|
|
3192
|
+
this.isVariantNode = isVariantNode(props);
|
|
3193
|
+
if (this.isVariantNode) {
|
|
3194
|
+
this.variantChildren = /* @__PURE__ */ new Set();
|
|
3195
|
+
}
|
|
3196
|
+
this.manuallyAnimateOnMount = Boolean(parent && parent.current);
|
|
3197
|
+
const { willChange, ...initialMotionValues } = this.scrapeMotionValuesFromProps(props, {}, this);
|
|
3198
|
+
for (const key in initialMotionValues) {
|
|
3199
|
+
const value = initialMotionValues[key];
|
|
3200
|
+
if (latestValues[key] !== void 0 && isMotionValue(value)) {
|
|
3201
|
+
value.set(latestValues[key], false);
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
mount(instance) {
|
|
3206
|
+
this.current = instance;
|
|
3207
|
+
visualElementStore.set(instance, this);
|
|
3208
|
+
if (this.projection && !this.projection.instance) {
|
|
3209
|
+
this.projection.mount(instance);
|
|
3210
|
+
}
|
|
3211
|
+
if (this.parent && this.isVariantNode && !this.isControllingVariants) {
|
|
3212
|
+
this.removeFromVariantTree = this.parent.addVariantChild(this);
|
|
3213
|
+
}
|
|
3214
|
+
this.values.forEach((value, key) => this.bindToMotionValue(key, value));
|
|
3215
|
+
if (!hasReducedMotionListener.current) {
|
|
3216
|
+
initPrefersReducedMotion();
|
|
3217
|
+
}
|
|
3218
|
+
this.shouldReduceMotion = this.reducedMotionConfig === "never" ? false : this.reducedMotionConfig === "always" ? true : prefersReducedMotion.current;
|
|
3219
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3220
|
+
warnOnce(this.shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
|
|
3221
|
+
}
|
|
3222
|
+
if (this.parent)
|
|
3223
|
+
this.parent.children.add(this);
|
|
3224
|
+
this.update(this.props, this.presenceContext);
|
|
3225
|
+
}
|
|
3226
|
+
unmount() {
|
|
3227
|
+
visualElementStore.delete(this.current);
|
|
3228
|
+
this.projection && this.projection.unmount();
|
|
3229
|
+
cancelFrame(this.notifyUpdate);
|
|
3230
|
+
cancelFrame(this.render);
|
|
3231
|
+
this.valueSubscriptions.forEach((remove) => remove());
|
|
3232
|
+
this.valueSubscriptions.clear();
|
|
3233
|
+
this.removeFromVariantTree && this.removeFromVariantTree();
|
|
3234
|
+
this.parent && this.parent.children.delete(this);
|
|
3235
|
+
for (const key in this.events) {
|
|
3236
|
+
this.events[key].clear();
|
|
3237
|
+
}
|
|
3238
|
+
for (const key in this.features) {
|
|
3239
|
+
const feature = this.features[key];
|
|
3240
|
+
if (feature) {
|
|
3241
|
+
feature.unmount();
|
|
3242
|
+
feature.isMounted = false;
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
this.current = null;
|
|
3246
|
+
}
|
|
3247
|
+
bindToMotionValue(key, value) {
|
|
3248
|
+
if (this.valueSubscriptions.has(key)) {
|
|
3249
|
+
this.valueSubscriptions.get(key)();
|
|
3250
|
+
}
|
|
3251
|
+
const valueIsTransform = transformProps.has(key);
|
|
3252
|
+
const removeOnChange = value.on("change", (latestValue) => {
|
|
3253
|
+
this.latestValues[key] = latestValue;
|
|
3254
|
+
this.props.onUpdate && frame.preRender(this.notifyUpdate);
|
|
3255
|
+
if (valueIsTransform && this.projection) {
|
|
3256
|
+
this.projection.isTransformDirty = true;
|
|
3257
|
+
}
|
|
3258
|
+
});
|
|
3259
|
+
const removeOnRenderRequest = value.on("renderRequest", this.scheduleRender);
|
|
3260
|
+
let removeSyncCheck;
|
|
3261
|
+
if (window.MotionCheckAppearSync) {
|
|
3262
|
+
removeSyncCheck = window.MotionCheckAppearSync(this, key, value);
|
|
3263
|
+
}
|
|
3264
|
+
this.valueSubscriptions.set(key, () => {
|
|
3265
|
+
removeOnChange();
|
|
3266
|
+
removeOnRenderRequest();
|
|
3267
|
+
if (removeSyncCheck)
|
|
3268
|
+
removeSyncCheck();
|
|
3269
|
+
if (value.owner)
|
|
3270
|
+
value.stop();
|
|
3271
|
+
});
|
|
3272
|
+
}
|
|
3273
|
+
sortNodePosition(other) {
|
|
3274
|
+
if (!this.current || !this.sortInstanceNodePosition || this.type !== other.type) {
|
|
3275
|
+
return 0;
|
|
3276
|
+
}
|
|
3277
|
+
return this.sortInstanceNodePosition(this.current, other.current);
|
|
3278
|
+
}
|
|
3279
|
+
updateFeatures() {
|
|
3280
|
+
let key = "animation";
|
|
3281
|
+
for (key in featureDefinitions) {
|
|
3282
|
+
const featureDefinition = featureDefinitions[key];
|
|
3283
|
+
if (!featureDefinition)
|
|
3284
|
+
continue;
|
|
3285
|
+
const { isEnabled, Feature: FeatureConstructor } = featureDefinition;
|
|
3286
|
+
if (!this.features[key] && FeatureConstructor && isEnabled(this.props)) {
|
|
3287
|
+
this.features[key] = new FeatureConstructor(this);
|
|
3288
|
+
}
|
|
3289
|
+
if (this.features[key]) {
|
|
3290
|
+
const feature = this.features[key];
|
|
3291
|
+
if (feature.isMounted) {
|
|
3292
|
+
feature.update();
|
|
3293
|
+
} else {
|
|
3294
|
+
feature.mount();
|
|
3295
|
+
feature.isMounted = true;
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
triggerBuild() {
|
|
3301
|
+
this.build(this.renderState, this.latestValues, this.props);
|
|
3302
|
+
}
|
|
3303
|
+
/**
|
|
3304
|
+
* Measure the current viewport box with or without transforms.
|
|
3305
|
+
* Only measures axis-aligned boxes, rotate and skew must be manually
|
|
3306
|
+
* removed with a re-render to work.
|
|
3307
|
+
*/
|
|
3308
|
+
measureViewportBox() {
|
|
3309
|
+
return this.current ? this.measureInstanceViewportBox(this.current, this.props) : createBox();
|
|
3310
|
+
}
|
|
3311
|
+
getStaticValue(key) {
|
|
3312
|
+
return this.latestValues[key];
|
|
3313
|
+
}
|
|
3314
|
+
setStaticValue(key, value) {
|
|
3315
|
+
this.latestValues[key] = value;
|
|
3316
|
+
}
|
|
3317
|
+
/**
|
|
3318
|
+
* Update the provided props. Ensure any newly-added motion values are
|
|
3319
|
+
* added to our map, old ones removed, and listeners updated.
|
|
3320
|
+
*/
|
|
3321
|
+
update(props, presenceContext) {
|
|
3322
|
+
if (props.transformTemplate || this.props.transformTemplate) {
|
|
3323
|
+
this.scheduleRender();
|
|
3324
|
+
}
|
|
3325
|
+
this.prevProps = this.props;
|
|
3326
|
+
this.props = props;
|
|
3327
|
+
this.prevPresenceContext = this.presenceContext;
|
|
3328
|
+
this.presenceContext = presenceContext;
|
|
3329
|
+
for (let i = 0; i < propEventHandlers.length; i++) {
|
|
3330
|
+
const key = propEventHandlers[i];
|
|
3331
|
+
if (this.propEventSubscriptions[key]) {
|
|
3332
|
+
this.propEventSubscriptions[key]();
|
|
3333
|
+
delete this.propEventSubscriptions[key];
|
|
3334
|
+
}
|
|
3335
|
+
const listenerName = "on" + key;
|
|
3336
|
+
const listener = props[listenerName];
|
|
3337
|
+
if (listener) {
|
|
3338
|
+
this.propEventSubscriptions[key] = this.on(key, listener);
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
this.prevMotionValues = updateMotionValuesFromProps(this, this.scrapeMotionValuesFromProps(props, this.prevProps, this), this.prevMotionValues);
|
|
3342
|
+
if (this.handleChildMotionValue) {
|
|
3343
|
+
this.handleChildMotionValue();
|
|
3344
|
+
}
|
|
3345
|
+
this.onUpdate && this.onUpdate(this);
|
|
3346
|
+
}
|
|
3347
|
+
getProps() {
|
|
3348
|
+
return this.props;
|
|
3349
|
+
}
|
|
3350
|
+
/**
|
|
3351
|
+
* Returns the variant definition with a given name.
|
|
3352
|
+
*/
|
|
3353
|
+
getVariant(name) {
|
|
3354
|
+
return this.props.variants ? this.props.variants[name] : void 0;
|
|
3355
|
+
}
|
|
3356
|
+
/**
|
|
3357
|
+
* Returns the defined default transition on this component.
|
|
3358
|
+
*/
|
|
3359
|
+
getDefaultTransition() {
|
|
3360
|
+
return this.props.transition;
|
|
3361
|
+
}
|
|
3362
|
+
getTransformPagePoint() {
|
|
3363
|
+
return this.props.transformPagePoint;
|
|
3364
|
+
}
|
|
3365
|
+
getClosestVariantNode() {
|
|
3366
|
+
return this.isVariantNode ? this : this.parent ? this.parent.getClosestVariantNode() : void 0;
|
|
3367
|
+
}
|
|
3368
|
+
/**
|
|
3369
|
+
* Add a child visual element to our set of children.
|
|
3370
|
+
*/
|
|
3371
|
+
addVariantChild(child) {
|
|
3372
|
+
const closestVariantNode = this.getClosestVariantNode();
|
|
3373
|
+
if (closestVariantNode) {
|
|
3374
|
+
closestVariantNode.variantChildren && closestVariantNode.variantChildren.add(child);
|
|
3375
|
+
return () => closestVariantNode.variantChildren.delete(child);
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
/**
|
|
3379
|
+
* Add a motion value and bind it to this visual element.
|
|
3380
|
+
*/
|
|
3381
|
+
addValue(key, value) {
|
|
3382
|
+
const existingValue = this.values.get(key);
|
|
3383
|
+
if (value !== existingValue) {
|
|
3384
|
+
if (existingValue)
|
|
3385
|
+
this.removeValue(key);
|
|
3386
|
+
this.bindToMotionValue(key, value);
|
|
3387
|
+
this.values.set(key, value);
|
|
3388
|
+
this.latestValues[key] = value.get();
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
/**
|
|
3392
|
+
* Remove a motion value and unbind any active subscriptions.
|
|
3393
|
+
*/
|
|
3394
|
+
removeValue(key) {
|
|
3395
|
+
this.values.delete(key);
|
|
3396
|
+
const unsubscribe = this.valueSubscriptions.get(key);
|
|
3397
|
+
if (unsubscribe) {
|
|
3398
|
+
unsubscribe();
|
|
3399
|
+
this.valueSubscriptions.delete(key);
|
|
3400
|
+
}
|
|
3401
|
+
delete this.latestValues[key];
|
|
3402
|
+
this.removeValueFromRenderState(key, this.renderState);
|
|
3403
|
+
}
|
|
3404
|
+
/**
|
|
3405
|
+
* Check whether we have a motion value for this key
|
|
3406
|
+
*/
|
|
3407
|
+
hasValue(key) {
|
|
3408
|
+
return this.values.has(key);
|
|
3409
|
+
}
|
|
3410
|
+
getValue(key, defaultValue) {
|
|
3411
|
+
if (this.props.values && this.props.values[key]) {
|
|
3412
|
+
return this.props.values[key];
|
|
3413
|
+
}
|
|
3414
|
+
let value = this.values.get(key);
|
|
3415
|
+
if (value === void 0 && defaultValue !== void 0) {
|
|
3416
|
+
value = motionValue(defaultValue === null ? void 0 : defaultValue, { owner: this });
|
|
3417
|
+
this.addValue(key, value);
|
|
3418
|
+
}
|
|
3419
|
+
return value;
|
|
3420
|
+
}
|
|
3421
|
+
/**
|
|
3422
|
+
* If we're trying to animate to a previously unencountered value,
|
|
3423
|
+
* we need to check for it in our state and as a last resort read it
|
|
3424
|
+
* directly from the instance (which might have performance implications).
|
|
3425
|
+
*/
|
|
3426
|
+
readValue(key, target) {
|
|
3427
|
+
var _a;
|
|
3428
|
+
let value = this.latestValues[key] !== void 0 || !this.current ? this.latestValues[key] : (_a = this.getBaseTargetFromProps(this.props, key)) !== null && _a !== void 0 ? _a : this.readValueFromInstance(this.current, key, this.options);
|
|
3429
|
+
if (value !== void 0 && value !== null) {
|
|
3430
|
+
if (typeof value === "string" && (isNumericalString(value) || isZeroValueString(value))) {
|
|
3431
|
+
value = parseFloat(value);
|
|
3432
|
+
} else if (!findValueType(value) && complex.test(target)) {
|
|
3433
|
+
value = getAnimatableNone(key, target);
|
|
3434
|
+
}
|
|
3435
|
+
this.setBaseTarget(key, isMotionValue(value) ? value.get() : value);
|
|
3436
|
+
}
|
|
3437
|
+
return isMotionValue(value) ? value.get() : value;
|
|
3438
|
+
}
|
|
3439
|
+
/**
|
|
3440
|
+
* Set the base target to later animate back to. This is currently
|
|
3441
|
+
* only hydrated on creation and when we first read a value.
|
|
3442
|
+
*/
|
|
3443
|
+
setBaseTarget(key, value) {
|
|
3444
|
+
this.baseTarget[key] = value;
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* Find the base target for a value thats been removed from all animation
|
|
3448
|
+
* props.
|
|
3449
|
+
*/
|
|
3450
|
+
getBaseTarget(key) {
|
|
3451
|
+
var _a;
|
|
3452
|
+
const { initial } = this.props;
|
|
3453
|
+
let valueFromInitial;
|
|
3454
|
+
if (typeof initial === "string" || typeof initial === "object") {
|
|
3455
|
+
const variant = resolveVariantFromProps(this.props, initial, (_a = this.presenceContext) === null || _a === void 0 ? void 0 : _a.custom);
|
|
3456
|
+
if (variant) {
|
|
3457
|
+
valueFromInitial = variant[key];
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
if (initial && valueFromInitial !== void 0) {
|
|
3461
|
+
return valueFromInitial;
|
|
3462
|
+
}
|
|
3463
|
+
const target = this.getBaseTargetFromProps(this.props, key);
|
|
3464
|
+
if (target !== void 0 && !isMotionValue(target))
|
|
3465
|
+
return target;
|
|
3466
|
+
return this.initialValues[key] !== void 0 && valueFromInitial === void 0 ? void 0 : this.baseTarget[key];
|
|
3467
|
+
}
|
|
3468
|
+
on(eventName, callback) {
|
|
3469
|
+
if (!this.events[eventName]) {
|
|
3470
|
+
this.events[eventName] = new SubscriptionManager();
|
|
3471
|
+
}
|
|
3472
|
+
return this.events[eventName].add(callback);
|
|
3473
|
+
}
|
|
3474
|
+
notify(eventName, ...args) {
|
|
3475
|
+
if (this.events[eventName]) {
|
|
3476
|
+
this.events[eventName].notify(...args);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
class DOMVisualElement extends VisualElement {
|
|
3481
|
+
constructor() {
|
|
3482
|
+
super(...arguments);
|
|
3483
|
+
this.KeyframeResolver = DOMKeyframesResolver;
|
|
3484
|
+
}
|
|
3485
|
+
sortInstanceNodePosition(a, b) {
|
|
3486
|
+
return a.compareDocumentPosition(b) & 2 ? 1 : -1;
|
|
3487
|
+
}
|
|
3488
|
+
getBaseTargetFromProps(props, key) {
|
|
3489
|
+
return props.style ? props.style[key] : void 0;
|
|
3490
|
+
}
|
|
3491
|
+
removeValueFromRenderState(key, { vars, style }) {
|
|
3492
|
+
delete vars[key];
|
|
3493
|
+
delete style[key];
|
|
3494
|
+
}
|
|
3495
|
+
handleChildMotionValue() {
|
|
3496
|
+
if (this.childSubscription) {
|
|
3497
|
+
this.childSubscription();
|
|
3498
|
+
delete this.childSubscription;
|
|
3499
|
+
}
|
|
3500
|
+
const { children } = this.props;
|
|
3501
|
+
if (isMotionValue(children)) {
|
|
3502
|
+
this.childSubscription = children.on("change", (latest) => {
|
|
3503
|
+
if (this.current) {
|
|
3504
|
+
this.current.textContent = `${latest}`;
|
|
3505
|
+
}
|
|
3506
|
+
});
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
function getComputedStyle(element) {
|
|
3511
|
+
return window.getComputedStyle(element);
|
|
3512
|
+
}
|
|
3513
|
+
class HTMLVisualElement extends DOMVisualElement {
|
|
3514
|
+
constructor() {
|
|
3515
|
+
super(...arguments);
|
|
3516
|
+
this.type = "html";
|
|
3517
|
+
this.renderInstance = renderHTML;
|
|
3518
|
+
}
|
|
3519
|
+
readValueFromInstance(instance, key) {
|
|
3520
|
+
if (transformProps.has(key)) {
|
|
3521
|
+
const defaultType = getDefaultValueType(key);
|
|
3522
|
+
return defaultType ? defaultType.default || 0 : 0;
|
|
3523
|
+
} else {
|
|
3524
|
+
const computedStyle = getComputedStyle(instance);
|
|
3525
|
+
const value = (isCSSVariableName(key) ? computedStyle.getPropertyValue(key) : computedStyle[key]) || 0;
|
|
3526
|
+
return typeof value === "string" ? value.trim() : value;
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
measureInstanceViewportBox(instance, { transformPagePoint }) {
|
|
3530
|
+
return measureViewportBox(instance, transformPagePoint);
|
|
3531
|
+
}
|
|
3532
|
+
build(renderState, latestValues, props) {
|
|
3533
|
+
buildHTMLStyles(renderState, latestValues, props.transformTemplate);
|
|
3534
|
+
}
|
|
3535
|
+
scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
3536
|
+
return scrapeMotionValuesFromProps$1(props, prevProps, visualElement);
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
class SVGVisualElement extends DOMVisualElement {
|
|
3540
|
+
constructor() {
|
|
3541
|
+
super(...arguments);
|
|
3542
|
+
this.type = "svg";
|
|
3543
|
+
this.isSVGTag = false;
|
|
3544
|
+
this.measureInstanceViewportBox = createBox;
|
|
3545
|
+
}
|
|
3546
|
+
getBaseTargetFromProps(props, key) {
|
|
3547
|
+
return props[key];
|
|
3548
|
+
}
|
|
3549
|
+
readValueFromInstance(instance, key) {
|
|
3550
|
+
if (transformProps.has(key)) {
|
|
3551
|
+
const defaultType = getDefaultValueType(key);
|
|
3552
|
+
return defaultType ? defaultType.default || 0 : 0;
|
|
3553
|
+
}
|
|
3554
|
+
key = !camelCaseAttributes.has(key) ? camelToDash(key) : key;
|
|
3555
|
+
return instance.getAttribute(key);
|
|
3556
|
+
}
|
|
3557
|
+
scrapeMotionValuesFromProps(props, prevProps, visualElement) {
|
|
3558
|
+
return scrapeMotionValuesFromProps(props, prevProps, visualElement);
|
|
3559
|
+
}
|
|
3560
|
+
build(renderState, latestValues, props) {
|
|
3561
|
+
buildSVGAttrs(renderState, latestValues, this.isSVGTag, props.transformTemplate);
|
|
3562
|
+
}
|
|
3563
|
+
renderInstance(instance, renderState, styleProp, projection) {
|
|
3564
|
+
renderSVG(instance, renderState, styleProp, projection);
|
|
3565
|
+
}
|
|
3566
|
+
mount(instance) {
|
|
3567
|
+
this.isSVGTag = isSVGTag(instance.tagName);
|
|
3568
|
+
super.mount(instance);
|
|
3569
|
+
}
|
|
3570
|
+
}
|
|
3571
|
+
function useUnmountEffect(callback) {
|
|
3572
|
+
return useEffect(() => () => callback(), []);
|
|
3573
|
+
}
|
|
3574
|
+
function createGeneratorEasing(options, scale2 = 100, createGenerator) {
|
|
3575
|
+
const generator = createGenerator({ ...options, keyframes: [0, scale2] });
|
|
3576
|
+
const duration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
|
|
3577
|
+
return {
|
|
3578
|
+
type: "keyframes",
|
|
3579
|
+
ease: (progress2) => {
|
|
3580
|
+
return generator.next(duration * progress2).value / scale2;
|
|
3581
|
+
},
|
|
3582
|
+
duration: /* @__PURE__ */ millisecondsToSeconds(duration)
|
|
3583
|
+
};
|
|
3584
|
+
}
|
|
3585
|
+
const wrap = (min, max, v) => {
|
|
3586
|
+
const rangeSize = max - min;
|
|
3587
|
+
return ((v - min) % rangeSize + rangeSize) % rangeSize + min;
|
|
3588
|
+
};
|
|
3589
|
+
function getEasingForSegment(easing, i) {
|
|
3590
|
+
return isEasingArray(easing) ? easing[wrap(0, easing.length, i)] : easing;
|
|
3591
|
+
}
|
|
3592
|
+
function isDOMKeyframes(keyframes2) {
|
|
3593
|
+
return typeof keyframes2 === "object" && !Array.isArray(keyframes2);
|
|
3594
|
+
}
|
|
3595
|
+
function resolveSubjects(subject, keyframes2, scope, selectorCache) {
|
|
3596
|
+
if (typeof subject === "string" && isDOMKeyframes(keyframes2)) {
|
|
3597
|
+
return resolveElements(subject, scope, selectorCache);
|
|
3598
|
+
} else if (subject instanceof NodeList) {
|
|
3599
|
+
return Array.from(subject);
|
|
3600
|
+
} else if (Array.isArray(subject)) {
|
|
3601
|
+
return subject;
|
|
3602
|
+
} else {
|
|
3603
|
+
return [subject];
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
function calculateRepeatDuration(duration, repeat, _repeatDelay) {
|
|
3607
|
+
return duration * (repeat + 1);
|
|
3608
|
+
}
|
|
3609
|
+
function calcNextTime(current, next, prev, labels) {
|
|
3610
|
+
var _a;
|
|
3611
|
+
if (typeof next === "number") {
|
|
3612
|
+
return next;
|
|
3613
|
+
} else if (next.startsWith("-") || next.startsWith("+")) {
|
|
3614
|
+
return Math.max(0, current + parseFloat(next));
|
|
3615
|
+
} else if (next === "<") {
|
|
3616
|
+
return prev;
|
|
3617
|
+
} else {
|
|
3618
|
+
return (_a = labels.get(next)) !== null && _a !== void 0 ? _a : current;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
function eraseKeyframes(sequence, startTime, endTime) {
|
|
3622
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
3623
|
+
const keyframe = sequence[i];
|
|
3624
|
+
if (keyframe.at > startTime && keyframe.at < endTime) {
|
|
3625
|
+
removeItem(sequence, keyframe);
|
|
3626
|
+
i--;
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
}
|
|
3630
|
+
function addKeyframes(sequence, keyframes2, easing, offset, startTime, endTime) {
|
|
3631
|
+
eraseKeyframes(sequence, startTime, endTime);
|
|
3632
|
+
for (let i = 0; i < keyframes2.length; i++) {
|
|
3633
|
+
sequence.push({
|
|
3634
|
+
value: keyframes2[i],
|
|
3635
|
+
at: mixNumber$1(startTime, endTime, offset[i]),
|
|
3636
|
+
easing: getEasingForSegment(easing, i)
|
|
3637
|
+
});
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
function normalizeTimes(times, repeat) {
|
|
3641
|
+
for (let i = 0; i < times.length; i++) {
|
|
3642
|
+
times[i] = times[i] / (repeat + 1);
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
function compareByTime(a, b) {
|
|
3646
|
+
if (a.at === b.at) {
|
|
3647
|
+
if (a.value === null)
|
|
3648
|
+
return 1;
|
|
3649
|
+
if (b.value === null)
|
|
3650
|
+
return -1;
|
|
3651
|
+
return 0;
|
|
3652
|
+
} else {
|
|
3653
|
+
return a.at - b.at;
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
const defaultSegmentEasing = "easeInOut";
|
|
3657
|
+
const MAX_REPEAT = 20;
|
|
3658
|
+
function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators2) {
|
|
3659
|
+
const defaultDuration = defaultTransition.duration || 0.3;
|
|
3660
|
+
const animationDefinitions = /* @__PURE__ */ new Map();
|
|
3661
|
+
const sequences = /* @__PURE__ */ new Map();
|
|
3662
|
+
const elementCache = {};
|
|
3663
|
+
const timeLabels = /* @__PURE__ */ new Map();
|
|
3664
|
+
let prevTime = 0;
|
|
3665
|
+
let currentTime = 0;
|
|
3666
|
+
let totalDuration = 0;
|
|
3667
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
3668
|
+
const segment = sequence[i];
|
|
3669
|
+
if (typeof segment === "string") {
|
|
3670
|
+
timeLabels.set(segment, currentTime);
|
|
3671
|
+
continue;
|
|
3672
|
+
} else if (!Array.isArray(segment)) {
|
|
3673
|
+
timeLabels.set(segment.name, calcNextTime(currentTime, segment.at, prevTime, timeLabels));
|
|
3674
|
+
continue;
|
|
3675
|
+
}
|
|
3676
|
+
let [subject, keyframes2, transition = {}] = segment;
|
|
3677
|
+
if (transition.at !== void 0) {
|
|
3678
|
+
currentTime = calcNextTime(currentTime, transition.at, prevTime, timeLabels);
|
|
3679
|
+
}
|
|
3680
|
+
let maxDuration2 = 0;
|
|
3681
|
+
const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
|
|
3682
|
+
const valueKeyframesAsList = keyframesAsList(valueKeyframes);
|
|
3683
|
+
const { delay = 0, times = defaultOffset(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
|
|
3684
|
+
let { ease: ease2 = defaultTransition.ease || "easeOut", duration } = valueTransition;
|
|
3685
|
+
const calculatedDelay = typeof delay === "function" ? delay(elementIndex, numSubjects) : delay;
|
|
3686
|
+
const numKeyframes = valueKeyframesAsList.length;
|
|
3687
|
+
const createGenerator = isGenerator(type) ? type : generators2 === null || generators2 === void 0 ? void 0 : generators2[type];
|
|
3688
|
+
if (numKeyframes <= 2 && createGenerator) {
|
|
3689
|
+
let absoluteDelta = 100;
|
|
3690
|
+
if (numKeyframes === 2 && isNumberKeyframesArray(valueKeyframesAsList)) {
|
|
3691
|
+
const delta = valueKeyframesAsList[1] - valueKeyframesAsList[0];
|
|
3692
|
+
absoluteDelta = Math.abs(delta);
|
|
3693
|
+
}
|
|
3694
|
+
const springTransition = { ...remainingTransition };
|
|
3695
|
+
if (duration !== void 0) {
|
|
3696
|
+
springTransition.duration = /* @__PURE__ */ secondsToMilliseconds(duration);
|
|
3697
|
+
}
|
|
3698
|
+
const springEasing = createGeneratorEasing(springTransition, absoluteDelta, createGenerator);
|
|
3699
|
+
ease2 = springEasing.ease;
|
|
3700
|
+
duration = springEasing.duration;
|
|
3701
|
+
}
|
|
3702
|
+
duration !== null && duration !== void 0 ? duration : duration = defaultDuration;
|
|
3703
|
+
const startTime = currentTime + calculatedDelay;
|
|
3704
|
+
if (times.length === 1 && times[0] === 0) {
|
|
3705
|
+
times[1] = 1;
|
|
3706
|
+
}
|
|
3707
|
+
const remainder = times.length - valueKeyframesAsList.length;
|
|
3708
|
+
remainder > 0 && fillOffset(times, remainder);
|
|
3709
|
+
valueKeyframesAsList.length === 1 && valueKeyframesAsList.unshift(null);
|
|
3710
|
+
if (repeat) {
|
|
3711
|
+
invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
|
|
3712
|
+
duration = calculateRepeatDuration(duration, repeat);
|
|
3713
|
+
const originalKeyframes = [...valueKeyframesAsList];
|
|
3714
|
+
const originalTimes = [...times];
|
|
3715
|
+
ease2 = Array.isArray(ease2) ? [...ease2] : [ease2];
|
|
3716
|
+
const originalEase = [...ease2];
|
|
3717
|
+
for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
|
|
3718
|
+
valueKeyframesAsList.push(...originalKeyframes);
|
|
3719
|
+
for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
|
|
3720
|
+
times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
|
|
3721
|
+
ease2.push(keyframeIndex === 0 ? "linear" : getEasingForSegment(originalEase, keyframeIndex - 1));
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
normalizeTimes(times, repeat);
|
|
3725
|
+
}
|
|
3726
|
+
const targetTime = startTime + duration;
|
|
3727
|
+
addKeyframes(valueSequence, valueKeyframesAsList, ease2, times, startTime, targetTime);
|
|
3728
|
+
maxDuration2 = Math.max(calculatedDelay + duration, maxDuration2);
|
|
3729
|
+
totalDuration = Math.max(targetTime, totalDuration);
|
|
3730
|
+
};
|
|
3731
|
+
if (isMotionValue(subject)) {
|
|
3732
|
+
const subjectSequence = getSubjectSequence(subject, sequences);
|
|
3733
|
+
resolveValueSequence(keyframes2, transition, getValueSequence("default", subjectSequence));
|
|
3734
|
+
} else {
|
|
3735
|
+
const subjects = resolveSubjects(subject, keyframes2, scope, elementCache);
|
|
3736
|
+
const numSubjects = subjects.length;
|
|
3737
|
+
for (let subjectIndex = 0; subjectIndex < numSubjects; subjectIndex++) {
|
|
3738
|
+
keyframes2 = keyframes2;
|
|
3739
|
+
transition = transition;
|
|
3740
|
+
const thisSubject = subjects[subjectIndex];
|
|
3741
|
+
const subjectSequence = getSubjectSequence(thisSubject, sequences);
|
|
3742
|
+
for (const key in keyframes2) {
|
|
3743
|
+
resolveValueSequence(keyframes2[key], getValueTransition(transition, key), getValueSequence(key, subjectSequence), subjectIndex, numSubjects);
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
prevTime = currentTime;
|
|
3748
|
+
currentTime += maxDuration2;
|
|
3749
|
+
}
|
|
3750
|
+
sequences.forEach((valueSequences, element) => {
|
|
3751
|
+
for (const key in valueSequences) {
|
|
3752
|
+
const valueSequence = valueSequences[key];
|
|
3753
|
+
valueSequence.sort(compareByTime);
|
|
3754
|
+
const keyframes2 = [];
|
|
3755
|
+
const valueOffset = [];
|
|
3756
|
+
const valueEasing = [];
|
|
3757
|
+
for (let i = 0; i < valueSequence.length; i++) {
|
|
3758
|
+
const { at, value, easing } = valueSequence[i];
|
|
3759
|
+
keyframes2.push(value);
|
|
3760
|
+
valueOffset.push(/* @__PURE__ */ progress(0, totalDuration, at));
|
|
3761
|
+
valueEasing.push(easing || "easeOut");
|
|
3762
|
+
}
|
|
3763
|
+
if (valueOffset[0] !== 0) {
|
|
3764
|
+
valueOffset.unshift(0);
|
|
3765
|
+
keyframes2.unshift(keyframes2[0]);
|
|
3766
|
+
valueEasing.unshift(defaultSegmentEasing);
|
|
3767
|
+
}
|
|
3768
|
+
if (valueOffset[valueOffset.length - 1] !== 1) {
|
|
3769
|
+
valueOffset.push(1);
|
|
3770
|
+
keyframes2.push(null);
|
|
3771
|
+
}
|
|
3772
|
+
if (!animationDefinitions.has(element)) {
|
|
3773
|
+
animationDefinitions.set(element, {
|
|
3774
|
+
keyframes: {},
|
|
3775
|
+
transition: {}
|
|
3776
|
+
});
|
|
3777
|
+
}
|
|
3778
|
+
const definition = animationDefinitions.get(element);
|
|
3779
|
+
definition.keyframes[key] = keyframes2;
|
|
3780
|
+
definition.transition[key] = {
|
|
3781
|
+
...defaultTransition,
|
|
3782
|
+
duration: totalDuration,
|
|
3783
|
+
ease: valueEasing,
|
|
3784
|
+
times: valueOffset,
|
|
3785
|
+
...sequenceTransition
|
|
3786
|
+
};
|
|
3787
|
+
}
|
|
3788
|
+
});
|
|
3789
|
+
return animationDefinitions;
|
|
3790
|
+
}
|
|
3791
|
+
function getSubjectSequence(subject, sequences) {
|
|
3792
|
+
!sequences.has(subject) && sequences.set(subject, {});
|
|
3793
|
+
return sequences.get(subject);
|
|
3794
|
+
}
|
|
3795
|
+
function getValueSequence(name, sequences) {
|
|
3796
|
+
if (!sequences[name])
|
|
3797
|
+
sequences[name] = [];
|
|
3798
|
+
return sequences[name];
|
|
3799
|
+
}
|
|
3800
|
+
function keyframesAsList(keyframes2) {
|
|
3801
|
+
return Array.isArray(keyframes2) ? keyframes2 : [keyframes2];
|
|
3802
|
+
}
|
|
3803
|
+
function getValueTransition(transition, key) {
|
|
3804
|
+
return transition && transition[key] ? {
|
|
3805
|
+
...transition,
|
|
3806
|
+
...transition[key]
|
|
3807
|
+
} : { ...transition };
|
|
3808
|
+
}
|
|
3809
|
+
const isNumber = (keyframe) => typeof keyframe === "number";
|
|
3810
|
+
const isNumberKeyframesArray = (keyframes2) => keyframes2.every(isNumber);
|
|
3811
|
+
function isObjectKey(key, object) {
|
|
3812
|
+
return key in object;
|
|
3813
|
+
}
|
|
3814
|
+
class ObjectVisualElement extends VisualElement {
|
|
3815
|
+
constructor() {
|
|
3816
|
+
super(...arguments);
|
|
3817
|
+
this.type = "object";
|
|
3818
|
+
}
|
|
3819
|
+
readValueFromInstance(instance, key) {
|
|
3820
|
+
if (isObjectKey(key, instance)) {
|
|
3821
|
+
const value = instance[key];
|
|
3822
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
3823
|
+
return value;
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
return void 0;
|
|
3827
|
+
}
|
|
3828
|
+
getBaseTargetFromProps() {
|
|
3829
|
+
return void 0;
|
|
3830
|
+
}
|
|
3831
|
+
removeValueFromRenderState(key, renderState) {
|
|
3832
|
+
delete renderState.output[key];
|
|
3833
|
+
}
|
|
3834
|
+
measureInstanceViewportBox() {
|
|
3835
|
+
return createBox();
|
|
3836
|
+
}
|
|
3837
|
+
build(renderState, latestValues) {
|
|
3838
|
+
Object.assign(renderState.output, latestValues);
|
|
3839
|
+
}
|
|
3840
|
+
renderInstance(instance, { output }) {
|
|
3841
|
+
Object.assign(instance, output);
|
|
3842
|
+
}
|
|
3843
|
+
sortInstanceNodePosition() {
|
|
3844
|
+
return 0;
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
function createDOMVisualElement(element) {
|
|
3848
|
+
const options = {
|
|
3849
|
+
presenceContext: null,
|
|
3850
|
+
props: {},
|
|
3851
|
+
visualState: {
|
|
3852
|
+
renderState: {
|
|
3853
|
+
transform: {},
|
|
3854
|
+
transformOrigin: {},
|
|
3855
|
+
style: {},
|
|
3856
|
+
vars: {},
|
|
3857
|
+
attrs: {}
|
|
3858
|
+
},
|
|
3859
|
+
latestValues: {}
|
|
3860
|
+
}
|
|
3861
|
+
};
|
|
3862
|
+
const node = isSVGElement(element) ? new SVGVisualElement(options) : new HTMLVisualElement(options);
|
|
3863
|
+
node.mount(element);
|
|
3864
|
+
visualElementStore.set(element, node);
|
|
3865
|
+
}
|
|
3866
|
+
function createObjectVisualElement(subject) {
|
|
3867
|
+
const options = {
|
|
3868
|
+
presenceContext: null,
|
|
3869
|
+
props: {},
|
|
3870
|
+
visualState: {
|
|
3871
|
+
renderState: {
|
|
3872
|
+
output: {}
|
|
3873
|
+
},
|
|
3874
|
+
latestValues: {}
|
|
3875
|
+
}
|
|
3876
|
+
};
|
|
3877
|
+
const node = new ObjectVisualElement(options);
|
|
3878
|
+
node.mount(subject);
|
|
3879
|
+
visualElementStore.set(subject, node);
|
|
3880
|
+
}
|
|
3881
|
+
function isSingleValue(subject, keyframes2) {
|
|
3882
|
+
return isMotionValue(subject) || typeof subject === "number" || typeof subject === "string" && !isDOMKeyframes(keyframes2);
|
|
3883
|
+
}
|
|
3884
|
+
function animateSubject(subject, keyframes2, options, scope) {
|
|
3885
|
+
const animations = [];
|
|
3886
|
+
if (isSingleValue(subject, keyframes2)) {
|
|
3887
|
+
animations.push(animateSingleValue(subject, isDOMKeyframes(keyframes2) ? keyframes2.default || keyframes2 : keyframes2, options ? options.default || options : options));
|
|
3888
|
+
} else {
|
|
3889
|
+
const subjects = resolveSubjects(subject, keyframes2, scope);
|
|
3890
|
+
const numSubjects = subjects.length;
|
|
3891
|
+
invariant(Boolean(numSubjects), "No valid elements provided.");
|
|
3892
|
+
for (let i = 0; i < numSubjects; i++) {
|
|
3893
|
+
const thisSubject = subjects[i];
|
|
3894
|
+
const createVisualElement = thisSubject instanceof Element ? createDOMVisualElement : createObjectVisualElement;
|
|
3895
|
+
if (!visualElementStore.has(thisSubject)) {
|
|
3896
|
+
createVisualElement(thisSubject);
|
|
3897
|
+
}
|
|
3898
|
+
const visualElement = visualElementStore.get(thisSubject);
|
|
3899
|
+
const transition = { ...options };
|
|
3900
|
+
if ("delay" in transition && typeof transition.delay === "function") {
|
|
3901
|
+
transition.delay = transition.delay(i, numSubjects);
|
|
3902
|
+
}
|
|
3903
|
+
animations.push(...animateTarget(visualElement, { ...keyframes2, transition }, {}));
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
return animations;
|
|
3907
|
+
}
|
|
3908
|
+
function animateSequence(sequence, options, scope) {
|
|
3909
|
+
const animations = [];
|
|
3910
|
+
const animationDefinitions = createAnimationsFromSequence(sequence, options, scope, { spring });
|
|
3911
|
+
animationDefinitions.forEach(({ keyframes: keyframes2, transition }, subject) => {
|
|
3912
|
+
animations.push(...animateSubject(subject, keyframes2, transition));
|
|
3913
|
+
});
|
|
3914
|
+
return animations;
|
|
3915
|
+
}
|
|
3916
|
+
function isSequence(value) {
|
|
3917
|
+
return Array.isArray(value) && value.some(Array.isArray);
|
|
3918
|
+
}
|
|
3919
|
+
function createScopedAnimate(scope) {
|
|
3920
|
+
function scopedAnimate(subjectOrSequence, optionsOrKeyframes, options) {
|
|
3921
|
+
let animations = [];
|
|
3922
|
+
if (isSequence(subjectOrSequence)) {
|
|
3923
|
+
animations = animateSequence(subjectOrSequence, optionsOrKeyframes, scope);
|
|
3924
|
+
} else {
|
|
3925
|
+
animations = animateSubject(subjectOrSequence, optionsOrKeyframes, options, scope);
|
|
3926
|
+
}
|
|
3927
|
+
const animation = new GroupPlaybackControls(animations);
|
|
3928
|
+
if (scope) {
|
|
3929
|
+
scope.animations.push(animation);
|
|
3930
|
+
}
|
|
3931
|
+
return animation;
|
|
3932
|
+
}
|
|
3933
|
+
return scopedAnimate;
|
|
3934
|
+
}
|
|
3935
|
+
function useAnimate() {
|
|
3936
|
+
const scope = useConstant(() => ({
|
|
3937
|
+
current: null,
|
|
3938
|
+
// Will be hydrated by React
|
|
3939
|
+
animations: []
|
|
3940
|
+
}));
|
|
3941
|
+
const animate = useConstant(() => createScopedAnimate(scope));
|
|
3942
|
+
useUnmountEffect(() => {
|
|
3943
|
+
scope.animations.forEach((animation) => animation.stop());
|
|
3944
|
+
});
|
|
3945
|
+
return [scope, animate];
|
|
3946
|
+
}
|
|
3947
|
+
export {
|
|
3948
|
+
useConstant as a,
|
|
3949
|
+
isBrowser as i,
|
|
3950
|
+
useAnimate as u
|
|
3951
|
+
};
|
|
3952
|
+
//# sourceMappingURL=use-animate.js.map
|