@helsenorge/designsystem-react 12.9.0 → 12.10.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/CHANGELOG.md +20 -0
- package/Drawer.js +4 -204
- package/Drawer.js.map +1 -1
- package/SVGVisualElement.js +3759 -0
- package/SVGVisualElement.js.map +1 -0
- package/Toast.js +24 -0
- package/Toast.js.map +1 -0
- package/components/Drawer/styles.module.scss +19 -18
- package/components/Dropdown/index.js +1 -0
- package/components/Dropdown/index.js.map +1 -1
- package/components/Dropdown/styles.module.scss +1 -0
- package/components/Toast/Toast.d.ts +13 -0
- package/components/Toast/Toast.test.d.ts +1 -0
- package/components/Toast/index.d.ts +3 -0
- package/components/Toast/index.js +5 -0
- package/components/Toast/index.js.map +1 -0
- package/components/Toast/styles.module.scss +50 -0
- package/components/ToastList/ToastList.d.ts +14 -0
- package/components/ToastList/ToastList.test.d.ts +1 -0
- package/components/ToastList/index.d.ts +3 -0
- package/components/ToastList/index.js +3531 -0
- package/components/ToastList/index.js.map +1 -0
- package/components/ToastList/styles.module.scss +12 -0
- package/components/ToastList/styles.module.scss.d.ts +9 -0
- package/index2.js +213 -0
- package/index2.js.map +1 -0
- package/package.json +1 -1
- package/use-animate.js +50 -3614
- package/use-animate.js.map +1 -1
|
@@ -0,0 +1,3531 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React__default, { createContext, useContext, useMemo, useCallback, useRef, useInsertionEffect, useEffect, forwardRef, Fragment, createElement, Component } from "react";
|
|
3
|
+
import { mergeRefs } from "../../utils/refs.js";
|
|
4
|
+
import { T as Toast } from "../../Toast.js";
|
|
5
|
+
import styles from "./styles.module.scss";
|
|
6
|
+
import { P as PresenceContext, M as MotionConfigContext, a as useIsomorphicLayoutEffect, L as LayoutGroupContext, u as usePresence, A as AnimatePresence } from "../../index2.js";
|
|
7
|
+
import { w as featureDefinitions, x as warnOnce, y as isControllingVariants, z as isVariantLabel, A as createRenderBatcher, B as optimizedAppearDataAttribute, i as isBrowser, C as warning, k as invariant, f as isMotionValue, D as isCustomValue, u as useConstant, E as isVariantNode, F as isAnimationControls, I as resolveVariantFromProps, J as scrapeMotionValuesFromProps, K as transformProps, L as frame, M as buildSVGAttrs, N as isSVGTag, O as renderSVG, P as scrapeMotionValuesFromProps$1, Q as isForcedMotionValue, R as buildHTMLStyles, T as resolveVariant, q as animateTarget, U as variantProps, W as isKeyframesTarget, X as variantPriorityOrder, Y as frameData, Z as pipe, _ as cancelFrame, s as secondsToMilliseconds, a as millisecondsToSeconds, d as mixNumber, p as progress, l as createBox, $ as measurePageBox, a0 as convertBoxToBoundingBox, a1 as convertBoundingBoxToBox, a2 as addValueToWillChange, a3 as animateMotionValue, a4 as percent, a5 as noop, a6 as px, a7 as complex, a8 as addScaleCorrector, a9 as addUniqueItem, e as removeItem, aa as time, ab as circOut, ac as scalePoint, ad as SubscriptionManager, n as isSVGElement, ae as getValueTransition, af as frameSteps, ag as hasTransform, ah as translateAxis, ai as transformBox, aj as hasScale, ak as applyBoxDelta, al as has2DTranslate, am as applyTreeDeltas, an as createDelta, o as animateSingleValue, ao as scaleCorrectors, ap as getOptimisedAppearId, r as resolveElements, S as SVGVisualElement, H as HTMLVisualElement } from "../../SVGVisualElement.js";
|
|
8
|
+
import { c as clamp } from "../../clamp.js";
|
|
9
|
+
const LazyContext = createContext({ strict: false });
|
|
10
|
+
function loadFeatures(features) {
|
|
11
|
+
for (const key in features) {
|
|
12
|
+
featureDefinitions[key] = {
|
|
13
|
+
...featureDefinitions[key],
|
|
14
|
+
...features[key]
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const validMotionProps = /* @__PURE__ */ new Set([
|
|
19
|
+
"animate",
|
|
20
|
+
"exit",
|
|
21
|
+
"variants",
|
|
22
|
+
"initial",
|
|
23
|
+
"style",
|
|
24
|
+
"values",
|
|
25
|
+
"variants",
|
|
26
|
+
"transition",
|
|
27
|
+
"transformTemplate",
|
|
28
|
+
"custom",
|
|
29
|
+
"inherit",
|
|
30
|
+
"onBeforeLayoutMeasure",
|
|
31
|
+
"onAnimationStart",
|
|
32
|
+
"onAnimationComplete",
|
|
33
|
+
"onUpdate",
|
|
34
|
+
"onDragStart",
|
|
35
|
+
"onDrag",
|
|
36
|
+
"onDragEnd",
|
|
37
|
+
"onMeasureDragConstraints",
|
|
38
|
+
"onDirectionLock",
|
|
39
|
+
"onDragTransitionEnd",
|
|
40
|
+
"_dragX",
|
|
41
|
+
"_dragY",
|
|
42
|
+
"onHoverStart",
|
|
43
|
+
"onHoverEnd",
|
|
44
|
+
"onViewportEnter",
|
|
45
|
+
"onViewportLeave",
|
|
46
|
+
"globalTapTarget",
|
|
47
|
+
"ignoreStrict",
|
|
48
|
+
"viewport"
|
|
49
|
+
]);
|
|
50
|
+
function isValidMotionProp(key) {
|
|
51
|
+
return key.startsWith("while") || key.startsWith("drag") && key !== "draggable" || key.startsWith("layout") || key.startsWith("onTap") || key.startsWith("onPan") || key.startsWith("onLayout") || validMotionProps.has(key);
|
|
52
|
+
}
|
|
53
|
+
let shouldForward = (key) => !isValidMotionProp(key);
|
|
54
|
+
function loadExternalIsValidProp(isValidProp) {
|
|
55
|
+
if (!isValidProp)
|
|
56
|
+
return;
|
|
57
|
+
shouldForward = (key) => key.startsWith("on") ? !isValidMotionProp(key) : isValidProp(key);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
loadExternalIsValidProp(require("@emotion/is-prop-valid").default);
|
|
61
|
+
} catch (_a) {
|
|
62
|
+
}
|
|
63
|
+
function filterProps(props, isDom, forwardMotionProps) {
|
|
64
|
+
const filteredProps = {};
|
|
65
|
+
for (const key in props) {
|
|
66
|
+
if (key === "values" && typeof props.values === "object")
|
|
67
|
+
continue;
|
|
68
|
+
if (shouldForward(key) || forwardMotionProps === true && isValidMotionProp(key) || !isDom && !isValidMotionProp(key) || // If trying to use native HTML drag events, forward drag listeners
|
|
69
|
+
props["draggable"] && key.startsWith("onDrag")) {
|
|
70
|
+
filteredProps[key] = props[key];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return filteredProps;
|
|
74
|
+
}
|
|
75
|
+
function createDOMMotionComponentProxy(componentFactory) {
|
|
76
|
+
if (typeof Proxy === "undefined") {
|
|
77
|
+
return componentFactory;
|
|
78
|
+
}
|
|
79
|
+
const componentCache = /* @__PURE__ */ new Map();
|
|
80
|
+
const deprecatedFactoryFunction = (...args) => {
|
|
81
|
+
if (process.env.NODE_ENV !== "production") {
|
|
82
|
+
warnOnce(false, "motion() is deprecated. Use motion.create() instead.");
|
|
83
|
+
}
|
|
84
|
+
return componentFactory(...args);
|
|
85
|
+
};
|
|
86
|
+
return new Proxy(deprecatedFactoryFunction, {
|
|
87
|
+
/**
|
|
88
|
+
* Called when `motion` is referenced with a prop: `motion.div`, `motion.input` etc.
|
|
89
|
+
* The prop name is passed through as `key` and we can use that to generate a `motion`
|
|
90
|
+
* DOM component with that name.
|
|
91
|
+
*/
|
|
92
|
+
get: (_target, key) => {
|
|
93
|
+
if (key === "create")
|
|
94
|
+
return componentFactory;
|
|
95
|
+
if (!componentCache.has(key)) {
|
|
96
|
+
componentCache.set(key, componentFactory(key));
|
|
97
|
+
}
|
|
98
|
+
return componentCache.get(key);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const MotionContext = createContext({});
|
|
103
|
+
function getCurrentTreeVariants(props, context) {
|
|
104
|
+
if (isControllingVariants(props)) {
|
|
105
|
+
const { initial, animate } = props;
|
|
106
|
+
return {
|
|
107
|
+
initial: initial === false || isVariantLabel(initial) ? initial : void 0,
|
|
108
|
+
animate: isVariantLabel(animate) ? animate : void 0
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return props.inherit !== false ? context : {};
|
|
112
|
+
}
|
|
113
|
+
function useCreateMotionContext(props) {
|
|
114
|
+
const { initial, animate } = getCurrentTreeVariants(props, useContext(MotionContext));
|
|
115
|
+
return useMemo(() => ({ initial, animate }), [variantLabelsAsDependency(initial), variantLabelsAsDependency(animate)]);
|
|
116
|
+
}
|
|
117
|
+
function variantLabelsAsDependency(prop) {
|
|
118
|
+
return Array.isArray(prop) ? prop.join(" ") : prop;
|
|
119
|
+
}
|
|
120
|
+
const motionComponentSymbol = Symbol.for("motionComponentSymbol");
|
|
121
|
+
function isRefObject(ref) {
|
|
122
|
+
return ref && typeof ref === "object" && Object.prototype.hasOwnProperty.call(ref, "current");
|
|
123
|
+
}
|
|
124
|
+
function useMotionRef(visualState, visualElement, externalRef) {
|
|
125
|
+
return useCallback(
|
|
126
|
+
(instance) => {
|
|
127
|
+
if (instance) {
|
|
128
|
+
visualState.onMount && visualState.onMount(instance);
|
|
129
|
+
}
|
|
130
|
+
if (visualElement) {
|
|
131
|
+
if (instance) {
|
|
132
|
+
visualElement.mount(instance);
|
|
133
|
+
} else {
|
|
134
|
+
visualElement.unmount();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (externalRef) {
|
|
138
|
+
if (typeof externalRef === "function") {
|
|
139
|
+
externalRef(instance);
|
|
140
|
+
} else if (isRefObject(externalRef)) {
|
|
141
|
+
externalRef.current = instance;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
/**
|
|
146
|
+
* Only pass a new ref callback to React if we've received a visual element
|
|
147
|
+
* factory. Otherwise we'll be mounting/remounting every time externalRef
|
|
148
|
+
* or other dependencies change.
|
|
149
|
+
*/
|
|
150
|
+
[visualElement]
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
const { schedule: microtask } = createRenderBatcher(queueMicrotask, false);
|
|
154
|
+
const SwitchLayoutGroupContext = createContext({});
|
|
155
|
+
function useVisualElement(Component2, visualState, props, createVisualElement, ProjectionNodeConstructor) {
|
|
156
|
+
var _a, _b;
|
|
157
|
+
const { visualElement: parent } = useContext(MotionContext);
|
|
158
|
+
const lazyContext = useContext(LazyContext);
|
|
159
|
+
const presenceContext = useContext(PresenceContext);
|
|
160
|
+
const reducedMotionConfig = useContext(MotionConfigContext).reducedMotion;
|
|
161
|
+
const visualElementRef = useRef(null);
|
|
162
|
+
createVisualElement = createVisualElement || lazyContext.renderer;
|
|
163
|
+
if (!visualElementRef.current && createVisualElement) {
|
|
164
|
+
visualElementRef.current = createVisualElement(Component2, {
|
|
165
|
+
visualState,
|
|
166
|
+
parent,
|
|
167
|
+
props,
|
|
168
|
+
presenceContext,
|
|
169
|
+
blockInitialAnimation: presenceContext ? presenceContext.initial === false : false,
|
|
170
|
+
reducedMotionConfig
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
const visualElement = visualElementRef.current;
|
|
174
|
+
const initialLayoutGroupConfig = useContext(SwitchLayoutGroupContext);
|
|
175
|
+
if (visualElement && !visualElement.projection && ProjectionNodeConstructor && (visualElement.type === "html" || visualElement.type === "svg")) {
|
|
176
|
+
createProjectionNode$1(visualElementRef.current, props, ProjectionNodeConstructor, initialLayoutGroupConfig);
|
|
177
|
+
}
|
|
178
|
+
const isMounted = useRef(false);
|
|
179
|
+
useInsertionEffect(() => {
|
|
180
|
+
if (visualElement && isMounted.current) {
|
|
181
|
+
visualElement.update(props, presenceContext);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
const optimisedAppearId = props[optimizedAppearDataAttribute];
|
|
185
|
+
const wantsHandoff = useRef(Boolean(optimisedAppearId) && !((_a = window.MotionHandoffIsComplete) === null || _a === void 0 ? void 0 : _a.call(window, optimisedAppearId)) && ((_b = window.MotionHasOptimisedAnimation) === null || _b === void 0 ? void 0 : _b.call(window, optimisedAppearId)));
|
|
186
|
+
useIsomorphicLayoutEffect(() => {
|
|
187
|
+
if (!visualElement)
|
|
188
|
+
return;
|
|
189
|
+
isMounted.current = true;
|
|
190
|
+
window.MotionIsMounted = true;
|
|
191
|
+
visualElement.updateFeatures();
|
|
192
|
+
microtask.render(visualElement.render);
|
|
193
|
+
if (wantsHandoff.current && visualElement.animationState) {
|
|
194
|
+
visualElement.animationState.animateChanges();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
if (!visualElement)
|
|
199
|
+
return;
|
|
200
|
+
if (!wantsHandoff.current && visualElement.animationState) {
|
|
201
|
+
visualElement.animationState.animateChanges();
|
|
202
|
+
}
|
|
203
|
+
if (wantsHandoff.current) {
|
|
204
|
+
queueMicrotask(() => {
|
|
205
|
+
var _a2;
|
|
206
|
+
(_a2 = window.MotionHandoffMarkAsComplete) === null || _a2 === void 0 ? void 0 : _a2.call(window, optimisedAppearId);
|
|
207
|
+
});
|
|
208
|
+
wantsHandoff.current = false;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
return visualElement;
|
|
212
|
+
}
|
|
213
|
+
function createProjectionNode$1(visualElement, props, ProjectionNodeConstructor, initialPromotionConfig) {
|
|
214
|
+
const { layoutId, layout: layout2, drag: drag2, dragConstraints, layoutScroll, layoutRoot } = props;
|
|
215
|
+
visualElement.projection = new ProjectionNodeConstructor(visualElement.latestValues, props["data-framer-portal-id"] ? void 0 : getClosestProjectingNode(visualElement.parent));
|
|
216
|
+
visualElement.projection.setOptions({
|
|
217
|
+
layoutId,
|
|
218
|
+
layout: layout2,
|
|
219
|
+
alwaysMeasureLayout: Boolean(drag2) || dragConstraints && isRefObject(dragConstraints),
|
|
220
|
+
visualElement,
|
|
221
|
+
/**
|
|
222
|
+
* TODO: Update options in an effect. This could be tricky as it'll be too late
|
|
223
|
+
* to update by the time layout animations run.
|
|
224
|
+
* We also need to fix this safeToRemove by linking it up to the one returned by usePresence,
|
|
225
|
+
* ensuring it gets called if there's no potential layout animations.
|
|
226
|
+
*
|
|
227
|
+
*/
|
|
228
|
+
animationType: typeof layout2 === "string" ? layout2 : "both",
|
|
229
|
+
initialPromotionConfig,
|
|
230
|
+
layoutScroll,
|
|
231
|
+
layoutRoot
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function getClosestProjectingNode(visualElement) {
|
|
235
|
+
if (!visualElement)
|
|
236
|
+
return void 0;
|
|
237
|
+
return visualElement.options.allowProjection !== false ? visualElement.projection : getClosestProjectingNode(visualElement.parent);
|
|
238
|
+
}
|
|
239
|
+
function createRendererMotionComponent({ preloadedFeatures, createVisualElement, useRender, useVisualState, Component: Component2 }) {
|
|
240
|
+
var _a, _b;
|
|
241
|
+
preloadedFeatures && loadFeatures(preloadedFeatures);
|
|
242
|
+
function MotionComponent(props, externalRef) {
|
|
243
|
+
let MeasureLayout2;
|
|
244
|
+
const configAndProps = {
|
|
245
|
+
...useContext(MotionConfigContext),
|
|
246
|
+
...props,
|
|
247
|
+
layoutId: useLayoutId(props)
|
|
248
|
+
};
|
|
249
|
+
const { isStatic } = configAndProps;
|
|
250
|
+
const context = useCreateMotionContext(props);
|
|
251
|
+
const visualState = useVisualState(props, isStatic);
|
|
252
|
+
if (!isStatic && isBrowser) {
|
|
253
|
+
useStrictMode(configAndProps, preloadedFeatures);
|
|
254
|
+
const layoutProjection = getProjectionFunctionality(configAndProps);
|
|
255
|
+
MeasureLayout2 = layoutProjection.MeasureLayout;
|
|
256
|
+
context.visualElement = useVisualElement(Component2, visualState, configAndProps, createVisualElement, layoutProjection.ProjectionNode);
|
|
257
|
+
}
|
|
258
|
+
return jsxs(MotionContext.Provider, { value: context, children: [MeasureLayout2 && context.visualElement ? jsx(MeasureLayout2, { visualElement: context.visualElement, ...configAndProps }) : null, useRender(Component2, props, useMotionRef(visualState, context.visualElement, externalRef), visualState, isStatic, context.visualElement)] });
|
|
259
|
+
}
|
|
260
|
+
MotionComponent.displayName = `motion.${typeof Component2 === "string" ? Component2 : `create(${(_b = (_a = Component2.displayName) !== null && _a !== void 0 ? _a : Component2.name) !== null && _b !== void 0 ? _b : ""})`}`;
|
|
261
|
+
const ForwardRefMotionComponent = forwardRef(MotionComponent);
|
|
262
|
+
ForwardRefMotionComponent[motionComponentSymbol] = Component2;
|
|
263
|
+
return ForwardRefMotionComponent;
|
|
264
|
+
}
|
|
265
|
+
function useLayoutId({ layoutId }) {
|
|
266
|
+
const layoutGroupId = useContext(LayoutGroupContext).id;
|
|
267
|
+
return layoutGroupId && layoutId !== void 0 ? layoutGroupId + "-" + layoutId : layoutId;
|
|
268
|
+
}
|
|
269
|
+
function useStrictMode(configAndProps, preloadedFeatures) {
|
|
270
|
+
const isStrict = useContext(LazyContext).strict;
|
|
271
|
+
if (process.env.NODE_ENV !== "production" && preloadedFeatures && isStrict) {
|
|
272
|
+
const strictMessage = "You have rendered a `motion` component within a `LazyMotion` component. This will break tree shaking. Import and render a `m` component instead.";
|
|
273
|
+
configAndProps.ignoreStrict ? warning(false, strictMessage) : invariant(false, strictMessage);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function getProjectionFunctionality(props) {
|
|
277
|
+
const { drag: drag2, layout: layout2 } = featureDefinitions;
|
|
278
|
+
if (!drag2 && !layout2)
|
|
279
|
+
return {};
|
|
280
|
+
const combined = { ...drag2, ...layout2 };
|
|
281
|
+
return {
|
|
282
|
+
MeasureLayout: (drag2 === null || drag2 === void 0 ? void 0 : drag2.isEnabled(props)) || (layout2 === null || layout2 === void 0 ? void 0 : layout2.isEnabled(props)) ? combined.MeasureLayout : void 0,
|
|
283
|
+
ProjectionNode: combined.ProjectionNode
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
const lowercaseSVGElements = [
|
|
287
|
+
"animate",
|
|
288
|
+
"circle",
|
|
289
|
+
"defs",
|
|
290
|
+
"desc",
|
|
291
|
+
"ellipse",
|
|
292
|
+
"g",
|
|
293
|
+
"image",
|
|
294
|
+
"line",
|
|
295
|
+
"filter",
|
|
296
|
+
"marker",
|
|
297
|
+
"mask",
|
|
298
|
+
"metadata",
|
|
299
|
+
"path",
|
|
300
|
+
"pattern",
|
|
301
|
+
"polygon",
|
|
302
|
+
"polyline",
|
|
303
|
+
"rect",
|
|
304
|
+
"stop",
|
|
305
|
+
"switch",
|
|
306
|
+
"symbol",
|
|
307
|
+
"svg",
|
|
308
|
+
"text",
|
|
309
|
+
"tspan",
|
|
310
|
+
"use",
|
|
311
|
+
"view"
|
|
312
|
+
];
|
|
313
|
+
function isSVGComponent(Component2) {
|
|
314
|
+
if (
|
|
315
|
+
/**
|
|
316
|
+
* If it's not a string, it's a custom React component. Currently we only support
|
|
317
|
+
* HTML custom React components.
|
|
318
|
+
*/
|
|
319
|
+
typeof Component2 !== "string" || /**
|
|
320
|
+
* If it contains a dash, the element is a custom HTML webcomponent.
|
|
321
|
+
*/
|
|
322
|
+
Component2.includes("-")
|
|
323
|
+
) {
|
|
324
|
+
return false;
|
|
325
|
+
} else if (
|
|
326
|
+
/**
|
|
327
|
+
* If it's in our list of lowercase SVG tags, it's an SVG component
|
|
328
|
+
*/
|
|
329
|
+
lowercaseSVGElements.indexOf(Component2) > -1 || /**
|
|
330
|
+
* If it contains a capital letter, it's an SVG component
|
|
331
|
+
*/
|
|
332
|
+
/[A-Z]/u.test(Component2)
|
|
333
|
+
) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
function resolveMotionValue(value) {
|
|
339
|
+
const unwrappedValue = isMotionValue(value) ? value.get() : value;
|
|
340
|
+
return isCustomValue(unwrappedValue) ? unwrappedValue.toValue() : unwrappedValue;
|
|
341
|
+
}
|
|
342
|
+
function makeState({ scrapeMotionValuesFromProps: scrapeMotionValuesFromProps2, createRenderState, onUpdate }, props, context, presenceContext) {
|
|
343
|
+
const state = {
|
|
344
|
+
latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps2),
|
|
345
|
+
renderState: createRenderState()
|
|
346
|
+
};
|
|
347
|
+
if (onUpdate) {
|
|
348
|
+
state.onMount = (instance) => onUpdate({ props, current: instance, ...state });
|
|
349
|
+
state.onUpdate = (visualElement) => onUpdate(visualElement);
|
|
350
|
+
}
|
|
351
|
+
return state;
|
|
352
|
+
}
|
|
353
|
+
const makeUseVisualState = (config) => (props, isStatic) => {
|
|
354
|
+
const context = useContext(MotionContext);
|
|
355
|
+
const presenceContext = useContext(PresenceContext);
|
|
356
|
+
const make = () => makeState(config, props, context, presenceContext);
|
|
357
|
+
return isStatic ? make() : useConstant(make);
|
|
358
|
+
};
|
|
359
|
+
function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
|
|
360
|
+
const values = {};
|
|
361
|
+
const motionValues = scrapeMotionValues(props, {});
|
|
362
|
+
for (const key in motionValues) {
|
|
363
|
+
values[key] = resolveMotionValue(motionValues[key]);
|
|
364
|
+
}
|
|
365
|
+
let { initial, animate } = props;
|
|
366
|
+
const isControllingVariants$1 = isControllingVariants(props);
|
|
367
|
+
const isVariantNode$1 = isVariantNode(props);
|
|
368
|
+
if (context && isVariantNode$1 && !isControllingVariants$1 && props.inherit !== false) {
|
|
369
|
+
if (initial === void 0)
|
|
370
|
+
initial = context.initial;
|
|
371
|
+
if (animate === void 0)
|
|
372
|
+
animate = context.animate;
|
|
373
|
+
}
|
|
374
|
+
let isInitialAnimationBlocked = presenceContext ? presenceContext.initial === false : false;
|
|
375
|
+
isInitialAnimationBlocked = isInitialAnimationBlocked || initial === false;
|
|
376
|
+
const variantToSet = isInitialAnimationBlocked ? animate : initial;
|
|
377
|
+
if (variantToSet && typeof variantToSet !== "boolean" && !isAnimationControls(variantToSet)) {
|
|
378
|
+
const list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
|
|
379
|
+
for (let i = 0; i < list.length; i++) {
|
|
380
|
+
const resolved = resolveVariantFromProps(props, list[i]);
|
|
381
|
+
if (resolved) {
|
|
382
|
+
const { transitionEnd, transition, ...target } = resolved;
|
|
383
|
+
for (const key in target) {
|
|
384
|
+
let valueTarget = target[key];
|
|
385
|
+
if (Array.isArray(valueTarget)) {
|
|
386
|
+
const index = isInitialAnimationBlocked ? valueTarget.length - 1 : 0;
|
|
387
|
+
valueTarget = valueTarget[index];
|
|
388
|
+
}
|
|
389
|
+
if (valueTarget !== null) {
|
|
390
|
+
values[key] = valueTarget;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
for (const key in transitionEnd) {
|
|
394
|
+
values[key] = transitionEnd[key];
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return values;
|
|
400
|
+
}
|
|
401
|
+
const createHtmlRenderState = () => ({
|
|
402
|
+
style: {},
|
|
403
|
+
transform: {},
|
|
404
|
+
transformOrigin: {},
|
|
405
|
+
vars: {}
|
|
406
|
+
});
|
|
407
|
+
const createSvgRenderState = () => ({
|
|
408
|
+
...createHtmlRenderState(),
|
|
409
|
+
attrs: {}
|
|
410
|
+
});
|
|
411
|
+
function updateSVGDimensions(instance, renderState) {
|
|
412
|
+
try {
|
|
413
|
+
renderState.dimensions = typeof instance.getBBox === "function" ? instance.getBBox() : instance.getBoundingClientRect();
|
|
414
|
+
} catch (e) {
|
|
415
|
+
renderState.dimensions = {
|
|
416
|
+
x: 0,
|
|
417
|
+
y: 0,
|
|
418
|
+
width: 0,
|
|
419
|
+
height: 0
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const layoutProps = ["x", "y", "width", "height", "cx", "cy", "r"];
|
|
424
|
+
const svgMotionConfig = {
|
|
425
|
+
useVisualState: makeUseVisualState({
|
|
426
|
+
scrapeMotionValuesFromProps,
|
|
427
|
+
createRenderState: createSvgRenderState,
|
|
428
|
+
onUpdate: ({ props, prevProps, current, renderState, latestValues }) => {
|
|
429
|
+
if (!current)
|
|
430
|
+
return;
|
|
431
|
+
let hasTransform2 = !!props.drag;
|
|
432
|
+
if (!hasTransform2) {
|
|
433
|
+
for (const key in latestValues) {
|
|
434
|
+
if (transformProps.has(key)) {
|
|
435
|
+
hasTransform2 = true;
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (!hasTransform2)
|
|
441
|
+
return;
|
|
442
|
+
let needsMeasure = !prevProps;
|
|
443
|
+
if (prevProps) {
|
|
444
|
+
for (let i = 0; i < layoutProps.length; i++) {
|
|
445
|
+
const key = layoutProps[i];
|
|
446
|
+
if (props[key] !== prevProps[key]) {
|
|
447
|
+
needsMeasure = true;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (!needsMeasure)
|
|
452
|
+
return;
|
|
453
|
+
frame.read(() => {
|
|
454
|
+
updateSVGDimensions(current, renderState);
|
|
455
|
+
frame.render(() => {
|
|
456
|
+
buildSVGAttrs(renderState, latestValues, isSVGTag(current.tagName), props.transformTemplate);
|
|
457
|
+
renderSVG(current, renderState);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
})
|
|
462
|
+
};
|
|
463
|
+
const htmlMotionConfig = {
|
|
464
|
+
useVisualState: makeUseVisualState({
|
|
465
|
+
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
466
|
+
createRenderState: createHtmlRenderState
|
|
467
|
+
})
|
|
468
|
+
};
|
|
469
|
+
function copyRawValuesOnly(target, source, props) {
|
|
470
|
+
for (const key in source) {
|
|
471
|
+
if (!isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
|
|
472
|
+
target[key] = source[key];
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function useInitialMotionValues({ transformTemplate }, visualState) {
|
|
477
|
+
return useMemo(() => {
|
|
478
|
+
const state = createHtmlRenderState();
|
|
479
|
+
buildHTMLStyles(state, visualState, transformTemplate);
|
|
480
|
+
return Object.assign({}, state.vars, state.style);
|
|
481
|
+
}, [visualState]);
|
|
482
|
+
}
|
|
483
|
+
function useStyle(props, visualState) {
|
|
484
|
+
const styleProp = props.style || {};
|
|
485
|
+
const style = {};
|
|
486
|
+
copyRawValuesOnly(style, styleProp, props);
|
|
487
|
+
Object.assign(style, useInitialMotionValues(props, visualState));
|
|
488
|
+
return style;
|
|
489
|
+
}
|
|
490
|
+
function useHTMLProps(props, visualState) {
|
|
491
|
+
const htmlProps = {};
|
|
492
|
+
const style = useStyle(props, visualState);
|
|
493
|
+
if (props.drag && props.dragListener !== false) {
|
|
494
|
+
htmlProps.draggable = false;
|
|
495
|
+
style.userSelect = style.WebkitUserSelect = style.WebkitTouchCallout = "none";
|
|
496
|
+
style.touchAction = props.drag === true ? "none" : `pan-${props.drag === "x" ? "y" : "x"}`;
|
|
497
|
+
}
|
|
498
|
+
if (props.tabIndex === void 0 && (props.onTap || props.onTapStart || props.whileTap)) {
|
|
499
|
+
htmlProps.tabIndex = 0;
|
|
500
|
+
}
|
|
501
|
+
htmlProps.style = style;
|
|
502
|
+
return htmlProps;
|
|
503
|
+
}
|
|
504
|
+
function useSVGProps(props, visualState, _isStatic, Component2) {
|
|
505
|
+
const visualProps = useMemo(() => {
|
|
506
|
+
const state = createSvgRenderState();
|
|
507
|
+
buildSVGAttrs(state, visualState, isSVGTag(Component2), props.transformTemplate);
|
|
508
|
+
return {
|
|
509
|
+
...state.attrs,
|
|
510
|
+
style: { ...state.style }
|
|
511
|
+
};
|
|
512
|
+
}, [visualState]);
|
|
513
|
+
if (props.style) {
|
|
514
|
+
const rawStyles = {};
|
|
515
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
516
|
+
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
517
|
+
}
|
|
518
|
+
return visualProps;
|
|
519
|
+
}
|
|
520
|
+
function createUseRender(forwardMotionProps = false) {
|
|
521
|
+
const useRender = (Component2, props, ref, { latestValues }, isStatic) => {
|
|
522
|
+
const useVisualProps = isSVGComponent(Component2) ? useSVGProps : useHTMLProps;
|
|
523
|
+
const visualProps = useVisualProps(props, latestValues, isStatic, Component2);
|
|
524
|
+
const filteredProps = filterProps(props, typeof Component2 === "string", forwardMotionProps);
|
|
525
|
+
const elementProps = Component2 !== Fragment ? { ...filteredProps, ...visualProps, ref } : {};
|
|
526
|
+
const { children } = props;
|
|
527
|
+
const renderedChildren = useMemo(() => isMotionValue(children) ? children.get() : children, [children]);
|
|
528
|
+
return createElement(Component2, {
|
|
529
|
+
...elementProps,
|
|
530
|
+
children: renderedChildren
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
return useRender;
|
|
534
|
+
}
|
|
535
|
+
function createMotionComponentFactory(preloadedFeatures, createVisualElement) {
|
|
536
|
+
return function createMotionComponent2(Component2, { forwardMotionProps } = { forwardMotionProps: false }) {
|
|
537
|
+
const baseConfig = isSVGComponent(Component2) ? svgMotionConfig : htmlMotionConfig;
|
|
538
|
+
const config = {
|
|
539
|
+
...baseConfig,
|
|
540
|
+
preloadedFeatures,
|
|
541
|
+
useRender: createUseRender(forwardMotionProps),
|
|
542
|
+
createVisualElement,
|
|
543
|
+
Component: Component2
|
|
544
|
+
};
|
|
545
|
+
return createRendererMotionComponent(config);
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function shallowCompare(next, prev) {
|
|
549
|
+
if (!Array.isArray(prev))
|
|
550
|
+
return false;
|
|
551
|
+
const prevLength = prev.length;
|
|
552
|
+
if (prevLength !== next.length)
|
|
553
|
+
return false;
|
|
554
|
+
for (let i = 0; i < prevLength; i++) {
|
|
555
|
+
if (prev[i] !== next[i])
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
function animateVariant(visualElement, variant, options = {}) {
|
|
561
|
+
var _a;
|
|
562
|
+
const resolved = resolveVariant(visualElement, variant, options.type === "exit" ? (_a = visualElement.presenceContext) === null || _a === void 0 ? void 0 : _a.custom : void 0);
|
|
563
|
+
let { transition = visualElement.getDefaultTransition() || {} } = resolved || {};
|
|
564
|
+
if (options.transitionOverride) {
|
|
565
|
+
transition = options.transitionOverride;
|
|
566
|
+
}
|
|
567
|
+
const getAnimation = resolved ? () => Promise.all(animateTarget(visualElement, resolved, options)) : () => Promise.resolve();
|
|
568
|
+
const getChildAnimations = visualElement.variantChildren && visualElement.variantChildren.size ? (forwardDelay = 0) => {
|
|
569
|
+
const { delayChildren = 0, staggerChildren, staggerDirection } = transition;
|
|
570
|
+
return animateChildren(visualElement, variant, delayChildren + forwardDelay, staggerChildren, staggerDirection, options);
|
|
571
|
+
} : () => Promise.resolve();
|
|
572
|
+
const { when } = transition;
|
|
573
|
+
if (when) {
|
|
574
|
+
const [first, last] = when === "beforeChildren" ? [getAnimation, getChildAnimations] : [getChildAnimations, getAnimation];
|
|
575
|
+
return first().then(() => last());
|
|
576
|
+
} else {
|
|
577
|
+
return Promise.all([getAnimation(), getChildAnimations(options.delay)]);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
function animateChildren(visualElement, variant, delayChildren = 0, staggerChildren = 0, staggerDirection = 1, options) {
|
|
581
|
+
const animations2 = [];
|
|
582
|
+
const maxStaggerDuration = (visualElement.variantChildren.size - 1) * staggerChildren;
|
|
583
|
+
const generateStaggerDuration = staggerDirection === 1 ? (i = 0) => i * staggerChildren : (i = 0) => maxStaggerDuration - i * staggerChildren;
|
|
584
|
+
Array.from(visualElement.variantChildren).sort(sortByTreeOrder).forEach((child, i) => {
|
|
585
|
+
child.notify("AnimationStart", variant);
|
|
586
|
+
animations2.push(animateVariant(child, variant, {
|
|
587
|
+
...options,
|
|
588
|
+
delay: delayChildren + generateStaggerDuration(i)
|
|
589
|
+
}).then(() => child.notify("AnimationComplete", variant)));
|
|
590
|
+
});
|
|
591
|
+
return Promise.all(animations2);
|
|
592
|
+
}
|
|
593
|
+
function sortByTreeOrder(a, b) {
|
|
594
|
+
return a.sortNodePosition(b);
|
|
595
|
+
}
|
|
596
|
+
function animateVisualElement(visualElement, definition, options = {}) {
|
|
597
|
+
visualElement.notify("AnimationStart", definition);
|
|
598
|
+
let animation;
|
|
599
|
+
if (Array.isArray(definition)) {
|
|
600
|
+
const animations2 = definition.map((variant) => animateVariant(visualElement, variant, options));
|
|
601
|
+
animation = Promise.all(animations2);
|
|
602
|
+
} else if (typeof definition === "string") {
|
|
603
|
+
animation = animateVariant(visualElement, definition, options);
|
|
604
|
+
} else {
|
|
605
|
+
const resolvedDefinition = typeof definition === "function" ? resolveVariant(visualElement, definition, options.custom) : definition;
|
|
606
|
+
animation = Promise.all(animateTarget(visualElement, resolvedDefinition, options));
|
|
607
|
+
}
|
|
608
|
+
return animation.then(() => {
|
|
609
|
+
visualElement.notify("AnimationComplete", definition);
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
const numVariantProps = variantProps.length;
|
|
613
|
+
function getVariantContext(visualElement) {
|
|
614
|
+
if (!visualElement)
|
|
615
|
+
return void 0;
|
|
616
|
+
if (!visualElement.isControllingVariants) {
|
|
617
|
+
const context2 = visualElement.parent ? getVariantContext(visualElement.parent) || {} : {};
|
|
618
|
+
if (visualElement.props.initial !== void 0) {
|
|
619
|
+
context2.initial = visualElement.props.initial;
|
|
620
|
+
}
|
|
621
|
+
return context2;
|
|
622
|
+
}
|
|
623
|
+
const context = {};
|
|
624
|
+
for (let i = 0; i < numVariantProps; i++) {
|
|
625
|
+
const name = variantProps[i];
|
|
626
|
+
const prop = visualElement.props[name];
|
|
627
|
+
if (isVariantLabel(prop) || prop === false) {
|
|
628
|
+
context[name] = prop;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return context;
|
|
632
|
+
}
|
|
633
|
+
const reversePriorityOrder = [...variantPriorityOrder].reverse();
|
|
634
|
+
const numAnimationTypes = variantPriorityOrder.length;
|
|
635
|
+
function animateList(visualElement) {
|
|
636
|
+
return (animations2) => Promise.all(animations2.map(({ animation, options }) => animateVisualElement(visualElement, animation, options)));
|
|
637
|
+
}
|
|
638
|
+
function createAnimationState(visualElement) {
|
|
639
|
+
let animate = animateList(visualElement);
|
|
640
|
+
let state = createState();
|
|
641
|
+
let isInitialRender = true;
|
|
642
|
+
const buildResolvedTypeValues = (type) => (acc, definition) => {
|
|
643
|
+
var _a;
|
|
644
|
+
const resolved = resolveVariant(visualElement, definition, type === "exit" ? (_a = visualElement.presenceContext) === null || _a === void 0 ? void 0 : _a.custom : void 0);
|
|
645
|
+
if (resolved) {
|
|
646
|
+
const { transition, transitionEnd, ...target } = resolved;
|
|
647
|
+
acc = { ...acc, ...target, ...transitionEnd };
|
|
648
|
+
}
|
|
649
|
+
return acc;
|
|
650
|
+
};
|
|
651
|
+
function setAnimateFunction(makeAnimator) {
|
|
652
|
+
animate = makeAnimator(visualElement);
|
|
653
|
+
}
|
|
654
|
+
function animateChanges(changedActiveType) {
|
|
655
|
+
const { props } = visualElement;
|
|
656
|
+
const context = getVariantContext(visualElement.parent) || {};
|
|
657
|
+
const animations2 = [];
|
|
658
|
+
const removedKeys = /* @__PURE__ */ new Set();
|
|
659
|
+
let encounteredKeys = {};
|
|
660
|
+
let removedVariantIndex = Infinity;
|
|
661
|
+
for (let i = 0; i < numAnimationTypes; i++) {
|
|
662
|
+
const type = reversePriorityOrder[i];
|
|
663
|
+
const typeState = state[type];
|
|
664
|
+
const prop = props[type] !== void 0 ? props[type] : context[type];
|
|
665
|
+
const propIsVariant = isVariantLabel(prop);
|
|
666
|
+
const activeDelta = type === changedActiveType ? typeState.isActive : null;
|
|
667
|
+
if (activeDelta === false)
|
|
668
|
+
removedVariantIndex = i;
|
|
669
|
+
let isInherited = prop === context[type] && prop !== props[type] && propIsVariant;
|
|
670
|
+
if (isInherited && isInitialRender && visualElement.manuallyAnimateOnMount) {
|
|
671
|
+
isInherited = false;
|
|
672
|
+
}
|
|
673
|
+
typeState.protectedKeys = { ...encounteredKeys };
|
|
674
|
+
if (
|
|
675
|
+
// If it isn't active and hasn't *just* been set as inactive
|
|
676
|
+
!typeState.isActive && activeDelta === null || // If we didn't and don't have any defined prop for this animation type
|
|
677
|
+
!prop && !typeState.prevProp || // Or if the prop doesn't define an animation
|
|
678
|
+
isAnimationControls(prop) || typeof prop === "boolean"
|
|
679
|
+
) {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
const variantDidChange = checkVariantsDidChange(typeState.prevProp, prop);
|
|
683
|
+
let shouldAnimateType = variantDidChange || // If we're making this variant active, we want to always make it active
|
|
684
|
+
type === changedActiveType && typeState.isActive && !isInherited && propIsVariant || // If we removed a higher-priority variant (i is in reverse order)
|
|
685
|
+
i > removedVariantIndex && propIsVariant;
|
|
686
|
+
let handledRemovedValues = false;
|
|
687
|
+
const definitionList = Array.isArray(prop) ? prop : [prop];
|
|
688
|
+
let resolvedValues = definitionList.reduce(buildResolvedTypeValues(type), {});
|
|
689
|
+
if (activeDelta === false)
|
|
690
|
+
resolvedValues = {};
|
|
691
|
+
const { prevResolvedValues = {} } = typeState;
|
|
692
|
+
const allKeys = {
|
|
693
|
+
...prevResolvedValues,
|
|
694
|
+
...resolvedValues
|
|
695
|
+
};
|
|
696
|
+
const markToAnimate = (key) => {
|
|
697
|
+
shouldAnimateType = true;
|
|
698
|
+
if (removedKeys.has(key)) {
|
|
699
|
+
handledRemovedValues = true;
|
|
700
|
+
removedKeys.delete(key);
|
|
701
|
+
}
|
|
702
|
+
typeState.needsAnimating[key] = true;
|
|
703
|
+
const motionValue = visualElement.getValue(key);
|
|
704
|
+
if (motionValue)
|
|
705
|
+
motionValue.liveStyle = false;
|
|
706
|
+
};
|
|
707
|
+
for (const key in allKeys) {
|
|
708
|
+
const next = resolvedValues[key];
|
|
709
|
+
const prev = prevResolvedValues[key];
|
|
710
|
+
if (encounteredKeys.hasOwnProperty(key))
|
|
711
|
+
continue;
|
|
712
|
+
let valueHasChanged = false;
|
|
713
|
+
if (isKeyframesTarget(next) && isKeyframesTarget(prev)) {
|
|
714
|
+
valueHasChanged = !shallowCompare(next, prev);
|
|
715
|
+
} else {
|
|
716
|
+
valueHasChanged = next !== prev;
|
|
717
|
+
}
|
|
718
|
+
if (valueHasChanged) {
|
|
719
|
+
if (next !== void 0 && next !== null) {
|
|
720
|
+
markToAnimate(key);
|
|
721
|
+
} else {
|
|
722
|
+
removedKeys.add(key);
|
|
723
|
+
}
|
|
724
|
+
} else if (next !== void 0 && removedKeys.has(key)) {
|
|
725
|
+
markToAnimate(key);
|
|
726
|
+
} else {
|
|
727
|
+
typeState.protectedKeys[key] = true;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
typeState.prevProp = prop;
|
|
731
|
+
typeState.prevResolvedValues = resolvedValues;
|
|
732
|
+
if (typeState.isActive) {
|
|
733
|
+
encounteredKeys = { ...encounteredKeys, ...resolvedValues };
|
|
734
|
+
}
|
|
735
|
+
if (isInitialRender && visualElement.blockInitialAnimation) {
|
|
736
|
+
shouldAnimateType = false;
|
|
737
|
+
}
|
|
738
|
+
const willAnimateViaParent = isInherited && variantDidChange;
|
|
739
|
+
const needsAnimating = !willAnimateViaParent || handledRemovedValues;
|
|
740
|
+
if (shouldAnimateType && needsAnimating) {
|
|
741
|
+
animations2.push(...definitionList.map((animation) => ({
|
|
742
|
+
animation,
|
|
743
|
+
options: { type }
|
|
744
|
+
})));
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
if (removedKeys.size) {
|
|
748
|
+
const fallbackAnimation = {};
|
|
749
|
+
removedKeys.forEach((key) => {
|
|
750
|
+
const fallbackTarget = visualElement.getBaseTarget(key);
|
|
751
|
+
const motionValue = visualElement.getValue(key);
|
|
752
|
+
if (motionValue)
|
|
753
|
+
motionValue.liveStyle = true;
|
|
754
|
+
fallbackAnimation[key] = fallbackTarget !== null && fallbackTarget !== void 0 ? fallbackTarget : null;
|
|
755
|
+
});
|
|
756
|
+
animations2.push({ animation: fallbackAnimation });
|
|
757
|
+
}
|
|
758
|
+
let shouldAnimate = Boolean(animations2.length);
|
|
759
|
+
if (isInitialRender && (props.initial === false || props.initial === props.animate) && !visualElement.manuallyAnimateOnMount) {
|
|
760
|
+
shouldAnimate = false;
|
|
761
|
+
}
|
|
762
|
+
isInitialRender = false;
|
|
763
|
+
return shouldAnimate ? animate(animations2) : Promise.resolve();
|
|
764
|
+
}
|
|
765
|
+
function setActive(type, isActive) {
|
|
766
|
+
var _a;
|
|
767
|
+
if (state[type].isActive === isActive)
|
|
768
|
+
return Promise.resolve();
|
|
769
|
+
(_a = visualElement.variantChildren) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
|
|
770
|
+
var _a2;
|
|
771
|
+
return (_a2 = child.animationState) === null || _a2 === void 0 ? void 0 : _a2.setActive(type, isActive);
|
|
772
|
+
});
|
|
773
|
+
state[type].isActive = isActive;
|
|
774
|
+
const animations2 = animateChanges(type);
|
|
775
|
+
for (const key in state) {
|
|
776
|
+
state[key].protectedKeys = {};
|
|
777
|
+
}
|
|
778
|
+
return animations2;
|
|
779
|
+
}
|
|
780
|
+
return {
|
|
781
|
+
animateChanges,
|
|
782
|
+
setActive,
|
|
783
|
+
setAnimateFunction,
|
|
784
|
+
getState: () => state,
|
|
785
|
+
reset: () => {
|
|
786
|
+
state = createState();
|
|
787
|
+
isInitialRender = true;
|
|
788
|
+
}
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
function checkVariantsDidChange(prev, next) {
|
|
792
|
+
if (typeof next === "string") {
|
|
793
|
+
return next !== prev;
|
|
794
|
+
} else if (Array.isArray(next)) {
|
|
795
|
+
return !shallowCompare(next, prev);
|
|
796
|
+
}
|
|
797
|
+
return false;
|
|
798
|
+
}
|
|
799
|
+
function createTypeState(isActive = false) {
|
|
800
|
+
return {
|
|
801
|
+
isActive,
|
|
802
|
+
protectedKeys: {},
|
|
803
|
+
needsAnimating: {},
|
|
804
|
+
prevResolvedValues: {}
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
function createState() {
|
|
808
|
+
return {
|
|
809
|
+
animate: createTypeState(true),
|
|
810
|
+
whileInView: createTypeState(),
|
|
811
|
+
whileHover: createTypeState(),
|
|
812
|
+
whileTap: createTypeState(),
|
|
813
|
+
whileDrag: createTypeState(),
|
|
814
|
+
whileFocus: createTypeState(),
|
|
815
|
+
exit: createTypeState()
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
class Feature {
|
|
819
|
+
constructor(node) {
|
|
820
|
+
this.isMounted = false;
|
|
821
|
+
this.node = node;
|
|
822
|
+
}
|
|
823
|
+
update() {
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
class AnimationFeature extends Feature {
|
|
827
|
+
/**
|
|
828
|
+
* We dynamically generate the AnimationState manager as it contains a reference
|
|
829
|
+
* to the underlying animation library. We only want to load that if we load this,
|
|
830
|
+
* so people can optionally code split it out using the `m` component.
|
|
831
|
+
*/
|
|
832
|
+
constructor(node) {
|
|
833
|
+
super(node);
|
|
834
|
+
node.animationState || (node.animationState = createAnimationState(node));
|
|
835
|
+
}
|
|
836
|
+
updateAnimationControlsSubscription() {
|
|
837
|
+
const { animate } = this.node.getProps();
|
|
838
|
+
if (isAnimationControls(animate)) {
|
|
839
|
+
this.unmountControls = animate.subscribe(this.node);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Subscribe any provided AnimationControls to the component's VisualElement
|
|
844
|
+
*/
|
|
845
|
+
mount() {
|
|
846
|
+
this.updateAnimationControlsSubscription();
|
|
847
|
+
}
|
|
848
|
+
update() {
|
|
849
|
+
const { animate } = this.node.getProps();
|
|
850
|
+
const { animate: prevAnimate } = this.node.prevProps || {};
|
|
851
|
+
if (animate !== prevAnimate) {
|
|
852
|
+
this.updateAnimationControlsSubscription();
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
unmount() {
|
|
856
|
+
var _a;
|
|
857
|
+
this.node.animationState.reset();
|
|
858
|
+
(_a = this.unmountControls) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
let id$1 = 0;
|
|
862
|
+
class ExitAnimationFeature extends Feature {
|
|
863
|
+
constructor() {
|
|
864
|
+
super(...arguments);
|
|
865
|
+
this.id = id$1++;
|
|
866
|
+
}
|
|
867
|
+
update() {
|
|
868
|
+
if (!this.node.presenceContext)
|
|
869
|
+
return;
|
|
870
|
+
const { isPresent, onExitComplete } = this.node.presenceContext;
|
|
871
|
+
const { isPresent: prevIsPresent } = this.node.prevPresenceContext || {};
|
|
872
|
+
if (!this.node.animationState || isPresent === prevIsPresent) {
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
const exitAnimation = this.node.animationState.setActive("exit", !isPresent);
|
|
876
|
+
if (onExitComplete && !isPresent) {
|
|
877
|
+
exitAnimation.then(() => onExitComplete(this.id));
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
mount() {
|
|
881
|
+
const { register } = this.node.presenceContext || {};
|
|
882
|
+
if (register) {
|
|
883
|
+
this.unmount = register(this.id);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
unmount() {
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
const animations = {
|
|
890
|
+
animation: {
|
|
891
|
+
Feature: AnimationFeature
|
|
892
|
+
},
|
|
893
|
+
exit: {
|
|
894
|
+
Feature: ExitAnimationFeature
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
const isDragging = {
|
|
898
|
+
x: false,
|
|
899
|
+
y: false
|
|
900
|
+
};
|
|
901
|
+
function isDragActive() {
|
|
902
|
+
return isDragging.x || isDragging.y;
|
|
903
|
+
}
|
|
904
|
+
function setDragLock(axis) {
|
|
905
|
+
if (axis === "x" || axis === "y") {
|
|
906
|
+
if (isDragging[axis]) {
|
|
907
|
+
return null;
|
|
908
|
+
} else {
|
|
909
|
+
isDragging[axis] = true;
|
|
910
|
+
return () => {
|
|
911
|
+
isDragging[axis] = false;
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
} else {
|
|
915
|
+
if (isDragging.x || isDragging.y) {
|
|
916
|
+
return null;
|
|
917
|
+
} else {
|
|
918
|
+
isDragging.x = isDragging.y = true;
|
|
919
|
+
return () => {
|
|
920
|
+
isDragging.x = isDragging.y = false;
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
const isPrimaryPointer = (event) => {
|
|
926
|
+
if (event.pointerType === "mouse") {
|
|
927
|
+
return typeof event.button !== "number" || event.button <= 0;
|
|
928
|
+
} else {
|
|
929
|
+
return event.isPrimary !== false;
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
function addDomEvent(target, eventName, handler, options = { passive: true }) {
|
|
933
|
+
target.addEventListener(eventName, handler, options);
|
|
934
|
+
return () => target.removeEventListener(eventName, handler);
|
|
935
|
+
}
|
|
936
|
+
function extractEventInfo(event) {
|
|
937
|
+
return {
|
|
938
|
+
point: {
|
|
939
|
+
x: event.pageX,
|
|
940
|
+
y: event.pageY
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
const addPointerInfo = (handler) => {
|
|
945
|
+
return (event) => isPrimaryPointer(event) && handler(event, extractEventInfo(event));
|
|
946
|
+
};
|
|
947
|
+
function addPointerEvent(target, eventName, handler, options) {
|
|
948
|
+
return addDomEvent(target, eventName, addPointerInfo(handler), options);
|
|
949
|
+
}
|
|
950
|
+
const distance = (a, b) => Math.abs(a - b);
|
|
951
|
+
function distance2D(a, b) {
|
|
952
|
+
const xDelta = distance(a.x, b.x);
|
|
953
|
+
const yDelta = distance(a.y, b.y);
|
|
954
|
+
return Math.sqrt(xDelta ** 2 + yDelta ** 2);
|
|
955
|
+
}
|
|
956
|
+
class PanSession {
|
|
957
|
+
constructor(event, handlers, { transformPagePoint, contextWindow, dragSnapToOrigin = false } = {}) {
|
|
958
|
+
this.startEvent = null;
|
|
959
|
+
this.lastMoveEvent = null;
|
|
960
|
+
this.lastMoveEventInfo = null;
|
|
961
|
+
this.handlers = {};
|
|
962
|
+
this.contextWindow = window;
|
|
963
|
+
this.updatePoint = () => {
|
|
964
|
+
if (!(this.lastMoveEvent && this.lastMoveEventInfo))
|
|
965
|
+
return;
|
|
966
|
+
const info2 = getPanInfo(this.lastMoveEventInfo, this.history);
|
|
967
|
+
const isPanStarted = this.startEvent !== null;
|
|
968
|
+
const isDistancePastThreshold = distance2D(info2.offset, { x: 0, y: 0 }) >= 3;
|
|
969
|
+
if (!isPanStarted && !isDistancePastThreshold)
|
|
970
|
+
return;
|
|
971
|
+
const { point: point2 } = info2;
|
|
972
|
+
const { timestamp: timestamp2 } = frameData;
|
|
973
|
+
this.history.push({ ...point2, timestamp: timestamp2 });
|
|
974
|
+
const { onStart, onMove } = this.handlers;
|
|
975
|
+
if (!isPanStarted) {
|
|
976
|
+
onStart && onStart(this.lastMoveEvent, info2);
|
|
977
|
+
this.startEvent = this.lastMoveEvent;
|
|
978
|
+
}
|
|
979
|
+
onMove && onMove(this.lastMoveEvent, info2);
|
|
980
|
+
};
|
|
981
|
+
this.handlePointerMove = (event2, info2) => {
|
|
982
|
+
this.lastMoveEvent = event2;
|
|
983
|
+
this.lastMoveEventInfo = transformPoint(info2, this.transformPagePoint);
|
|
984
|
+
frame.update(this.updatePoint, true);
|
|
985
|
+
};
|
|
986
|
+
this.handlePointerUp = (event2, info2) => {
|
|
987
|
+
this.end();
|
|
988
|
+
const { onEnd, onSessionEnd, resumeAnimation } = this.handlers;
|
|
989
|
+
if (this.dragSnapToOrigin)
|
|
990
|
+
resumeAnimation && resumeAnimation();
|
|
991
|
+
if (!(this.lastMoveEvent && this.lastMoveEventInfo))
|
|
992
|
+
return;
|
|
993
|
+
const panInfo = getPanInfo(event2.type === "pointercancel" ? this.lastMoveEventInfo : transformPoint(info2, this.transformPagePoint), this.history);
|
|
994
|
+
if (this.startEvent && onEnd) {
|
|
995
|
+
onEnd(event2, panInfo);
|
|
996
|
+
}
|
|
997
|
+
onSessionEnd && onSessionEnd(event2, panInfo);
|
|
998
|
+
};
|
|
999
|
+
if (!isPrimaryPointer(event))
|
|
1000
|
+
return;
|
|
1001
|
+
this.dragSnapToOrigin = dragSnapToOrigin;
|
|
1002
|
+
this.handlers = handlers;
|
|
1003
|
+
this.transformPagePoint = transformPagePoint;
|
|
1004
|
+
this.contextWindow = contextWindow || window;
|
|
1005
|
+
const info = extractEventInfo(event);
|
|
1006
|
+
const initialInfo = transformPoint(info, this.transformPagePoint);
|
|
1007
|
+
const { point } = initialInfo;
|
|
1008
|
+
const { timestamp } = frameData;
|
|
1009
|
+
this.history = [{ ...point, timestamp }];
|
|
1010
|
+
const { onSessionStart } = handlers;
|
|
1011
|
+
onSessionStart && onSessionStart(event, getPanInfo(initialInfo, this.history));
|
|
1012
|
+
this.removeListeners = pipe(addPointerEvent(this.contextWindow, "pointermove", this.handlePointerMove), addPointerEvent(this.contextWindow, "pointerup", this.handlePointerUp), addPointerEvent(this.contextWindow, "pointercancel", this.handlePointerUp));
|
|
1013
|
+
}
|
|
1014
|
+
updateHandlers(handlers) {
|
|
1015
|
+
this.handlers = handlers;
|
|
1016
|
+
}
|
|
1017
|
+
end() {
|
|
1018
|
+
this.removeListeners && this.removeListeners();
|
|
1019
|
+
cancelFrame(this.updatePoint);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
function transformPoint(info, transformPagePoint) {
|
|
1023
|
+
return transformPagePoint ? { point: transformPagePoint(info.point) } : info;
|
|
1024
|
+
}
|
|
1025
|
+
function subtractPoint(a, b) {
|
|
1026
|
+
return { x: a.x - b.x, y: a.y - b.y };
|
|
1027
|
+
}
|
|
1028
|
+
function getPanInfo({ point }, history) {
|
|
1029
|
+
return {
|
|
1030
|
+
point,
|
|
1031
|
+
delta: subtractPoint(point, lastDevicePoint(history)),
|
|
1032
|
+
offset: subtractPoint(point, startDevicePoint(history)),
|
|
1033
|
+
velocity: getVelocity(history, 0.1)
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
function startDevicePoint(history) {
|
|
1037
|
+
return history[0];
|
|
1038
|
+
}
|
|
1039
|
+
function lastDevicePoint(history) {
|
|
1040
|
+
return history[history.length - 1];
|
|
1041
|
+
}
|
|
1042
|
+
function getVelocity(history, timeDelta) {
|
|
1043
|
+
if (history.length < 2) {
|
|
1044
|
+
return { x: 0, y: 0 };
|
|
1045
|
+
}
|
|
1046
|
+
let i = history.length - 1;
|
|
1047
|
+
let timestampedPoint = null;
|
|
1048
|
+
const lastPoint = lastDevicePoint(history);
|
|
1049
|
+
while (i >= 0) {
|
|
1050
|
+
timestampedPoint = history[i];
|
|
1051
|
+
if (lastPoint.timestamp - timestampedPoint.timestamp > secondsToMilliseconds(timeDelta)) {
|
|
1052
|
+
break;
|
|
1053
|
+
}
|
|
1054
|
+
i--;
|
|
1055
|
+
}
|
|
1056
|
+
if (!timestampedPoint) {
|
|
1057
|
+
return { x: 0, y: 0 };
|
|
1058
|
+
}
|
|
1059
|
+
const time2 = millisecondsToSeconds(lastPoint.timestamp - timestampedPoint.timestamp);
|
|
1060
|
+
if (time2 === 0) {
|
|
1061
|
+
return { x: 0, y: 0 };
|
|
1062
|
+
}
|
|
1063
|
+
const currentVelocity = {
|
|
1064
|
+
x: (lastPoint.x - timestampedPoint.x) / time2,
|
|
1065
|
+
y: (lastPoint.y - timestampedPoint.y) / time2
|
|
1066
|
+
};
|
|
1067
|
+
if (currentVelocity.x === Infinity) {
|
|
1068
|
+
currentVelocity.x = 0;
|
|
1069
|
+
}
|
|
1070
|
+
if (currentVelocity.y === Infinity) {
|
|
1071
|
+
currentVelocity.y = 0;
|
|
1072
|
+
}
|
|
1073
|
+
return currentVelocity;
|
|
1074
|
+
}
|
|
1075
|
+
const SCALE_PRECISION = 1e-4;
|
|
1076
|
+
const SCALE_MIN = 1 - SCALE_PRECISION;
|
|
1077
|
+
const SCALE_MAX = 1 + SCALE_PRECISION;
|
|
1078
|
+
const TRANSLATE_PRECISION = 0.01;
|
|
1079
|
+
const TRANSLATE_MIN = 0 - TRANSLATE_PRECISION;
|
|
1080
|
+
const TRANSLATE_MAX = 0 + TRANSLATE_PRECISION;
|
|
1081
|
+
function calcLength(axis) {
|
|
1082
|
+
return axis.max - axis.min;
|
|
1083
|
+
}
|
|
1084
|
+
function isNear(value, target, maxDistance) {
|
|
1085
|
+
return Math.abs(value - target) <= maxDistance;
|
|
1086
|
+
}
|
|
1087
|
+
function calcAxisDelta(delta, source, target, origin = 0.5) {
|
|
1088
|
+
delta.origin = origin;
|
|
1089
|
+
delta.originPoint = mixNumber(source.min, source.max, delta.origin);
|
|
1090
|
+
delta.scale = calcLength(target) / calcLength(source);
|
|
1091
|
+
delta.translate = mixNumber(target.min, target.max, delta.origin) - delta.originPoint;
|
|
1092
|
+
if (delta.scale >= SCALE_MIN && delta.scale <= SCALE_MAX || isNaN(delta.scale)) {
|
|
1093
|
+
delta.scale = 1;
|
|
1094
|
+
}
|
|
1095
|
+
if (delta.translate >= TRANSLATE_MIN && delta.translate <= TRANSLATE_MAX || isNaN(delta.translate)) {
|
|
1096
|
+
delta.translate = 0;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
function calcBoxDelta(delta, source, target, origin) {
|
|
1100
|
+
calcAxisDelta(delta.x, source.x, target.x, origin ? origin.originX : void 0);
|
|
1101
|
+
calcAxisDelta(delta.y, source.y, target.y, origin ? origin.originY : void 0);
|
|
1102
|
+
}
|
|
1103
|
+
function calcRelativeAxis(target, relative, parent) {
|
|
1104
|
+
target.min = parent.min + relative.min;
|
|
1105
|
+
target.max = target.min + calcLength(relative);
|
|
1106
|
+
}
|
|
1107
|
+
function calcRelativeBox(target, relative, parent) {
|
|
1108
|
+
calcRelativeAxis(target.x, relative.x, parent.x);
|
|
1109
|
+
calcRelativeAxis(target.y, relative.y, parent.y);
|
|
1110
|
+
}
|
|
1111
|
+
function calcRelativeAxisPosition(target, layout2, parent) {
|
|
1112
|
+
target.min = layout2.min - parent.min;
|
|
1113
|
+
target.max = target.min + calcLength(layout2);
|
|
1114
|
+
}
|
|
1115
|
+
function calcRelativePosition(target, layout2, parent) {
|
|
1116
|
+
calcRelativeAxisPosition(target.x, layout2.x, parent.x);
|
|
1117
|
+
calcRelativeAxisPosition(target.y, layout2.y, parent.y);
|
|
1118
|
+
}
|
|
1119
|
+
function applyConstraints(point, { min, max }, elastic) {
|
|
1120
|
+
if (min !== void 0 && point < min) {
|
|
1121
|
+
point = elastic ? mixNumber(min, point, elastic.min) : Math.max(point, min);
|
|
1122
|
+
} else if (max !== void 0 && point > max) {
|
|
1123
|
+
point = elastic ? mixNumber(max, point, elastic.max) : Math.min(point, max);
|
|
1124
|
+
}
|
|
1125
|
+
return point;
|
|
1126
|
+
}
|
|
1127
|
+
function calcRelativeAxisConstraints(axis, min, max) {
|
|
1128
|
+
return {
|
|
1129
|
+
min: min !== void 0 ? axis.min + min : void 0,
|
|
1130
|
+
max: max !== void 0 ? axis.max + max - (axis.max - axis.min) : void 0
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
function calcRelativeConstraints(layoutBox, { top, left, bottom, right }) {
|
|
1134
|
+
return {
|
|
1135
|
+
x: calcRelativeAxisConstraints(layoutBox.x, left, right),
|
|
1136
|
+
y: calcRelativeAxisConstraints(layoutBox.y, top, bottom)
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
function calcViewportAxisConstraints(layoutAxis, constraintsAxis) {
|
|
1140
|
+
let min = constraintsAxis.min - layoutAxis.min;
|
|
1141
|
+
let max = constraintsAxis.max - layoutAxis.max;
|
|
1142
|
+
if (constraintsAxis.max - constraintsAxis.min < layoutAxis.max - layoutAxis.min) {
|
|
1143
|
+
[min, max] = [max, min];
|
|
1144
|
+
}
|
|
1145
|
+
return { min, max };
|
|
1146
|
+
}
|
|
1147
|
+
function calcViewportConstraints(layoutBox, constraintsBox) {
|
|
1148
|
+
return {
|
|
1149
|
+
x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),
|
|
1150
|
+
y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y)
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
function calcOrigin(source, target) {
|
|
1154
|
+
let origin = 0.5;
|
|
1155
|
+
const sourceLength = calcLength(source);
|
|
1156
|
+
const targetLength = calcLength(target);
|
|
1157
|
+
if (targetLength > sourceLength) {
|
|
1158
|
+
origin = progress(target.min, target.max - sourceLength, source.min);
|
|
1159
|
+
} else if (sourceLength > targetLength) {
|
|
1160
|
+
origin = progress(source.min, source.max - targetLength, target.min);
|
|
1161
|
+
}
|
|
1162
|
+
return clamp(0, 1, origin);
|
|
1163
|
+
}
|
|
1164
|
+
function rebaseAxisConstraints(layout2, constraints) {
|
|
1165
|
+
const relativeConstraints = {};
|
|
1166
|
+
if (constraints.min !== void 0) {
|
|
1167
|
+
relativeConstraints.min = constraints.min - layout2.min;
|
|
1168
|
+
}
|
|
1169
|
+
if (constraints.max !== void 0) {
|
|
1170
|
+
relativeConstraints.max = constraints.max - layout2.min;
|
|
1171
|
+
}
|
|
1172
|
+
return relativeConstraints;
|
|
1173
|
+
}
|
|
1174
|
+
const defaultElastic = 0.35;
|
|
1175
|
+
function resolveDragElastic(dragElastic = defaultElastic) {
|
|
1176
|
+
if (dragElastic === false) {
|
|
1177
|
+
dragElastic = 0;
|
|
1178
|
+
} else if (dragElastic === true) {
|
|
1179
|
+
dragElastic = defaultElastic;
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
x: resolveAxisElastic(dragElastic, "left", "right"),
|
|
1183
|
+
y: resolveAxisElastic(dragElastic, "top", "bottom")
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
function resolveAxisElastic(dragElastic, minLabel, maxLabel) {
|
|
1187
|
+
return {
|
|
1188
|
+
min: resolvePointElastic(dragElastic, minLabel),
|
|
1189
|
+
max: resolvePointElastic(dragElastic, maxLabel)
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
function resolvePointElastic(dragElastic, label) {
|
|
1193
|
+
return typeof dragElastic === "number" ? dragElastic : dragElastic[label] || 0;
|
|
1194
|
+
}
|
|
1195
|
+
function eachAxis(callback) {
|
|
1196
|
+
return [callback("x"), callback("y")];
|
|
1197
|
+
}
|
|
1198
|
+
const getContextWindow = ({ current }) => {
|
|
1199
|
+
return current ? current.ownerDocument.defaultView : null;
|
|
1200
|
+
};
|
|
1201
|
+
const elementDragControls = /* @__PURE__ */ new WeakMap();
|
|
1202
|
+
class VisualElementDragControls {
|
|
1203
|
+
constructor(visualElement) {
|
|
1204
|
+
this.openDragLock = null;
|
|
1205
|
+
this.isDragging = false;
|
|
1206
|
+
this.currentDirection = null;
|
|
1207
|
+
this.originPoint = { x: 0, y: 0 };
|
|
1208
|
+
this.constraints = false;
|
|
1209
|
+
this.hasMutatedConstraints = false;
|
|
1210
|
+
this.elastic = createBox();
|
|
1211
|
+
this.visualElement = visualElement;
|
|
1212
|
+
}
|
|
1213
|
+
start(originEvent, { snapToCursor = false } = {}) {
|
|
1214
|
+
const { presenceContext } = this.visualElement;
|
|
1215
|
+
if (presenceContext && presenceContext.isPresent === false)
|
|
1216
|
+
return;
|
|
1217
|
+
const onSessionStart = (event) => {
|
|
1218
|
+
const { dragSnapToOrigin: dragSnapToOrigin2 } = this.getProps();
|
|
1219
|
+
dragSnapToOrigin2 ? this.pauseAnimation() : this.stopAnimation();
|
|
1220
|
+
if (snapToCursor) {
|
|
1221
|
+
this.snapToCursor(extractEventInfo(event).point);
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
const onStart = (event, info) => {
|
|
1225
|
+
const { drag: drag2, dragPropagation, onDragStart } = this.getProps();
|
|
1226
|
+
if (drag2 && !dragPropagation) {
|
|
1227
|
+
if (this.openDragLock)
|
|
1228
|
+
this.openDragLock();
|
|
1229
|
+
this.openDragLock = setDragLock(drag2);
|
|
1230
|
+
if (!this.openDragLock)
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
this.isDragging = true;
|
|
1234
|
+
this.currentDirection = null;
|
|
1235
|
+
this.resolveConstraints();
|
|
1236
|
+
if (this.visualElement.projection) {
|
|
1237
|
+
this.visualElement.projection.isAnimationBlocked = true;
|
|
1238
|
+
this.visualElement.projection.target = void 0;
|
|
1239
|
+
}
|
|
1240
|
+
eachAxis((axis) => {
|
|
1241
|
+
let current = this.getAxisMotionValue(axis).get() || 0;
|
|
1242
|
+
if (percent.test(current)) {
|
|
1243
|
+
const { projection } = this.visualElement;
|
|
1244
|
+
if (projection && projection.layout) {
|
|
1245
|
+
const measuredAxis = projection.layout.layoutBox[axis];
|
|
1246
|
+
if (measuredAxis) {
|
|
1247
|
+
const length = calcLength(measuredAxis);
|
|
1248
|
+
current = length * (parseFloat(current) / 100);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
this.originPoint[axis] = current;
|
|
1253
|
+
});
|
|
1254
|
+
if (onDragStart) {
|
|
1255
|
+
frame.postRender(() => onDragStart(event, info));
|
|
1256
|
+
}
|
|
1257
|
+
addValueToWillChange(this.visualElement, "transform");
|
|
1258
|
+
const { animationState } = this.visualElement;
|
|
1259
|
+
animationState && animationState.setActive("whileDrag", true);
|
|
1260
|
+
};
|
|
1261
|
+
const onMove = (event, info) => {
|
|
1262
|
+
const { dragPropagation, dragDirectionLock, onDirectionLock, onDrag } = this.getProps();
|
|
1263
|
+
if (!dragPropagation && !this.openDragLock)
|
|
1264
|
+
return;
|
|
1265
|
+
const { offset } = info;
|
|
1266
|
+
if (dragDirectionLock && this.currentDirection === null) {
|
|
1267
|
+
this.currentDirection = getCurrentDirection(offset);
|
|
1268
|
+
if (this.currentDirection !== null) {
|
|
1269
|
+
onDirectionLock && onDirectionLock(this.currentDirection);
|
|
1270
|
+
}
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
this.updateAxis("x", info.point, offset);
|
|
1274
|
+
this.updateAxis("y", info.point, offset);
|
|
1275
|
+
this.visualElement.render();
|
|
1276
|
+
onDrag && onDrag(event, info);
|
|
1277
|
+
};
|
|
1278
|
+
const onSessionEnd = (event, info) => this.stop(event, info);
|
|
1279
|
+
const resumeAnimation = () => eachAxis((axis) => {
|
|
1280
|
+
var _a;
|
|
1281
|
+
return this.getAnimationState(axis) === "paused" && ((_a = this.getAxisMotionValue(axis).animation) === null || _a === void 0 ? void 0 : _a.play());
|
|
1282
|
+
});
|
|
1283
|
+
const { dragSnapToOrigin } = this.getProps();
|
|
1284
|
+
this.panSession = new PanSession(originEvent, {
|
|
1285
|
+
onSessionStart,
|
|
1286
|
+
onStart,
|
|
1287
|
+
onMove,
|
|
1288
|
+
onSessionEnd,
|
|
1289
|
+
resumeAnimation
|
|
1290
|
+
}, {
|
|
1291
|
+
transformPagePoint: this.visualElement.getTransformPagePoint(),
|
|
1292
|
+
dragSnapToOrigin,
|
|
1293
|
+
contextWindow: getContextWindow(this.visualElement)
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
stop(event, info) {
|
|
1297
|
+
const isDragging2 = this.isDragging;
|
|
1298
|
+
this.cancel();
|
|
1299
|
+
if (!isDragging2)
|
|
1300
|
+
return;
|
|
1301
|
+
const { velocity } = info;
|
|
1302
|
+
this.startAnimation(velocity);
|
|
1303
|
+
const { onDragEnd } = this.getProps();
|
|
1304
|
+
if (onDragEnd) {
|
|
1305
|
+
frame.postRender(() => onDragEnd(event, info));
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
cancel() {
|
|
1309
|
+
this.isDragging = false;
|
|
1310
|
+
const { projection, animationState } = this.visualElement;
|
|
1311
|
+
if (projection) {
|
|
1312
|
+
projection.isAnimationBlocked = false;
|
|
1313
|
+
}
|
|
1314
|
+
this.panSession && this.panSession.end();
|
|
1315
|
+
this.panSession = void 0;
|
|
1316
|
+
const { dragPropagation } = this.getProps();
|
|
1317
|
+
if (!dragPropagation && this.openDragLock) {
|
|
1318
|
+
this.openDragLock();
|
|
1319
|
+
this.openDragLock = null;
|
|
1320
|
+
}
|
|
1321
|
+
animationState && animationState.setActive("whileDrag", false);
|
|
1322
|
+
}
|
|
1323
|
+
updateAxis(axis, _point, offset) {
|
|
1324
|
+
const { drag: drag2 } = this.getProps();
|
|
1325
|
+
if (!offset || !shouldDrag(axis, drag2, this.currentDirection))
|
|
1326
|
+
return;
|
|
1327
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1328
|
+
let next = this.originPoint[axis] + offset[axis];
|
|
1329
|
+
if (this.constraints && this.constraints[axis]) {
|
|
1330
|
+
next = applyConstraints(next, this.constraints[axis], this.elastic[axis]);
|
|
1331
|
+
}
|
|
1332
|
+
axisValue.set(next);
|
|
1333
|
+
}
|
|
1334
|
+
resolveConstraints() {
|
|
1335
|
+
var _a;
|
|
1336
|
+
const { dragConstraints, dragElastic } = this.getProps();
|
|
1337
|
+
const layout2 = this.visualElement.projection && !this.visualElement.projection.layout ? this.visualElement.projection.measure(false) : (_a = this.visualElement.projection) === null || _a === void 0 ? void 0 : _a.layout;
|
|
1338
|
+
const prevConstraints = this.constraints;
|
|
1339
|
+
if (dragConstraints && isRefObject(dragConstraints)) {
|
|
1340
|
+
if (!this.constraints) {
|
|
1341
|
+
this.constraints = this.resolveRefConstraints();
|
|
1342
|
+
}
|
|
1343
|
+
} else {
|
|
1344
|
+
if (dragConstraints && layout2) {
|
|
1345
|
+
this.constraints = calcRelativeConstraints(layout2.layoutBox, dragConstraints);
|
|
1346
|
+
} else {
|
|
1347
|
+
this.constraints = false;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
this.elastic = resolveDragElastic(dragElastic);
|
|
1351
|
+
if (prevConstraints !== this.constraints && layout2 && this.constraints && !this.hasMutatedConstraints) {
|
|
1352
|
+
eachAxis((axis) => {
|
|
1353
|
+
if (this.constraints !== false && this.getAxisMotionValue(axis)) {
|
|
1354
|
+
this.constraints[axis] = rebaseAxisConstraints(layout2.layoutBox[axis], this.constraints[axis]);
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
resolveRefConstraints() {
|
|
1360
|
+
const { dragConstraints: constraints, onMeasureDragConstraints } = this.getProps();
|
|
1361
|
+
if (!constraints || !isRefObject(constraints))
|
|
1362
|
+
return false;
|
|
1363
|
+
const constraintsElement = constraints.current;
|
|
1364
|
+
invariant(constraintsElement !== null, "If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.");
|
|
1365
|
+
const { projection } = this.visualElement;
|
|
1366
|
+
if (!projection || !projection.layout)
|
|
1367
|
+
return false;
|
|
1368
|
+
const constraintsBox = measurePageBox(constraintsElement, projection.root, this.visualElement.getTransformPagePoint());
|
|
1369
|
+
let measuredConstraints = calcViewportConstraints(projection.layout.layoutBox, constraintsBox);
|
|
1370
|
+
if (onMeasureDragConstraints) {
|
|
1371
|
+
const userConstraints = onMeasureDragConstraints(convertBoxToBoundingBox(measuredConstraints));
|
|
1372
|
+
this.hasMutatedConstraints = !!userConstraints;
|
|
1373
|
+
if (userConstraints) {
|
|
1374
|
+
measuredConstraints = convertBoundingBoxToBox(userConstraints);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
return measuredConstraints;
|
|
1378
|
+
}
|
|
1379
|
+
startAnimation(velocity) {
|
|
1380
|
+
const { drag: drag2, dragMomentum, dragElastic, dragTransition, dragSnapToOrigin, onDragTransitionEnd } = this.getProps();
|
|
1381
|
+
const constraints = this.constraints || {};
|
|
1382
|
+
const momentumAnimations = eachAxis((axis) => {
|
|
1383
|
+
if (!shouldDrag(axis, drag2, this.currentDirection)) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
let transition = constraints && constraints[axis] || {};
|
|
1387
|
+
if (dragSnapToOrigin)
|
|
1388
|
+
transition = { min: 0, max: 0 };
|
|
1389
|
+
const bounceStiffness = dragElastic ? 200 : 1e6;
|
|
1390
|
+
const bounceDamping = dragElastic ? 40 : 1e7;
|
|
1391
|
+
const inertia = {
|
|
1392
|
+
type: "inertia",
|
|
1393
|
+
velocity: dragMomentum ? velocity[axis] : 0,
|
|
1394
|
+
bounceStiffness,
|
|
1395
|
+
bounceDamping,
|
|
1396
|
+
timeConstant: 750,
|
|
1397
|
+
restDelta: 1,
|
|
1398
|
+
restSpeed: 10,
|
|
1399
|
+
...dragTransition,
|
|
1400
|
+
...transition
|
|
1401
|
+
};
|
|
1402
|
+
return this.startAxisValueAnimation(axis, inertia);
|
|
1403
|
+
});
|
|
1404
|
+
return Promise.all(momentumAnimations).then(onDragTransitionEnd);
|
|
1405
|
+
}
|
|
1406
|
+
startAxisValueAnimation(axis, transition) {
|
|
1407
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1408
|
+
addValueToWillChange(this.visualElement, axis);
|
|
1409
|
+
return axisValue.start(animateMotionValue(axis, axisValue, 0, transition, this.visualElement, false));
|
|
1410
|
+
}
|
|
1411
|
+
stopAnimation() {
|
|
1412
|
+
eachAxis((axis) => this.getAxisMotionValue(axis).stop());
|
|
1413
|
+
}
|
|
1414
|
+
pauseAnimation() {
|
|
1415
|
+
eachAxis((axis) => {
|
|
1416
|
+
var _a;
|
|
1417
|
+
return (_a = this.getAxisMotionValue(axis).animation) === null || _a === void 0 ? void 0 : _a.pause();
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
getAnimationState(axis) {
|
|
1421
|
+
var _a;
|
|
1422
|
+
return (_a = this.getAxisMotionValue(axis).animation) === null || _a === void 0 ? void 0 : _a.state;
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Drag works differently depending on which props are provided.
|
|
1426
|
+
*
|
|
1427
|
+
* - If _dragX and _dragY are provided, we output the gesture delta directly to those motion values.
|
|
1428
|
+
* - Otherwise, we apply the delta to the x/y motion values.
|
|
1429
|
+
*/
|
|
1430
|
+
getAxisMotionValue(axis) {
|
|
1431
|
+
const dragKey = `_drag${axis.toUpperCase()}`;
|
|
1432
|
+
const props = this.visualElement.getProps();
|
|
1433
|
+
const externalMotionValue = props[dragKey];
|
|
1434
|
+
return externalMotionValue ? externalMotionValue : this.visualElement.getValue(axis, (props.initial ? props.initial[axis] : void 0) || 0);
|
|
1435
|
+
}
|
|
1436
|
+
snapToCursor(point) {
|
|
1437
|
+
eachAxis((axis) => {
|
|
1438
|
+
const { drag: drag2 } = this.getProps();
|
|
1439
|
+
if (!shouldDrag(axis, drag2, this.currentDirection))
|
|
1440
|
+
return;
|
|
1441
|
+
const { projection } = this.visualElement;
|
|
1442
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1443
|
+
if (projection && projection.layout) {
|
|
1444
|
+
const { min, max } = projection.layout.layoutBox[axis];
|
|
1445
|
+
axisValue.set(point[axis] - mixNumber(min, max, 0.5));
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* When the viewport resizes we want to check if the measured constraints
|
|
1451
|
+
* have changed and, if so, reposition the element within those new constraints
|
|
1452
|
+
* relative to where it was before the resize.
|
|
1453
|
+
*/
|
|
1454
|
+
scalePositionWithinConstraints() {
|
|
1455
|
+
if (!this.visualElement.current)
|
|
1456
|
+
return;
|
|
1457
|
+
const { drag: drag2, dragConstraints } = this.getProps();
|
|
1458
|
+
const { projection } = this.visualElement;
|
|
1459
|
+
if (!isRefObject(dragConstraints) || !projection || !this.constraints)
|
|
1460
|
+
return;
|
|
1461
|
+
this.stopAnimation();
|
|
1462
|
+
const boxProgress = { x: 0, y: 0 };
|
|
1463
|
+
eachAxis((axis) => {
|
|
1464
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1465
|
+
if (axisValue && this.constraints !== false) {
|
|
1466
|
+
const latest = axisValue.get();
|
|
1467
|
+
boxProgress[axis] = calcOrigin({ min: latest, max: latest }, this.constraints[axis]);
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
const { transformTemplate } = this.visualElement.getProps();
|
|
1471
|
+
this.visualElement.current.style.transform = transformTemplate ? transformTemplate({}, "") : "none";
|
|
1472
|
+
projection.root && projection.root.updateScroll();
|
|
1473
|
+
projection.updateLayout();
|
|
1474
|
+
this.resolveConstraints();
|
|
1475
|
+
eachAxis((axis) => {
|
|
1476
|
+
if (!shouldDrag(axis, drag2, null))
|
|
1477
|
+
return;
|
|
1478
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1479
|
+
const { min, max } = this.constraints[axis];
|
|
1480
|
+
axisValue.set(mixNumber(min, max, boxProgress[axis]));
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
addListeners() {
|
|
1484
|
+
if (!this.visualElement.current)
|
|
1485
|
+
return;
|
|
1486
|
+
elementDragControls.set(this.visualElement, this);
|
|
1487
|
+
const element = this.visualElement.current;
|
|
1488
|
+
const stopPointerListener = addPointerEvent(element, "pointerdown", (event) => {
|
|
1489
|
+
const { drag: drag2, dragListener = true } = this.getProps();
|
|
1490
|
+
drag2 && dragListener && this.start(event);
|
|
1491
|
+
});
|
|
1492
|
+
const measureDragConstraints = () => {
|
|
1493
|
+
const { dragConstraints } = this.getProps();
|
|
1494
|
+
if (isRefObject(dragConstraints) && dragConstraints.current) {
|
|
1495
|
+
this.constraints = this.resolveRefConstraints();
|
|
1496
|
+
}
|
|
1497
|
+
};
|
|
1498
|
+
const { projection } = this.visualElement;
|
|
1499
|
+
const stopMeasureLayoutListener = projection.addEventListener("measure", measureDragConstraints);
|
|
1500
|
+
if (projection && !projection.layout) {
|
|
1501
|
+
projection.root && projection.root.updateScroll();
|
|
1502
|
+
projection.updateLayout();
|
|
1503
|
+
}
|
|
1504
|
+
frame.read(measureDragConstraints);
|
|
1505
|
+
const stopResizeListener = addDomEvent(window, "resize", () => this.scalePositionWithinConstraints());
|
|
1506
|
+
const stopLayoutUpdateListener = projection.addEventListener("didUpdate", (({ delta, hasLayoutChanged }) => {
|
|
1507
|
+
if (this.isDragging && hasLayoutChanged) {
|
|
1508
|
+
eachAxis((axis) => {
|
|
1509
|
+
const motionValue = this.getAxisMotionValue(axis);
|
|
1510
|
+
if (!motionValue)
|
|
1511
|
+
return;
|
|
1512
|
+
this.originPoint[axis] += delta[axis].translate;
|
|
1513
|
+
motionValue.set(motionValue.get() + delta[axis].translate);
|
|
1514
|
+
});
|
|
1515
|
+
this.visualElement.render();
|
|
1516
|
+
}
|
|
1517
|
+
}));
|
|
1518
|
+
return () => {
|
|
1519
|
+
stopResizeListener();
|
|
1520
|
+
stopPointerListener();
|
|
1521
|
+
stopMeasureLayoutListener();
|
|
1522
|
+
stopLayoutUpdateListener && stopLayoutUpdateListener();
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
getProps() {
|
|
1526
|
+
const props = this.visualElement.getProps();
|
|
1527
|
+
const { drag: drag2 = false, dragDirectionLock = false, dragPropagation = false, dragConstraints = false, dragElastic = defaultElastic, dragMomentum = true } = props;
|
|
1528
|
+
return {
|
|
1529
|
+
...props,
|
|
1530
|
+
drag: drag2,
|
|
1531
|
+
dragDirectionLock,
|
|
1532
|
+
dragPropagation,
|
|
1533
|
+
dragConstraints,
|
|
1534
|
+
dragElastic,
|
|
1535
|
+
dragMomentum
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
function shouldDrag(direction, drag2, currentDirection) {
|
|
1540
|
+
return (drag2 === true || drag2 === direction) && (currentDirection === null || currentDirection === direction);
|
|
1541
|
+
}
|
|
1542
|
+
function getCurrentDirection(offset, lockThreshold = 10) {
|
|
1543
|
+
let direction = null;
|
|
1544
|
+
if (Math.abs(offset.y) > lockThreshold) {
|
|
1545
|
+
direction = "y";
|
|
1546
|
+
} else if (Math.abs(offset.x) > lockThreshold) {
|
|
1547
|
+
direction = "x";
|
|
1548
|
+
}
|
|
1549
|
+
return direction;
|
|
1550
|
+
}
|
|
1551
|
+
class DragGesture extends Feature {
|
|
1552
|
+
constructor(node) {
|
|
1553
|
+
super(node);
|
|
1554
|
+
this.removeGroupControls = noop;
|
|
1555
|
+
this.removeListeners = noop;
|
|
1556
|
+
this.controls = new VisualElementDragControls(node);
|
|
1557
|
+
}
|
|
1558
|
+
mount() {
|
|
1559
|
+
const { dragControls } = this.node.getProps();
|
|
1560
|
+
if (dragControls) {
|
|
1561
|
+
this.removeGroupControls = dragControls.subscribe(this.controls);
|
|
1562
|
+
}
|
|
1563
|
+
this.removeListeners = this.controls.addListeners() || noop;
|
|
1564
|
+
}
|
|
1565
|
+
unmount() {
|
|
1566
|
+
this.removeGroupControls();
|
|
1567
|
+
this.removeListeners();
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
const asyncHandler = (handler) => (event, info) => {
|
|
1571
|
+
if (handler) {
|
|
1572
|
+
frame.postRender(() => handler(event, info));
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
class PanGesture extends Feature {
|
|
1576
|
+
constructor() {
|
|
1577
|
+
super(...arguments);
|
|
1578
|
+
this.removePointerDownListener = noop;
|
|
1579
|
+
}
|
|
1580
|
+
onPointerDown(pointerDownEvent) {
|
|
1581
|
+
this.session = new PanSession(pointerDownEvent, this.createPanHandlers(), {
|
|
1582
|
+
transformPagePoint: this.node.getTransformPagePoint(),
|
|
1583
|
+
contextWindow: getContextWindow(this.node)
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
createPanHandlers() {
|
|
1587
|
+
const { onPanSessionStart, onPanStart, onPan, onPanEnd } = this.node.getProps();
|
|
1588
|
+
return {
|
|
1589
|
+
onSessionStart: asyncHandler(onPanSessionStart),
|
|
1590
|
+
onStart: asyncHandler(onPanStart),
|
|
1591
|
+
onMove: onPan,
|
|
1592
|
+
onEnd: (event, info) => {
|
|
1593
|
+
delete this.session;
|
|
1594
|
+
if (onPanEnd) {
|
|
1595
|
+
frame.postRender(() => onPanEnd(event, info));
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
mount() {
|
|
1601
|
+
this.removePointerDownListener = addPointerEvent(this.node.current, "pointerdown", (event) => this.onPointerDown(event));
|
|
1602
|
+
}
|
|
1603
|
+
update() {
|
|
1604
|
+
this.session && this.session.updateHandlers(this.createPanHandlers());
|
|
1605
|
+
}
|
|
1606
|
+
unmount() {
|
|
1607
|
+
this.removePointerDownListener();
|
|
1608
|
+
this.session && this.session.end();
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
const globalProjectionState = {
|
|
1612
|
+
/**
|
|
1613
|
+
* Global flag as to whether the tree has animated since the last time
|
|
1614
|
+
* we resized the window
|
|
1615
|
+
*/
|
|
1616
|
+
hasAnimatedSinceResize: true,
|
|
1617
|
+
/**
|
|
1618
|
+
* We set this to true once, on the first update. Any nodes added to the tree beyond that
|
|
1619
|
+
* update will be given a `data-projection-id` attribute.
|
|
1620
|
+
*/
|
|
1621
|
+
hasEverUpdated: false
|
|
1622
|
+
};
|
|
1623
|
+
function pixelsToPercent(pixels, axis) {
|
|
1624
|
+
if (axis.max === axis.min)
|
|
1625
|
+
return 0;
|
|
1626
|
+
return pixels / (axis.max - axis.min) * 100;
|
|
1627
|
+
}
|
|
1628
|
+
const correctBorderRadius = {
|
|
1629
|
+
correct: (latest, node) => {
|
|
1630
|
+
if (!node.target)
|
|
1631
|
+
return latest;
|
|
1632
|
+
if (typeof latest === "string") {
|
|
1633
|
+
if (px.test(latest)) {
|
|
1634
|
+
latest = parseFloat(latest);
|
|
1635
|
+
} else {
|
|
1636
|
+
return latest;
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
const x = pixelsToPercent(latest, node.target.x);
|
|
1640
|
+
const y = pixelsToPercent(latest, node.target.y);
|
|
1641
|
+
return `${x}% ${y}%`;
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
const correctBoxShadow = {
|
|
1645
|
+
correct: (latest, { treeScale, projectionDelta }) => {
|
|
1646
|
+
const original = latest;
|
|
1647
|
+
const shadow = complex.parse(latest);
|
|
1648
|
+
if (shadow.length > 5)
|
|
1649
|
+
return original;
|
|
1650
|
+
const template = complex.createTransformer(latest);
|
|
1651
|
+
const offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
1652
|
+
const xScale = projectionDelta.x.scale * treeScale.x;
|
|
1653
|
+
const yScale = projectionDelta.y.scale * treeScale.y;
|
|
1654
|
+
shadow[0 + offset] /= xScale;
|
|
1655
|
+
shadow[1 + offset] /= yScale;
|
|
1656
|
+
const averageScale = mixNumber(xScale, yScale, 0.5);
|
|
1657
|
+
if (typeof shadow[2 + offset] === "number")
|
|
1658
|
+
shadow[2 + offset] /= averageScale;
|
|
1659
|
+
if (typeof shadow[3 + offset] === "number")
|
|
1660
|
+
shadow[3 + offset] /= averageScale;
|
|
1661
|
+
return template(shadow);
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
class MeasureLayoutWithContext extends Component {
|
|
1665
|
+
/**
|
|
1666
|
+
* This only mounts projection nodes for components that
|
|
1667
|
+
* need measuring, we might want to do it for all components
|
|
1668
|
+
* in order to incorporate transforms
|
|
1669
|
+
*/
|
|
1670
|
+
componentDidMount() {
|
|
1671
|
+
const { visualElement, layoutGroup, switchLayoutGroup, layoutId } = this.props;
|
|
1672
|
+
const { projection } = visualElement;
|
|
1673
|
+
addScaleCorrector(defaultScaleCorrectors);
|
|
1674
|
+
if (projection) {
|
|
1675
|
+
if (layoutGroup.group)
|
|
1676
|
+
layoutGroup.group.add(projection);
|
|
1677
|
+
if (switchLayoutGroup && switchLayoutGroup.register && layoutId) {
|
|
1678
|
+
switchLayoutGroup.register(projection);
|
|
1679
|
+
}
|
|
1680
|
+
projection.root.didUpdate();
|
|
1681
|
+
projection.addEventListener("animationComplete", () => {
|
|
1682
|
+
this.safeToRemove();
|
|
1683
|
+
});
|
|
1684
|
+
projection.setOptions({
|
|
1685
|
+
...projection.options,
|
|
1686
|
+
onExitComplete: () => this.safeToRemove()
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
globalProjectionState.hasEverUpdated = true;
|
|
1690
|
+
}
|
|
1691
|
+
getSnapshotBeforeUpdate(prevProps) {
|
|
1692
|
+
const { layoutDependency, visualElement, drag: drag2, isPresent } = this.props;
|
|
1693
|
+
const projection = visualElement.projection;
|
|
1694
|
+
if (!projection)
|
|
1695
|
+
return null;
|
|
1696
|
+
projection.isPresent = isPresent;
|
|
1697
|
+
if (drag2 || prevProps.layoutDependency !== layoutDependency || layoutDependency === void 0) {
|
|
1698
|
+
projection.willUpdate();
|
|
1699
|
+
} else {
|
|
1700
|
+
this.safeToRemove();
|
|
1701
|
+
}
|
|
1702
|
+
if (prevProps.isPresent !== isPresent) {
|
|
1703
|
+
if (isPresent) {
|
|
1704
|
+
projection.promote();
|
|
1705
|
+
} else if (!projection.relegate()) {
|
|
1706
|
+
frame.postRender(() => {
|
|
1707
|
+
const stack = projection.getStack();
|
|
1708
|
+
if (!stack || !stack.members.length) {
|
|
1709
|
+
this.safeToRemove();
|
|
1710
|
+
}
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
return null;
|
|
1715
|
+
}
|
|
1716
|
+
componentDidUpdate() {
|
|
1717
|
+
const { projection } = this.props.visualElement;
|
|
1718
|
+
if (projection) {
|
|
1719
|
+
projection.root.didUpdate();
|
|
1720
|
+
microtask.postRender(() => {
|
|
1721
|
+
if (!projection.currentAnimation && projection.isLead()) {
|
|
1722
|
+
this.safeToRemove();
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
componentWillUnmount() {
|
|
1728
|
+
const { visualElement, layoutGroup, switchLayoutGroup: promoteContext } = this.props;
|
|
1729
|
+
const { projection } = visualElement;
|
|
1730
|
+
if (projection) {
|
|
1731
|
+
projection.scheduleCheckAfterUnmount();
|
|
1732
|
+
if (layoutGroup && layoutGroup.group)
|
|
1733
|
+
layoutGroup.group.remove(projection);
|
|
1734
|
+
if (promoteContext && promoteContext.deregister)
|
|
1735
|
+
promoteContext.deregister(projection);
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
safeToRemove() {
|
|
1739
|
+
const { safeToRemove } = this.props;
|
|
1740
|
+
safeToRemove && safeToRemove();
|
|
1741
|
+
}
|
|
1742
|
+
render() {
|
|
1743
|
+
return null;
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
function MeasureLayout(props) {
|
|
1747
|
+
const [isPresent, safeToRemove] = usePresence();
|
|
1748
|
+
const layoutGroup = useContext(LayoutGroupContext);
|
|
1749
|
+
return jsx(MeasureLayoutWithContext, { ...props, layoutGroup, switchLayoutGroup: useContext(SwitchLayoutGroupContext), isPresent, safeToRemove });
|
|
1750
|
+
}
|
|
1751
|
+
const defaultScaleCorrectors = {
|
|
1752
|
+
borderRadius: {
|
|
1753
|
+
...correctBorderRadius,
|
|
1754
|
+
applyTo: [
|
|
1755
|
+
"borderTopLeftRadius",
|
|
1756
|
+
"borderTopRightRadius",
|
|
1757
|
+
"borderBottomLeftRadius",
|
|
1758
|
+
"borderBottomRightRadius"
|
|
1759
|
+
]
|
|
1760
|
+
},
|
|
1761
|
+
borderTopLeftRadius: correctBorderRadius,
|
|
1762
|
+
borderTopRightRadius: correctBorderRadius,
|
|
1763
|
+
borderBottomLeftRadius: correctBorderRadius,
|
|
1764
|
+
borderBottomRightRadius: correctBorderRadius,
|
|
1765
|
+
boxShadow: correctBoxShadow
|
|
1766
|
+
};
|
|
1767
|
+
const compareByDepth = (a, b) => a.depth - b.depth;
|
|
1768
|
+
class FlatTree {
|
|
1769
|
+
constructor() {
|
|
1770
|
+
this.children = [];
|
|
1771
|
+
this.isDirty = false;
|
|
1772
|
+
}
|
|
1773
|
+
add(child) {
|
|
1774
|
+
addUniqueItem(this.children, child);
|
|
1775
|
+
this.isDirty = true;
|
|
1776
|
+
}
|
|
1777
|
+
remove(child) {
|
|
1778
|
+
removeItem(this.children, child);
|
|
1779
|
+
this.isDirty = true;
|
|
1780
|
+
}
|
|
1781
|
+
forEach(callback) {
|
|
1782
|
+
this.isDirty && this.children.sort(compareByDepth);
|
|
1783
|
+
this.isDirty = false;
|
|
1784
|
+
this.children.forEach(callback);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
function delay(callback, timeout) {
|
|
1788
|
+
const start = time.now();
|
|
1789
|
+
const checkElapsed = ({ timestamp }) => {
|
|
1790
|
+
const elapsed = timestamp - start;
|
|
1791
|
+
if (elapsed >= timeout) {
|
|
1792
|
+
cancelFrame(checkElapsed);
|
|
1793
|
+
callback(elapsed - timeout);
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
frame.read(checkElapsed, true);
|
|
1797
|
+
return () => cancelFrame(checkElapsed);
|
|
1798
|
+
}
|
|
1799
|
+
const borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"];
|
|
1800
|
+
const numBorders = borders.length;
|
|
1801
|
+
const asNumber = (value) => typeof value === "string" ? parseFloat(value) : value;
|
|
1802
|
+
const isPx = (value) => typeof value === "number" || px.test(value);
|
|
1803
|
+
function mixValues(target, follow, lead, progress2, shouldCrossfadeOpacity, isOnlyMember) {
|
|
1804
|
+
if (shouldCrossfadeOpacity) {
|
|
1805
|
+
target.opacity = mixNumber(
|
|
1806
|
+
0,
|
|
1807
|
+
// TODO Reinstate this if only child
|
|
1808
|
+
lead.opacity !== void 0 ? lead.opacity : 1,
|
|
1809
|
+
easeCrossfadeIn(progress2)
|
|
1810
|
+
);
|
|
1811
|
+
target.opacityExit = mixNumber(follow.opacity !== void 0 ? follow.opacity : 1, 0, easeCrossfadeOut(progress2));
|
|
1812
|
+
} else if (isOnlyMember) {
|
|
1813
|
+
target.opacity = mixNumber(follow.opacity !== void 0 ? follow.opacity : 1, lead.opacity !== void 0 ? lead.opacity : 1, progress2);
|
|
1814
|
+
}
|
|
1815
|
+
for (let i = 0; i < numBorders; i++) {
|
|
1816
|
+
const borderLabel = `border${borders[i]}Radius`;
|
|
1817
|
+
let followRadius = getRadius(follow, borderLabel);
|
|
1818
|
+
let leadRadius = getRadius(lead, borderLabel);
|
|
1819
|
+
if (followRadius === void 0 && leadRadius === void 0)
|
|
1820
|
+
continue;
|
|
1821
|
+
followRadius || (followRadius = 0);
|
|
1822
|
+
leadRadius || (leadRadius = 0);
|
|
1823
|
+
const canMix = followRadius === 0 || leadRadius === 0 || isPx(followRadius) === isPx(leadRadius);
|
|
1824
|
+
if (canMix) {
|
|
1825
|
+
target[borderLabel] = Math.max(mixNumber(asNumber(followRadius), asNumber(leadRadius), progress2), 0);
|
|
1826
|
+
if (percent.test(leadRadius) || percent.test(followRadius)) {
|
|
1827
|
+
target[borderLabel] += "%";
|
|
1828
|
+
}
|
|
1829
|
+
} else {
|
|
1830
|
+
target[borderLabel] = leadRadius;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
if (follow.rotate || lead.rotate) {
|
|
1834
|
+
target.rotate = mixNumber(follow.rotate || 0, lead.rotate || 0, progress2);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
function getRadius(values, radiusName) {
|
|
1838
|
+
return values[radiusName] !== void 0 ? values[radiusName] : values.borderRadius;
|
|
1839
|
+
}
|
|
1840
|
+
const easeCrossfadeIn = /* @__PURE__ */ compress(0, 0.5, circOut);
|
|
1841
|
+
const easeCrossfadeOut = /* @__PURE__ */ compress(0.5, 0.95, noop);
|
|
1842
|
+
function compress(min, max, easing) {
|
|
1843
|
+
return (p) => {
|
|
1844
|
+
if (p < min)
|
|
1845
|
+
return 0;
|
|
1846
|
+
if (p > max)
|
|
1847
|
+
return 1;
|
|
1848
|
+
return easing(progress(min, max, p));
|
|
1849
|
+
};
|
|
1850
|
+
}
|
|
1851
|
+
function copyAxisInto(axis, originAxis) {
|
|
1852
|
+
axis.min = originAxis.min;
|
|
1853
|
+
axis.max = originAxis.max;
|
|
1854
|
+
}
|
|
1855
|
+
function copyBoxInto(box, originBox) {
|
|
1856
|
+
copyAxisInto(box.x, originBox.x);
|
|
1857
|
+
copyAxisInto(box.y, originBox.y);
|
|
1858
|
+
}
|
|
1859
|
+
function copyAxisDeltaInto(delta, originDelta) {
|
|
1860
|
+
delta.translate = originDelta.translate;
|
|
1861
|
+
delta.scale = originDelta.scale;
|
|
1862
|
+
delta.originPoint = originDelta.originPoint;
|
|
1863
|
+
delta.origin = originDelta.origin;
|
|
1864
|
+
}
|
|
1865
|
+
function removePointDelta(point, translate, scale, originPoint, boxScale) {
|
|
1866
|
+
point -= translate;
|
|
1867
|
+
point = scalePoint(point, 1 / scale, originPoint);
|
|
1868
|
+
if (boxScale !== void 0) {
|
|
1869
|
+
point = scalePoint(point, 1 / boxScale, originPoint);
|
|
1870
|
+
}
|
|
1871
|
+
return point;
|
|
1872
|
+
}
|
|
1873
|
+
function removeAxisDelta(axis, translate = 0, scale = 1, origin = 0.5, boxScale, originAxis = axis, sourceAxis = axis) {
|
|
1874
|
+
if (percent.test(translate)) {
|
|
1875
|
+
translate = parseFloat(translate);
|
|
1876
|
+
const relativeProgress = mixNumber(sourceAxis.min, sourceAxis.max, translate / 100);
|
|
1877
|
+
translate = relativeProgress - sourceAxis.min;
|
|
1878
|
+
}
|
|
1879
|
+
if (typeof translate !== "number")
|
|
1880
|
+
return;
|
|
1881
|
+
let originPoint = mixNumber(originAxis.min, originAxis.max, origin);
|
|
1882
|
+
if (axis === originAxis)
|
|
1883
|
+
originPoint -= translate;
|
|
1884
|
+
axis.min = removePointDelta(axis.min, translate, scale, originPoint, boxScale);
|
|
1885
|
+
axis.max = removePointDelta(axis.max, translate, scale, originPoint, boxScale);
|
|
1886
|
+
}
|
|
1887
|
+
function removeAxisTransforms(axis, transforms, [key, scaleKey, originKey], origin, sourceAxis) {
|
|
1888
|
+
removeAxisDelta(axis, transforms[key], transforms[scaleKey], transforms[originKey], transforms.scale, origin, sourceAxis);
|
|
1889
|
+
}
|
|
1890
|
+
const xKeys = ["x", "scaleX", "originX"];
|
|
1891
|
+
const yKeys = ["y", "scaleY", "originY"];
|
|
1892
|
+
function removeBoxTransforms(box, transforms, originBox, sourceBox) {
|
|
1893
|
+
removeAxisTransforms(box.x, transforms, xKeys, originBox ? originBox.x : void 0, sourceBox ? sourceBox.x : void 0);
|
|
1894
|
+
removeAxisTransforms(box.y, transforms, yKeys, originBox ? originBox.y : void 0, sourceBox ? sourceBox.y : void 0);
|
|
1895
|
+
}
|
|
1896
|
+
function isAxisDeltaZero(delta) {
|
|
1897
|
+
return delta.translate === 0 && delta.scale === 1;
|
|
1898
|
+
}
|
|
1899
|
+
function isDeltaZero(delta) {
|
|
1900
|
+
return isAxisDeltaZero(delta.x) && isAxisDeltaZero(delta.y);
|
|
1901
|
+
}
|
|
1902
|
+
function axisEquals(a, b) {
|
|
1903
|
+
return a.min === b.min && a.max === b.max;
|
|
1904
|
+
}
|
|
1905
|
+
function boxEquals(a, b) {
|
|
1906
|
+
return axisEquals(a.x, b.x) && axisEquals(a.y, b.y);
|
|
1907
|
+
}
|
|
1908
|
+
function axisEqualsRounded(a, b) {
|
|
1909
|
+
return Math.round(a.min) === Math.round(b.min) && Math.round(a.max) === Math.round(b.max);
|
|
1910
|
+
}
|
|
1911
|
+
function boxEqualsRounded(a, b) {
|
|
1912
|
+
return axisEqualsRounded(a.x, b.x) && axisEqualsRounded(a.y, b.y);
|
|
1913
|
+
}
|
|
1914
|
+
function aspectRatio(box) {
|
|
1915
|
+
return calcLength(box.x) / calcLength(box.y);
|
|
1916
|
+
}
|
|
1917
|
+
function axisDeltaEquals(a, b) {
|
|
1918
|
+
return a.translate === b.translate && a.scale === b.scale && a.originPoint === b.originPoint;
|
|
1919
|
+
}
|
|
1920
|
+
class NodeStack {
|
|
1921
|
+
constructor() {
|
|
1922
|
+
this.members = [];
|
|
1923
|
+
}
|
|
1924
|
+
add(node) {
|
|
1925
|
+
addUniqueItem(this.members, node);
|
|
1926
|
+
node.scheduleRender();
|
|
1927
|
+
}
|
|
1928
|
+
remove(node) {
|
|
1929
|
+
removeItem(this.members, node);
|
|
1930
|
+
if (node === this.prevLead) {
|
|
1931
|
+
this.prevLead = void 0;
|
|
1932
|
+
}
|
|
1933
|
+
if (node === this.lead) {
|
|
1934
|
+
const prevLead = this.members[this.members.length - 1];
|
|
1935
|
+
if (prevLead) {
|
|
1936
|
+
this.promote(prevLead);
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
relegate(node) {
|
|
1941
|
+
const indexOfNode = this.members.findIndex((member) => node === member);
|
|
1942
|
+
if (indexOfNode === 0)
|
|
1943
|
+
return false;
|
|
1944
|
+
let prevLead;
|
|
1945
|
+
for (let i = indexOfNode; i >= 0; i--) {
|
|
1946
|
+
const member = this.members[i];
|
|
1947
|
+
if (member.isPresent !== false) {
|
|
1948
|
+
prevLead = member;
|
|
1949
|
+
break;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
if (prevLead) {
|
|
1953
|
+
this.promote(prevLead);
|
|
1954
|
+
return true;
|
|
1955
|
+
} else {
|
|
1956
|
+
return false;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
promote(node, preserveFollowOpacity) {
|
|
1960
|
+
const prevLead = this.lead;
|
|
1961
|
+
if (node === prevLead)
|
|
1962
|
+
return;
|
|
1963
|
+
this.prevLead = prevLead;
|
|
1964
|
+
this.lead = node;
|
|
1965
|
+
node.show();
|
|
1966
|
+
if (prevLead) {
|
|
1967
|
+
prevLead.instance && prevLead.scheduleRender();
|
|
1968
|
+
node.scheduleRender();
|
|
1969
|
+
node.resumeFrom = prevLead;
|
|
1970
|
+
if (preserveFollowOpacity) {
|
|
1971
|
+
node.resumeFrom.preserveOpacity = true;
|
|
1972
|
+
}
|
|
1973
|
+
if (prevLead.snapshot) {
|
|
1974
|
+
node.snapshot = prevLead.snapshot;
|
|
1975
|
+
node.snapshot.latestValues = prevLead.animationValues || prevLead.latestValues;
|
|
1976
|
+
}
|
|
1977
|
+
if (node.root && node.root.isUpdating) {
|
|
1978
|
+
node.isLayoutDirty = true;
|
|
1979
|
+
}
|
|
1980
|
+
const { crossfade } = node.options;
|
|
1981
|
+
if (crossfade === false) {
|
|
1982
|
+
prevLead.hide();
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
exitAnimationComplete() {
|
|
1987
|
+
this.members.forEach((node) => {
|
|
1988
|
+
const { options, resumingFrom } = node;
|
|
1989
|
+
options.onExitComplete && options.onExitComplete();
|
|
1990
|
+
if (resumingFrom) {
|
|
1991
|
+
resumingFrom.options.onExitComplete && resumingFrom.options.onExitComplete();
|
|
1992
|
+
}
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
scheduleRender() {
|
|
1996
|
+
this.members.forEach((node) => {
|
|
1997
|
+
node.instance && node.scheduleRender(false);
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
/**
|
|
2001
|
+
* Clear any leads that have been removed this render to prevent them from being
|
|
2002
|
+
* used in future animations and to prevent memory leaks
|
|
2003
|
+
*/
|
|
2004
|
+
removeLeadSnapshot() {
|
|
2005
|
+
if (this.lead && this.lead.snapshot) {
|
|
2006
|
+
this.lead.snapshot = void 0;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
2011
|
+
let transform = "";
|
|
2012
|
+
const xTranslate = delta.x.translate / treeScale.x;
|
|
2013
|
+
const yTranslate = delta.y.translate / treeScale.y;
|
|
2014
|
+
const zTranslate = (latestTransform === null || latestTransform === void 0 ? void 0 : latestTransform.z) || 0;
|
|
2015
|
+
if (xTranslate || yTranslate || zTranslate) {
|
|
2016
|
+
transform = `translate3d(${xTranslate}px, ${yTranslate}px, ${zTranslate}px) `;
|
|
2017
|
+
}
|
|
2018
|
+
if (treeScale.x !== 1 || treeScale.y !== 1) {
|
|
2019
|
+
transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
|
|
2020
|
+
}
|
|
2021
|
+
if (latestTransform) {
|
|
2022
|
+
const { transformPerspective, rotate, rotateX, rotateY, skewX, skewY } = latestTransform;
|
|
2023
|
+
if (transformPerspective)
|
|
2024
|
+
transform = `perspective(${transformPerspective}px) ${transform}`;
|
|
2025
|
+
if (rotate)
|
|
2026
|
+
transform += `rotate(${rotate}deg) `;
|
|
2027
|
+
if (rotateX)
|
|
2028
|
+
transform += `rotateX(${rotateX}deg) `;
|
|
2029
|
+
if (rotateY)
|
|
2030
|
+
transform += `rotateY(${rotateY}deg) `;
|
|
2031
|
+
if (skewX)
|
|
2032
|
+
transform += `skewX(${skewX}deg) `;
|
|
2033
|
+
if (skewY)
|
|
2034
|
+
transform += `skewY(${skewY}deg) `;
|
|
2035
|
+
}
|
|
2036
|
+
const elementScaleX = delta.x.scale * treeScale.x;
|
|
2037
|
+
const elementScaleY = delta.y.scale * treeScale.y;
|
|
2038
|
+
if (elementScaleX !== 1 || elementScaleY !== 1) {
|
|
2039
|
+
transform += `scale(${elementScaleX}, ${elementScaleY})`;
|
|
2040
|
+
}
|
|
2041
|
+
return transform || "none";
|
|
2042
|
+
}
|
|
2043
|
+
const metrics = {
|
|
2044
|
+
type: "projectionFrame",
|
|
2045
|
+
totalNodes: 0,
|
|
2046
|
+
resolvedTargetDeltas: 0,
|
|
2047
|
+
recalculatedProjection: 0
|
|
2048
|
+
};
|
|
2049
|
+
const isDebug = typeof window !== "undefined" && window.MotionDebug !== void 0;
|
|
2050
|
+
const transformAxes = ["", "X", "Y", "Z"];
|
|
2051
|
+
const hiddenVisibility = { visibility: "hidden" };
|
|
2052
|
+
const animationTarget = 1e3;
|
|
2053
|
+
let id = 0;
|
|
2054
|
+
function resetDistortingTransform(key, visualElement, values, sharedAnimationValues) {
|
|
2055
|
+
const { latestValues } = visualElement;
|
|
2056
|
+
if (latestValues[key]) {
|
|
2057
|
+
values[key] = latestValues[key];
|
|
2058
|
+
visualElement.setStaticValue(key, 0);
|
|
2059
|
+
if (sharedAnimationValues) {
|
|
2060
|
+
sharedAnimationValues[key] = 0;
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
function cancelTreeOptimisedTransformAnimations(projectionNode) {
|
|
2065
|
+
projectionNode.hasCheckedOptimisedAppear = true;
|
|
2066
|
+
if (projectionNode.root === projectionNode)
|
|
2067
|
+
return;
|
|
2068
|
+
const { visualElement } = projectionNode.options;
|
|
2069
|
+
if (!visualElement)
|
|
2070
|
+
return;
|
|
2071
|
+
const appearId = getOptimisedAppearId(visualElement);
|
|
2072
|
+
if (window.MotionHasOptimisedAnimation(appearId, "transform")) {
|
|
2073
|
+
const { layout: layout2, layoutId } = projectionNode.options;
|
|
2074
|
+
window.MotionCancelOptimisedAnimation(appearId, "transform", frame, !(layout2 || layoutId));
|
|
2075
|
+
}
|
|
2076
|
+
const { parent } = projectionNode;
|
|
2077
|
+
if (parent && !parent.hasCheckedOptimisedAppear) {
|
|
2078
|
+
cancelTreeOptimisedTransformAnimations(parent);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform }) {
|
|
2082
|
+
return class ProjectionNode {
|
|
2083
|
+
constructor(latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
|
|
2084
|
+
this.id = id++;
|
|
2085
|
+
this.animationId = 0;
|
|
2086
|
+
this.children = /* @__PURE__ */ new Set();
|
|
2087
|
+
this.options = {};
|
|
2088
|
+
this.isTreeAnimating = false;
|
|
2089
|
+
this.isAnimationBlocked = false;
|
|
2090
|
+
this.isLayoutDirty = false;
|
|
2091
|
+
this.isProjectionDirty = false;
|
|
2092
|
+
this.isSharedProjectionDirty = false;
|
|
2093
|
+
this.isTransformDirty = false;
|
|
2094
|
+
this.updateManuallyBlocked = false;
|
|
2095
|
+
this.updateBlockedByResize = false;
|
|
2096
|
+
this.isUpdating = false;
|
|
2097
|
+
this.isSVG = false;
|
|
2098
|
+
this.needsReset = false;
|
|
2099
|
+
this.shouldResetTransform = false;
|
|
2100
|
+
this.hasCheckedOptimisedAppear = false;
|
|
2101
|
+
this.treeScale = { x: 1, y: 1 };
|
|
2102
|
+
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
2103
|
+
this.hasTreeAnimated = false;
|
|
2104
|
+
this.updateScheduled = false;
|
|
2105
|
+
this.scheduleUpdate = () => this.update();
|
|
2106
|
+
this.projectionUpdateScheduled = false;
|
|
2107
|
+
this.checkUpdateFailed = () => {
|
|
2108
|
+
if (this.isUpdating) {
|
|
2109
|
+
this.isUpdating = false;
|
|
2110
|
+
this.clearAllSnapshots();
|
|
2111
|
+
}
|
|
2112
|
+
};
|
|
2113
|
+
this.updateProjection = () => {
|
|
2114
|
+
this.projectionUpdateScheduled = false;
|
|
2115
|
+
if (isDebug) {
|
|
2116
|
+
metrics.totalNodes = metrics.resolvedTargetDeltas = metrics.recalculatedProjection = 0;
|
|
2117
|
+
}
|
|
2118
|
+
this.nodes.forEach(propagateDirtyNodes);
|
|
2119
|
+
this.nodes.forEach(resolveTargetDelta);
|
|
2120
|
+
this.nodes.forEach(calcProjection);
|
|
2121
|
+
this.nodes.forEach(cleanDirtyNodes);
|
|
2122
|
+
if (isDebug) {
|
|
2123
|
+
window.MotionDebug.record(metrics);
|
|
2124
|
+
}
|
|
2125
|
+
};
|
|
2126
|
+
this.resolvedRelativeTargetAt = 0;
|
|
2127
|
+
this.hasProjected = false;
|
|
2128
|
+
this.isVisible = true;
|
|
2129
|
+
this.animationProgress = 0;
|
|
2130
|
+
this.sharedNodes = /* @__PURE__ */ new Map();
|
|
2131
|
+
this.latestValues = latestValues;
|
|
2132
|
+
this.root = parent ? parent.root || parent : this;
|
|
2133
|
+
this.path = parent ? [...parent.path, parent] : [];
|
|
2134
|
+
this.parent = parent;
|
|
2135
|
+
this.depth = parent ? parent.depth + 1 : 0;
|
|
2136
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
2137
|
+
this.path[i].shouldResetTransform = true;
|
|
2138
|
+
}
|
|
2139
|
+
if (this.root === this)
|
|
2140
|
+
this.nodes = new FlatTree();
|
|
2141
|
+
}
|
|
2142
|
+
addEventListener(name, handler) {
|
|
2143
|
+
if (!this.eventHandlers.has(name)) {
|
|
2144
|
+
this.eventHandlers.set(name, new SubscriptionManager());
|
|
2145
|
+
}
|
|
2146
|
+
return this.eventHandlers.get(name).add(handler);
|
|
2147
|
+
}
|
|
2148
|
+
notifyListeners(name, ...args) {
|
|
2149
|
+
const subscriptionManager = this.eventHandlers.get(name);
|
|
2150
|
+
subscriptionManager && subscriptionManager.notify(...args);
|
|
2151
|
+
}
|
|
2152
|
+
hasListeners(name) {
|
|
2153
|
+
return this.eventHandlers.has(name);
|
|
2154
|
+
}
|
|
2155
|
+
/**
|
|
2156
|
+
* Lifecycles
|
|
2157
|
+
*/
|
|
2158
|
+
mount(instance, isLayoutDirty = this.root.hasTreeAnimated) {
|
|
2159
|
+
if (this.instance)
|
|
2160
|
+
return;
|
|
2161
|
+
this.isSVG = isSVGElement(instance);
|
|
2162
|
+
this.instance = instance;
|
|
2163
|
+
const { layoutId, layout: layout2, visualElement } = this.options;
|
|
2164
|
+
if (visualElement && !visualElement.current) {
|
|
2165
|
+
visualElement.mount(instance);
|
|
2166
|
+
}
|
|
2167
|
+
this.root.nodes.add(this);
|
|
2168
|
+
this.parent && this.parent.children.add(this);
|
|
2169
|
+
if (isLayoutDirty && (layout2 || layoutId)) {
|
|
2170
|
+
this.isLayoutDirty = true;
|
|
2171
|
+
}
|
|
2172
|
+
if (attachResizeListener) {
|
|
2173
|
+
let cancelDelay;
|
|
2174
|
+
const resizeUnblockUpdate = () => this.root.updateBlockedByResize = false;
|
|
2175
|
+
attachResizeListener(instance, () => {
|
|
2176
|
+
this.root.updateBlockedByResize = true;
|
|
2177
|
+
cancelDelay && cancelDelay();
|
|
2178
|
+
cancelDelay = delay(resizeUnblockUpdate, 250);
|
|
2179
|
+
if (globalProjectionState.hasAnimatedSinceResize) {
|
|
2180
|
+
globalProjectionState.hasAnimatedSinceResize = false;
|
|
2181
|
+
this.nodes.forEach(finishAnimation);
|
|
2182
|
+
}
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
if (layoutId) {
|
|
2186
|
+
this.root.registerSharedNode(layoutId, this);
|
|
2187
|
+
}
|
|
2188
|
+
if (this.options.animate !== false && visualElement && (layoutId || layout2)) {
|
|
2189
|
+
this.addEventListener("didUpdate", ({ delta, hasLayoutChanged, hasRelativeTargetChanged, layout: newLayout }) => {
|
|
2190
|
+
if (this.isTreeAnimationBlocked()) {
|
|
2191
|
+
this.target = void 0;
|
|
2192
|
+
this.relativeTarget = void 0;
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
const layoutTransition = this.options.transition || visualElement.getDefaultTransition() || defaultLayoutTransition;
|
|
2196
|
+
const { onLayoutAnimationStart, onLayoutAnimationComplete } = visualElement.getProps();
|
|
2197
|
+
const targetChanged = !this.targetLayout || !boxEqualsRounded(this.targetLayout, newLayout) || hasRelativeTargetChanged;
|
|
2198
|
+
const hasOnlyRelativeTargetChanged = !hasLayoutChanged && hasRelativeTargetChanged;
|
|
2199
|
+
if (this.options.layoutRoot || this.resumeFrom && this.resumeFrom.instance || hasOnlyRelativeTargetChanged || hasLayoutChanged && (targetChanged || !this.currentAnimation)) {
|
|
2200
|
+
if (this.resumeFrom) {
|
|
2201
|
+
this.resumingFrom = this.resumeFrom;
|
|
2202
|
+
this.resumingFrom.resumingFrom = void 0;
|
|
2203
|
+
}
|
|
2204
|
+
this.setAnimationOrigin(delta, hasOnlyRelativeTargetChanged);
|
|
2205
|
+
const animationOptions = {
|
|
2206
|
+
...getValueTransition(layoutTransition, "layout"),
|
|
2207
|
+
onPlay: onLayoutAnimationStart,
|
|
2208
|
+
onComplete: onLayoutAnimationComplete
|
|
2209
|
+
};
|
|
2210
|
+
if (visualElement.shouldReduceMotion || this.options.layoutRoot) {
|
|
2211
|
+
animationOptions.delay = 0;
|
|
2212
|
+
animationOptions.type = false;
|
|
2213
|
+
}
|
|
2214
|
+
this.startAnimation(animationOptions);
|
|
2215
|
+
} else {
|
|
2216
|
+
if (!hasLayoutChanged) {
|
|
2217
|
+
finishAnimation(this);
|
|
2218
|
+
}
|
|
2219
|
+
if (this.isLead() && this.options.onExitComplete) {
|
|
2220
|
+
this.options.onExitComplete();
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
this.targetLayout = newLayout;
|
|
2224
|
+
});
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
unmount() {
|
|
2228
|
+
this.options.layoutId && this.willUpdate();
|
|
2229
|
+
this.root.nodes.remove(this);
|
|
2230
|
+
const stack = this.getStack();
|
|
2231
|
+
stack && stack.remove(this);
|
|
2232
|
+
this.parent && this.parent.children.delete(this);
|
|
2233
|
+
this.instance = void 0;
|
|
2234
|
+
cancelFrame(this.updateProjection);
|
|
2235
|
+
}
|
|
2236
|
+
// only on the root
|
|
2237
|
+
blockUpdate() {
|
|
2238
|
+
this.updateManuallyBlocked = true;
|
|
2239
|
+
}
|
|
2240
|
+
unblockUpdate() {
|
|
2241
|
+
this.updateManuallyBlocked = false;
|
|
2242
|
+
}
|
|
2243
|
+
isUpdateBlocked() {
|
|
2244
|
+
return this.updateManuallyBlocked || this.updateBlockedByResize;
|
|
2245
|
+
}
|
|
2246
|
+
isTreeAnimationBlocked() {
|
|
2247
|
+
return this.isAnimationBlocked || this.parent && this.parent.isTreeAnimationBlocked() || false;
|
|
2248
|
+
}
|
|
2249
|
+
// Note: currently only running on root node
|
|
2250
|
+
startUpdate() {
|
|
2251
|
+
if (this.isUpdateBlocked())
|
|
2252
|
+
return;
|
|
2253
|
+
this.isUpdating = true;
|
|
2254
|
+
this.nodes && this.nodes.forEach(resetSkewAndRotation);
|
|
2255
|
+
this.animationId++;
|
|
2256
|
+
}
|
|
2257
|
+
getTransformTemplate() {
|
|
2258
|
+
const { visualElement } = this.options;
|
|
2259
|
+
return visualElement && visualElement.getProps().transformTemplate;
|
|
2260
|
+
}
|
|
2261
|
+
willUpdate(shouldNotifyListeners = true) {
|
|
2262
|
+
this.root.hasTreeAnimated = true;
|
|
2263
|
+
if (this.root.isUpdateBlocked()) {
|
|
2264
|
+
this.options.onExitComplete && this.options.onExitComplete();
|
|
2265
|
+
return;
|
|
2266
|
+
}
|
|
2267
|
+
if (window.MotionCancelOptimisedAnimation && !this.hasCheckedOptimisedAppear) {
|
|
2268
|
+
cancelTreeOptimisedTransformAnimations(this);
|
|
2269
|
+
}
|
|
2270
|
+
!this.root.isUpdating && this.root.startUpdate();
|
|
2271
|
+
if (this.isLayoutDirty)
|
|
2272
|
+
return;
|
|
2273
|
+
this.isLayoutDirty = true;
|
|
2274
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
2275
|
+
const node = this.path[i];
|
|
2276
|
+
node.shouldResetTransform = true;
|
|
2277
|
+
node.updateScroll("snapshot");
|
|
2278
|
+
if (node.options.layoutRoot) {
|
|
2279
|
+
node.willUpdate(false);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
const { layoutId, layout: layout2 } = this.options;
|
|
2283
|
+
if (layoutId === void 0 && !layout2)
|
|
2284
|
+
return;
|
|
2285
|
+
const transformTemplate = this.getTransformTemplate();
|
|
2286
|
+
this.prevTransformTemplateValue = transformTemplate ? transformTemplate(this.latestValues, "") : void 0;
|
|
2287
|
+
this.updateSnapshot();
|
|
2288
|
+
shouldNotifyListeners && this.notifyListeners("willUpdate");
|
|
2289
|
+
}
|
|
2290
|
+
update() {
|
|
2291
|
+
this.updateScheduled = false;
|
|
2292
|
+
const updateWasBlocked = this.isUpdateBlocked();
|
|
2293
|
+
if (updateWasBlocked) {
|
|
2294
|
+
this.unblockUpdate();
|
|
2295
|
+
this.clearAllSnapshots();
|
|
2296
|
+
this.nodes.forEach(clearMeasurements);
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
if (!this.isUpdating) {
|
|
2300
|
+
this.nodes.forEach(clearIsLayoutDirty);
|
|
2301
|
+
}
|
|
2302
|
+
this.isUpdating = false;
|
|
2303
|
+
this.nodes.forEach(resetTransformStyle);
|
|
2304
|
+
this.nodes.forEach(updateLayout);
|
|
2305
|
+
this.nodes.forEach(notifyLayoutUpdate);
|
|
2306
|
+
this.clearAllSnapshots();
|
|
2307
|
+
const now = time.now();
|
|
2308
|
+
frameData.delta = clamp(0, 1e3 / 60, now - frameData.timestamp);
|
|
2309
|
+
frameData.timestamp = now;
|
|
2310
|
+
frameData.isProcessing = true;
|
|
2311
|
+
frameSteps.update.process(frameData);
|
|
2312
|
+
frameSteps.preRender.process(frameData);
|
|
2313
|
+
frameSteps.render.process(frameData);
|
|
2314
|
+
frameData.isProcessing = false;
|
|
2315
|
+
}
|
|
2316
|
+
didUpdate() {
|
|
2317
|
+
if (!this.updateScheduled) {
|
|
2318
|
+
this.updateScheduled = true;
|
|
2319
|
+
microtask.read(this.scheduleUpdate);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
clearAllSnapshots() {
|
|
2323
|
+
this.nodes.forEach(clearSnapshot);
|
|
2324
|
+
this.sharedNodes.forEach(removeLeadSnapshots);
|
|
2325
|
+
}
|
|
2326
|
+
scheduleUpdateProjection() {
|
|
2327
|
+
if (!this.projectionUpdateScheduled) {
|
|
2328
|
+
this.projectionUpdateScheduled = true;
|
|
2329
|
+
frame.preRender(this.updateProjection, false, true);
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
scheduleCheckAfterUnmount() {
|
|
2333
|
+
frame.postRender(() => {
|
|
2334
|
+
if (this.isLayoutDirty) {
|
|
2335
|
+
this.root.didUpdate();
|
|
2336
|
+
} else {
|
|
2337
|
+
this.root.checkUpdateFailed();
|
|
2338
|
+
}
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Update measurements
|
|
2343
|
+
*/
|
|
2344
|
+
updateSnapshot() {
|
|
2345
|
+
if (this.snapshot || !this.instance)
|
|
2346
|
+
return;
|
|
2347
|
+
this.snapshot = this.measure();
|
|
2348
|
+
}
|
|
2349
|
+
updateLayout() {
|
|
2350
|
+
if (!this.instance)
|
|
2351
|
+
return;
|
|
2352
|
+
this.updateScroll();
|
|
2353
|
+
if (!(this.options.alwaysMeasureLayout && this.isLead()) && !this.isLayoutDirty) {
|
|
2354
|
+
return;
|
|
2355
|
+
}
|
|
2356
|
+
if (this.resumeFrom && !this.resumeFrom.instance) {
|
|
2357
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
2358
|
+
const node = this.path[i];
|
|
2359
|
+
node.updateScroll();
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
const prevLayout = this.layout;
|
|
2363
|
+
this.layout = this.measure(false);
|
|
2364
|
+
this.layoutCorrected = createBox();
|
|
2365
|
+
this.isLayoutDirty = false;
|
|
2366
|
+
this.projectionDelta = void 0;
|
|
2367
|
+
this.notifyListeners("measure", this.layout.layoutBox);
|
|
2368
|
+
const { visualElement } = this.options;
|
|
2369
|
+
visualElement && visualElement.notify("LayoutMeasure", this.layout.layoutBox, prevLayout ? prevLayout.layoutBox : void 0);
|
|
2370
|
+
}
|
|
2371
|
+
updateScroll(phase = "measure") {
|
|
2372
|
+
let needsMeasurement = Boolean(this.options.layoutScroll && this.instance);
|
|
2373
|
+
if (this.scroll && this.scroll.animationId === this.root.animationId && this.scroll.phase === phase) {
|
|
2374
|
+
needsMeasurement = false;
|
|
2375
|
+
}
|
|
2376
|
+
if (needsMeasurement) {
|
|
2377
|
+
const isRoot = checkIsScrollRoot(this.instance);
|
|
2378
|
+
this.scroll = {
|
|
2379
|
+
animationId: this.root.animationId,
|
|
2380
|
+
phase,
|
|
2381
|
+
isRoot,
|
|
2382
|
+
offset: measureScroll(this.instance),
|
|
2383
|
+
wasRoot: this.scroll ? this.scroll.isRoot : isRoot
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
resetTransform() {
|
|
2388
|
+
if (!resetTransform)
|
|
2389
|
+
return;
|
|
2390
|
+
const isResetRequested = this.isLayoutDirty || this.shouldResetTransform || this.options.alwaysMeasureLayout;
|
|
2391
|
+
const hasProjection = this.projectionDelta && !isDeltaZero(this.projectionDelta);
|
|
2392
|
+
const transformTemplate = this.getTransformTemplate();
|
|
2393
|
+
const transformTemplateValue = transformTemplate ? transformTemplate(this.latestValues, "") : void 0;
|
|
2394
|
+
const transformTemplateHasChanged = transformTemplateValue !== this.prevTransformTemplateValue;
|
|
2395
|
+
if (isResetRequested && (hasProjection || hasTransform(this.latestValues) || transformTemplateHasChanged)) {
|
|
2396
|
+
resetTransform(this.instance, transformTemplateValue);
|
|
2397
|
+
this.shouldResetTransform = false;
|
|
2398
|
+
this.scheduleRender();
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
measure(removeTransform = true) {
|
|
2402
|
+
const pageBox = this.measurePageBox();
|
|
2403
|
+
let layoutBox = this.removeElementScroll(pageBox);
|
|
2404
|
+
if (removeTransform) {
|
|
2405
|
+
layoutBox = this.removeTransform(layoutBox);
|
|
2406
|
+
}
|
|
2407
|
+
roundBox(layoutBox);
|
|
2408
|
+
return {
|
|
2409
|
+
animationId: this.root.animationId,
|
|
2410
|
+
measuredBox: pageBox,
|
|
2411
|
+
layoutBox,
|
|
2412
|
+
latestValues: {},
|
|
2413
|
+
source: this.id
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
measurePageBox() {
|
|
2417
|
+
var _a;
|
|
2418
|
+
const { visualElement } = this.options;
|
|
2419
|
+
if (!visualElement)
|
|
2420
|
+
return createBox();
|
|
2421
|
+
const box = visualElement.measureViewportBox();
|
|
2422
|
+
const wasInScrollRoot = ((_a = this.scroll) === null || _a === void 0 ? void 0 : _a.wasRoot) || this.path.some(checkNodeWasScrollRoot);
|
|
2423
|
+
if (!wasInScrollRoot) {
|
|
2424
|
+
const { scroll } = this.root;
|
|
2425
|
+
if (scroll) {
|
|
2426
|
+
translateAxis(box.x, scroll.offset.x);
|
|
2427
|
+
translateAxis(box.y, scroll.offset.y);
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
return box;
|
|
2431
|
+
}
|
|
2432
|
+
removeElementScroll(box) {
|
|
2433
|
+
var _a;
|
|
2434
|
+
const boxWithoutScroll = createBox();
|
|
2435
|
+
copyBoxInto(boxWithoutScroll, box);
|
|
2436
|
+
if ((_a = this.scroll) === null || _a === void 0 ? void 0 : _a.wasRoot) {
|
|
2437
|
+
return boxWithoutScroll;
|
|
2438
|
+
}
|
|
2439
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
2440
|
+
const node = this.path[i];
|
|
2441
|
+
const { scroll, options } = node;
|
|
2442
|
+
if (node !== this.root && scroll && options.layoutScroll) {
|
|
2443
|
+
if (scroll.wasRoot) {
|
|
2444
|
+
copyBoxInto(boxWithoutScroll, box);
|
|
2445
|
+
}
|
|
2446
|
+
translateAxis(boxWithoutScroll.x, scroll.offset.x);
|
|
2447
|
+
translateAxis(boxWithoutScroll.y, scroll.offset.y);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
return boxWithoutScroll;
|
|
2451
|
+
}
|
|
2452
|
+
applyTransform(box, transformOnly = false) {
|
|
2453
|
+
const withTransforms = createBox();
|
|
2454
|
+
copyBoxInto(withTransforms, box);
|
|
2455
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
2456
|
+
const node = this.path[i];
|
|
2457
|
+
if (!transformOnly && node.options.layoutScroll && node.scroll && node !== node.root) {
|
|
2458
|
+
transformBox(withTransforms, {
|
|
2459
|
+
x: -node.scroll.offset.x,
|
|
2460
|
+
y: -node.scroll.offset.y
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2463
|
+
if (!hasTransform(node.latestValues))
|
|
2464
|
+
continue;
|
|
2465
|
+
transformBox(withTransforms, node.latestValues);
|
|
2466
|
+
}
|
|
2467
|
+
if (hasTransform(this.latestValues)) {
|
|
2468
|
+
transformBox(withTransforms, this.latestValues);
|
|
2469
|
+
}
|
|
2470
|
+
return withTransforms;
|
|
2471
|
+
}
|
|
2472
|
+
removeTransform(box) {
|
|
2473
|
+
const boxWithoutTransform = createBox();
|
|
2474
|
+
copyBoxInto(boxWithoutTransform, box);
|
|
2475
|
+
for (let i = 0; i < this.path.length; i++) {
|
|
2476
|
+
const node = this.path[i];
|
|
2477
|
+
if (!node.instance)
|
|
2478
|
+
continue;
|
|
2479
|
+
if (!hasTransform(node.latestValues))
|
|
2480
|
+
continue;
|
|
2481
|
+
hasScale(node.latestValues) && node.updateSnapshot();
|
|
2482
|
+
const sourceBox = createBox();
|
|
2483
|
+
const nodeBox = node.measurePageBox();
|
|
2484
|
+
copyBoxInto(sourceBox, nodeBox);
|
|
2485
|
+
removeBoxTransforms(boxWithoutTransform, node.latestValues, node.snapshot ? node.snapshot.layoutBox : void 0, sourceBox);
|
|
2486
|
+
}
|
|
2487
|
+
if (hasTransform(this.latestValues)) {
|
|
2488
|
+
removeBoxTransforms(boxWithoutTransform, this.latestValues);
|
|
2489
|
+
}
|
|
2490
|
+
return boxWithoutTransform;
|
|
2491
|
+
}
|
|
2492
|
+
setTargetDelta(delta) {
|
|
2493
|
+
this.targetDelta = delta;
|
|
2494
|
+
this.root.scheduleUpdateProjection();
|
|
2495
|
+
this.isProjectionDirty = true;
|
|
2496
|
+
}
|
|
2497
|
+
setOptions(options) {
|
|
2498
|
+
this.options = {
|
|
2499
|
+
...this.options,
|
|
2500
|
+
...options,
|
|
2501
|
+
crossfade: options.crossfade !== void 0 ? options.crossfade : true
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
clearMeasurements() {
|
|
2505
|
+
this.scroll = void 0;
|
|
2506
|
+
this.layout = void 0;
|
|
2507
|
+
this.snapshot = void 0;
|
|
2508
|
+
this.prevTransformTemplateValue = void 0;
|
|
2509
|
+
this.targetDelta = void 0;
|
|
2510
|
+
this.target = void 0;
|
|
2511
|
+
this.isLayoutDirty = false;
|
|
2512
|
+
}
|
|
2513
|
+
forceRelativeParentToResolveTarget() {
|
|
2514
|
+
if (!this.relativeParent)
|
|
2515
|
+
return;
|
|
2516
|
+
if (this.relativeParent.resolvedRelativeTargetAt !== frameData.timestamp) {
|
|
2517
|
+
this.relativeParent.resolveTargetDelta(true);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
resolveTargetDelta(forceRecalculation = false) {
|
|
2521
|
+
var _a;
|
|
2522
|
+
const lead = this.getLead();
|
|
2523
|
+
this.isProjectionDirty || (this.isProjectionDirty = lead.isProjectionDirty);
|
|
2524
|
+
this.isTransformDirty || (this.isTransformDirty = lead.isTransformDirty);
|
|
2525
|
+
this.isSharedProjectionDirty || (this.isSharedProjectionDirty = lead.isSharedProjectionDirty);
|
|
2526
|
+
const isShared = Boolean(this.resumingFrom) || this !== lead;
|
|
2527
|
+
const canSkip = !(forceRecalculation || isShared && this.isSharedProjectionDirty || this.isProjectionDirty || ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isProjectionDirty) || this.attemptToResolveRelativeTarget || this.root.updateBlockedByResize);
|
|
2528
|
+
if (canSkip)
|
|
2529
|
+
return;
|
|
2530
|
+
const { layout: layout2, layoutId } = this.options;
|
|
2531
|
+
if (!this.layout || !(layout2 || layoutId))
|
|
2532
|
+
return;
|
|
2533
|
+
this.resolvedRelativeTargetAt = frameData.timestamp;
|
|
2534
|
+
if (!this.targetDelta && !this.relativeTarget) {
|
|
2535
|
+
const relativeParent = this.getClosestProjectingParent();
|
|
2536
|
+
if (relativeParent && relativeParent.layout && this.animationProgress !== 1) {
|
|
2537
|
+
this.relativeParent = relativeParent;
|
|
2538
|
+
this.forceRelativeParentToResolveTarget();
|
|
2539
|
+
this.relativeTarget = createBox();
|
|
2540
|
+
this.relativeTargetOrigin = createBox();
|
|
2541
|
+
calcRelativePosition(this.relativeTargetOrigin, this.layout.layoutBox, relativeParent.layout.layoutBox);
|
|
2542
|
+
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
2543
|
+
} else {
|
|
2544
|
+
this.relativeParent = this.relativeTarget = void 0;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
if (!this.relativeTarget && !this.targetDelta)
|
|
2548
|
+
return;
|
|
2549
|
+
if (!this.target) {
|
|
2550
|
+
this.target = createBox();
|
|
2551
|
+
this.targetWithTransforms = createBox();
|
|
2552
|
+
}
|
|
2553
|
+
if (this.relativeTarget && this.relativeTargetOrigin && this.relativeParent && this.relativeParent.target) {
|
|
2554
|
+
this.forceRelativeParentToResolveTarget();
|
|
2555
|
+
calcRelativeBox(this.target, this.relativeTarget, this.relativeParent.target);
|
|
2556
|
+
} else if (this.targetDelta) {
|
|
2557
|
+
if (Boolean(this.resumingFrom)) {
|
|
2558
|
+
this.target = this.applyTransform(this.layout.layoutBox);
|
|
2559
|
+
} else {
|
|
2560
|
+
copyBoxInto(this.target, this.layout.layoutBox);
|
|
2561
|
+
}
|
|
2562
|
+
applyBoxDelta(this.target, this.targetDelta);
|
|
2563
|
+
} else {
|
|
2564
|
+
copyBoxInto(this.target, this.layout.layoutBox);
|
|
2565
|
+
}
|
|
2566
|
+
if (this.attemptToResolveRelativeTarget) {
|
|
2567
|
+
this.attemptToResolveRelativeTarget = false;
|
|
2568
|
+
const relativeParent = this.getClosestProjectingParent();
|
|
2569
|
+
if (relativeParent && Boolean(relativeParent.resumingFrom) === Boolean(this.resumingFrom) && !relativeParent.options.layoutScroll && relativeParent.target && this.animationProgress !== 1) {
|
|
2570
|
+
this.relativeParent = relativeParent;
|
|
2571
|
+
this.forceRelativeParentToResolveTarget();
|
|
2572
|
+
this.relativeTarget = createBox();
|
|
2573
|
+
this.relativeTargetOrigin = createBox();
|
|
2574
|
+
calcRelativePosition(this.relativeTargetOrigin, this.target, relativeParent.target);
|
|
2575
|
+
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
2576
|
+
} else {
|
|
2577
|
+
this.relativeParent = this.relativeTarget = void 0;
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
if (isDebug) {
|
|
2581
|
+
metrics.resolvedTargetDeltas++;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
getClosestProjectingParent() {
|
|
2585
|
+
if (!this.parent || hasScale(this.parent.latestValues) || has2DTranslate(this.parent.latestValues)) {
|
|
2586
|
+
return void 0;
|
|
2587
|
+
}
|
|
2588
|
+
if (this.parent.isProjecting()) {
|
|
2589
|
+
return this.parent;
|
|
2590
|
+
} else {
|
|
2591
|
+
return this.parent.getClosestProjectingParent();
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
isProjecting() {
|
|
2595
|
+
return Boolean((this.relativeTarget || this.targetDelta || this.options.layoutRoot) && this.layout);
|
|
2596
|
+
}
|
|
2597
|
+
calcProjection() {
|
|
2598
|
+
var _a;
|
|
2599
|
+
const lead = this.getLead();
|
|
2600
|
+
const isShared = Boolean(this.resumingFrom) || this !== lead;
|
|
2601
|
+
let canSkip = true;
|
|
2602
|
+
if (this.isProjectionDirty || ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isProjectionDirty)) {
|
|
2603
|
+
canSkip = false;
|
|
2604
|
+
}
|
|
2605
|
+
if (isShared && (this.isSharedProjectionDirty || this.isTransformDirty)) {
|
|
2606
|
+
canSkip = false;
|
|
2607
|
+
}
|
|
2608
|
+
if (this.resolvedRelativeTargetAt === frameData.timestamp) {
|
|
2609
|
+
canSkip = false;
|
|
2610
|
+
}
|
|
2611
|
+
if (canSkip)
|
|
2612
|
+
return;
|
|
2613
|
+
const { layout: layout2, layoutId } = this.options;
|
|
2614
|
+
this.isTreeAnimating = Boolean(this.parent && this.parent.isTreeAnimating || this.currentAnimation || this.pendingAnimation);
|
|
2615
|
+
if (!this.isTreeAnimating) {
|
|
2616
|
+
this.targetDelta = this.relativeTarget = void 0;
|
|
2617
|
+
}
|
|
2618
|
+
if (!this.layout || !(layout2 || layoutId))
|
|
2619
|
+
return;
|
|
2620
|
+
copyBoxInto(this.layoutCorrected, this.layout.layoutBox);
|
|
2621
|
+
const prevTreeScaleX = this.treeScale.x;
|
|
2622
|
+
const prevTreeScaleY = this.treeScale.y;
|
|
2623
|
+
applyTreeDeltas(this.layoutCorrected, this.treeScale, this.path, isShared);
|
|
2624
|
+
if (lead.layout && !lead.target && (this.treeScale.x !== 1 || this.treeScale.y !== 1)) {
|
|
2625
|
+
lead.target = lead.layout.layoutBox;
|
|
2626
|
+
lead.targetWithTransforms = createBox();
|
|
2627
|
+
}
|
|
2628
|
+
const { target } = lead;
|
|
2629
|
+
if (!target) {
|
|
2630
|
+
if (this.prevProjectionDelta) {
|
|
2631
|
+
this.createProjectionDeltas();
|
|
2632
|
+
this.scheduleRender();
|
|
2633
|
+
}
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
if (!this.projectionDelta || !this.prevProjectionDelta) {
|
|
2637
|
+
this.createProjectionDeltas();
|
|
2638
|
+
} else {
|
|
2639
|
+
copyAxisDeltaInto(this.prevProjectionDelta.x, this.projectionDelta.x);
|
|
2640
|
+
copyAxisDeltaInto(this.prevProjectionDelta.y, this.projectionDelta.y);
|
|
2641
|
+
}
|
|
2642
|
+
calcBoxDelta(this.projectionDelta, this.layoutCorrected, target, this.latestValues);
|
|
2643
|
+
if (this.treeScale.x !== prevTreeScaleX || this.treeScale.y !== prevTreeScaleY || !axisDeltaEquals(this.projectionDelta.x, this.prevProjectionDelta.x) || !axisDeltaEquals(this.projectionDelta.y, this.prevProjectionDelta.y)) {
|
|
2644
|
+
this.hasProjected = true;
|
|
2645
|
+
this.scheduleRender();
|
|
2646
|
+
this.notifyListeners("projectionUpdate", target);
|
|
2647
|
+
}
|
|
2648
|
+
if (isDebug) {
|
|
2649
|
+
metrics.recalculatedProjection++;
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
hide() {
|
|
2653
|
+
this.isVisible = false;
|
|
2654
|
+
}
|
|
2655
|
+
show() {
|
|
2656
|
+
this.isVisible = true;
|
|
2657
|
+
}
|
|
2658
|
+
scheduleRender(notifyAll = true) {
|
|
2659
|
+
var _a;
|
|
2660
|
+
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.scheduleRender();
|
|
2661
|
+
if (notifyAll) {
|
|
2662
|
+
const stack = this.getStack();
|
|
2663
|
+
stack && stack.scheduleRender();
|
|
2664
|
+
}
|
|
2665
|
+
if (this.resumingFrom && !this.resumingFrom.instance) {
|
|
2666
|
+
this.resumingFrom = void 0;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
createProjectionDeltas() {
|
|
2670
|
+
this.prevProjectionDelta = createDelta();
|
|
2671
|
+
this.projectionDelta = createDelta();
|
|
2672
|
+
this.projectionDeltaWithTransform = createDelta();
|
|
2673
|
+
}
|
|
2674
|
+
setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
|
|
2675
|
+
const snapshot = this.snapshot;
|
|
2676
|
+
const snapshotLatestValues = snapshot ? snapshot.latestValues : {};
|
|
2677
|
+
const mixedValues = { ...this.latestValues };
|
|
2678
|
+
const targetDelta = createDelta();
|
|
2679
|
+
if (!this.relativeParent || !this.relativeParent.options.layoutRoot) {
|
|
2680
|
+
this.relativeTarget = this.relativeTargetOrigin = void 0;
|
|
2681
|
+
}
|
|
2682
|
+
this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
|
|
2683
|
+
const relativeLayout = createBox();
|
|
2684
|
+
const snapshotSource = snapshot ? snapshot.source : void 0;
|
|
2685
|
+
const layoutSource = this.layout ? this.layout.source : void 0;
|
|
2686
|
+
const isSharedLayoutAnimation = snapshotSource !== layoutSource;
|
|
2687
|
+
const stack = this.getStack();
|
|
2688
|
+
const isOnlyMember = !stack || stack.members.length <= 1;
|
|
2689
|
+
const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation && !isOnlyMember && this.options.crossfade === true && !this.path.some(hasOpacityCrossfade));
|
|
2690
|
+
this.animationProgress = 0;
|
|
2691
|
+
let prevRelativeTarget;
|
|
2692
|
+
this.mixTargetDelta = (latest) => {
|
|
2693
|
+
const progress2 = latest / 1e3;
|
|
2694
|
+
mixAxisDelta(targetDelta.x, delta.x, progress2);
|
|
2695
|
+
mixAxisDelta(targetDelta.y, delta.y, progress2);
|
|
2696
|
+
this.setTargetDelta(targetDelta);
|
|
2697
|
+
if (this.relativeTarget && this.relativeTargetOrigin && this.layout && this.relativeParent && this.relativeParent.layout) {
|
|
2698
|
+
calcRelativePosition(relativeLayout, this.layout.layoutBox, this.relativeParent.layout.layoutBox);
|
|
2699
|
+
mixBox(this.relativeTarget, this.relativeTargetOrigin, relativeLayout, progress2);
|
|
2700
|
+
if (prevRelativeTarget && boxEquals(this.relativeTarget, prevRelativeTarget)) {
|
|
2701
|
+
this.isProjectionDirty = false;
|
|
2702
|
+
}
|
|
2703
|
+
if (!prevRelativeTarget)
|
|
2704
|
+
prevRelativeTarget = createBox();
|
|
2705
|
+
copyBoxInto(prevRelativeTarget, this.relativeTarget);
|
|
2706
|
+
}
|
|
2707
|
+
if (isSharedLayoutAnimation) {
|
|
2708
|
+
this.animationValues = mixedValues;
|
|
2709
|
+
mixValues(mixedValues, snapshotLatestValues, this.latestValues, progress2, shouldCrossfadeOpacity, isOnlyMember);
|
|
2710
|
+
}
|
|
2711
|
+
this.root.scheduleUpdateProjection();
|
|
2712
|
+
this.scheduleRender();
|
|
2713
|
+
this.animationProgress = progress2;
|
|
2714
|
+
};
|
|
2715
|
+
this.mixTargetDelta(this.options.layoutRoot ? 1e3 : 0);
|
|
2716
|
+
}
|
|
2717
|
+
startAnimation(options) {
|
|
2718
|
+
this.notifyListeners("animationStart");
|
|
2719
|
+
this.currentAnimation && this.currentAnimation.stop();
|
|
2720
|
+
if (this.resumingFrom && this.resumingFrom.currentAnimation) {
|
|
2721
|
+
this.resumingFrom.currentAnimation.stop();
|
|
2722
|
+
}
|
|
2723
|
+
if (this.pendingAnimation) {
|
|
2724
|
+
cancelFrame(this.pendingAnimation);
|
|
2725
|
+
this.pendingAnimation = void 0;
|
|
2726
|
+
}
|
|
2727
|
+
this.pendingAnimation = frame.update(() => {
|
|
2728
|
+
globalProjectionState.hasAnimatedSinceResize = true;
|
|
2729
|
+
this.currentAnimation = animateSingleValue(0, animationTarget, {
|
|
2730
|
+
...options,
|
|
2731
|
+
onUpdate: (latest) => {
|
|
2732
|
+
this.mixTargetDelta(latest);
|
|
2733
|
+
options.onUpdate && options.onUpdate(latest);
|
|
2734
|
+
},
|
|
2735
|
+
onComplete: () => {
|
|
2736
|
+
options.onComplete && options.onComplete();
|
|
2737
|
+
this.completeAnimation();
|
|
2738
|
+
}
|
|
2739
|
+
});
|
|
2740
|
+
if (this.resumingFrom) {
|
|
2741
|
+
this.resumingFrom.currentAnimation = this.currentAnimation;
|
|
2742
|
+
}
|
|
2743
|
+
this.pendingAnimation = void 0;
|
|
2744
|
+
});
|
|
2745
|
+
}
|
|
2746
|
+
completeAnimation() {
|
|
2747
|
+
if (this.resumingFrom) {
|
|
2748
|
+
this.resumingFrom.currentAnimation = void 0;
|
|
2749
|
+
this.resumingFrom.preserveOpacity = void 0;
|
|
2750
|
+
}
|
|
2751
|
+
const stack = this.getStack();
|
|
2752
|
+
stack && stack.exitAnimationComplete();
|
|
2753
|
+
this.resumingFrom = this.currentAnimation = this.animationValues = void 0;
|
|
2754
|
+
this.notifyListeners("animationComplete");
|
|
2755
|
+
}
|
|
2756
|
+
finishAnimation() {
|
|
2757
|
+
if (this.currentAnimation) {
|
|
2758
|
+
this.mixTargetDelta && this.mixTargetDelta(animationTarget);
|
|
2759
|
+
this.currentAnimation.stop();
|
|
2760
|
+
}
|
|
2761
|
+
this.completeAnimation();
|
|
2762
|
+
}
|
|
2763
|
+
applyTransformsToTarget() {
|
|
2764
|
+
const lead = this.getLead();
|
|
2765
|
+
let { targetWithTransforms, target, layout: layout2, latestValues } = lead;
|
|
2766
|
+
if (!targetWithTransforms || !target || !layout2)
|
|
2767
|
+
return;
|
|
2768
|
+
if (this !== lead && this.layout && layout2 && shouldAnimatePositionOnly(this.options.animationType, this.layout.layoutBox, layout2.layoutBox)) {
|
|
2769
|
+
target = this.target || createBox();
|
|
2770
|
+
const xLength = calcLength(this.layout.layoutBox.x);
|
|
2771
|
+
target.x.min = lead.target.x.min;
|
|
2772
|
+
target.x.max = target.x.min + xLength;
|
|
2773
|
+
const yLength = calcLength(this.layout.layoutBox.y);
|
|
2774
|
+
target.y.min = lead.target.y.min;
|
|
2775
|
+
target.y.max = target.y.min + yLength;
|
|
2776
|
+
}
|
|
2777
|
+
copyBoxInto(targetWithTransforms, target);
|
|
2778
|
+
transformBox(targetWithTransforms, latestValues);
|
|
2779
|
+
calcBoxDelta(this.projectionDeltaWithTransform, this.layoutCorrected, targetWithTransforms, latestValues);
|
|
2780
|
+
}
|
|
2781
|
+
registerSharedNode(layoutId, node) {
|
|
2782
|
+
if (!this.sharedNodes.has(layoutId)) {
|
|
2783
|
+
this.sharedNodes.set(layoutId, new NodeStack());
|
|
2784
|
+
}
|
|
2785
|
+
const stack = this.sharedNodes.get(layoutId);
|
|
2786
|
+
stack.add(node);
|
|
2787
|
+
const config = node.options.initialPromotionConfig;
|
|
2788
|
+
node.promote({
|
|
2789
|
+
transition: config ? config.transition : void 0,
|
|
2790
|
+
preserveFollowOpacity: config && config.shouldPreserveFollowOpacity ? config.shouldPreserveFollowOpacity(node) : void 0
|
|
2791
|
+
});
|
|
2792
|
+
}
|
|
2793
|
+
isLead() {
|
|
2794
|
+
const stack = this.getStack();
|
|
2795
|
+
return stack ? stack.lead === this : true;
|
|
2796
|
+
}
|
|
2797
|
+
getLead() {
|
|
2798
|
+
var _a;
|
|
2799
|
+
const { layoutId } = this.options;
|
|
2800
|
+
return layoutId ? ((_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.lead) || this : this;
|
|
2801
|
+
}
|
|
2802
|
+
getPrevLead() {
|
|
2803
|
+
var _a;
|
|
2804
|
+
const { layoutId } = this.options;
|
|
2805
|
+
return layoutId ? (_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.prevLead : void 0;
|
|
2806
|
+
}
|
|
2807
|
+
getStack() {
|
|
2808
|
+
const { layoutId } = this.options;
|
|
2809
|
+
if (layoutId)
|
|
2810
|
+
return this.root.sharedNodes.get(layoutId);
|
|
2811
|
+
}
|
|
2812
|
+
promote({ needsReset, transition, preserveFollowOpacity } = {}) {
|
|
2813
|
+
const stack = this.getStack();
|
|
2814
|
+
if (stack)
|
|
2815
|
+
stack.promote(this, preserveFollowOpacity);
|
|
2816
|
+
if (needsReset) {
|
|
2817
|
+
this.projectionDelta = void 0;
|
|
2818
|
+
this.needsReset = true;
|
|
2819
|
+
}
|
|
2820
|
+
if (transition)
|
|
2821
|
+
this.setOptions({ transition });
|
|
2822
|
+
}
|
|
2823
|
+
relegate() {
|
|
2824
|
+
const stack = this.getStack();
|
|
2825
|
+
if (stack) {
|
|
2826
|
+
return stack.relegate(this);
|
|
2827
|
+
} else {
|
|
2828
|
+
return false;
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
resetSkewAndRotation() {
|
|
2832
|
+
const { visualElement } = this.options;
|
|
2833
|
+
if (!visualElement)
|
|
2834
|
+
return;
|
|
2835
|
+
let hasDistortingTransform = false;
|
|
2836
|
+
const { latestValues } = visualElement;
|
|
2837
|
+
if (latestValues.z || latestValues.rotate || latestValues.rotateX || latestValues.rotateY || latestValues.rotateZ || latestValues.skewX || latestValues.skewY) {
|
|
2838
|
+
hasDistortingTransform = true;
|
|
2839
|
+
}
|
|
2840
|
+
if (!hasDistortingTransform)
|
|
2841
|
+
return;
|
|
2842
|
+
const resetValues = {};
|
|
2843
|
+
if (latestValues.z) {
|
|
2844
|
+
resetDistortingTransform("z", visualElement, resetValues, this.animationValues);
|
|
2845
|
+
}
|
|
2846
|
+
for (let i = 0; i < transformAxes.length; i++) {
|
|
2847
|
+
resetDistortingTransform(`rotate${transformAxes[i]}`, visualElement, resetValues, this.animationValues);
|
|
2848
|
+
resetDistortingTransform(`skew${transformAxes[i]}`, visualElement, resetValues, this.animationValues);
|
|
2849
|
+
}
|
|
2850
|
+
visualElement.render();
|
|
2851
|
+
for (const key in resetValues) {
|
|
2852
|
+
visualElement.setStaticValue(key, resetValues[key]);
|
|
2853
|
+
if (this.animationValues) {
|
|
2854
|
+
this.animationValues[key] = resetValues[key];
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
visualElement.scheduleRender();
|
|
2858
|
+
}
|
|
2859
|
+
getProjectionStyles(styleProp) {
|
|
2860
|
+
var _a, _b;
|
|
2861
|
+
if (!this.instance || this.isSVG)
|
|
2862
|
+
return void 0;
|
|
2863
|
+
if (!this.isVisible) {
|
|
2864
|
+
return hiddenVisibility;
|
|
2865
|
+
}
|
|
2866
|
+
const styles2 = {
|
|
2867
|
+
visibility: ""
|
|
2868
|
+
};
|
|
2869
|
+
const transformTemplate = this.getTransformTemplate();
|
|
2870
|
+
if (this.needsReset) {
|
|
2871
|
+
this.needsReset = false;
|
|
2872
|
+
styles2.opacity = "";
|
|
2873
|
+
styles2.pointerEvents = resolveMotionValue(styleProp === null || styleProp === void 0 ? void 0 : styleProp.pointerEvents) || "";
|
|
2874
|
+
styles2.transform = transformTemplate ? transformTemplate(this.latestValues, "") : "none";
|
|
2875
|
+
return styles2;
|
|
2876
|
+
}
|
|
2877
|
+
const lead = this.getLead();
|
|
2878
|
+
if (!this.projectionDelta || !this.layout || !lead.target) {
|
|
2879
|
+
const emptyStyles = {};
|
|
2880
|
+
if (this.options.layoutId) {
|
|
2881
|
+
emptyStyles.opacity = this.latestValues.opacity !== void 0 ? this.latestValues.opacity : 1;
|
|
2882
|
+
emptyStyles.pointerEvents = resolveMotionValue(styleProp === null || styleProp === void 0 ? void 0 : styleProp.pointerEvents) || "";
|
|
2883
|
+
}
|
|
2884
|
+
if (this.hasProjected && !hasTransform(this.latestValues)) {
|
|
2885
|
+
emptyStyles.transform = transformTemplate ? transformTemplate({}, "") : "none";
|
|
2886
|
+
this.hasProjected = false;
|
|
2887
|
+
}
|
|
2888
|
+
return emptyStyles;
|
|
2889
|
+
}
|
|
2890
|
+
const valuesToRender = lead.animationValues || lead.latestValues;
|
|
2891
|
+
this.applyTransformsToTarget();
|
|
2892
|
+
styles2.transform = buildProjectionTransform(this.projectionDeltaWithTransform, this.treeScale, valuesToRender);
|
|
2893
|
+
if (transformTemplate) {
|
|
2894
|
+
styles2.transform = transformTemplate(valuesToRender, styles2.transform);
|
|
2895
|
+
}
|
|
2896
|
+
const { x, y } = this.projectionDelta;
|
|
2897
|
+
styles2.transformOrigin = `${x.origin * 100}% ${y.origin * 100}% 0`;
|
|
2898
|
+
if (lead.animationValues) {
|
|
2899
|
+
styles2.opacity = lead === this ? (_b = (_a = valuesToRender.opacity) !== null && _a !== void 0 ? _a : this.latestValues.opacity) !== null && _b !== void 0 ? _b : 1 : this.preserveOpacity ? this.latestValues.opacity : valuesToRender.opacityExit;
|
|
2900
|
+
} else {
|
|
2901
|
+
styles2.opacity = lead === this ? valuesToRender.opacity !== void 0 ? valuesToRender.opacity : "" : valuesToRender.opacityExit !== void 0 ? valuesToRender.opacityExit : 0;
|
|
2902
|
+
}
|
|
2903
|
+
for (const key in scaleCorrectors) {
|
|
2904
|
+
if (valuesToRender[key] === void 0)
|
|
2905
|
+
continue;
|
|
2906
|
+
const { correct, applyTo } = scaleCorrectors[key];
|
|
2907
|
+
const corrected = styles2.transform === "none" ? valuesToRender[key] : correct(valuesToRender[key], lead);
|
|
2908
|
+
if (applyTo) {
|
|
2909
|
+
const num = applyTo.length;
|
|
2910
|
+
for (let i = 0; i < num; i++) {
|
|
2911
|
+
styles2[applyTo[i]] = corrected;
|
|
2912
|
+
}
|
|
2913
|
+
} else {
|
|
2914
|
+
styles2[key] = corrected;
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
if (this.options.layoutId) {
|
|
2918
|
+
styles2.pointerEvents = lead === this ? resolveMotionValue(styleProp === null || styleProp === void 0 ? void 0 : styleProp.pointerEvents) || "" : "none";
|
|
2919
|
+
}
|
|
2920
|
+
return styles2;
|
|
2921
|
+
}
|
|
2922
|
+
clearSnapshot() {
|
|
2923
|
+
this.resumeFrom = this.snapshot = void 0;
|
|
2924
|
+
}
|
|
2925
|
+
// Only run on root
|
|
2926
|
+
resetTree() {
|
|
2927
|
+
this.root.nodes.forEach((node) => {
|
|
2928
|
+
var _a;
|
|
2929
|
+
return (_a = node.currentAnimation) === null || _a === void 0 ? void 0 : _a.stop();
|
|
2930
|
+
});
|
|
2931
|
+
this.root.nodes.forEach(clearMeasurements);
|
|
2932
|
+
this.root.sharedNodes.clear();
|
|
2933
|
+
}
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
function updateLayout(node) {
|
|
2937
|
+
node.updateLayout();
|
|
2938
|
+
}
|
|
2939
|
+
function notifyLayoutUpdate(node) {
|
|
2940
|
+
var _a;
|
|
2941
|
+
const snapshot = ((_a = node.resumeFrom) === null || _a === void 0 ? void 0 : _a.snapshot) || node.snapshot;
|
|
2942
|
+
if (node.isLead() && node.layout && snapshot && node.hasListeners("didUpdate")) {
|
|
2943
|
+
const { layoutBox: layout2, measuredBox: measuredLayout } = node.layout;
|
|
2944
|
+
const { animationType } = node.options;
|
|
2945
|
+
const isShared = snapshot.source !== node.layout.source;
|
|
2946
|
+
if (animationType === "size") {
|
|
2947
|
+
eachAxis((axis) => {
|
|
2948
|
+
const axisSnapshot = isShared ? snapshot.measuredBox[axis] : snapshot.layoutBox[axis];
|
|
2949
|
+
const length = calcLength(axisSnapshot);
|
|
2950
|
+
axisSnapshot.min = layout2[axis].min;
|
|
2951
|
+
axisSnapshot.max = axisSnapshot.min + length;
|
|
2952
|
+
});
|
|
2953
|
+
} else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout2)) {
|
|
2954
|
+
eachAxis((axis) => {
|
|
2955
|
+
const axisSnapshot = isShared ? snapshot.measuredBox[axis] : snapshot.layoutBox[axis];
|
|
2956
|
+
const length = calcLength(layout2[axis]);
|
|
2957
|
+
axisSnapshot.max = axisSnapshot.min + length;
|
|
2958
|
+
if (node.relativeTarget && !node.currentAnimation) {
|
|
2959
|
+
node.isProjectionDirty = true;
|
|
2960
|
+
node.relativeTarget[axis].max = node.relativeTarget[axis].min + length;
|
|
2961
|
+
}
|
|
2962
|
+
});
|
|
2963
|
+
}
|
|
2964
|
+
const layoutDelta = createDelta();
|
|
2965
|
+
calcBoxDelta(layoutDelta, layout2, snapshot.layoutBox);
|
|
2966
|
+
const visualDelta = createDelta();
|
|
2967
|
+
if (isShared) {
|
|
2968
|
+
calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
|
|
2969
|
+
} else {
|
|
2970
|
+
calcBoxDelta(visualDelta, layout2, snapshot.layoutBox);
|
|
2971
|
+
}
|
|
2972
|
+
const hasLayoutChanged = !isDeltaZero(layoutDelta);
|
|
2973
|
+
let hasRelativeTargetChanged = false;
|
|
2974
|
+
if (!node.resumeFrom) {
|
|
2975
|
+
const relativeParent = node.getClosestProjectingParent();
|
|
2976
|
+
if (relativeParent && !relativeParent.resumeFrom) {
|
|
2977
|
+
const { snapshot: parentSnapshot, layout: parentLayout } = relativeParent;
|
|
2978
|
+
if (parentSnapshot && parentLayout) {
|
|
2979
|
+
const relativeSnapshot = createBox();
|
|
2980
|
+
calcRelativePosition(relativeSnapshot, snapshot.layoutBox, parentSnapshot.layoutBox);
|
|
2981
|
+
const relativeLayout = createBox();
|
|
2982
|
+
calcRelativePosition(relativeLayout, layout2, parentLayout.layoutBox);
|
|
2983
|
+
if (!boxEqualsRounded(relativeSnapshot, relativeLayout)) {
|
|
2984
|
+
hasRelativeTargetChanged = true;
|
|
2985
|
+
}
|
|
2986
|
+
if (relativeParent.options.layoutRoot) {
|
|
2987
|
+
node.relativeTarget = relativeLayout;
|
|
2988
|
+
node.relativeTargetOrigin = relativeSnapshot;
|
|
2989
|
+
node.relativeParent = relativeParent;
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
node.notifyListeners("didUpdate", {
|
|
2995
|
+
layout: layout2,
|
|
2996
|
+
snapshot,
|
|
2997
|
+
delta: visualDelta,
|
|
2998
|
+
layoutDelta,
|
|
2999
|
+
hasLayoutChanged,
|
|
3000
|
+
hasRelativeTargetChanged
|
|
3001
|
+
});
|
|
3002
|
+
} else if (node.isLead()) {
|
|
3003
|
+
const { onExitComplete } = node.options;
|
|
3004
|
+
onExitComplete && onExitComplete();
|
|
3005
|
+
}
|
|
3006
|
+
node.options.transition = void 0;
|
|
3007
|
+
}
|
|
3008
|
+
function propagateDirtyNodes(node) {
|
|
3009
|
+
if (isDebug) {
|
|
3010
|
+
metrics.totalNodes++;
|
|
3011
|
+
}
|
|
3012
|
+
if (!node.parent)
|
|
3013
|
+
return;
|
|
3014
|
+
if (!node.isProjecting()) {
|
|
3015
|
+
node.isProjectionDirty = node.parent.isProjectionDirty;
|
|
3016
|
+
}
|
|
3017
|
+
node.isSharedProjectionDirty || (node.isSharedProjectionDirty = Boolean(node.isProjectionDirty || node.parent.isProjectionDirty || node.parent.isSharedProjectionDirty));
|
|
3018
|
+
node.isTransformDirty || (node.isTransformDirty = node.parent.isTransformDirty);
|
|
3019
|
+
}
|
|
3020
|
+
function cleanDirtyNodes(node) {
|
|
3021
|
+
node.isProjectionDirty = node.isSharedProjectionDirty = node.isTransformDirty = false;
|
|
3022
|
+
}
|
|
3023
|
+
function clearSnapshot(node) {
|
|
3024
|
+
node.clearSnapshot();
|
|
3025
|
+
}
|
|
3026
|
+
function clearMeasurements(node) {
|
|
3027
|
+
node.clearMeasurements();
|
|
3028
|
+
}
|
|
3029
|
+
function clearIsLayoutDirty(node) {
|
|
3030
|
+
node.isLayoutDirty = false;
|
|
3031
|
+
}
|
|
3032
|
+
function resetTransformStyle(node) {
|
|
3033
|
+
const { visualElement } = node.options;
|
|
3034
|
+
if (visualElement && visualElement.getProps().onBeforeLayoutMeasure) {
|
|
3035
|
+
visualElement.notify("BeforeLayoutMeasure");
|
|
3036
|
+
}
|
|
3037
|
+
node.resetTransform();
|
|
3038
|
+
}
|
|
3039
|
+
function finishAnimation(node) {
|
|
3040
|
+
node.finishAnimation();
|
|
3041
|
+
node.targetDelta = node.relativeTarget = node.target = void 0;
|
|
3042
|
+
node.isProjectionDirty = true;
|
|
3043
|
+
}
|
|
3044
|
+
function resolveTargetDelta(node) {
|
|
3045
|
+
node.resolveTargetDelta();
|
|
3046
|
+
}
|
|
3047
|
+
function calcProjection(node) {
|
|
3048
|
+
node.calcProjection();
|
|
3049
|
+
}
|
|
3050
|
+
function resetSkewAndRotation(node) {
|
|
3051
|
+
node.resetSkewAndRotation();
|
|
3052
|
+
}
|
|
3053
|
+
function removeLeadSnapshots(stack) {
|
|
3054
|
+
stack.removeLeadSnapshot();
|
|
3055
|
+
}
|
|
3056
|
+
function mixAxisDelta(output, delta, p) {
|
|
3057
|
+
output.translate = mixNumber(delta.translate, 0, p);
|
|
3058
|
+
output.scale = mixNumber(delta.scale, 1, p);
|
|
3059
|
+
output.origin = delta.origin;
|
|
3060
|
+
output.originPoint = delta.originPoint;
|
|
3061
|
+
}
|
|
3062
|
+
function mixAxis(output, from, to, p) {
|
|
3063
|
+
output.min = mixNumber(from.min, to.min, p);
|
|
3064
|
+
output.max = mixNumber(from.max, to.max, p);
|
|
3065
|
+
}
|
|
3066
|
+
function mixBox(output, from, to, p) {
|
|
3067
|
+
mixAxis(output.x, from.x, to.x, p);
|
|
3068
|
+
mixAxis(output.y, from.y, to.y, p);
|
|
3069
|
+
}
|
|
3070
|
+
function hasOpacityCrossfade(node) {
|
|
3071
|
+
return node.animationValues && node.animationValues.opacityExit !== void 0;
|
|
3072
|
+
}
|
|
3073
|
+
const defaultLayoutTransition = {
|
|
3074
|
+
duration: 0.45,
|
|
3075
|
+
ease: [0.4, 0, 0.1, 1]
|
|
3076
|
+
};
|
|
3077
|
+
const userAgentContains = (string) => typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().includes(string);
|
|
3078
|
+
const roundPoint = userAgentContains("applewebkit/") && !userAgentContains("chrome/") ? Math.round : noop;
|
|
3079
|
+
function roundAxis(axis) {
|
|
3080
|
+
axis.min = roundPoint(axis.min);
|
|
3081
|
+
axis.max = roundPoint(axis.max);
|
|
3082
|
+
}
|
|
3083
|
+
function roundBox(box) {
|
|
3084
|
+
roundAxis(box.x);
|
|
3085
|
+
roundAxis(box.y);
|
|
3086
|
+
}
|
|
3087
|
+
function shouldAnimatePositionOnly(animationType, snapshot, layout2) {
|
|
3088
|
+
return animationType === "position" || animationType === "preserve-aspect" && !isNear(aspectRatio(snapshot), aspectRatio(layout2), 0.2);
|
|
3089
|
+
}
|
|
3090
|
+
function checkNodeWasScrollRoot(node) {
|
|
3091
|
+
var _a;
|
|
3092
|
+
return node !== node.root && ((_a = node.scroll) === null || _a === void 0 ? void 0 : _a.wasRoot);
|
|
3093
|
+
}
|
|
3094
|
+
const DocumentProjectionNode = createProjectionNode({
|
|
3095
|
+
attachResizeListener: (ref, notify) => addDomEvent(ref, "resize", notify),
|
|
3096
|
+
measureScroll: () => ({
|
|
3097
|
+
x: document.documentElement.scrollLeft || document.body.scrollLeft,
|
|
3098
|
+
y: document.documentElement.scrollTop || document.body.scrollTop
|
|
3099
|
+
}),
|
|
3100
|
+
checkIsScrollRoot: () => true
|
|
3101
|
+
});
|
|
3102
|
+
const rootProjectionNode = {
|
|
3103
|
+
current: void 0
|
|
3104
|
+
};
|
|
3105
|
+
const HTMLProjectionNode = createProjectionNode({
|
|
3106
|
+
measureScroll: (instance) => ({
|
|
3107
|
+
x: instance.scrollLeft,
|
|
3108
|
+
y: instance.scrollTop
|
|
3109
|
+
}),
|
|
3110
|
+
defaultParent: () => {
|
|
3111
|
+
if (!rootProjectionNode.current) {
|
|
3112
|
+
const documentNode = new DocumentProjectionNode({});
|
|
3113
|
+
documentNode.mount(window);
|
|
3114
|
+
documentNode.setOptions({ layoutScroll: true });
|
|
3115
|
+
rootProjectionNode.current = documentNode;
|
|
3116
|
+
}
|
|
3117
|
+
return rootProjectionNode.current;
|
|
3118
|
+
},
|
|
3119
|
+
resetTransform: (instance, value) => {
|
|
3120
|
+
instance.style.transform = value !== void 0 ? value : "none";
|
|
3121
|
+
},
|
|
3122
|
+
checkIsScrollRoot: (instance) => Boolean(window.getComputedStyle(instance).position === "fixed")
|
|
3123
|
+
});
|
|
3124
|
+
const drag = {
|
|
3125
|
+
pan: {
|
|
3126
|
+
Feature: PanGesture
|
|
3127
|
+
},
|
|
3128
|
+
drag: {
|
|
3129
|
+
Feature: DragGesture,
|
|
3130
|
+
ProjectionNode: HTMLProjectionNode,
|
|
3131
|
+
MeasureLayout
|
|
3132
|
+
}
|
|
3133
|
+
};
|
|
3134
|
+
function setupGesture(elementOrSelector, options) {
|
|
3135
|
+
const elements = resolveElements(elementOrSelector);
|
|
3136
|
+
const gestureAbortController = new AbortController();
|
|
3137
|
+
const eventOptions = {
|
|
3138
|
+
passive: true,
|
|
3139
|
+
...options,
|
|
3140
|
+
signal: gestureAbortController.signal
|
|
3141
|
+
};
|
|
3142
|
+
const cancel = () => gestureAbortController.abort();
|
|
3143
|
+
return [elements, eventOptions, cancel];
|
|
3144
|
+
}
|
|
3145
|
+
function filterEvents$1(callback) {
|
|
3146
|
+
return (event) => {
|
|
3147
|
+
if (event.pointerType === "touch" || isDragActive())
|
|
3148
|
+
return;
|
|
3149
|
+
callback(event);
|
|
3150
|
+
};
|
|
3151
|
+
}
|
|
3152
|
+
function hover(elementOrSelector, onHoverStart, options = {}) {
|
|
3153
|
+
const [elements, eventOptions, cancel] = setupGesture(elementOrSelector, options);
|
|
3154
|
+
const onPointerEnter = filterEvents$1((enterEvent) => {
|
|
3155
|
+
const { target } = enterEvent;
|
|
3156
|
+
const onHoverEnd = onHoverStart(enterEvent);
|
|
3157
|
+
if (typeof onHoverEnd !== "function" || !target)
|
|
3158
|
+
return;
|
|
3159
|
+
const onPointerLeave = filterEvents$1((leaveEvent) => {
|
|
3160
|
+
onHoverEnd(leaveEvent);
|
|
3161
|
+
target.removeEventListener("pointerleave", onPointerLeave);
|
|
3162
|
+
});
|
|
3163
|
+
target.addEventListener("pointerleave", onPointerLeave, eventOptions);
|
|
3164
|
+
});
|
|
3165
|
+
elements.forEach((element) => {
|
|
3166
|
+
element.addEventListener("pointerenter", onPointerEnter, eventOptions);
|
|
3167
|
+
});
|
|
3168
|
+
return cancel;
|
|
3169
|
+
}
|
|
3170
|
+
function handleHoverEvent(node, event, lifecycle) {
|
|
3171
|
+
const { props } = node;
|
|
3172
|
+
if (node.animationState && props.whileHover) {
|
|
3173
|
+
node.animationState.setActive("whileHover", lifecycle === "Start");
|
|
3174
|
+
}
|
|
3175
|
+
const eventName = "onHover" + lifecycle;
|
|
3176
|
+
const callback = props[eventName];
|
|
3177
|
+
if (callback) {
|
|
3178
|
+
frame.postRender(() => callback(event, extractEventInfo(event)));
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
class HoverGesture extends Feature {
|
|
3182
|
+
mount() {
|
|
3183
|
+
const { current } = this.node;
|
|
3184
|
+
if (!current)
|
|
3185
|
+
return;
|
|
3186
|
+
this.unmount = hover(current, (startEvent) => {
|
|
3187
|
+
handleHoverEvent(this.node, startEvent, "Start");
|
|
3188
|
+
return (endEvent) => handleHoverEvent(this.node, endEvent, "End");
|
|
3189
|
+
});
|
|
3190
|
+
}
|
|
3191
|
+
unmount() {
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
class FocusGesture extends Feature {
|
|
3195
|
+
constructor() {
|
|
3196
|
+
super(...arguments);
|
|
3197
|
+
this.isActive = false;
|
|
3198
|
+
}
|
|
3199
|
+
onFocus() {
|
|
3200
|
+
let isFocusVisible = false;
|
|
3201
|
+
try {
|
|
3202
|
+
isFocusVisible = this.node.current.matches(":focus-visible");
|
|
3203
|
+
} catch (e) {
|
|
3204
|
+
isFocusVisible = true;
|
|
3205
|
+
}
|
|
3206
|
+
if (!isFocusVisible || !this.node.animationState)
|
|
3207
|
+
return;
|
|
3208
|
+
this.node.animationState.setActive("whileFocus", true);
|
|
3209
|
+
this.isActive = true;
|
|
3210
|
+
}
|
|
3211
|
+
onBlur() {
|
|
3212
|
+
if (!this.isActive || !this.node.animationState)
|
|
3213
|
+
return;
|
|
3214
|
+
this.node.animationState.setActive("whileFocus", false);
|
|
3215
|
+
this.isActive = false;
|
|
3216
|
+
}
|
|
3217
|
+
mount() {
|
|
3218
|
+
this.unmount = pipe(addDomEvent(this.node.current, "focus", () => this.onFocus()), addDomEvent(this.node.current, "blur", () => this.onBlur()));
|
|
3219
|
+
}
|
|
3220
|
+
unmount() {
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
const isNodeOrChild = (parent, child) => {
|
|
3224
|
+
if (!child) {
|
|
3225
|
+
return false;
|
|
3226
|
+
} else if (parent === child) {
|
|
3227
|
+
return true;
|
|
3228
|
+
} else {
|
|
3229
|
+
return isNodeOrChild(parent, child.parentElement);
|
|
3230
|
+
}
|
|
3231
|
+
};
|
|
3232
|
+
const focusableElements = /* @__PURE__ */ new Set([
|
|
3233
|
+
"BUTTON",
|
|
3234
|
+
"INPUT",
|
|
3235
|
+
"SELECT",
|
|
3236
|
+
"TEXTAREA",
|
|
3237
|
+
"A"
|
|
3238
|
+
]);
|
|
3239
|
+
function isElementKeyboardAccessible(element) {
|
|
3240
|
+
return focusableElements.has(element.tagName) || element.tabIndex !== -1;
|
|
3241
|
+
}
|
|
3242
|
+
const isPressing = /* @__PURE__ */ new WeakSet();
|
|
3243
|
+
function filterEvents(callback) {
|
|
3244
|
+
return (event) => {
|
|
3245
|
+
if (event.key !== "Enter")
|
|
3246
|
+
return;
|
|
3247
|
+
callback(event);
|
|
3248
|
+
};
|
|
3249
|
+
}
|
|
3250
|
+
function firePointerEvent(target, type) {
|
|
3251
|
+
target.dispatchEvent(new PointerEvent("pointer" + type, { isPrimary: true, bubbles: true }));
|
|
3252
|
+
}
|
|
3253
|
+
const enableKeyboardPress = (focusEvent, eventOptions) => {
|
|
3254
|
+
const element = focusEvent.currentTarget;
|
|
3255
|
+
if (!element)
|
|
3256
|
+
return;
|
|
3257
|
+
const handleKeydown = filterEvents(() => {
|
|
3258
|
+
if (isPressing.has(element))
|
|
3259
|
+
return;
|
|
3260
|
+
firePointerEvent(element, "down");
|
|
3261
|
+
const handleKeyup = filterEvents(() => {
|
|
3262
|
+
firePointerEvent(element, "up");
|
|
3263
|
+
});
|
|
3264
|
+
const handleBlur = () => firePointerEvent(element, "cancel");
|
|
3265
|
+
element.addEventListener("keyup", handleKeyup, eventOptions);
|
|
3266
|
+
element.addEventListener("blur", handleBlur, eventOptions);
|
|
3267
|
+
});
|
|
3268
|
+
element.addEventListener("keydown", handleKeydown, eventOptions);
|
|
3269
|
+
element.addEventListener("blur", () => element.removeEventListener("keydown", handleKeydown), eventOptions);
|
|
3270
|
+
};
|
|
3271
|
+
function isValidPressEvent(event) {
|
|
3272
|
+
return isPrimaryPointer(event) && !isDragActive();
|
|
3273
|
+
}
|
|
3274
|
+
function press(elementOrSelector, onPressStart, options = {}) {
|
|
3275
|
+
const [elements, eventOptions, cancelEvents] = setupGesture(elementOrSelector, options);
|
|
3276
|
+
const startPress = (startEvent) => {
|
|
3277
|
+
const element = startEvent.currentTarget;
|
|
3278
|
+
if (!isValidPressEvent(startEvent) || isPressing.has(element))
|
|
3279
|
+
return;
|
|
3280
|
+
isPressing.add(element);
|
|
3281
|
+
const onPressEnd = onPressStart(startEvent);
|
|
3282
|
+
const onPointerEnd = (endEvent, success) => {
|
|
3283
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
3284
|
+
window.removeEventListener("pointercancel", onPointerCancel);
|
|
3285
|
+
if (!isValidPressEvent(endEvent) || !isPressing.has(element)) {
|
|
3286
|
+
return;
|
|
3287
|
+
}
|
|
3288
|
+
isPressing.delete(element);
|
|
3289
|
+
if (typeof onPressEnd === "function") {
|
|
3290
|
+
onPressEnd(endEvent, { success });
|
|
3291
|
+
}
|
|
3292
|
+
};
|
|
3293
|
+
const onPointerUp = (upEvent) => {
|
|
3294
|
+
onPointerEnd(upEvent, options.useGlobalTarget || isNodeOrChild(element, upEvent.target));
|
|
3295
|
+
};
|
|
3296
|
+
const onPointerCancel = (cancelEvent) => {
|
|
3297
|
+
onPointerEnd(cancelEvent, false);
|
|
3298
|
+
};
|
|
3299
|
+
window.addEventListener("pointerup", onPointerUp, eventOptions);
|
|
3300
|
+
window.addEventListener("pointercancel", onPointerCancel, eventOptions);
|
|
3301
|
+
};
|
|
3302
|
+
elements.forEach((element) => {
|
|
3303
|
+
if (!isElementKeyboardAccessible(element) && element.getAttribute("tabindex") === null) {
|
|
3304
|
+
element.tabIndex = 0;
|
|
3305
|
+
}
|
|
3306
|
+
const target = options.useGlobalTarget ? window : element;
|
|
3307
|
+
target.addEventListener("pointerdown", startPress, eventOptions);
|
|
3308
|
+
element.addEventListener("focus", (event) => enableKeyboardPress(event, eventOptions), eventOptions);
|
|
3309
|
+
});
|
|
3310
|
+
return cancelEvents;
|
|
3311
|
+
}
|
|
3312
|
+
function handlePressEvent(node, event, lifecycle) {
|
|
3313
|
+
const { props } = node;
|
|
3314
|
+
if (node.animationState && props.whileTap) {
|
|
3315
|
+
node.animationState.setActive("whileTap", lifecycle === "Start");
|
|
3316
|
+
}
|
|
3317
|
+
const eventName = "onTap" + (lifecycle === "End" ? "" : lifecycle);
|
|
3318
|
+
const callback = props[eventName];
|
|
3319
|
+
if (callback) {
|
|
3320
|
+
frame.postRender(() => callback(event, extractEventInfo(event)));
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
class PressGesture extends Feature {
|
|
3324
|
+
mount() {
|
|
3325
|
+
const { current } = this.node;
|
|
3326
|
+
if (!current)
|
|
3327
|
+
return;
|
|
3328
|
+
this.unmount = press(current, (startEvent) => {
|
|
3329
|
+
handlePressEvent(this.node, startEvent, "Start");
|
|
3330
|
+
return (endEvent, { success }) => handlePressEvent(this.node, endEvent, success ? "End" : "Cancel");
|
|
3331
|
+
}, { useGlobalTarget: this.node.props.globalTapTarget });
|
|
3332
|
+
}
|
|
3333
|
+
unmount() {
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
const observerCallbacks = /* @__PURE__ */ new WeakMap();
|
|
3337
|
+
const observers = /* @__PURE__ */ new WeakMap();
|
|
3338
|
+
const fireObserverCallback = (entry) => {
|
|
3339
|
+
const callback = observerCallbacks.get(entry.target);
|
|
3340
|
+
callback && callback(entry);
|
|
3341
|
+
};
|
|
3342
|
+
const fireAllObserverCallbacks = (entries) => {
|
|
3343
|
+
entries.forEach(fireObserverCallback);
|
|
3344
|
+
};
|
|
3345
|
+
function initIntersectionObserver({ root, ...options }) {
|
|
3346
|
+
const lookupRoot = root || document;
|
|
3347
|
+
if (!observers.has(lookupRoot)) {
|
|
3348
|
+
observers.set(lookupRoot, {});
|
|
3349
|
+
}
|
|
3350
|
+
const rootObservers = observers.get(lookupRoot);
|
|
3351
|
+
const key = JSON.stringify(options);
|
|
3352
|
+
if (!rootObservers[key]) {
|
|
3353
|
+
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, { root, ...options });
|
|
3354
|
+
}
|
|
3355
|
+
return rootObservers[key];
|
|
3356
|
+
}
|
|
3357
|
+
function observeIntersection(element, options, callback) {
|
|
3358
|
+
const rootInteresectionObserver = initIntersectionObserver(options);
|
|
3359
|
+
observerCallbacks.set(element, callback);
|
|
3360
|
+
rootInteresectionObserver.observe(element);
|
|
3361
|
+
return () => {
|
|
3362
|
+
observerCallbacks.delete(element);
|
|
3363
|
+
rootInteresectionObserver.unobserve(element);
|
|
3364
|
+
};
|
|
3365
|
+
}
|
|
3366
|
+
const thresholdNames = {
|
|
3367
|
+
some: 0,
|
|
3368
|
+
all: 1
|
|
3369
|
+
};
|
|
3370
|
+
class InViewFeature extends Feature {
|
|
3371
|
+
constructor() {
|
|
3372
|
+
super(...arguments);
|
|
3373
|
+
this.hasEnteredView = false;
|
|
3374
|
+
this.isInView = false;
|
|
3375
|
+
}
|
|
3376
|
+
startObserver() {
|
|
3377
|
+
this.unmount();
|
|
3378
|
+
const { viewport = {} } = this.node.getProps();
|
|
3379
|
+
const { root, margin: rootMargin, amount = "some", once } = viewport;
|
|
3380
|
+
const options = {
|
|
3381
|
+
root: root ? root.current : void 0,
|
|
3382
|
+
rootMargin,
|
|
3383
|
+
threshold: typeof amount === "number" ? amount : thresholdNames[amount]
|
|
3384
|
+
};
|
|
3385
|
+
const onIntersectionUpdate = (entry) => {
|
|
3386
|
+
const { isIntersecting } = entry;
|
|
3387
|
+
if (this.isInView === isIntersecting)
|
|
3388
|
+
return;
|
|
3389
|
+
this.isInView = isIntersecting;
|
|
3390
|
+
if (once && !isIntersecting && this.hasEnteredView) {
|
|
3391
|
+
return;
|
|
3392
|
+
} else if (isIntersecting) {
|
|
3393
|
+
this.hasEnteredView = true;
|
|
3394
|
+
}
|
|
3395
|
+
if (this.node.animationState) {
|
|
3396
|
+
this.node.animationState.setActive("whileInView", isIntersecting);
|
|
3397
|
+
}
|
|
3398
|
+
const { onViewportEnter, onViewportLeave } = this.node.getProps();
|
|
3399
|
+
const callback = isIntersecting ? onViewportEnter : onViewportLeave;
|
|
3400
|
+
callback && callback(entry);
|
|
3401
|
+
};
|
|
3402
|
+
return observeIntersection(this.node.current, options, onIntersectionUpdate);
|
|
3403
|
+
}
|
|
3404
|
+
mount() {
|
|
3405
|
+
this.startObserver();
|
|
3406
|
+
}
|
|
3407
|
+
update() {
|
|
3408
|
+
if (typeof IntersectionObserver === "undefined")
|
|
3409
|
+
return;
|
|
3410
|
+
const { props, prevProps } = this.node;
|
|
3411
|
+
const hasOptionsChanged = ["amount", "margin", "root"].some(hasViewportOptionChanged(props, prevProps));
|
|
3412
|
+
if (hasOptionsChanged) {
|
|
3413
|
+
this.startObserver();
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
unmount() {
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
function hasViewportOptionChanged({ viewport = {} }, { viewport: prevViewport = {} } = {}) {
|
|
3420
|
+
return (name) => viewport[name] !== prevViewport[name];
|
|
3421
|
+
}
|
|
3422
|
+
const gestureAnimations = {
|
|
3423
|
+
inView: {
|
|
3424
|
+
Feature: InViewFeature
|
|
3425
|
+
},
|
|
3426
|
+
tap: {
|
|
3427
|
+
Feature: PressGesture
|
|
3428
|
+
},
|
|
3429
|
+
focus: {
|
|
3430
|
+
Feature: FocusGesture
|
|
3431
|
+
},
|
|
3432
|
+
hover: {
|
|
3433
|
+
Feature: HoverGesture
|
|
3434
|
+
}
|
|
3435
|
+
};
|
|
3436
|
+
const layout = {
|
|
3437
|
+
layout: {
|
|
3438
|
+
ProjectionNode: HTMLProjectionNode,
|
|
3439
|
+
MeasureLayout
|
|
3440
|
+
}
|
|
3441
|
+
};
|
|
3442
|
+
const createDomVisualElement = (Component2, options) => {
|
|
3443
|
+
return isSVGComponent(Component2) ? new SVGVisualElement(options) : new HTMLVisualElement(options, {
|
|
3444
|
+
allowProjection: Component2 !== Fragment
|
|
3445
|
+
});
|
|
3446
|
+
};
|
|
3447
|
+
const createMotionComponent = /* @__PURE__ */ createMotionComponentFactory({
|
|
3448
|
+
...animations,
|
|
3449
|
+
...gestureAnimations,
|
|
3450
|
+
...drag,
|
|
3451
|
+
...layout
|
|
3452
|
+
}, createDomVisualElement);
|
|
3453
|
+
const motion = /* @__PURE__ */ createDOMMotionComponentProxy(createMotionComponent);
|
|
3454
|
+
const DURATION = 8e3;
|
|
3455
|
+
const ToastList = React__default.forwardRef((props, ref) => {
|
|
3456
|
+
const { testId, toasts = [] } = props;
|
|
3457
|
+
const internalRef = React__default.useRef(null);
|
|
3458
|
+
const [visibleToasts, setVisibleToasts] = React__default.useState([]);
|
|
3459
|
+
const [removedToastIds, setRemovedToastIds] = React__default.useState(/* @__PURE__ */ new Set());
|
|
3460
|
+
const timeoutRefs = React__default.useRef(/* @__PURE__ */ new Map());
|
|
3461
|
+
React__default.useEffect(() => {
|
|
3462
|
+
const newToasts = toasts.filter((toast) => !visibleToasts.some((vt) => vt.id === toast.id) && !removedToastIds.has(toast.id));
|
|
3463
|
+
if (newToasts.length > 0) {
|
|
3464
|
+
setVisibleToasts((prev) => [...prev, ...newToasts]);
|
|
3465
|
+
}
|
|
3466
|
+
}, [toasts, visibleToasts, removedToastIds]);
|
|
3467
|
+
const handleRemoveToast = React__default.useCallback((id2) => {
|
|
3468
|
+
setVisibleToasts((prev) => prev.filter((t) => t.id !== id2));
|
|
3469
|
+
setRemovedToastIds((prev) => /* @__PURE__ */ new Set([...prev, id2]));
|
|
3470
|
+
const timeout = timeoutRefs.current.get(id2);
|
|
3471
|
+
if (timeout) {
|
|
3472
|
+
clearTimeout(timeout);
|
|
3473
|
+
timeoutRefs.current.delete(id2);
|
|
3474
|
+
}
|
|
3475
|
+
}, []);
|
|
3476
|
+
React__default.useEffect(() => {
|
|
3477
|
+
const timeouts = timeoutRefs.current;
|
|
3478
|
+
visibleToasts.forEach((toast) => {
|
|
3479
|
+
if (!timeouts.has(toast.id)) {
|
|
3480
|
+
const timeout = setTimeout(() => {
|
|
3481
|
+
handleRemoveToast(toast.id);
|
|
3482
|
+
}, DURATION);
|
|
3483
|
+
timeouts.set(toast.id, timeout);
|
|
3484
|
+
}
|
|
3485
|
+
});
|
|
3486
|
+
}, [visibleToasts, handleRemoveToast]);
|
|
3487
|
+
React__default.useEffect(() => {
|
|
3488
|
+
const timeouts = timeoutRefs.current;
|
|
3489
|
+
const currentToastIds = new Set(visibleToasts.map((t) => t.id));
|
|
3490
|
+
timeouts.forEach((timeout, id2) => {
|
|
3491
|
+
if (!currentToastIds.has(id2)) {
|
|
3492
|
+
clearTimeout(timeout);
|
|
3493
|
+
timeouts.delete(id2);
|
|
3494
|
+
}
|
|
3495
|
+
});
|
|
3496
|
+
}, [visibleToasts]);
|
|
3497
|
+
React__default.useEffect(() => {
|
|
3498
|
+
return () => {
|
|
3499
|
+
timeoutRefs.current.forEach((timeout) => clearTimeout(timeout));
|
|
3500
|
+
timeoutRefs.current.clear();
|
|
3501
|
+
};
|
|
3502
|
+
}, []);
|
|
3503
|
+
const setRefs = mergeRefs([internalRef, ref]);
|
|
3504
|
+
return /* @__PURE__ */ jsx("section", { ref: setRefs, className: styles["toast-list"], "data-testid": testId, children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", children: visibleToasts.map((toast) => /* @__PURE__ */ jsx(
|
|
3505
|
+
motion.div,
|
|
3506
|
+
{
|
|
3507
|
+
layout: true,
|
|
3508
|
+
initial: { opacity: 0, y: 50 },
|
|
3509
|
+
animate: { opacity: 1, y: 0 },
|
|
3510
|
+
exit: { opacity: 0, y: -20 },
|
|
3511
|
+
transition: {
|
|
3512
|
+
layout: { type: "spring", duration: 0.4, bounce: 0.1 }
|
|
3513
|
+
},
|
|
3514
|
+
children: /* @__PURE__ */ jsx(
|
|
3515
|
+
Toast,
|
|
3516
|
+
{
|
|
3517
|
+
testId: `${testId}-${toast.id}`,
|
|
3518
|
+
title: toast.title,
|
|
3519
|
+
message: toast.message,
|
|
3520
|
+
onClose: () => handleRemoveToast(toast.id)
|
|
3521
|
+
}
|
|
3522
|
+
)
|
|
3523
|
+
},
|
|
3524
|
+
toast.id
|
|
3525
|
+
)) }) });
|
|
3526
|
+
});
|
|
3527
|
+
ToastList.displayName = "ToastList";
|
|
3528
|
+
export {
|
|
3529
|
+
ToastList as default
|
|
3530
|
+
};
|
|
3531
|
+
//# sourceMappingURL=index.js.map
|