@rootnative/inertia 0.0.0-alpha.0 → 0.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -0
  3. package/dist/gestureLayer/index.d.mts +6 -5
  4. package/dist/gestureLayer/index.d.ts +6 -5
  5. package/dist/gestureLayer/index.js +89 -27
  6. package/dist/gestureLayer/index.js.map +1 -1
  7. package/dist/gestureLayer/index.mjs +89 -27
  8. package/dist/gestureLayer/index.mjs.map +1 -1
  9. package/dist/index.d.mts +127 -16
  10. package/dist/index.d.ts +127 -16
  11. package/dist/index.js +177 -60
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +175 -61
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/motion/Image.d.mts +1 -1
  16. package/dist/motion/Image.d.ts +1 -1
  17. package/dist/motion/Image.js +90 -48
  18. package/dist/motion/Image.js.map +1 -1
  19. package/dist/motion/Image.mjs +90 -48
  20. package/dist/motion/Image.mjs.map +1 -1
  21. package/dist/motion/Pressable.d.mts +1 -1
  22. package/dist/motion/Pressable.d.ts +1 -1
  23. package/dist/motion/Pressable.js +90 -48
  24. package/dist/motion/Pressable.js.map +1 -1
  25. package/dist/motion/Pressable.mjs +90 -48
  26. package/dist/motion/Pressable.mjs.map +1 -1
  27. package/dist/motion/ScrollView.d.mts +1 -1
  28. package/dist/motion/ScrollView.d.ts +1 -1
  29. package/dist/motion/ScrollView.js +90 -48
  30. package/dist/motion/ScrollView.js.map +1 -1
  31. package/dist/motion/ScrollView.mjs +90 -48
  32. package/dist/motion/ScrollView.mjs.map +1 -1
  33. package/dist/motion/Text.d.mts +1 -1
  34. package/dist/motion/Text.d.ts +1 -1
  35. package/dist/motion/Text.js +90 -48
  36. package/dist/motion/Text.js.map +1 -1
  37. package/dist/motion/Text.mjs +90 -48
  38. package/dist/motion/Text.mjs.map +1 -1
  39. package/dist/motion/View.d.mts +1 -1
  40. package/dist/motion/View.d.ts +1 -1
  41. package/dist/motion/View.js +90 -48
  42. package/dist/motion/View.js.map +1 -1
  43. package/dist/motion/View.mjs +90 -48
  44. package/dist/motion/View.mjs.map +1 -1
  45. package/dist/touch/index.d.mts +1 -1
  46. package/dist/touch/index.d.ts +1 -1
  47. package/dist/{types-cU43dEmH.d.mts → types-BzEgiUdJ.d.mts} +58 -9
  48. package/dist/{types-cU43dEmH.d.ts → types-BzEgiUdJ.d.ts} +58 -9
  49. package/dist/{useGesture-BnY65PlQ.d.ts → useGesture-BRLgiNOC.d.ts} +6 -4
  50. package/dist/{useGesture-DxtXdz-K.d.mts → useGesture-C0GBS7d2.d.mts} +6 -4
  51. package/llms.txt +8 -4
  52. package/package.json +1 -1
  53. package/src/__type-tests__/motion-value.test-d.ts +39 -0
  54. package/src/config/MotionConfig.tsx +55 -9
  55. package/src/config/MotionConfigContext.ts +21 -1
  56. package/src/config/index.ts +7 -1
  57. package/src/config/namedTransitions.ts +80 -0
  58. package/src/gestureLayer/useGestureLayer.ts +32 -8
  59. package/src/index.ts +20 -2
  60. package/src/motion/createMotionComponent.tsx +36 -6
  61. package/src/transitions/cubicBezier.ts +126 -0
  62. package/src/transitions/index.ts +1 -0
  63. package/src/types.ts +63 -8
  64. package/src/values/useAnimation.ts +12 -6
  65. package/src/values/useBooleanSpring.ts +5 -3
  66. package/src/values/useGesture.ts +25 -7
  67. package/src/values/useMotionValue.ts +11 -0
  68. package/src/values/useScroll.ts +8 -1
  69. package/src/values/useSpring.ts +46 -9
package/dist/index.mjs CHANGED
@@ -5,8 +5,31 @@ import { jsx, Fragment } from 'react/jsx-runtime';
5
5
  import { isWorkletFunction } from 'react-native-worklets';
6
6
 
7
7
  // src/motion/Image.tsx
8
+
9
+ // src/transitions/sig.ts
10
+ function stableSig(value) {
11
+ if (value === void 0) return "";
12
+ try {
13
+ return stableStringify(value);
14
+ } catch {
15
+ return String(value);
16
+ }
17
+ }
18
+ function stableStringify(v) {
19
+ if (v === null || typeof v !== "object") {
20
+ if (typeof v === "function" || v === void 0) return "null";
21
+ return JSON.stringify(v);
22
+ }
23
+ if (Array.isArray(v)) {
24
+ return "[" + v.map(stableStringify).join(",") + "]";
25
+ }
26
+ const obj = v;
27
+ const keys = Object.keys(obj).sort();
28
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
29
+ }
8
30
  var DEFAULT_MOTION_CONFIG = {
9
- reducedMotion: "user"
31
+ reducedMotion: "user",
32
+ transitions: {}
10
33
  };
11
34
  var MotionConfigContext = createContext(
12
35
  DEFAULT_MOTION_CONFIG
@@ -14,6 +37,9 @@ var MotionConfigContext = createContext(
14
37
  function useMotionConfig() {
15
38
  return useContext(MotionConfigContext);
16
39
  }
40
+ function useNamedTransitions() {
41
+ return useMotionConfig().transitions;
42
+ }
17
43
  function useShouldReduceMotion() {
18
44
  const { reducedMotion } = useMotionConfig();
19
45
  const osReduced = useReducedMotion();
@@ -22,15 +48,80 @@ function useShouldReduceMotion() {
22
48
  return osReduced;
23
49
  }
24
50
  function MotionConfig({
25
- reducedMotion = "user",
51
+ reducedMotion,
52
+ transitions,
26
53
  children
27
54
  }) {
55
+ const parent = useMotionConfig();
56
+ const transitionsSig = stableSig(transitions);
28
57
  const value = useMemo(
29
- () => ({ reducedMotion }),
30
- [reducedMotion]
58
+ () => ({
59
+ reducedMotion: reducedMotion ?? parent.reducedMotion,
60
+ transitions: transitions ? { ...parent.transitions, ...transitions } : parent.transitions
61
+ }),
62
+ // eslint-disable-next-line react-hooks/exhaustive-deps
63
+ [reducedMotion, transitionsSig, parent]
31
64
  );
32
65
  return /* @__PURE__ */ jsx(MotionConfigContext.Provider, { value, children });
33
66
  }
67
+
68
+ // src/transitions/keys.ts
69
+ var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
70
+ "type",
71
+ "tension",
72
+ "friction",
73
+ "mass",
74
+ "velocity",
75
+ "restSpeedThreshold",
76
+ "restDisplacementThreshold",
77
+ "duration",
78
+ "easing",
79
+ "delay",
80
+ "repeat",
81
+ "deceleration",
82
+ "clamp"
83
+ ]);
84
+ function isTopLevelTransition(t) {
85
+ if (t === null || typeof t !== "object") return false;
86
+ const keys = Object.keys(t);
87
+ if (keys.length === 0) return false;
88
+ return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
89
+ }
90
+
91
+ // src/config/namedTransitions.ts
92
+ var UNKNOWN_NAME_FALLBACK = { type: "spring" };
93
+ function lookupNamedTransition(name, registry) {
94
+ const cfg = registry[name];
95
+ if (cfg) return cfg;
96
+ if (__DEV__) {
97
+ console.warn(
98
+ `[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
99
+ );
100
+ }
101
+ return UNKNOWN_NAME_FALLBACK;
102
+ }
103
+ function resolveNamedTransition(input, registry) {
104
+ if (input === void 0) return void 0;
105
+ if (typeof input === "string") return lookupNamedTransition(input, registry);
106
+ return input;
107
+ }
108
+ function resolveNamedTransitionProp(transition, registry) {
109
+ if (transition === void 0) return void 0;
110
+ if (typeof transition === "string") {
111
+ return lookupNamedTransition(transition, registry);
112
+ }
113
+ if (isTopLevelTransition(transition)) return transition;
114
+ const map = transition;
115
+ let out = null;
116
+ for (const key in map) {
117
+ const value = map[key];
118
+ if (typeof value === "string") {
119
+ if (out === null) out = { ...map };
120
+ out[key] = lookupNamedTransition(value, registry);
121
+ }
122
+ }
123
+ return out ?? transition;
124
+ }
34
125
  var modality = "keyboard";
35
126
  var installed = false;
36
127
  function setKeyboard() {
@@ -458,28 +549,51 @@ function mergeTransition(base, override) {
458
549
  }
459
550
  return { ...base ?? { type: "spring" }, ...override };
460
551
  }
461
-
462
- // src/transitions/keys.ts
463
- var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
464
- "type",
465
- "tension",
466
- "friction",
467
- "mass",
468
- "velocity",
469
- "restSpeedThreshold",
470
- "restDisplacementThreshold",
471
- "duration",
472
- "easing",
473
- "delay",
474
- "repeat",
475
- "deceleration",
476
- "clamp"
477
- ]);
478
- function isTopLevelTransition(t) {
479
- if (t === null || typeof t !== "object") return false;
480
- const keys = Object.keys(t);
481
- if (keys.length === 0) return false;
482
- return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
552
+ var CSS_KEYWORDS = {
553
+ ease: [0.25, 0.1, 0.25, 1],
554
+ "ease-in": [0.42, 0, 1, 1],
555
+ "ease-out": [0, 0, 0.58, 1],
556
+ "ease-in-out": [0.42, 0, 0.58, 1]
557
+ };
558
+ var CSS_FUNCTION = /^cubic-bezier\((.*)\)$/;
559
+ function cubicBezier(first, y1, x2, y2) {
560
+ if (typeof first === "string") return fromCss(first);
561
+ return bezier(first, y1, x2, y2, void 0);
562
+ }
563
+ function fromCss(input) {
564
+ const token = input.trim().toLowerCase();
565
+ if (token === "linear") return Easing.linear;
566
+ const keyword = CSS_KEYWORDS[token];
567
+ if (keyword) return bezier(...keyword, input);
568
+ const match = CSS_FUNCTION.exec(token);
569
+ if (!match) {
570
+ throw new Error(
571
+ `[inertia] cubicBezier: unsupported easing token ${JSON.stringify(input)}. Expected four numbers, a 'cubic-bezier(x1, y1, x2, y2)' string, or one of the CSS keywords 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out'.`
572
+ );
573
+ }
574
+ const parts = match[1].split(",").map((p) => Number(p.trim()));
575
+ if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) {
576
+ throw new Error(
577
+ `[inertia] cubicBezier: could not parse ${JSON.stringify(input)} \u2014 expected exactly four finite numbers inside cubic-bezier(...).`
578
+ );
579
+ }
580
+ return bezier(parts[0], parts[1], parts[2], parts[3], input);
581
+ }
582
+ function bezier(x1, y1, x2, y2, source) {
583
+ const describe = () => source !== void 0 ? JSON.stringify(source) : `cubicBezier(${x1}, ${y1}, ${x2}, ${y2})`;
584
+ for (const n of [x1, y1, x2, y2]) {
585
+ if (typeof n !== "number" || !Number.isFinite(n)) {
586
+ throw new Error(
587
+ `[inertia] cubicBezier: ${describe()} \u2014 every control point must be a finite number.`
588
+ );
589
+ }
590
+ }
591
+ if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) {
592
+ throw new Error(
593
+ `[inertia] cubicBezier: ${describe()} \u2014 x1 and x2 must be within [0, 1] (got x1=${x1}, x2=${x2}).`
594
+ );
595
+ }
596
+ return Easing.bezier(x1, y1, x2, y2);
483
597
  }
484
598
  var DEFAULT_TIMING_DURATION2 = 250;
485
599
  function buildReleaseAnimation(transition, toValue) {
@@ -503,28 +617,6 @@ function buildReleaseAnimation(transition, toValue) {
503
617
  }
504
618
  return withSpring(toValue, springToReanimated(transition));
505
619
  }
506
-
507
- // src/transitions/sig.ts
508
- function stableSig(value) {
509
- if (value === void 0) return "";
510
- try {
511
- return stableStringify(value);
512
- } catch {
513
- return String(value);
514
- }
515
- }
516
- function stableStringify(v) {
517
- if (v === null || typeof v !== "object") {
518
- if (typeof v === "function" || v === void 0) return "null";
519
- return JSON.stringify(v);
520
- }
521
- if (Array.isArray(v)) {
522
- return "[" + v.map(stableStringify).join(",") + "]";
523
- }
524
- const obj = v;
525
- const keys = Object.keys(obj).sort();
526
- return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
527
- }
528
620
  var alreadyChecked = false;
529
621
  function ensureReanimatedInstalled() {
530
622
  if (!__DEV__ || alreadyChecked) return;
@@ -627,12 +719,14 @@ var DEFAULT_RESTING = {
627
719
  };
628
720
  function transitionFor(prop, transition) {
629
721
  if (!transition) return void 0;
722
+ if (typeof transition === "string") return void 0;
630
723
  if (isTopLevelTransition(transition)) return transition;
631
724
  if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
632
725
  return transition[prop];
633
726
  }
634
727
  function gestureLayerTransitionFor(layer, transition) {
635
728
  if (!transition) return void 0;
729
+ if (typeof transition === "string") return void 0;
636
730
  if (isTopLevelTransition(transition)) return transition;
637
731
  return transition[layer];
638
732
  }
@@ -647,17 +741,23 @@ function createMotionComponent(Component) {
647
741
  initial,
648
742
  animate,
649
743
  exit,
650
- transition,
744
+ transition: transitionProp,
651
745
  variants,
652
746
  controller,
653
747
  gesture,
654
- layout,
748
+ layout: layoutProp,
655
749
  layoutId,
656
750
  onAnimationEnd,
657
751
  style,
658
752
  onLayout: userOnLayout,
659
753
  ...rest
660
754
  } = props;
755
+ const namedTransitions = useNamedTransitions();
756
+ const transition = resolveNamedTransitionProp(
757
+ transitionProp,
758
+ namedTransitions
759
+ );
760
+ const layout = typeof layoutProp === "string" ? lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
661
761
  if (__DEV__ && typeof style === "function") {
662
762
  throw new Error(
663
763
  "[inertia] `style` must be a style object or array of style objects, not a function. The function-form `style={(state) => ...}` Pressable API is not supported \u2014 use `gesture.pressed` (or `gesture.focused`, etc.) to drive state-dependent styling instead."
@@ -1265,28 +1365,30 @@ var Motion = {
1265
1365
  function useAnimation(target, transition) {
1266
1366
  const output = useSharedValue(target);
1267
1367
  const shouldReduceMotion = useShouldReduceMotion();
1268
- const cfgSig = stableSig(transition);
1368
+ const resolved = resolveNamedTransition(transition, useNamedTransitions());
1369
+ const cfgSig = stableSig(resolved);
1269
1370
  useEffect(() => {
1270
- const cfg = shouldReduceMotion ? { type: "no-animation" } : transition ?? { type: "spring" };
1371
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : resolved ?? { type: "spring" };
1271
1372
  output.value = resolveTransition(cfg, target);
1272
1373
  }, [target, cfgSig, shouldReduceMotion]);
1273
1374
  return output;
1274
1375
  }
1275
1376
  function useSpring(target, config) {
1377
+ const spring = resolveSpringInput(config, useNamedTransitions());
1276
1378
  const reanimConfig = useMemo(
1277
- () => springToReanimated(config ?? {}),
1379
+ () => springToReanimated(spring ?? {}),
1278
1380
  // Keyed on the resolved primitive fields rather than the `config` object
1279
1381
  // identity: callers routinely pass a fresh object literal each render, so
1280
1382
  // depending on `config` itself would rebuild the Reanimated config on
1281
1383
  // every render and defeat the memo.
1282
1384
  // eslint-disable-next-line react-hooks/exhaustive-deps
1283
1385
  [
1284
- config?.tension,
1285
- config?.friction,
1286
- config?.mass,
1287
- config?.velocity,
1288
- config?.restSpeedThreshold,
1289
- config?.restDisplacementThreshold
1386
+ spring?.tension,
1387
+ spring?.friction,
1388
+ spring?.mass,
1389
+ spring?.velocity,
1390
+ spring?.restSpeedThreshold,
1391
+ spring?.restDisplacementThreshold
1290
1392
  ]
1291
1393
  );
1292
1394
  const isSharedTarget = isSharedValue(target);
@@ -1311,6 +1413,17 @@ function useSpring(target, config) {
1311
1413
  );
1312
1414
  return output;
1313
1415
  }
1416
+ function resolveSpringInput(config, registry) {
1417
+ if (typeof config !== "string") return config;
1418
+ const cfg = lookupNamedTransition(config, registry);
1419
+ if (cfg.type === void 0 || cfg.type === "spring") return cfg;
1420
+ if (__DEV__) {
1421
+ console.warn(
1422
+ `[inertia] Named transition "${config}" resolves to type '${cfg.type}', but useSpring / useBooleanSpring are spring-only \u2014 falling back to the default spring. Use useAnimation to honor non-spring named transitions.`
1423
+ );
1424
+ }
1425
+ return void 0;
1426
+ }
1314
1427
  function isSharedValue(v) {
1315
1428
  return typeof v === "object" && v !== null && "value" in v;
1316
1429
  }
@@ -1334,9 +1447,10 @@ function useGesture(transition) {
1334
1447
  const focusVisible = useSharedValue(0);
1335
1448
  const hovered = useSharedValue(0);
1336
1449
  const shouldReduceMotion = useShouldReduceMotion();
1450
+ const resolved = resolveNamedTransitionProp(transition, useNamedTransitions());
1337
1451
  const setLayer = useCallback(
1338
1452
  (sv, layer, target) => {
1339
- const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, transition) ?? { type: "spring" };
1453
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
1340
1454
  sv.value = resolveTransition(cfg, target);
1341
1455
  },
1342
1456
  // The transition is intentionally read on every call rather than cooked
@@ -1510,6 +1624,6 @@ function useVariants(variants, initial) {
1510
1624
  }, []);
1511
1625
  }
1512
1626
 
1513
- export { Motion, MotionConfig, MotionImage, MotionPressable, MotionScrollView, MotionText, MotionView, Presence, buildReleaseAnimation, createMotionComponent, ensureWorkletEasing, resolveAnimatableValue, resolveTransition, useAnimation, useBooleanSpring, useColorTransition, useGesture, useMotionConfig, useMotionValue, usePresence, useScroll, useShadow, useShouldReduceMotion, useSpring, useTransform, useVariants };
1627
+ export { Motion, MotionConfig, MotionImage, MotionPressable, MotionScrollView, MotionText, MotionView, Presence, buildReleaseAnimation, createMotionComponent, cubicBezier, ensureWorkletEasing, resolveAnimatableValue, resolveNamedTransition, resolveTransition, useAnimation, useBooleanSpring, useColorTransition, useGesture, useMotionConfig, useMotionValue, useNamedTransitions, usePresence, useScroll, useShadow, useShouldReduceMotion, useSpring, useTransform, useVariants };
1514
1628
  //# sourceMappingURL=index.mjs.map
1515
1629
  //# sourceMappingURL=index.mjs.map