@rootnative/inertia 0.0.6 → 0.0.7

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 (63) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/README.md +7 -1
  3. package/dist/{chunk-C3EDC5ZW.mjs → chunk-52QSN2VQ.mjs} +1 -1
  4. package/dist/{chunk-767UKZXG.js → chunk-6V7MOBXO.js} +12 -0
  5. package/dist/{chunk-2ICQLWH2.mjs → chunk-HPJMIBBK.mjs} +12 -0
  6. package/dist/{chunk-PFPO7DX2.mjs → chunk-KBFN4TRO.mjs} +1 -1
  7. package/dist/chunk-NPJ46457.js +8 -0
  8. package/dist/chunk-QJYFTTM2.js +28 -0
  9. package/dist/{chunk-X7B5WR5A.js → chunk-QYR66E2G.js} +2 -2
  10. package/dist/{chunk-CMHVF6F4.mjs → chunk-RUIOM2YZ.mjs} +1 -1
  11. package/dist/{chunk-BAAQI37F.mjs → chunk-VSK2E35J.mjs} +1 -1
  12. package/dist/{chunk-5MGWHOSV.js → chunk-WGCF3WQG.js} +2 -2
  13. package/dist/{chunk-F7LJX56B.mjs → chunk-WMLS4TMX.mjs} +1 -1
  14. package/dist/chunk-YUTS6JRU.js +8 -0
  15. package/dist/chunk-ZOBOKLAS.mjs +22 -0
  16. package/dist/chunk-ZSOCRHU3.js +8 -0
  17. package/dist/gestureLayer/index.d.mts +2 -2
  18. package/dist/gestureLayer/index.d.ts +2 -2
  19. package/dist/index.d.mts +17 -9
  20. package/dist/index.d.ts +17 -9
  21. package/dist/index.js +29 -23
  22. package/dist/index.mjs +16 -13
  23. package/dist/motion/FlatList.d.mts +53 -0
  24. package/dist/motion/FlatList.d.ts +53 -0
  25. package/dist/motion/FlatList.js +13 -0
  26. package/dist/motion/FlatList.mjs +4 -0
  27. package/dist/motion/Image.d.mts +1 -1
  28. package/dist/motion/Image.d.ts +1 -1
  29. package/dist/motion/Image.js +3 -3
  30. package/dist/motion/Image.mjs +2 -2
  31. package/dist/motion/Pressable.d.mts +1 -1
  32. package/dist/motion/Pressable.d.ts +1 -1
  33. package/dist/motion/Pressable.js +3 -3
  34. package/dist/motion/Pressable.mjs +2 -2
  35. package/dist/motion/ScrollView.d.mts +1 -1
  36. package/dist/motion/ScrollView.d.ts +1 -1
  37. package/dist/motion/ScrollView.js +3 -3
  38. package/dist/motion/ScrollView.mjs +2 -2
  39. package/dist/motion/Text.d.mts +1 -1
  40. package/dist/motion/Text.d.ts +1 -1
  41. package/dist/motion/Text.js +3 -3
  42. package/dist/motion/Text.mjs +2 -2
  43. package/dist/motion/View.d.mts +1 -1
  44. package/dist/motion/View.d.ts +1 -1
  45. package/dist/motion/View.js +3 -3
  46. package/dist/motion/View.mjs +2 -2
  47. package/dist/touch/index.d.mts +1 -1
  48. package/dist/touch/index.d.ts +1 -1
  49. package/dist/{types-BQgLJeQG.d.mts → types-DyJpG64F.d.mts} +1 -1
  50. package/dist/{types-BQgLJeQG.d.ts → types-DyJpG64F.d.ts} +1 -1
  51. package/dist/{useGesture-DfaTx-3t.d.mts → useGesture-CnZQnYHH.d.mts} +1 -1
  52. package/dist/{useGesture-B0_CzOUz.d.ts → useGesture-DbH46EBp.d.ts} +1 -1
  53. package/jest-setup.js +7 -1
  54. package/llms.txt +7 -3
  55. package/package.json +8 -1
  56. package/src/index.ts +1 -0
  57. package/src/motion/FlatList.tsx +77 -0
  58. package/src/motion/createMotionComponent.tsx +23 -0
  59. package/src/motion/index.ts +3 -0
  60. package/src/values/useScroll.ts +9 -5
  61. package/dist/chunk-FWWVHLXB.js +0 -8
  62. package/dist/chunk-K5SI6VXS.js +0 -8
  63. package/dist/chunk-STARIT6W.js +0 -8
@@ -0,0 +1,53 @@
1
+ import { FlatListProps, FlatList } from 'react-native';
2
+ import { V as VariantsMap, a as MotionProps } from '../types-DyJpG64F.js';
3
+ import 'react';
4
+
5
+ /**
6
+ * Animatable, virtualized `FlatList`.
7
+ *
8
+ * Built on Reanimated's `Animated.FlatList` rather than RN's `FlatList`. That
9
+ * wrapper supplies two things this primitive would otherwise have to
10
+ * re-implement: the `CellRendererComponent` injection that powers per-row
11
+ * `itemLayoutAnimation`, and a `scrollEventThrottle` default of 1.
12
+ *
13
+ * A note on that throttle default, because the reasoning is easy to get wrong
14
+ * from Reanimated's own source comment: it says RN defaults FlatList's
15
+ * `scrollEventThrottle` to 50, which **is stale**. On RN 0.81
16
+ * (`@react-native/virtualized-lists`, `VirtualizedList.js`) the default is
17
+ * `props.scrollEventThrottle ?? 0.0001` — effectively every frame. So the
18
+ * patch is belt-and-braces on current RN rather than the load-bearing reason
19
+ * to use the wrapper. It is still worth inheriting: it costs nothing, and it
20
+ * pins the behaviour if RN's default changes again. **Do not restate the "50"
21
+ * figure as fact** — verify against the installed RN before relying on it.
22
+ *
23
+ * This is the primitive that lets one list both virtualize and animate. The
24
+ * `useScroll()` handler works because `Motion.*` components are Reanimated
25
+ * animated components — the same mechanism `Motion.ScrollView` relies on, and
26
+ * nothing about it was ever specific to `ScrollView`:
27
+ *
28
+ * ```tsx
29
+ * const { scrollY, onScroll } = useScroll()
30
+ *
31
+ * <Motion.FlatList
32
+ * data={items}
33
+ * renderItem={renderItem}
34
+ * onScroll={onScroll}
35
+ * initial={{ opacity: 0 }}
36
+ * animate={{ opacity: 1 }}
37
+ * />
38
+ * ```
39
+ *
40
+ * Two scoping notes:
41
+ *
42
+ * - `animate` / `initial` / `gesture` apply to the **scroll container**, not to
43
+ * rows. Animate rows by using a `Motion.*` primitive inside `renderItem`.
44
+ * - The `layout` prop animates the list frame. Per-row layout animation is
45
+ * Reanimated's `itemLayoutAnimation`, which is forwarded through untouched.
46
+ * Note that row-level layout animation can fight the list's own measurement
47
+ * passes — measure before adopting it.
48
+ */
49
+ declare const MotionFlatList: <ItemT = any, V extends VariantsMap<FlatListProps<ItemT>> = VariantsMap<FlatListProps<ItemT>>>(props: FlatListProps<ItemT> & MotionProps<FlatListProps<ItemT>, V> & {
50
+ ref?: React.Ref<FlatList<ItemT>>;
51
+ }) => React.ReactElement;
52
+
53
+ export { MotionFlatList };
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ var chunkQJYFTTM2_js = require('../chunk-QJYFTTM2.js');
4
+ require('../chunk-6V7MOBXO.js');
5
+ require('../chunk-OBRGJAST.js');
6
+ require('../chunk-PM6CVGXJ.js');
7
+
8
+
9
+
10
+ Object.defineProperty(exports, "MotionFlatList", {
11
+ enumerable: true,
12
+ get: function () { return chunkQJYFTTM2_js.MotionFlatList; }
13
+ });
@@ -0,0 +1,4 @@
1
+ export { MotionFlatList } from '../chunk-ZOBOKLAS.mjs';
2
+ import '../chunk-HPJMIBBK.mjs';
3
+ import '../chunk-Z3HCJ43H.mjs';
4
+ import '../chunk-REYL77RE.mjs';
@@ -1,5 +1,5 @@
1
1
  import { Image } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.mjs';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.mjs';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { Image } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.js';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.js';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkFWWVHLXB_js = require('../chunk-FWWVHLXB.js');
4
- require('../chunk-767UKZXG.js');
3
+ var chunkYUTS6JRU_js = require('../chunk-YUTS6JRU.js');
4
+ require('../chunk-6V7MOBXO.js');
5
5
  require('../chunk-OBRGJAST.js');
6
6
  require('../chunk-PM6CVGXJ.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PM6CVGXJ.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionImage", {
11
11
  enumerable: true,
12
- get: function () { return chunkFWWVHLXB_js.MotionImage; }
12
+ get: function () { return chunkYUTS6JRU_js.MotionImage; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionImage } from '../chunk-PFPO7DX2.mjs';
2
- import '../chunk-2ICQLWH2.mjs';
1
+ export { MotionImage } from '../chunk-KBFN4TRO.mjs';
2
+ import '../chunk-HPJMIBBK.mjs';
3
3
  import '../chunk-Z3HCJ43H.mjs';
4
4
  import '../chunk-REYL77RE.mjs';
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import * as react_native from 'react-native';
3
- import { M as MotionComponent } from '../types-BQgLJeQG.mjs';
3
+ import { M as MotionComponent } from '../types-DyJpG64F.mjs';
4
4
 
5
5
  /**
6
6
  * Animatable `Pressable`. The `gesture` prop's `pressed` sub-state hooks into
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import * as react_native from 'react-native';
3
- import { M as MotionComponent } from '../types-BQgLJeQG.js';
3
+ import { M as MotionComponent } from '../types-DyJpG64F.js';
4
4
 
5
5
  /**
6
6
  * Animatable `Pressable`. The `gesture` prop's `pressed` sub-state hooks into
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk5MGWHOSV_js = require('../chunk-5MGWHOSV.js');
4
- require('../chunk-767UKZXG.js');
3
+ var chunkWGCF3WQG_js = require('../chunk-WGCF3WQG.js');
4
+ require('../chunk-6V7MOBXO.js');
5
5
  require('../chunk-OBRGJAST.js');
6
6
  require('../chunk-PM6CVGXJ.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PM6CVGXJ.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionPressable", {
11
11
  enumerable: true,
12
- get: function () { return chunk5MGWHOSV_js.MotionPressable; }
12
+ get: function () { return chunkWGCF3WQG_js.MotionPressable; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionPressable } from '../chunk-C3EDC5ZW.mjs';
2
- import '../chunk-2ICQLWH2.mjs';
1
+ export { MotionPressable } from '../chunk-52QSN2VQ.mjs';
2
+ import '../chunk-HPJMIBBK.mjs';
3
3
  import '../chunk-Z3HCJ43H.mjs';
4
4
  import '../chunk-REYL77RE.mjs';
@@ -1,5 +1,5 @@
1
1
  import { ScrollView } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.mjs';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.mjs';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { ScrollView } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.js';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.js';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkX7B5WR5A_js = require('../chunk-X7B5WR5A.js');
4
- require('../chunk-767UKZXG.js');
3
+ var chunkQYR66E2G_js = require('../chunk-QYR66E2G.js');
4
+ require('../chunk-6V7MOBXO.js');
5
5
  require('../chunk-OBRGJAST.js');
6
6
  require('../chunk-PM6CVGXJ.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PM6CVGXJ.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionScrollView", {
11
11
  enumerable: true,
12
- get: function () { return chunkX7B5WR5A_js.MotionScrollView; }
12
+ get: function () { return chunkQYR66E2G_js.MotionScrollView; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionScrollView } from '../chunk-BAAQI37F.mjs';
2
- import '../chunk-2ICQLWH2.mjs';
1
+ export { MotionScrollView } from '../chunk-VSK2E35J.mjs';
2
+ import '../chunk-HPJMIBBK.mjs';
3
3
  import '../chunk-Z3HCJ43H.mjs';
4
4
  import '../chunk-REYL77RE.mjs';
@@ -1,5 +1,5 @@
1
1
  import { Text } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.mjs';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.mjs';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { Text } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.js';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.js';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkSTARIT6W_js = require('../chunk-STARIT6W.js');
4
- require('../chunk-767UKZXG.js');
3
+ var chunkZSOCRHU3_js = require('../chunk-ZSOCRHU3.js');
4
+ require('../chunk-6V7MOBXO.js');
5
5
  require('../chunk-OBRGJAST.js');
6
6
  require('../chunk-PM6CVGXJ.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PM6CVGXJ.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionText", {
11
11
  enumerable: true,
12
- get: function () { return chunkSTARIT6W_js.MotionText; }
12
+ get: function () { return chunkZSOCRHU3_js.MotionText; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionText } from '../chunk-F7LJX56B.mjs';
2
- import '../chunk-2ICQLWH2.mjs';
1
+ export { MotionText } from '../chunk-WMLS4TMX.mjs';
2
+ import '../chunk-HPJMIBBK.mjs';
3
3
  import '../chunk-Z3HCJ43H.mjs';
4
4
  import '../chunk-REYL77RE.mjs';
@@ -1,5 +1,5 @@
1
1
  import { View } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.mjs';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.mjs';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { View } from 'react-native';
2
- import { M as MotionComponent } from '../types-BQgLJeQG.js';
2
+ import { M as MotionComponent } from '../types-DyJpG64F.js';
3
3
  import 'react';
4
4
 
5
5
  /**
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkK5SI6VXS_js = require('../chunk-K5SI6VXS.js');
4
- require('../chunk-767UKZXG.js');
3
+ var chunkNPJ46457_js = require('../chunk-NPJ46457.js');
4
+ require('../chunk-6V7MOBXO.js');
5
5
  require('../chunk-OBRGJAST.js');
6
6
  require('../chunk-PM6CVGXJ.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PM6CVGXJ.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionView", {
11
11
  enumerable: true,
12
- get: function () { return chunkK5SI6VXS_js.MotionView; }
12
+ get: function () { return chunkNPJ46457_js.MotionView; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionView } from '../chunk-CMHVF6F4.mjs';
2
- import '../chunk-2ICQLWH2.mjs';
1
+ export { MotionView } from '../chunk-RUIOM2YZ.mjs';
2
+ import '../chunk-HPJMIBBK.mjs';
3
3
  import '../chunk-Z3HCJ43H.mjs';
4
4
  import '../chunk-REYL77RE.mjs';
@@ -1,6 +1,6 @@
1
1
  import { PanResponderInstance } from 'react-native';
2
2
  import { useAnimatedStyle, SharedValue } from 'react-native-reanimated';
3
- import { T as TransitionConfig } from '../types-BQgLJeQG.mjs';
3
+ import { T as TransitionConfig } from '../types-DyJpG64F.mjs';
4
4
  import 'react';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  import { PanResponderInstance } from 'react-native';
2
2
  import { useAnimatedStyle, SharedValue } from 'react-native-reanimated';
3
- import { T as TransitionConfig } from '../types-BQgLJeQG.js';
3
+ import { T as TransitionConfig } from '../types-DyJpG64F.js';
4
4
  import 'react';
5
5
 
6
6
  /**
@@ -456,4 +456,4 @@ interface MotionComponent<C extends ComponentType<any>> {
456
456
  displayName?: string;
457
457
  }
458
458
 
459
- export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantController as V, TransitionInput as a, TransitionName as b, AnimateStyle as c, AnimationCallbackInfo as d, EasingFunction as e, EasingFunctionFactory as f, GestureSubStates as g, MotionProps as h, NoAnimationTransition as i, RepeatConfig as j, SequenceStep as k, TimingTransition as l, Transition as m, VariantsMap as n };
459
+ export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantsMap as V, MotionProps as a, TransitionInput as b, TransitionName as c, VariantController as d, AnimateStyle as e, AnimationCallbackInfo as f, EasingFunction as g, EasingFunctionFactory as h, GestureSubStates as i, NoAnimationTransition as j, RepeatConfig as k, SequenceStep as l, TimingTransition as m, Transition as n };
@@ -456,4 +456,4 @@ interface MotionComponent<C extends ComponentType<any>> {
456
456
  displayName?: string;
457
457
  }
458
458
 
459
- export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantController as V, TransitionInput as a, TransitionName as b, AnimateStyle as c, AnimationCallbackInfo as d, EasingFunction as e, EasingFunctionFactory as f, GestureSubStates as g, MotionProps as h, NoAnimationTransition as i, RepeatConfig as j, SequenceStep as k, TimingTransition as l, Transition as m, VariantsMap as n };
459
+ export type { AnimatableValue as A, BoxShadowInput as B, DecayTransition as D, EasingInput as E, GestureLayerTransitions as G, MotionComponent as M, NamedTransitions as N, PerPropertyTransition as P, RegisteredTransitions as R, SpringTransition as S, TransitionConfig as T, VariantsMap as V, MotionProps as a, TransitionInput as b, TransitionName as c, VariantController as d, AnimateStyle as e, AnimationCallbackInfo as f, EasingFunction as g, EasingFunctionFactory as h, GestureSubStates as i, NoAnimationTransition as j, RepeatConfig as k, SequenceStep as l, TimingTransition as m, Transition as n };
@@ -1,5 +1,5 @@
1
1
  import { SharedValue } from 'react-native-reanimated';
2
- import { a as TransitionInput, G as GestureLayerTransitions } from './types-BQgLJeQG.mjs';
2
+ import { b as TransitionInput, G as GestureLayerTransitions } from './types-DyJpG64F.mjs';
3
3
 
4
4
  /**
5
5
  * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
@@ -1,5 +1,5 @@
1
1
  import { SharedValue } from 'react-native-reanimated';
2
- import { a as TransitionInput, G as GestureLayerTransitions } from './types-BQgLJeQG.js';
2
+ import { b as TransitionInput, G as GestureLayerTransitions } from './types-DyJpG64F.js';
3
3
 
4
4
  /**
5
5
  * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
package/jest-setup.js CHANGED
@@ -45,7 +45,7 @@ jest.mock('react-native/Libraries/Text/Text', () => {
45
45
  // run; targets snap in one step.
46
46
  jest.mock('react-native-reanimated', () => {
47
47
  const React = require('react')
48
- const { Image, ScrollView, Text, View } = require('react-native')
48
+ const { FlatList, Image, ScrollView, Text, View } = require('react-native')
49
49
 
50
50
  const wrap = (Component, displayName) => {
51
51
  const Wrapped = React.forwardRef((props, ref) =>
@@ -59,6 +59,10 @@ jest.mock('react-native-reanimated', () => {
59
59
  const AnimatedText = wrap(Text, 'Animated.Text')
60
60
  const AnimatedImage = wrap(Image, 'Animated.Image')
61
61
  const AnimatedScrollView = wrap(ScrollView, 'Animated.ScrollView')
62
+ // Reanimated's real `Animated.FlatList` also defaults `scrollEventThrottle`
63
+ // to 1 and injects a `CellRendererComponent`; neither is observable in this
64
+ // mock, so the wrapper is a plain pass-through like the others.
65
+ const AnimatedFlatList = wrap(FlatList, 'Animated.FlatList')
62
66
 
63
67
  return {
64
68
  __esModule: true,
@@ -67,6 +71,7 @@ jest.mock('react-native-reanimated', () => {
67
71
  Text: AnimatedText,
68
72
  Image: AnimatedImage,
69
73
  ScrollView: AnimatedScrollView,
74
+ FlatList: AnimatedFlatList,
70
75
  createAnimatedComponent: (c) =>
71
76
  wrap(c, `Animated(${c.displayName ?? c.name ?? 'Component'})`),
72
77
  },
@@ -74,6 +79,7 @@ jest.mock('react-native-reanimated', () => {
74
79
  Text: AnimatedText,
75
80
  Image: AnimatedImage,
76
81
  ScrollView: AnimatedScrollView,
82
+ FlatList: AnimatedFlatList,
77
83
  useSharedValue: (initial) => {
78
84
  const ref = React.useRef(null)
79
85
  if (ref.current === null) ref.current = { value: initial }
package/llms.txt CHANGED
@@ -34,17 +34,21 @@ import {
34
34
  import { useGestureLayer } from '@rootnative/inertia/gesture-layer'
35
35
  // Render-layer Reanimated interop for custom animated components:
36
36
  import { Animated, useAnimatedStyle } from '@rootnative/inertia/reanimated'
37
- // or for tree-shaking the primitives:
37
+ // or for tree-shaking the primitives. NOTE: these subpaths export a
38
+ // differently NAMED symbol — `MotionScrollView`, not `Motion.ScrollView`.
39
+ // `Motion` itself is only exported from the package root above, and there
40
+ // is no '@rootnative/inertia/motion' subpath.
38
41
  import { MotionView } from '@rootnative/inertia/view'
39
42
  import { MotionText } from '@rootnative/inertia/text'
40
43
  import { MotionImage } from '@rootnative/inertia/image'
41
44
  import { MotionPressable } from '@rootnative/inertia/pressable'
42
45
  import { MotionScrollView } from '@rootnative/inertia/scroll-view'
46
+ import { MotionFlatList } from '@rootnative/inertia/flat-list'
43
47
  ```
44
48
 
45
49
  ## Public API
46
50
 
47
- - `Motion.View` / `Motion.Text` / `Motion.Image` / `Motion.Pressable` / `Motion.ScrollView` — animatable primitives. Per-primitive style inference (no shared `ViewStyle & TextStyle & ImageStyle` fallback).
51
+ - `Motion.View` / `Motion.Text` / `Motion.Image` / `Motion.Pressable` / `Motion.ScrollView` / `Motion.FlatList` — animatable primitives. Per-primitive style inference (no shared `ViewStyle & TextStyle & ImageStyle` fallback). `Motion.FlatList` is the **virtualized** animated scroller: it takes `useScroll`'s `onScroll` handler and keeps `data` / `renderItem` item-type inference, so a long list can virtualize and animate at once. Animation props apply to the scroll container; animate rows with a `Motion.*` inside `renderItem`.
48
52
  - `<Presence>` — mount / unmount transitions; children need explicit `key`s. Exiting children get `pointerEvents: 'none'` automatically.
49
53
  - `<MotionConfig reducedMotion="user" | "never" | "always" transitions={{ name: TransitionConfig }}>` — gates motion against the OS reduce-motion setting (default `"user"`) and registers named transitions for the subtree. A registered name is accepted anywhere a `TransitionConfig` is: the `transition` prop (top-level and per-property/per-layer), the `layout` prop, and the value-layer hooks (`transition="selection"`, `useBooleanSpring(checked, 'selection')`). Nested providers merge (child overrides per name); unknown names warn in dev and fall back to the default spring. Names are consumer vocabulary — no presets ship with the library. Optional compile-time narrowing via `declare module '@rootnative/inertia' { interface RegisteredTransitions { ... } }`. Custom components join the registry with `useNamedTransitions()` + `resolveNamedTransition(input, registry)`.
50
54
  - `useGesture(transition?)` — hook-form of the `gesture` prop. Returns 0↔1 progress shared values (`pressed`, `focused`, `focusVisible`, `hovered`) plus a `handlers` bag to spread on a `Pressable`. Use when one gesture needs to drive multiple animated siblings (focus rings, MD3 state-layer halos, multi-element compositions).
@@ -60,7 +64,7 @@ import { MotionScrollView } from '@rootnative/inertia/scroll-view'
60
64
  - `useColorTransition(progress, [from, to], options?)` — pure value-layer interpolator for a single color channel, driven by a `SharedValue<number>` (0→1). Returns an animated style fragment with one color key (default `backgroundColor`; configurable via `options.key` to `color` / `borderColor` / `tintColor` / `shadowColor` / per-side border colors). For raw `SharedValue<string>` output, use `useTransform(progress, [0, 1], [from, to])` instead.
61
65
  - `useColorCascade(rest, layers, options?)` — pure value-layer interpolator compositing a **priority-ordered** stack of color layers over a base `rest` color; each `layers` entry is `{ progress: SharedValue<number>, color: string }`, later entries win as their progress rises (equivalent to the nested `focus(error(hover(rest)))` `interpolateColor` chain). `options.key` reuses `ColorStyleKey` (default `backgroundColor`). Returns a spreadable animated style fragment; memoized on a colors+key signature. Color-only by design — cascade a numeric key separately via `useInterpolatedStyle` + `useTransform` max. `useColorTransition` stays the single-layer fast path.
62
66
  - `useInterpolatedStyle(progress, map, options?)` — pure value-layer interpolator mapping one `SharedValue<number>` onto **N** style props at once, returned as a spreadable animated style fragment (the multi-key, style-fragment counterpart to `useTransform`'s output-range form). Numeric keys (`opacity` / `height` / `fontSize` / …) route through `interpolate`; transform keys (`translateX` / `scale` / `rotate` / …) lift into a `transform` array in map key-order (`rotate*` emit `'<n>deg'`); color keys (`backgroundColor` / `borderColor` / …) route through `interpolateColor` (a multi-stop `useColorTransition`). Stop types are compile-checked. `options.inputRange` (default `[0,1]` / evenly-spaced) and `options.extrapolate` (default `'clamp'`) apply to every key. Memoized on an order-preserving signature. For function-valued or multi-source composition, drop to `useTransform`'s worklet form or a hand-rolled `useAnimatedStyle`.
63
- - `useScroll()` — returns `{ scrollX, scrollY, onScroll }` for use with `Motion.ScrollView`. Scroll events fire on the UI thread.
67
+ - `useScroll()` — returns `{ scrollX, scrollY, onScroll }` for use with `Motion.ScrollView` or `Motion.FlatList`. Scroll events fire on the UI thread. Set `scrollEventThrottle={16}` on a `Motion.ScrollView`; `Motion.FlatList` defaults it to 1.
64
68
  - `createMotionComponent<C>(C)` — wrap any component with the same Motion prop surface, inferring style from `C`.
65
69
  - `buildReleaseAnimation(transition, toValue)` — worklet-safe single-step animation builder (spring / timing / decay / no-animation). For assigning Inertia-resolved animations to shared values from inside a gesture worklet. Used internally by `@rootnative/inertia-gestures`'s `useDrag({ onRelease })`.
66
70
  - `resolveTransition(config, toValue, callback?)` — JS-thread resolver: bakes a `TransitionConfig` + target into a Reanimated animation (`withSpring` / `withTiming` / `withDecay`, plus `delay` / `repeat` wrapping) ready to assign to a shared value. The building block for custom animated components that accept Inertia's `transition` shape; this is what the gradient and SVG adapter packages use.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootnative/inertia",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Declarative animation primitives for React Native, built on react-native-reanimated.",
5
5
  "license": "MIT",
6
6
  "author": "RootNative",
@@ -72,6 +72,13 @@
72
72
  "import": "./dist/motion/ScrollView.mjs",
73
73
  "require": "./dist/motion/ScrollView.js"
74
74
  },
75
+ "./flat-list": {
76
+ "types": "./dist/motion/FlatList.d.ts",
77
+ "react-native": "./src/motion/FlatList.tsx",
78
+ "source": "./src/motion/FlatList.tsx",
79
+ "import": "./dist/motion/FlatList.mjs",
80
+ "require": "./dist/motion/FlatList.js"
81
+ },
75
82
  "./testing": {
76
83
  "types": "./dist/testing/index.d.ts",
77
84
  "react-native": "./src/testing/index.ts",
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export {
16
16
  MotionImage,
17
17
  MotionPressable,
18
18
  MotionScrollView,
19
+ MotionFlatList,
19
20
  createMotionComponent,
20
21
  } from './motion'
21
22
  export {
@@ -0,0 +1,77 @@
1
+ import type { FlatList as RNFlatList, FlatListProps } from 'react-native'
2
+ import Animated from 'react-native-reanimated'
3
+ import type { MotionProps, VariantsMap } from '../types'
4
+ import { createMotionComponent } from './createMotionComponent'
5
+
6
+ /**
7
+ * Animatable, virtualized `FlatList`.
8
+ *
9
+ * Built on Reanimated's `Animated.FlatList` rather than RN's `FlatList`. That
10
+ * wrapper supplies two things this primitive would otherwise have to
11
+ * re-implement: the `CellRendererComponent` injection that powers per-row
12
+ * `itemLayoutAnimation`, and a `scrollEventThrottle` default of 1.
13
+ *
14
+ * A note on that throttle default, because the reasoning is easy to get wrong
15
+ * from Reanimated's own source comment: it says RN defaults FlatList's
16
+ * `scrollEventThrottle` to 50, which **is stale**. On RN 0.81
17
+ * (`@react-native/virtualized-lists`, `VirtualizedList.js`) the default is
18
+ * `props.scrollEventThrottle ?? 0.0001` — effectively every frame. So the
19
+ * patch is belt-and-braces on current RN rather than the load-bearing reason
20
+ * to use the wrapper. It is still worth inheriting: it costs nothing, and it
21
+ * pins the behaviour if RN's default changes again. **Do not restate the "50"
22
+ * figure as fact** — verify against the installed RN before relying on it.
23
+ *
24
+ * This is the primitive that lets one list both virtualize and animate. The
25
+ * `useScroll()` handler works because `Motion.*` components are Reanimated
26
+ * animated components — the same mechanism `Motion.ScrollView` relies on, and
27
+ * nothing about it was ever specific to `ScrollView`:
28
+ *
29
+ * ```tsx
30
+ * const { scrollY, onScroll } = useScroll()
31
+ *
32
+ * <Motion.FlatList
33
+ * data={items}
34
+ * renderItem={renderItem}
35
+ * onScroll={onScroll}
36
+ * initial={{ opacity: 0 }}
37
+ * animate={{ opacity: 1 }}
38
+ * />
39
+ * ```
40
+ *
41
+ * Two scoping notes:
42
+ *
43
+ * - `animate` / `initial` / `gesture` apply to the **scroll container**, not to
44
+ * rows. Animate rows by using a `Motion.*` primitive inside `renderItem`.
45
+ * - The `layout` prop animates the list frame. Per-row layout animation is
46
+ * Reanimated's `itemLayoutAnimation`, which is forwarded through untouched.
47
+ * Note that row-level layout animation can fight the list's own measurement
48
+ * passes — measure before adopting it.
49
+ */
50
+ export const MotionFlatList = createMotionComponent(
51
+ Animated.FlatList as never,
52
+ // `createMotionComponent<C>` returns a non-generic `MotionComponent<C>`, so
53
+ // `data` / `renderItem` would collapse to `any` and lose `ItemT` inference.
54
+ // Restore it with the same call-signature cast Reanimated itself uses for
55
+ // this exact problem (see its `ReanimatedFlatList` export, and the
56
+ // `@ts-expect-error` above `AnimatedFlatList` explaining that
57
+ // `createAnimatedComponent` cannot create generic components).
58
+ //
59
+ // **Both** generics live on the one call signature, and that is deliberate:
60
+ // `ItemT` infers from `data` while `V` infers from `variants`, independently.
61
+ // Declaring only `ItemT` (the obvious first cut) silently drops the
62
+ // variant-key narrowing that `MotionComponent` provides on every other
63
+ // primitive — `animate="typo"` would stop being a compile error here and
64
+ // nowhere else. Both directions are pinned in
65
+ // `__type-tests__/flat-list.test-d.tsx`.
66
+ ) as unknown as <
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ ItemT = any,
69
+ V extends VariantsMap<FlatListProps<ItemT>> = VariantsMap<
70
+ FlatListProps<ItemT>
71
+ >,
72
+ >(
73
+ props: FlatListProps<ItemT> &
74
+ MotionProps<FlatListProps<ItemT>, V> & {
75
+ ref?: React.Ref<RNFlatList<ItemT>>
76
+ },
77
+ ) => React.ReactElement
@@ -2025,6 +2025,26 @@ function useGestureHandlers(
2025
2025
  // forward to those when present so wrapping consumers stay consistent.
2026
2026
  handlers.onPressIn = compose(rest.onPressIn, () => setPressed(true))
2027
2027
  handlers.onPressOut = compose(rest.onPressOut, () => setPressed(false))
2028
+ // Web pointer events. `onTouchStart` reaches the DOM as a real
2029
+ // `touchstart` listener under react-native-web, which a mouse never
2030
+ // fires — so without these a plain `Motion.View` (anything that isn't a
2031
+ // Pressable, i.e. has no `onPressIn` path) was inert under a desktop
2032
+ // click while `Motion.Pressable` worked. Pointer events cover mouse, pen
2033
+ // and touch, so `pressed` means "any pointer" on every platform.
2034
+ //
2035
+ // A web touch fires `touchstart` *and* `pointerdown`; both set the same
2036
+ // boolean to the same value, so the overlap is idempotent, not a
2037
+ // double-toggle. React Native has no pointer props, so these are inert
2038
+ // on native and cost nothing there.
2039
+ handlers.onPointerDown = compose(rest.onPointerDown, () =>
2040
+ setPressed(true),
2041
+ )
2042
+ handlers.onPointerUp = compose(rest.onPointerUp, () => setPressed(false))
2043
+ // Fires when the browser takes over the gesture (scroll, drag start) —
2044
+ // without it the pressed layer would stick on after the pointer is gone.
2045
+ handlers.onPointerCancel = compose(rest.onPointerCancel, () =>
2046
+ setPressed(false),
2047
+ )
2028
2048
  }
2029
2049
  // Mount onFocus/onBlur if either focus sub-state is declared. The two flags
2030
2050
  // are independent: `focused` always tracks focus; `focusVisible` only
@@ -2061,6 +2081,9 @@ function useGestureHandlers(
2061
2081
  rest.onTouchCancel,
2062
2082
  rest.onPressIn,
2063
2083
  rest.onPressOut,
2084
+ rest.onPointerDown,
2085
+ rest.onPointerUp,
2086
+ rest.onPointerCancel,
2064
2087
  rest.onFocus,
2065
2088
  rest.onBlur,
2066
2089
  rest.onMouseEnter,
@@ -1,3 +1,4 @@
1
+ import { MotionFlatList } from './FlatList'
1
2
  import { MotionImage } from './Image'
2
3
  import { MotionPressable } from './Pressable'
3
4
  import { MotionScrollView } from './ScrollView'
@@ -11,6 +12,7 @@ export {
11
12
  MotionImage,
12
13
  MotionPressable,
13
14
  MotionScrollView,
15
+ MotionFlatList,
14
16
  }
15
17
 
16
18
  /**
@@ -23,4 +25,5 @@ export const Motion = {
23
25
  Image: MotionImage,
24
26
  Pressable: MotionPressable,
25
27
  ScrollView: MotionScrollView,
28
+ FlatList: MotionFlatList,
26
29
  } as const
@@ -11,10 +11,10 @@ export interface UseScrollResult {
11
11
  /** Vertical scroll offset in points. */
12
12
  scrollY: SharedValue<number>
13
13
  /**
14
- * Handler to pass to a `Motion.ScrollView`'s `onScroll` prop (or any other
15
- * Reanimated `Animated.ScrollView`). The handler is opaque to JS it runs
16
- * as a worklet — but the type narrows to the same shape RN's native
17
- * `onScroll` prop expects so it composes cleanly.
14
+ * Handler to pass to the `onScroll` prop of `Motion.ScrollView` or
15
+ * `Motion.FlatList` (or any other Reanimated animated scroller). The handler
16
+ * is opaque to JS — it runs as a worklet — but the type narrows to the same
17
+ * shape RN's native `onScroll` prop expects so it composes cleanly.
18
18
  */
19
19
  onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
20
20
  }
@@ -47,9 +47,13 @@ export interface UseScrollResult {
47
47
  * read from any worklet (`useAnimatedStyle`, `useDerivedValue`,
48
48
  * `useTransform`) without a JS-thread bounce.
49
49
  *
50
- * Remember to set `scrollEventThrottle={16}` on the `ScrollView` for 60Hz
50
+ * Remember to set `scrollEventThrottle={16}` on a `Motion.ScrollView` for 60Hz
51
51
  * updates — RN's default is to dispatch on every event, which on iOS still
52
52
  * means one per frame, but Android benefits from the explicit cap.
53
+ *
54
+ * `Motion.FlatList` needs no such setting — it defaults `scrollEventThrottle`
55
+ * to 1 for you. Prefer it over `Motion.ScrollView` for long or unbounded lists:
56
+ * it virtualizes, and both accept this handler.
53
57
  */
54
58
  export function useScroll(): UseScrollResult {
55
59
  const scrollX = useSharedValue(0)
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk767UKZXG_js = require('./chunk-767UKZXG.js');
4
- var reactNative = require('react-native');
5
-
6
- var MotionImage = chunk767UKZXG_js.createMotionComponent(reactNative.Image);
7
-
8
- exports.MotionImage = MotionImage;
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk767UKZXG_js = require('./chunk-767UKZXG.js');
4
- var reactNative = require('react-native');
5
-
6
- var MotionView = chunk767UKZXG_js.createMotionComponent(reactNative.View);
7
-
8
- exports.MotionView = MotionView;