@rootnative/inertia 0.0.7 → 0.0.9

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 (57) hide show
  1. package/CHANGELOG.md +31 -1
  2. package/README.md +1 -1
  3. package/dist/chunk-24NUL23E.js +8 -0
  4. package/dist/chunk-4XBX7KOD.js +8 -0
  5. package/dist/{chunk-OBRGJAST.js → chunk-6AN5X3YE.js} +3 -3
  6. package/dist/{chunk-WGCF3WQG.js → chunk-6NOCY764.js} +2 -2
  7. package/dist/{chunk-KBFN4TRO.mjs → chunk-6YIUETBF.mjs} +1 -1
  8. package/dist/{chunk-6V7MOBXO.js → chunk-E3ALFSH2.js} +64 -33
  9. package/dist/{chunk-ZOBOKLAS.mjs → chunk-EN4PN7X3.mjs} +1 -1
  10. package/dist/{chunk-RUIOM2YZ.mjs → chunk-GSUC4HWP.mjs} +1 -1
  11. package/dist/{chunk-QJYFTTM2.js → chunk-IHVMNOS4.js} +2 -2
  12. package/dist/{chunk-HPJMIBBK.mjs → chunk-IX6SEOSK.mjs} +41 -12
  13. package/dist/{chunk-52QSN2VQ.mjs → chunk-JBK5ZLMH.mjs} +1 -1
  14. package/dist/{chunk-OW5XTGVN.mjs → chunk-L4JFECXU.mjs} +2 -2
  15. package/dist/{chunk-VSK2E35J.mjs → chunk-M4766VUV.mjs} +1 -1
  16. package/dist/{chunk-Z3HCJ43H.mjs → chunk-MFAFB4K7.mjs} +1 -1
  17. package/dist/{chunk-4NAMD62I.js → chunk-MUT6BTZS.js} +7 -7
  18. package/dist/{chunk-WMLS4TMX.mjs → chunk-QNLSCOR5.mjs} +1 -1
  19. package/dist/{chunk-REYL77RE.mjs → chunk-W7NTRSPD.mjs} +17 -10
  20. package/dist/{chunk-PM6CVGXJ.js → chunk-WNVHPMBI.js} +16 -8
  21. package/dist/chunk-Z5USXWTE.js +8 -0
  22. package/dist/{chunk-QYR66E2G.js → chunk-ZBHQPVWE.js} +2 -2
  23. package/dist/gestureLayer/index.js +10 -10
  24. package/dist/gestureLayer/index.mjs +3 -3
  25. package/dist/index.d.mts +91 -4
  26. package/dist/index.d.ts +91 -4
  27. package/dist/index.js +69 -53
  28. package/dist/index.mjs +24 -20
  29. package/dist/motion/FlatList.js +5 -5
  30. package/dist/motion/FlatList.mjs +4 -4
  31. package/dist/motion/Image.js +5 -5
  32. package/dist/motion/Image.mjs +4 -4
  33. package/dist/motion/Pressable.js +5 -5
  34. package/dist/motion/Pressable.mjs +4 -4
  35. package/dist/motion/ScrollView.js +5 -5
  36. package/dist/motion/ScrollView.mjs +4 -4
  37. package/dist/motion/Text.js +5 -5
  38. package/dist/motion/Text.mjs +4 -4
  39. package/dist/motion/View.js +5 -5
  40. package/dist/motion/View.mjs +4 -4
  41. package/dist/touch/index.js +3 -3
  42. package/dist/touch/index.mjs +1 -1
  43. package/llms.txt +19 -2
  44. package/package.json +1 -1
  45. package/src/index.ts +5 -0
  46. package/src/motion/createMotionComponent.tsx +45 -10
  47. package/src/stagger/Stagger.tsx +75 -0
  48. package/src/stagger/StaggerContext.ts +25 -0
  49. package/src/stagger/index.ts +2 -0
  50. package/src/transitions/index.ts +6 -1
  51. package/src/transitions/resolve.ts +7 -1
  52. package/src/transitions/runtime.ts +22 -7
  53. package/src/values/index.ts +1 -0
  54. package/src/values/useInterpolatedStyle.ts +37 -7
  55. package/dist/chunk-NPJ46457.js +0 -8
  56. package/dist/chunk-YUTS6JRU.js +0 -8
  57. package/dist/chunk-ZSOCRHU3.js +0 -8
package/CHANGELOG.md CHANGED
@@ -4,6 +4,34 @@ All notable changes to `@rootnative/inertia` are documented here. The format fol
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.0.9] - 2026-08-22
8
+
9
+ ### Changed
10
+
11
+ - **`useInterpolatedStyle` types its return against the map it was given, so a `style` array no longer needs a cast.** The hook returned `ReturnType<typeof useAnimatedStyle>`, which resolves to Reanimated's `DefaultStyle` — the union `ViewStyle | ImageStyle | TextStyle`. Assigning that union to a single style works, but a **style array** checks every member, and `TextStyle` is not assignable to `ViewStyle` (`cursor` is `string` there and `CursorValue` here). So the documented, dominant call shape — a transform/opacity fragment spread into `style={[base, fragment]}` — was a type error, and consumers cast it away.
12
+
13
+ The return is now `InterpolatedStyle<K>`, computed from the map's own keys: view keys satisfy `StyleProp<ViewStyle>`, text-metric keys (`fontSize`, `lineHeight`, `letterSpacing`) satisfy `StyleProp<TextStyle>`, `tintColor` satisfies `StyleProp<ImageStyle>`, and transform keys collapse into the single `transform` array the worklet emits. The narrowing is exact rather than permissive — a text-only fragment is still rejected from a `ViewStyle` slot, pinned in both directions by `__type-tests__/interpolated-style.test-d.tsx`.
14
+
15
+ Types only: no runtime change, and no bundle-size change. Removing a now-unnecessary `as ViewStyle` is safe; the cast remains harmless if left in place. `InterpolatedStyle` is exported from the root barrel.
16
+
17
+ Surfaced by the `reelist` validation consumer, and it is the independent-application half of the loop reporting its first library defect.
18
+
19
+ ## [0.0.8] - 2026-08-16
20
+
21
+ ### Added
22
+
23
+ - **`<Stagger>` — parent-owned delays for a cascading list entrance.** Wrapping a list in `<Stagger interval={60}>` assigns each child a delay of `delay + position * interval` milliseconds, applied to the declarative animations (the `initial` → `animate` mount and any later `animate` change) of every `Motion.*` primitive in that child's subtree. No child computes `index * ms` itself, which removes the two structural problems of the per-child form: a list that filters or reorders staggers from stale indices, and the cascade cannot be turned off in one place. Positions re-derive from render order every render, `from="last"` reverses the cascade, and `enabled={false}` zeroes every delay — pass `enabled={revealed}` and the reveal cascades while the hide animates together.
24
+
25
+ The delay wraps each key's fully resolved animation exactly once, on the JS thread — never merged into the base transition config, which a keyframe sequence would re-apply per step. It composes with the child's own `transition.delay` (the two add). It deliberately does not delay `gesture` sub-state feedback (press feedback delayed by list position reads as lag), `<Presence>` exits (a positional delay holds `safeToRemove` — and therefore the unmount — hostage to the cascade), or reduced-motion snaps (a deferred snap is still choreography).
26
+
27
+ `<Stagger>` renders no host view — only per-child context providers, so it composes with any layout. Custom animated components built on `resolveTransition` / `resolveAnimatableValue` can participate through the new `useStaggerDelay()` hook, and `applyDelay(animation, ms)` is now exported alongside the other transition utilities.
28
+
29
+ Surfaced by the `purrfect-match` validation consumer (DX feedback entry 13), generalized here per the audience-and-scope rule: the shape follows Framer Motion's `staggerChildren` / `delayChildren`, renamed to `interval` / `delay` because the component's own name already says "children".
30
+
31
+ - **`buildReleaseAnimation` accepts a settle callback.** A third, optional `callback` parameter — the same `(finished) => void` shape Reanimated's `with*` factories accept — is forwarded to the underlying `withSpring` / `withTiming` / `withDecay` call and fires once when the animation settles. For `no-animation` it fires synchronously with `finished: true`, since a direct assignment has no settle point of its own. Existing two-argument call sites are unchanged.
32
+
33
+ This is the primitive behind `useSwipe`'s new `onSwipeEnd` in `@rootnative/inertia-gestures`: a gesture-release worklet can now learn when its release animation has finished without polling a shared value. The `AnimationCallback` type is exported from the root barrel alongside it.
34
+
7
35
  ## [0.0.7] - 2026-08-14
8
36
 
9
37
  ### Added
@@ -257,7 +285,9 @@ Initial alpha publish. The full initial surface is in place; APIs are still subj
257
285
  - SVG path morphing, gradient interpolation, and shared-element transitions across screens are out of scope until `0.2.x` / `1.x` per the roadmap.
258
286
  - `react-native-gesture-handler` integration (drag, pan, swipe sub-states) lands in `0.2` via the optional `@rootnative/inertia-gestures` adapter.
259
287
 
260
- [unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.7...HEAD
288
+ [unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.9...HEAD
289
+ [0.0.9]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.9
290
+ [0.0.8]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.8
261
291
  [0.0.7]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.7
262
292
  [0.0.6]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.6
263
293
  [0.0.5]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.5
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.7` — stable. Pre-`1.0.0` minor versions may break — see the root [README](https://github.com/rootnative/inertia#versioning--release).
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).
16
16
 
17
17
  ## Install
18
18
 
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var chunkE3ALFSH2_js = require('./chunk-E3ALFSH2.js');
4
+ var reactNative = require('react-native');
5
+
6
+ var MotionView = chunkE3ALFSH2_js.createMotionComponent(reactNative.View);
7
+
8
+ exports.MotionView = MotionView;
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var chunkE3ALFSH2_js = require('./chunk-E3ALFSH2.js');
4
+ var reactNative = require('react-native');
5
+
6
+ var MotionText = chunkE3ALFSH2_js.createMotionComponent(reactNative.Text);
7
+
8
+ exports.MotionText = MotionText;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkPM6CVGXJ_js = require('./chunk-PM6CVGXJ.js');
3
+ var chunkWNVHPMBI_js = require('./chunk-WNVHPMBI.js');
4
4
  var react = require('react');
5
5
  var reactNativeReanimated = require('react-native-reanimated');
6
6
  var jsxRuntime = require('react/jsx-runtime');
@@ -32,7 +32,7 @@ function MotionConfig({
32
32
  children
33
33
  }) {
34
34
  const parent = useMotionConfig();
35
- const transitionsSig = chunkPM6CVGXJ_js.stableSig(transitions);
35
+ const transitionsSig = chunkWNVHPMBI_js.stableSig(transitions);
36
36
  const value = react.useMemo(
37
37
  () => ({
38
38
  reducedMotion: reducedMotion ?? parent.reducedMotion,
@@ -66,7 +66,7 @@ function resolveNamedTransitionProp(transition, registry) {
66
66
  if (typeof transition === "string") {
67
67
  return lookupNamedTransition(transition, registry);
68
68
  }
69
- if (chunkPM6CVGXJ_js.isTopLevelTransition(transition)) return transition;
69
+ if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
70
70
  const map = transition;
71
71
  let out = null;
72
72
  for (const key in map) {
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunk6V7MOBXO_js = require('./chunk-6V7MOBXO.js');
3
+ var chunkE3ALFSH2_js = require('./chunk-E3ALFSH2.js');
4
4
  var reactNative = require('react-native');
5
5
 
6
- var MotionPressable = chunk6V7MOBXO_js.createMotionComponent(reactNative.Pressable);
6
+ var MotionPressable = chunkE3ALFSH2_js.createMotionComponent(reactNative.Pressable);
7
7
 
8
8
  exports.MotionPressable = MotionPressable;
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-HPJMIBBK.mjs';
1
+ import { createMotionComponent } from './chunk-IX6SEOSK.mjs';
2
2
  import { Image } from 'react-native';
3
3
 
4
4
  var MotionImage = createMotionComponent(Image);
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkOBRGJAST_js = require('./chunk-OBRGJAST.js');
4
- var chunkPM6CVGXJ_js = require('./chunk-PM6CVGXJ.js');
3
+ var chunk6AN5X3YE_js = require('./chunk-6AN5X3YE.js');
4
+ var chunkWNVHPMBI_js = require('./chunk-WNVHPMBI.js');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var Animated = require('react-native-reanimated');
@@ -159,6 +159,26 @@ function PresenceItem({
159
159
  );
160
160
  return /* @__PURE__ */ jsxRuntime.jsx(PresenceContext.Provider, { value, children });
161
161
  }
162
+ var StaggerContext = react.createContext(0);
163
+ function useStaggerDelay() {
164
+ return react.useContext(StaggerContext);
165
+ }
166
+ function Stagger({
167
+ children,
168
+ interval,
169
+ delay = 0,
170
+ from = "first",
171
+ enabled = true
172
+ }) {
173
+ const items = react.Children.toArray(children);
174
+ const count = items.length;
175
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((child, index) => {
176
+ const position = from === "last" ? count - 1 - index : index;
177
+ const childDelay = enabled ? delay + position * interval : 0;
178
+ const key = react.isValidElement(child) ? child.key ?? index : index;
179
+ return /* @__PURE__ */ jsxRuntime.jsx(StaggerContext.Provider, { value: childDelay, children: child }, key);
180
+ }) });
181
+ }
162
182
 
163
183
  // src/internal/boxShadow.ts
164
184
  var LENGTH = /^[+-]?(\d+\.?\d*|\.\d+)(px)?$/i;
@@ -345,14 +365,14 @@ function resolveLayoutTransition(layout) {
345
365
  if (cfg.type === "no-animation") return void 0;
346
366
  if (cfg.type === "timing") {
347
367
  let builder2 = Animated.LinearTransition.duration(cfg.duration ?? 300);
348
- const easing = chunkPM6CVGXJ_js.ensureWorkletEasing(cfg.easing);
368
+ const easing = chunkWNVHPMBI_js.ensureWorkletEasing(cfg.easing);
349
369
  if (easing) builder2 = builder2.easing(easing);
350
370
  if (cfg.delay) builder2 = builder2.delay(cfg.delay);
351
371
  return builder2;
352
372
  }
353
373
  const spring = cfg.type === "decay" ? { type: "spring" } : cfg;
354
- const { stiffness, damping, mass } = chunkPM6CVGXJ_js.springToReanimated({
355
- ...chunkPM6CVGXJ_js.DEFAULT_SPRING,
374
+ const { stiffness, damping, mass } = chunkWNVHPMBI_js.springToReanimated({
375
+ ...chunkWNVHPMBI_js.DEFAULT_SPRING,
356
376
  ...spring
357
377
  });
358
378
  let builder = Animated.LinearTransition.springify().stiffness(stiffness).damping(damping).mass(mass);
@@ -546,8 +566,8 @@ function legBuilder(transition) {
546
566
  Animated.withTiming(to, { duration })
547
567
  );
548
568
  }
549
- const springCfg = transition?.type === "spring" ? { ...chunkPM6CVGXJ_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunkPM6CVGXJ_js.DEFAULT_SPRING };
550
- const springParams = chunkPM6CVGXJ_js.springToReanimated(springCfg);
569
+ const springCfg = transition?.type === "spring" ? { ...chunkWNVHPMBI_js.DEFAULT_SPRING, ...transition } : { type: "spring", ...chunkWNVHPMBI_js.DEFAULT_SPRING };
570
+ const springParams = chunkWNVHPMBI_js.springToReanimated(springCfg);
551
571
  return (from, to) => Animated.withSequence(
552
572
  Animated.withTiming(from, { duration: 0 }),
553
573
  Animated.withSpring(to, springParams)
@@ -833,14 +853,14 @@ var DEFAULT_RESTING = {
833
853
  function transitionFor(prop, transition) {
834
854
  if (!transition) return void 0;
835
855
  if (typeof transition === "string") return void 0;
836
- if (chunkPM6CVGXJ_js.isTopLevelTransition(transition)) return transition;
856
+ if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
837
857
  if (GESTURE_LAYER_NAME_SET.has(prop)) return void 0;
838
858
  return transition[prop];
839
859
  }
840
860
  function gestureLayerTransitionFor(layer, transition) {
841
861
  if (!transition) return void 0;
842
862
  if (typeof transition === "string") return void 0;
843
- if (chunkPM6CVGXJ_js.isTopLevelTransition(transition)) return transition;
863
+ if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
844
864
  return transition[layer];
845
865
  }
846
866
  function createMotionComponent(Component) {
@@ -890,12 +910,12 @@ function createMotionComponent(Component) {
890
910
  onLayout: userOnLayout,
891
911
  ...rest
892
912
  } = props;
893
- const namedTransitions = chunkOBRGJAST_js.useNamedTransitions();
894
- const transition = chunkOBRGJAST_js.resolveNamedTransitionProp(
913
+ const namedTransitions = chunk6AN5X3YE_js.useNamedTransitions();
914
+ const transition = chunk6AN5X3YE_js.resolveNamedTransitionProp(
895
915
  transitionProp,
896
916
  namedTransitions
897
917
  );
898
- const layout = typeof layoutProp === "string" ? chunkOBRGJAST_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
918
+ const layout = typeof layoutProp === "string" ? chunk6AN5X3YE_js.lookupNamedTransition(layoutProp, namedTransitions) : layoutProp;
899
919
  if (__DEV__ && typeof style === "function") {
900
920
  throw new Error(
901
921
  "[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."
@@ -903,7 +923,8 @@ function createMotionComponent(Component) {
903
923
  }
904
924
  const presence = usePresence();
905
925
  const isExiting = presence !== null && presence.isPresent === false;
906
- const shouldReduceMotion = chunkOBRGJAST_js.useShouldReduceMotion();
926
+ const shouldReduceMotion = chunk6AN5X3YE_js.useShouldReduceMotion();
927
+ const staggerDelay = useStaggerDelay();
907
928
  const onAnimationEndRef = react.useRef(onAnimationEnd);
908
929
  onAnimationEndRef.current = onAnimationEnd;
909
930
  const variantKey = useControllerKey(controller);
@@ -987,7 +1008,7 @@ function createMotionComponent(Component) {
987
1008
  if (__DEV__ && hasBoxShadowRef.current && activeKeysRef.current.some(
988
1009
  (k) => k !== "boxShadow" && k.startsWith("shadow")
989
1010
  )) {
990
- chunkPM6CVGXJ_js.warnOnce(
1011
+ chunkWNVHPMBI_js.warnOnce(
991
1012
  "boxShadow-with-native-shadow",
992
1013
  "[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."
993
1014
  );
@@ -1055,7 +1076,7 @@ function createMotionComponent(Component) {
1055
1076
  const boxShadowInsets = Animated.useSharedValue(
1056
1077
  boxShadowSeedRef.current.insets
1057
1078
  );
1058
- const styleRestingSig = chunkPM6CVGXJ_js.stableSig(styleResting);
1079
+ const styleRestingSig = chunkWNVHPMBI_js.stableSig(styleResting);
1059
1080
  react.useEffect(() => {
1060
1081
  for (const key of activeKeysRef.current) {
1061
1082
  if (everDrivenRef.current.has(key)) continue;
@@ -1083,13 +1104,13 @@ function createMotionComponent(Component) {
1083
1104
  const gestureSV = Animated.useSharedValue(
1084
1105
  resolveGestureLayers(gesture)
1085
1106
  );
1086
- const gestureTargetsSig = chunkPM6CVGXJ_js.stableSig(gesture);
1107
+ const gestureTargetsSig = chunkWNVHPMBI_js.stableSig(gesture);
1087
1108
  react.useEffect(() => {
1088
1109
  gestureSV.value = resolveGestureLayers(gesture);
1089
1110
  }, [gestureTargetsSig]);
1090
1111
  const baseRecord = isExiting && exitRecord ? { ...animateRecord, ...exitRecord } : animateRecord;
1091
- const baseSig = chunkPM6CVGXJ_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
1092
- const transitionSig = chunkPM6CVGXJ_js.stableSig(transition);
1112
+ const baseSig = chunkWNVHPMBI_js.stableSig(baseRecord) + (isExiting ? "|exit" : "") + (shouldReduceMotion ? "|rm" : "");
1113
+ const transitionSig = chunkWNVHPMBI_js.stableSig(transition);
1093
1114
  const safeToRemoveRef = react.useRef(void 0);
1094
1115
  safeToRemoveRef.current = presence?.safeToRemove;
1095
1116
  react.useEffect(() => {
@@ -1111,6 +1132,7 @@ function createMotionComponent(Component) {
1111
1132
  SHADOW_OFFSET_KEY_SET.has(key) ? "shadowOffset" : key,
1112
1133
  transition
1113
1134
  );
1135
+ const runStagger = shouldReduceMotion || isExiting || staggerDelay <= 0 ? 0 : staggerDelay;
1114
1136
  let transformPending = 0;
1115
1137
  for (const k of ALL_KEYS) {
1116
1138
  if (!TRANSFORM_KEY_SET.has(k) || baseRecord[k] === void 0) continue;
@@ -1129,6 +1151,7 @@ function createMotionComponent(Component) {
1129
1151
  boxShadowInsets,
1130
1152
  shadowTarget,
1131
1153
  cfg2,
1154
+ runStagger,
1132
1155
  makeKeyCallbackFactory(
1133
1156
  "boxShadow",
1134
1157
  sharedValues.boxShadow,
@@ -1162,10 +1185,13 @@ function createMotionComponent(Component) {
1162
1185
  isExiting ? onSettle : void 0,
1163
1186
  TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
1164
1187
  );
1165
- sharedValues[key].value = chunkPM6CVGXJ_js.resolveAnimatableValue(
1166
- COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
1167
- cfg,
1168
- factory
1188
+ sharedValues[key].value = chunkWNVHPMBI_js.applyDelay(
1189
+ chunkWNVHPMBI_js.resolveAnimatableValue(
1190
+ COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
1191
+ cfg,
1192
+ factory
1193
+ ),
1194
+ runStagger
1169
1195
  );
1170
1196
  }
1171
1197
  if (isExiting && pending === 0) {
@@ -1224,7 +1250,7 @@ function createMotionComponent(Component) {
1224
1250
  const sharedLayout = useSharedLayout({
1225
1251
  layoutId,
1226
1252
  userRef: ref,
1227
- transition: chunkPM6CVGXJ_js.isTopLevelTransition(transition) ? transition : void 0,
1253
+ transition: chunkWNVHPMBI_js.isTopLevelTransition(transition) ? transition : void 0,
1228
1254
  shouldReduceMotion,
1229
1255
  userOnLayout,
1230
1256
  readStyles: readSharedStyles
@@ -1326,7 +1352,7 @@ function createMotionComponent(Component) {
1326
1352
  setFocusVisible,
1327
1353
  setHovered
1328
1354
  );
1329
- const layoutSig = chunkPM6CVGXJ_js.stableSig(layout);
1355
+ const layoutSig = chunkWNVHPMBI_js.stableSig(layout);
1330
1356
  const layoutTransition = react.useMemo(
1331
1357
  () => shouldReduceMotion ? void 0 : resolveLayoutTransition(layout),
1332
1358
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1467,7 +1493,7 @@ function shadowOffsetAxisFor(key) {
1467
1493
  function shadowOffsetAxisValue(source, axis) {
1468
1494
  return source?.[axis];
1469
1495
  }
1470
- function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
1496
+ function driveBoxShadow(slot, insetSlot, target, cfg, staggerDelay, factory) {
1471
1497
  const currentLayers = payloadToLayers(slot.value);
1472
1498
  const { from, to, insets } = prepareBoxShadowAnimation(
1473
1499
  { layers: currentLayers, insets: insetSlot.value },
@@ -1475,10 +1501,13 @@ function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
1475
1501
  );
1476
1502
  insetSlot.value = insets;
1477
1503
  if (from.length !== currentLayers.length) slot.value = layersToPayload(from);
1478
- slot.value = chunkPM6CVGXJ_js.resolveTransition(
1479
- cfg,
1480
- layersToPayload(to),
1481
- factory?.("animation", void 0)
1504
+ slot.value = chunkWNVHPMBI_js.applyDelay(
1505
+ chunkWNVHPMBI_js.resolveTransition(
1506
+ cfg,
1507
+ layersToPayload(to),
1508
+ factory?.("animation", void 0)
1509
+ ),
1510
+ staggerDelay
1482
1511
  );
1483
1512
  }
1484
1513
  function styleValueFor(flat, key) {
@@ -1599,7 +1628,7 @@ function resolveGestureLayers(gesture) {
1599
1628
  for (const key of ALL_KEYS) {
1600
1629
  if (STRUCTURED_KEY_SET.has(key)) {
1601
1630
  if (__DEV__ && subState[key] !== void 0) {
1602
- chunkPM6CVGXJ_js.warnOnce(
1631
+ chunkWNVHPMBI_js.warnOnce(
1603
1632
  `gesture-structured-${layer}-${key}`,
1604
1633
  `[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\`.`
1605
1634
  );
@@ -1623,7 +1652,7 @@ function resolveGestureLayers(gesture) {
1623
1652
  return out;
1624
1653
  }
1625
1654
  function useGestureLayerProgress(progress, active, declared, layer, transition, isExiting, shouldReduceMotion) {
1626
- const layerCfgSig = chunkPM6CVGXJ_js.stableSig(gestureLayerTransitionFor(layer, transition));
1655
+ const layerCfgSig = chunkWNVHPMBI_js.stableSig(gestureLayerTransitionFor(layer, transition));
1627
1656
  react.useEffect(() => {
1628
1657
  if (!declared) return;
1629
1658
  if (isExiting) {
@@ -1632,7 +1661,7 @@ function useGestureLayerProgress(progress, active, declared, layer, transition,
1632
1661
  }
1633
1662
  const target = active ? 1 : 0;
1634
1663
  const cfg = shouldReduceMotion ? { type: "no-animation" } : gestureLayerTransitionFor(layer, transition) ?? { type: "spring" };
1635
- progress.value = chunkPM6CVGXJ_js.resolveTransition(cfg, target);
1664
+ progress.value = chunkWNVHPMBI_js.resolveTransition(cfg, target);
1636
1665
  }, [active, declared, isExiting, shouldReduceMotion, layerCfgSig]);
1637
1666
  }
1638
1667
  function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisible, setHovered) {
@@ -1665,7 +1694,7 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
1665
1694
  if (gesture.focused || gesture.focusVisible) {
1666
1695
  handlers.onFocus = compose(rest.onFocus, () => {
1667
1696
  if (gesture.focused) setFocused(true);
1668
- if (gesture.focusVisible && chunkOBRGJAST_js.isFocusVisible()) setFocusVisible(true);
1697
+ if (gesture.focusVisible && chunk6AN5X3YE_js.isFocusVisible()) setFocusVisible(true);
1669
1698
  });
1670
1699
  handlers.onBlur = compose(rest.onBlur, () => {
1671
1700
  if (gesture.focused) setFocused(false);
@@ -1708,8 +1737,10 @@ function compose(user, ours) {
1708
1737
  }
1709
1738
 
1710
1739
  exports.Presence = Presence;
1740
+ exports.Stagger = Stagger;
1711
1741
  exports.TRANSPARENT = TRANSPARENT;
1712
1742
  exports.createMotionComponent = createMotionComponent;
1713
1743
  exports.pairBoxShadowLayers = pairBoxShadowLayers;
1714
1744
  exports.resolveBoxShadowInput = resolveBoxShadowInput;
1715
1745
  exports.usePresence = usePresence;
1746
+ exports.useStaggerDelay = useStaggerDelay;
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-HPJMIBBK.mjs';
1
+ import { createMotionComponent } from './chunk-IX6SEOSK.mjs';
2
2
  import Animated from 'react-native-reanimated';
3
3
 
4
4
  var MotionFlatList = createMotionComponent(
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-HPJMIBBK.mjs';
1
+ import { createMotionComponent } from './chunk-IX6SEOSK.mjs';
2
2
  import { View } from 'react-native';
3
3
 
4
4
  var MotionView = createMotionComponent(View);
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunk6V7MOBXO_js = require('./chunk-6V7MOBXO.js');
3
+ var chunkE3ALFSH2_js = require('./chunk-E3ALFSH2.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 = chunk6V7MOBXO_js.createMotionComponent(
10
+ var MotionFlatList = chunkE3ALFSH2_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,5 +1,5 @@
1
- import { useNamedTransitions, resolveNamedTransitionProp, lookupNamedTransition, useShouldReduceMotion, isFocusVisible } from './chunk-Z3HCJ43H.mjs';
2
- import { warnOnce, stableSig, resolveAnimatableValue, isTopLevelTransition, resolveTransition, ensureWorkletEasing, springToReanimated, DEFAULT_SPRING } from './chunk-REYL77RE.mjs';
1
+ import { useNamedTransitions, resolveNamedTransitionProp, lookupNamedTransition, useShouldReduceMotion, isFocusVisible } from './chunk-MFAFB4K7.mjs';
2
+ import { warnOnce, stableSig, applyDelay, resolveAnimatableValue, isTopLevelTransition, resolveTransition, ensureWorkletEasing, springToReanimated, DEFAULT_SPRING } from './chunk-W7NTRSPD.mjs';
3
3
  import { createContext, useContext, useMemo, Children, isValidElement, useState, useRef, useCallback, forwardRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
  import Animated, { useSharedValue, cancelAnimation, useAnimatedStyle, interpolateColor, reanimatedVersion, runOnJS, LinearTransition, withSequence, withTiming, withSpring } from 'react-native-reanimated';
@@ -153,6 +153,26 @@ function PresenceItem({
153
153
  );
154
154
  return /* @__PURE__ */ jsx(PresenceContext.Provider, { value, children });
155
155
  }
156
+ var StaggerContext = createContext(0);
157
+ function useStaggerDelay() {
158
+ return useContext(StaggerContext);
159
+ }
160
+ function Stagger({
161
+ children,
162
+ interval,
163
+ delay = 0,
164
+ from = "first",
165
+ enabled = true
166
+ }) {
167
+ const items = Children.toArray(children);
168
+ const count = items.length;
169
+ return /* @__PURE__ */ jsx(Fragment, { children: items.map((child, index) => {
170
+ const position = from === "last" ? count - 1 - index : index;
171
+ const childDelay = enabled ? delay + position * interval : 0;
172
+ const key = isValidElement(child) ? child.key ?? index : index;
173
+ return /* @__PURE__ */ jsx(StaggerContext.Provider, { value: childDelay, children: child }, key);
174
+ }) });
175
+ }
156
176
 
157
177
  // src/internal/boxShadow.ts
158
178
  var LENGTH = /^[+-]?(\d+\.?\d*|\.\d+)(px)?$/i;
@@ -898,6 +918,7 @@ function createMotionComponent(Component) {
898
918
  const presence = usePresence();
899
919
  const isExiting = presence !== null && presence.isPresent === false;
900
920
  const shouldReduceMotion = useShouldReduceMotion();
921
+ const staggerDelay = useStaggerDelay();
901
922
  const onAnimationEndRef = useRef(onAnimationEnd);
902
923
  onAnimationEndRef.current = onAnimationEnd;
903
924
  const variantKey = useControllerKey(controller);
@@ -1105,6 +1126,7 @@ function createMotionComponent(Component) {
1105
1126
  SHADOW_OFFSET_KEY_SET.has(key) ? "shadowOffset" : key,
1106
1127
  transition
1107
1128
  );
1129
+ const runStagger = shouldReduceMotion || isExiting || staggerDelay <= 0 ? 0 : staggerDelay;
1108
1130
  let transformPending = 0;
1109
1131
  for (const k of ALL_KEYS) {
1110
1132
  if (!TRANSFORM_KEY_SET.has(k) || baseRecord[k] === void 0) continue;
@@ -1123,6 +1145,7 @@ function createMotionComponent(Component) {
1123
1145
  boxShadowInsets,
1124
1146
  shadowTarget,
1125
1147
  cfg2,
1148
+ runStagger,
1126
1149
  makeKeyCallbackFactory(
1127
1150
  "boxShadow",
1128
1151
  sharedValues.boxShadow,
@@ -1156,10 +1179,13 @@ function createMotionComponent(Component) {
1156
1179
  isExiting ? onSettle : void 0,
1157
1180
  TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
1158
1181
  );
1159
- sharedValues[key].value = resolveAnimatableValue(
1160
- COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
1161
- cfg,
1162
- factory
1182
+ sharedValues[key].value = applyDelay(
1183
+ resolveAnimatableValue(
1184
+ COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
1185
+ cfg,
1186
+ factory
1187
+ ),
1188
+ runStagger
1163
1189
  );
1164
1190
  }
1165
1191
  if (isExiting && pending === 0) {
@@ -1461,7 +1487,7 @@ function shadowOffsetAxisFor(key) {
1461
1487
  function shadowOffsetAxisValue(source, axis) {
1462
1488
  return source?.[axis];
1463
1489
  }
1464
- function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
1490
+ function driveBoxShadow(slot, insetSlot, target, cfg, staggerDelay, factory) {
1465
1491
  const currentLayers = payloadToLayers(slot.value);
1466
1492
  const { from, to, insets } = prepareBoxShadowAnimation(
1467
1493
  { layers: currentLayers, insets: insetSlot.value },
@@ -1469,10 +1495,13 @@ function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
1469
1495
  );
1470
1496
  insetSlot.value = insets;
1471
1497
  if (from.length !== currentLayers.length) slot.value = layersToPayload(from);
1472
- slot.value = resolveTransition(
1473
- cfg,
1474
- layersToPayload(to),
1475
- factory?.("animation", void 0)
1498
+ slot.value = applyDelay(
1499
+ resolveTransition(
1500
+ cfg,
1501
+ layersToPayload(to),
1502
+ factory?.("animation", void 0)
1503
+ ),
1504
+ staggerDelay
1476
1505
  );
1477
1506
  }
1478
1507
  function styleValueFor(flat, key) {
@@ -1701,4 +1730,4 @@ function compose(user, ours) {
1701
1730
  };
1702
1731
  }
1703
1732
 
1704
- export { Presence, TRANSPARENT, createMotionComponent, pairBoxShadowLayers, resolveBoxShadowInput, usePresence };
1733
+ export { Presence, Stagger, TRANSPARENT, createMotionComponent, pairBoxShadowLayers, resolveBoxShadowInput, usePresence, useStaggerDelay };
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-HPJMIBBK.mjs';
1
+ import { createMotionComponent } from './chunk-IX6SEOSK.mjs';
2
2
  import { Pressable } from 'react-native';
3
3
 
4
4
  var MotionPressable = createMotionComponent(Pressable);
@@ -1,5 +1,5 @@
1
- import { useShouldReduceMotion, resolveNamedTransitionProp, useNamedTransitions, isFocusVisible } from './chunk-Z3HCJ43H.mjs';
2
- import { resolveTransition, isTopLevelTransition } from './chunk-REYL77RE.mjs';
1
+ import { useShouldReduceMotion, resolveNamedTransitionProp, useNamedTransitions, isFocusVisible } from './chunk-MFAFB4K7.mjs';
2
+ import { resolveTransition, isTopLevelTransition } from './chunk-W7NTRSPD.mjs';
3
3
  import { useCallback, useMemo } from 'react';
4
4
  import { useSharedValue } from 'react-native-reanimated';
5
5
 
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-HPJMIBBK.mjs';
1
+ import { createMotionComponent } from './chunk-IX6SEOSK.mjs';
2
2
  import { ScrollView } from 'react-native';
3
3
 
4
4
  var MotionScrollView = createMotionComponent(ScrollView);
@@ -1,4 +1,4 @@
1
- import { stableSig, isTopLevelTransition } from './chunk-REYL77RE.mjs';
1
+ import { stableSig, isTopLevelTransition } from './chunk-W7NTRSPD.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';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkOBRGJAST_js = require('./chunk-OBRGJAST.js');
4
- var chunkPM6CVGXJ_js = require('./chunk-PM6CVGXJ.js');
3
+ var chunk6AN5X3YE_js = require('./chunk-6AN5X3YE.js');
4
+ var chunkWNVHPMBI_js = require('./chunk-WNVHPMBI.js');
5
5
  var react = require('react');
6
6
  var reactNativeReanimated = require('react-native-reanimated');
7
7
 
@@ -10,12 +10,12 @@ 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 = chunkOBRGJAST_js.useShouldReduceMotion();
14
- const resolved = chunkOBRGJAST_js.resolveNamedTransitionProp(transition, chunkOBRGJAST_js.useNamedTransitions());
13
+ const shouldReduceMotion = chunk6AN5X3YE_js.useShouldReduceMotion();
14
+ const resolved = chunk6AN5X3YE_js.resolveNamedTransitionProp(transition, chunk6AN5X3YE_js.useNamedTransitions());
15
15
  const setLayer = react.useCallback(
16
16
  (sv, layer, target) => {
17
17
  const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
18
- sv.value = chunkPM6CVGXJ_js.resolveTransition(cfg, target);
18
+ sv.value = chunkWNVHPMBI_js.resolveTransition(cfg, target);
19
19
  },
20
20
  // The transition is intentionally read on every call rather than cooked
21
21
  // into the dep array — a fresh literal each render would otherwise
@@ -34,7 +34,7 @@ function useGesture(transition) {
34
34
  onHoverOut: () => setLayer(hovered, "hovered", 0),
35
35
  onFocus: () => {
36
36
  setLayer(focused, "focused", 1);
37
- if (chunkOBRGJAST_js.isFocusVisible()) setLayer(focusVisible, "focusVisible", 1);
37
+ if (chunk6AN5X3YE_js.isFocusVisible()) setLayer(focusVisible, "focusVisible", 1);
38
38
  },
39
39
  onBlur: () => {
40
40
  setLayer(focused, "focused", 0);
@@ -47,7 +47,7 @@ function useGesture(transition) {
47
47
  }
48
48
  function layerTransition(layer, transition) {
49
49
  if (!transition) return void 0;
50
- if (chunkPM6CVGXJ_js.isTopLevelTransition(transition)) return transition;
50
+ if (chunkWNVHPMBI_js.isTopLevelTransition(transition)) return transition;
51
51
  return transition[layer];
52
52
  }
53
53
 
@@ -1,4 +1,4 @@
1
- import { createMotionComponent } from './chunk-HPJMIBBK.mjs';
1
+ import { createMotionComponent } from './chunk-IX6SEOSK.mjs';
2
2
  import { Text } from 'react-native';
3
3
 
4
4
  var MotionText = createMotionComponent(Text);