@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.d.ts CHANGED
@@ -2,10 +2,10 @@ import * as react from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
3
  import * as react_native from 'react-native';
4
4
  import { NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
5
- import { M as MotionComponent, T as TransitionConfig, A as AnimatableValue, E as EasingInput, S as SpringTransition, V as VariantController } from './types-cU43dEmH.js';
6
- export { a as AnimateStyle, b as AnimationCallbackInfo, D as DecayTransition, G as GestureSubStates, c as MotionProps, N as NoAnimationTransition, P as PerPropertyTransition, R as RepeatConfig, d as SequenceStep, e as TimingTransition, f as Transition, g as VariantsMap } from './types-cU43dEmH.js';
5
+ import { M as MotionComponent, N as NamedTransitions, T as TransitionInput, a as TransitionConfig, A as AnimatableValue, E as EasingInput, S as SpringTransition, b as TransitionName, V as VariantController } from './types-BzEgiUdJ.js';
6
+ export { c as AnimateStyle, d as AnimationCallbackInfo, D as DecayTransition, e as EasingFunction, f as EasingFunctionFactory, G as GestureSubStates, g as MotionProps, h as NoAnimationTransition, P as PerPropertyTransition, R as RegisteredTransitions, i as RepeatConfig, j as SequenceStep, k as TimingTransition, l as Transition, m as VariantsMap } from './types-BzEgiUdJ.js';
7
7
  import { SharedValue, useAnimatedStyle } from 'react-native-reanimated';
8
- export { U as UseGestureHandlers, a as UseGestureResult, u as useGesture } from './useGesture-BnY65PlQ.js';
8
+ export { U as UseGestureHandlers, a as UseGestureResult, u as useGesture } from './useGesture-BRLgiNOC.js';
9
9
  export { MotionImage } from './motion/Image.js';
10
10
  export { MotionPressable } from './motion/Pressable.js';
11
11
  export { MotionScrollView } from './motion/ScrollView.js';
@@ -51,6 +51,12 @@ declare const Motion: {
51
51
  type ReducedMotion = 'user' | 'never' | 'always';
52
52
  interface MotionConfigValue {
53
53
  reducedMotion: ReducedMotion;
54
+ /**
55
+ * Named transitions registered by ancestor `<MotionConfig transitions>`
56
+ * providers, already merged (nearest provider wins per name). Empty with no
57
+ * provider — every name then resolves to the unknown-name fallback.
58
+ */
59
+ transitions: NamedTransitions;
54
60
  }
55
61
  /**
56
62
  * Read the active `<MotionConfig>` from a descendant. Returns the default
@@ -63,18 +69,64 @@ declare function useMotionConfig(): MotionConfigValue;
63
69
  * primitives call this to decide whether to swap transitions for
64
70
  * `no-animation`.
65
71
  */
72
+ /**
73
+ * Read the merged named-transition registry from the nearest `<MotionConfig>`
74
+ * ancestors. This is what the Motion primitives and value-layer hooks consult
75
+ * when a `TransitionName` string is passed where a `TransitionConfig` is
76
+ * accepted; custom animated components (and adapter packages) use it together
77
+ * with `resolveNamedTransition` to support names on their own surface.
78
+ */
79
+ declare function useNamedTransitions(): NamedTransitions;
66
80
  declare function useShouldReduceMotion(): boolean;
67
81
 
82
+ interface MotionConfigProps {
83
+ /**
84
+ * How descendants respond to reduced-motion preferences. Inherits from the
85
+ * nearest ancestor `<MotionConfig>` when omitted (the root default is
86
+ * `'user'` — respect the OS accessibility setting).
87
+ */
88
+ reducedMotion?: ReducedMotion;
89
+ /**
90
+ * Named transitions available to every descendant wherever a
91
+ * `TransitionConfig` is accepted — the `transition` prop (top-level and
92
+ * per-property), the `layout` prop, and the value-layer hooks:
93
+ *
94
+ * ```tsx
95
+ * <MotionConfig
96
+ * transitions={{
97
+ * 'state-press': { type: 'timing', duration: 100 },
98
+ * selection: { type: 'spring', tension: 380, friction: 33 },
99
+ * }}
100
+ * >
101
+ * <Motion.View animate={{ scale: 1 }} transition="selection" />
102
+ * </MotionConfig>
103
+ * ```
104
+ *
105
+ * Names resolve at the nearest provider; nested providers merge with the
106
+ * ancestor registry, child entries overriding same-named ancestor entries.
107
+ * Unknown names warn in dev and fall back to the library default spring.
108
+ * Names are consumer vocabulary — Inertia ships no presets.
109
+ */
110
+ transitions?: NamedTransitions;
111
+ children: ReactNode;
112
+ }
68
113
  /**
69
- * Provider that controls how descendant Motion primitives respond to
70
- * reduced-motion preferences. Wrap the root of your app once with the
114
+ * Provider for subtree-wide animation config: reduced-motion behaviour and
115
+ * the named-transition registry. Wrap the root of your app once with the
71
116
  * default (`reducedMotion="user"`) to respect the OS accessibility setting,
72
117
  * or scope a subtree with `'always'` / `'never'` for specific use cases.
118
+ * Nested providers inherit from their ancestor: an omitted prop keeps the
119
+ * ancestor's value, and `transitions` maps merge per name (child wins).
73
120
  */
74
- declare function MotionConfig({ reducedMotion, children, }: {
75
- reducedMotion?: ReducedMotion;
76
- children: ReactNode;
77
- }): react.JSX.Element;
121
+ declare function MotionConfig({ reducedMotion, transitions, children, }: MotionConfigProps): react.JSX.Element;
122
+
123
+ /**
124
+ * Resolve a single transition input — a `TransitionConfig` passes through
125
+ * untouched, a `TransitionName` is looked up in `registry`. This is the
126
+ * building block adapter packages use to accept names wherever they accept a
127
+ * config (pair it with `useNamedTransitions()` for the registry).
128
+ */
129
+ declare function resolveNamedTransition(input: TransitionInput | undefined, registry: NamedTransitions): TransitionConfig | undefined;
78
130
 
79
131
  /**
80
132
  * Wrap a list of children with mount / unmount transitions. When a child is
@@ -154,6 +206,47 @@ declare function resolveTransition(config: TransitionConfig | undefined, toValue
154
206
  */
155
207
  declare function resolveAnimatableValue<V extends number | string>(value: AnimatableValue<V>, base: TransitionConfig | undefined, factory?: CallbackFactory): unknown;
156
208
 
209
+ /**
210
+ * Build a `timing.easing` value from cubic-bezier control points — as four
211
+ * numbers, as a W3C CSS `cubic-bezier(...)` string, or as a CSS easing
212
+ * keyword. Design systems store easing tokens in the CSS format; this helper
213
+ * makes any such token file directly consumable without hand-translating to
214
+ * `Easing.bezier` calls:
215
+ *
216
+ * ```ts
217
+ * cubicBezier(0.2, 0, 0, 1) // number form
218
+ * cubicBezier('cubic-bezier(0.2, 0, 0, 1)') // CSS token form
219
+ * cubicBezier('ease-out') // CSS keywords, incl. 'linear'
220
+ * ```
221
+ *
222
+ * The return value is exactly what `timing.easing` accepts (Reanimated's
223
+ * bezier factory; the resolver worklet-wraps it via `ensureWorkletEasing`
224
+ * like every other easing input), so it works in the `transition` prop, in
225
+ * named transitions registered on `<MotionConfig transitions>`, and in the
226
+ * value-layer hooks:
227
+ *
228
+ * ```tsx
229
+ * <MotionConfig
230
+ * transitions={{
231
+ * 'state-hover': {
232
+ * type: 'timing',
233
+ * duration: 150,
234
+ * easing: cubicBezier(theme.motion.easingStandard),
235
+ * },
236
+ * }}
237
+ * >
238
+ * ```
239
+ *
240
+ * Invalid input **throws** rather than warning: easing tokens are constructed
241
+ * at theme/module setup, and a malformed token should fail loudly there, not
242
+ * silently animate with the wrong curve. Per the CSS spec, `x1` / `x2` must
243
+ * be within `[0, 1]` (`y1` / `y2` are unrestricted). The stepping keywords
244
+ * (`step-start` / `step-end`) and the CSS `linear(...)` function are not
245
+ * easing curves this helper produces — they're intentionally unsupported.
246
+ */
247
+ declare function cubicBezier(x1: number, y1: number, x2: number, y2: number): EasingInput;
248
+ declare function cubicBezier(css: string): EasingInput;
249
+
157
250
  /**
158
251
  * Reanimated 3.9+ validates that easing functions used in nested-transition
159
252
  * contexts (variants, sequences, per-property maps) are worklets, and crashes
@@ -200,7 +293,8 @@ declare function buildReleaseAnimation(transition: TransitionConfig, toValue: nu
200
293
 
201
294
  /**
202
295
  * Drive a `SharedValue<number>` toward `target` with **any** transition shape
203
- * — spring, timing, decay, or no-animation. The general-purpose value-layer
296
+ * — spring, timing, decay, or no-animation or a `TransitionName` registered
297
+ * on the nearest `<MotionConfig transitions>`. The general-purpose value-layer
204
298
  * hook: reach for it when you need raw `useSharedValue + useEffect + withX`
205
299
  * outside the declarative `animate` flow.
206
300
  *
@@ -242,7 +336,7 @@ declare function buildReleaseAnimation(transition: TransitionConfig, toValue: nu
242
336
  * })
243
337
  * ```
244
338
  */
245
- declare function useAnimation(target: number, transition?: TransitionConfig): SharedValue<number>;
339
+ declare function useAnimation(target: number, transition?: TransitionInput): SharedValue<number>;
246
340
 
247
341
  /**
248
342
  * Toggle a 0↔1 progress value with a spring whenever `active` flips.
@@ -265,9 +359,11 @@ declare function useAnimation(target: number, transition?: TransitionConfig): Sh
265
359
  *
266
360
  * The spring config follows the same react-spring vocabulary as the rest of
267
361
  * the library (`tension` / `friction` / `mass`); omit it to take the
268
- * library's defaults.
362
+ * library's defaults, or pass a `TransitionName` registered on the nearest
363
+ * `<MotionConfig transitions>` (spring-typed names only — see `useSpring`
364
+ * for the non-spring fallback behaviour).
269
365
  */
270
- declare function useBooleanSpring(active: boolean, springConfig?: SpringTransition): SharedValue<number>;
366
+ declare function useBooleanSpring(active: boolean, springConfig?: SpringTransition | TransitionName): SharedValue<number>;
271
367
 
272
368
  /**
273
369
  * Color style keys understood by React Native that this hook can target.
@@ -334,6 +430,8 @@ declare function useColorTransition(progress: SharedValue<number>, range: readon
334
430
  * onPress={() => { x.value = 100 }}
335
431
  * ```
336
432
  */
433
+ declare function useMotionValue(initial: number): SharedValue<number>;
434
+ declare function useMotionValue(initial: string): SharedValue<string>;
337
435
  declare function useMotionValue<T extends number | string>(initial: T): SharedValue<T>;
338
436
 
339
437
  /**
@@ -349,8 +447,14 @@ declare function useMotionValue<T extends number | string>(initial: T): SharedVa
349
447
  *
350
448
  * Both call sites end up at the same `withSpring` invocation; the split is
351
449
  * just about which thread observes the source change.
450
+ *
451
+ * `config` also accepts a `TransitionName` registered on the nearest
452
+ * `<MotionConfig transitions>`. Because this hook is spring-only, the name
453
+ * must resolve to a spring config — a name registered as timing / decay /
454
+ * no-animation warns in dev and falls back to the default spring (reach for
455
+ * `useAnimation` when the named transition's type should be honored).
352
456
  */
353
- declare function useSpring(target: number | SharedValue<number>, config?: SpringTransition): SharedValue<number>;
457
+ declare function useSpring(target: number | SharedValue<number>, config?: SpringTransition | TransitionName): SharedValue<number>;
354
458
 
355
459
  /**
356
460
  * Extrapolation behavior at the edges of the input range. Mirrors
@@ -415,10 +519,13 @@ interface UseScrollResult {
415
519
  * ```tsx
416
520
  * const { scrollY, onScroll } = useScroll()
417
521
  * const headerOpacity = useTransform(scrollY, [0, 100], [1, 0])
522
+ * const headerStyle = useAnimatedStyle(() => ({
523
+ * opacity: headerOpacity.value,
524
+ * }))
418
525
  *
419
526
  * return (
420
527
  * <>
421
- * <Motion.View animate={{ opacity: headerOpacity }} />
528
+ * <Animated.View style={headerStyle} />
422
529
  * <Motion.ScrollView onScroll={onScroll} scrollEventThrottle={16}>
423
530
  * …
424
531
  * </Motion.ScrollView>
@@ -426,6 +533,10 @@ interface UseScrollResult {
426
533
  * )
427
534
  * ```
428
535
  *
536
+ * The derived shared values are consumed through Reanimated interop
537
+ * (`useAnimatedStyle` / `useDerivedValue`) — the declarative `animate` prop
538
+ * takes target values, not shared values.
539
+ *
429
540
  * Scroll events fire on the UI thread, so `scrollX` / `scrollY` are safe to
430
541
  * read from any worklet (`useAnimatedStyle`, `useDerivedValue`,
431
542
  * `useTransform`) without a JS-thread bounce.
@@ -504,4 +615,4 @@ declare function useShadow({ from, to, progress, }: UseShadowOptions): ReturnTyp
504
615
  */
505
616
  declare function useVariants<V extends Readonly<Record<string, object>>>(variants: V, initial?: keyof V & string): VariantController<keyof V & string>;
506
617
 
507
- export { AnimatableValue, type ColorStyleKey, type ExtrapolationMode, Motion, MotionComponent, MotionConfig, type MotionConfigValue, Presence, type PresenceContextValue, type ReducedMotion, type ShadowConfig, SpringTransition, TransitionConfig, type UseColorTransitionOptions, type UseScrollResult, type UseShadowOptions, type UseTransformOptions, VariantController, buildReleaseAnimation, createMotionComponent, ensureWorkletEasing, resolveAnimatableValue, resolveTransition, useAnimation, useBooleanSpring, useColorTransition, useMotionConfig, useMotionValue, usePresence, useScroll, useShadow, useShouldReduceMotion, useSpring, useTransform, useVariants };
618
+ export { AnimatableValue, type ColorStyleKey, EasingInput, type ExtrapolationMode, Motion, MotionComponent, MotionConfig, type MotionConfigProps, type MotionConfigValue, NamedTransitions, Presence, type PresenceContextValue, type ReducedMotion, type ShadowConfig, SpringTransition, TransitionConfig, TransitionInput, TransitionName, type UseColorTransitionOptions, type UseScrollResult, type UseShadowOptions, type UseTransformOptions, VariantController, buildReleaseAnimation, createMotionComponent, cubicBezier, ensureWorkletEasing, resolveAnimatableValue, resolveNamedTransition, resolveTransition, useAnimation, useBooleanSpring, useColorTransition, useMotionConfig, useMotionValue, useNamedTransitions, usePresence, useScroll, useShadow, useShouldReduceMotion, useSpring, useTransform, useVariants };
package/dist/index.js CHANGED
@@ -11,8 +11,31 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
  var Animated__default = /*#__PURE__*/_interopDefault(Animated);
12
12
 
13
13
  // src/motion/Image.tsx
14
+
15
+ // src/transitions/sig.ts
16
+ function stableSig(value) {
17
+ if (value === void 0) return "";
18
+ try {
19
+ return stableStringify(value);
20
+ } catch {
21
+ return String(value);
22
+ }
23
+ }
24
+ function stableStringify(v) {
25
+ if (v === null || typeof v !== "object") {
26
+ if (typeof v === "function" || v === void 0) return "null";
27
+ return JSON.stringify(v);
28
+ }
29
+ if (Array.isArray(v)) {
30
+ return "[" + v.map(stableStringify).join(",") + "]";
31
+ }
32
+ const obj = v;
33
+ const keys = Object.keys(obj).sort();
34
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
35
+ }
14
36
  var DEFAULT_MOTION_CONFIG = {
15
- reducedMotion: "user"
37
+ reducedMotion: "user",
38
+ transitions: {}
16
39
  };
17
40
  var MotionConfigContext = react.createContext(
18
41
  DEFAULT_MOTION_CONFIG
@@ -20,6 +43,9 @@ var MotionConfigContext = react.createContext(
20
43
  function useMotionConfig() {
21
44
  return react.useContext(MotionConfigContext);
22
45
  }
46
+ function useNamedTransitions() {
47
+ return useMotionConfig().transitions;
48
+ }
23
49
  function useShouldReduceMotion() {
24
50
  const { reducedMotion } = useMotionConfig();
25
51
  const osReduced = Animated.useReducedMotion();
@@ -28,15 +54,80 @@ function useShouldReduceMotion() {
28
54
  return osReduced;
29
55
  }
30
56
  function MotionConfig({
31
- reducedMotion = "user",
57
+ reducedMotion,
58
+ transitions,
32
59
  children
33
60
  }) {
61
+ const parent = useMotionConfig();
62
+ const transitionsSig = stableSig(transitions);
34
63
  const value = react.useMemo(
35
- () => ({ reducedMotion }),
36
- [reducedMotion]
64
+ () => ({
65
+ reducedMotion: reducedMotion ?? parent.reducedMotion,
66
+ transitions: transitions ? { ...parent.transitions, ...transitions } : parent.transitions
67
+ }),
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ [reducedMotion, transitionsSig, parent]
37
70
  );
38
71
  return /* @__PURE__ */ jsxRuntime.jsx(MotionConfigContext.Provider, { value, children });
39
72
  }
73
+
74
+ // src/transitions/keys.ts
75
+ var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
76
+ "type",
77
+ "tension",
78
+ "friction",
79
+ "mass",
80
+ "velocity",
81
+ "restSpeedThreshold",
82
+ "restDisplacementThreshold",
83
+ "duration",
84
+ "easing",
85
+ "delay",
86
+ "repeat",
87
+ "deceleration",
88
+ "clamp"
89
+ ]);
90
+ function isTopLevelTransition(t) {
91
+ if (t === null || typeof t !== "object") return false;
92
+ const keys = Object.keys(t);
93
+ if (keys.length === 0) return false;
94
+ return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
95
+ }
96
+
97
+ // src/config/namedTransitions.ts
98
+ var UNKNOWN_NAME_FALLBACK = { type: "spring" };
99
+ function lookupNamedTransition(name, registry) {
100
+ const cfg = registry[name];
101
+ if (cfg) return cfg;
102
+ if (__DEV__) {
103
+ console.warn(
104
+ `[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
105
+ );
106
+ }
107
+ return UNKNOWN_NAME_FALLBACK;
108
+ }
109
+ function resolveNamedTransition(input, registry) {
110
+ if (input === void 0) return void 0;
111
+ if (typeof input === "string") return lookupNamedTransition(input, registry);
112
+ return input;
113
+ }
114
+ function resolveNamedTransitionProp(transition, registry) {
115
+ if (transition === void 0) return void 0;
116
+ if (typeof transition === "string") {
117
+ return lookupNamedTransition(transition, registry);
118
+ }
119
+ if (isTopLevelTransition(transition)) return transition;
120
+ const map = transition;
121
+ let out = null;
122
+ for (const key in map) {
123
+ const value = map[key];
124
+ if (typeof value === "string") {
125
+ if (out === null) out = { ...map };
126
+ out[key] = lookupNamedTransition(value, registry);
127
+ }
128
+ }
129
+ return out ?? transition;
130
+ }
40
131
  var modality = "keyboard";
41
132
  var installed = false;
42
133
  function setKeyboard() {
@@ -464,28 +555,51 @@ function mergeTransition(base, override) {
464
555
  }
465
556
  return { ...base ?? { type: "spring" }, ...override };
466
557
  }
467
-
468
- // src/transitions/keys.ts
469
- var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
470
- "type",
471
- "tension",
472
- "friction",
473
- "mass",
474
- "velocity",
475
- "restSpeedThreshold",
476
- "restDisplacementThreshold",
477
- "duration",
478
- "easing",
479
- "delay",
480
- "repeat",
481
- "deceleration",
482
- "clamp"
483
- ]);
484
- function isTopLevelTransition(t) {
485
- if (t === null || typeof t !== "object") return false;
486
- const keys = Object.keys(t);
487
- if (keys.length === 0) return false;
488
- return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
558
+ var CSS_KEYWORDS = {
559
+ ease: [0.25, 0.1, 0.25, 1],
560
+ "ease-in": [0.42, 0, 1, 1],
561
+ "ease-out": [0, 0, 0.58, 1],
562
+ "ease-in-out": [0.42, 0, 0.58, 1]
563
+ };
564
+ var CSS_FUNCTION = /^cubic-bezier\((.*)\)$/;
565
+ function cubicBezier(first, y1, x2, y2) {
566
+ if (typeof first === "string") return fromCss(first);
567
+ return bezier(first, y1, x2, y2, void 0);
568
+ }
569
+ function fromCss(input) {
570
+ const token = input.trim().toLowerCase();
571
+ if (token === "linear") return Animated.Easing.linear;
572
+ const keyword = CSS_KEYWORDS[token];
573
+ if (keyword) return bezier(...keyword, input);
574
+ const match = CSS_FUNCTION.exec(token);
575
+ if (!match) {
576
+ throw new Error(
577
+ `[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'.`
578
+ );
579
+ }
580
+ const parts = match[1].split(",").map((p) => Number(p.trim()));
581
+ if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) {
582
+ throw new Error(
583
+ `[inertia] cubicBezier: could not parse ${JSON.stringify(input)} \u2014 expected exactly four finite numbers inside cubic-bezier(...).`
584
+ );
585
+ }
586
+ return bezier(parts[0], parts[1], parts[2], parts[3], input);
587
+ }
588
+ function bezier(x1, y1, x2, y2, source) {
589
+ const describe = () => source !== void 0 ? JSON.stringify(source) : `cubicBezier(${x1}, ${y1}, ${x2}, ${y2})`;
590
+ for (const n of [x1, y1, x2, y2]) {
591
+ if (typeof n !== "number" || !Number.isFinite(n)) {
592
+ throw new Error(
593
+ `[inertia] cubicBezier: ${describe()} \u2014 every control point must be a finite number.`
594
+ );
595
+ }
596
+ }
597
+ if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) {
598
+ throw new Error(
599
+ `[inertia] cubicBezier: ${describe()} \u2014 x1 and x2 must be within [0, 1] (got x1=${x1}, x2=${x2}).`
600
+ );
601
+ }
602
+ return Animated.Easing.bezier(x1, y1, x2, y2);
489
603
  }
490
604
  var DEFAULT_TIMING_DURATION2 = 250;
491
605
  function buildReleaseAnimation(transition, toValue) {
@@ -509,28 +623,6 @@ function buildReleaseAnimation(transition, toValue) {
509
623
  }
510
624
  return Animated.withSpring(toValue, springToReanimated(transition));
511
625
  }
512
-
513
- // src/transitions/sig.ts
514
- function stableSig(value) {
515
- if (value === void 0) return "";
516
- try {
517
- return stableStringify(value);
518
- } catch {
519
- return String(value);
520
- }
521
- }
522
- function stableStringify(v) {
523
- if (v === null || typeof v !== "object") {
524
- if (typeof v === "function" || v === void 0) return "null";
525
- return JSON.stringify(v);
526
- }
527
- if (Array.isArray(v)) {
528
- return "[" + v.map(stableStringify).join(",") + "]";
529
- }
530
- const obj = v;
531
- const keys = Object.keys(obj).sort();
532
- return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
533
- }
534
626
  var alreadyChecked = false;
535
627
  function ensureReanimatedInstalled() {
536
628
  if (!__DEV__ || alreadyChecked) return;
@@ -633,12 +725,14 @@ var DEFAULT_RESTING = {
633
725
  };
634
726
  function transitionFor(prop, transition) {
635
727
  if (!transition) return void 0;
728
+ if (typeof transition === "string") return void 0;
636
729
  if (isTopLevelTransition(transition)) return transition;
637
730
  if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
638
731
  return transition[prop];
639
732
  }
640
733
  function gestureLayerTransitionFor(layer, transition) {
641
734
  if (!transition) return void 0;
735
+ if (typeof transition === "string") return void 0;
642
736
  if (isTopLevelTransition(transition)) return transition;
643
737
  return transition[layer];
644
738
  }
@@ -653,17 +747,23 @@ function createMotionComponent(Component) {
653
747
  initial,
654
748
  animate,
655
749
  exit,
656
- transition,
750
+ transition: transitionProp,
657
751
  variants,
658
752
  controller,
659
753
  gesture,
660
- layout,
754
+ layout: layoutProp,
661
755
  layoutId,
662
756
  onAnimationEnd,
663
757
  style,
664
758
  onLayout: userOnLayout,
665
759
  ...rest
666
760
  } = props;
761
+ const namedTransitions = useNamedTransitions();
762
+ const transition = resolveNamedTransitionProp(
763
+ transitionProp,
764
+ namedTransitions
765
+ );
766
+ const layout = typeof layoutProp === "string" ? lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
667
767
  if (__DEV__ && typeof style === "function") {
668
768
  throw new Error(
669
769
  "[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."
@@ -1271,28 +1371,30 @@ var Motion = {
1271
1371
  function useAnimation(target, transition) {
1272
1372
  const output = Animated.useSharedValue(target);
1273
1373
  const shouldReduceMotion = useShouldReduceMotion();
1274
- const cfgSig = stableSig(transition);
1374
+ const resolved = resolveNamedTransition(transition, useNamedTransitions());
1375
+ const cfgSig = stableSig(resolved);
1275
1376
  react.useEffect(() => {
1276
- const cfg = shouldReduceMotion ? { type: "no-animation" } : transition ?? { type: "spring" };
1377
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : resolved ?? { type: "spring" };
1277
1378
  output.value = resolveTransition(cfg, target);
1278
1379
  }, [target, cfgSig, shouldReduceMotion]);
1279
1380
  return output;
1280
1381
  }
1281
1382
  function useSpring(target, config) {
1383
+ const spring = resolveSpringInput(config, useNamedTransitions());
1282
1384
  const reanimConfig = react.useMemo(
1283
- () => springToReanimated(config ?? {}),
1385
+ () => springToReanimated(spring ?? {}),
1284
1386
  // Keyed on the resolved primitive fields rather than the `config` object
1285
1387
  // identity: callers routinely pass a fresh object literal each render, so
1286
1388
  // depending on `config` itself would rebuild the Reanimated config on
1287
1389
  // every render and defeat the memo.
1288
1390
  // eslint-disable-next-line react-hooks/exhaustive-deps
1289
1391
  [
1290
- config?.tension,
1291
- config?.friction,
1292
- config?.mass,
1293
- config?.velocity,
1294
- config?.restSpeedThreshold,
1295
- config?.restDisplacementThreshold
1392
+ spring?.tension,
1393
+ spring?.friction,
1394
+ spring?.mass,
1395
+ spring?.velocity,
1396
+ spring?.restSpeedThreshold,
1397
+ spring?.restDisplacementThreshold
1296
1398
  ]
1297
1399
  );
1298
1400
  const isSharedTarget = isSharedValue(target);
@@ -1317,6 +1419,17 @@ function useSpring(target, config) {
1317
1419
  );
1318
1420
  return output;
1319
1421
  }
1422
+ function resolveSpringInput(config, registry) {
1423
+ if (typeof config !== "string") return config;
1424
+ const cfg = lookupNamedTransition(config, registry);
1425
+ if (cfg.type === void 0 || cfg.type === "spring") return cfg;
1426
+ if (__DEV__) {
1427
+ console.warn(
1428
+ `[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.`
1429
+ );
1430
+ }
1431
+ return void 0;
1432
+ }
1320
1433
  function isSharedValue(v) {
1321
1434
  return typeof v === "object" && v !== null && "value" in v;
1322
1435
  }
@@ -1340,9 +1453,10 @@ function useGesture(transition) {
1340
1453
  const focusVisible = Animated.useSharedValue(0);
1341
1454
  const hovered = Animated.useSharedValue(0);
1342
1455
  const shouldReduceMotion = useShouldReduceMotion();
1456
+ const resolved = resolveNamedTransitionProp(transition, useNamedTransitions());
1343
1457
  const setLayer = react.useCallback(
1344
1458
  (sv, layer, target) => {
1345
- const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, transition) ?? { type: "spring" };
1459
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
1346
1460
  sv.value = resolveTransition(cfg, target);
1347
1461
  },
1348
1462
  // The transition is intentionally read on every call rather than cooked
@@ -1526,8 +1640,10 @@ exports.MotionView = MotionView;
1526
1640
  exports.Presence = Presence;
1527
1641
  exports.buildReleaseAnimation = buildReleaseAnimation;
1528
1642
  exports.createMotionComponent = createMotionComponent;
1643
+ exports.cubicBezier = cubicBezier;
1529
1644
  exports.ensureWorkletEasing = ensureWorkletEasing;
1530
1645
  exports.resolveAnimatableValue = resolveAnimatableValue;
1646
+ exports.resolveNamedTransition = resolveNamedTransition;
1531
1647
  exports.resolveTransition = resolveTransition;
1532
1648
  exports.useAnimation = useAnimation;
1533
1649
  exports.useBooleanSpring = useBooleanSpring;
@@ -1535,6 +1651,7 @@ exports.useColorTransition = useColorTransition;
1535
1651
  exports.useGesture = useGesture;
1536
1652
  exports.useMotionConfig = useMotionConfig;
1537
1653
  exports.useMotionValue = useMotionValue;
1654
+ exports.useNamedTransitions = useNamedTransitions;
1538
1655
  exports.usePresence = usePresence;
1539
1656
  exports.useScroll = useScroll;
1540
1657
  exports.useShadow = useShadow;