@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/native/index.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { createContext, defineUniversalComponent, hookSlots, universalChildren, universalComponent, universalContext, universalIf, universalPlan, universalProps, universalValue, useContext, useEffect, useLayoutEffect, useRef, useState, withSlot } from "@nativescript-community/octane";
|
|
2
|
-
import {
|
|
3
|
-
import { Application, Utils } from "@nativescript/core";
|
|
2
|
+
import { HStack, Pressable, View } from "@octane-xplat/ui";
|
|
3
|
+
import { Application, Device, Utils } from "@nativescript/core";
|
|
4
4
|
import { cancelAnimationFrame, requestAnimationFrame } from "@nativescript/core/animation-frame";
|
|
5
|
+
import { GestureHandlerStateEvent, GestureHandlerTouchEvent, GestureState, HandlerType, Manager } from "@nativescript-community/gesturehandler";
|
|
5
6
|
//#region src/reduced-motion.ts
|
|
6
7
|
function readReducedMotion() {
|
|
7
8
|
const platform = globalThis;
|
|
8
9
|
if (Application.ios) return Boolean(platform.UIAccessibilityIsReduceMotionEnabled?.());
|
|
10
|
+
if (!platform.android) return false;
|
|
11
|
+
if (Number(Device.sdkVersion) >= 26 && platform.android.animation?.ValueAnimator?.areAnimatorsEnabled?.() === false) return true;
|
|
9
12
|
const context = Utils.android.getApplicationContext();
|
|
10
13
|
return platform.android.provider.Settings.Global.getFloat(context.getContentResolver(), "animator_duration_scale", 1) === 0;
|
|
11
14
|
}
|
|
12
15
|
function observeReducedMotion(notify) {
|
|
16
|
+
if (Application.ios) {
|
|
17
|
+
const name = globalThis.UIAccessibilityReduceMotionStatusDidChangeNotification;
|
|
18
|
+
const observer = Application.ios.addNotificationObserver(name, notify);
|
|
19
|
+
return () => Application.ios.removeNotificationObserver(observer, name);
|
|
20
|
+
}
|
|
13
21
|
let previous = readReducedMotion();
|
|
14
22
|
const check = () => {
|
|
15
23
|
const next = readReducedMotion();
|
|
@@ -165,12 +173,12 @@ var Presence = defineUniversalComponent("nativescript", function Presence(props)
|
|
|
165
173
|
const [retained, setRetained] = useState(props.present, _h$0$2);
|
|
166
174
|
const latest = useRef(props, _h$1$2);
|
|
167
175
|
latest.current = props;
|
|
168
|
-
const
|
|
169
|
-
if (!
|
|
176
|
+
const stateRef = useRef(null, _h$2$2);
|
|
177
|
+
if (!stateRef.current) stateRef.current = new PresenceState(props.present, () => {
|
|
170
178
|
setRetained(false);
|
|
171
179
|
latest.current.onExitComplete?.();
|
|
172
180
|
});
|
|
173
|
-
const state =
|
|
181
|
+
const state = stateRef.current;
|
|
174
182
|
const host = useRef(null, _h$3$2);
|
|
175
183
|
const restoreInput = useRef(null, _h$4$2);
|
|
176
184
|
const syncInput = () => {
|
|
@@ -191,59 +199,208 @@ var Presence = defineUniversalComponent("nativescript", function Presence(props)
|
|
|
191
199
|
restoreInput.current = null;
|
|
192
200
|
host.current = null;
|
|
193
201
|
}, [], _h$6$2);
|
|
194
|
-
const { present, onExitComplete, children,
|
|
202
|
+
const { present, onExitComplete, children, ref, ...viewProps } = props;
|
|
195
203
|
return universalValue(__octaneUniversalPlan2$1, [universalIf(props.present || retained, () => {
|
|
196
204
|
return universalValue(__octaneUniversalPlan1$1, [universalComponent("nativescript", View, universalProps([["spread", viewProps], [
|
|
197
205
|
"set",
|
|
198
|
-
"
|
|
199
|
-
(node) => {
|
|
206
|
+
"ref",
|
|
207
|
+
[(node) => {
|
|
200
208
|
if (host.current !== node) {
|
|
201
209
|
restoreInput.current?.();
|
|
202
210
|
restoreInput.current = null;
|
|
203
211
|
host.current = node;
|
|
204
212
|
}
|
|
205
213
|
syncInput();
|
|
206
|
-
|
|
207
|
-
}
|
|
214
|
+
}, ref]
|
|
208
215
|
]], universalChildren("nativescript", () => {
|
|
209
216
|
return universalValue(__octaneUniversalPlan0$1, [((__octaneContextProps) => universalContext(PresenceContext, __octaneContextProps.value, children))({ "value": state })]);
|
|
210
217
|
})))]);
|
|
211
218
|
})]);
|
|
212
219
|
}, { "module": "@nativescript-community/octane" });
|
|
213
220
|
//#endregion
|
|
221
|
+
//#region src/drag.ts
|
|
222
|
+
function validateDrag(props) {
|
|
223
|
+
if (props.drag !== void 0 && ![
|
|
224
|
+
true,
|
|
225
|
+
false,
|
|
226
|
+
"x",
|
|
227
|
+
"y"
|
|
228
|
+
].includes(props.drag)) throw new Error("motion: drag must be boolean, x, or y");
|
|
229
|
+
const bounds = props.dragConstraints ?? {};
|
|
230
|
+
for (const [key, value] of Object.entries(bounds)) if (![
|
|
231
|
+
"left",
|
|
232
|
+
"right",
|
|
233
|
+
"top",
|
|
234
|
+
"bottom"
|
|
235
|
+
].includes(key) || !Number.isFinite(value)) throw new Error("motion: dragConstraints requires finite numeric edges; refs are deferred");
|
|
236
|
+
if ((bounds.left ?? -Infinity) > (bounds.right ?? Infinity) || (bounds.top ?? -Infinity) > (bounds.bottom ?? Infinity)) throw new Error("motion: dragConstraints edges are reversed");
|
|
237
|
+
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");
|
|
238
|
+
if (props.drag) for (const axis of ["x", "y"]) {
|
|
239
|
+
if (props.drag !== true && props.drag !== axis) continue;
|
|
240
|
+
for (const target of [
|
|
241
|
+
props.animate,
|
|
242
|
+
props.whileTap,
|
|
243
|
+
props.whileFocus
|
|
244
|
+
]) if (target && typeof target === "object" && !Array.isArray(target) && target[axis] !== void 0) throw new Error(`motion: drag and animation both own ${axis}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
var clamp$1 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
248
|
+
/** Gesture writes and release springs bypass host delegation. */
|
|
249
|
+
function attachDrag(adapter, controller, props, valueFor, reduced, callbacks) {
|
|
250
|
+
if (!props.drag) return () => {};
|
|
251
|
+
if (!adapter.pan) throw new Error("motion: this host does not support drag");
|
|
252
|
+
const axes = ["x", "y"].filter((axis) => props.drag === true || props.drag === axis);
|
|
253
|
+
const values = new Map(axes.map((axis) => [axis, valueFor(axis)]));
|
|
254
|
+
const value = (axis) => values.get(axis);
|
|
255
|
+
const bounds = props.dragConstraints ?? {};
|
|
256
|
+
const elastic = typeof props.dragElastic === "number" ? props.dragElastic : props.dragElastic === false ? 0 : .35;
|
|
257
|
+
const origin = {
|
|
258
|
+
x: 0,
|
|
259
|
+
y: 0
|
|
260
|
+
};
|
|
261
|
+
let active = false;
|
|
262
|
+
const limits = (axis) => axis === "x" ? [bounds.left ?? -Infinity, bounds.right ?? Infinity] : [bounds.top ?? -Infinity, bounds.bottom ?? Infinity];
|
|
263
|
+
const move = (info) => {
|
|
264
|
+
for (const axis of axes) {
|
|
265
|
+
const [min, max] = limits(axis);
|
|
266
|
+
const next = origin[axis] + info.offset[axis];
|
|
267
|
+
const bounded = clamp$1(next, min, max);
|
|
268
|
+
value(axis).jump(bounded + (next - bounded) * elastic);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
const off = adapter.pan(props.drag, {
|
|
272
|
+
start(event, info) {
|
|
273
|
+
controller.stop();
|
|
274
|
+
active = true;
|
|
275
|
+
for (const axis of axes) {
|
|
276
|
+
const channel = value(axis);
|
|
277
|
+
channel.stop();
|
|
278
|
+
origin[axis] = channel.get();
|
|
279
|
+
}
|
|
280
|
+
callbacks().onDragStart?.(event, info);
|
|
281
|
+
},
|
|
282
|
+
move(event, info) {
|
|
283
|
+
if (!active) return;
|
|
284
|
+
move(info);
|
|
285
|
+
callbacks().onDrag?.(event, info);
|
|
286
|
+
},
|
|
287
|
+
end(event, info) {
|
|
288
|
+
if (!active) return;
|
|
289
|
+
active = false;
|
|
290
|
+
move(info);
|
|
291
|
+
for (const axis of axes) {
|
|
292
|
+
const channel = value(axis);
|
|
293
|
+
const velocity = info.cancelled || props.dragMomentum === false ? 0 : info.velocity[axis];
|
|
294
|
+
const [min, max] = limits(axis);
|
|
295
|
+
const target = clamp$1(channel.get() + velocity * .2, min, max);
|
|
296
|
+
if (elastic === 0) channel.jump(clamp$1(channel.get(), min, max));
|
|
297
|
+
if (reduced()) channel.jump(target);
|
|
298
|
+
else if (target !== channel.get() || velocity !== 0) channel.animate(target, {
|
|
299
|
+
type: "spring",
|
|
300
|
+
stiffness: 200,
|
|
301
|
+
damping: 30,
|
|
302
|
+
velocity
|
|
303
|
+
}, elastic === 0 ? (next) => clamp$1(next, min, max) : void 0);
|
|
304
|
+
}
|
|
305
|
+
callbacks().onDragEnd?.(event, info);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
return () => {
|
|
309
|
+
active = false;
|
|
310
|
+
off();
|
|
311
|
+
for (const channel of values.values()) channel.stop();
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
//#endregion
|
|
214
315
|
//#region src/clock.ts
|
|
316
|
+
var platform$1 = globalThis;
|
|
215
317
|
var clock = {
|
|
216
|
-
now: () => Date.now(),
|
|
318
|
+
now: Application.ios ? platform$1.CACurrentMediaTime ? () => platform$1.CACurrentMediaTime() * 1e3 : platform$1.__time ?? Date.now : platform$1.java?.lang?.System ? () => platform$1.java.lang.System.nanoTime() / 1e6 : Date.now,
|
|
217
319
|
request: requestAnimationFrame,
|
|
218
320
|
cancel: cancelAnimationFrame
|
|
219
321
|
};
|
|
220
322
|
//#endregion
|
|
221
|
-
//#region src/
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
323
|
+
//#region src/pan.ts
|
|
324
|
+
var tag = 7e8;
|
|
325
|
+
function attachPan(node, axis, callbacks) {
|
|
326
|
+
const androidHost = Boolean(globalThis.android);
|
|
327
|
+
const slop = androidHost ? Utils.layout.toDevicePixels(8) : 8;
|
|
328
|
+
const handler = Manager.getInstance().createGestureHandler(HandlerType.PAN, tag++, {
|
|
329
|
+
shouldCancelWhenOutside: false,
|
|
330
|
+
...androidHost && axis !== true ? { minDist: 1e9 } : {},
|
|
331
|
+
...axis === true ? { minDist: slop } : axis === "x" ? {
|
|
332
|
+
activeOffsetXStart: -slop,
|
|
333
|
+
activeOffsetXEnd: slop,
|
|
334
|
+
failOffsetYStart: -slop,
|
|
335
|
+
failOffsetYEnd: slop
|
|
336
|
+
} : {
|
|
337
|
+
activeOffsetYStart: -slop,
|
|
338
|
+
activeOffsetYEnd: slop,
|
|
339
|
+
failOffsetXStart: -slop,
|
|
340
|
+
failOffsetXEnd: slop
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
let active = false;
|
|
344
|
+
let last = {
|
|
345
|
+
x: 0,
|
|
346
|
+
y: 0
|
|
230
347
|
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
348
|
+
const sample = (args, cancelled = false) => {
|
|
349
|
+
const extra = args.data.extraData ?? {};
|
|
350
|
+
const offset = {
|
|
351
|
+
x: extra.translationX ?? last.x,
|
|
352
|
+
y: extra.translationY ?? last.y
|
|
353
|
+
};
|
|
354
|
+
const delta = {
|
|
355
|
+
x: offset.x - last.x,
|
|
356
|
+
y: offset.y - last.y
|
|
357
|
+
};
|
|
358
|
+
last = offset;
|
|
359
|
+
return {
|
|
360
|
+
point: {
|
|
361
|
+
x: extra.absoluteX ?? extra.x ?? 0,
|
|
362
|
+
y: extra.absoluteY ?? extra.y ?? 0
|
|
363
|
+
},
|
|
364
|
+
delta,
|
|
365
|
+
offset,
|
|
366
|
+
velocity: {
|
|
367
|
+
x: extra.velocityX ?? 0,
|
|
368
|
+
y: extra.velocityY ?? 0
|
|
369
|
+
},
|
|
370
|
+
cancelled
|
|
371
|
+
};
|
|
239
372
|
};
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
373
|
+
const state = (args) => {
|
|
374
|
+
const next = args.data.state;
|
|
375
|
+
if (next === GestureState.ACTIVE && !active) {
|
|
376
|
+
last = {
|
|
377
|
+
x: 0,
|
|
378
|
+
y: 0
|
|
379
|
+
};
|
|
380
|
+
active = true;
|
|
381
|
+
const info = sample(args);
|
|
382
|
+
callbacks.start(args, info);
|
|
383
|
+
callbacks.move(args, info);
|
|
384
|
+
} else if (active && [
|
|
385
|
+
GestureState.END,
|
|
386
|
+
GestureState.CANCELLED,
|
|
387
|
+
GestureState.FAILED
|
|
388
|
+
].includes(next)) {
|
|
389
|
+
active = false;
|
|
390
|
+
callbacks.end(args, sample(args, next !== GestureState.END));
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
const touch = (args) => {
|
|
394
|
+
if (active && args.data.state === GestureState.ACTIVE) callbacks.move(args, sample(args));
|
|
395
|
+
};
|
|
396
|
+
handler.on(GestureHandlerStateEvent, state);
|
|
397
|
+
handler.on(GestureHandlerTouchEvent, touch);
|
|
398
|
+
handler.attachToView(node);
|
|
399
|
+
return () => {
|
|
400
|
+
active = false;
|
|
401
|
+
handler.off(GestureHandlerStateEvent, state);
|
|
402
|
+
handler.off(GestureHandlerTouchEvent, touch);
|
|
403
|
+
handler.detachFromView(node);
|
|
247
404
|
};
|
|
248
405
|
}
|
|
249
406
|
//#endregion
|
|
@@ -1185,13 +1342,79 @@ function keyframes({ duration = 300, keyframes: keyframeValues, times, ease = "e
|
|
|
1185
1342
|
}
|
|
1186
1343
|
//#endregion
|
|
1187
1344
|
//#region src/engine.ts
|
|
1345
|
+
var MOTION_KEYS = [
|
|
1346
|
+
"opacity",
|
|
1347
|
+
"x",
|
|
1348
|
+
"y",
|
|
1349
|
+
"scale",
|
|
1350
|
+
"scaleX",
|
|
1351
|
+
"scaleY",
|
|
1352
|
+
"rotate"
|
|
1353
|
+
];
|
|
1354
|
+
/** Platform animators take one timing curve per run — cubic-bezier only. */
|
|
1355
|
+
var BEZIER_EASES = /* @__PURE__ */ new Set([
|
|
1356
|
+
"linear",
|
|
1357
|
+
"easeIn",
|
|
1358
|
+
"easeOut",
|
|
1359
|
+
"easeInOut"
|
|
1360
|
+
]);
|
|
1361
|
+
function isBezierEase(ease) {
|
|
1362
|
+
return ease === void 0 || Array.isArray(ease) || BEZIER_EASES.has(ease);
|
|
1363
|
+
}
|
|
1364
|
+
var BEZIER_POINTS = {
|
|
1365
|
+
linear: [
|
|
1366
|
+
0,
|
|
1367
|
+
0,
|
|
1368
|
+
1,
|
|
1369
|
+
1
|
|
1370
|
+
],
|
|
1371
|
+
easeIn: [
|
|
1372
|
+
.42,
|
|
1373
|
+
0,
|
|
1374
|
+
1,
|
|
1375
|
+
1
|
|
1376
|
+
],
|
|
1377
|
+
easeOut: [
|
|
1378
|
+
0,
|
|
1379
|
+
0,
|
|
1380
|
+
.58,
|
|
1381
|
+
1
|
|
1382
|
+
],
|
|
1383
|
+
easeInOut: [
|
|
1384
|
+
.42,
|
|
1385
|
+
0,
|
|
1386
|
+
.58,
|
|
1387
|
+
1
|
|
1388
|
+
]
|
|
1389
|
+
};
|
|
1390
|
+
/** CSS cubic-bezier control points for a delegatable ease; tuples pass through. */
|
|
1391
|
+
function bezierPoints(ease) {
|
|
1392
|
+
return Array.isArray(ease) ? ease : BEZIER_POINTS[ease ?? "easeInOut"];
|
|
1393
|
+
}
|
|
1394
|
+
function isOrchestrated(t) {
|
|
1395
|
+
if (!t || typeof t !== "object") return false;
|
|
1396
|
+
return "default" in t || MOTION_KEYS.some((key) => key in t);
|
|
1397
|
+
}
|
|
1398
|
+
function resolveTransition(t, key) {
|
|
1399
|
+
return isOrchestrated(t) ? {
|
|
1400
|
+
...t.default,
|
|
1401
|
+
...t[key]
|
|
1402
|
+
} : t;
|
|
1403
|
+
}
|
|
1188
1404
|
function validateTransition(t) {
|
|
1189
|
-
if (t.type === "spring" &&
|
|
1405
|
+
if (t.type === "spring" && t.ease !== void 0) throw new Error("motion: physical springs do not accept ease");
|
|
1190
1406
|
const allowed = [
|
|
1407
|
+
"staggerChildren",
|
|
1408
|
+
"delayChildren",
|
|
1409
|
+
"when",
|
|
1191
1410
|
"type",
|
|
1192
1411
|
"duration",
|
|
1193
1412
|
"delay",
|
|
1194
1413
|
"ease",
|
|
1414
|
+
"repeat",
|
|
1415
|
+
"repeatType",
|
|
1416
|
+
"repeatDelay",
|
|
1417
|
+
"bounce",
|
|
1195
1418
|
"stiffness",
|
|
1196
1419
|
"damping",
|
|
1197
1420
|
"mass",
|
|
@@ -1200,10 +1423,15 @@ function validateTransition(t) {
|
|
|
1200
1423
|
"restDelta"
|
|
1201
1424
|
];
|
|
1202
1425
|
for (const key of Object.keys(t)) if (!allowed.includes(key)) throw new Error(`motion: unsupported transition ${key}`);
|
|
1426
|
+
if (t.when !== void 0 && !["beforeChildren", "afterChildren"].includes(t.when)) throw new Error("motion: unsupported when");
|
|
1203
1427
|
if (t.type !== void 0 && t.type !== "tween" && t.type !== "spring") throw new Error("motion: unsupported transition type");
|
|
1204
1428
|
for (const key of [
|
|
1429
|
+
"staggerChildren",
|
|
1430
|
+
"delayChildren",
|
|
1205
1431
|
"duration",
|
|
1206
1432
|
"delay",
|
|
1433
|
+
"repeatDelay",
|
|
1434
|
+
"bounce",
|
|
1207
1435
|
"stiffness",
|
|
1208
1436
|
"damping",
|
|
1209
1437
|
"mass",
|
|
@@ -1214,6 +1442,12 @@ function validateTransition(t) {
|
|
|
1214
1442
|
const value = t[key];
|
|
1215
1443
|
if (value !== void 0 && (!Number.isFinite(value) || key !== "velocity" && value < 0)) throw new Error(`motion: invalid ${key}`);
|
|
1216
1444
|
}
|
|
1445
|
+
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");
|
|
1446
|
+
if (t.repeatType !== void 0 && ![
|
|
1447
|
+
"loop",
|
|
1448
|
+
"reverse",
|
|
1449
|
+
"mirror"
|
|
1450
|
+
].includes(t.repeatType)) throw new Error("motion: unsupported repeatType");
|
|
1217
1451
|
for (const key of [
|
|
1218
1452
|
"mass",
|
|
1219
1453
|
"stiffness",
|
|
@@ -1228,10 +1462,31 @@ function validateTransition(t) {
|
|
|
1228
1462
|
"linear",
|
|
1229
1463
|
"easeIn",
|
|
1230
1464
|
"easeOut",
|
|
1231
|
-
"easeInOut"
|
|
1465
|
+
"easeInOut",
|
|
1466
|
+
"circIn",
|
|
1467
|
+
"circOut",
|
|
1468
|
+
"circInOut",
|
|
1469
|
+
"backIn",
|
|
1470
|
+
"backOut",
|
|
1471
|
+
"backInOut",
|
|
1472
|
+
"anticipate"
|
|
1232
1473
|
].includes(t.ease)) throw new Error("motion: unsupported easing");
|
|
1233
1474
|
}
|
|
1234
1475
|
}
|
|
1476
|
+
function validateTransitionInput(t) {
|
|
1477
|
+
if (isOrchestrated(t)) {
|
|
1478
|
+
const { staggerChildren, delayChildren, when, ...channels } = t;
|
|
1479
|
+
validateTransition({
|
|
1480
|
+
staggerChildren,
|
|
1481
|
+
delayChildren,
|
|
1482
|
+
when
|
|
1483
|
+
});
|
|
1484
|
+
for (const [key, value] of Object.entries(channels)) {
|
|
1485
|
+
if (key !== "default" && !MOTION_KEYS.includes(key)) throw new Error(`motion: unsupported transition ${key}`);
|
|
1486
|
+
if (value) validateTransition(value);
|
|
1487
|
+
}
|
|
1488
|
+
} else validateTransition(t);
|
|
1489
|
+
}
|
|
1235
1490
|
function runAnimation(clock, from, to, transition, update, complete) {
|
|
1236
1491
|
validateTransition(transition);
|
|
1237
1492
|
let frame = 0;
|
|
@@ -1248,34 +1503,53 @@ function runAnimation(clock, from, to, transition, update, complete) {
|
|
|
1248
1503
|
if (result === "finished") complete?.();
|
|
1249
1504
|
};
|
|
1250
1505
|
const duration = transition.duration ?? .3;
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1506
|
+
const repeat = transition.repeat ?? 0;
|
|
1507
|
+
const repeatType = transition.repeatType ?? "loop";
|
|
1508
|
+
const repeatDelay = (transition.repeatDelay ?? 0) * 1e3;
|
|
1509
|
+
const makeGenerator = (legFrom, legTo) => transition.type === "spring" ? spring({
|
|
1510
|
+
keyframes: [legFrom, legTo],
|
|
1253
1511
|
stiffness: transition.stiffness ?? 100,
|
|
1254
1512
|
damping: transition.damping ?? 10,
|
|
1255
1513
|
mass: transition.mass ?? 1,
|
|
1256
1514
|
velocity: transition.velocity ?? 0,
|
|
1257
1515
|
restSpeed: transition.restSpeed,
|
|
1258
|
-
restDelta: transition.restDelta
|
|
1516
|
+
restDelta: transition.restDelta,
|
|
1517
|
+
duration: transition.duration !== void 0 ? duration * 1e3 : void 0,
|
|
1518
|
+
bounce: transition.bounce
|
|
1259
1519
|
}) : keyframes({
|
|
1260
|
-
keyframes: [
|
|
1520
|
+
keyframes: [legFrom, legTo],
|
|
1261
1521
|
duration: duration * 1e3,
|
|
1262
1522
|
ease: transition.ease ?? "easeInOut"
|
|
1263
1523
|
});
|
|
1264
|
-
|
|
1524
|
+
let leg = 0;
|
|
1525
|
+
let generator = makeGenerator(from, to);
|
|
1526
|
+
let legStart = clock.now() + (transition.delay ?? 0) * 1e3;
|
|
1265
1527
|
const tick = () => {
|
|
1266
1528
|
if (settled) return;
|
|
1267
|
-
const
|
|
1268
|
-
if (
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1529
|
+
const now = clock.now();
|
|
1530
|
+
if (now < legStart) {
|
|
1531
|
+
frame = clock.request(tick);
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
const elapsed = Math.max(0, now - legStart);
|
|
1535
|
+
const state = generator.next(elapsed);
|
|
1536
|
+
const legEnd = repeatType === "loop" || leg % 2 === 0 ? to : from;
|
|
1537
|
+
update(state.done ? legEnd : state.value);
|
|
1538
|
+
if (state.done) {
|
|
1539
|
+
if (leg < repeat) {
|
|
1540
|
+
leg++;
|
|
1541
|
+
const [legFrom, legTo] = repeatType === "loop" || leg % 2 === 0 ? [from, to] : [to, from];
|
|
1542
|
+
generator = makeGenerator(legFrom, legTo);
|
|
1543
|
+
legStart = now + repeatDelay;
|
|
1544
|
+
frame = clock.request(tick);
|
|
1273
1545
|
return;
|
|
1274
1546
|
}
|
|
1547
|
+
settle("finished");
|
|
1548
|
+
return;
|
|
1275
1549
|
}
|
|
1276
1550
|
if (!settled) frame = clock.request(tick);
|
|
1277
1551
|
};
|
|
1278
|
-
if (transition.type !== "spring" && duration === 0 && !transition.delay) {
|
|
1552
|
+
if (transition.type !== "spring" && duration === 0 && !transition.delay && repeat === 0) {
|
|
1279
1553
|
update(to);
|
|
1280
1554
|
settle("finished");
|
|
1281
1555
|
} else frame = clock.request(tick);
|
|
@@ -1285,6 +1559,214 @@ function runAnimation(clock, from, to, transition, update, complete) {
|
|
|
1285
1559
|
};
|
|
1286
1560
|
}
|
|
1287
1561
|
//#endregion
|
|
1562
|
+
//#region src/delegation.ts
|
|
1563
|
+
function delegationStats() {
|
|
1564
|
+
const platform = globalThis;
|
|
1565
|
+
return platform.__xplatMotionDelegations ??= {
|
|
1566
|
+
started: 0,
|
|
1567
|
+
finished: 0,
|
|
1568
|
+
cancelled: 0,
|
|
1569
|
+
fallback: 0
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
/** Count a delegated run and fold its settled result into the counters. */
|
|
1573
|
+
function trackDelegatedRun(run) {
|
|
1574
|
+
delegationStats().started++;
|
|
1575
|
+
const finished = run.finished.then((result) => {
|
|
1576
|
+
if (result === "finished") delegationStats().finished++;
|
|
1577
|
+
else delegationStats().cancelled++;
|
|
1578
|
+
return result;
|
|
1579
|
+
});
|
|
1580
|
+
return {
|
|
1581
|
+
...run,
|
|
1582
|
+
finished
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
//#endregion
|
|
1586
|
+
//#region src/driver.ts
|
|
1587
|
+
var platform = globalThis;
|
|
1588
|
+
function iosRun(node, req, write) {
|
|
1589
|
+
const view = node.ios ?? node.nativeViewProtected;
|
|
1590
|
+
if (!view?.layer || !platform.UIViewPropertyAnimator) return null;
|
|
1591
|
+
const { eff, target, transition: t } = req;
|
|
1592
|
+
const [x1, y1, x2, y2] = bezierPoints(t.ease);
|
|
1593
|
+
const params = platform.UICubicTimingParameters.alloc().initWithControlPoint1ControlPoint2(platform.CGPointMake(x1, y1), platform.CGPointMake(x2, y2));
|
|
1594
|
+
const animator = platform.UIViewPropertyAnimator.alloc().initWithDurationTimingParameters(t.duration ?? .3, params);
|
|
1595
|
+
const radians = (eff.rotate ?? 0) * Math.PI / 180;
|
|
1596
|
+
const dest = platform.CGAffineTransformScale(platform.CGAffineTransformRotate(platform.CGAffineTransformMakeTranslation(eff.x ?? 0, eff.y ?? 0), radians), eff.scaleX ?? 1, eff.scaleY ?? 1);
|
|
1597
|
+
const sample = () => {
|
|
1598
|
+
const layer = view.layer.presentationLayer?.() ?? view.layer;
|
|
1599
|
+
const tr = layer.transform;
|
|
1600
|
+
return {
|
|
1601
|
+
opacity: layer.opacity,
|
|
1602
|
+
x: tr.m41,
|
|
1603
|
+
y: tr.m42,
|
|
1604
|
+
scaleX: Math.hypot(tr.m11, tr.m12),
|
|
1605
|
+
scaleY: Math.hypot(tr.m21, tr.m22),
|
|
1606
|
+
rotate: Math.atan2(tr.m12, tr.m11) * 180 / Math.PI
|
|
1607
|
+
};
|
|
1608
|
+
};
|
|
1609
|
+
let resolve;
|
|
1610
|
+
const finished = new Promise((done) => {
|
|
1611
|
+
resolve = done;
|
|
1612
|
+
});
|
|
1613
|
+
let settled = false;
|
|
1614
|
+
const settle = (result) => {
|
|
1615
|
+
if (!settled) {
|
|
1616
|
+
settled = true;
|
|
1617
|
+
resolve(result);
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1620
|
+
animator.addAnimations(() => {
|
|
1621
|
+
if (target.x !== void 0 || target.y !== void 0 || target.rotate !== void 0 || target.scale !== void 0 || target.scaleX !== void 0 || target.scaleY !== void 0) view.transform = dest;
|
|
1622
|
+
if (target.opacity !== void 0) view.alpha = Math.min(1, Math.max(0, eff.opacity ?? target.opacity));
|
|
1623
|
+
});
|
|
1624
|
+
animator.addCompletion((position) => {
|
|
1625
|
+
if (position === 0) {
|
|
1626
|
+
write(req.dest);
|
|
1627
|
+
settle("finished");
|
|
1628
|
+
} else settle("cancelled");
|
|
1629
|
+
});
|
|
1630
|
+
if (t.delay) animator.startAnimationAfterDelay(t.delay);
|
|
1631
|
+
else animator.startAnimation();
|
|
1632
|
+
return {
|
|
1633
|
+
finished,
|
|
1634
|
+
sample,
|
|
1635
|
+
cancel() {
|
|
1636
|
+
const current = sample();
|
|
1637
|
+
animator.stopAnimation(true);
|
|
1638
|
+
write({
|
|
1639
|
+
opacity: current.opacity,
|
|
1640
|
+
x: current.x,
|
|
1641
|
+
y: current.y,
|
|
1642
|
+
scaleX: current.scaleX,
|
|
1643
|
+
scaleY: current.scaleY,
|
|
1644
|
+
rotate: current.rotate
|
|
1645
|
+
});
|
|
1646
|
+
settle("cancelled");
|
|
1647
|
+
}
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
function androidRun(node, req, write) {
|
|
1651
|
+
const view = node.nativeViewProtected ?? node.android;
|
|
1652
|
+
const android = platform.android;
|
|
1653
|
+
const androidx = platform.androidx;
|
|
1654
|
+
if (!view?.animate || !android?.animation || !androidx?.core?.view?.animation?.PathInterpolatorCompat) return null;
|
|
1655
|
+
const { eff, target, transition: t } = req;
|
|
1656
|
+
const animator = view.animate();
|
|
1657
|
+
const [x1, y1, x2, y2] = bezierPoints(t.ease);
|
|
1658
|
+
animator.setInterpolator(androidx.core.view.animation.PathInterpolatorCompat.create(x1, y1, x2, y2));
|
|
1659
|
+
animator.setDuration(Math.round((t.duration ?? .3) * 1e3));
|
|
1660
|
+
animator.setStartDelay(Math.round((t.delay ?? 0) * 1e3));
|
|
1661
|
+
if (target.x !== void 0) animator.translationX(eff.x);
|
|
1662
|
+
if (target.y !== void 0) animator.translationY(eff.y);
|
|
1663
|
+
if (target.scale !== void 0 || target.scaleX !== void 0) animator.scaleX(eff.scaleX);
|
|
1664
|
+
if (target.scale !== void 0 || target.scaleY !== void 0) animator.scaleY(eff.scaleY);
|
|
1665
|
+
if (target.rotate !== void 0) animator.rotation(eff.rotate);
|
|
1666
|
+
if (target.opacity !== void 0) animator.alpha(Math.min(1, Math.max(0, eff.opacity ?? target.opacity)));
|
|
1667
|
+
let resolve;
|
|
1668
|
+
const finished = new Promise((done) => {
|
|
1669
|
+
resolve = done;
|
|
1670
|
+
});
|
|
1671
|
+
let settled = false;
|
|
1672
|
+
const settle = (result) => {
|
|
1673
|
+
if (!settled) {
|
|
1674
|
+
settled = true;
|
|
1675
|
+
resolve(result);
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1678
|
+
let cancelled = false;
|
|
1679
|
+
animator.setListener(new android.animation.Animator.AnimatorListener({
|
|
1680
|
+
onAnimationCancel() {
|
|
1681
|
+
cancelled = true;
|
|
1682
|
+
settle("cancelled");
|
|
1683
|
+
},
|
|
1684
|
+
onAnimationEnd() {
|
|
1685
|
+
if (!cancelled) write(req.dest);
|
|
1686
|
+
settle(cancelled ? "cancelled" : "finished");
|
|
1687
|
+
},
|
|
1688
|
+
onAnimationStart() {},
|
|
1689
|
+
onAnimationRepeat() {}
|
|
1690
|
+
}));
|
|
1691
|
+
animator.start();
|
|
1692
|
+
return {
|
|
1693
|
+
finished,
|
|
1694
|
+
sample: () => ({
|
|
1695
|
+
opacity: view.getAlpha(),
|
|
1696
|
+
x: view.getTranslationX(),
|
|
1697
|
+
y: view.getTranslationY(),
|
|
1698
|
+
scaleX: view.getScaleX(),
|
|
1699
|
+
scaleY: view.getScaleY(),
|
|
1700
|
+
rotate: view.getRotation()
|
|
1701
|
+
}),
|
|
1702
|
+
cancel() {
|
|
1703
|
+
animator.cancel();
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
function delegatedRun(node, req, write) {
|
|
1708
|
+
if (!isBezierEase(req.transition.ease)) {
|
|
1709
|
+
delegationStats().fallback++;
|
|
1710
|
+
return null;
|
|
1711
|
+
}
|
|
1712
|
+
const run = node.ios && platform.UIViewPropertyAnimator ? iosRun(node, req, write) : platform.android?.animation && (node.nativeViewProtected ?? node.android) ? androidRun(node, req, write) : null;
|
|
1713
|
+
if (!run) {
|
|
1714
|
+
delegationStats().fallback++;
|
|
1715
|
+
return null;
|
|
1716
|
+
}
|
|
1717
|
+
return trackDelegatedRun(run);
|
|
1718
|
+
}
|
|
1719
|
+
//#endregion
|
|
1720
|
+
//#region src/host.ts
|
|
1721
|
+
function attachHost(node) {
|
|
1722
|
+
const original = {
|
|
1723
|
+
opacity: node.opacity ?? 1,
|
|
1724
|
+
x: node.translateX ?? 0,
|
|
1725
|
+
y: node.translateY ?? 0,
|
|
1726
|
+
scaleX: node.scaleX ?? 1,
|
|
1727
|
+
scaleY: node.scaleY ?? 1,
|
|
1728
|
+
rotate: node.rotate ?? 0
|
|
1729
|
+
};
|
|
1730
|
+
if (original.x || original.y || original.rotate || original.scaleX !== 1 || original.scaleY !== 1) throw new Error("motion: put existing transforms on an outer container");
|
|
1731
|
+
const write = (values) => {
|
|
1732
|
+
if (values.opacity !== void 0) node.opacity = Math.min(1, Math.max(0, values.opacity));
|
|
1733
|
+
if (values.x !== void 0) node.translateX = values.x;
|
|
1734
|
+
if (values.y !== void 0) node.translateY = values.y;
|
|
1735
|
+
if (values.rotate !== void 0) node.rotate = values.rotate;
|
|
1736
|
+
if (values.scale !== void 0 || values.scaleX !== void 0) node.scaleX = (values.scale ?? 1) * (values.scaleX ?? 1);
|
|
1737
|
+
if (values.scale !== void 0 || values.scaleY !== void 0) node.scaleY = (values.scale ?? 1) * (values.scaleY ?? 1);
|
|
1738
|
+
};
|
|
1739
|
+
return {
|
|
1740
|
+
pan: (axis, callbacks) => attachPan(node, axis, callbacks),
|
|
1741
|
+
read: () => ({
|
|
1742
|
+
...original,
|
|
1743
|
+
scale: 1
|
|
1744
|
+
}),
|
|
1745
|
+
write,
|
|
1746
|
+
restore: () => write(original),
|
|
1747
|
+
delegate: (req) => delegatedRun(node, req, write),
|
|
1748
|
+
gesture(kind, callbacks) {
|
|
1749
|
+
if (typeof node.on !== "function" || typeof node.off !== "function") return null;
|
|
1750
|
+
if (kind === "press") {
|
|
1751
|
+
const onTouch = (event) => {
|
|
1752
|
+
if (event.action === "down") callbacks.start();
|
|
1753
|
+
else if (event.action === "up" || event.action === "cancel") callbacks.end();
|
|
1754
|
+
};
|
|
1755
|
+
node.on("touch", onTouch);
|
|
1756
|
+
return () => node.off("touch", onTouch);
|
|
1757
|
+
}
|
|
1758
|
+
const onFocus = () => callbacks.start();
|
|
1759
|
+
const onBlur = () => callbacks.end();
|
|
1760
|
+
node.on("focus", onFocus);
|
|
1761
|
+
node.on("blur", onBlur);
|
|
1762
|
+
return () => {
|
|
1763
|
+
node.off("focus", onFocus);
|
|
1764
|
+
node.off("blur", onBlur);
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1769
|
+
//#endregion
|
|
1288
1770
|
//#region src/value.ts
|
|
1289
1771
|
/** Numeric value with direct subscriptions; it does not subscribe Octane renders. */
|
|
1290
1772
|
var MotionValue = class {
|
|
@@ -1349,6 +1831,13 @@ var MotionValue = class {
|
|
|
1349
1831
|
for (const callback of [...this.listeners.get(event) ?? []]) callback(value);
|
|
1350
1832
|
}
|
|
1351
1833
|
write(value) {
|
|
1834
|
+
this.track(value);
|
|
1835
|
+
if (!this.disposed && value !== this.previous) this.emit("change", value);
|
|
1836
|
+
}
|
|
1837
|
+
/** Update position bookkeeping without emitting — platform-delegated runs
|
|
1838
|
+
* track presentation state so interruption reads fresh value/velocity. */
|
|
1839
|
+
track(value) {
|
|
1840
|
+
this.assert(value);
|
|
1352
1841
|
if (this.disposed) return;
|
|
1353
1842
|
const now = this.clock.now();
|
|
1354
1843
|
const elapsed = now - this.updated;
|
|
@@ -1356,10 +1845,9 @@ var MotionValue = class {
|
|
|
1356
1845
|
this.previous = this.current;
|
|
1357
1846
|
this.current = value;
|
|
1358
1847
|
this.updated = now;
|
|
1359
|
-
if (value !== this.previous) this.emit("change", value);
|
|
1360
1848
|
}
|
|
1361
1849
|
/** Animate to a destination. New playback replaces old playback. */
|
|
1362
|
-
animate(target, transition = {}) {
|
|
1850
|
+
animate(target, transition = {}, clampSample) {
|
|
1363
1851
|
this.assert(target);
|
|
1364
1852
|
validateTransition(transition);
|
|
1365
1853
|
if (this.disposed) return {
|
|
@@ -1373,7 +1861,7 @@ var MotionValue = class {
|
|
|
1373
1861
|
const controls = runAnimation(this.clock, this.current, target, {
|
|
1374
1862
|
...transition,
|
|
1375
1863
|
velocity
|
|
1376
|
-
}, (value) => this.write(value));
|
|
1864
|
+
}, (value) => this.write(clampSample ? clampSample(value) : value));
|
|
1377
1865
|
this.controls = controls;
|
|
1378
1866
|
controls.finished.then((result) => {
|
|
1379
1867
|
if (generation !== this.generation || this.disposed) return;
|
|
@@ -1434,7 +1922,10 @@ function validateTarget(target) {
|
|
|
1434
1922
|
var Controller = class {
|
|
1435
1923
|
clock;
|
|
1436
1924
|
values = /* @__PURE__ */ new Map();
|
|
1437
|
-
write
|
|
1925
|
+
/** Per-write snapshot callback (rAF-rate during delegated and JS runs). */
|
|
1926
|
+
onUpdate;
|
|
1927
|
+
adapter;
|
|
1928
|
+
delegated;
|
|
1438
1929
|
generation = 0;
|
|
1439
1930
|
constructor(clock) {
|
|
1440
1931
|
this.clock = clock;
|
|
@@ -1448,15 +1939,24 @@ var Controller = class {
|
|
|
1448
1939
|
}
|
|
1449
1940
|
return value;
|
|
1450
1941
|
}
|
|
1451
|
-
attach(
|
|
1452
|
-
this.
|
|
1942
|
+
attach(adapter) {
|
|
1943
|
+
this.adapter = adapter;
|
|
1453
1944
|
this.flush();
|
|
1454
1945
|
}
|
|
1946
|
+
cancelDelegated() {
|
|
1947
|
+
if (!this.delegated) return;
|
|
1948
|
+
this.clock.cancel(this.delegated.frame);
|
|
1949
|
+
this.delegated.trackSample();
|
|
1950
|
+
this.delegated.run.cancel();
|
|
1951
|
+
this.delegated = void 0;
|
|
1952
|
+
}
|
|
1455
1953
|
snapshot() {
|
|
1456
1954
|
return Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()]));
|
|
1457
1955
|
}
|
|
1458
1956
|
flush() {
|
|
1459
|
-
|
|
1957
|
+
const snapshot = Object.fromEntries([...this.values].map(([key, value]) => [key, value.get()]));
|
|
1958
|
+
this.adapter?.write(snapshot);
|
|
1959
|
+
this.onUpdate?.(snapshot);
|
|
1460
1960
|
}
|
|
1461
1961
|
set(key, next) {
|
|
1462
1962
|
this.value(key).jump(next);
|
|
@@ -1468,9 +1968,65 @@ var Controller = class {
|
|
|
1468
1968
|
async animate(target, transition, reduced) {
|
|
1469
1969
|
validateTarget(target);
|
|
1470
1970
|
const generation = ++this.generation;
|
|
1971
|
+
this.cancelDelegated();
|
|
1471
1972
|
for (const value of this.values.values()) value.stop("replaced");
|
|
1973
|
+
if (!reduced && !isOrchestrated(transition) && transition.type !== "spring" && (transition.duration ?? .3) > 0 && (transition.repeat ?? 0) === 0 && isBezierEase(transition.ease) && this.adapter?.delegate) {
|
|
1974
|
+
const dest = {
|
|
1975
|
+
...this.snapshot(),
|
|
1976
|
+
...target
|
|
1977
|
+
};
|
|
1978
|
+
const run = this.adapter.delegate({
|
|
1979
|
+
target,
|
|
1980
|
+
dest,
|
|
1981
|
+
eff: {
|
|
1982
|
+
opacity: dest.opacity,
|
|
1983
|
+
x: dest.x,
|
|
1984
|
+
y: dest.y,
|
|
1985
|
+
scaleX: (dest.scale ?? 1) * (dest.scaleX ?? 1),
|
|
1986
|
+
scaleY: (dest.scale ?? 1) * (dest.scaleY ?? 1),
|
|
1987
|
+
rotate: dest.rotate
|
|
1988
|
+
},
|
|
1989
|
+
transition
|
|
1990
|
+
});
|
|
1991
|
+
if (run) {
|
|
1992
|
+
const trackSample = () => {
|
|
1993
|
+
const eff = run.sample();
|
|
1994
|
+
for (const key of keys) {
|
|
1995
|
+
if (target[key] === void 0) continue;
|
|
1996
|
+
let next;
|
|
1997
|
+
if (key === "scale") next = (eff.scaleX ?? 1) / (dest.scaleX || 1);
|
|
1998
|
+
else if (key === "scaleX") next = (eff.scaleX ?? 1) / (dest.scale || 1);
|
|
1999
|
+
else if (key === "scaleY") next = (eff.scaleY ?? 1) / (dest.scale || 1);
|
|
2000
|
+
else next = eff[key];
|
|
2001
|
+
if (next !== void 0 && Number.isFinite(next)) this.value(key).track(next);
|
|
2002
|
+
}
|
|
2003
|
+
this.onUpdate?.(this.snapshot());
|
|
2004
|
+
};
|
|
2005
|
+
const entry = {
|
|
2006
|
+
run,
|
|
2007
|
+
frame: 0,
|
|
2008
|
+
trackSample
|
|
2009
|
+
};
|
|
2010
|
+
const tick = () => {
|
|
2011
|
+
if (this.delegated !== entry) return;
|
|
2012
|
+
trackSample();
|
|
2013
|
+
entry.frame = this.clock.request(tick);
|
|
2014
|
+
};
|
|
2015
|
+
entry.frame = this.clock.request(tick);
|
|
2016
|
+
this.delegated = entry;
|
|
2017
|
+
const result = await run.finished;
|
|
2018
|
+
if (this.delegated === entry) {
|
|
2019
|
+
this.clock.cancel(entry.frame);
|
|
2020
|
+
this.delegated = void 0;
|
|
2021
|
+
}
|
|
2022
|
+
if (generation !== this.generation) return "replaced";
|
|
2023
|
+
if (result !== "finished") return "cancelled";
|
|
2024
|
+
for (const key of keys) if (dest[key] !== void 0) this.value(key).jump(dest[key]);
|
|
2025
|
+
return "finished";
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
1472
2028
|
const jobs = Object.entries(target).map(([key, to]) => {
|
|
1473
|
-
return this.value(key).animate(to, reduced && key !== "opacity" ? { duration: 0 } : transition).finished;
|
|
2029
|
+
return this.value(key).animate(to, reduced && key !== "opacity" ? { duration: 0 } : resolveTransition(transition, key)).finished;
|
|
1474
2030
|
});
|
|
1475
2031
|
const results = await Promise.all(jobs);
|
|
1476
2032
|
if (generation !== this.generation) return "replaced";
|
|
@@ -1478,18 +2034,135 @@ var Controller = class {
|
|
|
1478
2034
|
}
|
|
1479
2035
|
stop() {
|
|
1480
2036
|
++this.generation;
|
|
2037
|
+
this.cancelDelegated();
|
|
1481
2038
|
for (const value of this.values.values()) value.stop();
|
|
1482
2039
|
}
|
|
1483
2040
|
destroy() {
|
|
1484
2041
|
this.stop();
|
|
1485
2042
|
for (const value of this.values.values()) value.destroy();
|
|
1486
2043
|
this.values.clear();
|
|
1487
|
-
this.
|
|
2044
|
+
this.adapter = void 0;
|
|
2045
|
+
}
|
|
2046
|
+
};
|
|
2047
|
+
//#endregion
|
|
2048
|
+
//#region src/variants.ts
|
|
2049
|
+
function isLabels(value) {
|
|
2050
|
+
return typeof value === "string" || Array.isArray(value) && value.every((label) => typeof label === "string");
|
|
2051
|
+
}
|
|
2052
|
+
function resolveVariant(definition, variants, custom) {
|
|
2053
|
+
const target = {};
|
|
2054
|
+
let transition;
|
|
2055
|
+
if (definition === void 0 || definition === false) return {
|
|
2056
|
+
target,
|
|
2057
|
+
transition
|
|
2058
|
+
};
|
|
2059
|
+
const entries = isLabels(definition) ? (typeof definition === "string" ? [definition] : definition).map((label) => Object.hasOwn(variants ?? {}, label) ? variants[label] : void 0) : [definition];
|
|
2060
|
+
for (const entry of entries) {
|
|
2061
|
+
const resolved = typeof entry === "function" ? entry(custom) : entry;
|
|
2062
|
+
if (!resolved) continue;
|
|
2063
|
+
const { transition: override, ...values } = resolved;
|
|
2064
|
+
validateTarget(values);
|
|
2065
|
+
Object.assign(target, values);
|
|
2066
|
+
if (override !== void 0) {
|
|
2067
|
+
validateTransitionInput(override);
|
|
2068
|
+
transition = override;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
return {
|
|
2072
|
+
target,
|
|
2073
|
+
transition
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
2076
|
+
/** Keep tree timing out of Controller and add inherited delay to every channel. */
|
|
2077
|
+
function playbackTransition(input, delay = 0) {
|
|
2078
|
+
if (isOrchestrated(input)) {
|
|
2079
|
+
const { staggerChildren: _staggerChildren, delayChildren: _delayChildren, when: _when, ...timing } = input;
|
|
2080
|
+
const result = { default: {
|
|
2081
|
+
...timing.default,
|
|
2082
|
+
delay: (timing.default?.delay ?? 0) + delay
|
|
2083
|
+
} };
|
|
2084
|
+
for (const [key, value] of Object.entries(timing)) if (key !== "default" && value) result[key] = {
|
|
2085
|
+
...value,
|
|
2086
|
+
delay: (value.delay ?? timing.default?.delay ?? 0) + delay
|
|
2087
|
+
};
|
|
2088
|
+
return result;
|
|
2089
|
+
}
|
|
2090
|
+
const { staggerChildren: _staggerChildren, delayChildren: _delayChildren, when: _when, ...timing } = input;
|
|
2091
|
+
return {
|
|
2092
|
+
...timing,
|
|
2093
|
+
delay: (timing.delay ?? 0) + delay
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
/** Root-local tree of inherited runs. Generations prevent queued work after replacement/disposal. */
|
|
2097
|
+
var VariantNode = class {
|
|
2098
|
+
children = /* @__PURE__ */ new Set();
|
|
2099
|
+
generation = 0;
|
|
2100
|
+
active;
|
|
2101
|
+
initial;
|
|
2102
|
+
animate;
|
|
2103
|
+
resolve;
|
|
2104
|
+
play;
|
|
2105
|
+
stopOwn;
|
|
2106
|
+
register(child) {
|
|
2107
|
+
this.children.add(child);
|
|
2108
|
+
const active = this.active;
|
|
2109
|
+
if (active && isLabels(active.definition)) active.finished.then((result) => {
|
|
2110
|
+
if (result !== "finished" || active.generation !== this.generation || !this.children.has(child)) return;
|
|
2111
|
+
const { transition } = this.resolve(active.definition);
|
|
2112
|
+
child.run(active.definition, (transition.delayChildren ?? 0) + [...this.children].indexOf(child) * (transition.staggerChildren ?? 0));
|
|
2113
|
+
});
|
|
2114
|
+
return () => {
|
|
2115
|
+
this.children.delete(child);
|
|
2116
|
+
child.stop();
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
/** Invalidate queued phases without stopping independently registered Presence exits. */
|
|
2120
|
+
cancelPending() {
|
|
2121
|
+
this.generation++;
|
|
2122
|
+
for (const child of this.children) child.cancelPending();
|
|
2123
|
+
}
|
|
2124
|
+
stop() {
|
|
2125
|
+
this.generation++;
|
|
2126
|
+
this.stopOwn?.();
|
|
2127
|
+
for (const child of this.children) child.stop();
|
|
2128
|
+
}
|
|
2129
|
+
run(definition, delay = 0) {
|
|
2130
|
+
this.animate = isLabels(definition) ? definition : void 0;
|
|
2131
|
+
this.stop();
|
|
2132
|
+
const generation = this.generation;
|
|
2133
|
+
const finished = this.runTree(definition, delay, generation);
|
|
2134
|
+
this.active = {
|
|
2135
|
+
definition,
|
|
2136
|
+
finished,
|
|
2137
|
+
generation
|
|
2138
|
+
};
|
|
2139
|
+
return finished;
|
|
2140
|
+
}
|
|
2141
|
+
async runTree(definition, delay, generation) {
|
|
2142
|
+
const { target, transition } = this.resolve(definition);
|
|
2143
|
+
const participants = [...this.children];
|
|
2144
|
+
const own = () => this.play(definition, target, playbackTransition(transition, transition.when === "afterChildren" && participants.length && isLabels(definition) ? 0 : delay));
|
|
2145
|
+
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))) : []);
|
|
2146
|
+
let results;
|
|
2147
|
+
if (transition.when === "beforeChildren") {
|
|
2148
|
+
const result = await own();
|
|
2149
|
+
if (generation !== this.generation || result !== "finished") return "cancelled";
|
|
2150
|
+
results = [result, ...await children()];
|
|
2151
|
+
} else if (transition.when === "afterChildren") {
|
|
2152
|
+
results = await children();
|
|
2153
|
+
if (generation !== this.generation || results.some((result) => result !== "finished")) return "cancelled";
|
|
2154
|
+
results.push(await own());
|
|
2155
|
+
} else {
|
|
2156
|
+
const parent = own();
|
|
2157
|
+
const descendants = children();
|
|
2158
|
+
results = [await parent, ...await descendants];
|
|
2159
|
+
}
|
|
2160
|
+
return generation === this.generation && results.every((result) => result === "finished") ? "finished" : "cancelled";
|
|
1488
2161
|
}
|
|
1489
2162
|
};
|
|
1490
2163
|
//#endregion
|
|
1491
2164
|
//#region src/components.tsrx
|
|
1492
|
-
var _hs$$1 = /* @__PURE__ */ hookSlots(
|
|
2165
|
+
var _hs$$1 = /* @__PURE__ */ hookSlots(24);
|
|
1493
2166
|
var _h$0$1 = /* @__PURE__ */ Symbol(_hs$$1);
|
|
1494
2167
|
var _h$1$1 = /* @__PURE__ */ Symbol(_hs$$1 + 1);
|
|
1495
2168
|
var _h$2$1 = /* @__PURE__ */ Symbol(_hs$$1 + 2);
|
|
@@ -1498,10 +2171,10 @@ var _h$4$1 = /* @__PURE__ */ Symbol(_hs$$1 + 4);
|
|
|
1498
2171
|
var _h$5$1 = /* @__PURE__ */ Symbol(_hs$$1 + 5);
|
|
1499
2172
|
var _h$6$1 = /* @__PURE__ */ Symbol(_hs$$1 + 6);
|
|
1500
2173
|
var _h$7$1 = /* @__PURE__ */ Symbol(_hs$$1 + 7);
|
|
1501
|
-
var _h$8 = /* @__PURE__ */ Symbol(_hs$$1 + 8);
|
|
1502
|
-
var _h$9 = /* @__PURE__ */ Symbol(_hs$$1 + 9);
|
|
1503
|
-
var _h$10 = /* @__PURE__ */ Symbol(_hs$$1 + 10);
|
|
1504
|
-
var _h$11 = /* @__PURE__ */ Symbol(_hs$$1 + 11);
|
|
2174
|
+
var _h$8$1 = /* @__PURE__ */ Symbol(_hs$$1 + 8);
|
|
2175
|
+
var _h$9$1 = /* @__PURE__ */ Symbol(_hs$$1 + 9);
|
|
2176
|
+
var _h$10$1 = /* @__PURE__ */ Symbol(_hs$$1 + 10);
|
|
2177
|
+
var _h$11$1 = /* @__PURE__ */ Symbol(_hs$$1 + 11);
|
|
1505
2178
|
var _h$12 = /* @__PURE__ */ Symbol(_hs$$1 + 12);
|
|
1506
2179
|
var _h$13 = /* @__PURE__ */ Symbol(_hs$$1 + 13);
|
|
1507
2180
|
var _h$14 = /* @__PURE__ */ Symbol(_hs$$1 + 14);
|
|
@@ -1509,6 +2182,11 @@ var _h$15 = /* @__PURE__ */ Symbol(_hs$$1 + 15);
|
|
|
1509
2182
|
var _h$16 = /* @__PURE__ */ Symbol(_hs$$1 + 16);
|
|
1510
2183
|
var _h$17 = /* @__PURE__ */ Symbol(_hs$$1 + 17);
|
|
1511
2184
|
var _h$18 = /* @__PURE__ */ Symbol(_hs$$1 + 18);
|
|
2185
|
+
var _h$19 = /* @__PURE__ */ Symbol(_hs$$1 + 19);
|
|
2186
|
+
var _h$20 = /* @__PURE__ */ Symbol(_hs$$1 + 20);
|
|
2187
|
+
var _h$21 = /* @__PURE__ */ Symbol(_hs$$1 + 21);
|
|
2188
|
+
var _h$22 = /* @__PURE__ */ Symbol(_hs$$1 + 22);
|
|
2189
|
+
var _h$23 = /* @__PURE__ */ Symbol(_hs$$1 + 23);
|
|
1512
2190
|
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
1513
2191
|
"kind": "slot",
|
|
1514
2192
|
"slot": 0
|
|
@@ -1521,40 +2199,88 @@ var __octaneUniversalPlan2 = universalPlan("nativescript", {
|
|
|
1521
2199
|
"kind": "slot",
|
|
1522
2200
|
"slot": 0
|
|
1523
2201
|
});
|
|
2202
|
+
var __octaneUniversalPlan3 = universalPlan("nativescript", {
|
|
2203
|
+
"kind": "slot",
|
|
2204
|
+
"slot": 0
|
|
2205
|
+
});
|
|
2206
|
+
var __octaneUniversalPlan4 = universalPlan("nativescript", {
|
|
2207
|
+
"kind": "slot",
|
|
2208
|
+
"slot": 0
|
|
2209
|
+
});
|
|
2210
|
+
var __octaneUniversalPlan5 = universalPlan("nativescript", {
|
|
2211
|
+
"kind": "slot",
|
|
2212
|
+
"slot": 0
|
|
2213
|
+
});
|
|
2214
|
+
var __octaneUniversalPlan6 = universalPlan("nativescript", {
|
|
2215
|
+
"kind": "slot",
|
|
2216
|
+
"slot": 0
|
|
2217
|
+
});
|
|
2218
|
+
var __octaneUniversalPlan7 = universalPlan("nativescript", {
|
|
2219
|
+
"kind": "slot",
|
|
2220
|
+
"slot": 0
|
|
2221
|
+
});
|
|
2222
|
+
var VariantContext = createContext(null);
|
|
2223
|
+
var controllers = /* @__PURE__ */ new WeakMap();
|
|
2224
|
+
var GESTURE_PROPS = {
|
|
2225
|
+
press: {
|
|
2226
|
+
target: "whileTap",
|
|
2227
|
+
transition: "whileTapTransition"
|
|
2228
|
+
},
|
|
2229
|
+
focus: {
|
|
2230
|
+
target: "whileFocus",
|
|
2231
|
+
transition: "whileFocusTransition"
|
|
2232
|
+
}
|
|
2233
|
+
};
|
|
1524
2234
|
function useMotion(props) {
|
|
1525
2235
|
for (const name of [
|
|
1526
|
-
"drag",
|
|
1527
2236
|
"layout",
|
|
1528
2237
|
"layoutId",
|
|
1529
|
-
"
|
|
1530
|
-
"whileTap",
|
|
2238
|
+
"inherit",
|
|
1531
2239
|
"whileHover",
|
|
1532
|
-
"
|
|
1533
|
-
"
|
|
2240
|
+
"whileInView",
|
|
2241
|
+
"whileDrag"
|
|
1534
2242
|
]) if (name in props) throw new Error(`motion: ${name} is outside the supported subset`);
|
|
2243
|
+
validateDrag(props);
|
|
2244
|
+
const parentVariant = useContext(VariantContext);
|
|
2245
|
+
const inherits = props.animate === void 0 && parentVariant !== null;
|
|
2246
|
+
const initialDefinition = props.initial ?? parentVariant?.initial;
|
|
2247
|
+
const animateDefinition = props.animate ?? parentVariant?.animate;
|
|
2248
|
+
const resolve = (definition, source = props) => {
|
|
2249
|
+
const resolved = resolveVariant(definition, source.variants, source.custom);
|
|
2250
|
+
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`);
|
|
2251
|
+
return resolved;
|
|
2252
|
+
};
|
|
2253
|
+
const resolvedAnimate = resolve(animateDefinition);
|
|
2254
|
+
const resolvedInitial = resolve(initialDefinition);
|
|
2255
|
+
const resolvedExit = resolve(props.exit);
|
|
1535
2256
|
const presence = useContext(PresenceContext);
|
|
1536
2257
|
if (props.exit && !presence) throw new Error("motion: exit requires a mounted Presence boundary");
|
|
1537
2258
|
const config = useContext(ConfigContext);
|
|
1538
2259
|
const systemReduced = withSlot(_h$0$1, useReducedMotion);
|
|
1539
2260
|
const reduced = config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced;
|
|
1540
2261
|
const transition = props.transition ?? config.transition ?? {};
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
if (props.
|
|
2262
|
+
validateTransitionInput(transition);
|
|
2263
|
+
resolve(props.whileTap);
|
|
2264
|
+
resolve(props.whileFocus);
|
|
2265
|
+
if (props.whileTapTransition) validateTransitionInput(props.whileTapTransition);
|
|
2266
|
+
if (props.whileFocusTransition) validateTransitionInput(props.whileFocusTransition);
|
|
1545
2267
|
const latest = useRef(props, _h$1$1);
|
|
1546
2268
|
latest.current = props;
|
|
1547
2269
|
const state = useRef(null, _h$2$1);
|
|
1548
2270
|
if (!state.current) state.current = {
|
|
1549
2271
|
controller: new Controller(clock),
|
|
1550
|
-
initialized: false
|
|
2272
|
+
initialized: false,
|
|
2273
|
+
preGesture: {
|
|
2274
|
+
press: void 0,
|
|
2275
|
+
focus: void 0
|
|
2276
|
+
}
|
|
1551
2277
|
};
|
|
1552
2278
|
const current = state.current;
|
|
1553
2279
|
const style = {};
|
|
1554
2280
|
const bindings = [];
|
|
1555
2281
|
for (const [key, value] of Object.entries(props.style ?? {})) if (keys.includes(key)) {
|
|
1556
2282
|
if (!(value instanceof MotionValue) && (typeof value !== "number" || !Number.isFinite(value))) throw new Error(`motion: invalid style ${key}`);
|
|
1557
|
-
if (value instanceof MotionValue && (
|
|
2283
|
+
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`);
|
|
1558
2284
|
bindings.push([key, value]);
|
|
1559
2285
|
} else {
|
|
1560
2286
|
if (value instanceof MotionValue || [
|
|
@@ -1570,11 +2296,36 @@ function useMotion(props) {
|
|
|
1570
2296
|
const boundKeys = useRef([], _h$4$1);
|
|
1571
2297
|
const firstBinding = useRef(true, _h$5$1);
|
|
1572
2298
|
const firstAnimation = useRef(true, _h$6$1);
|
|
2299
|
+
const inheritedRun = useRef(null, _h$7$1);
|
|
1573
2300
|
if (previous.current.length !== bindings.length || previous.current.some(([key, value], i) => key !== bindings[i][0] || value !== bindings[i][1])) previous.current = bindings;
|
|
1574
|
-
|
|
1575
|
-
|
|
2301
|
+
current.controller.onUpdate = (snapshot) => latest.current.onUpdate?.(snapshot);
|
|
2302
|
+
const gesture = (kind, phase) => {
|
|
2303
|
+
const shape = GESTURE_PROPS[kind];
|
|
2304
|
+
const definition = latest.current[shape.target];
|
|
2305
|
+
if (!definition) return;
|
|
2306
|
+
const { target, transition: override } = resolve(definition, latest.current);
|
|
2307
|
+
const gestureTransition = playbackTransition(override ?? latest.current[shape.transition] ?? playback.current.transition);
|
|
2308
|
+
if (phase === "start") {
|
|
2309
|
+
const snapshot = current.controller.snapshot();
|
|
2310
|
+
const rest = {};
|
|
2311
|
+
for (const key of Object.keys(target)) rest[key] = snapshot[key];
|
|
2312
|
+
current.preGesture[kind] = rest;
|
|
2313
|
+
current.controller.animate(target, gestureTransition, playback.current.reduced);
|
|
2314
|
+
} else {
|
|
2315
|
+
const snap = current.preGesture[kind] ?? {};
|
|
2316
|
+
current.preGesture[kind] = void 0;
|
|
2317
|
+
const rest = {};
|
|
2318
|
+
for (const key of Object.keys(target)) rest[key] = resolve(latest.current.animate ?? parentVariant?.animate, latest.current).target[key] ?? snap[key] ?? defaults[key];
|
|
2319
|
+
current.controller.animate(rest, gestureTransition, playback.current.reduced);
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2322
|
+
const ref = useRef(() => {}, _h$8$1);
|
|
2323
|
+
ref.current = (host) => {
|
|
1576
2324
|
if (!host) return;
|
|
1577
2325
|
if (current.host !== host) {
|
|
2326
|
+
current.gestureOff?.();
|
|
2327
|
+
current.dragOff?.();
|
|
2328
|
+
current.gestureOff = void 0;
|
|
1578
2329
|
current.adapter?.restore();
|
|
1579
2330
|
current.host = host;
|
|
1580
2331
|
current.adapter = attachHost(host);
|
|
@@ -1582,49 +2333,83 @@ function useMotion(props) {
|
|
|
1582
2333
|
const baseline = current.adapter.read();
|
|
1583
2334
|
for (const [key, value] of previous.current) baseline[key] = value instanceof MotionValue ? value.get() : value;
|
|
1584
2335
|
current.controller.seed(baseline);
|
|
1585
|
-
current.controller.seed(
|
|
2336
|
+
current.controller.seed(initialDefinition === false ? resolvedAnimate.target : resolvedInitial.target);
|
|
1586
2337
|
current.initialized = true;
|
|
1587
2338
|
}
|
|
1588
|
-
current.controller.attach(current.adapter
|
|
2339
|
+
current.controller.attach(current.adapter);
|
|
2340
|
+
controllers.set(host, current.controller);
|
|
2341
|
+
configureDrag();
|
|
2342
|
+
if (current.adapter.gesture) {
|
|
2343
|
+
const offs = ["press", "focus"].map((kind) => current.adapter.gesture(kind, {
|
|
2344
|
+
start: () => gesture(kind, "start"),
|
|
2345
|
+
end: () => gesture(kind, "end")
|
|
2346
|
+
})).filter((off) => typeof off === "function");
|
|
2347
|
+
current.gestureOff = () => offs.forEach((off) => off());
|
|
2348
|
+
}
|
|
1589
2349
|
}
|
|
1590
2350
|
current.controller.flush();
|
|
1591
|
-
latest.current.bind?.(host);
|
|
1592
2351
|
};
|
|
1593
2352
|
const playback = useRef({
|
|
1594
2353
|
transition,
|
|
1595
2354
|
reduced
|
|
1596
|
-
}, _h$
|
|
2355
|
+
}, _h$9$1);
|
|
1597
2356
|
playback.current = {
|
|
1598
2357
|
transition,
|
|
1599
2358
|
reduced
|
|
1600
2359
|
};
|
|
1601
|
-
const
|
|
1602
|
-
|
|
2360
|
+
const nodeRef = useRef(null, _h$10$1);
|
|
2361
|
+
if (!nodeRef.current) nodeRef.current = new VariantNode();
|
|
2362
|
+
const node = nodeRef.current;
|
|
2363
|
+
node.initial = initialDefinition === false || isLabels(initialDefinition) ? initialDefinition : void 0;
|
|
2364
|
+
node.animate = isLabels(animateDefinition) ? animateDefinition : void 0;
|
|
2365
|
+
node.resolve = (definition) => {
|
|
2366
|
+
const resolved = resolve(definition, latest.current);
|
|
2367
|
+
return {
|
|
2368
|
+
target: resolved.target,
|
|
2369
|
+
transition: resolved.transition ?? playback.current.transition
|
|
2370
|
+
};
|
|
2371
|
+
};
|
|
2372
|
+
node.stopOwn = () => current.controller.stop();
|
|
2373
|
+
node.play = async (definition, target, timing) => {
|
|
2374
|
+
latest.current.onAnimationStart?.(definition);
|
|
2375
|
+
const result = await current.controller.animate(target, timing, playback.current.reduced);
|
|
2376
|
+
if (result === "finished" && current.host) latest.current.onAnimationComplete?.();
|
|
2377
|
+
return result;
|
|
2378
|
+
};
|
|
2379
|
+
useLayoutEffect(() => inherits ? parentVariant.register(node) : void 0, [inherits, parentVariant], _h$11$1);
|
|
2380
|
+
const returning = useRef(null, _h$12);
|
|
2381
|
+
const member = useRef(null, _h$13);
|
|
1603
2382
|
if (!member.current) member.current = {
|
|
1604
2383
|
exit() {
|
|
2384
|
+
node.cancelPending();
|
|
1605
2385
|
const snapshot = current.controller.snapshot();
|
|
1606
2386
|
returning.current ??= {};
|
|
1607
|
-
|
|
1608
|
-
|
|
2387
|
+
const resolved = resolve(latest.current.exit, latest.current);
|
|
2388
|
+
for (const key of Object.keys(resolved.target)) if (!(key in returning.current)) returning.current[key] = snapshot[key];
|
|
2389
|
+
return current.controller.animate(resolved.target, playbackTransition(resolved.transition ?? playback.current.transition), playback.current.reduced);
|
|
1609
2390
|
},
|
|
1610
2391
|
enter() {
|
|
2392
|
+
const resolved = resolve(latest.current.animate ?? parentVariant?.animate, latest.current);
|
|
1611
2393
|
const target = {
|
|
1612
2394
|
...returning.current,
|
|
1613
|
-
...
|
|
2395
|
+
...resolved.target
|
|
1614
2396
|
};
|
|
1615
2397
|
returning.current = null;
|
|
1616
|
-
current.controller.animate(target, playback.current.transition, playback.current.reduced).then((result) => {
|
|
2398
|
+
current.controller.animate(target, playbackTransition(resolved.transition ?? playback.current.transition), playback.current.reduced).then((result) => {
|
|
1617
2399
|
if (result === "finished" && current.host && presence?.present) latest.current.onAnimationComplete?.();
|
|
1618
2400
|
});
|
|
1619
2401
|
}
|
|
1620
2402
|
};
|
|
1621
|
-
useLayoutEffect(() => presence?.register(member.current), [presence], _h$
|
|
1622
|
-
const
|
|
2403
|
+
useLayoutEffect(() => presence?.register(member.current), [presence], _h$14);
|
|
2404
|
+
const hostRef = useRef((host) => ref.current(host), _h$15).current;
|
|
1623
2405
|
useLayoutEffect(() => () => {
|
|
2406
|
+
node.stop();
|
|
2407
|
+
current.dragOff?.();
|
|
2408
|
+
current.gestureOff?.();
|
|
1624
2409
|
current.controller.destroy();
|
|
1625
2410
|
current.host = void 0;
|
|
1626
2411
|
current.adapter = void 0;
|
|
1627
|
-
}, [], _h$
|
|
2412
|
+
}, [], _h$16);
|
|
1628
2413
|
useLayoutEffect(() => {
|
|
1629
2414
|
const off = [];
|
|
1630
2415
|
for (const key of boundKeys.current) if (!previous.current.some(([next]) => key === next)) current.controller.set(key, defaults[key]);
|
|
@@ -1635,44 +2420,106 @@ function useMotion(props) {
|
|
|
1635
2420
|
}
|
|
1636
2421
|
firstBinding.current = false;
|
|
1637
2422
|
return () => off.forEach((unsubscribe) => unsubscribe());
|
|
1638
|
-
}, [previous.current], _h$
|
|
2423
|
+
}, [previous.current], _h$17);
|
|
2424
|
+
const configureDrag = () => {
|
|
2425
|
+
current.dragOff?.();
|
|
2426
|
+
current.dragOff = void 0;
|
|
2427
|
+
if (!current.adapter) return;
|
|
2428
|
+
current.dragOff = attachDrag(current.adapter, current.controller, latest.current, (axis) => {
|
|
2429
|
+
const binding = previous.current.find(([key]) => key === axis)?.[1];
|
|
2430
|
+
return binding instanceof MotionValue ? binding : current.controller.value(axis);
|
|
2431
|
+
}, () => playback.current.reduced, () => latest.current);
|
|
2432
|
+
};
|
|
1639
2433
|
useLayoutEffect(() => {
|
|
1640
|
-
|
|
1641
|
-
|
|
2434
|
+
configureDrag();
|
|
2435
|
+
}, [
|
|
2436
|
+
props.drag,
|
|
2437
|
+
JSON.stringify(props.dragConstraints),
|
|
2438
|
+
props.dragElastic,
|
|
2439
|
+
props.dragMomentum,
|
|
2440
|
+
previous.current
|
|
2441
|
+
], _h$18);
|
|
2442
|
+
useLayoutEffect(() => {
|
|
2443
|
+
const skip = firstAnimation.current && initialDefinition === false;
|
|
1642
2444
|
firstAnimation.current = false;
|
|
1643
2445
|
if (presence && !presence.present) presence.restart(member.current);
|
|
1644
|
-
else if (
|
|
1645
|
-
if (
|
|
1646
|
-
|
|
2446
|
+
else if (animateDefinition !== void 0 && !skip) {
|
|
2447
|
+
if (!inherits) node.run(animateDefinition);
|
|
2448
|
+
else {
|
|
2449
|
+
const label = JSON.stringify(animateDefinition);
|
|
2450
|
+
const resolved = JSON.stringify({
|
|
2451
|
+
resolvedAnimate,
|
|
2452
|
+
transition,
|
|
2453
|
+
reduced
|
|
2454
|
+
});
|
|
2455
|
+
const previousRun = inheritedRun.current;
|
|
2456
|
+
if (previousRun?.label === label && previousRun.resolved !== resolved) {
|
|
2457
|
+
const parentTiming = parentVariant.resolve(animateDefinition).transition;
|
|
2458
|
+
node.run(animateDefinition, (parentTiming.delayChildren ?? 0) + [...parentVariant.children].indexOf(node) * (parentTiming.staggerChildren ?? 0));
|
|
2459
|
+
}
|
|
2460
|
+
inheritedRun.current = {
|
|
2461
|
+
label,
|
|
2462
|
+
resolved
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
1647
2466
|
return () => {
|
|
1648
|
-
|
|
1649
|
-
current.controller.stop();
|
|
2467
|
+
if (!inherits) node.stop();
|
|
1650
2468
|
};
|
|
1651
2469
|
}, [
|
|
1652
|
-
JSON.stringify(
|
|
1653
|
-
JSON.stringify(
|
|
2470
|
+
JSON.stringify(resolvedAnimate),
|
|
2471
|
+
JSON.stringify(resolvedExit),
|
|
2472
|
+
JSON.stringify(animateDefinition),
|
|
1654
2473
|
JSON.stringify(transition),
|
|
1655
|
-
reduced
|
|
1656
|
-
|
|
1657
|
-
|
|
2474
|
+
reduced,
|
|
2475
|
+
inherits
|
|
2476
|
+
], _h$19);
|
|
2477
|
+
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;
|
|
1658
2478
|
return {
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
2479
|
+
hostProps: {
|
|
2480
|
+
...rest,
|
|
2481
|
+
style,
|
|
2482
|
+
ref: [hostRef, props.ref]
|
|
2483
|
+
},
|
|
2484
|
+
node
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
var MotionLeaf = defineUniversalComponent("nativescript", function MotionLeaf(props) {
|
|
2488
|
+
const Component = props.component;
|
|
2489
|
+
const { hostProps, node } = withSlot(_h$20, useMotion, props);
|
|
2490
|
+
return universalValue(__octaneUniversalPlan1, [((__octaneContextProps) => universalContext(VariantContext, __octaneContextProps.value, universalChildren("nativescript", () => {
|
|
2491
|
+
return universalValue(__octaneUniversalPlan0, [universalComponent("nativescript", Component, universalProps([["spread", hostProps]], props.children))]);
|
|
2492
|
+
})))({ "value": node })]);
|
|
2493
|
+
}, { "module": "@nativescript-community/octane" });
|
|
2494
|
+
function createMotion(Component) {
|
|
2495
|
+
return function MotionCreated(props, __s, __extra) {
|
|
2496
|
+
return MotionLeaf({
|
|
2497
|
+
...props,
|
|
2498
|
+
component: Component
|
|
2499
|
+
}, __s, __extra);
|
|
1662
2500
|
};
|
|
1663
2501
|
}
|
|
1664
2502
|
var MotionView = defineUniversalComponent("nativescript", function MotionView(props) {
|
|
1665
|
-
|
|
2503
|
+
const { hostProps, node } = withSlot(_h$21, useMotion, props);
|
|
2504
|
+
return universalValue(__octaneUniversalPlan3, [((__octaneContextProps) => universalContext(VariantContext, __octaneContextProps.value, universalChildren("nativescript", () => {
|
|
2505
|
+
return universalValue(__octaneUniversalPlan2, [universalComponent("nativescript", View, universalProps([["spread", hostProps]], props.children))]);
|
|
2506
|
+
})))({ "value": node })]);
|
|
1666
2507
|
}, { "module": "@nativescript-community/octane" });
|
|
1667
2508
|
var MotionRow = defineUniversalComponent("nativescript", function MotionRow(props) {
|
|
1668
|
-
|
|
2509
|
+
const { hostProps, node } = withSlot(_h$22, useMotion, props);
|
|
2510
|
+
return universalValue(__octaneUniversalPlan5, [((__octaneContextProps) => universalContext(VariantContext, __octaneContextProps.value, universalChildren("nativescript", () => {
|
|
2511
|
+
return universalValue(__octaneUniversalPlan4, [universalComponent("nativescript", HStack, universalProps([["spread", hostProps]], props.children))]);
|
|
2512
|
+
})))({ "value": node })]);
|
|
1669
2513
|
}, { "module": "@nativescript-community/octane" });
|
|
1670
2514
|
var MotionPressable = defineUniversalComponent("nativescript", function MotionPressable(props) {
|
|
1671
|
-
|
|
2515
|
+
const { hostProps, node } = withSlot(_h$23, useMotion, props);
|
|
2516
|
+
return universalValue(__octaneUniversalPlan7, [((__octaneContextProps) => universalContext(VariantContext, __octaneContextProps.value, universalChildren("nativescript", () => {
|
|
2517
|
+
return universalValue(__octaneUniversalPlan6, [universalComponent("nativescript", Pressable, universalProps([["spread", hostProps]], props.children))]);
|
|
2518
|
+
})))({ "value": node })]);
|
|
1672
2519
|
}, { "module": "@nativescript-community/octane" });
|
|
1673
2520
|
//#endregion
|
|
1674
2521
|
//#region src/hooks.tsrx
|
|
1675
|
-
var _hs$ = /* @__PURE__ */ hookSlots(
|
|
2522
|
+
var _hs$ = /* @__PURE__ */ hookSlots(12);
|
|
1676
2523
|
var _h$0 = /* @__PURE__ */ Symbol(_hs$);
|
|
1677
2524
|
var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
|
|
1678
2525
|
var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
|
|
@@ -1681,6 +2528,10 @@ var _h$4 = /* @__PURE__ */ Symbol(_hs$ + 4);
|
|
|
1681
2528
|
var _h$5 = /* @__PURE__ */ Symbol(_hs$ + 5);
|
|
1682
2529
|
var _h$6 = /* @__PURE__ */ Symbol(_hs$ + 6);
|
|
1683
2530
|
var _h$7 = /* @__PURE__ */ Symbol(_hs$ + 7);
|
|
2531
|
+
var _h$8 = /* @__PURE__ */ Symbol(_hs$ + 8);
|
|
2532
|
+
var _h$9 = /* @__PURE__ */ Symbol(_hs$ + 9);
|
|
2533
|
+
var _h$10 = /* @__PURE__ */ Symbol(_hs$ + 10);
|
|
2534
|
+
var _h$11 = /* @__PURE__ */ Symbol(_hs$ + 11);
|
|
1684
2535
|
function useMotionValue(initial) {
|
|
1685
2536
|
const ref = useRef(null, _h$0);
|
|
1686
2537
|
if (!ref.current) ref.current = new MotionValue(initial, clock);
|
|
@@ -1735,13 +2586,30 @@ function useSpring(source, options = {}) {
|
|
|
1735
2586
|
}, [source instanceof MotionValue ? source : null, JSON.stringify(options)], _h$7);
|
|
1736
2587
|
return value;
|
|
1737
2588
|
}
|
|
2589
|
+
function useAnimate() {
|
|
2590
|
+
const scope = useRef(null, _h$8);
|
|
2591
|
+
const config = useContext(ConfigContext);
|
|
2592
|
+
const systemReduced = withSlot(_h$9, useReducedMotion);
|
|
2593
|
+
const reducedRef = useRef(config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced, _h$10);
|
|
2594
|
+
reducedRef.current = config.reducedMotion === "always" || config.reducedMotion === "user" && systemReduced;
|
|
2595
|
+
return [scope, useRef((target, transitionOrTo, transition) => {
|
|
2596
|
+
if (target instanceof MotionValue) return target.animate(transitionOrTo, transition);
|
|
2597
|
+
const controller = target && typeof target === "object" && controllers.has(target) ? controllers.get(target) : scope.current ? controllers.get(scope.current) : void 0;
|
|
2598
|
+
if (!controller) return Promise.resolve("cancelled");
|
|
2599
|
+
const destination = controllers.has(target) ? transitionOrTo ?? {} : target;
|
|
2600
|
+
const spec = controllers.has(target) ? transition ?? {} : transitionOrTo ?? {};
|
|
2601
|
+
return controller.animate(destination, spec, reducedRef.current);
|
|
2602
|
+
}, _h$11).current];
|
|
2603
|
+
}
|
|
1738
2604
|
//#endregion
|
|
1739
2605
|
//#region src/index.ts
|
|
1740
|
-
/** Bounded motion hosts for shared xplat UI primitives.
|
|
2606
|
+
/** Bounded motion hosts for shared xplat UI primitives; `motion.create` wraps
|
|
2607
|
+
* any component that accepts `ref`/`style`/`children`. */
|
|
1741
2608
|
var motion = {
|
|
1742
2609
|
View: MotionView,
|
|
1743
2610
|
Row: MotionRow,
|
|
1744
|
-
Pressable: MotionPressable
|
|
2611
|
+
Pressable: MotionPressable,
|
|
2612
|
+
create: createMotion
|
|
1745
2613
|
};
|
|
1746
2614
|
//#endregion
|
|
1747
|
-
export { MotionConfig, Presence, motion, useMotionValue, useMotionValueEvent, useReducedMotion, useSpring, useTransform };
|
|
2615
|
+
export { MotionConfig, Presence, motion, useAnimate, useMotionValue, useMotionValueEvent, useReducedMotion, useSpring, useTransform };
|