@onlynative/inertia 0.0.1-alpha.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -0
  3. package/README.md +90 -0
  4. package/dist/index.d.mts +185 -0
  5. package/dist/index.d.ts +185 -0
  6. package/dist/index.js +817 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/index.mjs +796 -0
  9. package/dist/index.mjs.map +1 -0
  10. package/dist/motion/Image.d.mts +12 -0
  11. package/dist/motion/Image.d.ts +12 -0
  12. package/dist/motion/Image.js +656 -0
  13. package/dist/motion/Image.js.map +1 -0
  14. package/dist/motion/Image.mjs +650 -0
  15. package/dist/motion/Image.mjs.map +1 -0
  16. package/dist/motion/Pressable.d.mts +15 -0
  17. package/dist/motion/Pressable.d.ts +15 -0
  18. package/dist/motion/Pressable.js +656 -0
  19. package/dist/motion/Pressable.js.map +1 -0
  20. package/dist/motion/Pressable.mjs +650 -0
  21. package/dist/motion/Pressable.mjs.map +1 -0
  22. package/dist/motion/ScrollView.d.mts +12 -0
  23. package/dist/motion/ScrollView.d.ts +12 -0
  24. package/dist/motion/ScrollView.js +656 -0
  25. package/dist/motion/ScrollView.js.map +1 -0
  26. package/dist/motion/ScrollView.mjs +650 -0
  27. package/dist/motion/ScrollView.mjs.map +1 -0
  28. package/dist/motion/Text.d.mts +11 -0
  29. package/dist/motion/Text.d.ts +11 -0
  30. package/dist/motion/Text.js +656 -0
  31. package/dist/motion/Text.js.map +1 -0
  32. package/dist/motion/Text.mjs +650 -0
  33. package/dist/motion/Text.mjs.map +1 -0
  34. package/dist/motion/View.d.mts +11 -0
  35. package/dist/motion/View.d.ts +11 -0
  36. package/dist/motion/View.js +656 -0
  37. package/dist/motion/View.js.map +1 -0
  38. package/dist/motion/View.mjs +650 -0
  39. package/dist/motion/View.mjs.map +1 -0
  40. package/dist/types-CmbXx-G3.d.mts +185 -0
  41. package/dist/types-CmbXx-G3.d.ts +185 -0
  42. package/llms.txt +78 -0
  43. package/package.json +120 -0
  44. package/src/config/MotionConfig.tsx +30 -0
  45. package/src/config/MotionConfigContext.ts +53 -0
  46. package/src/config/index.ts +9 -0
  47. package/src/index.ts +49 -0
  48. package/src/motion/Image.tsx +9 -0
  49. package/src/motion/Pressable.tsx +12 -0
  50. package/src/motion/ScrollView.tsx +9 -0
  51. package/src/motion/Text.tsx +8 -0
  52. package/src/motion/View.tsx +8 -0
  53. package/src/motion/createMotionComponent.tsx +850 -0
  54. package/src/motion/index.ts +26 -0
  55. package/src/presence/Presence.tsx +165 -0
  56. package/src/presence/PresenceContext.ts +28 -0
  57. package/src/presence/index.ts +6 -0
  58. package/src/transitions/easing.ts +29 -0
  59. package/src/transitions/index.ts +2 -0
  60. package/src/transitions/resolve.ts +265 -0
  61. package/src/types.ts +207 -0
  62. package/src/values/index.ts +1 -0
  63. package/src/values/useVariants.ts +60 -0
package/dist/index.js ADDED
@@ -0,0 +1,817 @@
1
+ 'use strict';
2
+
3
+ var reactNative = require('react-native');
4
+ var react = require('react');
5
+ var Animated = require('react-native-reanimated');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var Animated__default = /*#__PURE__*/_interopDefault(Animated);
11
+
12
+ // src/motion/Image.tsx
13
+ var DEFAULT_MOTION_CONFIG = {
14
+ reducedMotion: "user"
15
+ };
16
+ var MotionConfigContext = react.createContext(
17
+ DEFAULT_MOTION_CONFIG
18
+ );
19
+ function useMotionConfig() {
20
+ return react.useContext(MotionConfigContext);
21
+ }
22
+ function useShouldReduceMotion() {
23
+ const { reducedMotion } = useMotionConfig();
24
+ const osReduced = Animated.useReducedMotion();
25
+ if (reducedMotion === "never") return false;
26
+ if (reducedMotion === "always") return true;
27
+ return osReduced;
28
+ }
29
+ function MotionConfig({
30
+ reducedMotion = "user",
31
+ children
32
+ }) {
33
+ const value = react.useMemo(
34
+ () => ({ reducedMotion }),
35
+ [reducedMotion]
36
+ );
37
+ return /* @__PURE__ */ jsxRuntime.jsx(MotionConfigContext.Provider, { value, children });
38
+ }
39
+ var PresenceContext = react.createContext(null);
40
+ function usePresence() {
41
+ return react.useContext(PresenceContext);
42
+ }
43
+ function Presence({ children }) {
44
+ const incoming = react.useMemo(() => {
45
+ const out = [];
46
+ react.Children.forEach(children, (child) => {
47
+ if (!react.isValidElement(child)) return;
48
+ if (child.key === null) {
49
+ if (__DEV__) {
50
+ console.warn(
51
+ "[inertia] <Presence> children must have a `key`. Skipping a keyless child."
52
+ );
53
+ }
54
+ return;
55
+ }
56
+ out.push(child);
57
+ });
58
+ return out;
59
+ }, [children]);
60
+ const [exiting, setExiting] = react.useState(
61
+ () => /* @__PURE__ */ new Map()
62
+ );
63
+ const prevIncomingRef = react.useRef(incoming);
64
+ if (prevIncomingRef.current !== incoming) {
65
+ const prev = prevIncomingRef.current;
66
+ prevIncomingRef.current = incoming;
67
+ const incomingKeys = new Set(incoming.map((el) => el.key));
68
+ let next = null;
69
+ const ensureMutable = () => {
70
+ if (!next) next = new Map(exiting);
71
+ return next;
72
+ };
73
+ for (const oldEl of prev) {
74
+ const key = oldEl.key;
75
+ if (!incomingKeys.has(key) && !exiting.has(key)) {
76
+ ensureMutable().set(key, oldEl);
77
+ }
78
+ }
79
+ for (const el of incoming) {
80
+ const key = el.key;
81
+ if (exiting.has(key)) {
82
+ ensureMutable().delete(key);
83
+ }
84
+ }
85
+ if (next) setExiting(next);
86
+ }
87
+ const handleRemove = react.useCallback((key) => {
88
+ setExiting((prev) => {
89
+ if (!prev.has(key)) return prev;
90
+ const next = new Map(prev);
91
+ next.delete(key);
92
+ return next;
93
+ });
94
+ }, []);
95
+ const renderList = [];
96
+ for (const el of incoming) {
97
+ renderList.push({
98
+ key: el.key,
99
+ element: el,
100
+ isPresent: true
101
+ });
102
+ }
103
+ for (const [key, el] of exiting) {
104
+ if (!renderList.some((entry) => entry.key === key)) {
105
+ renderList.push({ key, element: el, isPresent: false });
106
+ }
107
+ }
108
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderList.map(({ key, element, isPresent }) => /* @__PURE__ */ jsxRuntime.jsx(
109
+ PresenceItem,
110
+ {
111
+ itemKey: key,
112
+ isPresent,
113
+ onRemove: handleRemove,
114
+ children: element
115
+ },
116
+ key
117
+ )) });
118
+ }
119
+ function PresenceItem({
120
+ itemKey,
121
+ isPresent,
122
+ onRemove,
123
+ children
124
+ }) {
125
+ const value = react.useMemo(
126
+ () => ({
127
+ isPresent,
128
+ safeToRemove: () => onRemove(itemKey)
129
+ }),
130
+ [isPresent, itemKey, onRemove]
131
+ );
132
+ return /* @__PURE__ */ jsxRuntime.jsx(PresenceContext.Provider, { value, children });
133
+ }
134
+ function ensureWorkletEasing(easing) {
135
+ if (!easing) return void 0;
136
+ if (Animated.isWorkletFunction(easing)) return easing;
137
+ const wrapped = (t) => {
138
+ "worklet";
139
+ return easing(t);
140
+ };
141
+ return wrapped;
142
+ }
143
+
144
+ // src/transitions/resolve.ts
145
+ var DEFAULT_SPRING = {
146
+ tension: 170,
147
+ friction: 26,
148
+ mass: 1
149
+ };
150
+ var DEFAULT_TIMING_DURATION = 250;
151
+ function springToReanimated(t) {
152
+ return {
153
+ stiffness: t.tension ?? DEFAULT_SPRING.tension,
154
+ damping: t.friction ?? DEFAULT_SPRING.friction,
155
+ mass: t.mass ?? DEFAULT_SPRING.mass,
156
+ velocity: t.velocity,
157
+ restSpeedThreshold: t.restSpeedThreshold,
158
+ restDisplacementThreshold: t.restDisplacementThreshold
159
+ };
160
+ }
161
+ function buildSpring(cfg, toValue, cb) {
162
+ return Animated.withSpring(toValue, springToReanimated(cfg), cb);
163
+ }
164
+ function buildTiming(cfg, toValue, cb) {
165
+ return Animated.withTiming(
166
+ toValue,
167
+ {
168
+ duration: cfg.duration ?? DEFAULT_TIMING_DURATION,
169
+ easing: ensureWorkletEasing(cfg.easing) ?? Animated.Easing.inOut(Animated.Easing.ease)
170
+ },
171
+ cb
172
+ );
173
+ }
174
+ function buildDecay(cfg, cb) {
175
+ return Animated.withDecay(
176
+ {
177
+ velocity: cfg.velocity ?? 0,
178
+ deceleration: cfg.deceleration,
179
+ clamp: cfg.clamp
180
+ },
181
+ cb
182
+ );
183
+ }
184
+ function buildOne(cfg, toValue, cb) {
185
+ if (cfg.type === "no-animation") {
186
+ if (cb) cb(true, toValue);
187
+ return toValue;
188
+ }
189
+ if (cfg.type === "decay") return buildDecay(cfg, cb);
190
+ if (cfg.type === "timing") return buildTiming(cfg, toValue, cb);
191
+ return buildSpring(cfg, toValue, cb);
192
+ }
193
+ function applyRepeat(animation, repeat) {
194
+ if (repeat === void 0) return animation;
195
+ if (repeat === "infinite") {
196
+ return Animated.withRepeat(animation, -1, true);
197
+ }
198
+ if (typeof repeat === "number") {
199
+ return Animated.withRepeat(animation, repeat, true);
200
+ }
201
+ const count = repeat.count === "infinite" ? -1 : repeat.count;
202
+ const alternate = repeat.alternate ?? true;
203
+ return Animated.withRepeat(animation, count, alternate);
204
+ }
205
+ function applyDelay(animation, delay) {
206
+ if (!delay || delay <= 0) return animation;
207
+ return Animated.withDelay(delay, animation);
208
+ }
209
+ function resolveTransition(config, toValue, callback) {
210
+ const cfg = config ?? { type: "spring" };
211
+ const base = buildOne(cfg, toValue, callback);
212
+ const repeated = applyRepeat(base, repeatOf(cfg));
213
+ return applyDelay(repeated, delayOf(cfg));
214
+ }
215
+ function repeatOf(cfg) {
216
+ if (cfg.type === "no-animation" || cfg.type === "decay") return void 0;
217
+ return cfg.repeat;
218
+ }
219
+ function stripRepeat(cfg) {
220
+ if (!cfg) return cfg;
221
+ if (cfg.type === "no-animation" || cfg.type === "decay") return cfg;
222
+ if (cfg.repeat === void 0) return cfg;
223
+ const next = { ...cfg };
224
+ delete next.repeat;
225
+ return next;
226
+ }
227
+ function delayOf(cfg) {
228
+ if (cfg.type === "no-animation") return void 0;
229
+ return cfg.delay;
230
+ }
231
+ function isStepObject(v) {
232
+ return typeof v === "object" && v !== null && !Array.isArray(v) && "to" in v;
233
+ }
234
+ function resolveAnimatableValue(value, base, factory) {
235
+ if (Array.isArray(value)) {
236
+ const steps = value;
237
+ const stepBase = stripRepeat(base);
238
+ const animations = steps.map(
239
+ (step2, i) => resolveStep(step2, stepBase, factory?.("step", i))
240
+ );
241
+ const seq = Animated.withSequence(...animations);
242
+ return applyRepeat(seq, base ? repeatOf(base) : void 0);
243
+ }
244
+ const step = value;
245
+ const cb = factory?.("animation", void 0);
246
+ if (isStepObject(step)) {
247
+ return resolveStep(step, base, cb);
248
+ }
249
+ return resolveTransition(base, step, cb);
250
+ }
251
+ function resolveStep(step, base, cb) {
252
+ if (isStepObject(step)) {
253
+ const { to, ...override } = step;
254
+ const merged = mergeTransition(base, override);
255
+ return resolveTransition(merged, to, cb);
256
+ }
257
+ return resolveTransition(base, step, cb);
258
+ }
259
+ function mergeTransition(base, override) {
260
+ if (override.type && base && override.type !== base.type) {
261
+ return override;
262
+ }
263
+ return { ...base ?? { type: "spring" }, ...override };
264
+ }
265
+ var TRANSFORM_KEYS = [
266
+ "translateX",
267
+ "translateY",
268
+ "scale",
269
+ "scaleX",
270
+ "scaleY",
271
+ "rotate"
272
+ ];
273
+ var TOP_LEVEL_KEYS = ["opacity", "width", "height", "borderRadius"];
274
+ var ALL_KEYS = [...TRANSFORM_KEYS, ...TOP_LEVEL_KEYS];
275
+ var TRANSFORM_KEY_SET = new Set(TRANSFORM_KEYS);
276
+ var EXITING_POINTER_EVENTS_STYLE = { pointerEvents: "none" };
277
+ var DEFAULT_RESTING = {
278
+ translateX: 0,
279
+ translateY: 0,
280
+ scale: 1,
281
+ scaleX: 1,
282
+ scaleY: 1,
283
+ rotate: 0,
284
+ opacity: 1,
285
+ width: 0,
286
+ height: 0,
287
+ borderRadius: 0
288
+ };
289
+ var TRANSITION_KEYS = /* @__PURE__ */ new Set([
290
+ "type",
291
+ "tension",
292
+ "friction",
293
+ "mass",
294
+ "velocity",
295
+ "restSpeedThreshold",
296
+ "restDisplacementThreshold",
297
+ "duration",
298
+ "easing",
299
+ "delay",
300
+ "repeat",
301
+ "deceleration",
302
+ "clamp"
303
+ ]);
304
+ function isTopLevelTransition(t) {
305
+ if (t === null || typeof t !== "object") return false;
306
+ const keys = Object.keys(t);
307
+ if (keys.length === 0) return false;
308
+ return keys.every((k) => TRANSITION_KEYS.has(k));
309
+ }
310
+ function transitionFor(prop, transition) {
311
+ if (!transition) return void 0;
312
+ if (isTopLevelTransition(transition)) return transition;
313
+ return transition[prop];
314
+ }
315
+ function createMotionComponent(Component) {
316
+ const AnimatedComponent = Animated__default.default.createAnimatedComponent(
317
+ Component
318
+ );
319
+ const Motion2 = react.forwardRef(function Motion3(props, ref) {
320
+ const {
321
+ initial,
322
+ animate,
323
+ exit,
324
+ transition,
325
+ variants,
326
+ controller,
327
+ gesture,
328
+ onAnimationEnd,
329
+ style,
330
+ ...rest
331
+ } = props;
332
+ const presence = usePresence();
333
+ const isExiting = presence !== null && presence.isPresent === false;
334
+ const shouldReduceMotion = useShouldReduceMotion();
335
+ const onAnimationEndRef = react.useRef(onAnimationEnd);
336
+ onAnimationEndRef.current = onAnimationEnd;
337
+ const variantKey = useControllerKey(controller);
338
+ const resolvedAnimate = resolveAnimateInput(
339
+ animate,
340
+ variants,
341
+ variantKey
342
+ );
343
+ const animateRecord = resolvedAnimate ?? {};
344
+ const initialRecord = initial && initial !== false ? initial : void 0;
345
+ const exitRecord = exit ? exit : void 0;
346
+ const [pressed, setPressed] = react.useState(false);
347
+ const [focused, setFocused] = react.useState(false);
348
+ const [hovered, setHovered] = react.useState(false);
349
+ const activeKeysRef = react.useRef(null);
350
+ if (activeKeysRef.current === null) {
351
+ const touched = /* @__PURE__ */ new Set();
352
+ for (const k of ALL_KEYS) {
353
+ if (k in animateRecord) touched.add(k);
354
+ if (initialRecord && k in initialRecord) touched.add(k);
355
+ }
356
+ if (variants) {
357
+ for (const variant of Object.values(variants)) {
358
+ if (!variant) continue;
359
+ for (const k of ALL_KEYS) {
360
+ if (k in variant) touched.add(k);
361
+ }
362
+ }
363
+ }
364
+ if (gesture) {
365
+ for (const subState of [
366
+ gesture.pressed,
367
+ gesture.focused,
368
+ gesture.hovered
369
+ ]) {
370
+ if (!subState) continue;
371
+ for (const k of ALL_KEYS) {
372
+ if (k in subState) touched.add(k);
373
+ }
374
+ }
375
+ }
376
+ if (exitRecord) {
377
+ for (const k of ALL_KEYS) {
378
+ if (k in exitRecord) touched.add(k);
379
+ }
380
+ }
381
+ activeKeysRef.current = ALL_KEYS.filter((k) => touched.has(k));
382
+ }
383
+ const hasTransformRef = react.useRef(
384
+ activeKeysRef.current.some((k) => TRANSFORM_KEY_SET.has(k))
385
+ );
386
+ const sharedValues = useAnimatableSharedValues((key) => {
387
+ if (initial === false) {
388
+ const a = animateRecord[key];
389
+ return restValue(a) ?? DEFAULT_RESTING[key];
390
+ }
391
+ return initialRecord?.[key] ?? restValue(animateRecord[key]) ?? DEFAULT_RESTING[key];
392
+ });
393
+ const mergedRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : mergeGestureTargets(animateRecord, gesture, {
394
+ pressed,
395
+ focused,
396
+ hovered
397
+ });
398
+ const mergedSig = stableSig(mergedRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
399
+ const transitionSig = stableSig(transition);
400
+ const safeToRemoveRef = react.useRef(void 0);
401
+ safeToRemoveRef.current = presence?.safeToRemove;
402
+ react.useEffect(() => {
403
+ if (isExiting && (!exitRecord || Object.keys(exitRecord).length === 0)) {
404
+ safeToRemoveRef.current?.();
405
+ return;
406
+ }
407
+ let pending = 0;
408
+ let done = false;
409
+ const onSettle = () => {
410
+ if (done) return;
411
+ pending--;
412
+ if (pending <= 0) {
413
+ done = true;
414
+ if (isExiting) safeToRemoveRef.current?.();
415
+ }
416
+ };
417
+ let transformPending = 0;
418
+ for (const k of ALL_KEYS) {
419
+ if (TRANSFORM_KEY_SET.has(k) && mergedRecord[k] !== void 0) {
420
+ transformPending++;
421
+ }
422
+ }
423
+ const transformGroup = transformPending > 0 ? { remaining: transformPending } : void 0;
424
+ for (const key of ALL_KEYS) {
425
+ const target = mergedRecord[key];
426
+ if (target === void 0) continue;
427
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : transitionFor(key, transition);
428
+ if (isExiting) pending++;
429
+ const factory = makeKeyCallbackFactory(
430
+ key,
431
+ sharedValues[key],
432
+ targetEndValue(target),
433
+ onAnimationEndRef,
434
+ {
435
+ stepCount: stepCountOf(target),
436
+ totalIterations: totalIterationsOf(cfg)
437
+ },
438
+ isExiting ? onSettle : void 0,
439
+ TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
440
+ );
441
+ sharedValues[key].value = resolveAnimatableValue(
442
+ target,
443
+ cfg,
444
+ factory
445
+ );
446
+ }
447
+ if (isExiting && pending === 0) {
448
+ safeToRemoveRef.current?.();
449
+ }
450
+ }, [mergedSig, transitionSig]);
451
+ const animatedStyle = Animated.useAnimatedStyle(() => {
452
+ const activeKeys = activeKeysRef.current;
453
+ const hasTransform = hasTransformRef.current;
454
+ const out = {};
455
+ const transform = [];
456
+ for (const key of activeKeys) {
457
+ const v = sharedValues[key].value;
458
+ if (TRANSFORM_KEY_SET.has(key)) {
459
+ transform.push(
460
+ key === "rotate" ? { rotate: `${v}deg` } : { [key]: v }
461
+ );
462
+ } else {
463
+ out[key] = v;
464
+ }
465
+ }
466
+ if (hasTransform) out.transform = transform;
467
+ return out;
468
+ });
469
+ const mergedStyle = react.useMemo(
470
+ () => isExiting ? [style, animatedStyle, EXITING_POINTER_EVENTS_STYLE] : [style, animatedStyle],
471
+ [style, animatedStyle, isExiting]
472
+ );
473
+ const gestureHandlers = useGestureHandlers(
474
+ gesture,
475
+ rest,
476
+ setPressed,
477
+ setFocused,
478
+ setHovered
479
+ );
480
+ return /* @__PURE__ */ jsxRuntime.jsx(
481
+ AnimatedComponent,
482
+ {
483
+ ref,
484
+ ...rest,
485
+ ...gestureHandlers,
486
+ style: mergedStyle
487
+ }
488
+ );
489
+ });
490
+ Motion2.displayName = `Motion(${Component.displayName ?? Component.name ?? "Component"})`;
491
+ return Motion2;
492
+ }
493
+ function useAnimatableSharedValues(init) {
494
+ const translateX = Animated.useSharedValue(init("translateX"));
495
+ const translateY = Animated.useSharedValue(init("translateY"));
496
+ const scale = Animated.useSharedValue(init("scale"));
497
+ const scaleX = Animated.useSharedValue(init("scaleX"));
498
+ const scaleY = Animated.useSharedValue(init("scaleY"));
499
+ const rotate = Animated.useSharedValue(init("rotate"));
500
+ const opacity = Animated.useSharedValue(init("opacity"));
501
+ const width = Animated.useSharedValue(init("width"));
502
+ const height = Animated.useSharedValue(init("height"));
503
+ const borderRadius = Animated.useSharedValue(init("borderRadius"));
504
+ const ref = react.useRef(null);
505
+ if (ref.current === null) {
506
+ ref.current = {
507
+ translateX,
508
+ translateY,
509
+ scale,
510
+ scaleX,
511
+ scaleY,
512
+ rotate,
513
+ opacity,
514
+ width,
515
+ height,
516
+ borderRadius
517
+ };
518
+ }
519
+ return ref.current;
520
+ }
521
+ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, meta, onSettle, transformGroup) {
522
+ if (!onAnimationEndRef.current && !onSettle) return void 0;
523
+ const state = { iteration: 0 };
524
+ const isTransformKey = TRANSFORM_KEY_SET.has(key);
525
+ const dispatch = (rawPhase, step, finished, value) => {
526
+ const isLastIteration = state.iteration >= meta.totalIterations - 1;
527
+ let phase;
528
+ let isTerminal = false;
529
+ if (rawPhase === "step") {
530
+ const isLastInPass = step !== void 0 && step === meta.stepCount - 1;
531
+ if (!isLastInPass) {
532
+ phase = "step";
533
+ } else if (isLastIteration) {
534
+ phase = "animation";
535
+ isTerminal = true;
536
+ } else {
537
+ phase = "sequence";
538
+ }
539
+ } else if (isLastIteration) {
540
+ phase = "animation";
541
+ isTerminal = true;
542
+ } else {
543
+ phase = "repeat";
544
+ }
545
+ const reportedIteration = state.iteration;
546
+ if (phase === "sequence" || phase === "repeat") state.iteration++;
547
+ const fn = onAnimationEndRef.current;
548
+ if (fn) {
549
+ if (isTransformKey && transformGroup && phase === "animation") {
550
+ transformGroup.remaining--;
551
+ if (transformGroup.remaining <= 0) {
552
+ fn({
553
+ key: "transform",
554
+ finished,
555
+ value,
556
+ target,
557
+ phase,
558
+ step,
559
+ iteration: reportedIteration
560
+ });
561
+ }
562
+ } else {
563
+ fn({
564
+ key,
565
+ finished,
566
+ value,
567
+ target,
568
+ phase,
569
+ step,
570
+ iteration: reportedIteration
571
+ });
572
+ }
573
+ }
574
+ if (onSettle && isTerminal) onSettle();
575
+ };
576
+ return (rawPhase, step) => {
577
+ const cb = (finished) => {
578
+ "worklet";
579
+ Animated.runOnJS(dispatch)(rawPhase, step, !!finished, sharedValue.value);
580
+ };
581
+ return cb;
582
+ };
583
+ }
584
+ function stepCountOf(v) {
585
+ if (Array.isArray(v)) return v.length;
586
+ return 1;
587
+ }
588
+ function totalIterationsOf(cfg) {
589
+ if (!cfg || cfg.type === "no-animation" || cfg.type === "decay") return 1;
590
+ const r = cfg.repeat;
591
+ if (r === void 0) return 1;
592
+ if (r === "infinite") return Number.POSITIVE_INFINITY;
593
+ if (typeof r === "number") return r;
594
+ if (r.count === "infinite") return Number.POSITIVE_INFINITY;
595
+ return r.count;
596
+ }
597
+ function targetEndValue(v) {
598
+ if (v === void 0) return void 0;
599
+ if (typeof v === "number" || typeof v === "string") return v;
600
+ if (Array.isArray(v)) {
601
+ return v.length > 0 ? targetEndValue(v[v.length - 1]) : void 0;
602
+ }
603
+ if (typeof v === "object" && v !== null && "to" in v) {
604
+ const to = v.to;
605
+ return typeof to === "number" || typeof to === "string" ? to : void 0;
606
+ }
607
+ return void 0;
608
+ }
609
+ function useControllerKey(controller) {
610
+ const [, setTick] = react.useState(0);
611
+ react.useEffect(() => {
612
+ if (!controller) return;
613
+ const unsub = controller.subscribe(() => setTick((n) => n + 1));
614
+ return unsub;
615
+ }, [controller]);
616
+ return controller?.current;
617
+ }
618
+ function resolveAnimateInput(animate, variants, controllerKey) {
619
+ if (controllerKey !== void 0 && variants && controllerKey in variants) {
620
+ return variants[controllerKey];
621
+ }
622
+ if (typeof animate === "string") {
623
+ if (variants && animate in variants) return variants[animate];
624
+ if (__DEV__) {
625
+ console.warn(
626
+ `[inertia] animate="${animate}" but no matching variant. Did you forget to pass \`variants\`?`
627
+ );
628
+ }
629
+ return void 0;
630
+ }
631
+ return animate;
632
+ }
633
+ function restValue(v) {
634
+ if (v === void 0) return void 0;
635
+ if (typeof v === "number") return v;
636
+ if (Array.isArray(v)) {
637
+ return v.length > 0 ? restValue(v[0]) : void 0;
638
+ }
639
+ if (typeof v === "object" && v !== null && "to" in v) {
640
+ const to = v.to;
641
+ return typeof to === "number" ? to : void 0;
642
+ }
643
+ return void 0;
644
+ }
645
+ function stableSig(value) {
646
+ if (value === void 0) return "";
647
+ try {
648
+ return stableStringify(value);
649
+ } catch {
650
+ return String(value);
651
+ }
652
+ }
653
+ function stableStringify(v) {
654
+ if (v === null || typeof v !== "object") {
655
+ if (typeof v === "function" || v === void 0) return "null";
656
+ return JSON.stringify(v);
657
+ }
658
+ if (Array.isArray(v)) {
659
+ return "[" + v.map(stableStringify).join(",") + "]";
660
+ }
661
+ const obj = v;
662
+ const keys = Object.keys(obj).sort();
663
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
664
+ }
665
+ function mergeGestureTargets(base, gesture, active) {
666
+ if (!gesture) return base;
667
+ const merged = {
668
+ ...base
669
+ };
670
+ const subStates = [
671
+ gesture.hovered,
672
+ gesture.focused,
673
+ gesture.pressed
674
+ ];
675
+ for (const sub of subStates) {
676
+ if (!sub) continue;
677
+ for (const k of ALL_KEYS) {
678
+ if (k in sub && !(k in merged)) {
679
+ merged[k] = DEFAULT_RESTING[k];
680
+ }
681
+ }
682
+ }
683
+ if (active.hovered && gesture.hovered) {
684
+ Object.assign(
685
+ merged,
686
+ gesture.hovered
687
+ );
688
+ }
689
+ if (active.focused && gesture.focused) {
690
+ Object.assign(
691
+ merged,
692
+ gesture.focused
693
+ );
694
+ }
695
+ if (active.pressed && gesture.pressed) {
696
+ Object.assign(
697
+ merged,
698
+ gesture.pressed
699
+ );
700
+ }
701
+ return merged;
702
+ }
703
+ function useGestureHandlers(gesture, rest, setPressed, setFocused, setHovered) {
704
+ return react.useMemo(() => {
705
+ if (!gesture) return {};
706
+ const handlers = {};
707
+ if (gesture.pressed) {
708
+ handlers.onTouchStart = compose(rest.onTouchStart, () => setPressed(true));
709
+ handlers.onTouchEnd = compose(rest.onTouchEnd, () => setPressed(false));
710
+ handlers.onTouchCancel = compose(
711
+ rest.onTouchCancel,
712
+ () => setPressed(false)
713
+ );
714
+ handlers.onPressIn = compose(rest.onPressIn, () => setPressed(true));
715
+ handlers.onPressOut = compose(rest.onPressOut, () => setPressed(false));
716
+ }
717
+ if (gesture.focused) {
718
+ handlers.onFocus = compose(rest.onFocus, () => setFocused(true));
719
+ handlers.onBlur = compose(rest.onBlur, () => setFocused(false));
720
+ }
721
+ if (gesture.hovered) {
722
+ handlers.onMouseEnter = compose(rest.onMouseEnter, () => setHovered(true));
723
+ handlers.onMouseLeave = compose(
724
+ rest.onMouseLeave,
725
+ () => setHovered(false)
726
+ );
727
+ }
728
+ return handlers;
729
+ }, [
730
+ gesture?.pressed ? 1 : 0,
731
+ gesture?.focused ? 1 : 0,
732
+ gesture?.hovered ? 1 : 0,
733
+ rest.onTouchStart,
734
+ rest.onTouchEnd,
735
+ rest.onTouchCancel,
736
+ rest.onPressIn,
737
+ rest.onPressOut,
738
+ rest.onFocus,
739
+ rest.onBlur,
740
+ rest.onMouseEnter,
741
+ rest.onMouseLeave
742
+ ]);
743
+ }
744
+ function compose(user, ours) {
745
+ if (typeof user !== "function") return ours;
746
+ return (event) => {
747
+ user(event);
748
+ ours(event);
749
+ };
750
+ }
751
+
752
+ // src/motion/Image.tsx
753
+ var MotionImage = createMotionComponent(reactNative.Image);
754
+ var MotionPressable = createMotionComponent(reactNative.Pressable);
755
+ var MotionScrollView = createMotionComponent(reactNative.ScrollView);
756
+ var MotionText = createMotionComponent(reactNative.Text);
757
+ var MotionView = createMotionComponent(reactNative.View);
758
+
759
+ // src/motion/index.ts
760
+ var Motion = {
761
+ View: MotionView,
762
+ Text: MotionText,
763
+ Image: MotionImage,
764
+ Pressable: MotionPressable,
765
+ ScrollView: MotionScrollView
766
+ };
767
+ function useVariants(variants, initial) {
768
+ const variantsRef = react.useRef(variants);
769
+ return react.useMemo(() => {
770
+ const listeners = /* @__PURE__ */ new Set();
771
+ let current = initial ?? (Object.keys(variantsRef.current)[0] ?? "");
772
+ const controller = {
773
+ get current() {
774
+ return current;
775
+ },
776
+ transitionTo(next) {
777
+ if (next === current) return;
778
+ if (!(next in variantsRef.current)) {
779
+ if (__DEV__) {
780
+ console.warn(
781
+ `[inertia] useVariants: unknown variant "${String(next)}". Known keys: ${Object.keys(variantsRef.current).join(", ")}`
782
+ );
783
+ }
784
+ return;
785
+ }
786
+ current = next;
787
+ for (const fn of listeners) fn(next);
788
+ },
789
+ subscribe(listener) {
790
+ listeners.add(listener);
791
+ return () => {
792
+ listeners.delete(listener);
793
+ };
794
+ }
795
+ };
796
+ return controller;
797
+ }, []);
798
+ }
799
+
800
+ exports.Motion = Motion;
801
+ exports.MotionConfig = MotionConfig;
802
+ exports.MotionImage = MotionImage;
803
+ exports.MotionPressable = MotionPressable;
804
+ exports.MotionScrollView = MotionScrollView;
805
+ exports.MotionText = MotionText;
806
+ exports.MotionView = MotionView;
807
+ exports.Presence = Presence;
808
+ exports.createMotionComponent = createMotionComponent;
809
+ exports.ensureWorkletEasing = ensureWorkletEasing;
810
+ exports.resolveAnimatableValue = resolveAnimatableValue;
811
+ exports.resolveTransition = resolveTransition;
812
+ exports.useMotionConfig = useMotionConfig;
813
+ exports.usePresence = usePresence;
814
+ exports.useShouldReduceMotion = useShouldReduceMotion;
815
+ exports.useVariants = useVariants;
816
+ //# sourceMappingURL=index.js.map
817
+ //# sourceMappingURL=index.js.map