@octane-xplat/motion 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -2
- package/UPSTREAM.md +284 -16
- package/dist/native/index.js +980 -112
- package/dist/native/octane-client-build.json +1 -1
- package/dist/web/index.js +1104 -166
- package/dist/web/octane-client-build.json +1 -1
- package/package.json +8 -3
- package/src/clock.ts +13 -1
- package/src/components.mobile.test.tsrx +58 -0
- package/src/components.tsrx +185 -39
- package/src/components.web.test.tsrx +234 -1
- package/src/controller.ts +122 -10
- package/src/delegation.test.ts +269 -0
- package/src/delegation.ts +29 -0
- package/src/delegation.web.test.ts +270 -0
- package/src/drag.mobile.test.ts +81 -0
- package/src/drag.test.ts +167 -0
- package/src/drag.ts +157 -0
- package/src/driver.ts +249 -0
- package/src/driver.web.ts +180 -0
- package/src/engine.test.ts +86 -0
- package/src/engine.ts +137 -15
- package/src/hooks.tsrx +53 -2
- package/src/host-types.ts +44 -1
- package/src/host.ts +39 -2
- package/src/host.web.ts +51 -10
- package/src/index.ts +18 -4
- package/src/index.web.ts +18 -4
- package/src/pan.ts +92 -0
- package/src/pan.web.ts +116 -0
- package/src/presence.tsrx +6 -7
- package/src/reduced-motion.ts +23 -4
- package/src/types.ts +99 -10
- package/src/value.ts +15 -5
- package/src/variants.test.ts +197 -0
- package/src/variants.ts +226 -0
- package/types/engine.d.ts +7 -1
- package/types/index.d.ts +22 -1
- package/types/types.d.ts +93 -10
- package/types/value.d.ts +4 -1
package/dist/web/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { __createCompiledContext, textHoleUpdate } from "octane/internal/client";
|
|
2
|
+
import { bag4, child, clone, componentSlot, componentSlotVoid, createContext, drainFrag, hookSlots, ifBlock, markChildrenBlock, template, useContext, useEffect, useLayoutEffect, useRef, useState, withSlot } from "octane";
|
|
3
|
+
import { HStack, Pressable, View } from "@octane-xplat/ui";
|
|
4
4
|
//#region src/reduced-motion.web.ts
|
|
5
5
|
function readReducedMotion() {
|
|
6
6
|
return typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
@@ -17,7 +17,7 @@ var _t$0$2 = /* @__PURE__ */ template("<!>", 0, 1);
|
|
|
17
17
|
var _hs$$3 = /* @__PURE__ */ hookSlots(2);
|
|
18
18
|
var _h$0$2 = /* @__PURE__ */ Symbol(_hs$$3);
|
|
19
19
|
var _h$1$2 = /* @__PURE__ */ Symbol(_hs$$3 + 1);
|
|
20
|
-
var __childrenBody$
|
|
20
|
+
var __childrenBody$8 = {};
|
|
21
21
|
var ConfigContext = /* @__PURE__ */ createContext({ reducedMotion: "never" });
|
|
22
22
|
function useReducedMotion() {
|
|
23
23
|
const [reduced, setReduced] = useState(readReducedMotion, _h$0$2);
|
|
@@ -55,7 +55,7 @@ var MotionConfig = function MotionConfig(props, __s, __extra) {
|
|
|
55
55
|
}
|
|
56
56
|
componentSlot(__s, 0, __block.parentNode, ConfigContext, {
|
|
57
57
|
"value": value,
|
|
58
|
-
"children": markChildrenBlock(__children$1, __childrenBody$
|
|
58
|
+
"children": markChildrenBlock(__children$1, __childrenBody$8)
|
|
59
59
|
}, __block.endMarker, void 0, void 0, true, void 0, "c:1bf28fec");
|
|
60
60
|
};
|
|
61
61
|
//#endregion
|
|
@@ -147,9 +147,9 @@ var __childrenBody$1 = {};
|
|
|
147
147
|
var __childrenBody$$1 = {};
|
|
148
148
|
function __then$0(__props, __s, __extra) {
|
|
149
149
|
const __block = __s.block;
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
const
|
|
150
|
+
const children = __extra[0];
|
|
151
|
+
const host = __extra[1];
|
|
152
|
+
const ref = __extra[2];
|
|
153
153
|
const restoreInput = __extra[3];
|
|
154
154
|
const state = __extra[4];
|
|
155
155
|
const syncInput = __extra[5];
|
|
@@ -176,19 +176,18 @@ function __then$0(__props, __s, __extra) {
|
|
|
176
176
|
componentSlot(__s, 0, __block.parentNode, PresenceContext, {
|
|
177
177
|
"value": state,
|
|
178
178
|
"children": markChildrenBlock(__children$4, __childrenBody$1)
|
|
179
|
-
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:
|
|
179
|
+
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:f1bd5f1c");
|
|
180
180
|
}
|
|
181
181
|
componentSlot(__s, 0, __block.parentNode, View, {
|
|
182
182
|
...viewProps,
|
|
183
|
-
"
|
|
183
|
+
"ref": [(node) => {
|
|
184
184
|
if (host.current !== node) {
|
|
185
185
|
restoreInput.current?.();
|
|
186
186
|
restoreInput.current = null;
|
|
187
187
|
host.current = node;
|
|
188
188
|
}
|
|
189
189
|
syncInput();
|
|
190
|
-
|
|
191
|
-
},
|
|
190
|
+
}, ref],
|
|
192
191
|
"children": markChildrenBlock(__children$2, __childrenBody$$1)
|
|
193
192
|
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:cf4c2460");
|
|
194
193
|
}
|
|
@@ -198,12 +197,12 @@ var Presence = function Presence(props, __s, __extra) {
|
|
|
198
197
|
const [retained, setRetained] = useState(props.present, _hs$$2 + 0);
|
|
199
198
|
const latest = useRef(props, _hs$$2 + 1);
|
|
200
199
|
latest.current = props;
|
|
201
|
-
const
|
|
202
|
-
if (!
|
|
200
|
+
const stateRef = useRef(null, _hs$$2 + 2);
|
|
201
|
+
if (!stateRef.current) stateRef.current = new PresenceState(props.present, () => {
|
|
203
202
|
setRetained(false);
|
|
204
203
|
latest.current.onExitComplete?.();
|
|
205
204
|
});
|
|
206
|
-
const state =
|
|
205
|
+
const state = stateRef.current;
|
|
207
206
|
const host = useRef(null, _hs$$2 + 3);
|
|
208
207
|
const restoreInput = useRef(null, _hs$$2 + 4);
|
|
209
208
|
const syncInput = () => {
|
|
@@ -224,14 +223,14 @@ var Presence = function Presence(props, __s, __extra) {
|
|
|
224
223
|
restoreInput.current = null;
|
|
225
224
|
host.current = null;
|
|
226
225
|
}, [], _hs$$2 + 6);
|
|
227
|
-
const { present, onExitComplete, children,
|
|
226
|
+
const { present, onExitComplete, children, ref, ...viewProps } = props;
|
|
228
227
|
if (__s.block.pending && !__s.block.crossRenderUpdate) return;
|
|
229
228
|
{
|
|
230
229
|
const __ifCondition = props.present || retained;
|
|
231
230
|
ifBlock(__s, 0, __block.parentNode, __ifCondition, __then$0, null, __block.endMarker, __ifCondition ? [
|
|
232
|
-
bind,
|
|
233
231
|
children,
|
|
234
232
|
host,
|
|
233
|
+
ref,
|
|
235
234
|
restoreInput,
|
|
236
235
|
state,
|
|
237
236
|
syncInput,
|
|
@@ -240,6 +239,100 @@ var Presence = function Presence(props, __s, __extra) {
|
|
|
240
239
|
}
|
|
241
240
|
};
|
|
242
241
|
//#endregion
|
|
242
|
+
//#region src/drag.ts
|
|
243
|
+
function validateDrag(props) {
|
|
244
|
+
if (props.drag !== void 0 && ![
|
|
245
|
+
true,
|
|
246
|
+
false,
|
|
247
|
+
"x",
|
|
248
|
+
"y"
|
|
249
|
+
].includes(props.drag)) throw new Error("motion: drag must be boolean, x, or y");
|
|
250
|
+
const bounds = props.dragConstraints ?? {};
|
|
251
|
+
for (const [key, value] of Object.entries(bounds)) if (![
|
|
252
|
+
"left",
|
|
253
|
+
"right",
|
|
254
|
+
"top",
|
|
255
|
+
"bottom"
|
|
256
|
+
].includes(key) || !Number.isFinite(value)) throw new Error("motion: dragConstraints requires finite numeric edges; refs are deferred");
|
|
257
|
+
if ((bounds.left ?? -Infinity) > (bounds.right ?? Infinity) || (bounds.top ?? -Infinity) > (bounds.bottom ?? Infinity)) throw new Error("motion: dragConstraints edges are reversed");
|
|
258
|
+
if (typeof props.dragElastic !== "boolean" && props.dragElastic !== void 0 && (!Number.isFinite(props.dragElastic) || props.dragElastic < 0 || props.dragElastic > 1)) throw new Error("motion: dragElastic must be boolean or a number from 0 to 1");
|
|
259
|
+
if (props.drag) for (const axis of ["x", "y"]) {
|
|
260
|
+
if (props.drag !== true && props.drag !== axis) continue;
|
|
261
|
+
for (const target of [
|
|
262
|
+
props.animate,
|
|
263
|
+
props.whileTap,
|
|
264
|
+
props.whileFocus
|
|
265
|
+
]) if (target && typeof target === "object" && !Array.isArray(target) && target[axis] !== void 0) throw new Error(`motion: drag and animation both own ${axis}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
var clamp$1 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
269
|
+
/** Gesture writes and release springs bypass host delegation. */
|
|
270
|
+
function attachDrag(adapter, controller, props, valueFor, reduced, callbacks) {
|
|
271
|
+
if (!props.drag) return () => {};
|
|
272
|
+
if (!adapter.pan) throw new Error("motion: this host does not support drag");
|
|
273
|
+
const axes = ["x", "y"].filter((axis) => props.drag === true || props.drag === axis);
|
|
274
|
+
const values = new Map(axes.map((axis) => [axis, valueFor(axis)]));
|
|
275
|
+
const value = (axis) => values.get(axis);
|
|
276
|
+
const bounds = props.dragConstraints ?? {};
|
|
277
|
+
const elastic = typeof props.dragElastic === "number" ? props.dragElastic : props.dragElastic === false ? 0 : .35;
|
|
278
|
+
const origin = {
|
|
279
|
+
x: 0,
|
|
280
|
+
y: 0
|
|
281
|
+
};
|
|
282
|
+
let active = false;
|
|
283
|
+
const limits = (axis) => axis === "x" ? [bounds.left ?? -Infinity, bounds.right ?? Infinity] : [bounds.top ?? -Infinity, bounds.bottom ?? Infinity];
|
|
284
|
+
const move = (info) => {
|
|
285
|
+
for (const axis of axes) {
|
|
286
|
+
const [min, max] = limits(axis);
|
|
287
|
+
const next = origin[axis] + info.offset[axis];
|
|
288
|
+
const bounded = clamp$1(next, min, max);
|
|
289
|
+
value(axis).jump(bounded + (next - bounded) * elastic);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
const off = adapter.pan(props.drag, {
|
|
293
|
+
start(event, info) {
|
|
294
|
+
controller.stop();
|
|
295
|
+
active = true;
|
|
296
|
+
for (const axis of axes) {
|
|
297
|
+
const channel = value(axis);
|
|
298
|
+
channel.stop();
|
|
299
|
+
origin[axis] = channel.get();
|
|
300
|
+
}
|
|
301
|
+
callbacks().onDragStart?.(event, info);
|
|
302
|
+
},
|
|
303
|
+
move(event, info) {
|
|
304
|
+
if (!active) return;
|
|
305
|
+
move(info);
|
|
306
|
+
callbacks().onDrag?.(event, info);
|
|
307
|
+
},
|
|
308
|
+
end(event, info) {
|
|
309
|
+
if (!active) return;
|
|
310
|
+
active = false;
|
|
311
|
+
move(info);
|
|
312
|
+
for (const axis of axes) {
|
|
313
|
+
const channel = value(axis);
|
|
314
|
+
const velocity = info.cancelled || props.dragMomentum === false ? 0 : info.velocity[axis];
|
|
315
|
+
const [min, max] = limits(axis);
|
|
316
|
+
const target = clamp$1(channel.get() + velocity * .2, min, max);
|
|
317
|
+
if (elastic === 0) channel.jump(clamp$1(channel.get(), min, max));
|
|
318
|
+
if (reduced()) channel.jump(target);
|
|
319
|
+
else if (target !== channel.get() || velocity !== 0) channel.animate(target, {
|
|
320
|
+
type: "spring",
|
|
321
|
+
stiffness: 200,
|
|
322
|
+
damping: 30,
|
|
323
|
+
velocity
|
|
324
|
+
}, elastic === 0 ? (next) => clamp$1(next, min, max) : void 0);
|
|
325
|
+
}
|
|
326
|
+
callbacks().onDragEnd?.(event, info);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
return () => {
|
|
330
|
+
active = false;
|
|
331
|
+
off();
|
|
332
|
+
for (const channel of values.values()) channel.stop();
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
//#endregion
|
|
243
336
|
//#region src/clock.web.ts
|
|
244
337
|
var clock = {
|
|
245
338
|
now: () => performance.now(),
|
|
@@ -247,30 +340,115 @@ var clock = {
|
|
|
247
340
|
cancel: (id) => cancelAnimationFrame(id)
|
|
248
341
|
};
|
|
249
342
|
//#endregion
|
|
250
|
-
//#region src/
|
|
251
|
-
function
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
343
|
+
//#region src/pan.web.ts
|
|
344
|
+
function attachPan(node, axis, callbacks) {
|
|
345
|
+
const touchAction = node.style.touchAction;
|
|
346
|
+
node.style.touchAction = axis === "x" ? "pan-y" : axis === "y" ? "pan-x" : "none";
|
|
347
|
+
let pointer;
|
|
348
|
+
let active = false;
|
|
349
|
+
let start = {
|
|
350
|
+
x: 0,
|
|
351
|
+
y: 0
|
|
352
|
+
};
|
|
353
|
+
let last = start;
|
|
354
|
+
let time = 0;
|
|
355
|
+
let velocity = {
|
|
356
|
+
x: 0,
|
|
357
|
+
y: 0
|
|
358
|
+
};
|
|
359
|
+
let velocityTime = 0;
|
|
360
|
+
const sample = (event, cancelled = false) => {
|
|
361
|
+
const point = cancelled ? last : {
|
|
362
|
+
x: event.clientX,
|
|
363
|
+
y: event.clientY
|
|
364
|
+
};
|
|
365
|
+
const delta = {
|
|
366
|
+
x: point.x - last.x,
|
|
367
|
+
y: point.y - last.y
|
|
368
|
+
};
|
|
369
|
+
const elapsed = event.timeStamp - time;
|
|
370
|
+
if (elapsed > 0 && (delta.x || delta.y)) {
|
|
371
|
+
velocity = {
|
|
372
|
+
x: delta.x * 1e3 / elapsed,
|
|
373
|
+
y: delta.y * 1e3 / elapsed
|
|
374
|
+
};
|
|
375
|
+
velocityTime = event.timeStamp;
|
|
376
|
+
} else if (event.timeStamp - velocityTime > 100) velocity = {
|
|
259
377
|
x: 0,
|
|
260
|
-
y: 0
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
378
|
+
y: 0
|
|
379
|
+
};
|
|
380
|
+
last = point;
|
|
381
|
+
time = event.timeStamp;
|
|
382
|
+
return {
|
|
383
|
+
point,
|
|
384
|
+
delta,
|
|
385
|
+
offset: {
|
|
386
|
+
x: point.x - start.x,
|
|
387
|
+
y: point.y - start.y
|
|
388
|
+
},
|
|
389
|
+
velocity,
|
|
390
|
+
cancelled
|
|
391
|
+
};
|
|
392
|
+
};
|
|
393
|
+
const down = (event) => {
|
|
394
|
+
if (pointer !== void 0 || event.button !== 0 || event.isPrimary === false) return;
|
|
395
|
+
pointer = event.pointerId;
|
|
396
|
+
start = last = {
|
|
397
|
+
x: event.clientX,
|
|
398
|
+
y: event.clientY
|
|
399
|
+
};
|
|
400
|
+
time = velocityTime = event.timeStamp;
|
|
401
|
+
velocity = {
|
|
402
|
+
x: 0,
|
|
403
|
+
y: 0
|
|
404
|
+
};
|
|
405
|
+
try {
|
|
406
|
+
node.setPointerCapture?.(event.pointerId);
|
|
407
|
+
} catch (error) {
|
|
408
|
+
if (event.isTrusted || error.name !== "NotFoundError") throw error;
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
const move = (event) => {
|
|
412
|
+
if (event.pointerId !== pointer) return;
|
|
413
|
+
const info = sample(event);
|
|
414
|
+
if (!active) {
|
|
415
|
+
const primary = axis === "y" ? info.offset.y : info.offset.x;
|
|
416
|
+
const other = axis === "y" ? info.offset.x : info.offset.y;
|
|
417
|
+
if (axis !== true && Math.abs(other) > 8 && Math.abs(primary) <= 8) {
|
|
418
|
+
finish(event, true);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if ((axis === true ? Math.hypot(info.offset.x, info.offset.y) : Math.abs(primary)) <= 8) return;
|
|
422
|
+
active = true;
|
|
423
|
+
callbacks.start(event, info);
|
|
424
|
+
}
|
|
425
|
+
callbacks.move(event, info);
|
|
426
|
+
};
|
|
427
|
+
const finish = (event, cancelled) => {
|
|
428
|
+
if (pointer === void 0 || event.pointerId !== pointer) return;
|
|
429
|
+
const id = pointer;
|
|
430
|
+
pointer = void 0;
|
|
431
|
+
if (active) {
|
|
432
|
+
active = false;
|
|
433
|
+
callbacks.end(event, sample(event, cancelled));
|
|
273
434
|
}
|
|
435
|
+
if (node.hasPointerCapture?.(id)) node.releasePointerCapture(id);
|
|
436
|
+
};
|
|
437
|
+
const up = (event) => finish(event, false);
|
|
438
|
+
const cancel = (event) => finish(event, true);
|
|
439
|
+
node.addEventListener("pointerdown", down);
|
|
440
|
+
node.addEventListener("pointermove", move);
|
|
441
|
+
node.addEventListener("pointerup", up);
|
|
442
|
+
node.addEventListener("pointercancel", cancel);
|
|
443
|
+
node.addEventListener("lostpointercapture", cancel);
|
|
444
|
+
return () => {
|
|
445
|
+
node.removeEventListener("pointerdown", down);
|
|
446
|
+
node.removeEventListener("pointermove", move);
|
|
447
|
+
node.removeEventListener("pointerup", up);
|
|
448
|
+
node.removeEventListener("pointercancel", cancel);
|
|
449
|
+
node.removeEventListener("lostpointercapture", cancel);
|
|
450
|
+
if (pointer !== void 0 && node.hasPointerCapture?.(pointer)) node.releasePointerCapture(pointer);
|
|
451
|
+
node.style.touchAction = touchAction;
|
|
274
452
|
};
|
|
275
453
|
}
|
|
276
454
|
//#endregion
|
|
@@ -1212,13 +1390,79 @@ function keyframes({ duration = 300, keyframes: keyframeValues, times, ease = "e
|
|
|
1212
1390
|
}
|
|
1213
1391
|
//#endregion
|
|
1214
1392
|
//#region src/engine.ts
|
|
1393
|
+
var MOTION_KEYS = [
|
|
1394
|
+
"opacity",
|
|
1395
|
+
"x",
|
|
1396
|
+
"y",
|
|
1397
|
+
"scale",
|
|
1398
|
+
"scaleX",
|
|
1399
|
+
"scaleY",
|
|
1400
|
+
"rotate"
|
|
1401
|
+
];
|
|
1402
|
+
/** Platform animators take one timing curve per run — cubic-bezier only. */
|
|
1403
|
+
var BEZIER_EASES = /* @__PURE__ */ new Set([
|
|
1404
|
+
"linear",
|
|
1405
|
+
"easeIn",
|
|
1406
|
+
"easeOut",
|
|
1407
|
+
"easeInOut"
|
|
1408
|
+
]);
|
|
1409
|
+
function isBezierEase(ease) {
|
|
1410
|
+
return ease === void 0 || Array.isArray(ease) || BEZIER_EASES.has(ease);
|
|
1411
|
+
}
|
|
1412
|
+
var BEZIER_POINTS = {
|
|
1413
|
+
linear: [
|
|
1414
|
+
0,
|
|
1415
|
+
0,
|
|
1416
|
+
1,
|
|
1417
|
+
1
|
|
1418
|
+
],
|
|
1419
|
+
easeIn: [
|
|
1420
|
+
.42,
|
|
1421
|
+
0,
|
|
1422
|
+
1,
|
|
1423
|
+
1
|
|
1424
|
+
],
|
|
1425
|
+
easeOut: [
|
|
1426
|
+
0,
|
|
1427
|
+
0,
|
|
1428
|
+
.58,
|
|
1429
|
+
1
|
|
1430
|
+
],
|
|
1431
|
+
easeInOut: [
|
|
1432
|
+
.42,
|
|
1433
|
+
0,
|
|
1434
|
+
.58,
|
|
1435
|
+
1
|
|
1436
|
+
]
|
|
1437
|
+
};
|
|
1438
|
+
/** CSS cubic-bezier control points for a delegatable ease; tuples pass through. */
|
|
1439
|
+
function bezierPoints(ease) {
|
|
1440
|
+
return Array.isArray(ease) ? ease : BEZIER_POINTS[ease ?? "easeInOut"];
|
|
1441
|
+
}
|
|
1442
|
+
function isOrchestrated(t) {
|
|
1443
|
+
if (!t || typeof t !== "object") return false;
|
|
1444
|
+
return "default" in t || MOTION_KEYS.some((key) => key in t);
|
|
1445
|
+
}
|
|
1446
|
+
function resolveTransition(t, key) {
|
|
1447
|
+
return isOrchestrated(t) ? {
|
|
1448
|
+
...t.default,
|
|
1449
|
+
...t[key]
|
|
1450
|
+
} : t;
|
|
1451
|
+
}
|
|
1215
1452
|
function validateTransition(t) {
|
|
1216
|
-
if (t.type === "spring" &&
|
|
1453
|
+
if (t.type === "spring" && t.ease !== void 0) throw new Error("motion: physical springs do not accept ease");
|
|
1217
1454
|
const allowed = [
|
|
1455
|
+
"staggerChildren",
|
|
1456
|
+
"delayChildren",
|
|
1457
|
+
"when",
|
|
1218
1458
|
"type",
|
|
1219
1459
|
"duration",
|
|
1220
1460
|
"delay",
|
|
1221
1461
|
"ease",
|
|
1462
|
+
"repeat",
|
|
1463
|
+
"repeatType",
|
|
1464
|
+
"repeatDelay",
|
|
1465
|
+
"bounce",
|
|
1222
1466
|
"stiffness",
|
|
1223
1467
|
"damping",
|
|
1224
1468
|
"mass",
|
|
@@ -1227,10 +1471,15 @@ function validateTransition(t) {
|
|
|
1227
1471
|
"restDelta"
|
|
1228
1472
|
];
|
|
1229
1473
|
for (const key of Object.keys(t)) if (!allowed.includes(key)) throw new Error(`motion: unsupported transition ${key}`);
|
|
1474
|
+
if (t.when !== void 0 && !["beforeChildren", "afterChildren"].includes(t.when)) throw new Error("motion: unsupported when");
|
|
1230
1475
|
if (t.type !== void 0 && t.type !== "tween" && t.type !== "spring") throw new Error("motion: unsupported transition type");
|
|
1231
1476
|
for (const key of [
|
|
1477
|
+
"staggerChildren",
|
|
1478
|
+
"delayChildren",
|
|
1232
1479
|
"duration",
|
|
1233
1480
|
"delay",
|
|
1481
|
+
"repeatDelay",
|
|
1482
|
+
"bounce",
|
|
1234
1483
|
"stiffness",
|
|
1235
1484
|
"damping",
|
|
1236
1485
|
"mass",
|
|
@@ -1241,6 +1490,12 @@ function validateTransition(t) {
|
|
|
1241
1490
|
const value = t[key];
|
|
1242
1491
|
if (value !== void 0 && (!Number.isFinite(value) || key !== "velocity" && value < 0)) throw new Error(`motion: invalid ${key}`);
|
|
1243
1492
|
}
|
|
1493
|
+
if (t.repeat !== void 0 && (t.repeat < 0 || !Number.isInteger(t.repeat) && t.repeat !== Infinity)) throw new Error("motion: repeat must be a non-negative integer or Infinity");
|
|
1494
|
+
if (t.repeatType !== void 0 && ![
|
|
1495
|
+
"loop",
|
|
1496
|
+
"reverse",
|
|
1497
|
+
"mirror"
|
|
1498
|
+
].includes(t.repeatType)) throw new Error("motion: unsupported repeatType");
|
|
1244
1499
|
for (const key of [
|
|
1245
1500
|
"mass",
|
|
1246
1501
|
"stiffness",
|
|
@@ -1255,10 +1510,31 @@ function validateTransition(t) {
|
|
|
1255
1510
|
"linear",
|
|
1256
1511
|
"easeIn",
|
|
1257
1512
|
"easeOut",
|
|
1258
|
-
"easeInOut"
|
|
1513
|
+
"easeInOut",
|
|
1514
|
+
"circIn",
|
|
1515
|
+
"circOut",
|
|
1516
|
+
"circInOut",
|
|
1517
|
+
"backIn",
|
|
1518
|
+
"backOut",
|
|
1519
|
+
"backInOut",
|
|
1520
|
+
"anticipate"
|
|
1259
1521
|
].includes(t.ease)) throw new Error("motion: unsupported easing");
|
|
1260
1522
|
}
|
|
1261
1523
|
}
|
|
1524
|
+
function validateTransitionInput(t) {
|
|
1525
|
+
if (isOrchestrated(t)) {
|
|
1526
|
+
const { staggerChildren, delayChildren, when, ...channels } = t;
|
|
1527
|
+
validateTransition({
|
|
1528
|
+
staggerChildren,
|
|
1529
|
+
delayChildren,
|
|
1530
|
+
when
|
|
1531
|
+
});
|
|
1532
|
+
for (const [key, value] of Object.entries(channels)) {
|
|
1533
|
+
if (key !== "default" && !MOTION_KEYS.includes(key)) throw new Error(`motion: unsupported transition ${key}`);
|
|
1534
|
+
if (value) validateTransition(value);
|
|
1535
|
+
}
|
|
1536
|
+
} else validateTransition(t);
|
|
1537
|
+
}
|
|
1262
1538
|
function runAnimation(clock, from, to, transition, update, complete) {
|
|
1263
1539
|
validateTransition(transition);
|
|
1264
1540
|
let frame = 0;
|
|
@@ -1275,34 +1551,53 @@ function runAnimation(clock, from, to, transition, update, complete) {
|
|
|
1275
1551
|
if (result === "finished") complete?.();
|
|
1276
1552
|
};
|
|
1277
1553
|
const duration = transition.duration ?? .3;
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1554
|
+
const repeat = transition.repeat ?? 0;
|
|
1555
|
+
const repeatType = transition.repeatType ?? "loop";
|
|
1556
|
+
const repeatDelay = (transition.repeatDelay ?? 0) * 1e3;
|
|
1557
|
+
const makeGenerator = (legFrom, legTo) => transition.type === "spring" ? spring({
|
|
1558
|
+
keyframes: [legFrom, legTo],
|
|
1280
1559
|
stiffness: transition.stiffness ?? 100,
|
|
1281
1560
|
damping: transition.damping ?? 10,
|
|
1282
1561
|
mass: transition.mass ?? 1,
|
|
1283
1562
|
velocity: transition.velocity ?? 0,
|
|
1284
1563
|
restSpeed: transition.restSpeed,
|
|
1285
|
-
restDelta: transition.restDelta
|
|
1564
|
+
restDelta: transition.restDelta,
|
|
1565
|
+
duration: transition.duration !== void 0 ? duration * 1e3 : void 0,
|
|
1566
|
+
bounce: transition.bounce
|
|
1286
1567
|
}) : keyframes({
|
|
1287
|
-
keyframes: [
|
|
1568
|
+
keyframes: [legFrom, legTo],
|
|
1288
1569
|
duration: duration * 1e3,
|
|
1289
1570
|
ease: transition.ease ?? "easeInOut"
|
|
1290
1571
|
});
|
|
1291
|
-
|
|
1572
|
+
let leg = 0;
|
|
1573
|
+
let generator = makeGenerator(from, to);
|
|
1574
|
+
let legStart = clock.now() + (transition.delay ?? 0) * 1e3;
|
|
1292
1575
|
const tick = () => {
|
|
1293
1576
|
if (settled) return;
|
|
1294
|
-
const
|
|
1295
|
-
if (
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1577
|
+
const now = clock.now();
|
|
1578
|
+
if (now < legStart) {
|
|
1579
|
+
frame = clock.request(tick);
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
const elapsed = Math.max(0, now - legStart);
|
|
1583
|
+
const state = generator.next(elapsed);
|
|
1584
|
+
const legEnd = repeatType === "loop" || leg % 2 === 0 ? to : from;
|
|
1585
|
+
update(state.done ? legEnd : state.value);
|
|
1586
|
+
if (state.done) {
|
|
1587
|
+
if (leg < repeat) {
|
|
1588
|
+
leg++;
|
|
1589
|
+
const [legFrom, legTo] = repeatType === "loop" || leg % 2 === 0 ? [from, to] : [to, from];
|
|
1590
|
+
generator = makeGenerator(legFrom, legTo);
|
|
1591
|
+
legStart = now + repeatDelay;
|
|
1592
|
+
frame = clock.request(tick);
|
|
1300
1593
|
return;
|
|
1301
1594
|
}
|
|
1595
|
+
settle("finished");
|
|
1596
|
+
return;
|
|
1302
1597
|
}
|
|
1303
1598
|
if (!settled) frame = clock.request(tick);
|
|
1304
1599
|
};
|
|
1305
|
-
if (transition.type !== "spring" && duration === 0 && !transition.delay) {
|
|
1600
|
+
if (transition.type !== "spring" && duration === 0 && !transition.delay && repeat === 0) {
|
|
1306
1601
|
update(to);
|
|
1307
1602
|
settle("finished");
|
|
1308
1603
|
} else frame = clock.request(tick);
|
|
@@ -1312,6 +1607,230 @@ function runAnimation(clock, from, to, transition, update, complete) {
|
|
|
1312
1607
|
};
|
|
1313
1608
|
}
|
|
1314
1609
|
//#endregion
|
|
1610
|
+
//#region src/delegation.ts
|
|
1611
|
+
function delegationStats() {
|
|
1612
|
+
const platform = globalThis;
|
|
1613
|
+
return platform.__xplatMotionDelegations ??= {
|
|
1614
|
+
started: 0,
|
|
1615
|
+
finished: 0,
|
|
1616
|
+
cancelled: 0,
|
|
1617
|
+
fallback: 0
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
/** Count a delegated run and fold its settled result into the counters. */
|
|
1621
|
+
function trackDelegatedRun(run) {
|
|
1622
|
+
delegationStats().started++;
|
|
1623
|
+
const finished = run.finished.then((result) => {
|
|
1624
|
+
if (result === "finished") delegationStats().finished++;
|
|
1625
|
+
else delegationStats().cancelled++;
|
|
1626
|
+
return result;
|
|
1627
|
+
});
|
|
1628
|
+
return {
|
|
1629
|
+
...run,
|
|
1630
|
+
finished
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
//#endregion
|
|
1634
|
+
//#region src/driver.web.ts
|
|
1635
|
+
var TRANSFORM_KEYS = [
|
|
1636
|
+
"x",
|
|
1637
|
+
"y",
|
|
1638
|
+
"scale",
|
|
1639
|
+
"scaleX",
|
|
1640
|
+
"scaleY",
|
|
1641
|
+
"rotate"
|
|
1642
|
+
];
|
|
1643
|
+
var transform = (values) => `translateX(${values.x ?? 0}px) translateY(${values.y ?? 0}px) scaleX(${values.scaleX ?? 1}) scaleY(${values.scaleY ?? 1}) rotate(${values.rotate ?? 0}deg)`;
|
|
1644
|
+
function decompose(v, origin) {
|
|
1645
|
+
const [ox, oy] = origin.split(" ").map((part) => Number.parseFloat(part) || 0);
|
|
1646
|
+
const [a, b, c, d, e, f] = v.length === 16 ? [
|
|
1647
|
+
v[0],
|
|
1648
|
+
v[1],
|
|
1649
|
+
v[4],
|
|
1650
|
+
v[5],
|
|
1651
|
+
v[12],
|
|
1652
|
+
v[13]
|
|
1653
|
+
] : v;
|
|
1654
|
+
const scaleX = Math.hypot(a, c);
|
|
1655
|
+
const scaleY = Math.hypot(b, d);
|
|
1656
|
+
let rotate = scaleX && scaleY ? Math.atan2(b / scaleY, a / scaleX) * 180 / Math.PI : 0;
|
|
1657
|
+
if (!Number.isFinite(rotate)) rotate = 0;
|
|
1658
|
+
let flippedY = scaleY;
|
|
1659
|
+
if (a * d - b * c < 0) {
|
|
1660
|
+
flippedY = -scaleY;
|
|
1661
|
+
rotate = -rotate;
|
|
1662
|
+
}
|
|
1663
|
+
return {
|
|
1664
|
+
x: e + (a - 1) * ox + c * oy,
|
|
1665
|
+
y: f + b * ox + (d - 1) * oy,
|
|
1666
|
+
scaleX,
|
|
1667
|
+
scaleY: flippedY,
|
|
1668
|
+
rotate
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
function readChannels(node, fallback) {
|
|
1672
|
+
const computed = getComputedStyle(node);
|
|
1673
|
+
const opacity = Number(computed.opacity);
|
|
1674
|
+
const base = {
|
|
1675
|
+
...fallback,
|
|
1676
|
+
opacity: Number.isFinite(opacity) ? opacity : fallback.opacity ?? 1
|
|
1677
|
+
};
|
|
1678
|
+
const match = /matrix(?:3d)?\(([^)]*)\)/.exec(computed.transform);
|
|
1679
|
+
if (!match) return computed.transform === "none" ? {
|
|
1680
|
+
...base,
|
|
1681
|
+
x: 0,
|
|
1682
|
+
y: 0,
|
|
1683
|
+
scaleX: 1,
|
|
1684
|
+
scaleY: 1,
|
|
1685
|
+
rotate: 0
|
|
1686
|
+
} : base;
|
|
1687
|
+
const values = match[1].split(",").map(Number.parseFloat);
|
|
1688
|
+
return values.every(Number.isFinite) ? {
|
|
1689
|
+
...base,
|
|
1690
|
+
...decompose(values, computed.transformOrigin)
|
|
1691
|
+
} : base;
|
|
1692
|
+
}
|
|
1693
|
+
function waapiRun(node, req, write) {
|
|
1694
|
+
if (typeof node.animate !== "function") return null;
|
|
1695
|
+
const { target, eff, transition: t } = req;
|
|
1696
|
+
const animatesTransform = TRANSFORM_KEYS.some((key) => target[key] !== void 0);
|
|
1697
|
+
if (!animatesTransform && target.opacity === void 0) return null;
|
|
1698
|
+
let last = readChannels(node, {
|
|
1699
|
+
opacity: 1,
|
|
1700
|
+
x: 0,
|
|
1701
|
+
y: 0,
|
|
1702
|
+
scaleX: 1,
|
|
1703
|
+
scaleY: 1,
|
|
1704
|
+
rotate: 0
|
|
1705
|
+
});
|
|
1706
|
+
const frames = [{}, {}];
|
|
1707
|
+
if (animatesTransform) {
|
|
1708
|
+
frames[0].transform = transform(last);
|
|
1709
|
+
frames[1].transform = transform(eff);
|
|
1710
|
+
}
|
|
1711
|
+
if (target.opacity !== void 0) {
|
|
1712
|
+
frames[0].opacity = last.opacity ?? 1;
|
|
1713
|
+
frames[1].opacity = Math.min(1, Math.max(0, eff.opacity ?? 1));
|
|
1714
|
+
}
|
|
1715
|
+
const [x1, y1, x2, y2] = bezierPoints(t.ease);
|
|
1716
|
+
let animation;
|
|
1717
|
+
try {
|
|
1718
|
+
animation = node.animate(frames, {
|
|
1719
|
+
duration: (t.duration ?? .3) * 1e3,
|
|
1720
|
+
delay: (t.delay ?? 0) * 1e3,
|
|
1721
|
+
easing: `cubic-bezier(${x1}, ${y1}, ${x2}, ${y2})`,
|
|
1722
|
+
fill: "forwards"
|
|
1723
|
+
});
|
|
1724
|
+
} catch {
|
|
1725
|
+
return null;
|
|
1726
|
+
}
|
|
1727
|
+
const sample = () => {
|
|
1728
|
+
last = readChannels(node, last);
|
|
1729
|
+
return { ...last };
|
|
1730
|
+
};
|
|
1731
|
+
let resolve;
|
|
1732
|
+
const finished = new Promise((done) => {
|
|
1733
|
+
resolve = done;
|
|
1734
|
+
});
|
|
1735
|
+
let settled = false;
|
|
1736
|
+
const settle = (result) => {
|
|
1737
|
+
if (!settled) {
|
|
1738
|
+
settled = true;
|
|
1739
|
+
resolve(result);
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
const complete = () => {
|
|
1743
|
+
write(req.dest);
|
|
1744
|
+
settle("finished");
|
|
1745
|
+
animation.cancel();
|
|
1746
|
+
};
|
|
1747
|
+
const cancelled = () => settle("cancelled");
|
|
1748
|
+
if (typeof animation.finished?.then === "function") animation.finished.then(complete, cancelled);
|
|
1749
|
+
else {
|
|
1750
|
+
animation.onfinish = complete;
|
|
1751
|
+
animation.oncancel = cancelled;
|
|
1752
|
+
}
|
|
1753
|
+
return {
|
|
1754
|
+
finished,
|
|
1755
|
+
sample,
|
|
1756
|
+
cancel() {
|
|
1757
|
+
const current = sample();
|
|
1758
|
+
animation.cancel();
|
|
1759
|
+
write(current);
|
|
1760
|
+
settle("cancelled");
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
function delegatedRun(node, req, write) {
|
|
1765
|
+
if (!isBezierEase(req.transition.ease)) {
|
|
1766
|
+
delegationStats().fallback++;
|
|
1767
|
+
return null;
|
|
1768
|
+
}
|
|
1769
|
+
const run = waapiRun(node, req, write);
|
|
1770
|
+
if (!run) {
|
|
1771
|
+
delegationStats().fallback++;
|
|
1772
|
+
return null;
|
|
1773
|
+
}
|
|
1774
|
+
return trackDelegatedRun(run);
|
|
1775
|
+
}
|
|
1776
|
+
//#endregion
|
|
1777
|
+
//#region src/host.web.ts
|
|
1778
|
+
function attachHost(node) {
|
|
1779
|
+
const transform = node.style.transform;
|
|
1780
|
+
const opacity = node.style.opacity;
|
|
1781
|
+
const computed = getComputedStyle(node);
|
|
1782
|
+
if (computed.transform && computed.transform !== "none") throw new Error("motion: put existing CSS transforms on an outer container");
|
|
1783
|
+
const write = (values) => {
|
|
1784
|
+
if (values.opacity !== void 0) node.style.opacity = String(Math.min(1, Math.max(0, values.opacity)));
|
|
1785
|
+
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)`;
|
|
1786
|
+
};
|
|
1787
|
+
return {
|
|
1788
|
+
pan: (axis, callbacks) => attachPan(node, axis, callbacks),
|
|
1789
|
+
read: () => ({
|
|
1790
|
+
opacity: Number(computed.opacity || 1),
|
|
1791
|
+
x: 0,
|
|
1792
|
+
y: 0,
|
|
1793
|
+
scale: 1,
|
|
1794
|
+
scaleX: 1,
|
|
1795
|
+
scaleY: 1,
|
|
1796
|
+
rotate: 0
|
|
1797
|
+
}),
|
|
1798
|
+
write,
|
|
1799
|
+
delegate: (req) => delegatedRun(node, req, write),
|
|
1800
|
+
restore() {
|
|
1801
|
+
node.style.transform = transform;
|
|
1802
|
+
node.style.opacity = opacity;
|
|
1803
|
+
},
|
|
1804
|
+
gesture(kind, callbacks) {
|
|
1805
|
+
if (kind === "press") {
|
|
1806
|
+
const down = (event) => {
|
|
1807
|
+
try {
|
|
1808
|
+
event.target?.setPointerCapture?.(event.pointerId);
|
|
1809
|
+
} catch (error) {
|
|
1810
|
+
if (event.isTrusted || error.name !== "NotFoundError") throw error;
|
|
1811
|
+
}
|
|
1812
|
+
callbacks.start();
|
|
1813
|
+
};
|
|
1814
|
+
const end = () => callbacks.end();
|
|
1815
|
+
node.addEventListener("pointerdown", down);
|
|
1816
|
+
node.addEventListener("pointerup", end);
|
|
1817
|
+
node.addEventListener("pointercancel", end);
|
|
1818
|
+
return () => {
|
|
1819
|
+
node.removeEventListener("pointerdown", down);
|
|
1820
|
+
node.removeEventListener("pointerup", end);
|
|
1821
|
+
node.removeEventListener("pointercancel", end);
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
node.addEventListener("focus", callbacks.start);
|
|
1825
|
+
node.addEventListener("blur", callbacks.end);
|
|
1826
|
+
return () => {
|
|
1827
|
+
node.removeEventListener("focus", callbacks.start);
|
|
1828
|
+
node.removeEventListener("blur", callbacks.end);
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
//#endregion
|
|
1315
1834
|
//#region src/value.ts
|
|
1316
1835
|
/** Numeric value with direct subscriptions; it does not subscribe Octane renders. */
|
|
1317
1836
|
var MotionValue = class {
|
|
@@ -1376,6 +1895,13 @@ var MotionValue = class {
|
|
|
1376
1895
|
for (const callback of [...this.listeners.get(event) ?? []]) callback(value);
|
|
1377
1896
|
}
|
|
1378
1897
|
write(value) {
|
|
1898
|
+
this.track(value);
|
|
1899
|
+
if (!this.disposed && value !== this.previous) this.emit("change", value);
|
|
1900
|
+
}
|
|
1901
|
+
/** Update position bookkeeping without emitting — platform-delegated runs
|
|
1902
|
+
* track presentation state so interruption reads fresh value/velocity. */
|
|
1903
|
+
track(value) {
|
|
1904
|
+
this.assert(value);
|
|
1379
1905
|
if (this.disposed) return;
|
|
1380
1906
|
const now = this.clock.now();
|
|
1381
1907
|
const elapsed = now - this.updated;
|
|
@@ -1383,10 +1909,9 @@ var MotionValue = class {
|
|
|
1383
1909
|
this.previous = this.current;
|
|
1384
1910
|
this.current = value;
|
|
1385
1911
|
this.updated = now;
|
|
1386
|
-
if (value !== this.previous) this.emit("change", value);
|
|
1387
1912
|
}
|
|
1388
1913
|
/** Animate to a destination. New playback replaces old playback. */
|
|
1389
|
-
animate(target, transition = {}) {
|
|
1914
|
+
animate(target, transition = {}, clampSample) {
|
|
1390
1915
|
this.assert(target);
|
|
1391
1916
|
validateTransition(transition);
|
|
1392
1917
|
if (this.disposed) return {
|
|
@@ -1400,7 +1925,7 @@ var MotionValue = class {
|
|
|
1400
1925
|
const controls = runAnimation(this.clock, this.current, target, {
|
|
1401
1926
|
...transition,
|
|
1402
1927
|
velocity
|
|
1403
|
-
}, (value) => this.write(value));
|
|
1928
|
+
}, (value) => this.write(clampSample ? clampSample(value) : value));
|
|
1404
1929
|
this.controls = controls;
|
|
1405
1930
|
controls.finished.then((result) => {
|
|
1406
1931
|
if (generation !== this.generation || this.disposed) return;
|
|
@@ -1461,7 +1986,10 @@ function validateTarget(target) {
|
|
|
1461
1986
|
var Controller = class {
|
|
1462
1987
|
clock;
|
|
1463
1988
|
values = /* @__PURE__ */ new Map();
|
|
1464
|
-
write
|
|
1989
|
+
/** Per-write snapshot callback (rAF-rate during delegated and JS runs). */
|
|
1990
|
+
onUpdate;
|
|
1991
|
+
adapter;
|
|
1992
|
+
delegated;
|
|
1465
1993
|
generation = 0;
|
|
1466
1994
|
constructor(clock) {
|
|
1467
1995
|
this.clock = clock;
|
|
@@ -1475,15 +2003,24 @@ var Controller = class {
|
|
|
1475
2003
|
}
|
|
1476
2004
|
return value;
|
|
1477
2005
|
}
|
|
1478
|
-
attach(
|
|
1479
|
-
this.
|
|
2006
|
+
attach(adapter) {
|
|
2007
|
+
this.adapter = adapter;
|
|
1480
2008
|
this.flush();
|
|
1481
2009
|
}
|
|
2010
|
+
cancelDelegated() {
|
|
2011
|
+
if (!this.delegated) return;
|
|
2012
|
+
this.clock.cancel(this.delegated.frame);
|
|
2013
|
+
this.delegated.trackSample();
|
|
2014
|
+
this.delegated.run.cancel();
|
|
2015
|
+
this.delegated = void 0;
|
|
2016
|
+
}
|
|
1482
2017
|
snapshot() {
|
|
1483
2018
|
return Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()]));
|
|
1484
2019
|
}
|
|
1485
2020
|
flush() {
|
|
1486
|
-
|
|
2021
|
+
const snapshot = Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()]));
|
|
2022
|
+
this.adapter?.write(snapshot);
|
|
2023
|
+
this.onUpdate?.(snapshot);
|
|
1487
2024
|
}
|
|
1488
2025
|
set(key, next) {
|
|
1489
2026
|
this.value(key).jump(next);
|
|
@@ -1495,9 +2032,65 @@ var Controller = class {
|
|
|
1495
2032
|
async animate(target, transition, reduced) {
|
|
1496
2033
|
validateTarget(target);
|
|
1497
2034
|
const generation = ++this.generation;
|
|
2035
|
+
this.cancelDelegated();
|
|
1498
2036
|
for (const value of this.values.values()) value.stop("replaced");
|
|
2037
|
+
if (!reduced && !isOrchestrated(transition) && transition.type !== "spring" && (transition.duration ?? .3) > 0 && (transition.repeat ?? 0) === 0 && isBezierEase(transition.ease) && this.adapter?.delegate) {
|
|
2038
|
+
const dest = {
|
|
2039
|
+
...this.snapshot(),
|
|
2040
|
+
...target
|
|
2041
|
+
};
|
|
2042
|
+
const run = this.adapter.delegate({
|
|
2043
|
+
target,
|
|
2044
|
+
dest,
|
|
2045
|
+
eff: {
|
|
2046
|
+
opacity: dest.opacity,
|
|
2047
|
+
x: dest.x,
|
|
2048
|
+
y: dest.y,
|
|
2049
|
+
scaleX: (dest.scale ?? 1) * (dest.scaleX ?? 1),
|
|
2050
|
+
scaleY: (dest.scale ?? 1) * (dest.scaleY ?? 1),
|
|
2051
|
+
rotate: dest.rotate
|
|
2052
|
+
},
|
|
2053
|
+
transition
|
|
2054
|
+
});
|
|
2055
|
+
if (run) {
|
|
2056
|
+
const trackSample = () => {
|
|
2057
|
+
const eff = run.sample();
|
|
2058
|
+
for (const key of keys) {
|
|
2059
|
+
if (target[key] === void 0) continue;
|
|
2060
|
+
let next;
|
|
2061
|
+
if (key === "scale") next = (eff.scaleX ?? 1) / (dest.scaleX || 1);
|
|
2062
|
+
else if (key === "scaleX") next = (eff.scaleX ?? 1) / (dest.scale || 1);
|
|
2063
|
+
else if (key === "scaleY") next = (eff.scaleY ?? 1) / (dest.scale || 1);
|
|
2064
|
+
else next = eff[key];
|
|
2065
|
+
if (next !== void 0 && Number.isFinite(next)) this.value(key).track(next);
|
|
2066
|
+
}
|
|
2067
|
+
this.onUpdate?.(this.snapshot());
|
|
2068
|
+
};
|
|
2069
|
+
const entry = {
|
|
2070
|
+
run,
|
|
2071
|
+
frame: 0,
|
|
2072
|
+
trackSample
|
|
2073
|
+
};
|
|
2074
|
+
const tick = () => {
|
|
2075
|
+
if (this.delegated !== entry) return;
|
|
2076
|
+
trackSample();
|
|
2077
|
+
entry.frame = this.clock.request(tick);
|
|
2078
|
+
};
|
|
2079
|
+
entry.frame = this.clock.request(tick);
|
|
2080
|
+
this.delegated = entry;
|
|
2081
|
+
const result = await run.finished;
|
|
2082
|
+
if (this.delegated === entry) {
|
|
2083
|
+
this.clock.cancel(entry.frame);
|
|
2084
|
+
this.delegated = void 0;
|
|
2085
|
+
}
|
|
2086
|
+
if (generation !== this.generation) return "replaced";
|
|
2087
|
+
if (result !== "finished") return "cancelled";
|
|
2088
|
+
for (const key of keys) if (dest[key] !== void 0) this.value(key).jump(dest[key]);
|
|
2089
|
+
return "finished";
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
1499
2092
|
const jobs = Object.entries(target).map(([key, to]) => {
|
|
1500
|
-
return this.value(key).animate(to, reduced && key !== "opacity" ? { duration: 0 } : transition).finished;
|
|
2093
|
+
return this.value(key).animate(to, reduced && key !== "opacity" ? { duration: 0 } : resolveTransition(transition, key)).finished;
|
|
1501
2094
|
});
|
|
1502
2095
|
const results = await Promise.all(jobs);
|
|
1503
2096
|
if (generation !== this.generation) return "replaced";
|
|
@@ -1505,19 +2098,136 @@ var Controller = class {
|
|
|
1505
2098
|
}
|
|
1506
2099
|
stop() {
|
|
1507
2100
|
++this.generation;
|
|
2101
|
+
this.cancelDelegated();
|
|
1508
2102
|
for (const value of this.values.values()) value.stop();
|
|
1509
2103
|
}
|
|
1510
2104
|
destroy() {
|
|
1511
2105
|
this.stop();
|
|
1512
2106
|
for (const value of this.values.values()) value.destroy();
|
|
1513
2107
|
this.values.clear();
|
|
1514
|
-
this.
|
|
2108
|
+
this.adapter = void 0;
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
//#endregion
|
|
2112
|
+
//#region src/variants.ts
|
|
2113
|
+
function isLabels(value) {
|
|
2114
|
+
return typeof value === "string" || Array.isArray(value) && value.every((label) => typeof label === "string");
|
|
2115
|
+
}
|
|
2116
|
+
function resolveVariant(definition, variants, custom) {
|
|
2117
|
+
const target = {};
|
|
2118
|
+
let transition;
|
|
2119
|
+
if (definition === void 0 || definition === false) return {
|
|
2120
|
+
target,
|
|
2121
|
+
transition
|
|
2122
|
+
};
|
|
2123
|
+
const entries = isLabels(definition) ? (typeof definition === "string" ? [definition] : definition).map((label) => Object.hasOwn(variants ?? {}, label) ? variants[label] : void 0) : [definition];
|
|
2124
|
+
for (const entry of entries) {
|
|
2125
|
+
const resolved = typeof entry === "function" ? entry(custom) : entry;
|
|
2126
|
+
if (!resolved) continue;
|
|
2127
|
+
const { transition: override, ...values } = resolved;
|
|
2128
|
+
validateTarget(values);
|
|
2129
|
+
Object.assign(target, values);
|
|
2130
|
+
if (override !== void 0) {
|
|
2131
|
+
validateTransitionInput(override);
|
|
2132
|
+
transition = override;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
return {
|
|
2136
|
+
target,
|
|
2137
|
+
transition
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
/** Keep tree timing out of Controller and add inherited delay to every channel. */
|
|
2141
|
+
function playbackTransition(input, delay = 0) {
|
|
2142
|
+
if (isOrchestrated(input)) {
|
|
2143
|
+
const { staggerChildren: _staggerChildren, delayChildren: _delayChildren, when: _when, ...timing } = input;
|
|
2144
|
+
const result = { default: {
|
|
2145
|
+
...timing.default,
|
|
2146
|
+
delay: (timing.default?.delay ?? 0) + delay
|
|
2147
|
+
} };
|
|
2148
|
+
for (const [key, value] of Object.entries(timing)) if (key !== "default" && value) result[key] = {
|
|
2149
|
+
...value,
|
|
2150
|
+
delay: (value.delay ?? timing.default?.delay ?? 0) + delay
|
|
2151
|
+
};
|
|
2152
|
+
return result;
|
|
2153
|
+
}
|
|
2154
|
+
const { staggerChildren: _staggerChildren, delayChildren: _delayChildren, when: _when, ...timing } = input;
|
|
2155
|
+
return {
|
|
2156
|
+
...timing,
|
|
2157
|
+
delay: (timing.delay ?? 0) + delay
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
/** Root-local tree of inherited runs. Generations prevent queued work after replacement/disposal. */
|
|
2161
|
+
var VariantNode = class {
|
|
2162
|
+
children = /* @__PURE__ */ new Set();
|
|
2163
|
+
generation = 0;
|
|
2164
|
+
active;
|
|
2165
|
+
initial;
|
|
2166
|
+
animate;
|
|
2167
|
+
resolve;
|
|
2168
|
+
play;
|
|
2169
|
+
stopOwn;
|
|
2170
|
+
register(child) {
|
|
2171
|
+
this.children.add(child);
|
|
2172
|
+
const active = this.active;
|
|
2173
|
+
if (active && isLabels(active.definition)) active.finished.then((result) => {
|
|
2174
|
+
if (result !== "finished" || active.generation !== this.generation || !this.children.has(child)) return;
|
|
2175
|
+
const { transition } = this.resolve(active.definition);
|
|
2176
|
+
child.run(active.definition, (transition.delayChildren ?? 0) + [...this.children].indexOf(child) * (transition.staggerChildren ?? 0));
|
|
2177
|
+
});
|
|
2178
|
+
return () => {
|
|
2179
|
+
this.children.delete(child);
|
|
2180
|
+
child.stop();
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
/** Invalidate queued phases without stopping independently registered Presence exits. */
|
|
2184
|
+
cancelPending() {
|
|
2185
|
+
this.generation++;
|
|
2186
|
+
for (const child of this.children) child.cancelPending();
|
|
2187
|
+
}
|
|
2188
|
+
stop() {
|
|
2189
|
+
this.generation++;
|
|
2190
|
+
this.stopOwn?.();
|
|
2191
|
+
for (const child of this.children) child.stop();
|
|
2192
|
+
}
|
|
2193
|
+
run(definition, delay = 0) {
|
|
2194
|
+
this.animate = isLabels(definition) ? definition : void 0;
|
|
2195
|
+
this.stop();
|
|
2196
|
+
const generation = this.generation;
|
|
2197
|
+
const finished = this.runTree(definition, delay, generation);
|
|
2198
|
+
this.active = {
|
|
2199
|
+
definition,
|
|
2200
|
+
finished,
|
|
2201
|
+
generation
|
|
2202
|
+
};
|
|
2203
|
+
return finished;
|
|
2204
|
+
}
|
|
2205
|
+
async runTree(definition, delay, generation) {
|
|
2206
|
+
const { target, transition } = this.resolve(definition);
|
|
2207
|
+
const participants = [...this.children];
|
|
2208
|
+
const own = () => this.play(definition, target, playbackTransition(transition, transition.when === "afterChildren" && participants.length && isLabels(definition) ? 0 : delay));
|
|
2209
|
+
const children = () => Promise.all(isLabels(definition) ? participants.filter((child) => this.children.has(child)).map((child, index) => child.run(definition, (transition.when === "beforeChildren" ? 0 : delay) + (transition.delayChildren ?? 0) + index * (transition.staggerChildren ?? 0))) : []);
|
|
2210
|
+
let results;
|
|
2211
|
+
if (transition.when === "beforeChildren") {
|
|
2212
|
+
const result = await own();
|
|
2213
|
+
if (generation !== this.generation || result !== "finished") return "cancelled";
|
|
2214
|
+
results = [result, ...await children()];
|
|
2215
|
+
} else if (transition.when === "afterChildren") {
|
|
2216
|
+
results = await children();
|
|
2217
|
+
if (generation !== this.generation || results.some((result) => result !== "finished")) return "cancelled";
|
|
2218
|
+
results.push(await own());
|
|
2219
|
+
} else {
|
|
2220
|
+
const parent = own();
|
|
2221
|
+
const descendants = children();
|
|
2222
|
+
results = [await parent, ...await descendants];
|
|
2223
|
+
}
|
|
2224
|
+
return generation === this.generation && results.every((result) => result === "finished") ? "finished" : "cancelled";
|
|
1515
2225
|
}
|
|
1516
2226
|
};
|
|
1517
2227
|
//#endregion
|
|
1518
2228
|
//#region src/components.tsrx
|
|
1519
2229
|
var _t$0 = /* @__PURE__ */ template("<!>", 0, 1);
|
|
1520
|
-
var _hs$$1 = /* @__PURE__ */ hookSlots(
|
|
2230
|
+
var _hs$$1 = /* @__PURE__ */ hookSlots(24);
|
|
1521
2231
|
var _h$0$1 = /* @__PURE__ */ Symbol(_hs$$1);
|
|
1522
2232
|
var _h$1$1 = /* @__PURE__ */ Symbol(_hs$$1 + 1);
|
|
1523
2233
|
var _h$2$1 = /* @__PURE__ */ Symbol(_hs$$1 + 2);
|
|
@@ -1526,51 +2236,92 @@ var _h$4$1 = /* @__PURE__ */ Symbol(_hs$$1 + 4);
|
|
|
1526
2236
|
var _h$5$1 = /* @__PURE__ */ Symbol(_hs$$1 + 5);
|
|
1527
2237
|
var _h$6$1 = /* @__PURE__ */ Symbol(_hs$$1 + 6);
|
|
1528
2238
|
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);
|
|
2239
|
+
var _h$8$1 = /* @__PURE__ */ Symbol(_hs$$1 + 8);
|
|
2240
|
+
var _h$9$1 = /* @__PURE__ */ Symbol(_hs$$1 + 9);
|
|
2241
|
+
var _h$10$1 = /* @__PURE__ */ Symbol(_hs$$1 + 10);
|
|
2242
|
+
var _h$11$1 = /* @__PURE__ */ Symbol(_hs$$1 + 11);
|
|
1533
2243
|
var _h$12 = /* @__PURE__ */ Symbol(_hs$$1 + 12);
|
|
1534
2244
|
var _h$13 = /* @__PURE__ */ Symbol(_hs$$1 + 13);
|
|
1535
2245
|
var _h$14 = /* @__PURE__ */ Symbol(_hs$$1 + 14);
|
|
1536
2246
|
var _h$15 = /* @__PURE__ */ Symbol(_hs$$1 + 15);
|
|
2247
|
+
var _h$16 = /* @__PURE__ */ Symbol(_hs$$1 + 16);
|
|
2248
|
+
var _h$17 = /* @__PURE__ */ Symbol(_hs$$1 + 17);
|
|
2249
|
+
var _h$18 = /* @__PURE__ */ Symbol(_hs$$1 + 18);
|
|
2250
|
+
var _h$19 = /* @__PURE__ */ Symbol(_hs$$1 + 19);
|
|
2251
|
+
var _h$20 = /* @__PURE__ */ Symbol(_hs$$1 + 20);
|
|
1537
2252
|
var __childrenBody = {};
|
|
1538
2253
|
var __childrenBody$ = {};
|
|
2254
|
+
var _h$21 = /* @__PURE__ */ Symbol(_hs$$1 + 21);
|
|
1539
2255
|
var __childrenBody$2 = {};
|
|
2256
|
+
var __childrenBody$3 = {};
|
|
2257
|
+
var _h$22 = /* @__PURE__ */ Symbol(_hs$$1 + 22);
|
|
2258
|
+
var __childrenBody$4 = {};
|
|
2259
|
+
var __childrenBody$5 = {};
|
|
2260
|
+
var _h$23 = /* @__PURE__ */ Symbol(_hs$$1 + 23);
|
|
2261
|
+
var __childrenBody$6 = {};
|
|
2262
|
+
var __childrenBody$7 = {};
|
|
2263
|
+
var VariantContext = /* @__PURE__ */ __createCompiledContext(null);
|
|
2264
|
+
var controllers = /* @__PURE__ */ new WeakMap();
|
|
2265
|
+
var GESTURE_PROPS = {
|
|
2266
|
+
press: {
|
|
2267
|
+
target: "whileTap",
|
|
2268
|
+
transition: "whileTapTransition"
|
|
2269
|
+
},
|
|
2270
|
+
focus: {
|
|
2271
|
+
target: "whileFocus",
|
|
2272
|
+
transition: "whileFocusTransition"
|
|
2273
|
+
}
|
|
2274
|
+
};
|
|
1540
2275
|
function useMotion(props) {
|
|
1541
2276
|
for (const name of [
|
|
1542
|
-
"drag",
|
|
1543
2277
|
"layout",
|
|
1544
2278
|
"layoutId",
|
|
1545
|
-
"
|
|
1546
|
-
"whileTap",
|
|
2279
|
+
"inherit",
|
|
1547
2280
|
"whileHover",
|
|
1548
|
-
"
|
|
1549
|
-
"
|
|
2281
|
+
"whileInView",
|
|
2282
|
+
"whileDrag"
|
|
1550
2283
|
]) if (name in props) throw new Error(`motion: ${name} is outside the supported subset`);
|
|
2284
|
+
validateDrag(props);
|
|
2285
|
+
const parentVariant = useContext(VariantContext);
|
|
2286
|
+
const inherits = props.animate === void 0 && parentVariant !== null;
|
|
2287
|
+
const initialDefinition = props.initial ?? parentVariant?.initial;
|
|
2288
|
+
const animateDefinition = props.animate ?? parentVariant?.animate;
|
|
2289
|
+
const resolve = (definition, source = props) => {
|
|
2290
|
+
const resolved = resolveVariant(definition, source.variants, source.custom);
|
|
2291
|
+
for (const key of keys) if (resolved.target[key] !== void 0 && source.style?.[key] instanceof MotionValue) throw new Error(`motion: ${key} has both an animate target and a MotionValue writer`);
|
|
2292
|
+
return resolved;
|
|
2293
|
+
};
|
|
2294
|
+
const resolvedAnimate = resolve(animateDefinition);
|
|
2295
|
+
const resolvedInitial = resolve(initialDefinition);
|
|
2296
|
+
const resolvedExit = resolve(props.exit);
|
|
1551
2297
|
const presence = useContext(PresenceContext);
|
|
1552
2298
|
if (props.exit && !presence) throw new Error("motion: exit requires a mounted Presence boundary");
|
|
1553
2299
|
const config = useContext(ConfigContext);
|
|
1554
2300
|
const systemReduced = withSlot(_h$0$1, useReducedMotion);
|
|
1555
2301
|
const reduced = config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced;
|
|
1556
2302
|
const transition = props.transition ?? config.transition ?? {};
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
if (props.
|
|
2303
|
+
validateTransitionInput(transition);
|
|
2304
|
+
resolve(props.whileTap);
|
|
2305
|
+
resolve(props.whileFocus);
|
|
2306
|
+
if (props.whileTapTransition) validateTransitionInput(props.whileTapTransition);
|
|
2307
|
+
if (props.whileFocusTransition) validateTransitionInput(props.whileFocusTransition);
|
|
1561
2308
|
const latest = useRef(props, _h$1$1);
|
|
1562
2309
|
latest.current = props;
|
|
1563
2310
|
const state = useRef(null, _h$2$1);
|
|
1564
2311
|
if (!state.current) state.current = {
|
|
1565
2312
|
controller: new Controller(clock),
|
|
1566
|
-
initialized: false
|
|
2313
|
+
initialized: false,
|
|
2314
|
+
preGesture: {
|
|
2315
|
+
press: void 0,
|
|
2316
|
+
focus: void 0
|
|
2317
|
+
}
|
|
1567
2318
|
};
|
|
1568
2319
|
const current = state.current;
|
|
1569
2320
|
const style = {};
|
|
1570
2321
|
const bindings = [];
|
|
1571
2322
|
for (const [key, value] of Object.entries(props.style ?? {})) if (keys.includes(key)) {
|
|
1572
2323
|
if (!(value instanceof MotionValue) && (typeof value !== "number" || !Number.isFinite(value))) throw new Error(`motion: invalid style ${key}`);
|
|
1573
|
-
if (value instanceof MotionValue && (
|
|
2324
|
+
if (value instanceof MotionValue && (resolvedAnimate.target[key] !== void 0 || resolvedExit.target[key] !== void 0 || resolvedInitial.target[key] !== void 0)) throw new Error(`motion: ${key} has both an animate target and a MotionValue writer`);
|
|
1574
2325
|
bindings.push([key, value]);
|
|
1575
2326
|
} else {
|
|
1576
2327
|
if (value instanceof MotionValue || [
|
|
@@ -1586,11 +2337,36 @@ function useMotion(props) {
|
|
|
1586
2337
|
const boundKeys = useRef([], _h$4$1);
|
|
1587
2338
|
const firstBinding = useRef(true, _h$5$1);
|
|
1588
2339
|
const firstAnimation = useRef(true, _h$6$1);
|
|
2340
|
+
const inheritedRun = useRef(null, _h$7$1);
|
|
1589
2341
|
if (previous.current.length !== bindings.length || previous.current.some(([key, value], i) => key !== bindings[i][0] || value !== bindings[i][1])) previous.current = bindings;
|
|
1590
|
-
|
|
1591
|
-
|
|
2342
|
+
current.controller.onUpdate = (snapshot) => latest.current.onUpdate?.(snapshot);
|
|
2343
|
+
const gesture = (kind, phase) => {
|
|
2344
|
+
const shape = GESTURE_PROPS[kind];
|
|
2345
|
+
const definition = latest.current[shape.target];
|
|
2346
|
+
if (!definition) return;
|
|
2347
|
+
const { target, transition: override } = resolve(definition, latest.current);
|
|
2348
|
+
const gestureTransition = playbackTransition(override ?? latest.current[shape.transition] ?? playback.current.transition);
|
|
2349
|
+
if (phase === "start") {
|
|
2350
|
+
const snapshot = current.controller.snapshot();
|
|
2351
|
+
const rest = {};
|
|
2352
|
+
for (const key of Object.keys(target)) rest[key] = snapshot[key];
|
|
2353
|
+
current.preGesture[kind] = rest;
|
|
2354
|
+
current.controller.animate(target, gestureTransition, playback.current.reduced);
|
|
2355
|
+
} else {
|
|
2356
|
+
const snap = current.preGesture[kind] ?? {};
|
|
2357
|
+
current.preGesture[kind] = void 0;
|
|
2358
|
+
const rest = {};
|
|
2359
|
+
for (const key of Object.keys(target)) rest[key] = resolve(latest.current.animate ?? parentVariant?.animate, latest.current).target[key] ?? snap[key] ?? defaults[key];
|
|
2360
|
+
current.controller.animate(rest, gestureTransition, playback.current.reduced);
|
|
2361
|
+
}
|
|
2362
|
+
};
|
|
2363
|
+
const ref = useRef(() => {}, _h$8$1);
|
|
2364
|
+
ref.current = (host) => {
|
|
1592
2365
|
if (!host) return;
|
|
1593
2366
|
if (current.host !== host) {
|
|
2367
|
+
current.gestureOff?.();
|
|
2368
|
+
current.dragOff?.();
|
|
2369
|
+
current.gestureOff = void 0;
|
|
1594
2370
|
current.adapter?.restore();
|
|
1595
2371
|
current.host = host;
|
|
1596
2372
|
current.adapter = attachHost(host);
|
|
@@ -1598,49 +2374,83 @@ function useMotion(props) {
|
|
|
1598
2374
|
const baseline = current.adapter.read();
|
|
1599
2375
|
for (const [key, value] of previous.current) baseline[key] = value instanceof MotionValue ? value.get() : value;
|
|
1600
2376
|
current.controller.seed(baseline);
|
|
1601
|
-
current.controller.seed(
|
|
2377
|
+
current.controller.seed(initialDefinition === false ? resolvedAnimate.target : resolvedInitial.target);
|
|
1602
2378
|
current.initialized = true;
|
|
1603
2379
|
}
|
|
1604
|
-
current.controller.attach(current.adapter
|
|
2380
|
+
current.controller.attach(current.adapter);
|
|
2381
|
+
controllers.set(host, current.controller);
|
|
2382
|
+
configureDrag();
|
|
2383
|
+
if (current.adapter.gesture) {
|
|
2384
|
+
const offs = ["press", "focus"].map((kind) => current.adapter.gesture(kind, {
|
|
2385
|
+
start: () => gesture(kind, "start"),
|
|
2386
|
+
end: () => gesture(kind, "end")
|
|
2387
|
+
})).filter((off) => typeof off === "function");
|
|
2388
|
+
current.gestureOff = () => offs.forEach((off) => off());
|
|
2389
|
+
}
|
|
1605
2390
|
}
|
|
1606
2391
|
current.controller.flush();
|
|
1607
|
-
latest.current.bind?.(host);
|
|
1608
2392
|
};
|
|
1609
2393
|
const playback = useRef({
|
|
1610
2394
|
transition,
|
|
1611
2395
|
reduced
|
|
1612
|
-
}, _h$
|
|
2396
|
+
}, _h$9$1);
|
|
1613
2397
|
playback.current = {
|
|
1614
2398
|
transition,
|
|
1615
2399
|
reduced
|
|
1616
2400
|
};
|
|
1617
|
-
const
|
|
1618
|
-
|
|
2401
|
+
const nodeRef = useRef(null, _h$10$1);
|
|
2402
|
+
if (!nodeRef.current) nodeRef.current = new VariantNode();
|
|
2403
|
+
const node = nodeRef.current;
|
|
2404
|
+
node.initial = initialDefinition === false || isLabels(initialDefinition) ? initialDefinition : void 0;
|
|
2405
|
+
node.animate = isLabels(animateDefinition) ? animateDefinition : void 0;
|
|
2406
|
+
node.resolve = (definition) => {
|
|
2407
|
+
const resolved = resolve(definition, latest.current);
|
|
2408
|
+
return {
|
|
2409
|
+
target: resolved.target,
|
|
2410
|
+
transition: resolved.transition ?? playback.current.transition
|
|
2411
|
+
};
|
|
2412
|
+
};
|
|
2413
|
+
node.stopOwn = () => current.controller.stop();
|
|
2414
|
+
node.play = async (definition, target, timing) => {
|
|
2415
|
+
latest.current.onAnimationStart?.(definition);
|
|
2416
|
+
const result = await current.controller.animate(target, timing, playback.current.reduced);
|
|
2417
|
+
if (result === "finished" && current.host) latest.current.onAnimationComplete?.();
|
|
2418
|
+
return result;
|
|
2419
|
+
};
|
|
2420
|
+
useLayoutEffect(() => inherits ? parentVariant.register(node) : void 0, [inherits, parentVariant], _h$11$1);
|
|
2421
|
+
const returning = useRef(null, _h$12);
|
|
2422
|
+
const member = useRef(null, _h$13);
|
|
1619
2423
|
if (!member.current) member.current = {
|
|
1620
2424
|
exit() {
|
|
2425
|
+
node.cancelPending();
|
|
1621
2426
|
const snapshot = current.controller.snapshot();
|
|
1622
2427
|
returning.current ??= {};
|
|
1623
|
-
|
|
1624
|
-
|
|
2428
|
+
const resolved = resolve(latest.current.exit, latest.current);
|
|
2429
|
+
for (const key of Object.keys(resolved.target)) if (!(key in returning.current)) returning.current[key] = snapshot[key];
|
|
2430
|
+
return current.controller.animate(resolved.target, playbackTransition(resolved.transition ?? playback.current.transition), playback.current.reduced);
|
|
1625
2431
|
},
|
|
1626
2432
|
enter() {
|
|
2433
|
+
const resolved = resolve(latest.current.animate ?? parentVariant?.animate, latest.current);
|
|
1627
2434
|
const target = {
|
|
1628
2435
|
...returning.current,
|
|
1629
|
-
...
|
|
2436
|
+
...resolved.target
|
|
1630
2437
|
};
|
|
1631
2438
|
returning.current = null;
|
|
1632
|
-
current.controller.animate(target, playback.current.transition, playback.current.reduced).then((result) => {
|
|
2439
|
+
current.controller.animate(target, playbackTransition(resolved.transition ?? playback.current.transition), playback.current.reduced).then((result) => {
|
|
1633
2440
|
if (result === "finished" && current.host && presence?.present) latest.current.onAnimationComplete?.();
|
|
1634
2441
|
});
|
|
1635
2442
|
}
|
|
1636
2443
|
};
|
|
1637
|
-
useLayoutEffect(() => presence?.register(member.current), [presence], _h$
|
|
1638
|
-
const
|
|
2444
|
+
useLayoutEffect(() => presence?.register(member.current), [presence], _h$14);
|
|
2445
|
+
const hostRef = useRef((host) => ref.current(host), _h$15).current;
|
|
1639
2446
|
useLayoutEffect(() => () => {
|
|
2447
|
+
node.stop();
|
|
2448
|
+
current.dragOff?.();
|
|
2449
|
+
current.gestureOff?.();
|
|
1640
2450
|
current.controller.destroy();
|
|
1641
2451
|
current.host = void 0;
|
|
1642
2452
|
current.adapter = void 0;
|
|
1643
|
-
}, [], _h$
|
|
2453
|
+
}, [], _h$16);
|
|
1644
2454
|
useLayoutEffect(() => {
|
|
1645
2455
|
const off = [];
|
|
1646
2456
|
for (const key of boundKeys.current) if (!previous.current.some(([next]) => key === next)) current.controller.set(key, defaults[key]);
|
|
@@ -1651,107 +2461,214 @@ function useMotion(props) {
|
|
|
1651
2461
|
}
|
|
1652
2462
|
firstBinding.current = false;
|
|
1653
2463
|
return () => off.forEach((unsubscribe) => unsubscribe());
|
|
1654
|
-
}, [previous.current], _h$
|
|
2464
|
+
}, [previous.current], _h$17);
|
|
2465
|
+
const configureDrag = () => {
|
|
2466
|
+
current.dragOff?.();
|
|
2467
|
+
current.dragOff = void 0;
|
|
2468
|
+
if (!current.adapter) return;
|
|
2469
|
+
current.dragOff = attachDrag(current.adapter, current.controller, latest.current, (axis) => {
|
|
2470
|
+
const binding = previous.current.find(([key]) => key === axis)?.[1];
|
|
2471
|
+
return binding instanceof MotionValue ? binding : current.controller.value(axis);
|
|
2472
|
+
}, () => playback.current.reduced, () => latest.current);
|
|
2473
|
+
};
|
|
1655
2474
|
useLayoutEffect(() => {
|
|
1656
|
-
|
|
1657
|
-
|
|
2475
|
+
configureDrag();
|
|
2476
|
+
}, [
|
|
2477
|
+
props.drag,
|
|
2478
|
+
JSON.stringify(props.dragConstraints),
|
|
2479
|
+
props.dragElastic,
|
|
2480
|
+
props.dragMomentum,
|
|
2481
|
+
previous.current
|
|
2482
|
+
], _h$18);
|
|
2483
|
+
useLayoutEffect(() => {
|
|
2484
|
+
const skip = firstAnimation.current && initialDefinition === false;
|
|
1658
2485
|
firstAnimation.current = false;
|
|
1659
2486
|
if (presence && !presence.present) presence.restart(member.current);
|
|
1660
|
-
else if (
|
|
1661
|
-
if (
|
|
1662
|
-
|
|
2487
|
+
else if (animateDefinition !== void 0 && !skip) {
|
|
2488
|
+
if (!inherits) node.run(animateDefinition);
|
|
2489
|
+
else {
|
|
2490
|
+
const label = JSON.stringify(animateDefinition);
|
|
2491
|
+
const resolved = JSON.stringify({
|
|
2492
|
+
resolvedAnimate,
|
|
2493
|
+
transition,
|
|
2494
|
+
reduced
|
|
2495
|
+
});
|
|
2496
|
+
const previousRun = inheritedRun.current;
|
|
2497
|
+
if (previousRun?.label === label && previousRun.resolved !== resolved) {
|
|
2498
|
+
const parentTiming = parentVariant.resolve(animateDefinition).transition;
|
|
2499
|
+
node.run(animateDefinition, (parentTiming.delayChildren ?? 0) + [...parentVariant.children].indexOf(node) * (parentTiming.staggerChildren ?? 0));
|
|
2500
|
+
}
|
|
2501
|
+
inheritedRun.current = {
|
|
2502
|
+
label,
|
|
2503
|
+
resolved
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
1663
2507
|
return () => {
|
|
1664
|
-
|
|
1665
|
-
current.controller.stop();
|
|
2508
|
+
if (!inherits) node.stop();
|
|
1666
2509
|
};
|
|
1667
2510
|
}, [
|
|
1668
|
-
JSON.stringify(
|
|
1669
|
-
JSON.stringify(
|
|
2511
|
+
JSON.stringify(resolvedAnimate),
|
|
2512
|
+
JSON.stringify(resolvedExit),
|
|
2513
|
+
JSON.stringify(animateDefinition),
|
|
1670
2514
|
JSON.stringify(transition),
|
|
1671
|
-
reduced
|
|
1672
|
-
|
|
1673
|
-
|
|
2515
|
+
reduced,
|
|
2516
|
+
inherits
|
|
2517
|
+
], _h$19);
|
|
2518
|
+
const { drag, dragConstraints, dragElastic, dragMomentum, onDragStart, onDrag, onDragEnd, variants, custom, initial, exit, animate, transition: ignoredTransition, whileTap, whileTapTransition, whileFocus, whileFocusTransition, onAnimationStart, onAnimationComplete, onUpdate, style: ignoredStyle, ref: ignoredRef, ...rest } = props;
|
|
1674
2519
|
return {
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2520
|
+
hostProps: {
|
|
2521
|
+
...rest,
|
|
2522
|
+
style,
|
|
2523
|
+
ref: [hostRef, props.ref]
|
|
2524
|
+
},
|
|
2525
|
+
node
|
|
1678
2526
|
};
|
|
1679
2527
|
}
|
|
1680
|
-
var
|
|
2528
|
+
var MotionLeaf = function MotionLeaf(props, __s, __extra) {
|
|
1681
2529
|
const __block = __s.block;
|
|
2530
|
+
const Component = props.component;
|
|
2531
|
+
const { hostProps, node } = withSlot(_h$20, useMotion, props);
|
|
2532
|
+
if (__s.block.pending && !__s.block.crossRenderUpdate) return;
|
|
1682
2533
|
function __children$1(__props, __s, __extra) {
|
|
1683
2534
|
const __block = __s.block;
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
let
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
2535
|
+
function __children$3(__props, __s, __extra) {
|
|
2536
|
+
const __block = __s.block;
|
|
2537
|
+
let _b = __s.slots[0];
|
|
2538
|
+
if (_b === void 0) {
|
|
2539
|
+
let _m0, _m1;
|
|
2540
|
+
const _root = clone(_t$0);
|
|
2541
|
+
_m0 = __block.parentNode;
|
|
2542
|
+
_m1 = child(_root);
|
|
2543
|
+
drainFrag(_root, __block.parentNode, __block.endMarker);
|
|
2544
|
+
_b = bag4(__s, null, _m0, _m1, null, void 0);
|
|
2545
|
+
}
|
|
2546
|
+
{
|
|
2547
|
+
const _v = props.children;
|
|
2548
|
+
_b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
|
|
2549
|
+
_b.d = _v;
|
|
2550
|
+
}
|
|
1692
2551
|
}
|
|
1693
|
-
{
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
2552
|
+
componentSlot(__s, 0, __block.parentNode, Component, {
|
|
2553
|
+
...hostProps,
|
|
2554
|
+
"children": markChildrenBlock(__children$3, __childrenBody)
|
|
2555
|
+
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:2b39630a");
|
|
2556
|
+
}
|
|
2557
|
+
componentSlotVoid(__s, 0, __block.parentNode, VariantContext, {
|
|
2558
|
+
"value": node,
|
|
2559
|
+
"children": markChildrenBlock(__children$1, __childrenBody$)
|
|
2560
|
+
}, __block.endMarker, void 0, void 0, true, void 0, "c:3e3b1f06");
|
|
2561
|
+
};
|
|
2562
|
+
function createMotion(Component) {
|
|
2563
|
+
return function MotionCreated(props, __s, __extra) {
|
|
2564
|
+
return MotionLeaf({
|
|
2565
|
+
...props,
|
|
2566
|
+
component: Component
|
|
2567
|
+
}, __s, __extra);
|
|
2568
|
+
};
|
|
2569
|
+
}
|
|
2570
|
+
var MotionView = function MotionView(props, __s, __extra) {
|
|
2571
|
+
const __block = __s.block;
|
|
2572
|
+
const { hostProps, node } = withSlot(_h$21, useMotion, props);
|
|
2573
|
+
if (__s.block.pending && !__s.block.crossRenderUpdate) return;
|
|
2574
|
+
function __children$6(__props, __s, __extra) {
|
|
2575
|
+
const __block = __s.block;
|
|
2576
|
+
function __children$8(__props, __s, __extra) {
|
|
2577
|
+
const __block = __s.block;
|
|
2578
|
+
let _b = __s.slots[0];
|
|
2579
|
+
if (_b === void 0) {
|
|
2580
|
+
let _m0, _m1;
|
|
2581
|
+
const _root = clone(_t$0);
|
|
2582
|
+
_m0 = __block.parentNode;
|
|
2583
|
+
_m1 = child(_root);
|
|
2584
|
+
drainFrag(_root, __block.parentNode, __block.endMarker);
|
|
2585
|
+
_b = bag4(__s, null, _m0, _m1, null, void 0);
|
|
2586
|
+
}
|
|
2587
|
+
{
|
|
2588
|
+
const _v = props.children;
|
|
2589
|
+
_b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
|
|
2590
|
+
_b.d = _v;
|
|
2591
|
+
}
|
|
1697
2592
|
}
|
|
2593
|
+
componentSlot(__s, 0, __block.parentNode, View, {
|
|
2594
|
+
...hostProps,
|
|
2595
|
+
"children": markChildrenBlock(__children$8, __childrenBody$2)
|
|
2596
|
+
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:47ef6ed2");
|
|
1698
2597
|
}
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
"children": markChildrenBlock(__children$
|
|
1702
|
-
}, __block.endMarker, void 0, void 0, true, void 0, "c:
|
|
2598
|
+
componentSlotVoid(__s, 0, __block.parentNode, VariantContext, {
|
|
2599
|
+
"value": node,
|
|
2600
|
+
"children": markChildrenBlock(__children$6, __childrenBody$3)
|
|
2601
|
+
}, __block.endMarker, void 0, void 0, true, void 0, "c:556f022a");
|
|
1703
2602
|
};
|
|
1704
2603
|
var MotionRow = function MotionRow(props, __s, __extra) {
|
|
1705
2604
|
const __block = __s.block;
|
|
1706
|
-
|
|
2605
|
+
const { hostProps, node } = withSlot(_h$22, useMotion, props);
|
|
2606
|
+
if (__s.block.pending && !__s.block.crossRenderUpdate) return;
|
|
2607
|
+
function __children$11(__props, __s, __extra) {
|
|
1707
2608
|
const __block = __s.block;
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
let
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
2609
|
+
function __children$13(__props, __s, __extra) {
|
|
2610
|
+
const __block = __s.block;
|
|
2611
|
+
let _b = __s.slots[0];
|
|
2612
|
+
if (_b === void 0) {
|
|
2613
|
+
let _m0, _m1;
|
|
2614
|
+
const _root = clone(_t$0);
|
|
2615
|
+
_m0 = __block.parentNode;
|
|
2616
|
+
_m1 = child(_root);
|
|
2617
|
+
drainFrag(_root, __block.parentNode, __block.endMarker);
|
|
2618
|
+
_b = bag4(__s, null, _m0, _m1, null, void 0);
|
|
2619
|
+
}
|
|
2620
|
+
{
|
|
2621
|
+
const _v = props.children;
|
|
2622
|
+
_b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
|
|
2623
|
+
_b.d = _v;
|
|
2624
|
+
}
|
|
1721
2625
|
}
|
|
2626
|
+
componentSlot(__s, 0, __block.parentNode, HStack, {
|
|
2627
|
+
...hostProps,
|
|
2628
|
+
"children": markChildrenBlock(__children$13, __childrenBody$4)
|
|
2629
|
+
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:4ef5f0ee");
|
|
1722
2630
|
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
"children": markChildrenBlock(__children$
|
|
1726
|
-
}, __block.endMarker, void 0, void 0, true, void 0, "c:
|
|
2631
|
+
componentSlotVoid(__s, 0, __block.parentNode, VariantContext, {
|
|
2632
|
+
"value": node,
|
|
2633
|
+
"children": markChildrenBlock(__children$11, __childrenBody$5)
|
|
2634
|
+
}, __block.endMarker, void 0, void 0, true, void 0, "c:098721c2");
|
|
1727
2635
|
};
|
|
1728
2636
|
var MotionPressable = function MotionPressable(props, __s, __extra) {
|
|
1729
2637
|
const __block = __s.block;
|
|
1730
|
-
|
|
2638
|
+
const { hostProps, node } = withSlot(_h$23, useMotion, props);
|
|
2639
|
+
if (__s.block.pending && !__s.block.crossRenderUpdate) return;
|
|
2640
|
+
function __children$16(__props, __s, __extra) {
|
|
1731
2641
|
const __block = __s.block;
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
let
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
2642
|
+
function __children$18(__props, __s, __extra) {
|
|
2643
|
+
const __block = __s.block;
|
|
2644
|
+
let _b = __s.slots[0];
|
|
2645
|
+
if (_b === void 0) {
|
|
2646
|
+
let _m0, _m1;
|
|
2647
|
+
const _root = clone(_t$0);
|
|
2648
|
+
_m0 = __block.parentNode;
|
|
2649
|
+
_m1 = child(_root);
|
|
2650
|
+
drainFrag(_root, __block.parentNode, __block.endMarker);
|
|
2651
|
+
_b = bag4(__s, null, _m0, _m1, null, void 0);
|
|
2652
|
+
}
|
|
2653
|
+
{
|
|
2654
|
+
const _v = props.children;
|
|
2655
|
+
_b.c = textHoleUpdate(__s, 1, _b.a, _v, _b.c, _b.d, _b.b, true, true);
|
|
2656
|
+
_b.d = _v;
|
|
2657
|
+
}
|
|
1745
2658
|
}
|
|
2659
|
+
componentSlot(__s, 0, __block.parentNode, Pressable, {
|
|
2660
|
+
...hostProps,
|
|
2661
|
+
"children": markChildrenBlock(__children$18, __childrenBody$6)
|
|
2662
|
+
}, __block.endMarker, void 0, void 0, void 0, void 0, "c:de6a02de");
|
|
1746
2663
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
"children": markChildrenBlock(__children$
|
|
1750
|
-
}, __block.endMarker, void 0, void 0, true, void 0, "c:
|
|
2664
|
+
componentSlotVoid(__s, 0, __block.parentNode, VariantContext, {
|
|
2665
|
+
"value": node,
|
|
2666
|
+
"children": markChildrenBlock(__children$16, __childrenBody$7)
|
|
2667
|
+
}, __block.endMarker, void 0, void 0, true, void 0, "c:b94b76f9");
|
|
1751
2668
|
};
|
|
1752
2669
|
//#endregion
|
|
1753
2670
|
//#region src/hooks.tsrx
|
|
1754
|
-
var _hs$ = /* @__PURE__ */ hookSlots(
|
|
2671
|
+
var _hs$ = /* @__PURE__ */ hookSlots(12);
|
|
1755
2672
|
var _h$0 = /* @__PURE__ */ Symbol(_hs$);
|
|
1756
2673
|
var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
|
|
1757
2674
|
var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
|
|
@@ -1760,6 +2677,10 @@ var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
|
|
|
1760
2677
|
var _h$5 = /* @__PURE__ */ Symbol(_hs$ + 5);
|
|
1761
2678
|
var _h$6 = /* @__PURE__ */ Symbol(_hs$ + 6);
|
|
1762
2679
|
var _h$7 = /* @__PURE__ */ Symbol(_hs$ + 7);
|
|
2680
|
+
var _h$8 = /* @__PURE__ */ Symbol(_hs$ + 8);
|
|
2681
|
+
var _h$9 = /* @__PURE__ */ Symbol(_hs$ + 9);
|
|
2682
|
+
var _h$10 = /* @__PURE__ */ Symbol(_hs$ + 10);
|
|
2683
|
+
var _h$11 = /* @__PURE__ */ Symbol(_hs$ + 11);
|
|
1763
2684
|
function useMotionValue(initial) {
|
|
1764
2685
|
const ref = useRef(null, _h$0);
|
|
1765
2686
|
if (!ref.current) ref.current = new MotionValue(initial, clock);
|
|
@@ -1814,13 +2735,30 @@ function useSpring(source, options = {}) {
|
|
|
1814
2735
|
}, [source instanceof MotionValue ? source : null, JSON.stringify(options)], _h$7);
|
|
1815
2736
|
return value;
|
|
1816
2737
|
}
|
|
2738
|
+
function useAnimate() {
|
|
2739
|
+
const scope = useRef(null, _h$8);
|
|
2740
|
+
const config = useContext(ConfigContext);
|
|
2741
|
+
const systemReduced = withSlot(_h$9, useReducedMotion);
|
|
2742
|
+
const reducedRef = useRef(config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced, _h$10);
|
|
2743
|
+
reducedRef.current = config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced;
|
|
2744
|
+
return [scope, useRef((target, transitionOrTo, transition) => {
|
|
2745
|
+
if (target instanceof MotionValue) return target.animate(transitionOrTo, transition);
|
|
2746
|
+
const controller = target && typeof target === "object" && controllers.has(target) ? controllers.get(target) : scope.current ? controllers.get(scope.current) : void 0;
|
|
2747
|
+
if (!controller) return Promise.resolve("cancelled");
|
|
2748
|
+
const destination = controllers.has(target) ? transitionOrTo ?? {} : target;
|
|
2749
|
+
const spec = controllers.has(target) ? transition ?? {} : transitionOrTo ?? {};
|
|
2750
|
+
return controller.animate(destination, spec, reducedRef.current);
|
|
2751
|
+
}, _h$11).current];
|
|
2752
|
+
}
|
|
1817
2753
|
//#endregion
|
|
1818
2754
|
//#region src/index.web.ts
|
|
1819
|
-
/** Bounded motion hosts for shared xplat UI primitives.
|
|
2755
|
+
/** Bounded motion hosts for shared xplat UI primitives; `motion.create` wraps
|
|
2756
|
+
* any component that accepts `ref`/`style`/`children`. */
|
|
1820
2757
|
var motion = {
|
|
1821
2758
|
View: MotionView,
|
|
1822
2759
|
Row: MotionRow,
|
|
1823
|
-
Pressable: MotionPressable
|
|
2760
|
+
Pressable: MotionPressable,
|
|
2761
|
+
create: createMotion
|
|
1824
2762
|
};
|
|
1825
2763
|
//#endregion
|
|
1826
|
-
export { MotionConfig, Presence, motion, useMotionValue, useMotionValueEvent, useReducedMotion, useSpring, useTransform };
|
|
2764
|
+
export { MotionConfig, Presence, motion, useAnimate, useMotionValue, useMotionValueEvent, useReducedMotion, useSpring, useTransform };
|