@rootnative/inertia 0.0.9 → 0.0.10

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 (100) hide show
  1. package/CHANGELOG.md +68 -1
  2. package/README.md +7 -7
  3. package/dist/applyBounds-BYGiHrYO.d.mts +18 -0
  4. package/dist/applyBounds-BYGiHrYO.d.ts +18 -0
  5. package/dist/{chunk-E3ALFSH2.js → chunk-2UGWAB6N.js} +78 -70
  6. package/dist/{chunk-ZBHQPVWE.js → chunk-3ZNHPT5Z.js} +2 -2
  7. package/dist/{chunk-IHVMNOS4.js → chunk-46766TBM.js} +2 -2
  8. package/dist/{chunk-MUT6BTZS.js → chunk-4EZ5DBL3.js} +10 -7
  9. package/dist/{chunk-MFAFB4K7.mjs → chunk-6FCATUMY.mjs} +8 -10
  10. package/dist/{chunk-6YIUETBF.mjs → chunk-7BH3CAO5.mjs} +1 -1
  11. package/dist/{chunk-JBK5ZLMH.mjs → chunk-CUHOCONB.mjs} +1 -1
  12. package/dist/{chunk-M4766VUV.mjs → chunk-DRA2K53O.mjs} +1 -1
  13. package/dist/{chunk-L4JFECXU.mjs → chunk-F4HMCXAX.mjs} +6 -3
  14. package/dist/{chunk-W7NTRSPD.mjs → chunk-HEAWMZEM.mjs} +105 -66
  15. package/dist/{chunk-IX6SEOSK.mjs → chunk-JENYDTXH.mjs} +52 -44
  16. package/dist/chunk-KFHZMFAX.js +23 -0
  17. package/dist/{chunk-6AN5X3YE.js → chunk-KXU6VH2Y.js} +10 -11
  18. package/dist/{chunk-WNVHPMBI.js → chunk-N33GSDNQ.js} +106 -65
  19. package/dist/chunk-OH46TGEA.mjs +20 -0
  20. package/dist/{chunk-QNLSCOR5.mjs → chunk-OLOSU2BD.mjs} +1 -1
  21. package/dist/chunk-PLKXCJIB.js +8 -0
  22. package/dist/{chunk-GSUC4HWP.mjs → chunk-QXKPIENP.mjs} +1 -1
  23. package/dist/chunk-UBHQJFUW.js +8 -0
  24. package/dist/{chunk-6NOCY764.js → chunk-VKXSL3ZL.js} +2 -2
  25. package/dist/chunk-XKNEQDAT.js +8 -0
  26. package/dist/{chunk-EN4PN7X3.mjs → chunk-Z23AMUSW.mjs} +1 -1
  27. package/dist/gestureLayer/index.d.mts +3 -3
  28. package/dist/gestureLayer/index.d.ts +3 -3
  29. package/dist/gestureLayer/index.js +12 -18
  30. package/dist/gestureLayer/index.mjs +5 -11
  31. package/dist/index.d.mts +87 -45
  32. package/dist/index.d.ts +87 -45
  33. package/dist/index.js +114 -91
  34. package/dist/index.mjs +66 -59
  35. package/dist/motion/FlatList.d.mts +1 -1
  36. package/dist/motion/FlatList.d.ts +1 -1
  37. package/dist/motion/FlatList.js +5 -5
  38. package/dist/motion/FlatList.mjs +4 -4
  39. package/dist/motion/Image.d.mts +1 -1
  40. package/dist/motion/Image.d.ts +1 -1
  41. package/dist/motion/Image.js +5 -5
  42. package/dist/motion/Image.mjs +4 -4
  43. package/dist/motion/Pressable.d.mts +1 -1
  44. package/dist/motion/Pressable.d.ts +1 -1
  45. package/dist/motion/Pressable.js +5 -5
  46. package/dist/motion/Pressable.mjs +4 -4
  47. package/dist/motion/ScrollView.d.mts +1 -1
  48. package/dist/motion/ScrollView.d.ts +1 -1
  49. package/dist/motion/ScrollView.js +5 -5
  50. package/dist/motion/ScrollView.mjs +4 -4
  51. package/dist/motion/Text.d.mts +1 -1
  52. package/dist/motion/Text.d.ts +1 -1
  53. package/dist/motion/Text.js +5 -5
  54. package/dist/motion/Text.mjs +4 -4
  55. package/dist/motion/View.d.mts +1 -1
  56. package/dist/motion/View.d.ts +1 -1
  57. package/dist/motion/View.js +5 -5
  58. package/dist/motion/View.mjs +4 -4
  59. package/dist/touch/index.d.mts +2 -1
  60. package/dist/touch/index.d.ts +2 -1
  61. package/dist/touch/index.js +16 -31
  62. package/dist/touch/index.mjs +11 -29
  63. package/dist/{types-DyJpG64F.d.mts → types-08mG8fNk.d.mts} +10 -3
  64. package/dist/{types-DyJpG64F.d.ts → types-08mG8fNk.d.ts} +10 -3
  65. package/dist/{useGesture-DbH46EBp.d.ts → useGesture-D1lHeQQ6.d.ts} +1 -1
  66. package/dist/{useGesture-CnZQnYHH.d.mts → useGesture-DjszaHWz.d.mts} +1 -1
  67. package/package.json +4 -2
  68. package/src/config/namedTransitions.ts +7 -9
  69. package/src/gestureLayer/index.ts +3 -0
  70. package/src/gestureLayer/useGestureLayer.ts +6 -9
  71. package/src/gestures/focusVisibility.ts +19 -17
  72. package/src/gestures/index.ts +1 -1
  73. package/src/index.ts +9 -0
  74. package/src/layout/resolveLayout.ts +4 -1
  75. package/src/layout/useSharedLayout.ts +2 -1
  76. package/src/motion/createMotionComponent.tsx +92 -44
  77. package/src/presence/Presence.tsx +5 -7
  78. package/src/touch/applyBounds.ts +30 -0
  79. package/src/touch/index.ts +1 -0
  80. package/src/touch/useTouchDrag.ts +15 -45
  81. package/src/transitions/constants.ts +14 -0
  82. package/src/transitions/easing.ts +23 -11
  83. package/src/transitions/index.ts +5 -0
  84. package/src/transitions/keys.ts +0 -2
  85. package/src/transitions/resolve.ts +86 -11
  86. package/src/transitions/resolveSequence.ts +3 -1
  87. package/src/transitions/runtime.ts +4 -7
  88. package/src/transitions/spring.ts +7 -2
  89. package/src/types.ts +9 -2
  90. package/src/values/extrapolation.ts +21 -0
  91. package/src/values/index.ts +1 -0
  92. package/src/values/useGesture.ts +9 -2
  93. package/src/values/useInterpolatedStyle.ts +5 -12
  94. package/src/values/useShadow.ts +18 -7
  95. package/src/values/useSpring.ts +34 -25
  96. package/src/values/useTransform.ts +24 -20
  97. package/src/values/useTranslateStyle.ts +31 -0
  98. package/dist/chunk-24NUL23E.js +0 -8
  99. package/dist/chunk-4XBX7KOD.js +0 -8
  100. package/dist/chunk-Z5USXWTE.js +0 -8
package/CHANGELOG.md CHANGED
@@ -4,6 +4,72 @@ All notable changes to `@rootnative/inertia` are documented here. The format fol
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.0.10] - 2026-09-06
8
+
9
+ ### Changed
10
+
11
+ - **`react-native-worklets` is a required peer, not an optional one.** Core imports `isWorkletFunction` from it without a guard in `transitions/easing.ts` and `values/useTransform.ts`, so the package never worked without it. The `optional: true` flag in `peerDependenciesMeta` is removed. A package manager now warns when the peer is missing instead of staying silent. The installation docs already list it as a peer, so no install step changes. Core also declares it as a devDependency, pinned to `~0.5.1` next to Reanimated `~4.1.1`; before, the workspace typecheck passed only because the example app hoisted it. Found by the `1.0.0` readiness audit (2026-09-05).
12
+
13
+ - **`@testing-library/react-native` is declared as an optional peer (`>=13.0.0`).** The `@rootnative/inertia/testing` entry point imports its `render`, but no field in `package.json` said so. A consumer without the library got a bare module-not-found error from that subpath. It is optional because only that entry point needs it. The docs testing page now names the requirement. Found by the `1.0.0` readiness audit (2026-09-05).
14
+
15
+ ### Removed
16
+
17
+ - **Breaking: `restSpeedThreshold` and `restDisplacementThreshold` are removed from `SpringTransition`.** Both keys were silently inert on every release since `0.0.1`. They are Reanimated 3 names: Reanimated 4 settles springs on an internal `energyThreshold`, its `SpringConfig` type does not have either key, and its runtime never reads them. Inertia forwarded both into `withSpring`, where they were ignored — a documented public key that did nothing, which is the defect class the `0.0.5` type narrowing exists to prevent. Found by the pre-`1.0.0` review of the transition vocabulary.
18
+
19
+ Migration: delete the two keys from any spring config. Their removal cannot change animation behavior, because they never had any. If a settle knob is needed later, Reanimated 4's `overshootClamping` / `energyThreshold` are the candidates, as a non-breaking addition.
20
+
21
+ ### Fixed
22
+
23
+ - **`repeat: 0` (and any count below 1) runs the animation once instead of forever.** Reanimated's `withRepeat` reads a count of `0` or less as endless, and the resolver forwarded the count as given, so `repeat: 0` — the natural way to write "do not repeat" from a variable — looped without end. Counts below `1` are now treated as "run once", warn once in dev, and are not forwarded. `onAnimationEnd`'s iteration counter and `<Presence>`'s settle gate use the same rule through the new `repeatIterationsOf` helper, so the three cannot disagree. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
24
+
25
+ - **`repeat.alternate` is no longer forwarded for a sequence, and an explicit `alternate: true` on a sequence warns.** Reanimated's `reverse` flag only swaps the wrapped animation's target, which a `withSequence` ignores — every pass restarts at the first step — so the flag never alternated a sequence. The resolver now passes `reverse: false` for sequences, the `RepeatConfig` docs state the limit, and the sequences page shows the working form: write the reverse steps into the sequence. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
26
+
27
+ - **`<Presence>` no longer releases an exiting child early when its animation run is replaced mid-exit.** The settle counter that gates `safeToRemove` counted every callback, including the `finished: false` callbacks Reanimated fires for animations that a later effect run replaced. If the value-driving effect re-ran during an exit (a controller change, a reduce-motion flip), the replaced run drained its own counter and unmounted the child while the new run was still animating. Each run is now a token: the effect's cleanup marks the run done, and a superseded run's callbacks are ignored. Pinned by `phase3-audit.test.tsx`, which fails against the previous implementation. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
28
+
29
+ - **An `onAnimationEnd` handler added after mount is wired without waiting for the next animation change.** The callback factory skips callback installation when there is no handler and nothing to settle. A handler that went from `undefined` to defined on a later render was read through a ref, but no callback existed to read it, so it stayed silent until `animate` or `transition` changed. The effect is now also keyed on the handler's presence (not its identity — a changing handler still costs nothing). Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
30
+
31
+ - **`useSpring` and `useBooleanSpring` honour reduced motion.** Under `<MotionConfig reducedMotion>` both hooks assign the target to the output directly, with no spring, on the plain-number path and the shared-value path. They were the only value-layer hooks that ignored the setting. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
32
+
33
+ - **Dev warnings fire once per misconfiguration, not once per render.** The unknown-variant warning (`animate="open"` with no matching variant), the unknown named-transition warning, the `<Presence>` keyless-child warning, the `useSpring` spring-only warning, and the `useInterpolatedStyle` range-length warning all went through a bare `console.warn` in render or in a per-render resolver, so a single mistake flooded the console. All now use `warnOnce`, keyed per distinct misconfiguration. `useSwipe`'s decay `releaseTransition` warning in `-gestures` is guarded the same way. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
34
+
35
+ - **`useTouchDrag` no longer rebuilds its `PanResponder` when an inline callback changes identity.** `onDragStart` / `onDragEnd` / `onRelease` were dependencies of the responder memo, so `onRelease={(e) => ...}` written inline rebuilt the responder on every render. The callbacks are now read through a ref at call time; the responder depends only on the axis, constraint, and elastic scalars, and it always calls the latest callback. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
36
+
37
+ - **`useShadow`, `useTransform`, and `useGestureLayer` no longer rebuild their worklet for inline literals.** `useShadow` re-parsed the `boxShadow` pairs on every render, `useTransform` captured a fresh `inputRange` / `outputRange` array, and `useGestureLayer` keyed its per-key table on the identity of each `states` layer object. Each render with inline literals — the documented way to call all three — produced a new UI-thread closure. All three now memoise on a structural signature (`stableSig`). Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
38
+
39
+ - **`sideEffects: false` is now true.** The `focusVisible` input-modality tracker attached its web `document` listeners at import time, which is a side effect the package declared it did not have. The listeners now attach from a mount effect of the first component that tracks `focusVisible` (the `gesture` prop or `useGesture`). Mount time is early enough: the click that focuses an element lands on an element that is already mounted, so the preceding `mousedown` is observed. `installFocusVisibility` is exported from `./gestures` for the same purpose. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
40
+
41
+ - **A key added to `animate` after mount now animates on native.** The `useAnimatedStyle` worklet read the active key set through plain `useRef` objects. `react-native-worklets` clones a captured plain object once, when the worklet is first serialised, and in dev it freezes the original, so later writes to `.current` were dropped with a `Tried to modify key 'current'` warning. The worklet only ever saw the mount-time set: a parent that changed `animate={{ opacity: 1 }}` to `animate={{ opacity: 1, translateX: 120 }}` drove the `translateX` shared value, but the element did not move. The set now crosses to the UI thread through a shared value that is rewritten once per growth. The Jest mock runs the worklet on the JS thread and never showed the defect; it was confirmed and fixed against an Android emulator. Found by the `1.0.0` readiness audit (2026-09-05).
42
+
43
+ - **`useSpring` follows a swapped `SharedValue` target.** The UI-thread reaction listed only the target kind and the spring config as dependencies, and an explicit list replaces Reanimated's closure-derived one. A caller that changed which shared value drives the spring kept the reaction wired to the first one. The current target is now in the list; a plain-number target maps to `null` there, so a changing number does not re-register the inert reaction. Found by the `1.0.0` readiness audit (2026-09-05).
44
+
45
+ ### Added
46
+
47
+ - **`useTranslateStyle(x, y)` is exported from the root barrel.** The `transform: [{ translateX }, { translateY }]` animated style that `useTouchDrag`, `useDrag`, `usePan`, and `useSwipe` all return; the four hooks now share this one implementation. Use it directly when a custom gesture owns its own translation values. Documented in `docs/docs/api/hooks.md`. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
48
+
49
+ - **`applyBounds(value, min, max, elastic)` is exported from the root barrel.** The worklet-safe clamp with optional rubber-band overshoot that `useTouchDrag` and `-gestures`' `useDrag` apply their `constraints` and `elastic` options through; the two hooks carried identical private copies. Documented in `docs/docs/api/hooks.md`. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
50
+
51
+ - **`isTopLevelTransition(value)` is exported from the root barrel.** It is the structural discriminator the factory uses to tell a single `TransitionConfig` from a per-property map: every key must be a known config field. Custom animated components that accept both shapes need the same test; `'type' in transition` is wrong because `SpringTransition.type` is optional. The three adapter packages had that bug and now use this export; see `docs/docs/api/transition-utilities.md`.
52
+
53
+ - **`stableSig(value)` is exported from the root barrel.** It is the order-independent structural signature the factory already keys its `transition` effects on. Custom animated components built on `resolveTransition` need the same thing: an inline `transition` literal is a new object every render, so an effect keyed on its identity restarts the animation each time the parent renders. The three adapter packages now use it for exactly that; see `docs/docs/api/transition-utilities.md`.
54
+
55
+ - **Three types that already appeared in exported signatures are now exported.** `GestureLayerTransitions` (the per-layer form of a gesture `transition`; from the root and from `@rootnative/inertia/gesture-layer`), `CallbackFactory` (the third parameter of `resolveAnimatableValue`), and `MotionComponentProps` (the props of a `Motion.*` primitive for a given component, for typing a wrapper). Pinned by `__type-tests__/public-types.test-d.tsx`. Found by the `1.0.0` readiness audit (2026-09-05).
56
+
57
+ - **Dev warning when `controller` and `animate` are set on the same primitive.** The controller drives the animation and `animate` is ignored; that precedence was documented but silent. It now warns once in dev.
58
+
59
+ ### Documentation
60
+
61
+ - `useVariants` documents that the controller pins the variants map from the first render, and that later renders passing a different map object do not re-key it.
62
+
63
+ - `RepeatConfig` and the sequences page document the count rule (total iterations, minimum `1`) and the `alternate` limit for sequences. `useSpring` documents that it honours reduced motion.
64
+
65
+ ### Internal
66
+
67
+ - The adapter peer range on `@rootnative/inertia` now has an upper bound: `>=<version> <next-minor>` instead of `>=<version>`. Pre-`1.0.0`, a minor bump is where a breaking change lands, so an adapter at `0.0.x` must not accept core `0.1.0`. `scripts/check-versions.mjs` check 2 and both release workflows compute the same bound. Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
68
+
69
+ - Duplicated code consolidated: `mapExtrapolation` (was in `useTransform` and `useInterpolatedStyle`) lives in `values/extrapolation.ts`; `DEFAULT_TIMING_DURATION` (250 ms, was declared in both `resolve.ts` and `runtime.ts`) and `DEFAULT_LAYOUT_DURATION` (300 ms, was a literal in two layout files) live in `transitions/constants.ts`; `buildReleaseAnimation` unwraps an `EasingFunctionFactory` through the same worklet helper `ensureWorkletEasing` uses (`unwrapEasingFactory`). Found by the `1.0.0` readiness audit (2026-09-05), Phase 3.
70
+
71
+ - Tests added for the gaps the audit listed: `useVariants().transitionTo` driving a primitive, the `Motion.Image` runtime path, `useDrag`'s `onDragStart` and decay branch, `usePan`'s `withDecay` config, `MotionLinearGradient`'s locations-presence throw, and `MotionPath`'s `initial.d` mismatch throw.
72
+
7
73
  ## [0.0.9] - 2026-08-22
8
74
 
9
75
  ### Changed
@@ -285,7 +351,8 @@ Initial alpha publish. The full initial surface is in place; APIs are still subj
285
351
  - SVG path morphing, gradient interpolation, and shared-element transitions across screens are out of scope until `0.2.x` / `1.x` per the roadmap.
286
352
  - `react-native-gesture-handler` integration (drag, pan, swipe sub-states) lands in `0.2` via the optional `@rootnative/inertia-gestures` adapter.
287
353
 
288
- [unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.9...HEAD
354
+ [unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.10...HEAD
355
+ [0.0.10]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.10
289
356
  [0.0.9]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.9
290
357
  [0.0.8]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.8
291
358
  [0.0.7]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.7
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  Declarative animation primitives for React Native, built as a thin wrapper around [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/). Inspired by Framer Motion (web) and react-spring (cross-platform).
14
14
 
15
- > **Status:** `0.0.9` — stable. Pre-`1.0.0` minor versions may break — see the root [README](https://github.com/rootnative/inertia#versioning--release).
15
+ > **Status:** `0.0.10` — stable. Pre-`1.0.0` minor versions may break — see the [CHANGELOG](https://github.com/rootnative/inertia/blob/main/packages/core/CHANGELOG.md).
16
16
 
17
17
  ## Install
18
18
 
@@ -76,12 +76,12 @@ Both forms land at ~4.1–4.2 kB brotlied for a single primitive (peers excluded
76
76
 
77
77
  ## Transitions
78
78
 
79
- | `type` | Public config keys | Maps to |
80
- | -------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------- |
81
- | `'spring'` (default) | `tension`, `friction`, `mass`, `velocity`, `restSpeedThreshold`, `restDisplacementThreshold` | `withSpring` |
82
- | `'timing'` | `duration`, `easing`, `delay` | `withTiming` |
83
- | `'decay'` | `velocity`, `deceleration`, `clamp` | `withDecay` |
84
- | `'no-animation'` | — | direct assignment, no interpolation |
79
+ | `type` | Public config keys | Maps to |
80
+ | -------------------- | ----------------------------------------- | ----------------------------------- |
81
+ | `'spring'` (default) | `tension`, `friction`, `mass`, `velocity` | `withSpring` |
82
+ | `'timing'` | `duration`, `easing`, `delay` | `withTiming` |
83
+ | `'decay'` | `velocity`, `deceleration`, `clamp` | `withDecay` |
84
+ | `'no-animation'` | — | direct assignment, no interpolation |
85
85
 
86
86
  Plus, on any transition: `delay`, `repeat`. Per-property transitions take precedence over the top-level transition. Spring config uses **react-spring vocabulary** (`tension`/`friction`); Reanimated's raw `stiffness`/`damping` is never on the public surface.
87
87
 
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Clamp `value` to `[min, max]`. When `elastic > 0` the overshoot past a
3
+ * bound is scaled by `elastic` instead of hard-clamped, giving a rubber-band
4
+ * feel. `min` / `max` may be `undefined` to leave that side unbounded.
5
+ *
6
+ * Worklet, so it runs both inside a gesture-handler pan handler on the UI
7
+ * thread (`useDrag`) and from a JS-thread `PanResponder` callback
8
+ * (`useTouchDrag`).
9
+ *
10
+ * ```ts
11
+ * applyBounds(120, -100, 100, 0) // 100
12
+ * applyBounds(120, -100, 100, 0.5) // 110
13
+ * applyBounds(50, undefined, 100, 0) // 50
14
+ * ```
15
+ */
16
+ declare function applyBounds(value: number, min: number | undefined, max: number | undefined, elastic: number): number;
17
+
18
+ export { applyBounds as a };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Clamp `value` to `[min, max]`. When `elastic > 0` the overshoot past a
3
+ * bound is scaled by `elastic` instead of hard-clamped, giving a rubber-band
4
+ * feel. `min` / `max` may be `undefined` to leave that side unbounded.
5
+ *
6
+ * Worklet, so it runs both inside a gesture-handler pan handler on the UI
7
+ * thread (`useDrag`) and from a JS-thread `PanResponder` callback
8
+ * (`useTouchDrag`).
9
+ *
10
+ * ```ts
11
+ * applyBounds(120, -100, 100, 0) // 100
12
+ * applyBounds(120, -100, 100, 0.5) // 110
13
+ * applyBounds(50, undefined, 100, 0) // 50
14
+ * ```
15
+ */
16
+ declare function applyBounds(value: number, min: number | undefined, max: number | undefined, elastic: number): number;
17
+
18
+ export { applyBounds as a };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk6AN5X3YE_js = require('./chunk-6AN5X3YE.js');
4
- var chunkWNVHPMBI_js = require('./chunk-WNVHPMBI.js');
3
+ var chunkKXU6VH2Y_js = require('./chunk-KXU6VH2Y.js');
4
+ var chunkN33GSDNQ_js = require('./chunk-N33GSDNQ.js');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var Animated = require('react-native-reanimated');
@@ -45,11 +45,10 @@ function Presence({ children }) {
45
45
  react.Children.forEach(children, (child) => {
46
46
  if (!react.isValidElement(child)) return;
47
47
  if (child.key === null) {
48
- if (__DEV__) {
49
- console.warn(
50
- "[inertia] <Presence> children must have a `key`. Skipping a keyless child."
51
- );
52
- }
48
+ chunkN33GSDNQ_js.warnOnce(
49
+ "presence-keyless-child",
50
+ "[inertia] <Presence> children must have a `key`. Skipping a keyless child."
51
+ );
53
52
  return;
54
53
  }
55
54
  out.push(child);
@@ -364,15 +363,17 @@ function resolveLayoutTransition(layout) {
364
363
  const cfg = layout === true ? { type: "spring" } : layout;
365
364
  if (cfg.type === "no-animation") return void 0;
366
365
  if (cfg.type === "timing") {
367
- let builder2 = Animated.LinearTransition.duration(cfg.duration ?? 300);
368
- const easing = chunkWNVHPMBI_js.ensureWorkletEasing(cfg.easing);
366
+ let builder2 = Animated.LinearTransition.duration(
367
+ cfg.duration ?? chunkN33GSDNQ_js.DEFAULT_LAYOUT_DURATION
368
+ );
369
+ const easing = chunkN33GSDNQ_js.ensureWorkletEasing(cfg.easing);
369
370
  if (easing) builder2 = builder2.easing(easing);
370
371
  if (cfg.delay) builder2 = builder2.delay(cfg.delay);
371
372
  return builder2;
372
373
  }
373
374
  const spring = cfg.type === "decay" ? { type: "spring" } : cfg;
374
- const { stiffness, damping, mass } = chunkWNVHPMBI_js.springToReanimated({
375
- ...chunkWNVHPMBI_js.DEFAULT_SPRING,
375
+ const { stiffness, damping, mass } = chunkN33GSDNQ_js.springToReanimated({
376
+ ...chunkN33GSDNQ_js.DEFAULT_SPRING,
376
377
  ...spring
377
378
  });
378
379
  let builder = Animated.LinearTransition.springify().stiffness(stiffness).damping(damping).mass(mass);
@@ -560,14 +561,14 @@ function useSharedLayout(options) {
560
561
  }
561
562
  function legBuilder(transition) {
562
563
  if (transition?.type === "timing") {
563
- const duration = transition.duration ?? 300;
564
+ const duration = transition.duration ?? chunkN33GSDNQ_js.DEFAULT_LAYOUT_DURATION;
564
565
  return (from, to) => Animated.withSequence(
565
566
  Animated.withTiming(from, { duration: 0 }),
566
567
  Animated.withTiming(to, { duration })
567
568
  );
568
569
  }
569
- const springCfg = transition?.type === "spring" ? { ...chunkWNVHPMBI_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunkWNVHPMBI_js.DEFAULT_SPRING };
570
- const springParams = chunkWNVHPMBI_js.springToReanimated(springCfg);
570
+ const springCfg = transition?.type === "spring" ? { ...chunkN33GSDNQ_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunkN33GSDNQ_js.DEFAULT_SPRING };
571
+ const springParams = chunkN33GSDNQ_js.springToReanimated(springCfg);
571
572
  return (from, to) => Animated.withSequence(
572
573
  Animated.withTiming(from, { duration: 0 }),
573
574
  Animated.withSpring(to, springParams)
@@ -853,14 +854,14 @@ var DEFAULT_RESTING = {
853
854
  function transitionFor(prop, transition) {
854
855
  if (!transition) return void 0;
855
856
  if (typeof transition === "string") return void 0;
856
- if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
857
+ if (chunkN33GSDNQ_js.isTopLevelTransition(transition)) return transition;
857
858
  if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
858
859
  return transition[prop];
859
860
  }
860
861
  function gestureLayerTransitionFor(layer, transition) {
861
862
  if (!transition) return void 0;
862
863
  if (typeof transition === "string") return void 0;
863
- if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
864
+ if (chunkN33GSDNQ_js.isTopLevelTransition(transition)) return transition;
864
865
  return transition[layer];
865
866
  }
866
867
  function createMotionComponent(Component) {
@@ -910,12 +911,12 @@ function createMotionComponent(Component) {
910
911
  onLayout: userOnLayout,
911
912
  ...rest
912
913
  } = props;
913
- const namedTransitions = chunk6AN5X3YE_js.useNamedTransitions();
914
- const transition = chunk6AN5X3YE_js.resolveNamedTransitionProp(
914
+ const namedTransitions = chunkKXU6VH2Y_js.useNamedTransitions();
915
+ const transition = chunkKXU6VH2Y_js.resolveNamedTransitionProp(
915
916
  transitionProp,
916
917
  namedTransitions
917
918
  );
918
- const layout = typeof layoutProp === "string" ? chunk6AN5X3YE_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
919
+ const layout = typeof layoutProp === "string" ? chunkKXU6VH2Y_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
919
920
  if (__DEV__ && typeof style === "function") {
920
921
  throw new Error(
921
922
  "[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."
@@ -923,7 +924,7 @@ function createMotionComponent(Component) {
923
924
  }
924
925
  const presence = usePresence();
925
926
  const isExiting = presence !== null && presence.isPresent === false;
926
- const shouldReduceMotion = chunk6AN5X3YE_js.useShouldReduceMotion();
927
+ const shouldReduceMotion = chunkKXU6VH2Y_js.useShouldReduceMotion();
927
928
  const staggerDelay = useStaggerDelay();
928
929
  const onAnimationEndRef = react.useRef(onAnimationEnd);
929
930
  onAnimationEndRef.current = onAnimationEnd;
@@ -980,11 +981,8 @@ function createMotionComponent(Component) {
980
981
  }
981
982
  }
982
983
  }
983
- const activeKeysRef = react.useRef(null);
984
- const hasTransformRef = react.useRef(false);
985
- const hasShadowOffsetRef = react.useRef(false);
986
- const hasBoxShadowRef = react.useRef(false);
987
- const prevActive = activeKeysRef.current;
984
+ const activeSetRef = react.useRef(null);
985
+ const prevActive = activeSetRef.current?.keys ?? null;
988
986
  let grew = prevActive === null;
989
987
  if (!grew && prevActive) {
990
988
  for (const k of touched) {
@@ -997,30 +995,32 @@ function createMotionComponent(Component) {
997
995
  if (grew) {
998
996
  const merged = new Set(prevActive ?? []);
999
997
  for (const k of touched) merged.add(k);
1000
- activeKeysRef.current = ALL_KEYS.filter((k) => merged.has(k));
1001
- hasTransformRef.current = activeKeysRef.current.some(
1002
- (k) => TRANSFORM_KEY_SET.has(k)
1003
- );
1004
- hasShadowOffsetRef.current = activeKeysRef.current.some(
1005
- (k) => SHADOW_OFFSET_KEY_SET.has(k)
1006
- );
1007
- hasBoxShadowRef.current = activeKeysRef.current.includes("boxShadow");
1008
- if (__DEV__ && hasBoxShadowRef.current && activeKeysRef.current.some(
1009
- (k) => k !== "boxShadow" && k.startsWith("shadow")
1010
- )) {
1011
- chunkWNVHPMBI_js.warnOnce(
998
+ const keys = ALL_KEYS.filter((k) => merged.has(k));
999
+ activeSetRef.current = {
1000
+ keys,
1001
+ hasTransform: keys.some((k) => TRANSFORM_KEY_SET.has(k)),
1002
+ hasShadowOffset: keys.some((k) => SHADOW_OFFSET_KEY_SET.has(k)),
1003
+ hasBoxShadow: keys.includes("boxShadow")
1004
+ };
1005
+ if (__DEV__ && activeSetRef.current.hasBoxShadow && keys.some((k) => k !== "boxShadow" && k.startsWith("shadow"))) {
1006
+ chunkN33GSDNQ_js.warnOnce(
1012
1007
  "boxShadow-with-native-shadow",
1013
1008
  "[inertia] `boxShadow` is animated alongside the native `shadow*` keys on the same element, which applies two shadow systems at once. Pick one: `boxShadow` for the cross-platform CSS form, or the native `shadow*` keys."
1014
1009
  );
1015
1010
  }
1016
1011
  }
1012
+ const activeKeys = activeSetRef.current.keys;
1013
+ const activeSetSV = Animated.useSharedValue(activeSetRef.current);
1014
+ const activeSet = activeSetRef.current;
1015
+ react.useEffect(() => {
1016
+ if (activeSetSV.value !== activeSet) activeSetSV.value = activeSet;
1017
+ }, [activeSetSV, activeSet]);
1017
1018
  const drivenNow = /* @__PURE__ */ new Set();
1018
1019
  collectTouchedKeys(drivenNow, animateRecord);
1019
1020
  if (initialRecord) collectTouchedKeys(drivenNow, initialRecord);
1020
1021
  if (isExiting && exitRecord) collectTouchedKeys(drivenNow, exitRecord);
1021
1022
  const everDrivenRef = react.useRef(/* @__PURE__ */ new Set());
1022
1023
  for (const k of drivenNow) everDrivenRef.current.add(k);
1023
- const activeKeys = activeKeysRef.current;
1024
1024
  const everDriven = everDrivenRef.current;
1025
1025
  const styleResting = {};
1026
1026
  let styleRestingShadow = null;
@@ -1076,9 +1076,9 @@ function createMotionComponent(Component) {
1076
1076
  const boxShadowInsets = Animated.useSharedValue(
1077
1077
  boxShadowSeedRef.current.insets
1078
1078
  );
1079
- const styleRestingSig = chunkWNVHPMBI_js.stableSig(styleResting);
1079
+ const styleRestingSig = chunkN33GSDNQ_js.stableSig(styleResting);
1080
1080
  react.useEffect(() => {
1081
- for (const key of activeKeysRef.current) {
1081
+ for (const key of activeKeys) {
1082
1082
  if (everDrivenRef.current.has(key)) continue;
1083
1083
  sharedValues[key].value = styleResting[key] ?? DEFAULT_RESTING[key];
1084
1084
  if (key === "boxShadow") {
@@ -1104,13 +1104,14 @@ function createMotionComponent(Component) {
1104
1104
  const gestureSV = Animated.useSharedValue(
1105
1105
  resolveGestureLayers(gesture)
1106
1106
  );
1107
- const gestureTargetsSig = chunkWNVHPMBI_js.stableSig(gesture);
1107
+ const gestureTargetsSig = chunkN33GSDNQ_js.stableSig(gesture);
1108
1108
  react.useEffect(() => {
1109
1109
  gestureSV.value = resolveGestureLayers(gesture);
1110
1110
  }, [gestureTargetsSig]);
1111
1111
  const baseRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : animateRecord;
1112
- const baseSig = chunkWNVHPMBI_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
1113
- const transitionSig = chunkWNVHPMBI_js.stableSig(transition);
1112
+ const baseSig = chunkN33GSDNQ_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
1113
+ const transitionSig = chunkN33GSDNQ_js.stableSig(transition);
1114
+ const hasAnimationEnd = onAnimationEnd !== void 0;
1114
1115
  const safeToRemoveRef = react.useRef(void 0);
1115
1116
  safeToRemoveRef.current = presence?.safeToRemove;
1116
1117
  react.useEffect(() => {
@@ -1185,8 +1186,8 @@ function createMotionComponent(Component) {
1185
1186
  isExiting ? onSettle : void 0,
1186
1187
  TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
1187
1188
  );
1188
- sharedValues[key].value = chunkWNVHPMBI_js.applyDelay(
1189
- chunkWNVHPMBI_js.resolveAnimatableValue(
1189
+ sharedValues[key].value = chunkN33GSDNQ_js.applyDelay(
1190
+ chunkN33GSDNQ_js.resolveAnimatableValue(
1190
1191
  COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
1191
1192
  cfg,
1192
1193
  factory
@@ -1197,7 +1198,10 @@ function createMotionComponent(Component) {
1197
1198
  if (isExiting && pending === 0) {
1198
1199
  safeToRemoveRef.current?.();
1199
1200
  }
1200
- }, [baseSig, transitionSig]);
1201
+ return () => {
1202
+ done = true;
1203
+ };
1204
+ }, [baseSig, transitionSig, hasAnimationEnd]);
1201
1205
  useGestureLayerProgress(
1202
1206
  pressedProgress,
1203
1207
  pressed,
@@ -1238,7 +1242,7 @@ function createMotionComponent(Component) {
1238
1242
  if (!hasLayoutId) return void 0;
1239
1243
  const out = {};
1240
1244
  let any = false;
1241
- for (const key of activeKeysRef.current) {
1245
+ for (const key of activeKeys) {
1242
1246
  if (!SHARED_STYLE_KEY_SET.has(key)) continue;
1243
1247
  const v = sharedValues[key].value;
1244
1248
  if (typeof v !== "number" && typeof v !== "string") continue;
@@ -1250,7 +1254,7 @@ function createMotionComponent(Component) {
1250
1254
  const sharedLayout = useSharedLayout({
1251
1255
  layoutId,
1252
1256
  userRef: ref,
1253
- transition: chunkWNVHPMBI_js.isTopLevelTransition(transition) ? transition : void 0,
1257
+ transition: chunkN33GSDNQ_js.isTopLevelTransition(transition) ? transition : void 0,
1254
1258
  shouldReduceMotion,
1255
1259
  userOnLayout,
1256
1260
  readStyles: readSharedStyles
@@ -1258,10 +1262,11 @@ function createMotionComponent(Component) {
1258
1262
  const flip = sharedLayout.flip;
1259
1263
  const carry = sharedLayout.carry;
1260
1264
  const animatedStyle = Animated.useAnimatedStyle(() => {
1261
- const activeKeys2 = activeKeysRef.current;
1262
- const hasTransform = hasTransformRef.current;
1263
- const hasShadowOffset = hasShadowOffsetRef.current;
1264
- const hasBoxShadow = hasBoxShadowRef.current;
1265
+ const activeSet2 = activeSetSV.value;
1266
+ const activeKeys2 = activeSet2.keys;
1267
+ const hasTransform = activeSet2.hasTransform;
1268
+ const hasShadowOffset = activeSet2.hasShadowOffset;
1269
+ const hasBoxShadow = activeSet2.hasBoxShadow;
1265
1270
  const out = {};
1266
1271
  const transform = [];
1267
1272
  let shadowOffsetW = 0;
@@ -1352,7 +1357,7 @@ function createMotionComponent(Component) {
1352
1357
  setFocusVisible,
1353
1358
  setHovered
1354
1359
  );
1355
- const layoutSig = chunkWNVHPMBI_js.stableSig(layout);
1360
+ const layoutSig = chunkN33GSDNQ_js.stableSig(layout);
1356
1361
  const layoutTransition = react.useMemo(
1357
1362
  () => shouldReduceMotion ? void 0 : resolveLayoutTransition(layout),
1358
1363
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1501,8 +1506,8 @@ function driveBoxShadow(slot, insetSlot, target, cfg, staggerDelay, factory) {
1501
1506
  );
1502
1507
  insetSlot.value = insets;
1503
1508
  if (from.length !== currentLayers.length) slot.value = layersToPayload(from);
1504
- slot.value = chunkWNVHPMBI_js.applyDelay(
1505
- chunkWNVHPMBI_js.resolveTransition(
1509
+ slot.value = chunkN33GSDNQ_js.applyDelay(
1510
+ chunkN33GSDNQ_js.resolveTransition(
1506
1511
  cfg,
1507
1512
  layersToPayload(to),
1508
1513
  factory?.("animation", void 0)
@@ -1560,12 +1565,7 @@ function stepCountOf(v) {
1560
1565
  }
1561
1566
  function totalIterationsOf(cfg) {
1562
1567
  if (!cfg || cfg.type === "no-animation" || cfg.type === "decay") return 1;
1563
- const r = cfg.repeat;
1564
- if (r === void 0) return 1;
1565
- if (r === "infinite") return Number.POSITIVE_INFINITY;
1566
- if (typeof r === "number") return r;
1567
- if (r.count === "infinite") return Number.POSITIVE_INFINITY;
1568
- return r.count;
1568
+ return chunkN33GSDNQ_js.repeatIterationsOf(cfg.repeat);
1569
1569
  }
1570
1570
  function reachesTerminalPhase(cfg) {
1571
1571
  return Number.isFinite(totalIterationsOf(cfg));
@@ -1592,16 +1592,21 @@ function useControllerKey(controller) {
1592
1592
  return controller?.current;
1593
1593
  }
1594
1594
  function resolveAnimateInput(animate, variants, controllerKey) {
1595
+ if (controllerKey !== void 0 && animate !== void 0) {
1596
+ chunkN33GSDNQ_js.warnOnce(
1597
+ "controller-and-animate",
1598
+ "[inertia] Both `controller` and `animate` are set on the same primitive. The controller drives the animation and `animate` is ignored \u2014 remove one of the two."
1599
+ );
1600
+ }
1595
1601
  if (controllerKey !== void 0 && variants && controllerKey in variants) {
1596
1602
  return variants[controllerKey];
1597
1603
  }
1598
1604
  if (typeof animate === "string") {
1599
1605
  if (variants && animate in variants) return variants[animate];
1600
- if (__DEV__) {
1601
- console.warn(
1602
- `[inertia] animate="${animate}" but no matching variant. Did you forget to pass \`variants\`?`
1603
- );
1604
- }
1606
+ chunkN33GSDNQ_js.warnOnce(
1607
+ `missing-variant:${animate}`,
1608
+ `[inertia] animate="${animate}" but no matching variant. Did you forget to pass \`variants\`?`
1609
+ );
1605
1610
  return void 0;
1606
1611
  }
1607
1612
  return animate;
@@ -1628,7 +1633,7 @@ function resolveGestureLayers(gesture) {
1628
1633
  for (const key of ALL_KEYS) {
1629
1634
  if (STRUCTURED_KEY_SET.has(key)) {
1630
1635
  if (__DEV__ && subState[key] !== void 0) {
1631
- chunkWNVHPMBI_js.warnOnce(
1636
+ chunkN33GSDNQ_js.warnOnce(
1632
1637
  `gesture-structured-${layer}-${key}`,
1633
1638
  `[inertia] \`${key}\` is not supported inside \`gesture.${layer}\` and will be ignored. Drive it from \`animate\` (optionally via a variant keyed off the same state), or interpolate it yourself with \`useShadow\`.`
1634
1639
  );
@@ -1652,7 +1657,7 @@ function resolveGestureLayers(gesture) {
1652
1657
  return out;
1653
1658
  }
1654
1659
  function useGestureLayerProgress(progress, active, declared, layer, transition, isExiting, shouldReduceMotion) {
1655
- const layerCfgSig = chunkWNVHPMBI_js.stableSig(gestureLayerTransitionFor(layer, transition));
1660
+ const layerCfgSig = chunkN33GSDNQ_js.stableSig(gestureLayerTransitionFor(layer, transition));
1656
1661
  react.useEffect(() => {
1657
1662
  if (!declared) return;
1658
1663
  if (isExiting) {
@@ -1661,7 +1666,7 @@ function useGestureLayerProgress(progress, active, declared, layer, transition,
1661
1666
  }
1662
1667
  const target = active ? 1 : 0;
1663
1668
  const cfg = shouldReduceMotion ? { type: "no-animation" } : gestureLayerTransitionFor(layer, transition) ?? { type: "spring" };
1664
- progress.value = chunkWNVHPMBI_js.resolveTransition(cfg, target);
1669
+ progress.value = chunkN33GSDNQ_js.resolveTransition(cfg, target);
1665
1670
  }, [active, declared, isExiting, shouldReduceMotion, layerCfgSig]);
1666
1671
  }
1667
1672
  function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisible, setHovered) {
@@ -1669,6 +1674,9 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
1669
1674
  const hasFocused = gesture?.focused ? 1 : 0;
1670
1675
  const hasFocusVisible = gesture?.focusVisible ? 1 : 0;
1671
1676
  const hasHovered = gesture?.hovered ? 1 : 0;
1677
+ react.useEffect(() => {
1678
+ if (hasFocusVisible) chunkKXU6VH2Y_js.installFocusVisibility();
1679
+ }, [hasFocusVisible]);
1672
1680
  return react.useMemo(() => {
1673
1681
  if (!gesture) return {};
1674
1682
  const handlers = {};
@@ -1694,7 +1702,7 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
1694
1702
  if (gesture.focused || gesture.focusVisible) {
1695
1703
  handlers.onFocus = compose(rest.onFocus, () => {
1696
1704
  if (gesture.focused) setFocused(true);
1697
- if (gesture.focusVisible && chunk6AN5X3YE_js.isFocusVisible()) setFocusVisible(true);
1705
+ if (gesture.focusVisible && chunkKXU6VH2Y_js.isFocusVisible()) setFocusVisible(true);
1698
1706
  });
1699
1707
  handlers.onBlur = compose(rest.onBlur, () => {
1700
1708
  if (gesture.focused) setFocused(false);
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkE3ALFSH2_js = require('./chunk-E3ALFSH2.js');
3
+ var chunk2UGWAB6N_js = require('./chunk-2UGWAB6N.js');
4
4
  var reactNative = require('react-native');
5
5
 
6
- var MotionScrollView = chunkE3ALFSH2_js.createMotionComponent(reactNative.ScrollView);
6
+ var MotionScrollView = chunk2UGWAB6N_js.createMotionComponent(reactNative.ScrollView);
7
7
 
8
8
  exports.MotionScrollView = MotionScrollView;
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkE3ALFSH2_js = require('./chunk-E3ALFSH2.js');
3
+ var chunk2UGWAB6N_js = require('./chunk-2UGWAB6N.js');
4
4
  var Animated = require('react-native-reanimated');
5
5
 
6
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
7
 
8
8
  var Animated__default = /*#__PURE__*/_interopDefault(Animated);
9
9
 
10
- var MotionFlatList = chunkE3ALFSH2_js.createMotionComponent(
10
+ var MotionFlatList = chunk2UGWAB6N_js.createMotionComponent(
11
11
  Animated__default.default.FlatList
12
12
  // `createMotionComponent<C>` returns a non-generic `MotionComponent<C>`, so
13
13
  // `data` / `renderItem` would collapse to `any` and lose `ItemT` inference.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk6AN5X3YE_js = require('./chunk-6AN5X3YE.js');
4
- var chunkWNVHPMBI_js = require('./chunk-WNVHPMBI.js');
3
+ var chunkKXU6VH2Y_js = require('./chunk-KXU6VH2Y.js');
4
+ var chunkN33GSDNQ_js = require('./chunk-N33GSDNQ.js');
5
5
  var react = require('react');
6
6
  var reactNativeReanimated = require('react-native-reanimated');
7
7
 
@@ -10,12 +10,15 @@ function useGesture(transition) {
10
10
  const focused = reactNativeReanimated.useSharedValue(0);
11
11
  const focusVisible = reactNativeReanimated.useSharedValue(0);
12
12
  const hovered = reactNativeReanimated.useSharedValue(0);
13
- const shouldReduceMotion = chunk6AN5X3YE_js.useShouldReduceMotion();
14
- const resolved = chunk6AN5X3YE_js.resolveNamedTransitionProp(transition, chunk6AN5X3YE_js.useNamedTransitions());
13
+ const shouldReduceMotion = chunkKXU6VH2Y_js.useShouldReduceMotion();
14
+ const resolved = chunkKXU6VH2Y_js.resolveNamedTransitionProp(transition, chunkKXU6VH2Y_js.useNamedTransitions());
15
+ react.useEffect(() => {
16
+ chunkKXU6VH2Y_js.installFocusVisibility();
17
+ }, []);
15
18
  const setLayer = react.useCallback(
16
19
  (sv, layer, target) => {
17
20
  const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
18
- sv.value = chunkWNVHPMBI_js.resolveTransition(cfg, target);
21
+ sv.value = chunkN33GSDNQ_js.resolveTransition(cfg, target);
19
22
  },
20
23
  // The transition is intentionally read on every call rather than cooked
21
24
  // into the dep array — a fresh literal each render would otherwise
@@ -34,7 +37,7 @@ function useGesture(transition) {
34
37
  onHoverOut: () => setLayer(hovered, "hovered", 0),
35
38
  onFocus: () => {
36
39
  setLayer(focused, "focused", 1);
37
- if (chunk6AN5X3YE_js.isFocusVisible()) setLayer(focusVisible, "focusVisible", 1);
40
+ if (chunkKXU6VH2Y_js.isFocusVisible()) setLayer(focusVisible, "focusVisible", 1);
38
41
  },
39
42
  onBlur: () => {
40
43
  setLayer(focused, "focused", 0);
@@ -47,7 +50,7 @@ function useGesture(transition) {
47
50
  }
48
51
  function layerTransition(layer, transition) {
49
52
  if (!transition) return void 0;
50
- if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
53
+ if (chunkN33GSDNQ_js.isTopLevelTransition(transition)) return transition;
51
54
  return transition[layer];
52
55
  }
53
56
 
@@ -1,4 +1,4 @@
1
- import { stableSig, isTopLevelTransition } from './chunk-W7NTRSPD.mjs';
1
+ import { stableSig, warnOnce, isTopLevelTransition } from './chunk-HEAWMZEM.mjs';
2
2
  import { createContext, useContext, useMemo } from 'react';
3
3
  import { useReducedMotion } from 'react-native-reanimated';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -47,11 +47,10 @@ var UNKNOWN_NAME_FALLBACK = { type: "spring" };
47
47
  function lookupNamedTransition(name, registry) {
48
48
  const cfg = registry[name];
49
49
  if (cfg) return cfg;
50
- if (__DEV__) {
51
- console.warn(
52
- `[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
53
- );
54
- }
50
+ warnOnce(
51
+ `unknown-transition:${name}`,
52
+ `[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
53
+ );
55
54
  return UNKNOWN_NAME_FALLBACK;
56
55
  }
57
56
  function resolveNamedTransition(input, registry) {
@@ -84,7 +83,7 @@ function setKeyboard() {
84
83
  function setPointer() {
85
84
  modality = "pointer";
86
85
  }
87
- function ensureInstalled() {
86
+ function installFocusVisibility() {
88
87
  if (installed) return;
89
88
  if (Platform.OS !== "web") return;
90
89
  if (typeof document === "undefined") return;
@@ -94,11 +93,10 @@ function ensureInstalled() {
94
93
  document.addEventListener("touchstart", setPointer, true);
95
94
  installed = true;
96
95
  }
97
- ensureInstalled();
98
96
  function isFocusVisible() {
99
97
  if (Platform.OS !== "web") return true;
100
- ensureInstalled();
98
+ installFocusVisibility();
101
99
  return modality === "keyboard";
102
100
  }
103
101
 
104
- export { MotionConfig, isFocusVisible, lookupNamedTransition, resolveNamedTransition, resolveNamedTransitionProp, useMotionConfig, useNamedTransitions, useShouldReduceMotion };
102
+ export { MotionConfig, installFocusVisibility, isFocusVisible, lookupNamedTransition, resolveNamedTransition, resolveNamedTransitionProp, useMotionConfig, useNamedTransitions, useShouldReduceMotion };