@octane-xplat/motion 0.0.0 → 0.7.1

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.
@@ -0,0 +1,1826 @@
1
+ import { bag4, child, clone, componentSlot, createContext, drainFrag, hookSlots, ifBlock, markChildrenBlock, template, useContext, useEffect, useLayoutEffect, useRef, useState, withSlot } from "octane";
2
+ import { textHoleUpdate } from "octane/internal/client";
3
+ import { Pressable, Row, View } from "@octane-xplat/ui";
4
+ //#region src/reduced-motion.web.ts
5
+ function readReducedMotion() {
6
+ return typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
7
+ }
8
+ function observeReducedMotion(notify) {
9
+ if (typeof matchMedia !== "function") return () => {};
10
+ const media = matchMedia("(prefers-reduced-motion: reduce)");
11
+ media.addEventListener("change", notify);
12
+ return () => media.removeEventListener("change", notify);
13
+ }
14
+ //#endregion
15
+ //#region src/config.tsrx
16
+ var _t$0$2 = /* @__PURE__ */ template("<!>", 0, 1);
17
+ var _hs$$3 = /* @__PURE__ */ hookSlots(2);
18
+ var _h$0$2 = /* @__PURE__ */ Symbol(_hs$$3);
19
+ var _h$1$2 = /* @__PURE__ */ Symbol(_hs$$3 + 1);
20
+ var __childrenBody$3 = {};
21
+ var ConfigContext = /* @__PURE__ */ createContext({ reducedMotion: "never" });
22
+ function useReducedMotion() {
23
+ const [reduced, setReduced] = useState(readReducedMotion, _h$0$2);
24
+ useEffect(() => {
25
+ const update = () => setReduced(readReducedMotion());
26
+ const off = observeReducedMotion(update);
27
+ update();
28
+ return off;
29
+ }, [], _h$1$2);
30
+ return reduced;
31
+ }
32
+ var MotionConfig = function MotionConfig(props, __s, __extra) {
33
+ const __block = __s.block;
34
+ const parent = useContext(ConfigContext);
35
+ const value = {
36
+ transition: props.transition ?? parent.transition,
37
+ reducedMotion: props.reducedMotion ?? parent.reducedMotion
38
+ };
39
+ function __children$1(__props, __s, __extra) {
40
+ const __block = __s.block;
41
+ let _b = __s.slots[0];
42
+ if (_b === void 0) {
43
+ let _m0, _m1;
44
+ const _root = clone(_t$0$2);
45
+ _m0 = __block.parentNode;
46
+ _m1 = child(_root);
47
+ drainFrag(_root, __block.parentNode, __block.endMarker);
48
+ _b = bag4(__s, null, _m0, _m1, null, void 0);
49
+ }
50
+ {
51
+ const _v = props.children;
52
+ _b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
53
+ _b.d = _v;
54
+ }
55
+ }
56
+ componentSlot(__s, 0, __block.parentNode, ConfigContext, {
57
+ "value": value,
58
+ "children": markChildrenBlock(__children$1, __childrenBody$3)
59
+ }, __block.endMarker, void 0, void 0, true, void 0, "c:1bf28fec");
60
+ };
61
+ //#endregion
62
+ //#region src/presence-state.ts
63
+ var PresenceState = class {
64
+ present;
65
+ complete;
66
+ members = /* @__PURE__ */ new Set();
67
+ pending = /* @__PURE__ */ new Map();
68
+ sequence = 0;
69
+ generation = 0;
70
+ disposed = false;
71
+ removed = false;
72
+ constructor(present, complete) {
73
+ this.present = present;
74
+ this.complete = complete;
75
+ }
76
+ register(member) {
77
+ this.members.add(member);
78
+ if (!this.present) this.restart(member);
79
+ return () => {
80
+ this.members.delete(member);
81
+ this.pending.delete(member);
82
+ this.check();
83
+ };
84
+ }
85
+ setPresent(present) {
86
+ if (this.disposed || present === this.present) return;
87
+ this.present = present;
88
+ ++this.generation;
89
+ this.removed = false;
90
+ this.pending.clear();
91
+ if (present) for (const member of this.members) member.enter();
92
+ else {
93
+ for (const member of this.members) this.restart(member);
94
+ this.check();
95
+ }
96
+ }
97
+ restart(member) {
98
+ if (this.disposed || this.present || !this.members.has(member)) return;
99
+ const token = ++this.sequence;
100
+ this.pending.set(member, token);
101
+ member.exit().then((result) => {
102
+ if (this.disposed || this.present || this.pending.get(member) !== token) return;
103
+ if (result !== "finished") return;
104
+ this.pending.delete(member);
105
+ this.check();
106
+ });
107
+ }
108
+ check() {
109
+ const generation = this.generation;
110
+ queueMicrotask(() => {
111
+ if (!this.disposed && !this.present && !this.removed && !this.pending.size && generation === this.generation) {
112
+ this.removed = true;
113
+ this.complete();
114
+ }
115
+ });
116
+ }
117
+ destroy() {
118
+ this.disposed = true;
119
+ ++this.generation;
120
+ this.members.clear();
121
+ this.pending.clear();
122
+ }
123
+ };
124
+ //#endregion
125
+ //#region src/presence-input.web.ts
126
+ function blockInput(node) {
127
+ const inert = node.hasAttribute("inert");
128
+ const hidden = node.getAttribute("aria-hidden");
129
+ const pointerEvents = node.style.pointerEvents;
130
+ const focused = node.ownerDocument.activeElement;
131
+ if (focused && node.contains(focused)) focused.blur();
132
+ node.setAttribute("inert", "");
133
+ node.setAttribute("aria-hidden", "true");
134
+ node.style.pointerEvents = "none";
135
+ return () => {
136
+ if (!inert) node.removeAttribute("inert");
137
+ if (hidden === null) node.removeAttribute("aria-hidden");
138
+ else node.setAttribute("aria-hidden", hidden);
139
+ node.style.pointerEvents = pointerEvents;
140
+ };
141
+ }
142
+ //#endregion
143
+ //#region src/presence.tsrx
144
+ var _t$0$1 = /* @__PURE__ */ template("<!>", 0, 1);
145
+ var _hs$$2 = /* @__PURE__ */ hookSlots(7);
146
+ var __childrenBody$1 = {};
147
+ var __childrenBody$$1 = {};
148
+ function __then$0(__props, __s, __extra) {
149
+ const __block = __s.block;
150
+ const bind = __extra[0];
151
+ const children = __extra[1];
152
+ const host = __extra[2];
153
+ const restoreInput = __extra[3];
154
+ const state = __extra[4];
155
+ const syncInput = __extra[5];
156
+ const viewProps = __extra[6];
157
+ function __children$2(__props, __s, __extra) {
158
+ const __block = __s.block;
159
+ function __children$4(__props, __s, __extra) {
160
+ const __block = __s.block;
161
+ let _b = __s.slots[0];
162
+ if (_b === void 0) {
163
+ let _m0, _m1;
164
+ const _root = clone(_t$0$1);
165
+ _m0 = __block.parentNode;
166
+ _m1 = child(_root);
167
+ drainFrag(_root, __block.parentNode, __block.endMarker);
168
+ _b = bag4(__s, null, _m0, _m1, null, void 0);
169
+ }
170
+ {
171
+ const _v = children;
172
+ _b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
173
+ _b.d = _v;
174
+ }
175
+ }
176
+ componentSlot(__s, 0, __block.parentNode, PresenceContext, {
177
+ "value": state,
178
+ "children": markChildrenBlock(__children$4, __childrenBody$1)
179
+ }, __block.endMarker, void 0, void 0, void 0, void 0, "c:63be6025");
180
+ }
181
+ componentSlot(__s, 0, __block.parentNode, View, {
182
+ ...viewProps,
183
+ "bind": (node) => {
184
+ if (host.current !== node) {
185
+ restoreInput.current?.();
186
+ restoreInput.current = null;
187
+ host.current = node;
188
+ }
189
+ syncInput();
190
+ bind?.(node);
191
+ },
192
+ "children": markChildrenBlock(__children$2, __childrenBody$$1)
193
+ }, __block.endMarker, void 0, void 0, void 0, void 0, "c:cf4c2460");
194
+ }
195
+ var PresenceContext = /* @__PURE__ */ createContext(null);
196
+ var Presence = function Presence(props, __s, __extra) {
197
+ const __block = __s.block;
198
+ const [retained, setRetained] = useState(props.present, _hs$$2 + 0);
199
+ const latest = useRef(props, _hs$$2 + 1);
200
+ latest.current = props;
201
+ const ref = useRef(null, _hs$$2 + 2);
202
+ if (!ref.current) ref.current = new PresenceState(props.present, () => {
203
+ setRetained(false);
204
+ latest.current.onExitComplete?.();
205
+ });
206
+ const state = ref.current;
207
+ const host = useRef(null, _hs$$2 + 3);
208
+ const restoreInput = useRef(null, _hs$$2 + 4);
209
+ const syncInput = () => {
210
+ if (!props.present && host.current && !restoreInput.current) restoreInput.current = blockInput(host.current);
211
+ if (props.present && restoreInput.current) {
212
+ restoreInput.current();
213
+ restoreInput.current = null;
214
+ }
215
+ };
216
+ useLayoutEffect(() => {
217
+ if (props.present) setRetained(true);
218
+ syncInput();
219
+ state.setPresent(props.present);
220
+ }, [props.present], _hs$$2 + 5);
221
+ useLayoutEffect(() => () => {
222
+ state.destroy();
223
+ restoreInput.current?.();
224
+ restoreInput.current = null;
225
+ host.current = null;
226
+ }, [], _hs$$2 + 6);
227
+ const { present, onExitComplete, children, bind, ...viewProps } = props;
228
+ if (__s.block.pending && !__s.block.crossRenderUpdate) return;
229
+ {
230
+ const __ifCondition = props.present || retained;
231
+ ifBlock(__s, 0, __block.parentNode, __ifCondition, __then$0, null, __block.endMarker, __ifCondition ? [
232
+ bind,
233
+ children,
234
+ host,
235
+ restoreInput,
236
+ state,
237
+ syncInput,
238
+ viewProps
239
+ ] : void 0);
240
+ }
241
+ };
242
+ //#endregion
243
+ //#region src/clock.web.ts
244
+ var clock = {
245
+ now: () => performance.now(),
246
+ request: (callback) => requestAnimationFrame(callback),
247
+ cancel: (id) => cancelAnimationFrame(id)
248
+ };
249
+ //#endregion
250
+ //#region src/host.web.ts
251
+ function attachHost(node) {
252
+ const transform = node.style.transform;
253
+ const opacity = node.style.opacity;
254
+ const computed = getComputedStyle(node);
255
+ if (computed.transform && computed.transform !== "none") throw new Error("motion: put existing CSS transforms on an outer container");
256
+ return {
257
+ read: () => ({
258
+ opacity: Number(computed.opacity || 1),
259
+ x: 0,
260
+ y: 0,
261
+ scale: 1,
262
+ scaleX: 1,
263
+ scaleY: 1,
264
+ rotate: 0
265
+ }),
266
+ write(values) {
267
+ if (values.opacity !== void 0) node.style.opacity = String(Math.min(1, Math.max(0, values.opacity)));
268
+ if (Object.keys(values).some((key) => key !== "opacity")) node.style.transform = `translateX(${values.x ?? 0}px) translateY(${values.y ?? 0}px) scale(${values.scale ?? 1}) scaleX(${values.scaleX ?? 1}) scaleY(${values.scaleY ?? 1}) rotate(${values.rotate ?? 0}deg)`;
269
+ },
270
+ restore() {
271
+ node.style.transform = transform;
272
+ node.style.opacity = opacity;
273
+ }
274
+ };
275
+ }
276
+ //#endregion
277
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/clamp.mjs
278
+ var clamp = (min, max, v) => {
279
+ if (v > max) return max;
280
+ if (v < min) return min;
281
+ return v;
282
+ };
283
+ //#endregion
284
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/format-error-message.mjs
285
+ function formatErrorMessage(message, errorCode) {
286
+ return errorCode ? `${message}. For more information and steps for solving, visit https://motion.dev/troubleshooting/${errorCode}` : message;
287
+ }
288
+ //#endregion
289
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/errors.mjs
290
+ var warning = () => {};
291
+ var invariant = () => {};
292
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
293
+ warning = (check, message, errorCode) => {
294
+ if (!check && typeof console !== "undefined") console.warn(formatErrorMessage(message, errorCode));
295
+ };
296
+ invariant = (check, message, errorCode) => {
297
+ if (!check) throw new Error(formatErrorMessage(message, errorCode));
298
+ };
299
+ }
300
+ //#endregion
301
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/global-config.mjs
302
+ var MotionGlobalConfig = {};
303
+ //#endregion
304
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/noop.mjs
305
+ var noop = /* @__NO_SIDE_EFFECTS__ */ (any) => any;
306
+ //#endregion
307
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/pipe.mjs
308
+ /**
309
+ * Pipe
310
+ * Compose other transformers to run linearily
311
+ * pipe(min(20), max(40))
312
+ * @param {...functions} transformers
313
+ * @return {function}
314
+ */
315
+ var pipe = (...transformers) => transformers.reduce((a, b) => (v) => b(a(v)));
316
+ //#endregion
317
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/progress.mjs
318
+ var progress = /* @__NO_SIDE_EFFECTS__ */ (from, to, value) => {
319
+ const range = to - from;
320
+ return range ? (value - from) / range : 1;
321
+ };
322
+ //#endregion
323
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/time-conversion.mjs
324
+ /**
325
+ * Converts seconds to milliseconds
326
+ *
327
+ * @param seconds - Time in seconds.
328
+ * @return milliseconds - Converted time in milliseconds.
329
+ */
330
+ var secondsToMilliseconds = /* @__NO_SIDE_EFFECTS__ */ (seconds) => seconds * 1e3;
331
+ var millisecondsToSeconds = /* @__NO_SIDE_EFFECTS__ */ (milliseconds) => milliseconds / 1e3;
332
+ //#endregion
333
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/cubic-bezier.mjs
334
+ var calcBezier = (t, a1, a2) => (((1 - 3 * a2 + 3 * a1) * t + (3 * a2 - 6 * a1)) * t + 3 * a1) * t;
335
+ var subdivisionPrecision = 1e-7;
336
+ var subdivisionMaxIterations = 12;
337
+ function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
338
+ let currentX;
339
+ let currentT;
340
+ let i = 0;
341
+ do {
342
+ currentT = lowerBound + (upperBound - lowerBound) / 2;
343
+ currentX = calcBezier(currentT, mX1, mX2) - x;
344
+ if (currentX > 0) upperBound = currentT;
345
+ else lowerBound = currentT;
346
+ } while (Math.abs(currentX) > subdivisionPrecision && ++i < subdivisionMaxIterations);
347
+ return currentT;
348
+ }
349
+ /*#__NO_SIDE_EFFECTS__*/
350
+ function cubicBezier(mX1, mY1, mX2, mY2) {
351
+ if (mX1 === mY1 && mX2 === mY2) return noop;
352
+ const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
353
+ return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
354
+ }
355
+ //#endregion
356
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/modifiers/mirror.mjs
357
+ var mirrorEasing = /* @__NO_SIDE_EFFECTS__ */ (easing) => (p) => p <= .5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
358
+ //#endregion
359
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/modifiers/reverse.mjs
360
+ var reverseEasing = /* @__NO_SIDE_EFFECTS__ */ (easing) => (p) => 1 - easing(1 - p);
361
+ //#endregion
362
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/back.mjs
363
+ var backOut = /*@__PURE__*/ cubicBezier(.33, 1.53, .69, .99);
364
+ var backIn = /*@__PURE__*/ reverseEasing(backOut);
365
+ var backInOut = /*@__PURE__*/ mirrorEasing(backIn);
366
+ //#endregion
367
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/anticipate.mjs
368
+ var anticipate = (p) => p >= 1 ? 1 : (p *= 2) < 1 ? .5 * backIn(p) : .5 * (2 - Math.pow(2, -10 * (p - 1)));
369
+ //#endregion
370
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/circ.mjs
371
+ var circIn = (p) => 1 - Math.sin(Math.acos(p));
372
+ var circOut = /* @__PURE__ */ reverseEasing(circIn);
373
+ var circInOut = /* @__PURE__ */ mirrorEasing(circIn);
374
+ //#endregion
375
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/ease.mjs
376
+ var easeIn = /*@__PURE__*/ cubicBezier(.42, 0, 1, 1);
377
+ var easeOut = /*@__PURE__*/ cubicBezier(0, 0, .58, 1);
378
+ var easeInOut = /*@__PURE__*/ cubicBezier(.42, 0, .58, 1);
379
+ //#endregion
380
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/utils/is-easing-array.mjs
381
+ var isEasingArray = /* @__NO_SIDE_EFFECTS__ */ (ease) => {
382
+ return Array.isArray(ease) && typeof ease[0] !== "number";
383
+ };
384
+ //#endregion
385
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/utils/is-bezier-definition.mjs
386
+ var isBezierDefinition = /* @__NO_SIDE_EFFECTS__ */ (easing) => Array.isArray(easing) && typeof easing[0] === "number";
387
+ //#endregion
388
+ //#region ../../node_modules/.pnpm/motion-utils@12.39.0/node_modules/motion-utils/dist/es/easing/utils/map.mjs
389
+ var easingLookup = {
390
+ linear: noop,
391
+ easeIn,
392
+ easeInOut,
393
+ easeOut,
394
+ circIn,
395
+ circInOut,
396
+ circOut,
397
+ backIn,
398
+ backInOut,
399
+ backOut,
400
+ anticipate
401
+ };
402
+ var isValidEasing = (easing) => {
403
+ return typeof easing === "string";
404
+ };
405
+ var easingDefinitionToFunction = (definition) => {
406
+ if (/* @__PURE__ */ isBezierDefinition(definition)) {
407
+ invariant(definition.length === 4, `Cubic bezier arrays must contain four numerical values.`, "cubic-bezier-length");
408
+ const [x1, y1, x2, y2] = definition;
409
+ return /* @__PURE__ */ cubicBezier(x1, y1, x2, y2);
410
+ } else if (isValidEasing(definition)) {
411
+ invariant(easingLookup[definition] !== void 0, `Invalid easing type '${definition}'`, "invalid-easing-type");
412
+ return easingLookup[definition];
413
+ }
414
+ return definition;
415
+ };
416
+ //#endregion
417
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/utils/is-css-variable.mjs
418
+ var checkStringStartsWith = (token) => (key) => typeof key === "string" && key.startsWith(token);
419
+ var startsAsVariableToken = /*@__PURE__*/ checkStringStartsWith("var(--");
420
+ var isCSSVariableToken = (value) => {
421
+ if (!startsAsVariableToken(value)) return false;
422
+ return singleCssVariableRegex.test(value.split("/*")[0].trim());
423
+ };
424
+ var singleCssVariableRegex = /var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu;
425
+ //#endregion
426
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/numbers/index.mjs
427
+ var number = {
428
+ test: (v) => typeof v === "number",
429
+ parse: parseFloat,
430
+ transform: (v) => v
431
+ };
432
+ var alpha = {
433
+ ...number,
434
+ transform: (v) => clamp(0, 1, v)
435
+ };
436
+ ({ ...number });
437
+ //#endregion
438
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/utils/sanitize.mjs
439
+ var sanitize = (v) => Math.round(v * 1e5) / 1e5;
440
+ //#endregion
441
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/utils/float-regex.mjs
442
+ var floatRegex = /-?(?:\d+(?:\.\d+)?|\.\d+)/gu;
443
+ //#endregion
444
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/utils/is-nullish.mjs
445
+ function isNullish(v) {
446
+ return v == null;
447
+ }
448
+ //#endregion
449
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/utils/single-color-regex.mjs
450
+ var singleColorRegex = /^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu;
451
+ //#endregion
452
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/color/utils.mjs
453
+ /**
454
+ * Returns true if the provided string is a color, ie rgba(0,0,0,0) or #000,
455
+ * but false if a number or multiple colors
456
+ */
457
+ var isColorString = (type, testProp) => (v) => {
458
+ return Boolean(typeof v === "string" && singleColorRegex.test(v) && v.startsWith(type) || testProp && !isNullish(v) && Object.prototype.hasOwnProperty.call(v, testProp));
459
+ };
460
+ var splitColor = (aName, bName, cName) => (v) => {
461
+ if (typeof v !== "string") return v;
462
+ const [a, b, c, alpha] = v.match(floatRegex);
463
+ return {
464
+ [aName]: parseFloat(a),
465
+ [bName]: parseFloat(b),
466
+ [cName]: parseFloat(c),
467
+ alpha: alpha !== void 0 ? parseFloat(alpha) : 1
468
+ };
469
+ };
470
+ //#endregion
471
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/color/rgba.mjs
472
+ var clampRgbUnit = (v) => clamp(0, 255, v);
473
+ var rgbUnit = {
474
+ ...number,
475
+ transform: (v) => Math.round(clampRgbUnit(v))
476
+ };
477
+ var rgba = {
478
+ test: /*@__PURE__*/ isColorString("rgb", "red"),
479
+ parse: /*@__PURE__*/ splitColor("red", "green", "blue"),
480
+ transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => "rgba(" + rgbUnit.transform(red) + ", " + rgbUnit.transform(green) + ", " + rgbUnit.transform(blue) + ", " + sanitize(alpha.transform(alpha$1)) + ")"
481
+ };
482
+ //#endregion
483
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/color/hex.mjs
484
+ function parseHex(v) {
485
+ let r = "";
486
+ let g = "";
487
+ let b = "";
488
+ let a = "";
489
+ if (v.length > 5) {
490
+ r = v.substring(1, 3);
491
+ g = v.substring(3, 5);
492
+ b = v.substring(5, 7);
493
+ a = v.substring(7, 9);
494
+ } else {
495
+ r = v.substring(1, 2);
496
+ g = v.substring(2, 3);
497
+ b = v.substring(3, 4);
498
+ a = v.substring(4, 5);
499
+ r += r;
500
+ g += g;
501
+ b += b;
502
+ a += a;
503
+ }
504
+ return {
505
+ red: parseInt(r, 16),
506
+ green: parseInt(g, 16),
507
+ blue: parseInt(b, 16),
508
+ alpha: a ? parseInt(a, 16) / 255 : 1
509
+ };
510
+ }
511
+ var hex = {
512
+ test: /*@__PURE__*/ isColorString("#"),
513
+ parse: parseHex,
514
+ transform: rgba.transform
515
+ };
516
+ //#endregion
517
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/numbers/units.mjs
518
+ var createUnitType = /* @__NO_SIDE_EFFECTS__ */ (unit) => ({
519
+ test: (v) => typeof v === "string" && v.endsWith(unit) && v.split(" ").length === 1,
520
+ parse: parseFloat,
521
+ transform: (v) => `${v}${unit}`
522
+ });
523
+ var percent = /*@__PURE__*/ createUnitType("%");
524
+ //#endregion
525
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/color/hsla.mjs
526
+ var hsla = {
527
+ test: /*@__PURE__*/ isColorString("hsl", "hue"),
528
+ parse: /*@__PURE__*/ splitColor("hue", "saturation", "lightness"),
529
+ transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
530
+ return "hsla(" + Math.round(hue) + ", " + percent.transform(sanitize(saturation)) + ", " + percent.transform(sanitize(lightness)) + ", " + sanitize(alpha.transform(alpha$1)) + ")";
531
+ }
532
+ };
533
+ //#endregion
534
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/color/index.mjs
535
+ var color = {
536
+ test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
537
+ parse: (v) => {
538
+ if (rgba.test(v)) return rgba.parse(v);
539
+ else if (hsla.test(v)) return hsla.parse(v);
540
+ else return hex.parse(v);
541
+ },
542
+ transform: (v) => {
543
+ return typeof v === "string" ? v : v.hasOwnProperty("red") ? rgba.transform(v) : hsla.transform(v);
544
+ },
545
+ getAnimatableNone: (v) => {
546
+ const parsed = color.parse(v);
547
+ parsed.alpha = 0;
548
+ return color.transform(parsed);
549
+ }
550
+ };
551
+ //#endregion
552
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/utils/color-regex.mjs
553
+ var colorRegex = /(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;
554
+ //#endregion
555
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/complex/index.mjs
556
+ function test(v) {
557
+ return isNaN(v) && typeof v === "string" && (v.match(floatRegex)?.length || 0) + (v.match(colorRegex)?.length || 0) > 0;
558
+ }
559
+ var NUMBER_TOKEN = "number";
560
+ var COLOR_TOKEN = "color";
561
+ var VAR_TOKEN = "var";
562
+ var VAR_FUNCTION_TOKEN = "var(";
563
+ var SPLIT_TOKEN = "${}";
564
+ var complexRegex = /var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;
565
+ function analyseComplexValue(value) {
566
+ const originalValue = value.toString();
567
+ const values = [];
568
+ const indexes = {
569
+ color: [],
570
+ number: [],
571
+ var: []
572
+ };
573
+ const types = [];
574
+ let i = 0;
575
+ return {
576
+ values,
577
+ split: originalValue.replace(complexRegex, (parsedValue) => {
578
+ if (color.test(parsedValue)) {
579
+ indexes.color.push(i);
580
+ types.push(COLOR_TOKEN);
581
+ values.push(color.parse(parsedValue));
582
+ } else if (parsedValue.startsWith(VAR_FUNCTION_TOKEN)) {
583
+ indexes.var.push(i);
584
+ types.push(VAR_TOKEN);
585
+ values.push(parsedValue);
586
+ } else {
587
+ indexes.number.push(i);
588
+ types.push(NUMBER_TOKEN);
589
+ values.push(parseFloat(parsedValue));
590
+ }
591
+ ++i;
592
+ return SPLIT_TOKEN;
593
+ }).split(SPLIT_TOKEN),
594
+ indexes,
595
+ types
596
+ };
597
+ }
598
+ function parseComplexValue(v) {
599
+ return analyseComplexValue(v).values;
600
+ }
601
+ function buildTransformer({ split, types }) {
602
+ const numSections = split.length;
603
+ return (v) => {
604
+ let output = "";
605
+ for (let i = 0; i < numSections; i++) {
606
+ output += split[i];
607
+ if (v[i] !== void 0) {
608
+ const type = types[i];
609
+ if (type === NUMBER_TOKEN) output += sanitize(v[i]);
610
+ else if (type === COLOR_TOKEN) output += color.transform(v[i]);
611
+ else output += v[i];
612
+ }
613
+ }
614
+ return output;
615
+ };
616
+ }
617
+ function createTransformer(source) {
618
+ return buildTransformer(analyseComplexValue(source));
619
+ }
620
+ var convertNumbersToZero = (v) => typeof v === "number" ? 0 : color.test(v) ? color.getAnimatableNone(v) : v;
621
+ /**
622
+ * Convert a parsed value to its zero equivalent, but preserve numbers
623
+ * that act as divisors in CSS calc() expressions.
624
+ *
625
+ * analyseComplexValue extracts numbers from CSS strings and puts the
626
+ * surrounding text into a `split` template array. For example:
627
+ * "calc(var(--gap) / 5)" → values: [var(--gap), 5]
628
+ * split: ["calc(", " / ", ")"]
629
+ *
630
+ * When building a zero-equivalent for animation, naively zeroing all
631
+ * numbers turns the divisor into 0 → "calc(var(--gap) / 0)" → NaN.
632
+ * We detect this by checking whether the text preceding a number
633
+ * (split[i]) ends with "/" — the CSS calc division operator.
634
+ */
635
+ var convertToZero = (value, splitBefore) => {
636
+ if (typeof value === "number") return splitBefore?.trim().endsWith("/") ? value : 0;
637
+ return convertNumbersToZero(value);
638
+ };
639
+ function getAnimatableNone(v) {
640
+ const info = analyseComplexValue(v);
641
+ return buildTransformer(info)(info.values.map((value, i) => convertToZero(value, info.split[i])));
642
+ }
643
+ var complex = {
644
+ test,
645
+ parse: parseComplexValue,
646
+ createTransformer,
647
+ getAnimatableNone
648
+ };
649
+ //#endregion
650
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/value/types/color/hsla-to-rgba.mjs
651
+ function hueToRgb(p, q, t) {
652
+ if (t < 0) t += 1;
653
+ if (t > 1) t -= 1;
654
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
655
+ if (t < 1 / 2) return q;
656
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
657
+ return p;
658
+ }
659
+ function hslaToRgba({ hue, saturation, lightness, alpha }) {
660
+ hue /= 360;
661
+ saturation /= 100;
662
+ lightness /= 100;
663
+ let red = 0;
664
+ let green = 0;
665
+ let blue = 0;
666
+ if (!saturation) red = green = blue = lightness;
667
+ else {
668
+ const q = lightness < .5 ? lightness * (1 + saturation) : lightness + saturation - lightness * saturation;
669
+ const p = 2 * lightness - q;
670
+ red = hueToRgb(p, q, hue + 1 / 3);
671
+ green = hueToRgb(p, q, hue);
672
+ blue = hueToRgb(p, q, hue - 1 / 3);
673
+ }
674
+ return {
675
+ red: Math.round(red * 255),
676
+ green: Math.round(green * 255),
677
+ blue: Math.round(blue * 255),
678
+ alpha
679
+ };
680
+ }
681
+ //#endregion
682
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/mix/immediate.mjs
683
+ function mixImmediate(a, b) {
684
+ return (p) => p > 0 ? b : a;
685
+ }
686
+ //#endregion
687
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/mix/number.mjs
688
+ var mixNumber$1 = (from, to, progress) => {
689
+ return from + (to - from) * progress;
690
+ };
691
+ //#endregion
692
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/mix/color.mjs
693
+ var mixLinearColor = (from, to, v) => {
694
+ const fromExpo = from * from;
695
+ const expo = v * (to * to - fromExpo) + fromExpo;
696
+ return expo < 0 ? 0 : Math.sqrt(expo);
697
+ };
698
+ var colorTypes = [
699
+ hex,
700
+ rgba,
701
+ hsla
702
+ ];
703
+ var getColorType = (v) => colorTypes.find((type) => type.test(v));
704
+ function asRGBA(color) {
705
+ const type = getColorType(color);
706
+ warning(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`, "color-not-animatable");
707
+ if (!Boolean(type)) return false;
708
+ let model = type.parse(color);
709
+ if (type === hsla) model = hslaToRgba(model);
710
+ return model;
711
+ }
712
+ var mixColor = (from, to) => {
713
+ const fromRGBA = asRGBA(from);
714
+ const toRGBA = asRGBA(to);
715
+ if (!fromRGBA || !toRGBA) return mixImmediate(from, to);
716
+ const blended = { ...fromRGBA };
717
+ return (v) => {
718
+ blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
719
+ blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
720
+ blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
721
+ blended.alpha = mixNumber$1(fromRGBA.alpha, toRGBA.alpha, v);
722
+ return rgba.transform(blended);
723
+ };
724
+ };
725
+ //#endregion
726
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/mix/visibility.mjs
727
+ var invisibleValues = /* @__PURE__ */ new Set(["none", "hidden"]);
728
+ /**
729
+ * Returns a function that, when provided a progress value between 0 and 1,
730
+ * will return the "none" or "hidden" string only when the progress is that of
731
+ * the origin or target.
732
+ */
733
+ function mixVisibility(origin, target) {
734
+ if (invisibleValues.has(origin)) return (p) => p <= 0 ? origin : target;
735
+ else return (p) => p >= 1 ? target : origin;
736
+ }
737
+ //#endregion
738
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/mix/complex.mjs
739
+ function mixNumber(a, b) {
740
+ return (p) => mixNumber$1(a, b, p);
741
+ }
742
+ function getMixer(a) {
743
+ if (typeof a === "number") return mixNumber;
744
+ else if (typeof a === "string") return isCSSVariableToken(a) ? mixImmediate : color.test(a) ? mixColor : mixComplex;
745
+ else if (Array.isArray(a)) return mixArray;
746
+ else if (typeof a === "object") return color.test(a) ? mixColor : mixObject;
747
+ return mixImmediate;
748
+ }
749
+ function mixArray(a, b) {
750
+ const output = [...a];
751
+ const numValues = output.length;
752
+ const blendValue = a.map((v, i) => getMixer(v)(v, b[i]));
753
+ return (p) => {
754
+ for (let i = 0; i < numValues; i++) output[i] = blendValue[i](p);
755
+ return output;
756
+ };
757
+ }
758
+ function mixObject(a, b) {
759
+ const output = {
760
+ ...a,
761
+ ...b
762
+ };
763
+ const blendValue = {};
764
+ for (const key in output) if (a[key] !== void 0 && b[key] !== void 0) blendValue[key] = getMixer(a[key])(a[key], b[key]);
765
+ return (v) => {
766
+ for (const key in blendValue) output[key] = blendValue[key](v);
767
+ return output;
768
+ };
769
+ }
770
+ function matchOrder(origin, target) {
771
+ const orderedOrigin = [];
772
+ const pointers = {
773
+ color: 0,
774
+ var: 0,
775
+ number: 0
776
+ };
777
+ for (let i = 0; i < target.values.length; i++) {
778
+ const type = target.types[i];
779
+ const originIndex = origin.indexes[type][pointers[type]];
780
+ const originValue = origin.values[originIndex] ?? 0;
781
+ orderedOrigin[i] = originValue;
782
+ pointers[type]++;
783
+ }
784
+ return orderedOrigin;
785
+ }
786
+ var mixComplex = (origin, target) => {
787
+ const template = complex.createTransformer(target);
788
+ const originStats = analyseComplexValue(origin);
789
+ const targetStats = analyseComplexValue(target);
790
+ if (originStats.indexes.var.length === targetStats.indexes.var.length && originStats.indexes.color.length === targetStats.indexes.color.length && originStats.indexes.number.length >= targetStats.indexes.number.length) {
791
+ if (invisibleValues.has(origin) && !targetStats.values.length || invisibleValues.has(target) && !originStats.values.length) return mixVisibility(origin, target);
792
+ return pipe(mixArray(matchOrder(originStats, targetStats), targetStats.values), template);
793
+ } else {
794
+ warning(true, `Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`, "complex-values-different");
795
+ return mixImmediate(origin, target);
796
+ }
797
+ };
798
+ //#endregion
799
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/mix/index.mjs
800
+ function mix(from, to, p) {
801
+ if (typeof from === "number" && typeof to === "number" && typeof p === "number") return mixNumber$1(from, to, p);
802
+ return getMixer(from)(from, to);
803
+ }
804
+ //#endregion
805
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/waapi/utils/linear.mjs
806
+ var generateLinearEasing = (easing, duration, resolution = 10) => {
807
+ let points = "";
808
+ const numPoints = Math.max(Math.round(duration / resolution), 2);
809
+ for (let i = 0; i < numPoints; i++) points += Math.round(easing(i / (numPoints - 1)) * 1e4) / 1e4 + ", ";
810
+ return `linear(${points.substring(0, points.length - 2)})`;
811
+ };
812
+ //#endregion
813
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/generators/utils/calc-duration.mjs
814
+ /**
815
+ * Implement a practical max duration for keyframe generation
816
+ * to prevent infinite loops
817
+ */
818
+ var maxGeneratorDuration = 2e4;
819
+ function calcGeneratorDuration(generator) {
820
+ let duration = 0;
821
+ const timeStep = 50;
822
+ let state = generator.next(duration);
823
+ while (!state.done && duration < 2e4) {
824
+ duration += timeStep;
825
+ state = generator.next(duration);
826
+ }
827
+ return duration >= 2e4 ? Infinity : duration;
828
+ }
829
+ //#endregion
830
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/generators/utils/create-generator-easing.mjs
831
+ /**
832
+ * Create a progress => progress easing function from a generator.
833
+ */
834
+ function createGeneratorEasing(options, scale = 100, createGenerator) {
835
+ const generator = createGenerator({
836
+ ...options,
837
+ keyframes: [0, scale]
838
+ });
839
+ const duration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
840
+ return {
841
+ type: "keyframes",
842
+ ease: (progress) => {
843
+ return generator.next(duration * progress).value / scale;
844
+ },
845
+ duration: /* @__PURE__ */ millisecondsToSeconds(duration)
846
+ };
847
+ }
848
+ //#endregion
849
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/generators/spring.mjs
850
+ var springDefaults = {
851
+ stiffness: 100,
852
+ damping: 10,
853
+ mass: 1,
854
+ velocity: 0,
855
+ duration: 800,
856
+ bounce: .3,
857
+ visualDuration: .3,
858
+ restSpeed: {
859
+ granular: .01,
860
+ default: 2
861
+ },
862
+ restDelta: {
863
+ granular: .005,
864
+ default: .5
865
+ },
866
+ minDuration: .01,
867
+ maxDuration: 10,
868
+ minDamping: .05,
869
+ maxDamping: 1
870
+ };
871
+ function calcAngularFreq(undampedFreq, dampingRatio) {
872
+ return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
873
+ }
874
+ var rootIterations = 12;
875
+ function approximateRoot(envelope, derivative, initialGuess) {
876
+ let result = initialGuess;
877
+ for (let i = 1; i < rootIterations; i++) result = result - envelope(result) / derivative(result);
878
+ return result;
879
+ }
880
+ /**
881
+ * This is ported from the Framer implementation of duration-based spring resolution.
882
+ */
883
+ var safeMin = .001;
884
+ function findSpring({ duration = springDefaults.duration, bounce = springDefaults.bounce, velocity = springDefaults.velocity, mass = springDefaults.mass }) {
885
+ let envelope;
886
+ let derivative;
887
+ warning(duration <= /* @__PURE__ */ secondsToMilliseconds(springDefaults.maxDuration), "Spring duration must be 10 seconds or less", "spring-duration-limit");
888
+ let dampingRatio = 1 - bounce;
889
+ /**
890
+ * Restrict dampingRatio and duration to within acceptable ranges.
891
+ */
892
+ dampingRatio = clamp(springDefaults.minDamping, springDefaults.maxDamping, dampingRatio);
893
+ duration = clamp(springDefaults.minDuration, springDefaults.maxDuration, /* @__PURE__ */ millisecondsToSeconds(duration));
894
+ if (dampingRatio < 1) {
895
+ /**
896
+ * Underdamped spring
897
+ */
898
+ envelope = (undampedFreq) => {
899
+ const exponentialDecay = undampedFreq * dampingRatio;
900
+ const delta = exponentialDecay * duration;
901
+ const a = exponentialDecay - velocity;
902
+ const b = calcAngularFreq(undampedFreq, dampingRatio);
903
+ const c = Math.exp(-delta);
904
+ return safeMin - a / b * c;
905
+ };
906
+ derivative = (undampedFreq) => {
907
+ const delta = undampedFreq * dampingRatio * duration;
908
+ const d = delta * velocity + velocity;
909
+ const e = Math.pow(dampingRatio, 2) * Math.pow(undampedFreq, 2) * duration;
910
+ const f = Math.exp(-delta);
911
+ const g = calcAngularFreq(Math.pow(undampedFreq, 2), dampingRatio);
912
+ return (-envelope(undampedFreq) + safeMin > 0 ? -1 : 1) * ((d - e) * f) / g;
913
+ };
914
+ } else {
915
+ /**
916
+ * Critically-damped spring
917
+ */
918
+ envelope = (undampedFreq) => {
919
+ return -.001 + Math.exp(-undampedFreq * duration) * ((undampedFreq - velocity) * duration + 1);
920
+ };
921
+ derivative = (undampedFreq) => {
922
+ return Math.exp(-undampedFreq * duration) * ((velocity - undampedFreq) * (duration * duration));
923
+ };
924
+ }
925
+ const initialGuess = 5 / duration;
926
+ const undampedFreq = approximateRoot(envelope, derivative, initialGuess);
927
+ duration = /* @__PURE__ */ secondsToMilliseconds(duration);
928
+ if (isNaN(undampedFreq)) return {
929
+ stiffness: springDefaults.stiffness,
930
+ damping: springDefaults.damping,
931
+ duration
932
+ };
933
+ else {
934
+ const stiffness = Math.pow(undampedFreq, 2) * mass;
935
+ return {
936
+ stiffness,
937
+ damping: dampingRatio * 2 * Math.sqrt(mass * stiffness),
938
+ duration
939
+ };
940
+ }
941
+ }
942
+ var durationKeys = ["duration", "bounce"];
943
+ var physicsKeys = [
944
+ "stiffness",
945
+ "damping",
946
+ "mass"
947
+ ];
948
+ function isSpringType(options, keys) {
949
+ return keys.some((key) => options[key] !== void 0);
950
+ }
951
+ function getSpringOptions(options) {
952
+ let springOptions = {
953
+ velocity: springDefaults.velocity,
954
+ stiffness: springDefaults.stiffness,
955
+ damping: springDefaults.damping,
956
+ mass: springDefaults.mass,
957
+ isResolvedFromDuration: false,
958
+ ...options
959
+ };
960
+ if (!isSpringType(options, physicsKeys) && isSpringType(options, durationKeys)) {
961
+ springOptions.velocity = 0;
962
+ if (options.visualDuration) {
963
+ const visualDuration = options.visualDuration;
964
+ const root = 2 * Math.PI / (visualDuration * 1.2);
965
+ const stiffness = root * root;
966
+ const damping = 2 * clamp(.05, 1, 1 - (options.bounce || 0)) * Math.sqrt(stiffness);
967
+ springOptions = {
968
+ ...springOptions,
969
+ mass: springDefaults.mass,
970
+ stiffness,
971
+ damping
972
+ };
973
+ } else {
974
+ const derived = findSpring({
975
+ ...options,
976
+ velocity: 0
977
+ });
978
+ springOptions = {
979
+ ...springOptions,
980
+ ...derived,
981
+ mass: springDefaults.mass
982
+ };
983
+ springOptions.isResolvedFromDuration = true;
984
+ }
985
+ }
986
+ return springOptions;
987
+ }
988
+ function spring(optionsOrVisualDuration = springDefaults.visualDuration, bounce = springDefaults.bounce) {
989
+ const options = typeof optionsOrVisualDuration !== "object" ? {
990
+ visualDuration: optionsOrVisualDuration,
991
+ keyframes: [0, 1],
992
+ bounce
993
+ } : optionsOrVisualDuration;
994
+ let { restSpeed, restDelta } = options;
995
+ const origin = options.keyframes[0];
996
+ const target = options.keyframes[options.keyframes.length - 1];
997
+ /**
998
+ * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
999
+ * to reduce GC during animation.
1000
+ */
1001
+ const state = {
1002
+ done: false,
1003
+ value: origin
1004
+ };
1005
+ const { stiffness, damping, mass, duration, velocity, isResolvedFromDuration } = getSpringOptions({
1006
+ ...options,
1007
+ velocity: -/* @__PURE__ */ millisecondsToSeconds(options.velocity || 0)
1008
+ });
1009
+ const initialVelocity = velocity || 0;
1010
+ const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
1011
+ const initialDelta = target - origin;
1012
+ const undampedAngularFreq = /* @__PURE__ */ millisecondsToSeconds(Math.sqrt(stiffness / mass));
1013
+ /**
1014
+ * If we're working on a granular scale, use smaller defaults for determining
1015
+ * when the spring is finished.
1016
+ *
1017
+ * These defaults have been selected emprically based on what strikes a good
1018
+ * ratio between feeling good and finishing as soon as changes are imperceptible.
1019
+ */
1020
+ const isGranularScale = Math.abs(initialDelta) < 5;
1021
+ restSpeed || (restSpeed = isGranularScale ? springDefaults.restSpeed.granular : springDefaults.restSpeed.default);
1022
+ restDelta || (restDelta = isGranularScale ? springDefaults.restDelta.granular : springDefaults.restDelta.default);
1023
+ let resolveSpring;
1024
+ let resolveVelocity;
1025
+ let angularFreq;
1026
+ let A;
1027
+ let sinCoeff;
1028
+ let cosCoeff;
1029
+ if (dampingRatio < 1) {
1030
+ angularFreq = calcAngularFreq(undampedAngularFreq, dampingRatio);
1031
+ A = (initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) / angularFreq;
1032
+ resolveSpring = (t) => {
1033
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
1034
+ return target - envelope * (A * Math.sin(angularFreq * t) + initialDelta * Math.cos(angularFreq * t));
1035
+ };
1036
+ sinCoeff = dampingRatio * undampedAngularFreq * A + initialDelta * angularFreq;
1037
+ cosCoeff = dampingRatio * undampedAngularFreq * initialDelta - A * angularFreq;
1038
+ resolveVelocity = (t) => {
1039
+ return Math.exp(-dampingRatio * undampedAngularFreq * t) * (sinCoeff * Math.sin(angularFreq * t) + cosCoeff * Math.cos(angularFreq * t));
1040
+ };
1041
+ } else if (dampingRatio === 1) {
1042
+ resolveSpring = (t) => target - Math.exp(-undampedAngularFreq * t) * (initialDelta + (initialVelocity + undampedAngularFreq * initialDelta) * t);
1043
+ const C = initialVelocity + undampedAngularFreq * initialDelta;
1044
+ resolveVelocity = (t) => Math.exp(-undampedAngularFreq * t) * (undampedAngularFreq * C * t - initialVelocity);
1045
+ } else {
1046
+ const dampedAngularFreq = undampedAngularFreq * Math.sqrt(dampingRatio * dampingRatio - 1);
1047
+ resolveSpring = (t) => {
1048
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
1049
+ const freqForT = Math.min(dampedAngularFreq * t, 300);
1050
+ return target - envelope * ((initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) * Math.sinh(freqForT) + dampedAngularFreq * initialDelta * Math.cosh(freqForT)) / dampedAngularFreq;
1051
+ };
1052
+ const P = (initialVelocity + dampingRatio * undampedAngularFreq * initialDelta) / dampedAngularFreq;
1053
+ const sinhCoeff = dampingRatio * undampedAngularFreq * P - initialDelta * dampedAngularFreq;
1054
+ const coshCoeff = dampingRatio * undampedAngularFreq * initialDelta - P * dampedAngularFreq;
1055
+ resolveVelocity = (t) => {
1056
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
1057
+ const freqForT = Math.min(dampedAngularFreq * t, 300);
1058
+ return envelope * (sinhCoeff * Math.sinh(freqForT) + coshCoeff * Math.cosh(freqForT));
1059
+ };
1060
+ }
1061
+ const generator = {
1062
+ calculatedDuration: isResolvedFromDuration ? duration || null : null,
1063
+ velocity: (t) => /* @__PURE__ */ secondsToMilliseconds(resolveVelocity(t)),
1064
+ next: (t) => {
1065
+ /**
1066
+ * For underdamped physics springs we need both position and
1067
+ * velocity each tick. Compute shared trig values once to avoid
1068
+ * duplicate Math.exp/sin/cos calls on the hot path.
1069
+ */
1070
+ if (!isResolvedFromDuration && dampingRatio < 1) {
1071
+ const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
1072
+ const sin = Math.sin(angularFreq * t);
1073
+ const cos = Math.cos(angularFreq * t);
1074
+ const current = target - envelope * (A * sin + initialDelta * cos);
1075
+ const currentVelocity = /* @__PURE__ */ secondsToMilliseconds(envelope * (sinCoeff * sin + cosCoeff * cos));
1076
+ state.done = Math.abs(currentVelocity) <= restSpeed && Math.abs(target - current) <= restDelta;
1077
+ state.value = state.done ? target : current;
1078
+ return state;
1079
+ }
1080
+ const current = resolveSpring(t);
1081
+ if (!isResolvedFromDuration) {
1082
+ const currentVelocity = /* @__PURE__ */ secondsToMilliseconds(resolveVelocity(t));
1083
+ state.done = Math.abs(currentVelocity) <= restSpeed && Math.abs(target - current) <= restDelta;
1084
+ } else state.done = t >= duration;
1085
+ state.value = state.done ? target : current;
1086
+ return state;
1087
+ },
1088
+ toString: () => {
1089
+ const calculatedDuration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
1090
+ const easing = generateLinearEasing((progress) => generator.next(calculatedDuration * progress).value, calculatedDuration, 30);
1091
+ return calculatedDuration + "ms " + easing;
1092
+ },
1093
+ toTransition: () => {}
1094
+ };
1095
+ return generator;
1096
+ }
1097
+ spring.applyToOptions = (options) => {
1098
+ const generatorOptions = createGeneratorEasing(options, 100, spring);
1099
+ options.ease = generatorOptions.ease;
1100
+ options.duration = /* @__PURE__ */ secondsToMilliseconds(generatorOptions.duration);
1101
+ options.type = "keyframes";
1102
+ return options;
1103
+ };
1104
+ //#endregion
1105
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/utils/interpolate.mjs
1106
+ function createMixers(output, ease, customMixer) {
1107
+ const mixers = [];
1108
+ const mixerFactory = customMixer || MotionGlobalConfig.mix || mix;
1109
+ const numMixers = output.length - 1;
1110
+ for (let i = 0; i < numMixers; i++) {
1111
+ let mixer = mixerFactory(output[i], output[i + 1]);
1112
+ if (ease) mixer = pipe(Array.isArray(ease) ? ease[i] || noop : ease, mixer);
1113
+ mixers.push(mixer);
1114
+ }
1115
+ return mixers;
1116
+ }
1117
+ /**
1118
+ * Create a function that maps from a numerical input array to a generic output array.
1119
+ *
1120
+ * Accepts:
1121
+ * - Numbers
1122
+ * - Colors (hex, hsl, hsla, rgb, rgba)
1123
+ * - Complex (combinations of one or more numbers or strings)
1124
+ *
1125
+ * ```jsx
1126
+ * const mixColor = interpolate([0, 1], ['#fff', '#000'])
1127
+ *
1128
+ * mixColor(0.5) // 'rgba(128, 128, 128, 1)'
1129
+ * ```
1130
+ *
1131
+ * TODO Revisit this approach once we've moved to data models for values,
1132
+ * probably not needed to pregenerate mixer functions.
1133
+ *
1134
+ * @public
1135
+ */
1136
+ function interpolate(input, output, { clamp: isClamp = true, ease, mixer } = {}) {
1137
+ const inputLength = input.length;
1138
+ invariant(inputLength === output.length, "Both input and output ranges must be the same length", "range-length");
1139
+ /**
1140
+ * If we're only provided a single input, we can just make a function
1141
+ * that returns the output.
1142
+ */
1143
+ if (inputLength === 1) return () => output[0];
1144
+ if (inputLength === 2 && output[0] === output[1]) return () => output[1];
1145
+ const isZeroDeltaRange = input[0] === input[1];
1146
+ if (input[0] > input[inputLength - 1]) {
1147
+ input = [...input].reverse();
1148
+ output = [...output].reverse();
1149
+ }
1150
+ const mixers = createMixers(output, ease, mixer);
1151
+ const numMixers = mixers.length;
1152
+ const interpolator = (v) => {
1153
+ if (isZeroDeltaRange && v < input[0]) return output[0];
1154
+ let i = 0;
1155
+ if (numMixers > 1) {
1156
+ for (; i < input.length - 2; i++) if (v < input[i + 1]) break;
1157
+ }
1158
+ const progressInRange = /* @__PURE__ */ progress(input[i], input[i + 1], v);
1159
+ return mixers[i](progressInRange);
1160
+ };
1161
+ return isClamp ? (v) => interpolator(clamp(input[0], input[inputLength - 1], v)) : interpolator;
1162
+ }
1163
+ //#endregion
1164
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/keyframes/offsets/fill.mjs
1165
+ function fillOffset(offset, remaining) {
1166
+ const min = offset[offset.length - 1];
1167
+ for (let i = 1; i <= remaining; i++) {
1168
+ const offsetProgress = /* @__PURE__ */ progress(0, remaining, i);
1169
+ offset.push(mixNumber$1(min, 1, offsetProgress));
1170
+ }
1171
+ }
1172
+ //#endregion
1173
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/keyframes/offsets/default.mjs
1174
+ function defaultOffset(arr) {
1175
+ const offset = [0];
1176
+ fillOffset(offset, arr.length - 1);
1177
+ return offset;
1178
+ }
1179
+ //#endregion
1180
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/keyframes/offsets/time.mjs
1181
+ function convertOffsetToTimes(offset, duration) {
1182
+ return offset.map((o) => o * duration);
1183
+ }
1184
+ //#endregion
1185
+ //#region ../../node_modules/.pnpm/motion-dom@12.42.2/node_modules/motion-dom/dist/es/animation/generators/keyframes.mjs
1186
+ function defaultEasing(values, easing) {
1187
+ return values.map(() => easing || easeInOut).splice(0, values.length - 1);
1188
+ }
1189
+ function keyframes({ duration = 300, keyframes: keyframeValues, times, ease = "easeInOut" }) {
1190
+ /**
1191
+ * Easing functions can be externally defined as strings. Here we convert them
1192
+ * into actual functions.
1193
+ */
1194
+ const easingFunctions = /* @__PURE__ */ isEasingArray(ease) ? ease.map(easingDefinitionToFunction) : easingDefinitionToFunction(ease);
1195
+ /**
1196
+ * This is the Iterator-spec return value. We ensure it's mutable rather than using a generator
1197
+ * to reduce GC during animation.
1198
+ */
1199
+ const state = {
1200
+ done: false,
1201
+ value: keyframeValues[0]
1202
+ };
1203
+ const mapTimeToKeyframe = interpolate(convertOffsetToTimes(times && times.length === keyframeValues.length ? times : defaultOffset(keyframeValues), duration), keyframeValues, { ease: Array.isArray(easingFunctions) ? easingFunctions : defaultEasing(keyframeValues, easingFunctions) });
1204
+ return {
1205
+ calculatedDuration: duration,
1206
+ next: (t) => {
1207
+ state.value = mapTimeToKeyframe(t);
1208
+ state.done = t >= duration;
1209
+ return state;
1210
+ }
1211
+ };
1212
+ }
1213
+ //#endregion
1214
+ //#region src/engine.ts
1215
+ function validateTransition(t) {
1216
+ if (t.type === "spring" && (t.duration !== void 0 || t.ease !== void 0)) throw new Error("motion: physical springs do not accept duration or ease");
1217
+ const allowed = [
1218
+ "type",
1219
+ "duration",
1220
+ "delay",
1221
+ "ease",
1222
+ "stiffness",
1223
+ "damping",
1224
+ "mass",
1225
+ "velocity",
1226
+ "restSpeed",
1227
+ "restDelta"
1228
+ ];
1229
+ for (const key of Object.keys(t)) if (!allowed.includes(key)) throw new Error(`motion: unsupported transition ${key}`);
1230
+ if (t.type !== void 0 && t.type !== "tween" && t.type !== "spring") throw new Error("motion: unsupported transition type");
1231
+ for (const key of [
1232
+ "duration",
1233
+ "delay",
1234
+ "stiffness",
1235
+ "damping",
1236
+ "mass",
1237
+ "velocity",
1238
+ "restSpeed",
1239
+ "restDelta"
1240
+ ]) {
1241
+ const value = t[key];
1242
+ if (value !== void 0 && (!Number.isFinite(value) || key !== "velocity" && value < 0)) throw new Error(`motion: invalid ${key}`);
1243
+ }
1244
+ for (const key of [
1245
+ "mass",
1246
+ "stiffness",
1247
+ "damping",
1248
+ "restSpeed",
1249
+ "restDelta"
1250
+ ]) if (t[key] === 0) throw new Error(`motion: ${key} must be positive`);
1251
+ if (t.ease !== void 0) {
1252
+ if (Array.isArray(t.ease)) {
1253
+ if (t.ease.length !== 4 || !t.ease.every(Number.isFinite) || t.ease[0] < 0 || t.ease[0] > 1 || t.ease[2] < 0 || t.ease[2] > 1) throw new Error("motion: invalid cubic Bezier");
1254
+ } else if (![
1255
+ "linear",
1256
+ "easeIn",
1257
+ "easeOut",
1258
+ "easeInOut"
1259
+ ].includes(t.ease)) throw new Error("motion: unsupported easing");
1260
+ }
1261
+ }
1262
+ function runAnimation(clock, from, to, transition, update, complete) {
1263
+ validateTransition(transition);
1264
+ let frame = 0;
1265
+ let settled = false;
1266
+ let resolve;
1267
+ const finished = new Promise((done) => {
1268
+ resolve = done;
1269
+ });
1270
+ const settle = (result) => {
1271
+ if (settled) return;
1272
+ settled = true;
1273
+ clock.cancel(frame);
1274
+ resolve(result);
1275
+ if (result === "finished") complete?.();
1276
+ };
1277
+ const duration = transition.duration ?? .3;
1278
+ const generator = transition.type === "spring" ? spring({
1279
+ keyframes: [from, to],
1280
+ stiffness: transition.stiffness ?? 100,
1281
+ damping: transition.damping ?? 10,
1282
+ mass: transition.mass ?? 1,
1283
+ velocity: transition.velocity ?? 0,
1284
+ restSpeed: transition.restSpeed,
1285
+ restDelta: transition.restDelta
1286
+ }) : keyframes({
1287
+ keyframes: [from, to],
1288
+ duration: duration * 1e3,
1289
+ ease: transition.ease ?? "easeInOut"
1290
+ });
1291
+ const start = clock.now() + (transition.delay ?? 0) * 1e3;
1292
+ const tick = () => {
1293
+ if (settled) return;
1294
+ const elapsed = Math.max(0, clock.now() - start);
1295
+ if (clock.now() >= start) {
1296
+ const state = generator.next(elapsed);
1297
+ update(state.done ? to : state.value);
1298
+ if (state.done) {
1299
+ settle("finished");
1300
+ return;
1301
+ }
1302
+ }
1303
+ if (!settled) frame = clock.request(tick);
1304
+ };
1305
+ if (transition.type !== "spring" && duration === 0 && !transition.delay) {
1306
+ update(to);
1307
+ settle("finished");
1308
+ } else frame = clock.request(tick);
1309
+ return {
1310
+ finished,
1311
+ stop: (reason = "cancelled") => settle(reason)
1312
+ };
1313
+ }
1314
+ //#endregion
1315
+ //#region src/value.ts
1316
+ /** Numeric value with direct subscriptions; it does not subscribe Octane renders. */
1317
+ var MotionValue = class {
1318
+ clock;
1319
+ current;
1320
+ previous;
1321
+ velocity = 0;
1322
+ updated;
1323
+ controls;
1324
+ generation = 0;
1325
+ listeners = /* @__PURE__ */ new Map();
1326
+ passive;
1327
+ disposed = false;
1328
+ constructor(initial, clock) {
1329
+ this.clock = clock;
1330
+ this.assert(initial);
1331
+ this.current = this.previous = initial;
1332
+ this.updated = clock.now();
1333
+ }
1334
+ assert(value) {
1335
+ if (!Number.isFinite(value)) throw new Error("motion: values must be finite numbers");
1336
+ }
1337
+ /** Read the current sample. */
1338
+ get() {
1339
+ return this.current;
1340
+ }
1341
+ /** Read the previous sample. */
1342
+ getPrevious() {
1343
+ return this.previous;
1344
+ }
1345
+ /** Velocity in units per second; stale samples have zero velocity. */
1346
+ getVelocity() {
1347
+ return this.clock.now() - this.updated > 30 ? 0 : this.velocity;
1348
+ }
1349
+ /** Set immediately, or animate when this is a useSpring value. */
1350
+ set(value) {
1351
+ this.assert(value);
1352
+ if (this.disposed) return;
1353
+ if (this.passive) this.passive(value);
1354
+ else {
1355
+ this.stop();
1356
+ this.write(value);
1357
+ }
1358
+ }
1359
+ /** Snap and stop current playback, resetting velocity. */
1360
+ jump(value) {
1361
+ this.assert(value);
1362
+ this.stop();
1363
+ this.write(value);
1364
+ this.velocity = 0;
1365
+ }
1366
+ /** Subscribe without causing a component render. Returns an unsubscribe function. */
1367
+ on(event, callback) {
1368
+ let listeners = this.listeners.get(event);
1369
+ if (!listeners) this.listeners.set(event, listeners = /* @__PURE__ */ new Set());
1370
+ listeners.add(callback);
1371
+ return () => {
1372
+ listeners.delete(callback);
1373
+ };
1374
+ }
1375
+ emit(event, value) {
1376
+ for (const callback of [...this.listeners.get(event) ?? []]) callback(value);
1377
+ }
1378
+ write(value) {
1379
+ if (this.disposed) return;
1380
+ const now = this.clock.now();
1381
+ const elapsed = now - this.updated;
1382
+ if (elapsed > 0) this.velocity = elapsed > 30 ? 0 : (value - this.current) * 1e3 / elapsed;
1383
+ this.previous = this.current;
1384
+ this.current = value;
1385
+ this.updated = now;
1386
+ if (value !== this.previous) this.emit("change", value);
1387
+ }
1388
+ /** Animate to a destination. New playback replaces old playback. */
1389
+ animate(target, transition = {}) {
1390
+ this.assert(target);
1391
+ validateTransition(transition);
1392
+ if (this.disposed) return {
1393
+ finished: Promise.resolve("cancelled"),
1394
+ stop() {}
1395
+ };
1396
+ const velocity = transition.velocity ?? this.getVelocity();
1397
+ this.stop("replaced");
1398
+ const generation = ++this.generation;
1399
+ this.emit("animationStart");
1400
+ const controls = runAnimation(this.clock, this.current, target, {
1401
+ ...transition,
1402
+ velocity
1403
+ }, (value) => this.write(value));
1404
+ this.controls = controls;
1405
+ controls.finished.then((result) => {
1406
+ if (generation !== this.generation || this.disposed) return;
1407
+ this.controls = void 0;
1408
+ if (result === "finished") this.emit("animationComplete");
1409
+ });
1410
+ return controls;
1411
+ }
1412
+ /** Stop playback at its current value. */
1413
+ stop(reason = "cancelled") {
1414
+ ++this.generation;
1415
+ if (this.controls) {
1416
+ this.controls.stop(reason);
1417
+ this.controls = void 0;
1418
+ this.emit("animationCancel");
1419
+ }
1420
+ }
1421
+ /** Release playback and listeners when the owning component unmounts. */
1422
+ destroy() {
1423
+ this.stop();
1424
+ this.emit("destroy");
1425
+ this.listeners.clear();
1426
+ this.passive = void 0;
1427
+ this.disposed = true;
1428
+ }
1429
+ /** @internal Install the useSpring setter interception. */
1430
+ attach(setter) {
1431
+ this.passive = setter;
1432
+ return () => {
1433
+ this.passive = void 0;
1434
+ this.stop();
1435
+ };
1436
+ }
1437
+ };
1438
+ //#endregion
1439
+ //#region src/controller.ts
1440
+ var keys = [
1441
+ "opacity",
1442
+ "x",
1443
+ "y",
1444
+ "scale",
1445
+ "scaleX",
1446
+ "scaleY",
1447
+ "rotate"
1448
+ ];
1449
+ var defaults = {
1450
+ opacity: 1,
1451
+ x: 0,
1452
+ y: 0,
1453
+ scale: 1,
1454
+ scaleX: 1,
1455
+ scaleY: 1,
1456
+ rotate: 0
1457
+ };
1458
+ function validateTarget(target) {
1459
+ for (const [key, value] of Object.entries(target ?? {})) if (!keys.includes(key) || !Number.isFinite(value)) throw new Error(`motion: unsupported target ${key}; expected a finite numeric motion channel`);
1460
+ }
1461
+ var Controller = class {
1462
+ clock;
1463
+ values = /* @__PURE__ */ new Map();
1464
+ write;
1465
+ generation = 0;
1466
+ constructor(clock) {
1467
+ this.clock = clock;
1468
+ }
1469
+ value(key) {
1470
+ let value = this.values.get(key);
1471
+ if (!value) {
1472
+ value = new MotionValue(defaults[key], this.clock);
1473
+ this.values.set(key, value);
1474
+ value.on("change", () => this.flush());
1475
+ }
1476
+ return value;
1477
+ }
1478
+ attach(write) {
1479
+ this.write = write;
1480
+ this.flush();
1481
+ }
1482
+ snapshot() {
1483
+ return Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()]));
1484
+ }
1485
+ flush() {
1486
+ this.write?.(Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()])));
1487
+ }
1488
+ set(key, next) {
1489
+ this.value(key).jump(next);
1490
+ }
1491
+ seed(target) {
1492
+ validateTarget(target);
1493
+ for (const [key, value] of Object.entries(target)) this.set(key, value);
1494
+ }
1495
+ async animate(target, transition, reduced) {
1496
+ validateTarget(target);
1497
+ const generation = ++this.generation;
1498
+ for (const value of this.values.values()) value.stop("replaced");
1499
+ const jobs = Object.entries(target).map(([key, to]) => {
1500
+ return this.value(key).animate(to, reduced && key !== "opacity" ? { duration: 0 } : transition).finished;
1501
+ });
1502
+ const results = await Promise.all(jobs);
1503
+ if (generation !== this.generation) return "replaced";
1504
+ return results.every((result) => result === "finished") ? "finished" : "cancelled";
1505
+ }
1506
+ stop() {
1507
+ ++this.generation;
1508
+ for (const value of this.values.values()) value.stop();
1509
+ }
1510
+ destroy() {
1511
+ this.stop();
1512
+ for (const value of this.values.values()) value.destroy();
1513
+ this.values.clear();
1514
+ this.write = void 0;
1515
+ }
1516
+ };
1517
+ //#endregion
1518
+ //#region src/components.tsrx
1519
+ var _t$0 = /* @__PURE__ */ template("<!>", 0, 1);
1520
+ var _hs$$1 = /* @__PURE__ */ hookSlots(16);
1521
+ var _h$0$1 = /* @__PURE__ */ Symbol(_hs$$1);
1522
+ var _h$1$1 = /* @__PURE__ */ Symbol(_hs$$1 + 1);
1523
+ var _h$2$1 = /* @__PURE__ */ Symbol(_hs$$1 + 2);
1524
+ var _h$3$1 = /* @__PURE__ */ Symbol(_hs$$1 + 3);
1525
+ var _h$4$1 = /* @__PURE__ */ Symbol(_hs$$1 + 4);
1526
+ var _h$5$1 = /* @__PURE__ */ Symbol(_hs$$1 + 5);
1527
+ var _h$6$1 = /* @__PURE__ */ Symbol(_hs$$1 + 6);
1528
+ var _h$7$1 = /* @__PURE__ */ Symbol(_hs$$1 + 7);
1529
+ var _h$8 = /* @__PURE__ */ Symbol(_hs$$1 + 8);
1530
+ var _h$9 = /* @__PURE__ */ Symbol(_hs$$1 + 9);
1531
+ var _h$10 = /* @__PURE__ */ Symbol(_hs$$1 + 10);
1532
+ var _h$11 = /* @__PURE__ */ Symbol(_hs$$1 + 11);
1533
+ var _h$12 = /* @__PURE__ */ Symbol(_hs$$1 + 12);
1534
+ var _h$13 = /* @__PURE__ */ Symbol(_hs$$1 + 13);
1535
+ var _h$14 = /* @__PURE__ */ Symbol(_hs$$1 + 14);
1536
+ var _h$15 = /* @__PURE__ */ Symbol(_hs$$1 + 15);
1537
+ var __childrenBody = {};
1538
+ var __childrenBody$ = {};
1539
+ var __childrenBody$2 = {};
1540
+ function useMotion(props) {
1541
+ for (const name of [
1542
+ "drag",
1543
+ "layout",
1544
+ "layoutId",
1545
+ "variants",
1546
+ "whileTap",
1547
+ "whileHover",
1548
+ "whileFocus",
1549
+ "whileInView"
1550
+ ]) if (name in props) throw new Error(`motion: ${name} is outside the supported subset`);
1551
+ const presence = useContext(PresenceContext);
1552
+ if (props.exit && !presence) throw new Error("motion: exit requires a mounted Presence boundary");
1553
+ const config = useContext(ConfigContext);
1554
+ const systemReduced = withSlot(_h$0$1, useReducedMotion);
1555
+ const reduced = config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced;
1556
+ const transition = props.transition ?? config.transition ?? {};
1557
+ validateTransition(transition);
1558
+ validateTarget(props.animate);
1559
+ validateTarget(props.exit);
1560
+ if (props.initial !== false) validateTarget(props.initial);
1561
+ const latest = useRef(props, _h$1$1);
1562
+ latest.current = props;
1563
+ const state = useRef(null, _h$2$1);
1564
+ if (!state.current) state.current = {
1565
+ controller: new Controller(clock),
1566
+ initialized: false
1567
+ };
1568
+ const current = state.current;
1569
+ const style = {};
1570
+ const bindings = [];
1571
+ for (const [key, value] of Object.entries(props.style ?? {})) if (keys.includes(key)) {
1572
+ if (!(value instanceof MotionValue) && (typeof value !== "number" || !Number.isFinite(value))) throw new Error(`motion: invalid style ${key}`);
1573
+ if (value instanceof MotionValue && (props.animate?.[key] !== void 0 || props.exit?.[key] !== void 0 || props.initial && props.initial[key] !== void 0)) throw new Error(`motion: ${key} has both an animate target and a MotionValue writer`);
1574
+ bindings.push([key, value]);
1575
+ } else {
1576
+ if (value instanceof MotionValue || [
1577
+ "transform",
1578
+ "translateX",
1579
+ "translateY",
1580
+ "animation",
1581
+ "transition"
1582
+ ].includes(key)) throw new Error(`motion: unsupported or conflicting style ${key}`);
1583
+ style[key] = value;
1584
+ }
1585
+ const previous = useRef(bindings, _h$3$1);
1586
+ const boundKeys = useRef([], _h$4$1);
1587
+ const firstBinding = useRef(true, _h$5$1);
1588
+ const firstAnimation = useRef(true, _h$6$1);
1589
+ if (previous.current.length !== bindings.length || previous.current.some(([key, value], i) => key !== bindings[i][0] || value !== bindings[i][1])) previous.current = bindings;
1590
+ const bind = useRef(() => {}, _h$7$1);
1591
+ bind.current = (host) => {
1592
+ if (!host) return;
1593
+ if (current.host !== host) {
1594
+ current.adapter?.restore();
1595
+ current.host = host;
1596
+ current.adapter = attachHost(host);
1597
+ if (!current.initialized) {
1598
+ const baseline = current.adapter.read();
1599
+ for (const [key, value] of previous.current) baseline[key] = value instanceof MotionValue ? value.get() : value;
1600
+ current.controller.seed(baseline);
1601
+ current.controller.seed(props.initial === false ? props.animate ?? {} : props.initial ?? {});
1602
+ current.initialized = true;
1603
+ }
1604
+ current.controller.attach(current.adapter.write);
1605
+ }
1606
+ current.controller.flush();
1607
+ latest.current.bind?.(host);
1608
+ };
1609
+ const playback = useRef({
1610
+ transition,
1611
+ reduced
1612
+ }, _h$8);
1613
+ playback.current = {
1614
+ transition,
1615
+ reduced
1616
+ };
1617
+ const returning = useRef(null, _h$9);
1618
+ const member = useRef(null, _h$10);
1619
+ if (!member.current) member.current = {
1620
+ exit() {
1621
+ const snapshot = current.controller.snapshot();
1622
+ returning.current ??= {};
1623
+ for (const key of Object.keys(latest.current.exit ?? {})) if (!(key in returning.current)) returning.current[key] = snapshot[key];
1624
+ return current.controller.animate(latest.current.exit ?? {}, playback.current.transition, playback.current.reduced);
1625
+ },
1626
+ enter() {
1627
+ const target = {
1628
+ ...returning.current,
1629
+ ...latest.current.animate
1630
+ };
1631
+ returning.current = null;
1632
+ current.controller.animate(target, playback.current.transition, playback.current.reduced).then((result) => {
1633
+ if (result === "finished" && current.host && presence?.present) latest.current.onAnimationComplete?.();
1634
+ });
1635
+ }
1636
+ };
1637
+ useLayoutEffect(() => presence?.register(member.current), [presence], _h$11);
1638
+ const stableBind = useRef((host) => bind.current(host), _h$12).current;
1639
+ useLayoutEffect(() => () => {
1640
+ current.controller.destroy();
1641
+ current.host = void 0;
1642
+ current.adapter = void 0;
1643
+ }, [], _h$13);
1644
+ useLayoutEffect(() => {
1645
+ const off = [];
1646
+ for (const key of boundKeys.current) if (!previous.current.some(([next]) => key === next)) current.controller.set(key, defaults[key]);
1647
+ boundKeys.current = previous.current.map(([key]) => key);
1648
+ for (const [key, value] of previous.current) {
1649
+ if (!firstBinding.current) current.controller.set(key, value instanceof MotionValue ? value.get() : value);
1650
+ if (value instanceof MotionValue) off.push(value.on("change", (next) => current.controller.set(key, next)));
1651
+ }
1652
+ firstBinding.current = false;
1653
+ return () => off.forEach((unsubscribe) => unsubscribe());
1654
+ }, [previous.current], _h$14);
1655
+ useLayoutEffect(() => {
1656
+ let active = true;
1657
+ const skip = firstAnimation.current && props.initial === false;
1658
+ firstAnimation.current = false;
1659
+ if (presence && !presence.present) presence.restart(member.current);
1660
+ else if (props.animate && !skip) current.controller.animate(props.animate, transition, reduced).then((result) => {
1661
+ if (active && result === "finished") latest.current.onAnimationComplete?.();
1662
+ });
1663
+ return () => {
1664
+ active = false;
1665
+ current.controller.stop();
1666
+ };
1667
+ }, [
1668
+ JSON.stringify(props.animate),
1669
+ JSON.stringify(props.exit),
1670
+ JSON.stringify(transition),
1671
+ reduced
1672
+ ], _h$15);
1673
+ const { initial, exit, animate, transition: ignoredTransition, onAnimationComplete, style: ignoredStyle, bind: ignoredBind, ...rest } = props;
1674
+ return {
1675
+ ...rest,
1676
+ style,
1677
+ bind: stableBind
1678
+ };
1679
+ }
1680
+ var MotionView = function MotionView(props, __s, __extra) {
1681
+ const __block = __s.block;
1682
+ function __children$1(__props, __s, __extra) {
1683
+ const __block = __s.block;
1684
+ let _b = __s.slots[0];
1685
+ if (_b === void 0) {
1686
+ let _m0, _m1;
1687
+ const _root = clone(_t$0);
1688
+ _m0 = __block.parentNode;
1689
+ _m1 = child(_root);
1690
+ drainFrag(_root, __block.parentNode, __block.endMarker);
1691
+ _b = bag4(__s, null, _m0, _m1, null, void 0);
1692
+ }
1693
+ {
1694
+ const _v = props.children;
1695
+ _b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
1696
+ _b.d = _v;
1697
+ }
1698
+ }
1699
+ componentSlot(__s, 0, __block.parentNode, View, {
1700
+ ...useMotion(props),
1701
+ "children": markChildrenBlock(__children$1, __childrenBody)
1702
+ }, __block.endMarker, void 0, void 0, true, void 0, "c:074db42c");
1703
+ };
1704
+ var MotionRow = function MotionRow(props, __s, __extra) {
1705
+ const __block = __s.block;
1706
+ function __children$4(__props, __s, __extra) {
1707
+ const __block = __s.block;
1708
+ let _b = __s.slots[0];
1709
+ if (_b === void 0) {
1710
+ let _m0, _m1;
1711
+ const _root = clone(_t$0);
1712
+ _m0 = __block.parentNode;
1713
+ _m1 = child(_root);
1714
+ drainFrag(_root, __block.parentNode, __block.endMarker);
1715
+ _b = bag4(__s, null, _m0, _m1, null, void 0);
1716
+ }
1717
+ {
1718
+ const _v = props.children;
1719
+ _b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
1720
+ _b.d = _v;
1721
+ }
1722
+ }
1723
+ componentSlot(__s, 0, __block.parentNode, Row, {
1724
+ ...useMotion(props),
1725
+ "children": markChildrenBlock(__children$4, __childrenBody$)
1726
+ }, __block.endMarker, void 0, void 0, true, void 0, "c:bfd4d1a7");
1727
+ };
1728
+ var MotionPressable = function MotionPressable(props, __s, __extra) {
1729
+ const __block = __s.block;
1730
+ function __children$7(__props, __s, __extra) {
1731
+ const __block = __s.block;
1732
+ let _b = __s.slots[0];
1733
+ if (_b === void 0) {
1734
+ let _m0, _m1;
1735
+ const _root = clone(_t$0);
1736
+ _m0 = __block.parentNode;
1737
+ _m1 = child(_root);
1738
+ drainFrag(_root, __block.parentNode, __block.endMarker);
1739
+ _b = bag4(__s, null, _m0, _m1, null, void 0);
1740
+ }
1741
+ {
1742
+ const _v = props.children;
1743
+ _b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
1744
+ _b.d = _v;
1745
+ }
1746
+ }
1747
+ componentSlot(__s, 0, __block.parentNode, Pressable, {
1748
+ ...useMotion(props),
1749
+ "children": markChildrenBlock(__children$7, __childrenBody$2)
1750
+ }, __block.endMarker, void 0, void 0, true, void 0, "c:55d0b7c5");
1751
+ };
1752
+ //#endregion
1753
+ //#region src/hooks.tsrx
1754
+ var _hs$ = /* @__PURE__ */ hookSlots(8);
1755
+ var _h$0 = /* @__PURE__ */ Symbol(_hs$);
1756
+ var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
1757
+ var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
1758
+ var _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
1759
+ var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
1760
+ var _h$5 = /* @__PURE__ */ Symbol(_hs$ + 5);
1761
+ var _h$6 = /* @__PURE__ */ Symbol(_hs$ + 6);
1762
+ var _h$7 = /* @__PURE__ */ Symbol(_hs$ + 7);
1763
+ function useMotionValue(initial) {
1764
+ const ref = useRef(null, _h$0);
1765
+ if (!ref.current) ref.current = new MotionValue(initial, clock);
1766
+ const value = ref.current;
1767
+ useLayoutEffect(() => () => value.destroy(), [], _h$1);
1768
+ return value;
1769
+ }
1770
+ function useMotionValueEvent(value, event, callback) {
1771
+ useLayoutEffect(() => value.on(event, callback), [
1772
+ value,
1773
+ event,
1774
+ callback
1775
+ ], _h$2);
1776
+ }
1777
+ function useTransform(source, input, output, options) {
1778
+ const sources = Array.isArray(source) ? source : [source];
1779
+ if (Array.isArray(input) && (!output || input.length !== output.length || input.length < 2)) throw new Error("motion: transform ranges must have matching lengths >= 2");
1780
+ const transform = typeof input === "function" ? input : interpolate(input, output, options);
1781
+ const read = () => transform(Array.isArray(source) ? sources.map((value) => value.get()) : source.get());
1782
+ const value = withSlot(_h$3, useMotionValue, read());
1783
+ const previous = useRef(sources, _h$4);
1784
+ if (previous.current.length !== sources.length || previous.current.some((value, i) => value !== sources[i])) previous.current = sources;
1785
+ useLayoutEffect(() => {
1786
+ const update = () => value.set(read());
1787
+ const off = sources.map((source) => source.on("change", update));
1788
+ update();
1789
+ return () => off.forEach((unsubscribe) => unsubscribe());
1790
+ }, [
1791
+ previous.current,
1792
+ input,
1793
+ output,
1794
+ options?.clamp
1795
+ ], _h$5);
1796
+ return value;
1797
+ }
1798
+ function useSpring(source, options = {}) {
1799
+ const value = withSlot(_h$6, useMotionValue, source instanceof MotionValue ? source.get() : source);
1800
+ useLayoutEffect(() => {
1801
+ const follow = (target) => {
1802
+ value.animate(target, {
1803
+ ...options,
1804
+ type: "spring"
1805
+ });
1806
+ };
1807
+ const detach = value.attach(follow);
1808
+ const unsubscribe = source instanceof MotionValue ? source.on("change", follow) : void 0;
1809
+ if (source instanceof MotionValue && source.get() !== value.get()) follow(source.get());
1810
+ return () => {
1811
+ unsubscribe?.();
1812
+ detach();
1813
+ };
1814
+ }, [source instanceof MotionValue ? source : null, JSON.stringify(options)], _h$7);
1815
+ return value;
1816
+ }
1817
+ //#endregion
1818
+ //#region src/index.web.ts
1819
+ /** Bounded motion hosts for shared xplat UI primitives. */
1820
+ var motion = {
1821
+ View: MotionView,
1822
+ Row: MotionRow,
1823
+ Pressable: MotionPressable
1824
+ };
1825
+ //#endregion
1826
+ export { MotionConfig, Presence, motion, useMotionValue, useMotionValueEvent, useReducedMotion, useSpring, useTransform };