@kitlangton/solid-motion 0.1.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/LICENSE +48 -0
- package/README.md +54 -0
- package/dist/animation/animate/index.d.ts +23 -0
- package/dist/animation/animate/resolve-subjects.d.ts +3 -0
- package/dist/animation/animate/sequence.d.ts +3 -0
- package/dist/animation/animate/subject.d.ts +7 -0
- package/dist/animation/sequence/create.d.ts +6 -0
- package/dist/animation/sequence/types.d.ts +51 -0
- package/dist/animation/sequence/utils/calc-repeat-duration.d.ts +1 -0
- package/dist/animation/sequence/utils/calc-time.d.ts +2 -0
- package/dist/animation/sequence/utils/edit.d.ts +5 -0
- package/dist/animation/sequence/utils/normalize-times.d.ts +1 -0
- package/dist/animation/sequence/utils/sort.d.ts +2 -0
- package/dist/animation/utils/create-visual-element.d.ts +2 -0
- package/dist/animation/utils/is-dom-keyframes.d.ts +2 -0
- package/dist/components/AnimatePresence.d.ts +27 -0
- package/dist/components/AnimatePresenceContext.d.ts +23 -0
- package/dist/components/AnimatePresenceTypes.d.ts +57 -0
- package/dist/components/MotionConfig.d.ts +16 -0
- package/dist/context/MotionContext/create.d.ts +3 -0
- package/dist/context/MotionContext/utils.d.ts +3 -0
- package/dist/context/MotionContext.d.ts +7 -0
- package/dist/context/PresenceContext.d.ts +13 -0
- package/dist/events/add-pointer-event.d.ts +2 -0
- package/dist/events/event-info.d.ts +4 -0
- package/dist/gestures/drag/VisualElementDragControls.d.ts +86 -0
- package/dist/gestures/drag/index.d.ts +11 -0
- package/dist/gestures/drag/utils/constraints.d.ts +77 -0
- package/dist/gestures/focus.d.ts +8 -0
- package/dist/gestures/hover.d.ts +5 -0
- package/dist/gestures/pan/PanSession.d.ts +102 -0
- package/dist/gestures/pan/index.d.ts +15 -0
- package/dist/gestures/press.d.ts +5 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +2466 -0
- package/dist/index.js.map +1 -0
- package/dist/motion/features/animation/exit.d.ts +7 -0
- package/dist/motion/features/animation/index.d.ts +9 -0
- package/dist/motion/features/animations.d.ts +10 -0
- package/dist/motion/features/definitions.d.ts +3 -0
- package/dist/motion/features/feature-bundle.d.ts +34 -0
- package/dist/motion/features/gestures.d.ts +26 -0
- package/dist/motion/features/load-features.d.ts +1 -0
- package/dist/motion/index.d.ts +22 -0
- package/dist/motion/types.d.ts +27 -0
- package/dist/motion/utils/drag-projection.d.ts +3 -0
- package/dist/motion/utils/use-visual-state.d.ts +14 -0
- package/dist/motion/utils/valid-prop.d.ts +1 -0
- package/dist/render/dom/create-visual-element.d.ts +2 -0
- package/dist/render/dom/filter-props.d.ts +2 -0
- package/dist/render/dom/is-svg-component.d.ts +1 -0
- package/dist/render/dom/style.d.ts +1 -0
- package/dist/render/html/use-props.d.ts +7 -0
- package/dist/render/html/utils/create-render-state.d.ts +2 -0
- package/dist/render/svg/lowercase-elements.d.ts +1 -0
- package/dist/render/svg/use-props.d.ts +3 -0
- package/dist/render/svg/utils/create-render-state.d.ts +2 -0
- package/dist/render/types.d.ts +3 -0
- package/dist/server.js +2407 -0
- package/dist/server.js.map +1 -0
- package/dist/source/animation/animate/index.js +39 -0
- package/dist/source/animation/animate/resolve-subjects.js +19 -0
- package/dist/source/animation/animate/sequence.js +11 -0
- package/dist/source/animation/animate/subject.js +37 -0
- package/dist/source/animation/sequence/create.js +171 -0
- package/dist/source/animation/sequence/types.js +1 -0
- package/dist/source/animation/sequence/utils/calc-repeat-duration.js +3 -0
- package/dist/source/animation/sequence/utils/calc-time.js +17 -0
- package/dist/source/animation/sequence/utils/edit.js +21 -0
- package/dist/source/animation/sequence/utils/normalize-times.js +5 -0
- package/dist/source/animation/sequence/utils/sort.js +12 -0
- package/dist/source/animation/utils/create-visual-element.js +37 -0
- package/dist/source/animation/utils/is-dom-keyframes.js +3 -0
- package/dist/source/components/AnimatePresence.jsx +444 -0
- package/dist/source/components/AnimatePresenceContext.jsx +20 -0
- package/dist/source/components/AnimatePresenceTypes.js +1 -0
- package/dist/source/components/MotionConfig.jsx +13 -0
- package/dist/source/context/MotionContext/create.js +19 -0
- package/dist/source/context/MotionContext/utils.js +11 -0
- package/dist/source/context/MotionContext.js +2 -0
- package/dist/source/context/PresenceContext.js +2 -0
- package/dist/source/events/add-pointer-event.js +5 -0
- package/dist/source/events/event-info.js +16 -0
- package/dist/source/gestures/drag/VisualElementDragControls.js +531 -0
- package/dist/source/gestures/drag/index.js +47 -0
- package/dist/source/gestures/drag/utils/constraints.js +160 -0
- package/dist/source/gestures/focus.js +37 -0
- package/dist/source/gestures/hover.js +25 -0
- package/dist/source/gestures/pan/PanSession.js +273 -0
- package/dist/source/gestures/pan/index.js +46 -0
- package/dist/source/gestures/press.js +28 -0
- package/dist/source/index.js +11 -0
- package/dist/source/motion/features/animation/exit.js +33 -0
- package/dist/source/motion/features/animation/index.js +27 -0
- package/dist/source/motion/features/animations.js +10 -0
- package/dist/source/motion/features/definitions.js +29 -0
- package/dist/source/motion/features/feature-bundle.js +6 -0
- package/dist/source/motion/features/gestures.js +20 -0
- package/dist/source/motion/features/load-features.js +12 -0
- package/dist/source/motion/index.jsx +176 -0
- package/dist/source/motion/types.js +1 -0
- package/dist/source/motion/utils/drag-projection.js +16 -0
- package/dist/source/motion/utils/use-visual-state.js +53 -0
- package/dist/source/motion/utils/valid-prop.js +40 -0
- package/dist/source/render/dom/create-visual-element.js +10 -0
- package/dist/source/render/dom/filter-props.js +15 -0
- package/dist/source/render/dom/is-svg-component.js +10 -0
- package/dist/source/render/dom/style.js +12 -0
- package/dist/source/render/html/use-props.js +39 -0
- package/dist/source/render/html/utils/create-render-state.js +6 -0
- package/dist/source/render/svg/lowercase-elements.js +27 -0
- package/dist/source/render/svg/use-props.js +28 -0
- package/dist/source/render/svg/utils/create-render-state.js +5 -0
- package/dist/source/render/types.js +1 -0
- package/dist/source/utils/distance.js +7 -0
- package/dist/source/utils/get-context-window.js +4 -0
- package/dist/source/utils/is-ref-object.js +5 -0
- package/dist/source/utils/safe-react-types.js +1 -0
- package/dist/source/utils/use-reduced-motion.js +15 -0
- package/dist/source/value/use-motion-value-event.js +5 -0
- package/dist/source/value/use-motion-value.js +16 -0
- package/dist/source/value/use-spring.js +59 -0
- package/dist/source/value/use-transform.js +25 -0
- package/dist/source/value/use-velocity.js +17 -0
- package/dist/utils/distance.d.ts +3 -0
- package/dist/utils/get-context-window.d.ts +2 -0
- package/dist/utils/is-ref-object.d.ts +2 -0
- package/dist/utils/safe-react-types.d.ts +3 -0
- package/dist/utils/use-reduced-motion.d.ts +6 -0
- package/dist/value/use-motion-value-event.d.ts +3 -0
- package/dist/value/use-motion-value.d.ts +5 -0
- package/dist/value/use-spring.d.ts +5 -0
- package/dist/value/use-transform.d.ts +9 -0
- package/dist/value/use-velocity.d.ts +3 -0
- package/package.json +61 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2466 @@
|
|
|
1
|
+
import { createComponent, Dynamic, mergeProps, getNextElement, use, insert, effect, style, template } from "solid-js/web";
|
|
2
|
+
import { createContext, useContext, splitProps, createSignal, createEffect, createMemo, onMount, onCleanup, mergeProps as mergeProps$1, on, untrack, For, batch, Index, children } from "solid-js";
|
|
3
|
+
import { isControllingVariants, isVariantLabel, SVGVisualElement, HTMLVisualElement, isMotionValue, isForcedMotionValue, buildHTMLStyles, buildSVGAttrs, isSVGTag, resolveMotionValue, isVariantNode, isAnimationControls, resolveVariantFromProps, getFeatureDefinitions, setFeatureDefinitions, Feature, createAnimationState, isPrimaryPointer, addDomEvent, frameData, frame, cancelFrame, mixNumber, calcLength, createBox, eachAxis, measurePageBox, convertBoxToBoundingBox, convertBoundingBoxToBox, addValueToWillChange, animateMotionValue, setDragLock, percent, hover, press, HTMLProjectionNode, scrapeSVGMotionValuesFromProps, scrapeHTMLMotionValuesFromProps, motionValue, transformValue, transform, mapValue, JSAnimation, resolveElements, defaultOffset, isGenerator, createGeneratorEasing, fillOffset, isSVGElement, isSVGSVGElement, visualElementStore, ObjectVisualElement, animateSingleValue, animateTarget, spring, GroupAnimationWithThen } from "motion-dom";
|
|
4
|
+
export * from "motion-dom";
|
|
5
|
+
import { pipe, secondsToMilliseconds, millisecondsToSeconds, progress, clamp, invariant, noop, getEasingForSegment, removeItem } from "motion-utils";
|
|
6
|
+
const defaultContext = {
|
|
7
|
+
transformPagePoint: ((p) => p),
|
|
8
|
+
isStatic: false,
|
|
9
|
+
reducedMotion: "never"
|
|
10
|
+
};
|
|
11
|
+
const MotionConfigContext = createContext(defaultContext);
|
|
12
|
+
function MotionConfig(props) {
|
|
13
|
+
const parent = useContext(MotionConfigContext);
|
|
14
|
+
const [local, contextProps] = splitProps(props, ["children"]);
|
|
15
|
+
const value = {
|
|
16
|
+
...parent,
|
|
17
|
+
...contextProps
|
|
18
|
+
};
|
|
19
|
+
return createComponent(MotionConfigContext.Provider, {
|
|
20
|
+
value,
|
|
21
|
+
get children() {
|
|
22
|
+
return local.children;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const MotionContext = createContext({});
|
|
27
|
+
const PresenceContext = createContext(null);
|
|
28
|
+
function getCurrentTreeVariants(props, context) {
|
|
29
|
+
if (isControllingVariants(props)) {
|
|
30
|
+
const { initial, animate: animate2 } = props;
|
|
31
|
+
return {
|
|
32
|
+
initial: initial === false || isVariantLabel(initial) ? initial : void 0,
|
|
33
|
+
animate: isVariantLabel(animate2) ? animate2 : void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return props.inherit !== false ? context : {};
|
|
37
|
+
}
|
|
38
|
+
function createMotionContext(props, parentContext) {
|
|
39
|
+
const [initial, setInitial] = createSignal();
|
|
40
|
+
const [animate2, setAnimate] = createSignal();
|
|
41
|
+
createEffect(() => {
|
|
42
|
+
const variants = getCurrentTreeVariants(props, parentContext);
|
|
43
|
+
setInitial(variants.initial);
|
|
44
|
+
setAnimate(variants.animate);
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
get initial() {
|
|
48
|
+
return initial();
|
|
49
|
+
},
|
|
50
|
+
get animate() {
|
|
51
|
+
return animate2();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const lowercaseSVGElements = [
|
|
56
|
+
"animate",
|
|
57
|
+
"circle",
|
|
58
|
+
"defs",
|
|
59
|
+
"desc",
|
|
60
|
+
"ellipse",
|
|
61
|
+
"g",
|
|
62
|
+
"image",
|
|
63
|
+
"line",
|
|
64
|
+
"filter",
|
|
65
|
+
"marker",
|
|
66
|
+
"mask",
|
|
67
|
+
"metadata",
|
|
68
|
+
"path",
|
|
69
|
+
"pattern",
|
|
70
|
+
"polygon",
|
|
71
|
+
"polyline",
|
|
72
|
+
"rect",
|
|
73
|
+
"stop",
|
|
74
|
+
"switch",
|
|
75
|
+
"symbol",
|
|
76
|
+
"svg",
|
|
77
|
+
"text",
|
|
78
|
+
"tspan",
|
|
79
|
+
"use",
|
|
80
|
+
"view"
|
|
81
|
+
];
|
|
82
|
+
function isSVGComponent(Component) {
|
|
83
|
+
if (typeof Component !== "string" || Component.includes("-")) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (lowercaseSVGElements.indexOf(Component) > -1 || /[A-Z]/u.test(Component)) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
const validMotionProps = /* @__PURE__ */ new Set([
|
|
92
|
+
"animate",
|
|
93
|
+
"exit",
|
|
94
|
+
"variants",
|
|
95
|
+
"initial",
|
|
96
|
+
"style",
|
|
97
|
+
"values",
|
|
98
|
+
"transition",
|
|
99
|
+
"transformTemplate",
|
|
100
|
+
"custom",
|
|
101
|
+
"inherit",
|
|
102
|
+
"onBeforeLayoutMeasure",
|
|
103
|
+
"onAnimationStart",
|
|
104
|
+
"onAnimationComplete",
|
|
105
|
+
"onUpdate",
|
|
106
|
+
"onDragStart",
|
|
107
|
+
"onDrag",
|
|
108
|
+
"onDragEnd",
|
|
109
|
+
"onMeasureDragConstraints",
|
|
110
|
+
"onDirectionLock",
|
|
111
|
+
"onDragTransitionEnd",
|
|
112
|
+
"_dragX",
|
|
113
|
+
"_dragY",
|
|
114
|
+
"onHoverStart",
|
|
115
|
+
"onHoverEnd",
|
|
116
|
+
"onViewportEnter",
|
|
117
|
+
"onViewportLeave",
|
|
118
|
+
"globalTapTarget",
|
|
119
|
+
"ignoreStrict",
|
|
120
|
+
"viewport"
|
|
121
|
+
]);
|
|
122
|
+
function isValidMotionProp(key) {
|
|
123
|
+
return key.startsWith("while") || key.startsWith("drag") && key !== "draggable" || key.startsWith("layout") || key.startsWith("onTap") || key.startsWith("onPan") || key.startsWith("onLayout") || validMotionProps.has(key);
|
|
124
|
+
}
|
|
125
|
+
function filterProps(props, isDom, forwardMotionProps) {
|
|
126
|
+
const filteredProps = {};
|
|
127
|
+
for (const key in props) {
|
|
128
|
+
if (key === "values" && typeof props.values === "object") continue;
|
|
129
|
+
if (!isValidMotionProp(key) || forwardMotionProps === true && isValidMotionProp(key) || !isDom && !isValidMotionProp(key) || props.draggable && key.startsWith("onDrag")) {
|
|
130
|
+
filteredProps[key] = props[key];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return filteredProps;
|
|
134
|
+
}
|
|
135
|
+
const createDomVisualElement = (Component, options) => {
|
|
136
|
+
const isSVG = options.isSVG ?? isSVGComponent(Component);
|
|
137
|
+
return isSVG ? new SVGVisualElement(options) : new HTMLVisualElement(options, {
|
|
138
|
+
allowProjection: Component !== "svg"
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
const createHtmlRenderState = () => ({
|
|
142
|
+
style: {},
|
|
143
|
+
transform: {},
|
|
144
|
+
transformOrigin: {},
|
|
145
|
+
vars: {}
|
|
146
|
+
});
|
|
147
|
+
function toSolidStyle(style2) {
|
|
148
|
+
const result = {};
|
|
149
|
+
for (const key in style2) {
|
|
150
|
+
const name = key.startsWith("--") ? key : key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`).replace(/^ms-/, "-ms-");
|
|
151
|
+
result[name] = style2[key];
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
function copyRawValuesOnly(target, source, props) {
|
|
156
|
+
for (const key in source) {
|
|
157
|
+
if (!isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
|
|
158
|
+
target[key] = source[key];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function resolveInitialMotionValues({ transformTemplate }, visualState) {
|
|
163
|
+
const state = createHtmlRenderState();
|
|
164
|
+
buildHTMLStyles(state, visualState, transformTemplate);
|
|
165
|
+
return { ...state.vars, ...state.style };
|
|
166
|
+
}
|
|
167
|
+
function resolveStyle(props, visualState) {
|
|
168
|
+
const styleProp = props.style || {};
|
|
169
|
+
const style2 = {};
|
|
170
|
+
copyRawValuesOnly(style2, styleProp, props);
|
|
171
|
+
Object.assign(style2, resolveInitialMotionValues(props, visualState));
|
|
172
|
+
return style2;
|
|
173
|
+
}
|
|
174
|
+
function resolveHTMLProps(props, visualState) {
|
|
175
|
+
const htmlProps = {};
|
|
176
|
+
const style2 = resolveStyle(props, visualState);
|
|
177
|
+
if (props.drag && props.dragListener !== false) {
|
|
178
|
+
htmlProps.draggable = false;
|
|
179
|
+
style2.userSelect = style2.WebkitUserSelect = style2.WebkitTouchCallout = "none";
|
|
180
|
+
style2.touchAction = props.drag === true ? "none" : `pan-${props.drag === "x" ? "y" : "x"}`;
|
|
181
|
+
}
|
|
182
|
+
if (props.tabIndex === void 0 && (props.onTap || props.onTapStart || props.whileTap)) {
|
|
183
|
+
htmlProps.tabIndex = 0;
|
|
184
|
+
}
|
|
185
|
+
htmlProps.style = toSolidStyle(style2);
|
|
186
|
+
return htmlProps;
|
|
187
|
+
}
|
|
188
|
+
const createSvgRenderState = () => ({
|
|
189
|
+
...createHtmlRenderState(),
|
|
190
|
+
attrs: {}
|
|
191
|
+
});
|
|
192
|
+
function resolveSVGProps(props, visualState, Component) {
|
|
193
|
+
const state = createSvgRenderState();
|
|
194
|
+
buildSVGAttrs(state, visualState, isSVGTag(Component), props.transformTemplate, props.style);
|
|
195
|
+
const visualProps = {
|
|
196
|
+
...state.attrs,
|
|
197
|
+
style: { ...state.style }
|
|
198
|
+
};
|
|
199
|
+
if (props.style) {
|
|
200
|
+
const rawStyles = {};
|
|
201
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
202
|
+
visualProps.style = { ...rawStyles, ...visualProps.style };
|
|
203
|
+
}
|
|
204
|
+
const pathLength = visualState.pathLength;
|
|
205
|
+
const pathSpacing = visualState.pathSpacing;
|
|
206
|
+
const pathOffset = visualState.pathOffset;
|
|
207
|
+
if (pathLength !== void 0) {
|
|
208
|
+
const spacing = pathSpacing ?? 1 - Number(pathLength);
|
|
209
|
+
visualProps.pathLength = 1;
|
|
210
|
+
visualProps["stroke-dasharray"] = `${pathLength} ${spacing}`;
|
|
211
|
+
visualProps["stroke-dashoffset"] = `${-Number(pathOffset ?? 0)}`;
|
|
212
|
+
}
|
|
213
|
+
visualProps.style = toSolidStyle(visualProps.style);
|
|
214
|
+
return visualProps;
|
|
215
|
+
}
|
|
216
|
+
function makeState({ scrapeMotionValuesFromProps, createRenderState }, props, context, presenceContext) {
|
|
217
|
+
const state = {
|
|
218
|
+
latestValues: makeLatestValues(props, context, presenceContext, scrapeMotionValuesFromProps),
|
|
219
|
+
renderState: createRenderState()
|
|
220
|
+
};
|
|
221
|
+
return state;
|
|
222
|
+
}
|
|
223
|
+
function makeLatestValues(props, context, presenceContext, scrapeMotionValues) {
|
|
224
|
+
const values = {};
|
|
225
|
+
const motionValues = scrapeMotionValues(props, {});
|
|
226
|
+
for (const key in motionValues) {
|
|
227
|
+
values[key] = resolveMotionValue(motionValues[key]);
|
|
228
|
+
}
|
|
229
|
+
let { initial, animate: animate2 } = props;
|
|
230
|
+
const isControllingVariants$1 = isControllingVariants(props);
|
|
231
|
+
const isVariantNode$1 = isVariantNode(props);
|
|
232
|
+
if (context && isVariantNode$1 && !isControllingVariants$1 && props.inherit !== false) {
|
|
233
|
+
if (initial === void 0) initial = context.initial;
|
|
234
|
+
if (animate2 === void 0) animate2 = context.animate;
|
|
235
|
+
}
|
|
236
|
+
let isInitialAnimationBlocked = presenceContext ? presenceContext.initial === false : false;
|
|
237
|
+
isInitialAnimationBlocked = isInitialAnimationBlocked || initial === false;
|
|
238
|
+
const variantToSet = isInitialAnimationBlocked ? animate2 : initial;
|
|
239
|
+
if (variantToSet && typeof variantToSet !== "boolean" && !isAnimationControls(variantToSet)) {
|
|
240
|
+
const list = Array.isArray(variantToSet) ? variantToSet : [variantToSet];
|
|
241
|
+
for (let i = 0; i < list.length; i++) {
|
|
242
|
+
const resolved = resolveVariantFromProps(props, list[i]);
|
|
243
|
+
if (resolved) {
|
|
244
|
+
const { transitionEnd, transition, ...target } = resolved;
|
|
245
|
+
for (const key in target) {
|
|
246
|
+
let valueTarget = target[key];
|
|
247
|
+
if (Array.isArray(valueTarget)) {
|
|
248
|
+
const index = isInitialAnimationBlocked ? valueTarget.length - 1 : 0;
|
|
249
|
+
valueTarget = valueTarget[index];
|
|
250
|
+
}
|
|
251
|
+
if (valueTarget !== null) {
|
|
252
|
+
values[key] = valueTarget;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
for (const key in transitionEnd) {
|
|
256
|
+
values[key] = transitionEnd[key];
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return values;
|
|
262
|
+
}
|
|
263
|
+
function makeVisualState(config, props, context, presenceContext) {
|
|
264
|
+
return makeState(config, props, context, presenceContext);
|
|
265
|
+
}
|
|
266
|
+
const featureProps = {
|
|
267
|
+
animation: ["animate", "variants", "whileHover", "whileTap", "exit", "whileInView", "whileFocus", "whileDrag"],
|
|
268
|
+
exit: ["exit"],
|
|
269
|
+
drag: ["drag", "dragControls"],
|
|
270
|
+
focus: ["whileFocus"],
|
|
271
|
+
hover: ["whileHover", "onHoverStart", "onHoverEnd"],
|
|
272
|
+
tap: ["whileTap", "onTap", "onTapStart", "onTapCancel"],
|
|
273
|
+
pan: ["onPan", "onPanStart", "onPanSessionStart", "onPanEnd"],
|
|
274
|
+
inView: ["whileInView", "onViewportEnter", "onViewportLeave"],
|
|
275
|
+
layout: ["layout", "layoutId"]
|
|
276
|
+
};
|
|
277
|
+
let isInitialized = false;
|
|
278
|
+
function initFeatureDefinitions() {
|
|
279
|
+
if (isInitialized) return;
|
|
280
|
+
const initialFeatureDefinitions = {};
|
|
281
|
+
for (const key in featureProps) {
|
|
282
|
+
initialFeatureDefinitions[key] = {
|
|
283
|
+
isEnabled: (props) => featureProps[key].some((name) => Boolean(props[name]))
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
setFeatureDefinitions(initialFeatureDefinitions);
|
|
287
|
+
isInitialized = true;
|
|
288
|
+
}
|
|
289
|
+
function getInitializedFeatureDefinitions() {
|
|
290
|
+
initFeatureDefinitions();
|
|
291
|
+
return getFeatureDefinitions();
|
|
292
|
+
}
|
|
293
|
+
function loadFeatures(features) {
|
|
294
|
+
const featureDefinitions = getInitializedFeatureDefinitions();
|
|
295
|
+
for (const key in features) {
|
|
296
|
+
featureDefinitions[key] = {
|
|
297
|
+
...featureDefinitions[key],
|
|
298
|
+
...features[key]
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
setFeatureDefinitions(featureDefinitions);
|
|
302
|
+
}
|
|
303
|
+
class AnimationFeature extends Feature {
|
|
304
|
+
constructor(node) {
|
|
305
|
+
super(node);
|
|
306
|
+
node.animationState || (node.animationState = createAnimationState(node));
|
|
307
|
+
}
|
|
308
|
+
updateAnimationControlsSubscription() {
|
|
309
|
+
const { animate: animate2 } = this.node.getProps();
|
|
310
|
+
if (isAnimationControls(animate2)) {
|
|
311
|
+
this.unmountControls = animate2.subscribe(this.node);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
mount() {
|
|
315
|
+
this.updateAnimationControlsSubscription();
|
|
316
|
+
}
|
|
317
|
+
update() {
|
|
318
|
+
const { animate: animate2 } = this.node.getProps();
|
|
319
|
+
const { animate: prevAnimate } = this.node.prevProps || {};
|
|
320
|
+
if (animate2 !== prevAnimate) {
|
|
321
|
+
this.updateAnimationControlsSubscription();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
unmount() {
|
|
325
|
+
this.node.animationState?.reset();
|
|
326
|
+
this.unmountControls?.();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
let id = 0;
|
|
330
|
+
class ExitAnimationFeature extends Feature {
|
|
331
|
+
constructor() {
|
|
332
|
+
super(...arguments);
|
|
333
|
+
this.id = id++;
|
|
334
|
+
}
|
|
335
|
+
update() {
|
|
336
|
+
if (!this.node.presenceContext) return;
|
|
337
|
+
const { isPresent, onExitComplete } = this.node.presenceContext;
|
|
338
|
+
const { isPresent: prevIsPresent } = this.node.prevPresenceContext || {};
|
|
339
|
+
if (!this.node.animationState || isPresent === prevIsPresent) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const exitAnimation = this.node.animationState.setActive("exit", !isPresent);
|
|
343
|
+
if (onExitComplete && !isPresent) {
|
|
344
|
+
exitAnimation.then(() => {
|
|
345
|
+
onExitComplete(this.id);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
mount() {
|
|
350
|
+
const { register, onExitComplete } = this.node.presenceContext || {};
|
|
351
|
+
if (onExitComplete) {
|
|
352
|
+
onExitComplete(this.id);
|
|
353
|
+
}
|
|
354
|
+
if (register) {
|
|
355
|
+
this.unmount = register(this.id);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
unmount() {
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
const animations = {
|
|
362
|
+
animation: {
|
|
363
|
+
Feature: AnimationFeature
|
|
364
|
+
},
|
|
365
|
+
exit: {
|
|
366
|
+
Feature: ExitAnimationFeature
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
function extractEventInfo(event) {
|
|
370
|
+
return {
|
|
371
|
+
point: {
|
|
372
|
+
x: event.pageX,
|
|
373
|
+
y: event.pageY
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const addPointerInfo = (handler) => {
|
|
378
|
+
return (event) => {
|
|
379
|
+
const pointer = event;
|
|
380
|
+
if (isPrimaryPointer(pointer)) handler(pointer, extractEventInfo(pointer));
|
|
381
|
+
};
|
|
382
|
+
};
|
|
383
|
+
function addPointerEvent(target, eventName, handler, options) {
|
|
384
|
+
return addDomEvent(target, eventName, addPointerInfo(handler), options);
|
|
385
|
+
}
|
|
386
|
+
const getContextWindow = ({ current }) => {
|
|
387
|
+
return current ? current.ownerDocument.defaultView : null;
|
|
388
|
+
};
|
|
389
|
+
function isRefObject(ref) {
|
|
390
|
+
return ref && typeof ref === "object" && Object.prototype.hasOwnProperty.call(ref, "current");
|
|
391
|
+
}
|
|
392
|
+
const distance = (a, b) => Math.abs(a - b);
|
|
393
|
+
function distance2D(a, b) {
|
|
394
|
+
const xDelta = distance(a.x, b.x);
|
|
395
|
+
const yDelta = distance(a.y, b.y);
|
|
396
|
+
return Math.sqrt(xDelta ** 2 + yDelta ** 2);
|
|
397
|
+
}
|
|
398
|
+
const overflowStyles = /* @__PURE__ */ new Set(["auto", "scroll"]);
|
|
399
|
+
class PanSession {
|
|
400
|
+
constructor(event, handlers, {
|
|
401
|
+
transformPagePoint,
|
|
402
|
+
contextWindow = window,
|
|
403
|
+
dragSnapToOrigin = false,
|
|
404
|
+
distanceThreshold = 3,
|
|
405
|
+
element
|
|
406
|
+
} = {}) {
|
|
407
|
+
this.history = [];
|
|
408
|
+
this.startEvent = null;
|
|
409
|
+
this.lastMoveEvent = null;
|
|
410
|
+
this.lastMoveEventInfo = null;
|
|
411
|
+
this.handlers = {};
|
|
412
|
+
this.removeListeners = () => {
|
|
413
|
+
};
|
|
414
|
+
this.dragSnapToOrigin = false;
|
|
415
|
+
this.distanceThreshold = 3;
|
|
416
|
+
this.contextWindow = window;
|
|
417
|
+
this.scrollPositions = /* @__PURE__ */ new Map();
|
|
418
|
+
this.removeScrollListeners = null;
|
|
419
|
+
this.onElementScroll = (event2) => {
|
|
420
|
+
this.handleScroll(event2.target);
|
|
421
|
+
};
|
|
422
|
+
this.onWindowScroll = () => {
|
|
423
|
+
this.handleScroll(window);
|
|
424
|
+
};
|
|
425
|
+
this.updatePoint = () => {
|
|
426
|
+
if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return;
|
|
427
|
+
const info2 = getPanInfo(this.lastMoveEventInfo, this.history);
|
|
428
|
+
const isPanStarted = this.startEvent !== null;
|
|
429
|
+
const isDistancePastThreshold = distance2D(info2.offset, { x: 0, y: 0 }) >= this.distanceThreshold;
|
|
430
|
+
if (!isPanStarted && !isDistancePastThreshold) return;
|
|
431
|
+
const { point: point2 } = info2;
|
|
432
|
+
const { timestamp: timestamp2 } = frameData;
|
|
433
|
+
this.history.push({ ...point2, timestamp: timestamp2 });
|
|
434
|
+
const { onStart, onMove } = this.handlers;
|
|
435
|
+
if (!isPanStarted) {
|
|
436
|
+
onStart && onStart(this.lastMoveEvent, info2);
|
|
437
|
+
this.startEvent = this.lastMoveEvent;
|
|
438
|
+
}
|
|
439
|
+
onMove && onMove(this.lastMoveEvent, info2);
|
|
440
|
+
};
|
|
441
|
+
this.handlePointerMove = (event2, info2) => {
|
|
442
|
+
this.lastMoveEvent = event2;
|
|
443
|
+
this.lastMoveEventInfo = transformPoint(info2, this.transformPagePoint);
|
|
444
|
+
frame.update(this.updatePoint, true);
|
|
445
|
+
};
|
|
446
|
+
this.handlePointerUp = (event2, info2) => {
|
|
447
|
+
this.end();
|
|
448
|
+
const { onEnd, onSessionEnd, resumeAnimation } = this.handlers;
|
|
449
|
+
if (this.dragSnapToOrigin || !this.startEvent) {
|
|
450
|
+
resumeAnimation && resumeAnimation();
|
|
451
|
+
}
|
|
452
|
+
if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return;
|
|
453
|
+
const panInfo = getPanInfo(
|
|
454
|
+
event2.type === "pointercancel" ? this.lastMoveEventInfo : transformPoint(info2, this.transformPagePoint),
|
|
455
|
+
this.history
|
|
456
|
+
);
|
|
457
|
+
if (this.startEvent && onEnd) {
|
|
458
|
+
onEnd(event2, panInfo);
|
|
459
|
+
}
|
|
460
|
+
onSessionEnd && onSessionEnd(event2, panInfo);
|
|
461
|
+
};
|
|
462
|
+
if (!isPrimaryPointer(event)) return;
|
|
463
|
+
this.dragSnapToOrigin = dragSnapToOrigin;
|
|
464
|
+
this.handlers = handlers;
|
|
465
|
+
this.transformPagePoint = transformPagePoint;
|
|
466
|
+
this.distanceThreshold = distanceThreshold;
|
|
467
|
+
this.contextWindow = contextWindow || window;
|
|
468
|
+
const info = extractEventInfo(event);
|
|
469
|
+
const initialInfo = transformPoint(info, this.transformPagePoint);
|
|
470
|
+
const { point } = initialInfo;
|
|
471
|
+
const { timestamp } = frameData;
|
|
472
|
+
this.history = [{ ...point, timestamp }];
|
|
473
|
+
const { onSessionStart } = handlers;
|
|
474
|
+
onSessionStart && onSessionStart(event, getPanInfo(initialInfo, this.history));
|
|
475
|
+
this.removeListeners = pipe(
|
|
476
|
+
addPointerEvent(
|
|
477
|
+
this.contextWindow,
|
|
478
|
+
"pointermove",
|
|
479
|
+
this.handlePointerMove
|
|
480
|
+
),
|
|
481
|
+
addPointerEvent(
|
|
482
|
+
this.contextWindow,
|
|
483
|
+
"pointerup",
|
|
484
|
+
this.handlePointerUp
|
|
485
|
+
),
|
|
486
|
+
addPointerEvent(
|
|
487
|
+
this.contextWindow,
|
|
488
|
+
"pointercancel",
|
|
489
|
+
this.handlePointerUp
|
|
490
|
+
)
|
|
491
|
+
);
|
|
492
|
+
if (element) {
|
|
493
|
+
this.startScrollTracking(element);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Start tracking scroll on ancestors and window.
|
|
498
|
+
*/
|
|
499
|
+
startScrollTracking(element) {
|
|
500
|
+
let current = element.parentElement;
|
|
501
|
+
while (current) {
|
|
502
|
+
const style2 = getComputedStyle(current);
|
|
503
|
+
if (overflowStyles.has(style2.overflowX) || overflowStyles.has(style2.overflowY)) {
|
|
504
|
+
this.scrollPositions.set(current, {
|
|
505
|
+
x: current.scrollLeft,
|
|
506
|
+
y: current.scrollTop
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
current = current.parentElement;
|
|
510
|
+
}
|
|
511
|
+
this.scrollPositions.set(window, {
|
|
512
|
+
x: window.scrollX,
|
|
513
|
+
y: window.scrollY
|
|
514
|
+
});
|
|
515
|
+
window.addEventListener("scroll", this.onElementScroll, {
|
|
516
|
+
capture: true,
|
|
517
|
+
passive: true
|
|
518
|
+
});
|
|
519
|
+
window.addEventListener("scroll", this.onWindowScroll, {
|
|
520
|
+
passive: true
|
|
521
|
+
});
|
|
522
|
+
this.removeScrollListeners = () => {
|
|
523
|
+
window.removeEventListener("scroll", this.onElementScroll, {
|
|
524
|
+
capture: true
|
|
525
|
+
});
|
|
526
|
+
window.removeEventListener("scroll", this.onWindowScroll);
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Handle scroll compensation during drag.
|
|
531
|
+
*
|
|
532
|
+
* For element scroll: adjusts history origin since pageX/pageY doesn't change.
|
|
533
|
+
* For window scroll: adjusts lastMoveEventInfo since pageX/pageY would change.
|
|
534
|
+
*/
|
|
535
|
+
handleScroll(target) {
|
|
536
|
+
const initial = this.scrollPositions.get(target);
|
|
537
|
+
if (!initial) return;
|
|
538
|
+
const isWindow = target === window;
|
|
539
|
+
const current = isWindow ? { x: window.scrollX, y: window.scrollY } : {
|
|
540
|
+
x: target.scrollLeft,
|
|
541
|
+
y: target.scrollTop
|
|
542
|
+
};
|
|
543
|
+
const delta = { x: current.x - initial.x, y: current.y - initial.y };
|
|
544
|
+
if (delta.x === 0 && delta.y === 0) return;
|
|
545
|
+
if (isWindow) {
|
|
546
|
+
if (this.lastMoveEventInfo) {
|
|
547
|
+
this.lastMoveEventInfo.point.x += delta.x;
|
|
548
|
+
this.lastMoveEventInfo.point.y += delta.y;
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
if (this.history.length > 0) {
|
|
552
|
+
this.history[0].x -= delta.x;
|
|
553
|
+
this.history[0].y -= delta.y;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
this.scrollPositions.set(target, current);
|
|
557
|
+
frame.update(this.updatePoint, true);
|
|
558
|
+
}
|
|
559
|
+
updateHandlers(handlers) {
|
|
560
|
+
this.handlers = handlers;
|
|
561
|
+
}
|
|
562
|
+
end() {
|
|
563
|
+
this.removeListeners && this.removeListeners();
|
|
564
|
+
this.removeScrollListeners && this.removeScrollListeners();
|
|
565
|
+
this.scrollPositions.clear();
|
|
566
|
+
cancelFrame(this.updatePoint);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function transformPoint(info, transformPagePoint) {
|
|
570
|
+
return transformPagePoint ? { point: transformPagePoint(info.point) } : info;
|
|
571
|
+
}
|
|
572
|
+
function subtractPoint(a, b) {
|
|
573
|
+
return { x: a.x - b.x, y: a.y - b.y };
|
|
574
|
+
}
|
|
575
|
+
function getPanInfo({ point }, history) {
|
|
576
|
+
return {
|
|
577
|
+
point,
|
|
578
|
+
delta: subtractPoint(point, lastDevicePoint(history)),
|
|
579
|
+
offset: subtractPoint(point, startDevicePoint(history)),
|
|
580
|
+
velocity: getVelocity(history, 0.1)
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
function startDevicePoint(history) {
|
|
584
|
+
return history[0];
|
|
585
|
+
}
|
|
586
|
+
function lastDevicePoint(history) {
|
|
587
|
+
return history[history.length - 1];
|
|
588
|
+
}
|
|
589
|
+
function getVelocity(history, timeDelta) {
|
|
590
|
+
if (history.length < 2) {
|
|
591
|
+
return { x: 0, y: 0 };
|
|
592
|
+
}
|
|
593
|
+
let i = history.length - 1;
|
|
594
|
+
let timestampedPoint = null;
|
|
595
|
+
const lastPoint = lastDevicePoint(history);
|
|
596
|
+
while (i >= 0) {
|
|
597
|
+
timestampedPoint = history[i];
|
|
598
|
+
if (lastPoint.timestamp - timestampedPoint.timestamp > secondsToMilliseconds(timeDelta)) {
|
|
599
|
+
break;
|
|
600
|
+
}
|
|
601
|
+
i--;
|
|
602
|
+
}
|
|
603
|
+
if (!timestampedPoint) {
|
|
604
|
+
return { x: 0, y: 0 };
|
|
605
|
+
}
|
|
606
|
+
const time = millisecondsToSeconds(
|
|
607
|
+
lastPoint.timestamp - timestampedPoint.timestamp
|
|
608
|
+
);
|
|
609
|
+
if (time === 0) {
|
|
610
|
+
return { x: 0, y: 0 };
|
|
611
|
+
}
|
|
612
|
+
const currentVelocity = {
|
|
613
|
+
x: (lastPoint.x - timestampedPoint.x) / time,
|
|
614
|
+
y: (lastPoint.y - timestampedPoint.y) / time
|
|
615
|
+
};
|
|
616
|
+
if (currentVelocity.x === Infinity) {
|
|
617
|
+
currentVelocity.x = 0;
|
|
618
|
+
}
|
|
619
|
+
if (currentVelocity.y === Infinity) {
|
|
620
|
+
currentVelocity.y = 0;
|
|
621
|
+
}
|
|
622
|
+
return currentVelocity;
|
|
623
|
+
}
|
|
624
|
+
function applyConstraints(point, { min, max }, elastic) {
|
|
625
|
+
if (min !== void 0 && point < min) {
|
|
626
|
+
point = elastic ? mixNumber(min, point, elastic.min) : Math.max(point, min);
|
|
627
|
+
} else if (max !== void 0 && point > max) {
|
|
628
|
+
point = elastic ? mixNumber(max, point, elastic.max) : Math.min(point, max);
|
|
629
|
+
}
|
|
630
|
+
return point;
|
|
631
|
+
}
|
|
632
|
+
function calcRelativeAxisConstraints(axis, min, max) {
|
|
633
|
+
return {
|
|
634
|
+
min: min !== void 0 ? axis.min + min : void 0,
|
|
635
|
+
max: max !== void 0 ? axis.max + max - (axis.max - axis.min) : void 0
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function calcRelativeConstraints(layoutBox, { top, left, bottom, right }) {
|
|
639
|
+
return {
|
|
640
|
+
x: calcRelativeAxisConstraints(layoutBox.x, left, right),
|
|
641
|
+
y: calcRelativeAxisConstraints(layoutBox.y, top, bottom)
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function calcViewportAxisConstraints(layoutAxis, constraintsAxis) {
|
|
645
|
+
let min = constraintsAxis.min - layoutAxis.min;
|
|
646
|
+
let max = constraintsAxis.max - layoutAxis.max;
|
|
647
|
+
if (constraintsAxis.max - constraintsAxis.min < layoutAxis.max - layoutAxis.min) {
|
|
648
|
+
[min, max] = [max, min];
|
|
649
|
+
}
|
|
650
|
+
return { min, max };
|
|
651
|
+
}
|
|
652
|
+
function calcViewportConstraints(layoutBox, constraintsBox) {
|
|
653
|
+
return {
|
|
654
|
+
x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),
|
|
655
|
+
y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y)
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function calcOrigin(source, target) {
|
|
659
|
+
let origin = 0.5;
|
|
660
|
+
const sourceLength = calcLength(source);
|
|
661
|
+
const targetLength = calcLength(target);
|
|
662
|
+
if (targetLength > sourceLength) {
|
|
663
|
+
origin = progress(target.min, target.max - sourceLength, source.min);
|
|
664
|
+
} else if (sourceLength > targetLength) {
|
|
665
|
+
origin = progress(source.min, source.max - targetLength, target.min);
|
|
666
|
+
}
|
|
667
|
+
return clamp(0, 1, origin);
|
|
668
|
+
}
|
|
669
|
+
function rebaseAxisConstraints(layout, constraints) {
|
|
670
|
+
const relativeConstraints = {};
|
|
671
|
+
if (constraints.min !== void 0) {
|
|
672
|
+
relativeConstraints.min = constraints.min - layout.min;
|
|
673
|
+
}
|
|
674
|
+
if (constraints.max !== void 0) {
|
|
675
|
+
relativeConstraints.max = constraints.max - layout.min;
|
|
676
|
+
}
|
|
677
|
+
return relativeConstraints;
|
|
678
|
+
}
|
|
679
|
+
const defaultElastic = 0.35;
|
|
680
|
+
function resolveDragElastic(dragElastic = defaultElastic) {
|
|
681
|
+
if (dragElastic === false) {
|
|
682
|
+
dragElastic = 0;
|
|
683
|
+
} else if (dragElastic === true) {
|
|
684
|
+
dragElastic = defaultElastic;
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
x: resolveAxisElastic(dragElastic, "left", "right"),
|
|
688
|
+
y: resolveAxisElastic(dragElastic, "top", "bottom")
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function resolveAxisElastic(dragElastic, minLabel, maxLabel) {
|
|
692
|
+
return {
|
|
693
|
+
min: resolvePointElastic(dragElastic, minLabel),
|
|
694
|
+
max: resolvePointElastic(dragElastic, maxLabel)
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
function resolvePointElastic(dragElastic, label) {
|
|
698
|
+
return typeof dragElastic === "number" ? dragElastic : dragElastic[label] || 0;
|
|
699
|
+
}
|
|
700
|
+
const elementDragControls = /* @__PURE__ */ new WeakMap();
|
|
701
|
+
class VisualElementDragControls {
|
|
702
|
+
constructor(visualElement) {
|
|
703
|
+
this.openDragLock = null;
|
|
704
|
+
this.isDragging = false;
|
|
705
|
+
this.currentDirection = null;
|
|
706
|
+
this.originPoint = { x: 0, y: 0 };
|
|
707
|
+
this.constraints = false;
|
|
708
|
+
this.hasMutatedConstraints = false;
|
|
709
|
+
this.elastic = createBox();
|
|
710
|
+
this.latestPointerEvent = null;
|
|
711
|
+
this.latestPanInfo = null;
|
|
712
|
+
this.visualElement = visualElement;
|
|
713
|
+
}
|
|
714
|
+
start(originEvent, { snapToCursor = false, distanceThreshold } = {}) {
|
|
715
|
+
const { presenceContext } = this.visualElement;
|
|
716
|
+
if (presenceContext && presenceContext.isPresent === false) return;
|
|
717
|
+
const onSessionStart = (event) => {
|
|
718
|
+
if (snapToCursor) {
|
|
719
|
+
this.stopAnimation();
|
|
720
|
+
this.snapToCursor(extractEventInfo(event).point);
|
|
721
|
+
} else {
|
|
722
|
+
this.pauseAnimation();
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
const onStart = (event, info) => {
|
|
726
|
+
this.stopAnimation();
|
|
727
|
+
const { drag, dragPropagation, onDragStart } = this.getProps();
|
|
728
|
+
if (drag && !dragPropagation) {
|
|
729
|
+
if (this.openDragLock) this.openDragLock();
|
|
730
|
+
this.openDragLock = setDragLock(drag);
|
|
731
|
+
if (!this.openDragLock) return;
|
|
732
|
+
}
|
|
733
|
+
this.latestPointerEvent = event;
|
|
734
|
+
this.latestPanInfo = info;
|
|
735
|
+
this.isDragging = true;
|
|
736
|
+
this.currentDirection = null;
|
|
737
|
+
this.resolveConstraints();
|
|
738
|
+
if (this.visualElement.projection) {
|
|
739
|
+
this.visualElement.projection.isAnimationBlocked = true;
|
|
740
|
+
this.visualElement.projection.target = void 0;
|
|
741
|
+
}
|
|
742
|
+
eachAxis((axis) => {
|
|
743
|
+
let current = this.getAxisMotionValue(axis).get() || 0;
|
|
744
|
+
if (percent.test(current)) {
|
|
745
|
+
const { projection } = this.visualElement;
|
|
746
|
+
if (projection && projection.layout) {
|
|
747
|
+
const measuredAxis = projection.layout.layoutBox[axis];
|
|
748
|
+
if (measuredAxis) {
|
|
749
|
+
const length = calcLength(measuredAxis);
|
|
750
|
+
current = length * (parseFloat(current) / 100);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
this.originPoint[axis] = current;
|
|
755
|
+
});
|
|
756
|
+
if (onDragStart) {
|
|
757
|
+
frame.postRender(() => onDragStart(event, info));
|
|
758
|
+
}
|
|
759
|
+
addValueToWillChange(this.visualElement, "transform");
|
|
760
|
+
const { animationState } = this.visualElement;
|
|
761
|
+
animationState && animationState.setActive("whileDrag", true);
|
|
762
|
+
};
|
|
763
|
+
const onMove = (event, info) => {
|
|
764
|
+
this.latestPointerEvent = event;
|
|
765
|
+
this.latestPanInfo = info;
|
|
766
|
+
const {
|
|
767
|
+
dragPropagation,
|
|
768
|
+
dragDirectionLock,
|
|
769
|
+
onDirectionLock,
|
|
770
|
+
onDrag
|
|
771
|
+
} = this.getProps();
|
|
772
|
+
if (!dragPropagation && !this.openDragLock) return;
|
|
773
|
+
const { offset } = info;
|
|
774
|
+
if (dragDirectionLock && this.currentDirection === null) {
|
|
775
|
+
this.currentDirection = getCurrentDirection(offset);
|
|
776
|
+
if (this.currentDirection !== null) {
|
|
777
|
+
onDirectionLock && onDirectionLock(this.currentDirection);
|
|
778
|
+
}
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
this.updateAxis("x", info.point, offset);
|
|
782
|
+
this.updateAxis("y", info.point, offset);
|
|
783
|
+
this.visualElement.render();
|
|
784
|
+
onDrag && onDrag(event, info);
|
|
785
|
+
};
|
|
786
|
+
const onSessionEnd = (event, info) => {
|
|
787
|
+
this.latestPointerEvent = event;
|
|
788
|
+
this.latestPanInfo = info;
|
|
789
|
+
this.stop(event, info);
|
|
790
|
+
this.latestPointerEvent = null;
|
|
791
|
+
this.latestPanInfo = null;
|
|
792
|
+
};
|
|
793
|
+
const resumeAnimation = () => eachAxis(
|
|
794
|
+
(axis) => this.getAnimationState(axis) === "paused" && this.getAxisMotionValue(axis).animation?.play()
|
|
795
|
+
);
|
|
796
|
+
const { dragSnapToOrigin } = this.getProps();
|
|
797
|
+
this.panSession = new PanSession(
|
|
798
|
+
originEvent,
|
|
799
|
+
{
|
|
800
|
+
onSessionStart,
|
|
801
|
+
onStart,
|
|
802
|
+
onMove,
|
|
803
|
+
onSessionEnd,
|
|
804
|
+
resumeAnimation
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
transformPagePoint: this.visualElement.getTransformPagePoint(),
|
|
808
|
+
dragSnapToOrigin,
|
|
809
|
+
distanceThreshold,
|
|
810
|
+
contextWindow: getContextWindow(this.visualElement),
|
|
811
|
+
element: this.visualElement.current
|
|
812
|
+
}
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* @internal
|
|
817
|
+
*/
|
|
818
|
+
stop(event, panInfo) {
|
|
819
|
+
const finalEvent = event || this.latestPointerEvent;
|
|
820
|
+
const finalPanInfo = panInfo || this.latestPanInfo;
|
|
821
|
+
const isDragging = this.isDragging;
|
|
822
|
+
this.cancel();
|
|
823
|
+
if (!isDragging || !finalPanInfo || !finalEvent) return;
|
|
824
|
+
const { velocity } = finalPanInfo;
|
|
825
|
+
this.startAnimation(velocity);
|
|
826
|
+
const { onDragEnd } = this.getProps();
|
|
827
|
+
if (onDragEnd) {
|
|
828
|
+
frame.postRender(() => onDragEnd(finalEvent, finalPanInfo));
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* @internal
|
|
833
|
+
*/
|
|
834
|
+
cancel() {
|
|
835
|
+
this.isDragging = false;
|
|
836
|
+
const { projection, animationState } = this.visualElement;
|
|
837
|
+
if (projection) {
|
|
838
|
+
projection.isAnimationBlocked = false;
|
|
839
|
+
}
|
|
840
|
+
this.endPanSession();
|
|
841
|
+
const { dragPropagation } = this.getProps();
|
|
842
|
+
if (!dragPropagation && this.openDragLock) {
|
|
843
|
+
this.openDragLock();
|
|
844
|
+
this.openDragLock = null;
|
|
845
|
+
}
|
|
846
|
+
animationState && animationState.setActive("whileDrag", false);
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Clean up the pan session without modifying other drag state.
|
|
850
|
+
* This is used during unmount to ensure event listeners are removed
|
|
851
|
+
* without affecting projection animations or drag locks.
|
|
852
|
+
* @internal
|
|
853
|
+
*/
|
|
854
|
+
endPanSession() {
|
|
855
|
+
this.panSession && this.panSession.end();
|
|
856
|
+
this.panSession = void 0;
|
|
857
|
+
}
|
|
858
|
+
/** Final owner disposal, including any release inertia on external values. */
|
|
859
|
+
dispose() {
|
|
860
|
+
this.cancel();
|
|
861
|
+
this.stopAnimation();
|
|
862
|
+
elementDragControls.delete(this.visualElement);
|
|
863
|
+
}
|
|
864
|
+
updateAxis(axis, _point, offset) {
|
|
865
|
+
const { drag } = this.getProps();
|
|
866
|
+
if (!offset || !shouldDrag(axis, drag, this.currentDirection)) return;
|
|
867
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
868
|
+
let next = this.originPoint[axis] + offset[axis];
|
|
869
|
+
if (this.constraints && this.constraints[axis]) {
|
|
870
|
+
next = applyConstraints(
|
|
871
|
+
next,
|
|
872
|
+
this.constraints[axis],
|
|
873
|
+
this.elastic[axis]
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
axisValue.set(next);
|
|
877
|
+
}
|
|
878
|
+
resolveConstraints() {
|
|
879
|
+
const { dragConstraints, dragElastic } = this.getProps();
|
|
880
|
+
const layout = this.visualElement.projection && !this.visualElement.projection.layout ? this.visualElement.projection.measure(false) : this.visualElement.projection?.layout;
|
|
881
|
+
const prevConstraints = this.constraints;
|
|
882
|
+
if (dragConstraints && isRefObject(dragConstraints)) {
|
|
883
|
+
if (!this.constraints) {
|
|
884
|
+
this.constraints = this.resolveRefConstraints();
|
|
885
|
+
}
|
|
886
|
+
} else {
|
|
887
|
+
if (dragConstraints && layout) {
|
|
888
|
+
this.constraints = calcRelativeConstraints(
|
|
889
|
+
layout.layoutBox,
|
|
890
|
+
dragConstraints
|
|
891
|
+
);
|
|
892
|
+
} else {
|
|
893
|
+
this.constraints = false;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
this.elastic = resolveDragElastic(dragElastic);
|
|
897
|
+
if (prevConstraints !== this.constraints && layout && this.constraints && !this.hasMutatedConstraints) {
|
|
898
|
+
eachAxis((axis) => {
|
|
899
|
+
if (this.constraints !== false && this.getAxisMotionValue(axis)) {
|
|
900
|
+
this.constraints[axis] = rebaseAxisConstraints(
|
|
901
|
+
layout.layoutBox[axis],
|
|
902
|
+
this.constraints[axis]
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
resolveRefConstraints() {
|
|
909
|
+
const { dragConstraints: constraints, onMeasureDragConstraints } = this.getProps();
|
|
910
|
+
if (!constraints || !isRefObject(constraints)) return false;
|
|
911
|
+
const constraintsElement = constraints.current;
|
|
912
|
+
invariant(
|
|
913
|
+
constraintsElement !== null,
|
|
914
|
+
"If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.",
|
|
915
|
+
"drag-constraints-ref"
|
|
916
|
+
);
|
|
917
|
+
const { projection } = this.visualElement;
|
|
918
|
+
if (!projection || !projection.layout) return false;
|
|
919
|
+
const constraintsBox = measurePageBox(
|
|
920
|
+
constraintsElement,
|
|
921
|
+
projection.root,
|
|
922
|
+
this.visualElement.getTransformPagePoint()
|
|
923
|
+
);
|
|
924
|
+
let measuredConstraints = calcViewportConstraints(
|
|
925
|
+
projection.layout.layoutBox,
|
|
926
|
+
constraintsBox
|
|
927
|
+
);
|
|
928
|
+
if (onMeasureDragConstraints) {
|
|
929
|
+
const userConstraints = onMeasureDragConstraints(
|
|
930
|
+
convertBoxToBoundingBox(measuredConstraints)
|
|
931
|
+
);
|
|
932
|
+
this.hasMutatedConstraints = !!userConstraints;
|
|
933
|
+
if (userConstraints) {
|
|
934
|
+
measuredConstraints = convertBoundingBoxToBox(userConstraints);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
return measuredConstraints;
|
|
938
|
+
}
|
|
939
|
+
startAnimation(velocity) {
|
|
940
|
+
const {
|
|
941
|
+
drag,
|
|
942
|
+
dragMomentum,
|
|
943
|
+
dragElastic,
|
|
944
|
+
dragTransition,
|
|
945
|
+
dragSnapToOrigin,
|
|
946
|
+
onDragTransitionEnd
|
|
947
|
+
} = this.getProps();
|
|
948
|
+
const constraints = this.constraints || {};
|
|
949
|
+
const momentumAnimations = eachAxis((axis) => {
|
|
950
|
+
if (!shouldDrag(axis, drag, this.currentDirection)) {
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
let transition = constraints && constraints[axis] || {};
|
|
954
|
+
if (dragSnapToOrigin) transition = { min: 0, max: 0 };
|
|
955
|
+
const bounceStiffness = dragElastic ? 200 : 1e6;
|
|
956
|
+
const bounceDamping = dragElastic ? 40 : 1e7;
|
|
957
|
+
const inertia = {
|
|
958
|
+
type: "inertia",
|
|
959
|
+
velocity: dragMomentum ? velocity[axis] : 0,
|
|
960
|
+
bounceStiffness,
|
|
961
|
+
bounceDamping,
|
|
962
|
+
timeConstant: 750,
|
|
963
|
+
restDelta: 1,
|
|
964
|
+
restSpeed: 10,
|
|
965
|
+
...dragTransition,
|
|
966
|
+
...transition
|
|
967
|
+
};
|
|
968
|
+
return this.startAxisValueAnimation(axis, inertia);
|
|
969
|
+
});
|
|
970
|
+
return Promise.all(momentumAnimations).then(onDragTransitionEnd);
|
|
971
|
+
}
|
|
972
|
+
startAxisValueAnimation(axis, transition) {
|
|
973
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
974
|
+
addValueToWillChange(this.visualElement, axis);
|
|
975
|
+
return axisValue.start(
|
|
976
|
+
animateMotionValue(
|
|
977
|
+
axis,
|
|
978
|
+
axisValue,
|
|
979
|
+
0,
|
|
980
|
+
transition,
|
|
981
|
+
this.visualElement,
|
|
982
|
+
false
|
|
983
|
+
)
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
stopAnimation() {
|
|
987
|
+
eachAxis((axis) => this.getAxisMotionValue(axis).stop());
|
|
988
|
+
}
|
|
989
|
+
pauseAnimation() {
|
|
990
|
+
eachAxis((axis) => this.getAxisMotionValue(axis).animation?.pause());
|
|
991
|
+
}
|
|
992
|
+
getAnimationState(axis) {
|
|
993
|
+
return this.getAxisMotionValue(axis).animation?.state;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Drag works differently depending on which props are provided.
|
|
997
|
+
*
|
|
998
|
+
* - If _dragX and _dragY are provided, we output the gesture delta directly to those motion values.
|
|
999
|
+
* - Otherwise, we apply the delta to the x/y motion values.
|
|
1000
|
+
*/
|
|
1001
|
+
getAxisMotionValue(axis) {
|
|
1002
|
+
const dragKey = `_drag${axis.toUpperCase()}`;
|
|
1003
|
+
const props = this.visualElement.getProps();
|
|
1004
|
+
const externalMotionValue = props[dragKey];
|
|
1005
|
+
return externalMotionValue ? externalMotionValue : this.visualElement.getValue(
|
|
1006
|
+
axis,
|
|
1007
|
+
(props.initial ? props.initial[axis] : void 0) || 0
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
snapToCursor(point) {
|
|
1011
|
+
eachAxis((axis) => {
|
|
1012
|
+
const { drag } = this.getProps();
|
|
1013
|
+
if (!shouldDrag(axis, drag, this.currentDirection)) return;
|
|
1014
|
+
const { projection } = this.visualElement;
|
|
1015
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1016
|
+
if (projection && projection.layout) {
|
|
1017
|
+
const { min, max } = projection.layout.layoutBox[axis];
|
|
1018
|
+
const current = axisValue.get() || 0;
|
|
1019
|
+
axisValue.set(point[axis] - mixNumber(min, max, 0.5) + current);
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* When the viewport resizes we want to check if the measured constraints
|
|
1025
|
+
* have changed and, if so, reposition the element within those new constraints
|
|
1026
|
+
* relative to where it was before the resize.
|
|
1027
|
+
*/
|
|
1028
|
+
scalePositionWithinConstraints() {
|
|
1029
|
+
if (!this.visualElement.current) return;
|
|
1030
|
+
const { drag, dragConstraints } = this.getProps();
|
|
1031
|
+
const { projection } = this.visualElement;
|
|
1032
|
+
if (!isRefObject(dragConstraints) || !projection || !this.constraints)
|
|
1033
|
+
return;
|
|
1034
|
+
this.stopAnimation();
|
|
1035
|
+
const boxProgress = { x: 0, y: 0 };
|
|
1036
|
+
eachAxis((axis) => {
|
|
1037
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1038
|
+
if (axisValue && this.constraints !== false) {
|
|
1039
|
+
const latest = axisValue.get();
|
|
1040
|
+
boxProgress[axis] = calcOrigin(
|
|
1041
|
+
{ min: latest, max: latest },
|
|
1042
|
+
this.constraints[axis]
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
const { transformTemplate } = this.visualElement.getProps();
|
|
1047
|
+
this.visualElement.current.style.transform = transformTemplate ? transformTemplate({}, "") : "none";
|
|
1048
|
+
projection.root && projection.root.updateScroll();
|
|
1049
|
+
projection.updateLayout();
|
|
1050
|
+
this.resolveConstraints();
|
|
1051
|
+
eachAxis((axis) => {
|
|
1052
|
+
if (!shouldDrag(axis, drag, null)) return;
|
|
1053
|
+
const axisValue = this.getAxisMotionValue(axis);
|
|
1054
|
+
const { min, max } = this.constraints[axis];
|
|
1055
|
+
axisValue.set(mixNumber(min, max, boxProgress[axis]));
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
addListeners() {
|
|
1059
|
+
if (!this.visualElement.current) return;
|
|
1060
|
+
elementDragControls.set(this.visualElement, this);
|
|
1061
|
+
const element = this.visualElement.current;
|
|
1062
|
+
const stopPointerListener = addPointerEvent(
|
|
1063
|
+
element,
|
|
1064
|
+
"pointerdown",
|
|
1065
|
+
(event) => {
|
|
1066
|
+
const { drag, dragListener = true } = this.getProps();
|
|
1067
|
+
const target = event.target;
|
|
1068
|
+
const isClickingTextInputChild = target !== element && (Boolean(target.closest("input, textarea, select")) || target instanceof HTMLElement && target.isContentEditable);
|
|
1069
|
+
if (drag && dragListener && !isClickingTextInputChild) {
|
|
1070
|
+
this.start(event);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
);
|
|
1074
|
+
const measureDragConstraints = () => {
|
|
1075
|
+
const { dragConstraints } = this.getProps();
|
|
1076
|
+
if (isRefObject(dragConstraints) && dragConstraints.current) {
|
|
1077
|
+
this.constraints = this.resolveRefConstraints();
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
const { projection } = this.visualElement;
|
|
1081
|
+
const stopMeasureLayoutListener = projection.addEventListener(
|
|
1082
|
+
"measure",
|
|
1083
|
+
measureDragConstraints
|
|
1084
|
+
);
|
|
1085
|
+
if (projection && !projection.layout) {
|
|
1086
|
+
projection.root && projection.root.updateScroll();
|
|
1087
|
+
projection.updateLayout();
|
|
1088
|
+
}
|
|
1089
|
+
frame.read(measureDragConstraints);
|
|
1090
|
+
const stopResizeListener = addDomEvent(
|
|
1091
|
+
window,
|
|
1092
|
+
"resize",
|
|
1093
|
+
() => this.scalePositionWithinConstraints()
|
|
1094
|
+
);
|
|
1095
|
+
const stopLayoutUpdateListener = projection.addEventListener(
|
|
1096
|
+
"didUpdate",
|
|
1097
|
+
(({ delta, hasLayoutChanged }) => {
|
|
1098
|
+
if (this.isDragging && hasLayoutChanged) {
|
|
1099
|
+
eachAxis((axis) => {
|
|
1100
|
+
const motionValue2 = this.getAxisMotionValue(axis);
|
|
1101
|
+
if (!motionValue2) return;
|
|
1102
|
+
this.originPoint[axis] += delta[axis].translate;
|
|
1103
|
+
motionValue2.set(
|
|
1104
|
+
motionValue2.get() + delta[axis].translate
|
|
1105
|
+
);
|
|
1106
|
+
});
|
|
1107
|
+
this.visualElement.render();
|
|
1108
|
+
}
|
|
1109
|
+
})
|
|
1110
|
+
);
|
|
1111
|
+
return () => {
|
|
1112
|
+
cancelFrame(measureDragConstraints);
|
|
1113
|
+
stopResizeListener();
|
|
1114
|
+
stopPointerListener();
|
|
1115
|
+
stopMeasureLayoutListener();
|
|
1116
|
+
stopLayoutUpdateListener && stopLayoutUpdateListener();
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
getProps() {
|
|
1120
|
+
const props = this.visualElement.getProps();
|
|
1121
|
+
const {
|
|
1122
|
+
drag = false,
|
|
1123
|
+
dragDirectionLock = false,
|
|
1124
|
+
dragPropagation = false,
|
|
1125
|
+
dragConstraints = false,
|
|
1126
|
+
dragElastic = defaultElastic,
|
|
1127
|
+
dragMomentum = true
|
|
1128
|
+
} = props;
|
|
1129
|
+
return {
|
|
1130
|
+
...props,
|
|
1131
|
+
drag,
|
|
1132
|
+
dragDirectionLock,
|
|
1133
|
+
dragPropagation,
|
|
1134
|
+
dragConstraints,
|
|
1135
|
+
dragElastic,
|
|
1136
|
+
dragMomentum
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
function shouldDrag(direction, drag, currentDirection) {
|
|
1141
|
+
return (drag === true || drag === direction) && (currentDirection === null || currentDirection === direction);
|
|
1142
|
+
}
|
|
1143
|
+
function getCurrentDirection(offset, lockThreshold = 10) {
|
|
1144
|
+
let direction = null;
|
|
1145
|
+
if (Math.abs(offset.y) > lockThreshold) {
|
|
1146
|
+
direction = "y";
|
|
1147
|
+
} else if (Math.abs(offset.x) > lockThreshold) {
|
|
1148
|
+
direction = "x";
|
|
1149
|
+
}
|
|
1150
|
+
return direction;
|
|
1151
|
+
}
|
|
1152
|
+
let DragGesture$1 = class DragGesture extends Feature {
|
|
1153
|
+
constructor(node) {
|
|
1154
|
+
super(node);
|
|
1155
|
+
this.removeGroupControls = noop;
|
|
1156
|
+
this.removeListeners = noop;
|
|
1157
|
+
this.controls = new VisualElementDragControls(node);
|
|
1158
|
+
}
|
|
1159
|
+
mount() {
|
|
1160
|
+
const { dragControls } = this.node.getProps();
|
|
1161
|
+
if (dragControls) {
|
|
1162
|
+
this.removeGroupControls = dragControls.subscribe(this.controls);
|
|
1163
|
+
}
|
|
1164
|
+
this.removeListeners = this.controls.addListeners() || noop;
|
|
1165
|
+
}
|
|
1166
|
+
update() {
|
|
1167
|
+
const { dragControls } = this.node.getProps();
|
|
1168
|
+
const { dragControls: prevDragControls } = this.node.prevProps || {};
|
|
1169
|
+
if (dragControls !== prevDragControls) {
|
|
1170
|
+
this.removeGroupControls();
|
|
1171
|
+
if (dragControls) {
|
|
1172
|
+
this.removeGroupControls = dragControls.subscribe(this.controls);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
unmount() {
|
|
1177
|
+
this.removeGroupControls();
|
|
1178
|
+
this.removeListeners();
|
|
1179
|
+
if (!this.controls.isDragging) {
|
|
1180
|
+
this.controls.endPanSession();
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
const asyncHandler = (handler) => (event, info) => {
|
|
1185
|
+
if (handler) {
|
|
1186
|
+
frame.postRender(() => handler(event, info));
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
class PanGesture extends Feature {
|
|
1190
|
+
constructor() {
|
|
1191
|
+
super(...arguments);
|
|
1192
|
+
this.removePointerDownListener = noop;
|
|
1193
|
+
}
|
|
1194
|
+
onPointerDown(pointerDownEvent) {
|
|
1195
|
+
this.session = new PanSession(
|
|
1196
|
+
pointerDownEvent,
|
|
1197
|
+
this.createPanHandlers(),
|
|
1198
|
+
{
|
|
1199
|
+
transformPagePoint: this.node.getTransformPagePoint(),
|
|
1200
|
+
contextWindow: getContextWindow(this.node)
|
|
1201
|
+
}
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
createPanHandlers() {
|
|
1205
|
+
const { onPanSessionStart, onPanStart, onPan, onPanEnd } = this.node.getProps();
|
|
1206
|
+
return {
|
|
1207
|
+
onSessionStart: asyncHandler(onPanSessionStart),
|
|
1208
|
+
onStart: asyncHandler(onPanStart),
|
|
1209
|
+
onMove: onPan,
|
|
1210
|
+
onEnd: (event, info) => {
|
|
1211
|
+
delete this.session;
|
|
1212
|
+
if (onPanEnd) {
|
|
1213
|
+
frame.postRender(() => onPanEnd(event, info));
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
mount() {
|
|
1219
|
+
this.removePointerDownListener = addPointerEvent(
|
|
1220
|
+
this.node.current,
|
|
1221
|
+
"pointerdown",
|
|
1222
|
+
(event) => this.onPointerDown(event)
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
update() {
|
|
1226
|
+
this.session && this.session.updateHandlers(this.createPanHandlers());
|
|
1227
|
+
}
|
|
1228
|
+
unmount() {
|
|
1229
|
+
this.removePointerDownListener();
|
|
1230
|
+
this.session && this.session.end();
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
function handleHoverEvent(node, event, lifecycle) {
|
|
1234
|
+
const { props } = node;
|
|
1235
|
+
if (node.animationState && props.whileHover) {
|
|
1236
|
+
node.animationState.setActive("whileHover", lifecycle === "Start");
|
|
1237
|
+
}
|
|
1238
|
+
const eventName = "onHover" + lifecycle;
|
|
1239
|
+
const callback = props[eventName];
|
|
1240
|
+
if (callback) {
|
|
1241
|
+
frame.postRender(() => callback(event, extractEventInfo(event)));
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
class HoverGesture extends Feature {
|
|
1245
|
+
mount() {
|
|
1246
|
+
const { current } = this.node;
|
|
1247
|
+
if (!current) return;
|
|
1248
|
+
this.unmount = hover(current, (_element, startEvent) => {
|
|
1249
|
+
handleHoverEvent(this.node, startEvent, "Start");
|
|
1250
|
+
return (endEvent) => handleHoverEvent(this.node, endEvent, "End");
|
|
1251
|
+
});
|
|
1252
|
+
}
|
|
1253
|
+
unmount() {
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
function handlePressEvent(node, event, lifecycle) {
|
|
1257
|
+
const { props } = node;
|
|
1258
|
+
if (node.current instanceof HTMLButtonElement && node.current.disabled) {
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
if (node.animationState && props.whileTap) {
|
|
1262
|
+
node.animationState.setActive("whileTap", lifecycle === "Start");
|
|
1263
|
+
}
|
|
1264
|
+
const eventName = "onTap" + (lifecycle === "End" ? "" : lifecycle);
|
|
1265
|
+
const callback = props[eventName];
|
|
1266
|
+
if (callback) {
|
|
1267
|
+
frame.postRender(() => callback(event, extractEventInfo(event)));
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
class PressGesture extends Feature {
|
|
1271
|
+
mount() {
|
|
1272
|
+
const { current } = this.node;
|
|
1273
|
+
if (!current) return;
|
|
1274
|
+
this.unmount = press(
|
|
1275
|
+
current,
|
|
1276
|
+
(_element, startEvent) => {
|
|
1277
|
+
handlePressEvent(this.node, startEvent, "Start");
|
|
1278
|
+
return (endEvent, { success }) => handlePressEvent(
|
|
1279
|
+
this.node,
|
|
1280
|
+
endEvent,
|
|
1281
|
+
success ? "End" : "Cancel"
|
|
1282
|
+
);
|
|
1283
|
+
},
|
|
1284
|
+
{ useGlobalTarget: this.node.props.globalTapTarget }
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
unmount() {
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
class FocusGesture extends Feature {
|
|
1291
|
+
constructor() {
|
|
1292
|
+
super(...arguments);
|
|
1293
|
+
this.isActive = false;
|
|
1294
|
+
}
|
|
1295
|
+
onFocus() {
|
|
1296
|
+
let isFocusVisible = false;
|
|
1297
|
+
try {
|
|
1298
|
+
isFocusVisible = this.node.current.matches(":focus-visible");
|
|
1299
|
+
} catch (e) {
|
|
1300
|
+
isFocusVisible = true;
|
|
1301
|
+
}
|
|
1302
|
+
if (!isFocusVisible || !this.node.animationState) return;
|
|
1303
|
+
this.node.animationState.setActive("whileFocus", true);
|
|
1304
|
+
this.isActive = true;
|
|
1305
|
+
}
|
|
1306
|
+
onBlur() {
|
|
1307
|
+
if (!this.isActive || !this.node.animationState) return;
|
|
1308
|
+
this.node.animationState.setActive("whileFocus", false);
|
|
1309
|
+
this.isActive = false;
|
|
1310
|
+
}
|
|
1311
|
+
mount() {
|
|
1312
|
+
this.unmount = pipe(
|
|
1313
|
+
addDomEvent(this.node.current, "focus", () => this.onFocus()),
|
|
1314
|
+
addDomEvent(this.node.current, "blur", () => this.onBlur())
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
unmount() {
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
class DragGesture2 extends DragGesture$1 {
|
|
1321
|
+
unmount() {
|
|
1322
|
+
this.controls.dispose();
|
|
1323
|
+
super.unmount();
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
const gestures = {
|
|
1327
|
+
drag: { Feature: DragGesture2 },
|
|
1328
|
+
pan: { Feature: PanGesture },
|
|
1329
|
+
hover: { Feature: HoverGesture },
|
|
1330
|
+
tap: { Feature: PressGesture },
|
|
1331
|
+
focus: { Feature: FocusGesture }
|
|
1332
|
+
};
|
|
1333
|
+
const featureBundle = {
|
|
1334
|
+
...animations,
|
|
1335
|
+
...gestures
|
|
1336
|
+
};
|
|
1337
|
+
function prepareDragProjection(node, props) {
|
|
1338
|
+
if (node.projection || !(props.drag || props.dragControls)) return;
|
|
1339
|
+
node.projection = new HTMLProjectionNode(node.latestValues, node.parent?.projection);
|
|
1340
|
+
node.projection.setOptions({
|
|
1341
|
+
visualElement: node,
|
|
1342
|
+
alwaysMeasureLayout: true,
|
|
1343
|
+
layout: false,
|
|
1344
|
+
animationType: "both"
|
|
1345
|
+
});
|
|
1346
|
+
if (node.current) node.projection.mount(node.current);
|
|
1347
|
+
}
|
|
1348
|
+
const isBrowser = typeof window !== "undefined";
|
|
1349
|
+
function useVisualState(isSVG, props, context, presenceContext) {
|
|
1350
|
+
const config = isSVG ? {
|
|
1351
|
+
scrapeMotionValuesFromProps: scrapeSVGMotionValuesFromProps,
|
|
1352
|
+
createRenderState: createSvgRenderState
|
|
1353
|
+
} : {
|
|
1354
|
+
scrapeMotionValuesFromProps: scrapeHTMLMotionValuesFromProps,
|
|
1355
|
+
createRenderState: createHtmlRenderState
|
|
1356
|
+
};
|
|
1357
|
+
return makeVisualState(config, props, context, presenceContext);
|
|
1358
|
+
}
|
|
1359
|
+
function createMotionComponent(Component, {
|
|
1360
|
+
forwardMotionProps = false,
|
|
1361
|
+
type
|
|
1362
|
+
} = {}, preloadedFeatures, createVisualElement) {
|
|
1363
|
+
if (preloadedFeatures) {
|
|
1364
|
+
loadFeatures(preloadedFeatures);
|
|
1365
|
+
}
|
|
1366
|
+
const isSVG = type ? type === "svg" : isSVGComponent(Component);
|
|
1367
|
+
return function MotionDOMComponent(props) {
|
|
1368
|
+
const motionConfig = useContext(MotionConfigContext);
|
|
1369
|
+
const parentContext = useContext(MotionContext);
|
|
1370
|
+
const rawPresenceContext = useContext(PresenceContext);
|
|
1371
|
+
const presenceContext = createMemo(() => {
|
|
1372
|
+
if (!rawPresenceContext) return null;
|
|
1373
|
+
const resolved = {
|
|
1374
|
+
id: rawPresenceContext.id(),
|
|
1375
|
+
isPresent: rawPresenceContext.isPresent(),
|
|
1376
|
+
initial: rawPresenceContext.initial(),
|
|
1377
|
+
custom: rawPresenceContext.custom(),
|
|
1378
|
+
onExitComplete: rawPresenceContext.onExitComplete,
|
|
1379
|
+
register: rawPresenceContext.register ?? (() => () => {
|
|
1380
|
+
})
|
|
1381
|
+
};
|
|
1382
|
+
return resolved;
|
|
1383
|
+
});
|
|
1384
|
+
const ownProps = createMemo(() => {
|
|
1385
|
+
const nextProps = {};
|
|
1386
|
+
for (const key in props) {
|
|
1387
|
+
if (key === "children") continue;
|
|
1388
|
+
nextProps[key] = props[key];
|
|
1389
|
+
}
|
|
1390
|
+
return nextProps;
|
|
1391
|
+
});
|
|
1392
|
+
const getLatestProps = createMemo(() => ({
|
|
1393
|
+
...motionConfig,
|
|
1394
|
+
...ownProps()
|
|
1395
|
+
}));
|
|
1396
|
+
const isStatic = createMemo(() => Boolean(getLatestProps().isStatic));
|
|
1397
|
+
const context = createMotionContext(props, parentContext);
|
|
1398
|
+
const visualState = useVisualState(isSVG, props, context, presenceContext());
|
|
1399
|
+
let visualElement;
|
|
1400
|
+
const initialPresenceContext = presenceContext();
|
|
1401
|
+
if (!isStatic() && isBrowser) {
|
|
1402
|
+
visualElement = (createVisualElement || createDomVisualElement)(Component, {
|
|
1403
|
+
visualState,
|
|
1404
|
+
parent: parentContext.visualElement,
|
|
1405
|
+
props: getLatestProps(),
|
|
1406
|
+
presenceContext: initialPresenceContext,
|
|
1407
|
+
blockInitialAnimation: initialPresenceContext ? initialPresenceContext.initial === false : false,
|
|
1408
|
+
reducedMotionConfig: motionConfig.reducedMotion,
|
|
1409
|
+
skipAnimations: motionConfig.skipAnimations,
|
|
1410
|
+
isSVG
|
|
1411
|
+
});
|
|
1412
|
+
if (visualElement) prepareDragProjection(visualElement, getLatestProps());
|
|
1413
|
+
}
|
|
1414
|
+
context.visualElement = visualElement;
|
|
1415
|
+
const [local, rest] = splitProps(props, ["ref", "children"]);
|
|
1416
|
+
const elementProps = createMemo(() => {
|
|
1417
|
+
const latestProps = getLatestProps();
|
|
1418
|
+
const filtered = filterProps(ownProps(), typeof Component === "string", forwardMotionProps);
|
|
1419
|
+
delete filtered.children;
|
|
1420
|
+
delete filtered.ref;
|
|
1421
|
+
const componentTag = typeof Component === "string" ? Component : "svg";
|
|
1422
|
+
const visualProps = isSVG ? resolveSVGProps(latestProps, visualState.latestValues, componentTag) : resolveHTMLProps(latestProps, visualState.latestValues);
|
|
1423
|
+
return {
|
|
1424
|
+
...filtered,
|
|
1425
|
+
...visualProps
|
|
1426
|
+
};
|
|
1427
|
+
});
|
|
1428
|
+
onMount(() => {
|
|
1429
|
+
if (!visualElement) return;
|
|
1430
|
+
visualElement.scheduleRenderMicrotask();
|
|
1431
|
+
});
|
|
1432
|
+
createEffect(() => {
|
|
1433
|
+
if (!visualElement) return;
|
|
1434
|
+
const nextProps = getLatestProps();
|
|
1435
|
+
const nextPresenceContext = presenceContext();
|
|
1436
|
+
visualElement.update(nextProps, nextPresenceContext);
|
|
1437
|
+
prepareDragProjection(visualElement, nextProps);
|
|
1438
|
+
visualElement.updateFeatures();
|
|
1439
|
+
if (visualElement.current && visualElement.animationState) {
|
|
1440
|
+
visualElement.animationState.animateChanges();
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
onCleanup(() => {
|
|
1444
|
+
visualElement?.unmount();
|
|
1445
|
+
});
|
|
1446
|
+
const setRef = (instance) => {
|
|
1447
|
+
if (!instance) return;
|
|
1448
|
+
visualElement?.mount(instance);
|
|
1449
|
+
if (visualElement && parentContext.visualElement) {
|
|
1450
|
+
const parent = parentContext.visualElement;
|
|
1451
|
+
visualElement.parent = parent;
|
|
1452
|
+
if (typeof parent.depth === "number") {
|
|
1453
|
+
visualElement.depth = parent.depth + 1;
|
|
1454
|
+
}
|
|
1455
|
+
if (visualElement.isVariantNode && !visualElement.isControllingVariants) {
|
|
1456
|
+
visualElement.removeFromVariantTree?.();
|
|
1457
|
+
if (typeof parent.addVariantChild === "function") {
|
|
1458
|
+
visualElement.removeFromVariantTree = parent.addVariantChild(visualElement);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
visualState.onMount?.(instance);
|
|
1463
|
+
const externalRef = local.ref;
|
|
1464
|
+
if (typeof externalRef === "function") {
|
|
1465
|
+
externalRef(instance);
|
|
1466
|
+
} else if (externalRef && typeof externalRef === "object") {
|
|
1467
|
+
externalRef.current = instance;
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
return createComponent(MotionContext.Provider, {
|
|
1471
|
+
value: context,
|
|
1472
|
+
get children() {
|
|
1473
|
+
return createComponent(Dynamic, mergeProps({
|
|
1474
|
+
component: Component
|
|
1475
|
+
}, elementProps, {
|
|
1476
|
+
ref: setRef,
|
|
1477
|
+
get children() {
|
|
1478
|
+
return local.children;
|
|
1479
|
+
}
|
|
1480
|
+
}));
|
|
1481
|
+
}
|
|
1482
|
+
});
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
function createMotionComponentWithFeatures(Component, options) {
|
|
1486
|
+
return createMotionComponent(Component, options, featureBundle, createDomVisualElement);
|
|
1487
|
+
}
|
|
1488
|
+
const componentCache = /* @__PURE__ */ new Map();
|
|
1489
|
+
const motionProxy = new Proxy(createMotionComponentWithFeatures, {
|
|
1490
|
+
get: (target, key) => {
|
|
1491
|
+
if (key === "create") return createMotionComponentWithFeatures;
|
|
1492
|
+
if (typeof key !== "string") return Reflect.get(target, key);
|
|
1493
|
+
let component = componentCache.get(key);
|
|
1494
|
+
if (!component) {
|
|
1495
|
+
component = createMotionComponentWithFeatures(key);
|
|
1496
|
+
componentCache.set(key, component);
|
|
1497
|
+
}
|
|
1498
|
+
return component;
|
|
1499
|
+
}
|
|
1500
|
+
});
|
|
1501
|
+
const motion = motionProxy;
|
|
1502
|
+
const m = motionProxy;
|
|
1503
|
+
var _tmpl$ = /* @__PURE__ */ template(`<div>`);
|
|
1504
|
+
let presenceCounter = 0;
|
|
1505
|
+
const autoKeyMap = /* @__PURE__ */ new WeakMap();
|
|
1506
|
+
function AnimatePresence(props) {
|
|
1507
|
+
const merged = mergeProps$1({
|
|
1508
|
+
initial: true,
|
|
1509
|
+
mode: "sync",
|
|
1510
|
+
presenceAffectsLayout: true
|
|
1511
|
+
}, props);
|
|
1512
|
+
const [local, others] = splitProps(merged, ["children", "when", "presenceKey", "initial", "onExitComplete", "mode", "presenceAffectsLayout", "custom", "anchorX", "root"]);
|
|
1513
|
+
let isInitialRender = true;
|
|
1514
|
+
let didWarn = false;
|
|
1515
|
+
const warnNonFactory = () => {
|
|
1516
|
+
if (didWarn) return;
|
|
1517
|
+
didWarn = true;
|
|
1518
|
+
console.warn("[AnimatePresence] Solid requires children to be a function for exit animations to work reliably. Use <AnimatePresence when={condition}>{() => <motion.div .../>}</AnimatePresence>.");
|
|
1519
|
+
};
|
|
1520
|
+
if (local.when !== void 0) {
|
|
1521
|
+
const currentChild = createMemo(() => {
|
|
1522
|
+
if (!local.when) return void 0;
|
|
1523
|
+
const childrenValue = local.children;
|
|
1524
|
+
const getChild = () => {
|
|
1525
|
+
let value = typeof childrenValue === "function" ? childrenValue() : childrenValue;
|
|
1526
|
+
if (typeof value === "function" && value.length === 0) {
|
|
1527
|
+
value = value();
|
|
1528
|
+
}
|
|
1529
|
+
return value;
|
|
1530
|
+
};
|
|
1531
|
+
if (typeof childrenValue !== "function") {
|
|
1532
|
+
warnNonFactory();
|
|
1533
|
+
}
|
|
1534
|
+
return {
|
|
1535
|
+
key: local.presenceKey ?? "index-0",
|
|
1536
|
+
getChild
|
|
1537
|
+
};
|
|
1538
|
+
});
|
|
1539
|
+
const initialChild = currentChild();
|
|
1540
|
+
const [rendered, setRendered] = createSignal(initialChild ? [initialChild] : []);
|
|
1541
|
+
createEffect(on(currentChild, (next) => {
|
|
1542
|
+
const previous = untrack(rendered);
|
|
1543
|
+
const exiting = previous.filter((child) => child.key !== next?.key);
|
|
1544
|
+
const present = next && (previous.find((child) => child.key === next.key) ?? next);
|
|
1545
|
+
setRendered(local.mode === "wait" && exiting.length ? exiting : present ? [present, ...exiting] : exiting);
|
|
1546
|
+
}, {
|
|
1547
|
+
defer: true
|
|
1548
|
+
}));
|
|
1549
|
+
onMount(() => {
|
|
1550
|
+
isInitialRender = false;
|
|
1551
|
+
});
|
|
1552
|
+
return createComponent(For, {
|
|
1553
|
+
get each() {
|
|
1554
|
+
return rendered();
|
|
1555
|
+
},
|
|
1556
|
+
children: (child) => {
|
|
1557
|
+
const isPresent = () => currentChild()?.key === child.key;
|
|
1558
|
+
const onExitComplete = () => {
|
|
1559
|
+
const next = untrack(currentChild);
|
|
1560
|
+
const previous = untrack(rendered);
|
|
1561
|
+
if (next?.key === child.key || !previous.includes(child)) return;
|
|
1562
|
+
const remaining = previous.filter((item) => item !== child);
|
|
1563
|
+
const hasExits = remaining.some((item) => item.key !== next?.key);
|
|
1564
|
+
setRendered(!hasExits && next ? [remaining.find((item) => item.key === next.key) ?? next] : remaining);
|
|
1565
|
+
if (!hasExits) local.onExitComplete?.();
|
|
1566
|
+
};
|
|
1567
|
+
return createComponent(PresenceChild, {
|
|
1568
|
+
get key() {
|
|
1569
|
+
return child.key;
|
|
1570
|
+
},
|
|
1571
|
+
isPresent,
|
|
1572
|
+
get onExitComplete() {
|
|
1573
|
+
return isPresent() ? void 0 : onExitComplete;
|
|
1574
|
+
},
|
|
1575
|
+
get initial() {
|
|
1576
|
+
return isInitialRender && !local.initial ? false : void 0;
|
|
1577
|
+
},
|
|
1578
|
+
get custom() {
|
|
1579
|
+
return local.custom;
|
|
1580
|
+
},
|
|
1581
|
+
get presenceAffectsLayout() {
|
|
1582
|
+
return local.presenceAffectsLayout;
|
|
1583
|
+
},
|
|
1584
|
+
get getChild() {
|
|
1585
|
+
return child.getChild;
|
|
1586
|
+
},
|
|
1587
|
+
get childKey() {
|
|
1588
|
+
return child.key;
|
|
1589
|
+
},
|
|
1590
|
+
get mode() {
|
|
1591
|
+
return local.mode;
|
|
1592
|
+
},
|
|
1593
|
+
get anchorX() {
|
|
1594
|
+
return local.anchorX;
|
|
1595
|
+
},
|
|
1596
|
+
get root() {
|
|
1597
|
+
return local.root;
|
|
1598
|
+
}
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
const resolveChildrenList = () => {
|
|
1604
|
+
const childrenValue = local.children;
|
|
1605
|
+
if (local.when !== void 0) {
|
|
1606
|
+
if (!local.when) return [];
|
|
1607
|
+
if (typeof childrenValue !== "function") {
|
|
1608
|
+
warnNonFactory();
|
|
1609
|
+
}
|
|
1610
|
+
const getChild = typeof childrenValue === "function" ? childrenValue : () => childrenValue;
|
|
1611
|
+
const key = local.presenceKey ?? "index-0";
|
|
1612
|
+
return [{
|
|
1613
|
+
key,
|
|
1614
|
+
getChild
|
|
1615
|
+
}];
|
|
1616
|
+
}
|
|
1617
|
+
const child = typeof childrenValue === "function" ? childrenValue() : childrenValue;
|
|
1618
|
+
if (!child || child === true) return [];
|
|
1619
|
+
const list = Array.isArray(child) ? child : [child];
|
|
1620
|
+
return list.filter((item) => item !== false && item != null).map((item, index) => ({
|
|
1621
|
+
key: getChildKey(item, index),
|
|
1622
|
+
getChild: () => item
|
|
1623
|
+
}));
|
|
1624
|
+
};
|
|
1625
|
+
const presentChildren = createMemo(() => resolveChildrenList());
|
|
1626
|
+
const presentKeys = createMemo(() => {
|
|
1627
|
+
return presentChildren().map((child) => child.key);
|
|
1628
|
+
});
|
|
1629
|
+
const [allChildren, setAllChildren] = createSignal([], {
|
|
1630
|
+
equals: false
|
|
1631
|
+
});
|
|
1632
|
+
const [exitStatus, setExitStatus] = createSignal(/* @__PURE__ */ new Map(), {
|
|
1633
|
+
equals: false
|
|
1634
|
+
});
|
|
1635
|
+
createEffect(() => {
|
|
1636
|
+
const current = presentChildren();
|
|
1637
|
+
const currentKeys = presentKeys();
|
|
1638
|
+
const prev = untrack(allChildren);
|
|
1639
|
+
const prevExitStatus = untrack(exitStatus);
|
|
1640
|
+
let nextExitStatus = prevExitStatus;
|
|
1641
|
+
let exitStatusChanged = false;
|
|
1642
|
+
const exitingChildren = prev.filter((child) => !currentKeys.includes(child.key));
|
|
1643
|
+
prevExitStatus.forEach((_, key) => {
|
|
1644
|
+
if (currentKeys.includes(key)) {
|
|
1645
|
+
if (!exitStatusChanged) {
|
|
1646
|
+
nextExitStatus = new Map(prevExitStatus);
|
|
1647
|
+
exitStatusChanged = true;
|
|
1648
|
+
}
|
|
1649
|
+
nextExitStatus.delete(key);
|
|
1650
|
+
}
|
|
1651
|
+
});
|
|
1652
|
+
exitingChildren.forEach((child) => {
|
|
1653
|
+
if (!prevExitStatus.has(child.key)) {
|
|
1654
|
+
if (!exitStatusChanged) {
|
|
1655
|
+
nextExitStatus = new Map(prevExitStatus);
|
|
1656
|
+
exitStatusChanged = true;
|
|
1657
|
+
}
|
|
1658
|
+
nextExitStatus.set(child.key, false);
|
|
1659
|
+
}
|
|
1660
|
+
});
|
|
1661
|
+
if (exitStatusChanged) {
|
|
1662
|
+
setExitStatus(nextExitStatus);
|
|
1663
|
+
}
|
|
1664
|
+
const nextChildren = [];
|
|
1665
|
+
for (let i = 0; i < current.length; i++) {
|
|
1666
|
+
const child = current[i];
|
|
1667
|
+
nextChildren.push({
|
|
1668
|
+
key: child.key,
|
|
1669
|
+
getChild: child.getChild,
|
|
1670
|
+
isPresent: true,
|
|
1671
|
+
index: i
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
if (local.mode === "wait" && exitingChildren.length > 0) {
|
|
1675
|
+
nextChildren.length = 0;
|
|
1676
|
+
exitingChildren.forEach((child) => {
|
|
1677
|
+
nextChildren.push({
|
|
1678
|
+
...child,
|
|
1679
|
+
isPresent: false
|
|
1680
|
+
});
|
|
1681
|
+
});
|
|
1682
|
+
} else {
|
|
1683
|
+
exitingChildren.forEach((child) => {
|
|
1684
|
+
nextChildren.push({
|
|
1685
|
+
...child,
|
|
1686
|
+
isPresent: false
|
|
1687
|
+
});
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
const isSame = prev.length === nextChildren.length && prev.every((child, index) => {
|
|
1691
|
+
const next = nextChildren[index];
|
|
1692
|
+
return child.key === next.key && child.getChild === next.getChild && child.isPresent === next.isPresent;
|
|
1693
|
+
});
|
|
1694
|
+
if (!isSame) {
|
|
1695
|
+
setAllChildren(nextChildren);
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1698
|
+
const allExitsComplete = createMemo(() => {
|
|
1699
|
+
const status = exitStatus();
|
|
1700
|
+
if (!status.size) return false;
|
|
1701
|
+
for (const isComplete of status.values()) {
|
|
1702
|
+
if (!isComplete) return false;
|
|
1703
|
+
}
|
|
1704
|
+
return true;
|
|
1705
|
+
});
|
|
1706
|
+
createEffect(() => {
|
|
1707
|
+
if (allExitsComplete()) {
|
|
1708
|
+
batch(() => {
|
|
1709
|
+
setExitStatus(/* @__PURE__ */ new Map());
|
|
1710
|
+
const current = presentChildren();
|
|
1711
|
+
presentKeys();
|
|
1712
|
+
setAllChildren(current.map((child, i) => ({
|
|
1713
|
+
key: child.key,
|
|
1714
|
+
getChild: child.getChild,
|
|
1715
|
+
isPresent: true,
|
|
1716
|
+
index: i
|
|
1717
|
+
})));
|
|
1718
|
+
});
|
|
1719
|
+
local.onExitComplete?.();
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
onMount(() => {
|
|
1723
|
+
isInitialRender = false;
|
|
1724
|
+
});
|
|
1725
|
+
return createComponent(Index, {
|
|
1726
|
+
get each() {
|
|
1727
|
+
return allChildren();
|
|
1728
|
+
},
|
|
1729
|
+
children: (childState) => {
|
|
1730
|
+
const state = childState;
|
|
1731
|
+
const isPresent = () => state().isPresent;
|
|
1732
|
+
const onExitComplete = () => {
|
|
1733
|
+
const status = untrack(exitStatus);
|
|
1734
|
+
const key = state().key;
|
|
1735
|
+
if (!status.has(key)) return;
|
|
1736
|
+
batch(() => {
|
|
1737
|
+
setExitStatus((map) => {
|
|
1738
|
+
const newMap = new Map(map);
|
|
1739
|
+
if (!newMap.has(key)) return newMap;
|
|
1740
|
+
newMap.set(key, true);
|
|
1741
|
+
return newMap;
|
|
1742
|
+
});
|
|
1743
|
+
});
|
|
1744
|
+
};
|
|
1745
|
+
return createComponent(PresenceChild, {
|
|
1746
|
+
get key() {
|
|
1747
|
+
return state().key;
|
|
1748
|
+
},
|
|
1749
|
+
isPresent,
|
|
1750
|
+
get onExitComplete() {
|
|
1751
|
+
return isPresent() ? void 0 : onExitComplete;
|
|
1752
|
+
},
|
|
1753
|
+
get initial() {
|
|
1754
|
+
return isInitialRender && !local.initial ? false : void 0;
|
|
1755
|
+
},
|
|
1756
|
+
get custom() {
|
|
1757
|
+
return local.custom;
|
|
1758
|
+
},
|
|
1759
|
+
get presenceAffectsLayout() {
|
|
1760
|
+
return local.presenceAffectsLayout;
|
|
1761
|
+
},
|
|
1762
|
+
get getChild() {
|
|
1763
|
+
return state().getChild;
|
|
1764
|
+
},
|
|
1765
|
+
get childKey() {
|
|
1766
|
+
return state().key;
|
|
1767
|
+
},
|
|
1768
|
+
get mode() {
|
|
1769
|
+
return local.mode;
|
|
1770
|
+
},
|
|
1771
|
+
get anchorX() {
|
|
1772
|
+
return local.anchorX;
|
|
1773
|
+
},
|
|
1774
|
+
get root() {
|
|
1775
|
+
return local.root;
|
|
1776
|
+
}
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
function PopChild(props) {
|
|
1782
|
+
let container;
|
|
1783
|
+
let wasPresent = props.isPresent;
|
|
1784
|
+
const [style$1, setStyle] = createSignal({
|
|
1785
|
+
display: "contents"
|
|
1786
|
+
});
|
|
1787
|
+
createEffect(() => {
|
|
1788
|
+
const now = props.isPresent;
|
|
1789
|
+
if (wasPresent && !now) {
|
|
1790
|
+
const target = container?.firstElementChild ?? container;
|
|
1791
|
+
if (target) {
|
|
1792
|
+
const rect = target.getBoundingClientRect();
|
|
1793
|
+
const parent = target.offsetParent;
|
|
1794
|
+
const parentRect = parent ? parent.getBoundingClientRect() : {
|
|
1795
|
+
left: 0,
|
|
1796
|
+
top: 0,
|
|
1797
|
+
width: 0
|
|
1798
|
+
};
|
|
1799
|
+
const top = rect.top - parentRect.top;
|
|
1800
|
+
const left = rect.left - parentRect.left;
|
|
1801
|
+
const right = parent ? parentRect.width - rect.width - left : 0;
|
|
1802
|
+
const x = props.anchorX === "right" ? {
|
|
1803
|
+
right: `${right}px`,
|
|
1804
|
+
left: "auto"
|
|
1805
|
+
} : {
|
|
1806
|
+
left: `${left}px`,
|
|
1807
|
+
right: "auto"
|
|
1808
|
+
};
|
|
1809
|
+
setStyle({
|
|
1810
|
+
position: "absolute",
|
|
1811
|
+
top: `${top}px`,
|
|
1812
|
+
width: `${rect.width}px`,
|
|
1813
|
+
height: `${rect.height}px`,
|
|
1814
|
+
...x
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
} else if (now) {
|
|
1818
|
+
setStyle({
|
|
1819
|
+
display: "contents"
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
wasPresent = now;
|
|
1823
|
+
});
|
|
1824
|
+
return (() => {
|
|
1825
|
+
var _el$ = getNextElement(_tmpl$);
|
|
1826
|
+
use((el) => container = el, _el$);
|
|
1827
|
+
insert(_el$, () => props.children);
|
|
1828
|
+
effect((_$p) => style(_el$, style$1(), _$p));
|
|
1829
|
+
return _el$;
|
|
1830
|
+
})();
|
|
1831
|
+
}
|
|
1832
|
+
function PresenceChild(props) {
|
|
1833
|
+
const presenceId = String(presenceCounter++);
|
|
1834
|
+
const [local, others] = splitProps(props, ["isPresent", "getChild", "childKey", "onExitComplete", "initial", "custom", "presenceAffectsLayout", "mode", "anchorX", "root"]);
|
|
1835
|
+
const [registeredChildren, setRegisteredChildren] = createSignal(/* @__PURE__ */ new Map());
|
|
1836
|
+
const register = (childId) => {
|
|
1837
|
+
const key = String(childId);
|
|
1838
|
+
batch(() => {
|
|
1839
|
+
setRegisteredChildren((map) => {
|
|
1840
|
+
const newMap = new Map(map);
|
|
1841
|
+
newMap.set(key, false);
|
|
1842
|
+
return newMap;
|
|
1843
|
+
});
|
|
1844
|
+
});
|
|
1845
|
+
return () => {
|
|
1846
|
+
batch(() => {
|
|
1847
|
+
setRegisteredChildren((map) => {
|
|
1848
|
+
const newMap = new Map(map);
|
|
1849
|
+
newMap.delete(key);
|
|
1850
|
+
return newMap;
|
|
1851
|
+
});
|
|
1852
|
+
});
|
|
1853
|
+
};
|
|
1854
|
+
};
|
|
1855
|
+
const onExitComplete = (childId) => {
|
|
1856
|
+
if (!local.onExitComplete) return;
|
|
1857
|
+
const key = String(childId);
|
|
1858
|
+
batch(() => {
|
|
1859
|
+
setRegisteredChildren((map) => {
|
|
1860
|
+
const newMap = new Map(map);
|
|
1861
|
+
newMap.set(key, true);
|
|
1862
|
+
return newMap;
|
|
1863
|
+
});
|
|
1864
|
+
});
|
|
1865
|
+
const allComplete = Array.from(registeredChildren().values()).every(Boolean);
|
|
1866
|
+
if (allComplete) {
|
|
1867
|
+
local.onExitComplete?.();
|
|
1868
|
+
}
|
|
1869
|
+
};
|
|
1870
|
+
createEffect(on(local.isPresent, (present) => {
|
|
1871
|
+
const current = untrack(registeredChildren);
|
|
1872
|
+
if (current.size) {
|
|
1873
|
+
setRegisteredChildren((map) => {
|
|
1874
|
+
const newMap = new Map(map);
|
|
1875
|
+
newMap.forEach((_, key) => newMap.set(key, false));
|
|
1876
|
+
return newMap;
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
if (!present && current.size === 0) {
|
|
1880
|
+
local.onExitComplete?.();
|
|
1881
|
+
}
|
|
1882
|
+
}, {
|
|
1883
|
+
defer: true
|
|
1884
|
+
}));
|
|
1885
|
+
const resolvedInitial = () => {
|
|
1886
|
+
if (local.initial === false) return false;
|
|
1887
|
+
if (typeof local.initial === "string" || Array.isArray(local.initial)) return local.initial;
|
|
1888
|
+
return void 0;
|
|
1889
|
+
};
|
|
1890
|
+
const presenceContext = createMemo(() => ({
|
|
1891
|
+
id: () => presenceId,
|
|
1892
|
+
isPresent: local.isPresent,
|
|
1893
|
+
initial: () => resolvedInitial(),
|
|
1894
|
+
custom: () => local.custom,
|
|
1895
|
+
onExitComplete,
|
|
1896
|
+
register
|
|
1897
|
+
}));
|
|
1898
|
+
return createComponent(PresenceContext.Provider, {
|
|
1899
|
+
get value() {
|
|
1900
|
+
return presenceContext();
|
|
1901
|
+
},
|
|
1902
|
+
get children() {
|
|
1903
|
+
return createComponent(PresenceChildContent, {
|
|
1904
|
+
get getChild() {
|
|
1905
|
+
return local.getChild;
|
|
1906
|
+
},
|
|
1907
|
+
get childKey() {
|
|
1908
|
+
return local.childKey;
|
|
1909
|
+
},
|
|
1910
|
+
get isPresent() {
|
|
1911
|
+
return local.isPresent;
|
|
1912
|
+
},
|
|
1913
|
+
get mode() {
|
|
1914
|
+
return local.mode;
|
|
1915
|
+
},
|
|
1916
|
+
get anchorX() {
|
|
1917
|
+
return local.anchorX;
|
|
1918
|
+
},
|
|
1919
|
+
get root() {
|
|
1920
|
+
return local.root;
|
|
1921
|
+
}
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
}
|
|
1926
|
+
function PresenceChildContent(props) {
|
|
1927
|
+
const resolved = children(() => {
|
|
1928
|
+
props.childKey;
|
|
1929
|
+
return untrack(() => props.getChild());
|
|
1930
|
+
});
|
|
1931
|
+
if (props.mode === "popLayout") {
|
|
1932
|
+
return createComponent(PopChild, {
|
|
1933
|
+
get isPresent() {
|
|
1934
|
+
return props.isPresent();
|
|
1935
|
+
},
|
|
1936
|
+
get anchorX() {
|
|
1937
|
+
return props.anchorX;
|
|
1938
|
+
},
|
|
1939
|
+
get root() {
|
|
1940
|
+
return props.root;
|
|
1941
|
+
},
|
|
1942
|
+
get children() {
|
|
1943
|
+
return resolved();
|
|
1944
|
+
}
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1947
|
+
return resolved();
|
|
1948
|
+
}
|
|
1949
|
+
function getChildKey(child, index) {
|
|
1950
|
+
if (!child) return "";
|
|
1951
|
+
const directKey = child.key ?? child.id ?? child?.props?.key;
|
|
1952
|
+
if (directKey != null && directKey !== "") return directKey;
|
|
1953
|
+
if (typeof child === "string" || typeof child === "number") return child;
|
|
1954
|
+
if (typeof child === "object" || typeof child === "function") {
|
|
1955
|
+
const cached = autoKeyMap.get(child);
|
|
1956
|
+
if (cached) return cached;
|
|
1957
|
+
}
|
|
1958
|
+
const nextKey = `index-${index}`;
|
|
1959
|
+
if (typeof child === "object" || typeof child === "function") {
|
|
1960
|
+
autoKeyMap.set(child, nextKey);
|
|
1961
|
+
}
|
|
1962
|
+
return nextKey;
|
|
1963
|
+
}
|
|
1964
|
+
function usePresence() {
|
|
1965
|
+
const context = useContext(PresenceContext);
|
|
1966
|
+
if (!context) {
|
|
1967
|
+
return [true, null];
|
|
1968
|
+
}
|
|
1969
|
+
const isPresent = context.isPresent();
|
|
1970
|
+
const safeToRemove = () => {
|
|
1971
|
+
if (context.onExitComplete) {
|
|
1972
|
+
context.onExitComplete(context.id());
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
return [!isPresent ? false : true, !isPresent ? safeToRemove : null];
|
|
1976
|
+
}
|
|
1977
|
+
function useIsPresent() {
|
|
1978
|
+
const context = useContext(PresenceContext);
|
|
1979
|
+
if (!context) return true;
|
|
1980
|
+
return context.isPresent();
|
|
1981
|
+
}
|
|
1982
|
+
function useMotionValue(initial) {
|
|
1983
|
+
const value = motionValue(initial);
|
|
1984
|
+
const { isStatic } = useContext(MotionConfigContext);
|
|
1985
|
+
if (isStatic) {
|
|
1986
|
+
const unsubscribe = value.on("change", () => {
|
|
1987
|
+
});
|
|
1988
|
+
onCleanup(() => unsubscribe());
|
|
1989
|
+
}
|
|
1990
|
+
onCleanup(() => value.destroy());
|
|
1991
|
+
return value;
|
|
1992
|
+
}
|
|
1993
|
+
function useTransform(input, inputRangeOrTransformer, outputRange, options) {
|
|
1994
|
+
if (typeof input === "function") {
|
|
1995
|
+
const value2 = transformValue(input);
|
|
1996
|
+
onCleanup(() => value2.destroy());
|
|
1997
|
+
return value2;
|
|
1998
|
+
}
|
|
1999
|
+
let value;
|
|
2000
|
+
if (Array.isArray(input)) {
|
|
2001
|
+
const transformer = typeof inputRangeOrTransformer === "function" ? inputRangeOrTransformer : transform(inputRangeOrTransformer, outputRange, options);
|
|
2002
|
+
value = transformValue(
|
|
2003
|
+
() => transformer(
|
|
2004
|
+
input.map((item) => item.get())
|
|
2005
|
+
)
|
|
2006
|
+
);
|
|
2007
|
+
} else if (typeof inputRangeOrTransformer === "function") {
|
|
2008
|
+
const transformer = inputRangeOrTransformer;
|
|
2009
|
+
value = transformValue(() => transformer(input.get()));
|
|
2010
|
+
} else {
|
|
2011
|
+
value = mapValue(
|
|
2012
|
+
input,
|
|
2013
|
+
inputRangeOrTransformer,
|
|
2014
|
+
outputRange,
|
|
2015
|
+
options
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
2018
|
+
onCleanup(() => value.destroy());
|
|
2019
|
+
return value;
|
|
2020
|
+
}
|
|
2021
|
+
function useSpring(source, options = {}) {
|
|
2022
|
+
const { isStatic } = useContext(MotionConfigContext);
|
|
2023
|
+
const getFromSource = () => isMotionValue(source) ? source.get() : source;
|
|
2024
|
+
if (isStatic) {
|
|
2025
|
+
return useTransform(getFromSource);
|
|
2026
|
+
}
|
|
2027
|
+
const initial = getFromSource();
|
|
2028
|
+
const value = motionValue(initial);
|
|
2029
|
+
const unit = typeof initial === "string" ? initial.replace(/[\d.-]/g, "") : "";
|
|
2030
|
+
const parse = (latest) => unit ? `${parseFloat(String(latest))}${unit}` : parseFloat(String(latest));
|
|
2031
|
+
let target = initial;
|
|
2032
|
+
let setter;
|
|
2033
|
+
let disposed = false;
|
|
2034
|
+
const stop = () => {
|
|
2035
|
+
cancelFrame(start);
|
|
2036
|
+
value.stop();
|
|
2037
|
+
};
|
|
2038
|
+
const start = () => {
|
|
2039
|
+
if (disposed) return;
|
|
2040
|
+
value.stop();
|
|
2041
|
+
const from = parseFloat(String(value.get()));
|
|
2042
|
+
const to = parseFloat(String(target));
|
|
2043
|
+
if (from === to) return;
|
|
2044
|
+
value.start((onComplete) => new JSAnimation({
|
|
2045
|
+
keyframes: [from, to],
|
|
2046
|
+
velocity: value.getVelocity(),
|
|
2047
|
+
type: "spring",
|
|
2048
|
+
restDelta: 1e-3,
|
|
2049
|
+
restSpeed: 0.01,
|
|
2050
|
+
...options,
|
|
2051
|
+
onUpdate: (latest) => setter(parse(latest)),
|
|
2052
|
+
onComplete
|
|
2053
|
+
}));
|
|
2054
|
+
};
|
|
2055
|
+
value.attach((latest, set) => {
|
|
2056
|
+
target = latest;
|
|
2057
|
+
setter = set;
|
|
2058
|
+
frame.postRender(start);
|
|
2059
|
+
}, stop);
|
|
2060
|
+
const unsubscribe = isMotionValue(source) ? source.on("change", (latest) => value.set(parse(latest))) : void 0;
|
|
2061
|
+
value.on("destroy", () => {
|
|
2062
|
+
disposed = true;
|
|
2063
|
+
unsubscribe?.();
|
|
2064
|
+
stop();
|
|
2065
|
+
});
|
|
2066
|
+
onCleanup(() => value.destroy());
|
|
2067
|
+
return value;
|
|
2068
|
+
}
|
|
2069
|
+
function useMotionValueEvent(value, event, callback) {
|
|
2070
|
+
onCleanup(value.on(event, callback));
|
|
2071
|
+
}
|
|
2072
|
+
function useVelocity(value) {
|
|
2073
|
+
const velocity = useMotionValue(value.getVelocity());
|
|
2074
|
+
const update = () => {
|
|
2075
|
+
const latest = value.getVelocity();
|
|
2076
|
+
velocity.set(latest);
|
|
2077
|
+
if (latest) frame.update(update);
|
|
2078
|
+
};
|
|
2079
|
+
useMotionValueEvent(value, "change", () => frame.update(update, false, true));
|
|
2080
|
+
onCleanup(() => cancelFrame(update));
|
|
2081
|
+
return velocity;
|
|
2082
|
+
}
|
|
2083
|
+
function useReducedMotion() {
|
|
2084
|
+
if (typeof window === "undefined" || !window.matchMedia) return () => null;
|
|
2085
|
+
const media = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
2086
|
+
const [reduced, setReduced] = createSignal(media.matches);
|
|
2087
|
+
const update = () => setReduced(media.matches);
|
|
2088
|
+
media.addEventListener("change", update);
|
|
2089
|
+
onCleanup(() => media.removeEventListener("change", update));
|
|
2090
|
+
return reduced;
|
|
2091
|
+
}
|
|
2092
|
+
function isDOMKeyframes(keyframes) {
|
|
2093
|
+
return typeof keyframes === "object" && !Array.isArray(keyframes);
|
|
2094
|
+
}
|
|
2095
|
+
function resolveSubjects(subject, keyframes, scope, selectorCache) {
|
|
2096
|
+
if (subject == null) {
|
|
2097
|
+
return [];
|
|
2098
|
+
}
|
|
2099
|
+
if (typeof subject === "string" && isDOMKeyframes(keyframes)) {
|
|
2100
|
+
return resolveElements(subject, scope, selectorCache);
|
|
2101
|
+
} else if (subject instanceof NodeList) {
|
|
2102
|
+
return Array.from(subject);
|
|
2103
|
+
} else if (Array.isArray(subject)) {
|
|
2104
|
+
return subject.filter((s) => s != null);
|
|
2105
|
+
} else {
|
|
2106
|
+
return [subject];
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
function calculateRepeatDuration(duration, repeat, _repeatDelay) {
|
|
2110
|
+
return duration * (repeat + 1);
|
|
2111
|
+
}
|
|
2112
|
+
function calcNextTime(current, next, prev, labels) {
|
|
2113
|
+
if (typeof next === "number") {
|
|
2114
|
+
return next;
|
|
2115
|
+
} else if (next.startsWith("-") || next.startsWith("+")) {
|
|
2116
|
+
return Math.max(0, current + parseFloat(next));
|
|
2117
|
+
} else if (next === "<") {
|
|
2118
|
+
return prev;
|
|
2119
|
+
} else if (next.startsWith("<")) {
|
|
2120
|
+
return Math.max(0, prev + parseFloat(next.slice(1)));
|
|
2121
|
+
} else {
|
|
2122
|
+
return labels.get(next) ?? current;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
function eraseKeyframes(sequence, startTime, endTime) {
|
|
2126
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
2127
|
+
const keyframe = sequence[i];
|
|
2128
|
+
if (keyframe.at > startTime && keyframe.at < endTime) {
|
|
2129
|
+
removeItem(sequence, keyframe);
|
|
2130
|
+
i--;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
function addKeyframes(sequence, keyframes, easing, offset, startTime, endTime) {
|
|
2135
|
+
eraseKeyframes(sequence, startTime, endTime);
|
|
2136
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
2137
|
+
sequence.push({
|
|
2138
|
+
value: keyframes[i],
|
|
2139
|
+
at: mixNumber(startTime, endTime, offset[i]),
|
|
2140
|
+
easing: getEasingForSegment(easing, i)
|
|
2141
|
+
});
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
function normalizeTimes(times, repeat) {
|
|
2145
|
+
for (let i = 0; i < times.length; i++) {
|
|
2146
|
+
times[i] = times[i] / (repeat + 1);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
function compareByTime(a, b) {
|
|
2150
|
+
if (a.at === b.at) {
|
|
2151
|
+
if (a.value === null) return 1;
|
|
2152
|
+
if (b.value === null) return -1;
|
|
2153
|
+
return 0;
|
|
2154
|
+
} else {
|
|
2155
|
+
return a.at - b.at;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
const defaultSegmentEasing = "easeInOut";
|
|
2159
|
+
const MAX_REPEAT = 20;
|
|
2160
|
+
function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators) {
|
|
2161
|
+
const defaultDuration = defaultTransition.duration || 0.3;
|
|
2162
|
+
const animationDefinitions = /* @__PURE__ */ new Map();
|
|
2163
|
+
const sequences = /* @__PURE__ */ new Map();
|
|
2164
|
+
const elementCache = {};
|
|
2165
|
+
const timeLabels = /* @__PURE__ */ new Map();
|
|
2166
|
+
let prevTime = 0;
|
|
2167
|
+
let currentTime = 0;
|
|
2168
|
+
let totalDuration = 0;
|
|
2169
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
2170
|
+
const segment = sequence[i];
|
|
2171
|
+
if (typeof segment === "string") {
|
|
2172
|
+
timeLabels.set(segment, currentTime);
|
|
2173
|
+
continue;
|
|
2174
|
+
} else if (!Array.isArray(segment)) {
|
|
2175
|
+
timeLabels.set(segment.name, calcNextTime(currentTime, segment.at, prevTime, timeLabels));
|
|
2176
|
+
continue;
|
|
2177
|
+
}
|
|
2178
|
+
let [subject, keyframes, transition = {}] = segment;
|
|
2179
|
+
if (transition.at !== void 0) {
|
|
2180
|
+
currentTime = calcNextTime(currentTime, transition.at, prevTime, timeLabels);
|
|
2181
|
+
}
|
|
2182
|
+
let maxDuration = 0;
|
|
2183
|
+
const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
|
|
2184
|
+
const valueKeyframesAsList = keyframesAsList(valueKeyframes);
|
|
2185
|
+
const {
|
|
2186
|
+
delay = 0,
|
|
2187
|
+
times = defaultOffset(valueKeyframesAsList),
|
|
2188
|
+
type = defaultTransition.type || "keyframes",
|
|
2189
|
+
repeat,
|
|
2190
|
+
repeatType,
|
|
2191
|
+
repeatDelay = 0,
|
|
2192
|
+
...remainingTransition
|
|
2193
|
+
} = valueTransition;
|
|
2194
|
+
let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
|
|
2195
|
+
const calculatedDelay = typeof delay === "function" ? delay(elementIndex, numSubjects) : delay;
|
|
2196
|
+
const numKeyframes = valueKeyframesAsList.length;
|
|
2197
|
+
const createGenerator = isGenerator(type) ? type : generators?.[type || "keyframes"];
|
|
2198
|
+
if (numKeyframes <= 2 && createGenerator) {
|
|
2199
|
+
let absoluteDelta = 100;
|
|
2200
|
+
if (numKeyframes === 2 && isNumberKeyframesArray(valueKeyframesAsList)) {
|
|
2201
|
+
const delta = valueKeyframesAsList[1] - valueKeyframesAsList[0];
|
|
2202
|
+
absoluteDelta = Math.abs(delta);
|
|
2203
|
+
}
|
|
2204
|
+
const springTransition = {
|
|
2205
|
+
...defaultTransition,
|
|
2206
|
+
...remainingTransition
|
|
2207
|
+
};
|
|
2208
|
+
if (duration !== void 0) {
|
|
2209
|
+
springTransition.duration = secondsToMilliseconds(duration);
|
|
2210
|
+
}
|
|
2211
|
+
const springEasing = createGeneratorEasing(springTransition, absoluteDelta, createGenerator);
|
|
2212
|
+
ease = springEasing.ease;
|
|
2213
|
+
duration = springEasing.duration;
|
|
2214
|
+
}
|
|
2215
|
+
duration = duration ?? defaultDuration;
|
|
2216
|
+
const startTime = currentTime + calculatedDelay;
|
|
2217
|
+
if (times.length === 1 && times[0] === 0) {
|
|
2218
|
+
times[1] = 1;
|
|
2219
|
+
}
|
|
2220
|
+
const remainder = times.length - valueKeyframesAsList.length;
|
|
2221
|
+
remainder > 0 && fillOffset(times, remainder);
|
|
2222
|
+
valueKeyframesAsList.length === 1 && valueKeyframesAsList.unshift(null);
|
|
2223
|
+
if (repeat) {
|
|
2224
|
+
invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20", "repeat-count-high");
|
|
2225
|
+
duration = calculateRepeatDuration(duration ?? defaultDuration, repeat);
|
|
2226
|
+
const originalKeyframes = [...valueKeyframesAsList];
|
|
2227
|
+
const originalTimes = [...times];
|
|
2228
|
+
ease = Array.isArray(ease) ? [...ease] : [ease];
|
|
2229
|
+
const originalEase = [...ease];
|
|
2230
|
+
for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
|
|
2231
|
+
valueKeyframesAsList.push(...originalKeyframes);
|
|
2232
|
+
for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
|
|
2233
|
+
times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
|
|
2234
|
+
ease.push(keyframeIndex === 0 ? "linear" : getEasingForSegment(originalEase, keyframeIndex - 1));
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
normalizeTimes(times, repeat);
|
|
2238
|
+
}
|
|
2239
|
+
const targetTime = startTime + (duration ?? defaultDuration);
|
|
2240
|
+
addKeyframes(valueSequence, valueKeyframesAsList, ease, times, startTime, targetTime);
|
|
2241
|
+
maxDuration = Math.max(calculatedDelay + duration, maxDuration);
|
|
2242
|
+
totalDuration = Math.max(targetTime, totalDuration);
|
|
2243
|
+
};
|
|
2244
|
+
if (isMotionValue(subject)) {
|
|
2245
|
+
const subjectSequence = getSubjectSequence(subject, sequences);
|
|
2246
|
+
resolveValueSequence(keyframes, transition, getValueSequence("default", subjectSequence));
|
|
2247
|
+
} else {
|
|
2248
|
+
const subjects = resolveSubjects(subject, keyframes, scope, elementCache);
|
|
2249
|
+
const numSubjects = subjects.length;
|
|
2250
|
+
for (let subjectIndex = 0; subjectIndex < numSubjects; subjectIndex++) {
|
|
2251
|
+
keyframes = keyframes;
|
|
2252
|
+
transition = transition;
|
|
2253
|
+
const thisSubject = subjects[subjectIndex];
|
|
2254
|
+
const subjectSequence = getSubjectSequence(thisSubject, sequences);
|
|
2255
|
+
for (const key in keyframes) {
|
|
2256
|
+
resolveValueSequence(
|
|
2257
|
+
keyframes[key],
|
|
2258
|
+
getValueTransition(transition, key),
|
|
2259
|
+
getValueSequence(key, subjectSequence),
|
|
2260
|
+
subjectIndex,
|
|
2261
|
+
numSubjects
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
prevTime = currentTime;
|
|
2267
|
+
currentTime += maxDuration;
|
|
2268
|
+
}
|
|
2269
|
+
sequences.forEach((valueSequences, element) => {
|
|
2270
|
+
for (const key in valueSequences) {
|
|
2271
|
+
const valueSequence = valueSequences[key];
|
|
2272
|
+
valueSequence.sort(compareByTime);
|
|
2273
|
+
const keyframes = [];
|
|
2274
|
+
const valueOffset = [];
|
|
2275
|
+
const valueEasing = [];
|
|
2276
|
+
for (let i = 0; i < valueSequence.length; i++) {
|
|
2277
|
+
const { at, value, easing } = valueSequence[i];
|
|
2278
|
+
keyframes.push(value);
|
|
2279
|
+
valueOffset.push(progress(0, totalDuration, at));
|
|
2280
|
+
valueEasing.push(easing || "easeOut");
|
|
2281
|
+
}
|
|
2282
|
+
if (valueOffset[0] !== 0) {
|
|
2283
|
+
valueOffset.unshift(0);
|
|
2284
|
+
keyframes.unshift(keyframes[0]);
|
|
2285
|
+
valueEasing.unshift(defaultSegmentEasing);
|
|
2286
|
+
}
|
|
2287
|
+
if (valueOffset[valueOffset.length - 1] !== 1) {
|
|
2288
|
+
valueOffset.push(1);
|
|
2289
|
+
keyframes.push(null);
|
|
2290
|
+
}
|
|
2291
|
+
if (!animationDefinitions.has(element)) {
|
|
2292
|
+
animationDefinitions.set(element, {
|
|
2293
|
+
keyframes: {},
|
|
2294
|
+
transition: {}
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2297
|
+
const definition = animationDefinitions.get(element);
|
|
2298
|
+
definition.keyframes[key] = keyframes;
|
|
2299
|
+
const { type: _type, ...remainingDefaultTransition } = defaultTransition;
|
|
2300
|
+
definition.transition[key] = {
|
|
2301
|
+
...remainingDefaultTransition,
|
|
2302
|
+
duration: totalDuration,
|
|
2303
|
+
ease: valueEasing,
|
|
2304
|
+
times: valueOffset,
|
|
2305
|
+
...sequenceTransition
|
|
2306
|
+
};
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
return animationDefinitions;
|
|
2310
|
+
}
|
|
2311
|
+
function getSubjectSequence(subject, sequences) {
|
|
2312
|
+
!sequences.has(subject) && sequences.set(subject, {});
|
|
2313
|
+
return sequences.get(subject);
|
|
2314
|
+
}
|
|
2315
|
+
function getValueSequence(name, sequences) {
|
|
2316
|
+
if (!sequences[name]) sequences[name] = [];
|
|
2317
|
+
return sequences[name];
|
|
2318
|
+
}
|
|
2319
|
+
function keyframesAsList(keyframes) {
|
|
2320
|
+
return Array.isArray(keyframes) ? keyframes : [keyframes];
|
|
2321
|
+
}
|
|
2322
|
+
function getValueTransition(transition, key) {
|
|
2323
|
+
return transition && transition[key] ? {
|
|
2324
|
+
...transition,
|
|
2325
|
+
...transition[key]
|
|
2326
|
+
} : { ...transition };
|
|
2327
|
+
}
|
|
2328
|
+
const isNumber = (keyframe) => typeof keyframe === "number";
|
|
2329
|
+
const isNumberKeyframesArray = (keyframes) => keyframes.every(isNumber);
|
|
2330
|
+
function createDOMVisualElement(element) {
|
|
2331
|
+
const options = {
|
|
2332
|
+
presenceContext: null,
|
|
2333
|
+
props: {},
|
|
2334
|
+
visualState: {
|
|
2335
|
+
renderState: {
|
|
2336
|
+
transform: {},
|
|
2337
|
+
transformOrigin: {},
|
|
2338
|
+
style: {},
|
|
2339
|
+
vars: {},
|
|
2340
|
+
attrs: {}
|
|
2341
|
+
},
|
|
2342
|
+
latestValues: {}
|
|
2343
|
+
}
|
|
2344
|
+
};
|
|
2345
|
+
const node = isSVGElement(element) && !isSVGSVGElement(element) ? new SVGVisualElement(options) : new HTMLVisualElement(options);
|
|
2346
|
+
node.mount(element);
|
|
2347
|
+
visualElementStore.set(element, node);
|
|
2348
|
+
}
|
|
2349
|
+
function createObjectVisualElement(subject) {
|
|
2350
|
+
const options = {
|
|
2351
|
+
presenceContext: null,
|
|
2352
|
+
props: {},
|
|
2353
|
+
visualState: {
|
|
2354
|
+
renderState: {
|
|
2355
|
+
output: {}
|
|
2356
|
+
},
|
|
2357
|
+
latestValues: {}
|
|
2358
|
+
}
|
|
2359
|
+
};
|
|
2360
|
+
const node = new ObjectVisualElement(options);
|
|
2361
|
+
node.mount(subject);
|
|
2362
|
+
visualElementStore.set(subject, node);
|
|
2363
|
+
}
|
|
2364
|
+
function isSingleValue(subject, keyframes) {
|
|
2365
|
+
return isMotionValue(subject) || typeof subject === "number" || typeof subject === "string" && !isDOMKeyframes(keyframes);
|
|
2366
|
+
}
|
|
2367
|
+
function animateSubject(subject, keyframes, options, scope) {
|
|
2368
|
+
const animations2 = [];
|
|
2369
|
+
if (isSingleValue(subject, keyframes)) {
|
|
2370
|
+
animations2.push(
|
|
2371
|
+
animateSingleValue(
|
|
2372
|
+
subject,
|
|
2373
|
+
isDOMKeyframes(keyframes) ? keyframes.default || keyframes : keyframes,
|
|
2374
|
+
options ? options.default || options : options
|
|
2375
|
+
)
|
|
2376
|
+
);
|
|
2377
|
+
} else {
|
|
2378
|
+
if (subject == null) {
|
|
2379
|
+
return animations2;
|
|
2380
|
+
}
|
|
2381
|
+
const subjects = resolveSubjects(subject, keyframes, scope);
|
|
2382
|
+
const numSubjects = subjects.length;
|
|
2383
|
+
invariant(Boolean(numSubjects), "No valid elements provided.", "no-valid-elements");
|
|
2384
|
+
for (let i = 0; i < numSubjects; i++) {
|
|
2385
|
+
const thisSubject = subjects[i];
|
|
2386
|
+
const createVisualElement = thisSubject instanceof Element ? createDOMVisualElement : createObjectVisualElement;
|
|
2387
|
+
if (!visualElementStore.has(thisSubject)) {
|
|
2388
|
+
createVisualElement(thisSubject);
|
|
2389
|
+
}
|
|
2390
|
+
const visualElement = visualElementStore.get(thisSubject);
|
|
2391
|
+
const transition = { ...options };
|
|
2392
|
+
if ("delay" in transition && typeof transition.delay === "function") {
|
|
2393
|
+
transition.delay = transition.delay(i, numSubjects);
|
|
2394
|
+
}
|
|
2395
|
+
animations2.push(...animateTarget(visualElement, { ...keyframes, transition }, {}));
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
return animations2;
|
|
2399
|
+
}
|
|
2400
|
+
function animateSequence(sequence, options, scope) {
|
|
2401
|
+
const animations2 = [];
|
|
2402
|
+
const animationDefinitions = createAnimationsFromSequence(sequence, options, scope, { spring });
|
|
2403
|
+
animationDefinitions.forEach(({ keyframes, transition }, subject) => {
|
|
2404
|
+
animations2.push(...animateSubject(subject, keyframes, transition));
|
|
2405
|
+
});
|
|
2406
|
+
return animations2;
|
|
2407
|
+
}
|
|
2408
|
+
function isSequence(value) {
|
|
2409
|
+
return Array.isArray(value) && value.some(Array.isArray);
|
|
2410
|
+
}
|
|
2411
|
+
function createScopedAnimate(options = {}) {
|
|
2412
|
+
const { scope, reduceMotion } = options;
|
|
2413
|
+
function scopedAnimate(subjectOrSequence, optionsOrKeyframes, options2) {
|
|
2414
|
+
let animations2 = [];
|
|
2415
|
+
let animationOnComplete;
|
|
2416
|
+
if (isSequence(subjectOrSequence)) {
|
|
2417
|
+
animations2 = animateSequence(
|
|
2418
|
+
subjectOrSequence,
|
|
2419
|
+
reduceMotion !== void 0 ? { reduceMotion, ...optionsOrKeyframes } : optionsOrKeyframes,
|
|
2420
|
+
scope
|
|
2421
|
+
);
|
|
2422
|
+
} else {
|
|
2423
|
+
const { onComplete, ...rest } = options2 || {};
|
|
2424
|
+
if (typeof onComplete === "function") {
|
|
2425
|
+
animationOnComplete = onComplete;
|
|
2426
|
+
}
|
|
2427
|
+
animations2 = animateSubject(
|
|
2428
|
+
subjectOrSequence,
|
|
2429
|
+
optionsOrKeyframes,
|
|
2430
|
+
reduceMotion !== void 0 ? { reduceMotion, ...rest } : rest,
|
|
2431
|
+
scope
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2434
|
+
const animation = new GroupAnimationWithThen(animations2);
|
|
2435
|
+
if (animationOnComplete) {
|
|
2436
|
+
animation.finished.then(animationOnComplete);
|
|
2437
|
+
}
|
|
2438
|
+
if (scope) {
|
|
2439
|
+
scope.animations.push(animation);
|
|
2440
|
+
animation.finished.then(() => {
|
|
2441
|
+
removeItem(scope.animations, animation);
|
|
2442
|
+
});
|
|
2443
|
+
}
|
|
2444
|
+
return animation;
|
|
2445
|
+
}
|
|
2446
|
+
return scopedAnimate;
|
|
2447
|
+
}
|
|
2448
|
+
const animate = createScopedAnimate();
|
|
2449
|
+
export {
|
|
2450
|
+
AnimatePresence,
|
|
2451
|
+
MotionConfig,
|
|
2452
|
+
animate,
|
|
2453
|
+
createMotionComponent,
|
|
2454
|
+
createScopedAnimate,
|
|
2455
|
+
m,
|
|
2456
|
+
motion,
|
|
2457
|
+
useIsPresent,
|
|
2458
|
+
useMotionValue,
|
|
2459
|
+
useMotionValueEvent,
|
|
2460
|
+
usePresence,
|
|
2461
|
+
useReducedMotion,
|
|
2462
|
+
useSpring,
|
|
2463
|
+
useTransform,
|
|
2464
|
+
useVelocity
|
|
2465
|
+
};
|
|
2466
|
+
//# sourceMappingURL=index.js.map
|