@octane-xplat/motion 0.9.0 → 0.11.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/dist/web/index.js CHANGED
@@ -1,6 +1,6 @@
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";
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$3 = {};
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$3)
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 bind = __extra[0];
151
- const children = __extra[1];
152
- const host = __extra[2];
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:63be6025");
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
- "bind": (node) => {
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
- bind?.(node);
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 ref = useRef(null, _hs$$2 + 2);
202
- if (!ref.current) ref.current = new PresenceState(props.present, () => {
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 = ref.current;
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, bind, ...viewProps } = props;
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/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),
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
- 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;
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" && (t.duration !== void 0 || t.ease !== void 0)) throw new Error("motion: physical springs do not accept duration or ease");
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 generator = transition.type === "spring" ? spring({
1279
- keyframes: [from, to],
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: [from, to],
1568
+ keyframes: [legFrom, legTo],
1288
1569
  duration: duration * 1e3,
1289
1570
  ease: transition.ease ?? "easeInOut"
1290
1571
  });
1291
- const start = clock.now() + (transition.delay ?? 0) * 1e3;
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 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");
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(write) {
1479
- this.write = write;
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
- this.write?.(Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()])));
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.write = void 0;
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(16);
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
- "variants",
1546
- "whileTap",
2279
+ "inherit",
1547
2280
  "whileHover",
1548
- "whileFocus",
1549
- "whileInView"
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
- validateTransition(transition);
1558
- validateTarget(props.animate);
1559
- validateTarget(props.exit);
1560
- if (props.initial !== false) validateTarget(props.initial);
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 && (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`);
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
- const bind = useRef(() => {}, _h$7$1);
1591
- bind.current = (host) => {
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(props.initial === false ? props.animate ?? {} : props.initial ?? {});
2377
+ current.controller.seed(initialDefinition === false ? resolvedAnimate.target : resolvedInitial.target);
1602
2378
  current.initialized = true;
1603
2379
  }
1604
- current.controller.attach(current.adapter.write);
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$8);
2396
+ }, _h$9$1);
1613
2397
  playback.current = {
1614
2398
  transition,
1615
2399
  reduced
1616
2400
  };
1617
- const returning = useRef(null, _h$9);
1618
- const member = useRef(null, _h$10);
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
- 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);
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
- ...latest.current.animate
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$11);
1638
- const stableBind = useRef((host) => bind.current(host), _h$12).current;
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$13);
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$14);
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
- let active = true;
1657
- const skip = firstAnimation.current && props.initial === false;
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 (props.animate && !skip) current.controller.animate(props.animate, transition, reduced).then((result) => {
1661
- if (active && result === "finished") latest.current.onAnimationComplete?.();
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
- active = false;
1665
- current.controller.stop();
2508
+ if (!inherits) node.stop();
1666
2509
  };
1667
2510
  }, [
1668
- JSON.stringify(props.animate),
1669
- JSON.stringify(props.exit),
2511
+ JSON.stringify(resolvedAnimate),
2512
+ JSON.stringify(resolvedExit),
2513
+ JSON.stringify(animateDefinition),
1670
2514
  JSON.stringify(transition),
1671
- reduced
1672
- ], _h$15);
1673
- const { initial, exit, animate, transition: ignoredTransition, onAnimationComplete, style: ignoredStyle, bind: ignoredBind, ...rest } = props;
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
- ...rest,
1676
- style,
1677
- bind: stableBind
2520
+ hostProps: {
2521
+ ...rest,
2522
+ style,
2523
+ ref: [hostRef, props.ref]
2524
+ },
2525
+ node
1678
2526
  };
1679
2527
  }
1680
- var MotionView = function MotionView(props, __s, __extra) {
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
- 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);
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
- 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;
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
- 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");
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
- function __children$4(__props, __s, __extra) {
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
- 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;
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
- 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");
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
- function __children$7(__props, __s, __extra) {
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
- 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;
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
- 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");
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(8);
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 };