@rootnative/inertia 0.0.3 → 0.0.5

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 (75) hide show
  1. package/CHANGELOG.md +92 -5
  2. package/README.md +9 -3
  3. package/dist/{chunk-OQV66TBQ.mjs → chunk-27MKBTSG.mjs} +1 -1
  4. package/dist/{chunk-3XTVY34H.js → chunk-27U6766G.js} +2 -2
  5. package/dist/{chunk-4PEHWDAZ.js → chunk-4NAMD62I.js} +7 -7
  6. package/dist/chunk-67GHRCF6.js +8 -0
  7. package/dist/{chunk-SGUHE5CX.mjs → chunk-COEJVWRZ.mjs} +1 -1
  8. package/dist/chunk-GPOMFIIU.js +8 -0
  9. package/dist/{chunk-BQQTHG2V.mjs → chunk-GTJ6VAH5.mjs} +1 -1
  10. package/dist/chunk-K63LXGKS.js +8 -0
  11. package/dist/{chunk-46P57VMY.mjs → chunk-OAUWLPQH.mjs} +1 -1
  12. package/dist/{chunk-7AOERN53.js → chunk-OBRGJAST.js} +3 -3
  13. package/dist/{chunk-RGNX6UZN.mjs → chunk-OW5XTGVN.mjs} +2 -2
  14. package/dist/{chunk-PTRF47DA.js → chunk-PM6CVGXJ.js} +11 -3
  15. package/dist/{chunk-W5MC3P4N.js → chunk-QQVDZKSD.js} +2 -2
  16. package/dist/{chunk-CY7Y64C3.mjs → chunk-REYL77RE.mjs} +11 -4
  17. package/dist/{chunk-CSODMRJ7.mjs → chunk-RIVVBABB.mjs} +597 -134
  18. package/dist/{chunk-BP3Y2SHQ.js → chunk-VQ5D35UA.js} +617 -152
  19. package/dist/{chunk-O22NXXCZ.mjs → chunk-XSK5MNUH.mjs} +1 -1
  20. package/dist/{chunk-R63GIUNU.mjs → chunk-Z3HCJ43H.mjs} +1 -1
  21. package/dist/gestureLayer/index.d.mts +2 -2
  22. package/dist/gestureLayer/index.d.ts +2 -2
  23. package/dist/gestureLayer/index.js +10 -10
  24. package/dist/gestureLayer/index.mjs +3 -3
  25. package/dist/index.d.mts +4 -4
  26. package/dist/index.d.ts +4 -4
  27. package/dist/index.js +48 -169
  28. package/dist/index.mjs +17 -137
  29. package/dist/motion/Image.d.mts +1 -1
  30. package/dist/motion/Image.d.ts +1 -1
  31. package/dist/motion/Image.js +5 -5
  32. package/dist/motion/Image.mjs +4 -4
  33. package/dist/motion/Pressable.d.mts +1 -1
  34. package/dist/motion/Pressable.d.ts +1 -1
  35. package/dist/motion/Pressable.js +5 -5
  36. package/dist/motion/Pressable.mjs +4 -4
  37. package/dist/motion/ScrollView.d.mts +1 -1
  38. package/dist/motion/ScrollView.d.ts +1 -1
  39. package/dist/motion/ScrollView.js +5 -5
  40. package/dist/motion/ScrollView.mjs +4 -4
  41. package/dist/motion/Text.d.mts +1 -1
  42. package/dist/motion/Text.d.ts +1 -1
  43. package/dist/motion/Text.js +5 -5
  44. package/dist/motion/Text.mjs +4 -4
  45. package/dist/motion/View.d.mts +1 -1
  46. package/dist/motion/View.d.ts +1 -1
  47. package/dist/motion/View.js +5 -5
  48. package/dist/motion/View.mjs +4 -4
  49. package/dist/touch/index.d.mts +1 -1
  50. package/dist/touch/index.d.ts +1 -1
  51. package/dist/touch/index.js +3 -3
  52. package/dist/touch/index.mjs +1 -1
  53. package/dist/{types-G1dBU2IQ.d.mts → types-BQgLJeQG.d.mts} +85 -14
  54. package/dist/{types-G1dBU2IQ.d.ts → types-BQgLJeQG.d.ts} +85 -14
  55. package/dist/{useGesture-D1e4ixJo.d.ts → useGesture-B0_CzOUz.d.ts} +1 -1
  56. package/dist/{useGesture-RFY6kTL3.d.mts → useGesture-DfaTx-3t.d.mts} +1 -1
  57. package/llms.txt +3 -1
  58. package/package.json +1 -1
  59. package/src/index.ts +2 -1
  60. package/src/internal/boxShadow.ts +177 -6
  61. package/src/internal/nonWorkletWarning.ts +4 -6
  62. package/src/internal/warnOnce.ts +28 -0
  63. package/src/layout/index.ts +10 -0
  64. package/src/layout/measureWindow.ts +135 -0
  65. package/src/layout/sharedRegistry.ts +107 -18
  66. package/src/layout/useSharedLayout.ts +256 -91
  67. package/src/motion/createMotionComponent.tsx +497 -74
  68. package/src/motion/installCheck.ts +1 -1
  69. package/src/transitions/index.ts +1 -1
  70. package/src/transitions/resolveSequence.ts +12 -0
  71. package/src/types.ts +155 -12
  72. package/src/values/useColorTransition.ts +1 -1
  73. package/dist/chunk-FNVFV4EY.js +0 -8
  74. package/dist/chunk-FWQOXA43.js +0 -8
  75. package/dist/chunk-KBP4LR75.js +0 -8
@@ -41,7 +41,7 @@ export function ensureReanimatedInstalled(): void {
41
41
  const major = parseInt(version.split('.')[0] ?? '0', 10)
42
42
  if (major < 4) {
43
43
  console.error(
44
- `[inertia] react-native-reanimated v${version} is installed, but @rootnative/inertia requires v4.0.0 or later. ` +
44
+ `[inertia] react-native-reanimated ${version} is installed, but @rootnative/inertia requires 4.0.0 or later. ` +
45
45
  `Upgrade with \`pnpm add react-native-reanimated@^4\` (or your package manager's equivalent).`,
46
46
  )
47
47
  return
@@ -1,4 +1,4 @@
1
- export { resolveTransition } from './resolve'
1
+ export { resolveTransition, type CallbackFactory } from './resolve'
2
2
  export { resolveAnimatableValue } from './resolveSequence'
3
3
  export { cubicBezier } from './cubicBezier'
4
4
  export { ensureWorkletEasing } from './easing'
@@ -77,6 +77,18 @@ function mergeTransition(
77
77
  base: TransitionConfig | undefined,
78
78
  override: Partial<TransitionConfig>,
79
79
  ): TransitionConfig {
80
+ // A `no-animation` base is a ceiling, not a default, so no step override can
81
+ // talk its way past it. This is the reduced-motion gate: `configFor` in the
82
+ // factory swaps every per-key transition for `{ type: 'no-animation' }`, and
83
+ // the step-type rule below would otherwise hand a step its own `withTiming`
84
+ // back — silently animating for a user who asked the OS not to. Keep this
85
+ // branch first; it is the whole reason the gate holds for sequences.
86
+ //
87
+ // Returning `base` also drops any step `delay`, which matches how the rest
88
+ // of the resolver already treats this type: `delayOf` and `repeatOf` both
89
+ // return `undefined` for `no-animation`, so a snap is never deferred or
90
+ // repeated anywhere in the library.
91
+ if (base?.type === 'no-animation') return base
80
92
  // If the override declares a `type`, it wins outright — mixing fields from
81
93
  // a spring base into a timing override produces garbage. Otherwise inherit
82
94
  // the base's type and shallow-merge the rest.
package/src/types.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  type ReactElement,
5
5
  type Ref,
6
6
  } from 'react'
7
- import { type StyleProp } from 'react-native'
7
+ import { type BoxShadowValue, type StyleProp } from 'react-native'
8
8
 
9
9
  /**
10
10
  * A single animation step's destination, optionally overriding the transition
@@ -184,6 +184,55 @@ type AnimatableTransformExtras = {
184
184
  rotateY?: AnimatableValue<number>
185
185
  }
186
186
 
187
+ /**
188
+ * Target shape for the `boxShadow` key on `animate` / `initial` / `exit`: a
189
+ * CSS `box-shadow` string, or RN's own array-of-layers form.
190
+ *
191
+ * Both endpoints of a `boxShadow` animation are normalized to a common layer
192
+ * count on the JS thread, so a two-layer shadow can animate to a one-layer one
193
+ * (the short side is padded with a transparent layer, as CSS transitions do).
194
+ * A layer that is `inset` on one side and not the other is not interpolable
195
+ * and throws.
196
+ */
197
+ export type BoxShadowInput = string | ReadonlyArray<BoxShadowValue>
198
+
199
+ /**
200
+ * Keys whose animatable form deliberately departs from the generic
201
+ * `AnimatableValue<S[K]>` mapping.
202
+ *
203
+ * `boxShadow` is the only member. Its natural value is already an array, which
204
+ * collides head-on with `AnimatableValue`'s keyframe-sequence form — nothing
205
+ * distinguishes `[layerA, layerB]` (one two-layer shadow) from a two-step
206
+ * sequence. The array slot is given to layers, which is the shape RN itself
207
+ * uses and by far the common case, and sequences are unsupported on this key.
208
+ * This mirrors the single-value-only contract `shadowOffset` has carried since
209
+ * `0.0.1`. Per-property transitions are unaffected: `transition={{ boxShadow:
210
+ * { type: 'timing' } }}` works as it does for every other key.
211
+ *
212
+ * Conditional on `S` so the key only appears where the underlying style
213
+ * actually has it, rather than being bolted onto every primitive.
214
+ */
215
+ type AnimatableStructuredExtras<S> = 'boxShadow' extends keyof S
216
+ ? { boxShadow?: BoxShadowInput }
217
+ : // eslint-disable-next-line @typescript-eslint/no-empty-object-type
218
+ {}
219
+
220
+ /**
221
+ * The `transform: [...]` array form, passed through as the underlying style
222
+ * types it. Inertia reads transform entries out of the array (see
223
+ * `styleValueFor` in `createMotionComponent`) rather than treating the array as
224
+ * an animatable scalar, so it is exempted from the `AnimatableValue` mapping —
225
+ * wrapping it there would offer a nonsensical `transform: [[...], [...]]`
226
+ * keyframe form.
227
+ *
228
+ * Conditional on `S` for the same reason as `boxShadow`: only appears where the
229
+ * underlying style actually has it.
230
+ */
231
+ type AnimatableTransformArray<S> = 'transform' extends keyof S
232
+ ? { transform?: S['transform'] }
233
+ : // eslint-disable-next-line @typescript-eslint/no-empty-object-type
234
+ {}
235
+
187
236
  /**
188
237
  * The animation state shape inferred from the underlying component's style
189
238
  * prop. We narrow to the value side of `style` so consumers see ViewStyle on
@@ -198,9 +247,98 @@ type AnimatableTransformExtras = {
198
247
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
248
  type _StyleValue<T> = Exclude<T, (...args: any[]) => any>
200
249
 
250
+ /**
251
+ * The style keys Inertia's runtime actually drives — the type-level mirror of
252
+ * `ALL_KEYS` in `createMotionComponent`, minus the `shadowOffset*` synthetics
253
+ * (consumers write the nested `shadowOffset` object, not the axes) and minus
254
+ * `boxShadow` (handled by `AnimatableStructuredExtras`, whose value shape
255
+ * deliberately departs from `AnimatableValue`).
256
+ *
257
+ * **This list and `ALL_KEYS` must stay in sync.** They are separate because one
258
+ * is a type and the other is a runtime array, and TypeScript can't derive the
259
+ * former from a value living in a module that imports this one. The direction
260
+ * that matters: a key here but not in `ALL_KEYS` typechecks and then silently
261
+ * does nothing at runtime — which is precisely the defect this type was
262
+ * introduced to kill. `animate-keys.test-d.tsx` pins the two together.
263
+ *
264
+ * Before 0.0.5 this type mapped over the component's *entire* style surface, so
265
+ * `animate={{ paddingTop: 40 }}` compiled cleanly and was then dropped on the
266
+ * floor — no error, no warning. That contradicted the library's own headline
267
+ * differentiator (wrong props should error, not go unnoticed), so the mapping is
268
+ * now an intersection: a key must be both animatable by Inertia *and* present on
269
+ * the underlying component's style prop.
270
+ */
271
+ type AnimatableStyleKey =
272
+ // Transform axes surfaced as top-level keys.
273
+ | 'translateX'
274
+ | 'translateY'
275
+ | 'scaleX'
276
+ | 'scaleY'
277
+ // Numeric top-level keys.
278
+ | 'opacity'
279
+ | 'width'
280
+ | 'height'
281
+ | 'borderRadius'
282
+ | 'shadowOpacity'
283
+ | 'shadowRadius'
284
+ | 'elevation'
285
+ | 'borderTopLeftRadius'
286
+ | 'borderTopRightRadius'
287
+ | 'borderBottomLeftRadius'
288
+ | 'borderBottomRightRadius'
289
+ | 'borderWidth'
290
+ | 'borderTopWidth'
291
+ | 'borderRightWidth'
292
+ | 'borderBottomWidth'
293
+ | 'borderLeftWidth'
294
+ | 'top'
295
+ | 'right'
296
+ | 'bottom'
297
+ | 'left'
298
+ | 'padding'
299
+ | 'paddingTop'
300
+ | 'paddingRight'
301
+ | 'paddingBottom'
302
+ | 'paddingLeft'
303
+ | 'paddingHorizontal'
304
+ | 'paddingVertical'
305
+ | 'margin'
306
+ | 'marginTop'
307
+ | 'marginRight'
308
+ | 'marginBottom'
309
+ | 'marginLeft'
310
+ | 'marginHorizontal'
311
+ | 'marginVertical'
312
+ | 'flex'
313
+ | 'flexGrow'
314
+ | 'flexShrink'
315
+ | 'fontSize'
316
+ | 'letterSpacing'
317
+ | 'lineHeight'
318
+ | 'zIndex'
319
+ | 'gap'
320
+ | 'rowGap'
321
+ | 'columnGap'
322
+ // Color keys.
323
+ | 'backgroundColor'
324
+ | 'borderColor'
325
+ | 'color'
326
+ | 'tintColor'
327
+ | 'shadowColor'
328
+ // The one nested-object style prop, written as `{ width, height }`.
329
+ | 'shadowOffset'
330
+
201
331
  export type AnimateStyle<C> = C extends { style?: infer Raw }
202
332
  ? _StyleValue<Raw> extends StyleProp<infer S>
203
- ? { [K in keyof S]?: AnimatableValue<S[K]> } & AnimatableTransformExtras
333
+ ? {
334
+ [K in keyof S as K extends AnimatableStyleKey ? K : never]?: K extends
335
+ | 'boxShadow'
336
+ | 'transform'
337
+ ? never
338
+ : AnimatableValue<S[K]>
339
+ } & AnimatableTransformExtras &
340
+ AnimatableStructuredExtras<S> &
341
+ AnimatableTransformArray<S>
204
342
  : never
205
343
  : never
206
344
 
@@ -379,19 +517,24 @@ export interface MotionProps<C, V extends VariantsMap<C> = VariantsMap<C>> {
379
517
  * recorded rect to its natural position via a FLIP transform stack.
380
518
  *
381
519
  * Reanimated 4 removed the `sharedTransitionTag` API — `layoutId` is the
382
- * Inertia-side measure-based replacement. Rects are recorded in
383
- * parent-relative coordinates (from `onLayout`), which composes when the
384
- * source and target screens share an outer content container (the common
385
- * stack-navigator case); nested-parent layouts need the v2
386
- * window-coordinate path.
520
+ * Inertia-side measure-based replacement. Rects are recorded in **window**
521
+ * coordinates wherever the host can be measured synchronously (Fabric),
522
+ * which is what lets a source and target sit under containers at different
523
+ * screen offsets; elsewhere both fall back to the parent-relative
524
+ * coordinates `onLayout` reports. A source and target that ended up in
525
+ * different spaces skip the animation rather than play a wrong one.
387
526
  *
388
527
  * The same `transition` prop drives the FLIP animation (spring by
389
528
  * default; `'timing'` honored; `'decay'` downgrades to spring; reduced
390
- * motion skips the transition). Out of scope for the first iteration:
391
- * style-prop interpolation (border radius, colors, etc.) only the
392
- * rect-to-rect transform is animated. Two simultaneously-mounted
393
- * primitives sharing the same `layoutId` are undefined behavior; pick a
394
- * primitive per id at a time.
529
+ * motion skips the transition). Alongside the rect, a fixed set of style
530
+ * keys is carried from the source and crossfaded out on that same
531
+ * transition: `opacity`, `borderRadius`, `backgroundColor`, `borderColor`,
532
+ * `color`, `tintColor`. Transform keys are not carried the FLIP owns
533
+ * them and a key only participates when the element already has a value
534
+ * for it, from a record or from its static `style`.
535
+ *
536
+ * Two simultaneously-mounted primitives sharing the same `layoutId` are
537
+ * undefined behavior; pick a primitive per id at a time.
395
538
  */
396
539
  layoutId?: string
397
540
  /**
@@ -6,7 +6,7 @@ import {
6
6
 
7
7
  /**
8
8
  * Color style keys understood by React Native that this hook can target.
9
- * Sticks to the keys that exist on the v0.1 animatable surface so the
9
+ * Sticks to the keys that exist on the animatable surface so the
10
10
  * returned style fragment is always a legal RN style.
11
11
  */
12
12
  export type ColorStyleKey =
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkBP3Y2SHQ_js = require('./chunk-BP3Y2SHQ.js');
4
- var reactNative = require('react-native');
5
-
6
- var MotionView = chunkBP3Y2SHQ_js.createMotionComponent(reactNative.View);
7
-
8
- exports.MotionView = MotionView;
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkBP3Y2SHQ_js = require('./chunk-BP3Y2SHQ.js');
4
- var reactNative = require('react-native');
5
-
6
- var MotionText = chunkBP3Y2SHQ_js.createMotionComponent(reactNative.Text);
7
-
8
- exports.MotionText = MotionText;
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkBP3Y2SHQ_js = require('./chunk-BP3Y2SHQ.js');
4
- var reactNative = require('react-native');
5
-
6
- var MotionImage = chunkBP3Y2SHQ_js.createMotionComponent(reactNative.Image);
7
-
8
- exports.MotionImage = MotionImage;