react-native-header-motion 0.2.0 → 0.4.0

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 (35) hide show
  1. package/README.md +58 -0
  2. package/lib/module/components/FlatList.js +22 -4
  3. package/lib/module/components/FlatList.js.map +1 -1
  4. package/lib/module/components/ScrollManager.js +20 -2
  5. package/lib/module/components/ScrollManager.js.map +1 -1
  6. package/lib/module/components/ScrollView.js +18 -2
  7. package/lib/module/components/ScrollView.js.map +1 -1
  8. package/lib/module/hooks/refreshControl.js +31 -0
  9. package/lib/module/hooks/refreshControl.js.map +1 -0
  10. package/lib/module/hooks/useConsumerScrollHandlers.js +86 -0
  11. package/lib/module/hooks/useConsumerScrollHandlers.js.map +1 -0
  12. package/lib/module/hooks/useScrollManager.js +37 -4
  13. package/lib/module/hooks/useScrollManager.js.map +1 -1
  14. package/lib/typescript/src/components/FlatList.d.ts +2 -4
  15. package/lib/typescript/src/components/FlatList.d.ts.map +1 -1
  16. package/lib/typescript/src/components/ScrollManager.d.ts +9 -2
  17. package/lib/typescript/src/components/ScrollManager.d.ts.map +1 -1
  18. package/lib/typescript/src/components/ScrollView.d.ts +1 -1
  19. package/lib/typescript/src/components/ScrollView.d.ts.map +1 -1
  20. package/lib/typescript/src/hooks/refreshControl.d.ts +13 -0
  21. package/lib/typescript/src/hooks/refreshControl.d.ts.map +1 -0
  22. package/lib/typescript/src/hooks/useConsumerScrollHandlers.d.ts +64 -0
  23. package/lib/typescript/src/hooks/useConsumerScrollHandlers.d.ts.map +1 -0
  24. package/lib/typescript/src/hooks/useScrollManager.d.ts +8 -1
  25. package/lib/typescript/src/hooks/useScrollManager.d.ts.map +1 -1
  26. package/lib/typescript/src/types.d.ts +6 -1
  27. package/lib/typescript/src/types.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/components/FlatList.tsx +31 -9
  30. package/src/components/ScrollManager.tsx +28 -1
  31. package/src/components/ScrollView.tsx +25 -3
  32. package/src/hooks/refreshControl.ts +55 -0
  33. package/src/hooks/useConsumerScrollHandlers.ts +148 -0
  34. package/src/hooks/useScrollManager.ts +52 -4
  35. package/src/types.ts +11 -1
package/README.md CHANGED
@@ -407,6 +407,15 @@ Supports `scrollId?: string` for multi-scroll scenarios.
407
407
 
408
408
  Render-prop API for custom scrollables (pager pages, 3rd party lists, etc.).
409
409
 
410
+ If you use `HeaderMotion.ScrollManager` directly for custom integrations, pass refresh-related props to `ScrollManager` (instead of your inner scrollable):
411
+
412
+ - `refreshControl`
413
+ - `refreshing`
414
+ - `onRefresh`
415
+ - optional `progressViewOffset` if you want to force your offset.
416
+
417
+ This is required, as the positioning of scrollables is affecting Refresh Control and has to be coupled with the header heights.
418
+
410
419
  ```tsx
411
420
  <HeaderMotion.ScrollManager scrollId="A">
412
421
  {(
@@ -424,6 +433,31 @@ Render-prop API for custom scrollables (pager pages, 3rd party lists, etc.).
424
433
  </HeaderMotion.ScrollManager>
425
434
  ```
426
435
 
436
+ Refresh example with explicit props on `ScrollManager`:
437
+
438
+ ```tsx
439
+ <HeaderMotion.ScrollManager
440
+ scrollId="A"
441
+ refreshing={refreshing}
442
+ onRefresh={onRefresh}
443
+ >
444
+ {(
445
+ { onScroll, refreshControl: managedRefreshControl, ...scrollableProps },
446
+ { originalHeaderHeight, minHeightContentContainerStyle }
447
+ ) => (
448
+ <Animated.ScrollView
449
+ {...scrollableProps}
450
+ onScroll={onScroll}
451
+ refreshControl={managedRefreshControl}
452
+ contentContainerStyle={[
453
+ minHeightContentContainerStyle,
454
+ { paddingTop: originalHeaderHeight },
455
+ ]}
456
+ />
457
+ )}
458
+ </HeaderMotion.ScrollManager>
459
+ ```
460
+
427
461
  ### Hooks
428
462
 
429
463
  #### `useMotionProgress()`
@@ -469,6 +503,30 @@ Reanimated-powered, absolutely positioned header base.
469
503
  - `WithCollapsibleHeaderProps` – convenience type for headers using motion progress props.
470
504
  - `WithCollapsiblePagedHeaderProps` – like above, plus `activeTab` and `onTabChange`.
471
505
 
506
+ ## Additional notes
507
+
508
+ ### Refresh Control (v.0.3.0+)
509
+
510
+ Refresh control support was improved in `v0.3.0+`.
511
+
512
+ - If you use `HeaderMotion.ScrollView` or `HeaderMotion.FlatList`, your refresh-control usage stays the same as in React Native.
513
+ - If you use `HeaderMotion.ScrollManager` directly for custom integrations, pass refresh-related props to `ScrollManager`:
514
+ - `refreshControl`
515
+ - `refreshing`
516
+ - `onRefresh`
517
+ - optional `progressViewOffset`
518
+
519
+ This is important because scrollable positioning affects refresh-control behavior and needs to stay coupled with measured header height.
520
+
521
+ #### Platform support note:
522
+
523
+ - Support for Refresh Control is currently partial.
524
+ - Android works well with the current implementation.
525
+ - iOS behavior is still not fully deterministic.
526
+ - `progressViewOffset` does not seem to be reliable on iOS in all scenarios.
527
+ - Other iOS approaches tried so far introduced different issues.
528
+ - Additional iOS support improvements are planned for future releases.
529
+
472
530
  ## Contributing
473
531
 
474
532
  - Development workflow: see [CONTRIBUTING.md](CONTRIBUTING.md)
@@ -25,13 +25,28 @@ export function HeaderMotionFlatList({
25
25
  scrollId,
26
26
  animatedRef,
27
27
  contentContainerStyle,
28
+ onScroll,
29
+ onScrollBeginDrag,
30
+ onScrollEndDrag,
31
+ onMomentumScrollBegin,
32
+ onMomentumScrollEnd,
28
33
  ...props
29
34
  }) {
30
35
  return /*#__PURE__*/_jsx(HeaderMotionScrollManager, {
31
36
  scrollId: scrollId,
32
37
  animatedRef: animatedRef,
38
+ refreshControl: props.refreshControl,
39
+ refreshing: props.refreshing,
40
+ onRefresh: props.onRefresh,
41
+ progressViewOffset: props.progressViewOffset,
42
+ onScroll: onScroll,
43
+ onScrollBeginDrag: onScrollBeginDrag,
44
+ onScrollEndDrag: onScrollEndDrag,
45
+ onMomentumScrollBegin: onMomentumScrollBegin,
46
+ onMomentumScrollEnd: onMomentumScrollEnd,
33
47
  children: ({
34
- onScroll,
48
+ onScroll: managedOnScroll,
49
+ refreshControl: managedRefreshControl,
35
50
  ...scrollViewProps
36
51
  }, {
37
52
  originalHeaderHeight,
@@ -39,9 +54,12 @@ export function HeaderMotionFlatList({
39
54
  }) => /*#__PURE__*/_jsx(Animated.FlatList, {
40
55
  ...scrollViewProps,
41
56
  ...props,
42
- onScroll: onScroll,
43
- renderScrollComponent: propsz => /*#__PURE__*/_jsx(AnimatedScrollContainer, {
44
- ...propsz,
57
+ onScroll: managedOnScroll,
58
+ ...(managedRefreshControl && {
59
+ refreshControl: managedRefreshControl
60
+ }),
61
+ renderScrollComponent: scrollComponentProps => /*#__PURE__*/_jsx(AnimatedScrollContainer, {
62
+ ...scrollComponentProps,
45
63
  contentContainerStyle: [minHeightContentContainerStyle, {
46
64
  paddingTop: originalHeaderHeight
47
65
  }, contentContainerStyle]
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionFlatList","scrollId","animatedRef","contentContainerStyle","props","children","onScroll","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","FlatList","renderScrollComponent","propsz","AnimatedScrollContainer","paddingTop","rest","ref","ScrollView","View","style"],"sourceRoot":"../../../src","sources":["components/FlatList.tsx"],"mappings":";;AAAA,SAASA,UAAU,QAAgD,OAAO;AAC1E,OAAOC,QAAQ,MAA4B,yBAAyB;AACpE,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAqB5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAAU;EAC5CC,QAAQ;EACRC,WAAW;EACXC,qBAAqB;EACrB,GAAGC;AACyB,CAAC,EAAE;EAC/B,oBACEL,IAAA,CAACF,yBAAyB;IAACI,QAAQ,EAAEA,QAAS;IAACC,WAAW,EAAEA,WAAY;IAAAG,QAAA,EACrEA,CACC;MAAEC,QAAQ;MAAE,GAAGC;IAAgB,CAAC,EAChC;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDV,IAAA,CAACH,QAAQ,CAACc,QAAQ;MAAA,GACZH,eAAe;MAAA,GACfH,KAAK;MACTE,QAAQ,EAAEA,QAAS;MACnBK,qBAAqB,EAAGC,MAAM,iBAC5Bb,IAAA,CAACc,uBAAuB;QAAA,GAClBD,MAAM;QACVT,qBAAqB,EAAE,CACrBM,8BAA8B,EAC9B;UAAEK,UAAU,EAAEN;QAAqB,CAAC,EACpCL,qBAAqB;MACrB,CACH;IACD,CACH;EACF,CACwB,CAAC;AAEhC;AAEA,MAAMU,uBAAuB,gBAAGlB,UAAU,CAGxC,CAAC;EAAEU,QAAQ;EAAEF,qBAAqB;EAAE,GAAGY;AAAK,CAAC,EAAEC,GAAG,KAAK;EACvD,oBACEjB,IAAA,CAACH,QAAQ,CAACqB,UAAU;IAAA,GAAKF,IAAI;IAAEC,GAAG,EAAEA,GAAI;IAAAX,QAAA,eACtCN,IAAA,CAACH,QAAQ,CAACsB,IAAI;MAACC,KAAK,EAAEhB,qBAAsB;MAAAE,QAAA,EAAEA;IAAQ,CAAgB;EAAC,CACpD,CAAC;AAE1B,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["forwardRef","Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionFlatList","scrollId","animatedRef","contentContainerStyle","onScroll","onScrollBeginDrag","onScrollEndDrag","onMomentumScrollBegin","onMomentumScrollEnd","props","refreshControl","refreshing","onRefresh","progressViewOffset","children","managedOnScroll","managedRefreshControl","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","FlatList","renderScrollComponent","scrollComponentProps","AnimatedScrollContainer","paddingTop","rest","ref","ScrollView","View","style"],"sourceRoot":"../../../src","sources":["components/FlatList.tsx"],"mappings":";;AAAA,SAASA,UAAU,QAAgD,OAAO;AAC1E,OAAOC,QAAQ,MAA4B,yBAAyB;AACpE,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAmB5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAAU;EAC5CC,QAAQ;EACRC,WAAW;EACXC,qBAAqB;EACrBC,QAAQ;EACRC,iBAAiB;EACjBC,eAAe;EACfC,qBAAqB;EACrBC,mBAAmB;EACnB,GAAGC;AACyB,CAAC,EAAE;EAC/B,oBACEV,IAAA,CAACF,yBAAyB;IACxBI,QAAQ,EAAEA,QAAS;IACnBC,WAAW,EAAEA,WAAY;IACzBQ,cAAc,EAAED,KAAK,CAACC,cAAe;IACrCC,UAAU,EAAEF,KAAK,CAACE,UAAW;IAC7BC,SAAS,EAAEH,KAAK,CAACG,SAAU;IAC3BC,kBAAkB,EAAEJ,KAAK,CAACI,kBAAmB;IAC7CT,QAAQ,EAAEA,QAAS;IACnBC,iBAAiB,EAAEA,iBAAkB;IACrCC,eAAe,EAAEA,eAAgB;IACjCC,qBAAqB,EAAEA,qBAAsB;IAC7CC,mBAAmB,EAAEA,mBAAoB;IAAAM,QAAA,EAExCA,CACC;MACEV,QAAQ,EAAEW,eAAe;MACzBL,cAAc,EAAEM,qBAAqB;MACrC,GAAGC;IACL,CAAC,EACD;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDpB,IAAA,CAACH,QAAQ,CAACwB,QAAQ;MAAA,GACZH,eAAe;MAAA,GACfR,KAAK;MACTL,QAAQ,EAAEW,eAAgB;MAAA,IACrBC,qBAAqB,IAAI;QAC5BN,cAAc,EAAEM;MAClB,CAAC;MACDK,qBAAqB,EAAGC,oBAAoB,iBAC1CvB,IAAA,CAACwB,uBAAuB;QAAA,GAClBD,oBAAoB;QACxBnB,qBAAqB,EAAE,CACrBgB,8BAA8B,EAC9B;UAAEK,UAAU,EAAEN;QAAqB,CAAC,EACpCf,qBAAqB;MACrB,CACH;IACD,CACH;EACF,CACwB,CAAC;AAEhC;AAEA,MAAMoB,uBAAuB,gBAAG5B,UAAU,CAGxC,CAAC;EAAEmB,QAAQ;EAAEX,qBAAqB;EAAE,GAAGsB;AAAK,CAAC,EAAEC,GAAG,KAAK;EACvD,oBACE3B,IAAA,CAACH,QAAQ,CAAC+B,UAAU;IAAA,GAAKF,IAAI;IAAEC,GAAG,EAAEA,GAAI;IAAAZ,QAAA,eACtCf,IAAA,CAACH,QAAQ,CAACgC,IAAI;MAACC,KAAK,EAAE1B,qBAAsB;MAAAW,QAAA,EAAEA;IAAQ,CAAgB;EAAC,CACpD,CAAC;AAE1B,CAAC,CAAC","ignoreList":[]}
@@ -26,7 +26,16 @@ import { useScrollManager } from "../hooks/index.js";
26
26
  export function HeaderMotionScrollManager({
27
27
  children,
28
28
  scrollId,
29
- animatedRef
29
+ animatedRef,
30
+ refreshControl,
31
+ refreshing,
32
+ onRefresh,
33
+ progressViewOffset,
34
+ onScroll,
35
+ onScrollBeginDrag,
36
+ onScrollEndDrag,
37
+ onMomentumScrollBegin,
38
+ onMomentumScrollEnd
30
39
  }) {
31
40
  if (typeof children !== 'function') {
32
41
  throw new Error('HeaderMotion.ScrollManager only accepts render function as the only child.');
@@ -35,7 +44,16 @@ export function HeaderMotionScrollManager({
35
44
  scrollableProps,
36
45
  headerMotionContext
37
46
  } = useScrollManager(scrollId, {
38
- animatedRef
47
+ animatedRef,
48
+ refreshControl,
49
+ refreshing,
50
+ onRefresh,
51
+ progressViewOffset,
52
+ onScroll,
53
+ onScrollBeginDrag,
54
+ onScrollEndDrag,
55
+ onMomentumScrollBegin,
56
+ onMomentumScrollEnd
39
57
  });
40
58
  return children(scrollableProps, headerMotionContext);
41
59
  }
@@ -1 +1 @@
1
- {"version":3,"names":["useScrollManager","HeaderMotionScrollManager","children","scrollId","animatedRef","Error","scrollableProps","headerMotionContext"],"sourceRoot":"../../../src","sources":["components/ScrollManager.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,mBAAU;AA4B3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,yBAAyBA,CAAC;EACxCC,QAAQ;EACRC,QAAQ;EACRC;AAC8B,CAAC,EAAE;EACjC,IAAI,OAAOF,QAAQ,KAAK,UAAU,EAAE;IAClC,MAAM,IAAIG,KAAK,CACb,4EACF,CAAC;EACH;EAEA,MAAM;IAAEC,eAAe;IAAEC;EAAoB,CAAC,GAAGP,gBAAgB,CAACG,QAAQ,EAAE;IAC1EC;EACF,CAAC,CAAC;EAEF,OAAOF,QAAQ,CAACI,eAAe,EAAEC,mBAAmB,CAAC;AACvD","ignoreList":[]}
1
+ {"version":3,"names":["useScrollManager","HeaderMotionScrollManager","children","scrollId","animatedRef","refreshControl","refreshing","onRefresh","progressViewOffset","onScroll","onScrollBeginDrag","onScrollEndDrag","onMomentumScrollBegin","onMomentumScrollEnd","Error","scrollableProps","headerMotionContext"],"sourceRoot":"../../../src","sources":["components/ScrollManager.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,mBAAU;AAqC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,yBAAyBA,CAAC;EACxCC,QAAQ;EACRC,QAAQ;EACRC,WAAW;EACXC,cAAc;EACdC,UAAU;EACVC,SAAS;EACTC,kBAAkB;EAClBC,QAAQ;EACRC,iBAAiB;EACjBC,eAAe;EACfC,qBAAqB;EACrBC;AAC8B,CAAC,EAAE;EACjC,IAAI,OAAOX,QAAQ,KAAK,UAAU,EAAE;IAClC,MAAM,IAAIY,KAAK,CACb,4EACF,CAAC;EACH;EAEA,MAAM;IAAEC,eAAe;IAAEC;EAAoB,CAAC,GAAGhB,gBAAgB,CAACG,QAAQ,EAAE;IAC1EC,WAAW;IACXC,cAAc;IACdC,UAAU;IACVC,SAAS;IACTC,kBAAkB;IAClBC,QAAQ;IACRC,iBAAiB;IACjBC,eAAe;IACfC,qBAAqB;IACrBC;EACF,CAAC,CAAC;EAEF,OAAOX,QAAQ,CAACa,eAAe,EAAEC,mBAAmB,CAAC;AACvD","ignoreList":[]}
@@ -22,13 +22,26 @@ export function HeaderMotionScrollView({
22
22
  animatedRef,
23
23
  children,
24
24
  contentContainerStyle,
25
+ refreshControl,
26
+ onScroll,
27
+ onScrollBeginDrag,
28
+ onScrollEndDrag,
29
+ onMomentumScrollBegin,
30
+ onMomentumScrollEnd,
25
31
  ...props
26
32
  }) {
27
33
  return /*#__PURE__*/_jsx(HeaderMotionScrollManager, {
28
34
  scrollId: scrollId,
29
35
  animatedRef: animatedRef,
36
+ refreshControl: refreshControl,
37
+ onScroll: onScroll,
38
+ onScrollBeginDrag: onScrollBeginDrag,
39
+ onScrollEndDrag: onScrollEndDrag,
40
+ onMomentumScrollBegin: onMomentumScrollBegin,
41
+ onMomentumScrollEnd: onMomentumScrollEnd,
30
42
  children: ({
31
- onScroll,
43
+ onScroll: managedOnScroll,
44
+ refreshControl: managedRefreshControl,
32
45
  ...scrollViewProps
33
46
  }, {
34
47
  originalHeaderHeight,
@@ -36,7 +49,10 @@ export function HeaderMotionScrollView({
36
49
  }) => /*#__PURE__*/_jsx(Animated.ScrollView, {
37
50
  ...scrollViewProps,
38
51
  ...props,
39
- onScroll: onScroll,
52
+ onScroll: managedOnScroll,
53
+ ...(managedRefreshControl && {
54
+ refreshControl: managedRefreshControl
55
+ }),
40
56
  children: /*#__PURE__*/_jsx(Animated.View, {
41
57
  style: [minHeightContentContainerStyle, {
42
58
  paddingTop: originalHeaderHeight
@@ -1 +1 @@
1
- {"version":3,"names":["Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionScrollView","scrollId","animatedRef","children","contentContainerStyle","props","onScroll","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","ScrollView","View","style","paddingTop"],"sourceRoot":"../../../src","sources":["components/ScrollView.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAGR,yBAAyB;AAChC,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAe5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CAAC;EACrCC,QAAQ;EACRC,WAAW;EACXC,QAAQ;EACRC,qBAAqB;EACrB,GAAGC;AACwB,CAAC,EAAE;EAC9B,oBACEN,IAAA,CAACF,yBAAyB;IAACI,QAAQ,EAAEA,QAAS;IAACC,WAAW,EAAEA,WAAY;IAAAC,QAAA,EACrEA,CACC;MAAEG,QAAQ;MAAE,GAAGC;IAAgB,CAAC,EAChC;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDV,IAAA,CAACH,QAAQ,CAACc,UAAU;MAAA,GACdH,eAAe;MAAA,GACfF,KAAK;MACTC,QAAQ,EAAEA,QAAS;MAAAH,QAAA,eAEnBJ,IAAA,CAACH,QAAQ,CAACe,IAAI;QACZC,KAAK,EAAE,CACLH,8BAA8B,EAC9B;UAAEI,UAAU,EAAEL;QAAqB,CAAC,EACpCJ,qBAAqB,CACrB;QAAAD,QAAA,EAEDA;MAAQ,CACI;IAAC,CACG;EACtB,CACwB,CAAC;AAEhC","ignoreList":[]}
1
+ {"version":3,"names":["Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionScrollView","scrollId","animatedRef","children","contentContainerStyle","refreshControl","onScroll","onScrollBeginDrag","onScrollEndDrag","onMomentumScrollBegin","onMomentumScrollEnd","props","managedOnScroll","managedRefreshControl","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","ScrollView","View","style","paddingTop"],"sourceRoot":"../../../src","sources":["components/ScrollView.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAGR,yBAAyB;AAChC,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAe5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CAAC;EACrCC,QAAQ;EACRC,WAAW;EACXC,QAAQ;EACRC,qBAAqB;EACrBC,cAAc;EACdC,QAAQ;EACRC,iBAAiB;EACjBC,eAAe;EACfC,qBAAqB;EACrBC,mBAAmB;EACnB,GAAGC;AACwB,CAAC,EAAE;EAC9B,oBACEZ,IAAA,CAACF,yBAAyB;IACxBI,QAAQ,EAAEA,QAAS;IACnBC,WAAW,EAAEA,WAAY;IACzBG,cAAc,EAAEA,cAAe;IAC/BC,QAAQ,EAAEA,QAAS;IACnBC,iBAAiB,EAAEA,iBAAkB;IACrCC,eAAe,EAAEA,eAAgB;IACjCC,qBAAqB,EAAEA,qBAAsB;IAC7CC,mBAAmB,EAAEA,mBAAoB;IAAAP,QAAA,EAExCA,CACC;MACEG,QAAQ,EAAEM,eAAe;MACzBP,cAAc,EAAEQ,qBAAqB;MACrC,GAAGC;IACL,CAAC,EACD;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDjB,IAAA,CAACH,QAAQ,CAACqB,UAAU;MAAA,GACdH,eAAe;MAAA,GACfH,KAAK;MACTL,QAAQ,EAAEM,eAAgB;MAAA,IACrBC,qBAAqB,IAAI;QAC5BR,cAAc,EAAEQ;MAClB,CAAC;MAAAV,QAAA,eAEDJ,IAAA,CAACH,QAAQ,CAACsB,IAAI;QACZC,KAAK,EAAE,CACLH,8BAA8B,EAC9B;UAAEI,UAAU,EAAEL;QAAqB,CAAC,EACpCX,qBAAqB,CACrB;QAAAD,QAAA,EAEDA;MAAQ,CACI;IAAC,CACG;EACtB,CACwB,CAAC;AAEhC","ignoreList":[]}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ import { cloneElement, createElement, isValidElement } from 'react';
4
+ import { RefreshControl } from 'react-native';
5
+ function injectProgressViewOffset(refreshControl, progressViewOffset) {
6
+ if (refreshControl.props.progressViewOffset !== undefined) {
7
+ return refreshControl;
8
+ }
9
+ return /*#__PURE__*/cloneElement(refreshControl, {
10
+ progressViewOffset: progressViewOffset
11
+ });
12
+ }
13
+ export function resolveRefreshControl({
14
+ refreshControl,
15
+ refreshing,
16
+ onRefresh,
17
+ progressViewOffset
18
+ }) {
19
+ if (refreshControl) {
20
+ return /*#__PURE__*/isValidElement(refreshControl) ? injectProgressViewOffset(refreshControl, progressViewOffset) : undefined;
21
+ }
22
+ if (!onRefresh) {
23
+ return undefined;
24
+ }
25
+ return /*#__PURE__*/createElement(RefreshControl, {
26
+ refreshing: refreshing ?? false,
27
+ onRefresh: onRefresh,
28
+ progressViewOffset: progressViewOffset
29
+ });
30
+ }
31
+ //# sourceMappingURL=refreshControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["cloneElement","createElement","isValidElement","RefreshControl","injectProgressViewOffset","refreshControl","progressViewOffset","props","undefined","resolveRefreshControl","refreshing","onRefresh"],"sourceRoot":"../../../src","sources":["hooks/refreshControl.ts"],"mappings":";;AAAA,SACEA,YAAY,EACZC,aAAa,EACbC,cAAc,QAET,OAAO;AACd,SAASC,cAAc,QAAkC,cAAc;AAYvE,SAASC,wBAAwBA,CAC/BC,cAAiD,EACjDC,kBAAuC,EACvC;EACA,IAAID,cAAc,CAACE,KAAK,CAACD,kBAAkB,KAAKE,SAAS,EAAE;IACzD,OAAOH,cAAc;EACvB;EAEA,oBAAOL,YAAY,CAACK,cAAc,EAAE;IAClCC,kBAAkB,EAAEA;EACtB,CAAC,CAAC;AACJ;AAEA,OAAO,SAASG,qBAAqBA,CAAC;EACpCJ,cAAc;EACdK,UAAU;EACVC,SAAS;EACTL;AAC4B,CAAC,EAEjB;EACZ,IAAID,cAAc,EAAE;IAClB,OAAO,aAAAH,cAAc,CAAsBG,cAAc,CAAC,GACtDD,wBAAwB,CAACC,cAAc,EAAEC,kBAAkB,CAAC,GAC5DE,SAAS;EACf;EAEA,IAAI,CAACG,SAAS,EAAE;IACd,OAAOH,SAAS;EAClB;EAEA,oBAAOP,aAAa,CAACE,cAAc,EAAE;IACnCO,UAAU,EAAGA,UAAU,IAAgB,KAAK;IAC5CC,SAAS,EAAEA,SAAuB;IAClCL,kBAAkB,EAAEA;EACtB,CAAC,CAAC;AACJ","ignoreList":[]}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+
3
+ import { useCallback } from 'react';
4
+ import { useComposedEventHandler } from 'react-native-reanimated';
5
+ import { scheduleOnRN } from 'react-native-worklets';
6
+ export function useConsumerScrollHandlers({
7
+ onScroll,
8
+ onScrollBeginDrag,
9
+ onScrollEndDrag,
10
+ onMomentumScrollBegin,
11
+ onMomentumScrollEnd
12
+ }) {
13
+ const consumerOnScroll = typeof onScroll === 'function' ? onScroll : undefined;
14
+ const consumerOnScrollBeginDrag = typeof onScrollBeginDrag === 'function' ? onScrollBeginDrag : undefined;
15
+ const consumerOnScrollEndDrag = typeof onScrollEndDrag === 'function' ? onScrollEndDrag : undefined;
16
+ const consumerOnMomentumScrollBegin = typeof onMomentumScrollBegin === 'function' ? onMomentumScrollBegin : undefined;
17
+ const consumerOnMomentumScrollEnd = typeof onMomentumScrollEnd === 'function' ? onMomentumScrollEnd : undefined;
18
+ const onScrollBridge = useCallback(event => {
19
+ 'worklet';
20
+
21
+ if (!consumerOnScroll) {
22
+ return;
23
+ }
24
+ scheduleOnRN(consumerOnScroll, {
25
+ nativeEvent: event
26
+ });
27
+ }, [consumerOnScroll]);
28
+ const onBeginDragBridge = useCallback(event => {
29
+ 'worklet';
30
+
31
+ if (!consumerOnScrollBeginDrag) {
32
+ return;
33
+ }
34
+ scheduleOnRN(consumerOnScrollBeginDrag, {
35
+ nativeEvent: event
36
+ });
37
+ }, [consumerOnScrollBeginDrag]);
38
+ const onEndDragBridge = useCallback(event => {
39
+ 'worklet';
40
+
41
+ if (!consumerOnScrollEndDrag) {
42
+ return;
43
+ }
44
+ scheduleOnRN(consumerOnScrollEndDrag, {
45
+ nativeEvent: event
46
+ });
47
+ }, [consumerOnScrollEndDrag]);
48
+ const onMomentumBeginBridge = useCallback(event => {
49
+ 'worklet';
50
+
51
+ if (!consumerOnMomentumScrollBegin) {
52
+ return;
53
+ }
54
+ scheduleOnRN(consumerOnMomentumScrollBegin, {
55
+ nativeEvent: event
56
+ });
57
+ }, [consumerOnMomentumScrollBegin]);
58
+ const onMomentumEndBridge = useCallback(event => {
59
+ 'worklet';
60
+
61
+ if (!consumerOnMomentumScrollEnd) {
62
+ return;
63
+ }
64
+ scheduleOnRN(consumerOnMomentumScrollEnd, {
65
+ nativeEvent: event
66
+ });
67
+ }, [consumerOnMomentumScrollEnd]);
68
+ return {
69
+ onScroll: onScrollBridge,
70
+ onBeginDrag: onBeginDragBridge,
71
+ onEndDrag: onEndDragBridge,
72
+ onMomentumBegin: onMomentumBeginBridge,
73
+ onMomentumEnd: onMomentumEndBridge
74
+ };
75
+ }
76
+ export function useScrollHandlerComposition(ownScrollHandler, consumerScrollHandler) {
77
+ // TODO: I guess the typing here could be more precise
78
+ const consumerWorkletHandler = isAnimatedScrollHandler(consumerScrollHandler) ? consumerScrollHandler : null;
79
+ return useComposedEventHandler([ownScrollHandler, consumerWorkletHandler]);
80
+ }
81
+ function isAnimatedScrollHandler(handler) {
82
+ // FUTURE: we could be checking just by typeof handler === 'object'?
83
+ // This seems safer for now, unless Reanimated changes this shape. Revisit
84
+ return !!handler && 'workletEventHandler' in handler;
85
+ }
86
+ //# sourceMappingURL=useConsumerScrollHandlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useCallback","useComposedEventHandler","scheduleOnRN","useConsumerScrollHandlers","onScroll","onScrollBeginDrag","onScrollEndDrag","onMomentumScrollBegin","onMomentumScrollEnd","consumerOnScroll","undefined","consumerOnScrollBeginDrag","consumerOnScrollEndDrag","consumerOnMomentumScrollBegin","consumerOnMomentumScrollEnd","onScrollBridge","event","nativeEvent","onBeginDragBridge","onEndDragBridge","onMomentumBeginBridge","onMomentumEndBridge","onBeginDrag","onEndDrag","onMomentumBegin","onMomentumEnd","useScrollHandlerComposition","ownScrollHandler","consumerScrollHandler","consumerWorkletHandler","isAnimatedScrollHandler","handler"],"sourceRoot":"../../../src","sources":["hooks/useConsumerScrollHandlers.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,OAAO;AACnC,SACEC,uBAAuB,QAIlB,yBAAyB;AAChC,SAASC,YAAY,QAAQ,uBAAuB;AAwBpD,OAAO,SAASC,yBAAyBA,CAAC;EACxCC,QAAQ;EACRC,iBAAiB;EACjBC,eAAe;EACfC,qBAAqB;EACrBC;AAC2B,CAAC,EAAyB;EACrD,MAAMC,gBAAgB,GACpB,OAAOL,QAAQ,KAAK,UAAU,GACzBA,QAAQ,GACTM,SAAS;EACf,MAAMC,yBAAyB,GAC7B,OAAON,iBAAiB,KAAK,UAAU,GAClCA,iBAAiB,GAClBK,SAAS;EACf,MAAME,uBAAuB,GAC3B,OAAON,eAAe,KAAK,UAAU,GAChCA,eAAe,GAChBI,SAAS;EACf,MAAMG,6BAA6B,GACjC,OAAON,qBAAqB,KAAK,UAAU,GACtCA,qBAAqB,GACtBG,SAAS;EACf,MAAMI,2BAA2B,GAC/B,OAAON,mBAAmB,KAAK,UAAU,GACpCA,mBAAmB,GACpBE,SAAS;EAEf,MAAMK,cAAc,GAAGf,WAAW,CAC/BgB,KAAkB,IAAK;IACtB,SAAS;;IACT,IAAI,CAACP,gBAAgB,EAAE;MACrB;IACF;IACAP,YAAY,CAACO,gBAAgB,EAAE;MAAEQ,WAAW,EAAED;IAAM,CAAY,CAAC;EACnE,CAAC,EACD,CAACP,gBAAgB,CACnB,CAAC;EAED,MAAMS,iBAAiB,GAAGlB,WAAW,CAClCgB,KAAkB,IAAK;IACtB,SAAS;;IACT,IAAI,CAACL,yBAAyB,EAAE;MAC9B;IACF;IACAT,YAAY,CAACS,yBAAyB,EAAE;MACtCM,WAAW,EAAED;IACf,CAAY,CAAC;EACf,CAAC,EACD,CAACL,yBAAyB,CAC5B,CAAC;EAED,MAAMQ,eAAe,GAAGnB,WAAW,CAChCgB,KAAkB,IAAK;IACtB,SAAS;;IACT,IAAI,CAACJ,uBAAuB,EAAE;MAC5B;IACF;IACAV,YAAY,CAACU,uBAAuB,EAAE;MAAEK,WAAW,EAAED;IAAM,CAAY,CAAC;EAC1E,CAAC,EACD,CAACJ,uBAAuB,CAC1B,CAAC;EAED,MAAMQ,qBAAqB,GAAGpB,WAAW,CACtCgB,KAAkB,IAAK;IACtB,SAAS;;IACT,IAAI,CAACH,6BAA6B,EAAE;MAClC;IACF;IACAX,YAAY,CAACW,6BAA6B,EAAE;MAC1CI,WAAW,EAAED;IACf,CAAY,CAAC;EACf,CAAC,EACD,CAACH,6BAA6B,CAChC,CAAC;EAED,MAAMQ,mBAAmB,GAAGrB,WAAW,CACpCgB,KAAkB,IAAK;IACtB,SAAS;;IACT,IAAI,CAACF,2BAA2B,EAAE;MAChC;IACF;IACAZ,YAAY,CAACY,2BAA2B,EAAE;MACxCG,WAAW,EAAED;IACf,CAAY,CAAC;EACf,CAAC,EACD,CAACF,2BAA2B,CAC9B,CAAC;EAED,OAAO;IACLV,QAAQ,EAAEW,cAAc;IACxBO,WAAW,EAAEJ,iBAAiB;IAC9BK,SAAS,EAAEJ,eAAe;IAC1BK,eAAe,EAAEJ,qBAAqB;IACtCK,aAAa,EAAEJ;EACjB,CAAC;AACH;AAEA,OAAO,SAASK,2BAA2BA,CACzCC,gBAA8D,EAC9DC,qBAA6D,EAC7D;EACA;EACA,MAAMC,sBAAsB,GAAGC,uBAAuB,CAACF,qBAAqB,CAAC,GACxEA,qBAAqB,GACtB,IAAI;EAER,OAAO3B,uBAAuB,CAAC,CAAC0B,gBAAgB,EAAEE,sBAAsB,CAAC,CAAC;AAC5E;AAEA,SAASC,uBAAuBA,CAC9BC,OAA+C,EACR;EACvC;EACA;EACA,OAAO,CAAC,CAACA,OAAO,IAAI,qBAAqB,IAAIA,OAAO;AACtD","ignoreList":[]}
@@ -5,6 +5,8 @@ import { measure, scrollTo, useAnimatedReaction, useAnimatedRef, useAnimatedScro
5
5
  import { RuntimeKind, scheduleOnUI } from 'react-native-worklets';
6
6
  import { HeaderMotionContext } from "../context.js";
7
7
  import { DEFAULT_SCROLL_ID, getInitialScrollValue } from "../utils/index.js";
8
+ import { resolveRefreshControl } from "./refreshControl.js";
9
+ import { useConsumerScrollHandlers, useScrollHandlerComposition } from "./useConsumerScrollHandlers.js";
8
10
 
9
11
  /**
10
12
  * Hook that manages scroll tracking and synchronization for header animations.
@@ -59,6 +61,23 @@ export function useScrollManager(scrollId, options) {
59
61
  const id = scrollId ?? DEFAULT_SCROLL_ID;
60
62
  const localRef = useAnimatedRef(); // TODO: better typing
61
63
  const animatedRef = options?.animatedRef ?? localRef;
64
+ const refreshControl = options?.refreshControl;
65
+ const refreshing = options?.refreshing;
66
+ const onRefresh = options?.onRefresh;
67
+ const progressViewOffset = options?.progressViewOffset ?? originalHeaderHeight;
68
+ const {
69
+ onScroll,
70
+ onBeginDrag,
71
+ onEndDrag,
72
+ onMomentumBegin,
73
+ onMomentumEnd
74
+ } = useConsumerScrollHandlers({
75
+ onScroll: options?.onScroll,
76
+ onScrollBeginDrag: options?.onScrollBeginDrag,
77
+ onScrollEndDrag: options?.onScrollEndDrag,
78
+ onMomentumScrollBegin: options?.onMomentumScrollBegin,
79
+ onMomentumScrollEnd: options?.onMomentumScrollEnd
80
+ });
62
81
  useEffect(() => {
63
82
  return () => {
64
83
  scheduleOnUI(scrollIdToDelete => {
@@ -105,6 +124,7 @@ export function useScrollManager(scrollId, options) {
105
124
  const scrollHandler = useCallback(e => {
106
125
  'worklet';
107
126
 
127
+ onScroll?.(e);
108
128
  scrollValues.modify(value => {
109
129
  if (!value[id]) {
110
130
  return value;
@@ -123,8 +143,14 @@ export function useScrollManager(scrollId, options) {
123
143
  }
124
144
  return value;
125
145
  });
126
- }, [scrollValues, id, activeScrollId, progressThreshold]);
127
- const onScroll = useAnimatedScrollHandler(scrollHandler);
146
+ }, [scrollValues, id, activeScrollId, progressThreshold, onScroll]);
147
+ const animatedScrollHandler = useAnimatedScrollHandler({
148
+ onScroll: scrollHandler,
149
+ onBeginDrag,
150
+ onEndDrag,
151
+ onMomentumBegin,
152
+ onMomentumEnd
153
+ });
128
154
  const minHeightContentContainerStyle = useAnimatedStyle(() => {
129
155
  if (globalThis.__RUNTIME_KIND === RuntimeKind.ReactNative) {
130
156
  return {};
@@ -137,10 +163,17 @@ export function useScrollManager(scrollId, options) {
137
163
  minHeight: measurement.height + progressThreshold
138
164
  };
139
165
  });
166
+ const resolvedRefreshControl = resolveRefreshControl({
167
+ refreshControl,
168
+ refreshing,
169
+ onRefresh,
170
+ progressViewOffset
171
+ });
140
172
  const scrollableProps = {
141
- onScroll,
173
+ onScroll: useScrollHandlerComposition(animatedScrollHandler, options?.onScroll),
142
174
  scrollEventThrottle: 16,
143
- ref: animatedRef
175
+ ref: animatedRef,
176
+ refreshControl: resolvedRefreshControl
144
177
  };
145
178
  const headerMotionContext = {
146
179
  originalHeaderHeight,
@@ -1 +1 @@
1
- {"version":3,"names":["useContext","useCallback","useEffect","measure","scrollTo","useAnimatedReaction","useAnimatedRef","useAnimatedScrollHandler","useAnimatedStyle","RuntimeKind","scheduleOnUI","HeaderMotionContext","DEFAULT_SCROLL_ID","getInitialScrollValue","useScrollManager","scrollId","options","ctxValue","Error","scrollValues","progress","activeScrollId","progressThreshold","originalHeaderHeight","id","localRef","animatedRef","scrollIdToDelete","modify","value","newProgress","oldProgress","currentActiveScrollId","get","newCur","scrollValue","progressDiff","current","newMin","min","scrollHandler","e","activeScrollIdValue","oldCurrent","oldMin","isCollapsed","newCurrent","contentOffset","y","Math","max","onScroll","minHeightContentContainerStyle","globalThis","__RUNTIME_KIND","ReactNative","measurement","minHeight","height","scrollableProps","scrollEventThrottle","ref","headerMotionContext"],"sourceRoot":"../../../src","sources":["hooks/useScrollManager.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useContext","useCallback","useEffect","measure","scrollTo","useAnimatedReaction","useAnimatedRef","useAnimatedScrollHandler","useAnimatedStyle","RuntimeKind","scheduleOnUI","HeaderMotionContext","DEFAULT_SCROLL_ID","getInitialScrollValue","resolveRefreshControl","useConsumerScrollHandlers","useScrollHandlerComposition","useScrollManager","scrollId","options","ctxValue","Error","scrollValues","progress","activeScrollId","progressThreshold","originalHeaderHeight","id","localRef","animatedRef","refreshControl","refreshing","onRefresh","progressViewOffset","onScroll","onBeginDrag","onEndDrag","onMomentumBegin","onMomentumEnd","onScrollBeginDrag","onScrollEndDrag","onMomentumScrollBegin","onMomentumScrollEnd","scrollIdToDelete","modify","value","newProgress","oldProgress","currentActiveScrollId","get","newCur","scrollValue","progressDiff","current","newMin","min","scrollHandler","e","activeScrollIdValue","oldCurrent","oldMin","isCollapsed","newCurrent","contentOffset","y","Math","max","animatedScrollHandler","minHeightContentContainerStyle","globalThis","__RUNTIME_KIND","ReactNative","measurement","minHeight","height","resolvedRefreshControl","scrollableProps","scrollEventThrottle","ref","headerMotionContext"],"sourceRoot":"../../../src","sources":["hooks/useScrollManager.ts"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,6 @@
1
1
  import { type ComponentProps } from 'react';
2
2
  import Animated, { type AnimatedRef } from 'react-native-reanimated';
3
- type AnimatedFlatListProps<T = any> = ComponentProps<typeof Animated.FlatList<T>>;
4
- export type HeaderMotionFlatListProps<T = any> = AnimatedFlatListProps<T> & {
3
+ export type HeaderMotionFlatListProps<T = any> = ComponentProps<typeof Animated.FlatList<T>> & {
5
4
  /**
6
5
  * Optional unique identifier for this scroll view.
7
6
  * Use this when you have multiple scroll views (e.g. in tabs) to track them separately.
@@ -30,6 +29,5 @@ export type HeaderMotionFlatListProps<T = any> = AnimatedFlatListProps<T> & {
30
29
  * </HeaderMotion>
31
30
  * ```
32
31
  */
33
- export declare function HeaderMotionFlatList<T = any>({ scrollId, animatedRef, contentContainerStyle, ...props }: HeaderMotionFlatListProps<T>): import("react/jsx-runtime").JSX.Element;
34
- export {};
32
+ export declare function HeaderMotionFlatList<T = any>({ scrollId, animatedRef, contentContainerStyle, onScroll, onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd, ...props }: HeaderMotionFlatListProps<T>): import("react/jsx-runtime").JSX.Element;
35
33
  //# sourceMappingURL=FlatList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FlatList.d.ts","sourceRoot":"","sources":["../../../../src/components/FlatList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAqB,MAAM,OAAO,CAAC;AAC3E,OAAO,QAAQ,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAKrE,KAAK,qBAAqB,CAAC,CAAC,GAAG,GAAG,IAAI,cAAc,CAClD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC5B,CAAC;AAEF,MAAM,MAAM,yBAAyB,CAAC,CAAC,GAAG,GAAG,IAAI,qBAAqB,CAAC,CAAC,CAAC,GAAG;IAC1E;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,GAAG,EAAE,EAC5C,QAAQ,EACR,WAAW,EACX,qBAAqB,EACrB,GAAG,KAAK,EACT,EAAE,yBAAyB,CAAC,CAAC,CAAC,2CAyB9B"}
1
+ {"version":3,"file":"FlatList.d.ts","sourceRoot":"","sources":["../../../../src/components/FlatList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAqB,MAAM,OAAO,CAAC;AAC3E,OAAO,QAAQ,EAAE,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAKrE,MAAM,MAAM,yBAAyB,CAAC,CAAC,GAAG,GAAG,IAAI,cAAc,CAC7D,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC5B,GAAG;IACF;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,GAAG,EAAE,EAC5C,QAAQ,EACR,WAAW,EACX,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,GAAG,KAAK,EACT,EAAE,yBAAyB,CAAC,CAAC,CAAC,2CA4C9B"}
@@ -1,8 +1,10 @@
1
1
  import type { ScrollManagerConfig } from '../types';
2
+ import type { ResolveRefreshControlOptions } from '../hooks/refreshControl';
2
3
  import type { ReactNode } from 'react';
3
4
  import type { AnimatedRef } from 'react-native-reanimated';
5
+ import type { ConsumerScrollEventHandlers } from '../hooks/useConsumerScrollHandlers';
4
6
  type ScrollManagerRenderChildren = (scrollableProps: ScrollManagerConfig['scrollableProps'], options: ScrollManagerConfig['headerMotionContext']) => ReactNode;
5
- export interface HeaderMotionScrollManagerProps {
7
+ export interface HeaderMotionScrollManagerProps extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'>, ConsumerScrollEventHandlers {
6
8
  /**
7
9
  * Optional unique identifier for this scroll view.
8
10
  * Use this when you have multiple scroll views (e.g., in tabs) to track them separately.
@@ -13,6 +15,11 @@ export interface HeaderMotionScrollManagerProps {
13
15
  * When provided, the scroll manager will use this ref instead of creating its own.
14
16
  */
15
17
  animatedRef?: AnimatedRef<any>;
18
+ /**
19
+ * Optional refresh progress offset override.
20
+ * When provided, it takes precedence over the automatic offset based on header height.
21
+ */
22
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
16
23
  /**
17
24
  * Render function that receives scroll props and header context.
18
25
  * Use this to create custom scroll implementations that integrate with HeaderMotion.
@@ -41,6 +48,6 @@ export interface HeaderMotionScrollManagerProps {
41
48
  * </HeaderMotion>
42
49
  * ```
43
50
  */
44
- export declare function HeaderMotionScrollManager({ children, scrollId, animatedRef, }: HeaderMotionScrollManagerProps): ReactNode;
51
+ export declare function HeaderMotionScrollManager({ children, scrollId, animatedRef, refreshControl, refreshing, onRefresh, progressViewOffset, onScroll, onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd, }: HeaderMotionScrollManagerProps): ReactNode;
45
52
  export {};
46
53
  //# sourceMappingURL=ScrollManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollManager.d.ts","sourceRoot":"","sources":["../../../../src/components/ScrollManager.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,KAAK,2BAA2B,GAAG,CACjC,eAAe,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,EACvD,OAAO,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,KAChD,SAAS,CAAC;AAEf,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B;;;OAGG;IACH,QAAQ,EAAE,2BAA2B,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,QAAQ,EACR,WAAW,GACZ,EAAE,8BAA8B,aAYhC"}
1
+ {"version":3,"file":"ScrollManager.d.ts","sourceRoot":"","sources":["../../../../src/components/ScrollManager.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AAEtF,KAAK,2BAA2B,GAAG,CACjC,eAAe,EAAE,mBAAmB,CAAC,iBAAiB,CAAC,EACvD,OAAO,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,KAChD,SAAS,CAAC;AAEf,MAAM,WAAW,8BACf,SAAQ,IAAI,CAAC,4BAA4B,EAAE,oBAAoB,CAAC,EAC9D,2BAA2B;IAC7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,4BAA4B,CAAC,oBAAoB,CAAC,CAAC;IACxE;;;OAGG;IACH,QAAQ,EAAE,2BAA2B,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,GACpB,EAAE,8BAA8B,aAqBhC"}
@@ -25,5 +25,5 @@ export type HeaderMotionScrollViewProps = AnimatedScrollViewProps & {
25
25
  * </HeaderMotion>
26
26
  * ```
27
27
  */
28
- export declare function HeaderMotionScrollView({ scrollId, animatedRef, children, contentContainerStyle, ...props }: HeaderMotionScrollViewProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function HeaderMotionScrollView({ scrollId, animatedRef, children, contentContainerStyle, refreshControl, onScroll, onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd, ...props }: HeaderMotionScrollViewProps): import("react/jsx-runtime").JSX.Element;
29
29
  //# sourceMappingURL=ScrollView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollView.d.ts","sourceRoot":"","sources":["../../../../src/components/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAiB,EACf,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC7B,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,2BAA2B,GAAG,uBAAuB,GAAG;IAClE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,qBAAqB,EACrB,GAAG,KAAK,EACT,EAAE,2BAA2B,2CAyB7B"}
1
+ {"version":3,"file":"ScrollView.d.ts","sourceRoot":"","sources":["../../../../src/components/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAiB,EACf,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC7B,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,2BAA2B,GAAG,uBAAuB,GAAG;IAClE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,qBAAqB,EACrB,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,GAAG,KAAK,EACT,EAAE,2BAA2B,2CAyC7B"}
@@ -0,0 +1,13 @@
1
+ import { type ReactElement } from 'react';
2
+ import { type RefreshControlProps } from 'react-native';
3
+ import type { SharedValue } from 'react-native-reanimated';
4
+ type MaybeShared<T> = T | SharedValue<T | undefined>;
5
+ export interface ResolveRefreshControlOptions {
6
+ refreshControl?: MaybeShared<ReactElement<RefreshControlProps>>;
7
+ refreshing?: MaybeShared<boolean>;
8
+ onRefresh?: MaybeShared<() => void>;
9
+ progressViewOffset: MaybeShared<number>;
10
+ }
11
+ export declare function resolveRefreshControl({ refreshControl, refreshing, onRefresh, progressViewOffset, }: ResolveRefreshControlOptions): ReactElement<RefreshControlProps> | undefined;
12
+ export {};
13
+ //# sourceMappingURL=refreshControl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refreshControl.d.ts","sourceRoot":"","sources":["../../../../src/hooks/refreshControl.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,OAAO,CAAC;AACf,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAErD,MAAM,WAAW,4BAA4B;IAC3C,cAAc,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAChE,UAAU,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,IAAI,CAAC,CAAC;IACpC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACzC;AAeD,wBAAgB,qBAAqB,CAAC,EACpC,cAAc,EACd,UAAU,EACV,SAAS,EACT,kBAAkB,GACnB,EAAE,4BAA4B,GAC3B,YAAY,CAAC,mBAAmB,CAAC,GACjC,SAAS,CAgBZ"}
@@ -0,0 +1,64 @@
1
+ import { type AnimatedScrollViewProps, type ScrollHandler, type ScrollHandlerProcessed } from 'react-native-reanimated';
2
+ import type { ScrollHandlerContext } from '../types';
3
+ type AnimatedScrollViewOnScroll = AnimatedScrollViewProps['onScroll'];
4
+ type ScrollEvent = Parameters<ScrollHandler<Record<string, unknown>>>[0];
5
+ export type ConsumerScrollEventHandlers = Pick<AnimatedScrollViewProps, 'onScroll' | 'onScrollBeginDrag' | 'onScrollEndDrag' | 'onMomentumScrollBegin' | 'onMomentumScrollEnd'>;
6
+ export interface ConsumerScrollBridges {
7
+ onScroll?: (event: ScrollEvent) => void;
8
+ onBeginDrag?: (event: ScrollEvent) => void;
9
+ onEndDrag?: (event: ScrollEvent) => void;
10
+ onMomentumBegin?: (event: ScrollEvent) => void;
11
+ onMomentumEnd?: (event: ScrollEvent) => void;
12
+ }
13
+ export declare function useConsumerScrollHandlers({ onScroll, onScrollBeginDrag, onScrollEndDrag, onMomentumScrollBegin, onMomentumScrollEnd, }: ConsumerScrollEventHandlers): ConsumerScrollBridges;
14
+ export declare function useScrollHandlerComposition(ownScrollHandler: ScrollHandlerProcessed<ScrollHandlerContext>, consumerScrollHandler: AnimatedScrollViewOnScroll | undefined): (event: Readonly<{
15
+ bubbles: boolean | undefined;
16
+ cancelable: boolean | undefined;
17
+ currentTarget: number | import("react-native").HostInstance;
18
+ defaultPrevented: boolean | undefined;
19
+ dispatchConfig: Readonly<{
20
+ registrationName: string;
21
+ }>;
22
+ eventPhase: number | undefined;
23
+ preventDefault: () => void;
24
+ isDefaultPrevented: () => boolean;
25
+ stopPropagation: () => void;
26
+ isPropagationStopped: () => boolean;
27
+ isTrusted: boolean | undefined;
28
+ nativeEvent: Readonly<{
29
+ contentInset: Readonly<{
30
+ bottom: number;
31
+ left: number;
32
+ right: number;
33
+ top: number;
34
+ }>;
35
+ contentOffset: Readonly<{
36
+ y: number;
37
+ x: number;
38
+ }>;
39
+ contentSize: Readonly<{
40
+ height: number;
41
+ width: number;
42
+ }>;
43
+ layoutMeasurement: Readonly<{
44
+ height: number;
45
+ width: number;
46
+ }>;
47
+ velocity?: Readonly<{
48
+ y: number;
49
+ x: number;
50
+ }>;
51
+ zoomScale?: number;
52
+ responderIgnoreScroll?: boolean;
53
+ targetContentOffset?: Readonly<{
54
+ y: number;
55
+ x: number;
56
+ }>;
57
+ }>;
58
+ persist: () => void;
59
+ target: (number | undefined) | import("react-native").HostInstance;
60
+ timeStamp: number;
61
+ type: string | undefined;
62
+ }>, context?: ScrollHandlerContext | undefined) => void;
63
+ export {};
64
+ //# sourceMappingURL=useConsumerScrollHandlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useConsumerScrollHandlers.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useConsumerScrollHandlers.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC5B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGrD,KAAK,0BAA0B,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;AACtE,KAAK,WAAW,GAAG,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzE,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,uBAAuB,EACrB,UAAU,GACV,mBAAmB,GACnB,iBAAiB,GACjB,uBAAuB,GACvB,qBAAqB,CACxB,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC/C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CAC9C;AAED,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,mBAAmB,GACpB,EAAE,2BAA2B,GAAG,qBAAqB,CA0FrD;AAED,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,sBAAsB,CAAC,oBAAoB,CAAC,EAC9D,qBAAqB,EAAE,0BAA0B,GAAG,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDAQ9D"}
@@ -1,5 +1,7 @@
1
1
  import { type AnimatedRef } from 'react-native-reanimated';
2
2
  import type { ScrollManagerConfig } from '../types';
3
+ import { type ResolveRefreshControlOptions } from './refreshControl';
4
+ import { type ConsumerScrollEventHandlers } from './useConsumerScrollHandlers';
3
5
  /**
4
6
  * Hook that manages scroll tracking and synchronization for header animations.
5
7
  * Returns props to apply to scrollable components and additional values that help with adjusting styling of the scrollables to header's dimensions.
@@ -37,12 +39,17 @@ import type { ScrollManagerConfig } from '../types';
37
39
  * }
38
40
  * ```
39
41
  */
40
- export interface UseScrollManagerOptions {
42
+ export interface UseScrollManagerOptions extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'>, ConsumerScrollEventHandlers {
41
43
  /**
42
44
  * Optional animated ref to use instead of creating one internally.
43
45
  * Useful when you need access to the scroll view ref from outside.
44
46
  */
45
47
  animatedRef?: AnimatedRef<any>;
48
+ /**
49
+ * Optional refresh progress offset override.
50
+ * When provided, it takes precedence over the automatic offset based on header height.
51
+ */
52
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
46
53
  }
47
54
  export declare function useScrollManager(scrollId?: string, options?: UseScrollManagerOptions): ScrollManagerConfig;
48
55
  //# sourceMappingURL=useScrollManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollManager.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useScrollManager.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,WAAW,EAEjB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,UAAU,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;CAChC;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,uBAAuB,GAChC,mBAAmB,CAyIrB"}
1
+ {"version":3,"file":"useScrollManager.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useScrollManager.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,WAAW,EAEjB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,UAAU,CAAC;AAElE,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAGL,KAAK,2BAA2B,EACjC,MAAM,6BAA6B,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,4BAA4B,EAAE,oBAAoB,CAAC,EAC9D,2BAA2B;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,4BAA4B,CAAC,oBAAoB,CAAC,CAAC;CACzE;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,uBAAuB,GAChC,mBAAmB,CAyKrB"}
@@ -1,4 +1,5 @@
1
- import type { LayoutChangeEvent, ScrollViewProps } from 'react-native';
1
+ import type { ReactElement } from 'react';
2
+ import type { LayoutChangeEvent, RefreshControlProps, ScrollViewProps } from 'react-native';
2
3
  import type { AnimatedRef, SharedValue } from 'react-native-reanimated';
3
4
  import { DEFAULT_SCROLL_ID } from './utils/defaults';
4
5
  export type Progress = SharedValue<number>;
@@ -36,8 +37,12 @@ export interface ScrollManagerHeaderMotionContext {
36
37
  }
37
38
  export interface ScrollManagerConfig {
38
39
  scrollableProps: Required<Pick<ScrollViewProps, 'onScroll' | 'scrollEventThrottle'>> & {
40
+ refreshControl?: ReactElement<RefreshControlProps>;
39
41
  ref: AnimatedRef<any>;
40
42
  };
41
43
  headerMotionContext: ScrollManagerHeaderMotionContext;
42
44
  }
45
+ export type ScrollHandlerContext = {
46
+ lastOffset: number | undefined;
47
+ };
43
48
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,CAAC,CAAC,mBAAmB,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;AAC9C,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,EAAE,iBAAiB,KAAK,MAAM,CAAC;AACrE,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEzE,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAC5D,KAAK,EAAE,CAAC,CAAC;IACT,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC;AACF,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG;KACtD,GAAG,IAAI,OAAO,iBAAiB,CAAC,CAAC,EAAE,WAAW;CAChD,CAAC;AAEF,MAAM,MAAM,0BAA0B,CACpC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACzD,CAAC,GAAG,cAAc,CAAC;AAEvB,MAAM,MAAM,+BAA+B,CACzC,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACzD,0BAA0B,CAAC,CAAC,CAAC,GAAG;IAClC,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,SAAS,EAAE,GAAG,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,2BAA2B,CAAC;IAChD,cAAc,EAAE,2BAA2B,CAAC;CAC7C;AAED,MAAM,WAAW,gCAAgC;IAC/C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8BAA8B,EAC1B,EAAE,GACF;QACE,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACP;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,QAAQ,CACvB,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,qBAAqB,CAAC,CAC1D,GAAG;QACF,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;KACvB,CAAC;IACF,mBAAmB,EAAE,gCAAgC,CAAC;CACvD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,CAAC,CAAC,mBAAmB,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;AAC9C,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,EAAE,iBAAiB,KAAK,MAAM,CAAC;AACrE,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEzE,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAC5D,KAAK,EAAE,CAAC,CAAC;IACT,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC;AACF,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AACD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG;KACtD,GAAG,IAAI,OAAO,iBAAiB,CAAC,CAAC,EAAE,WAAW;CAChD,CAAC;AAEF,MAAM,MAAM,0BAA0B,CACpC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACzD,CAAC,GAAG,cAAc,CAAC;AAEvB,MAAM,MAAM,+BAA+B,CACzC,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACzD,0BAA0B,CAAC,CAAC,CAAC,GAAG;IAClC,WAAW,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,SAAS,EAAE,GAAG,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,2BAA2B,CAAC;IAChD,cAAc,EAAE,2BAA2B,CAAC;CAC7C;AAED,MAAM,WAAW,gCAAgC;IAC/C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8BAA8B,EAC1B,EAAE,GACF;QACE,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACP;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,QAAQ,CACvB,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,qBAAqB,CAAC,CAC1D,GAAG;QACF,cAAc,CAAC,EAAE,YAAY,CAAC,mBAAmB,CAAC,CAAC;QACnD,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;KACvB,CAAC;IACF,mBAAmB,EAAE,gCAAgC,CAAC;CACvD;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-header-motion",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Smooth, animated collapsible headers with scroll-based motion control in React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -4,11 +4,9 @@ import { HeaderMotionScrollManager } from './ScrollManager';
4
4
 
5
5
  import type { ScrollViewProps } from 'react-native';
6
6
 
7
- type AnimatedFlatListProps<T = any> = ComponentProps<
7
+ export type HeaderMotionFlatListProps<T = any> = ComponentProps<
8
8
  typeof Animated.FlatList<T>
9
- >;
10
-
11
- export type HeaderMotionFlatListProps<T = any> = AnimatedFlatListProps<T> & {
9
+ > & {
12
10
  /**
13
11
  * Optional unique identifier for this scroll view.
14
12
  * Use this when you have multiple scroll views (e.g. in tabs) to track them separately.
@@ -42,21 +40,45 @@ export function HeaderMotionFlatList<T = any>({
42
40
  scrollId,
43
41
  animatedRef,
44
42
  contentContainerStyle,
43
+ onScroll,
44
+ onScrollBeginDrag,
45
+ onScrollEndDrag,
46
+ onMomentumScrollBegin,
47
+ onMomentumScrollEnd,
45
48
  ...props
46
49
  }: HeaderMotionFlatListProps<T>) {
47
50
  return (
48
- <HeaderMotionScrollManager scrollId={scrollId} animatedRef={animatedRef}>
51
+ <HeaderMotionScrollManager
52
+ scrollId={scrollId}
53
+ animatedRef={animatedRef}
54
+ refreshControl={props.refreshControl}
55
+ refreshing={props.refreshing}
56
+ onRefresh={props.onRefresh}
57
+ progressViewOffset={props.progressViewOffset}
58
+ onScroll={onScroll}
59
+ onScrollBeginDrag={onScrollBeginDrag}
60
+ onScrollEndDrag={onScrollEndDrag}
61
+ onMomentumScrollBegin={onMomentumScrollBegin}
62
+ onMomentumScrollEnd={onMomentumScrollEnd}
63
+ >
49
64
  {(
50
- { onScroll, ...scrollViewProps },
65
+ {
66
+ onScroll: managedOnScroll,
67
+ refreshControl: managedRefreshControl,
68
+ ...scrollViewProps
69
+ },
51
70
  { originalHeaderHeight, minHeightContentContainerStyle }
52
71
  ) => (
53
72
  <Animated.FlatList
54
73
  {...scrollViewProps}
55
74
  {...props}
56
- onScroll={onScroll}
57
- renderScrollComponent={(propsz) => (
75
+ onScroll={managedOnScroll}
76
+ {...(managedRefreshControl && {
77
+ refreshControl: managedRefreshControl,
78
+ })}
79
+ renderScrollComponent={(scrollComponentProps) => (
58
80
  <AnimatedScrollContainer
59
- {...propsz}
81
+ {...scrollComponentProps}
60
82
  contentContainerStyle={[
61
83
  minHeightContentContainerStyle,
62
84
  { paddingTop: originalHeaderHeight },
@@ -1,14 +1,18 @@
1
1
  import { useScrollManager } from '../hooks';
2
2
  import type { ScrollManagerConfig } from '../types';
3
+ import type { ResolveRefreshControlOptions } from '../hooks/refreshControl';
3
4
  import type { ReactNode } from 'react';
4
5
  import type { AnimatedRef } from 'react-native-reanimated';
6
+ import type { ConsumerScrollEventHandlers } from '../hooks/useConsumerScrollHandlers';
5
7
 
6
8
  type ScrollManagerRenderChildren = (
7
9
  scrollableProps: ScrollManagerConfig['scrollableProps'],
8
10
  options: ScrollManagerConfig['headerMotionContext']
9
11
  ) => ReactNode;
10
12
 
11
- export interface HeaderMotionScrollManagerProps {
13
+ export interface HeaderMotionScrollManagerProps
14
+ extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'>,
15
+ ConsumerScrollEventHandlers {
12
16
  /**
13
17
  * Optional unique identifier for this scroll view.
14
18
  * Use this when you have multiple scroll views (e.g., in tabs) to track them separately.
@@ -19,6 +23,11 @@ export interface HeaderMotionScrollManagerProps {
19
23
  * When provided, the scroll manager will use this ref instead of creating its own.
20
24
  */
21
25
  animatedRef?: AnimatedRef<any>;
26
+ /**
27
+ * Optional refresh progress offset override.
28
+ * When provided, it takes precedence over the automatic offset based on header height.
29
+ */
30
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
22
31
  /**
23
32
  * Render function that receives scroll props and header context.
24
33
  * Use this to create custom scroll implementations that integrate with HeaderMotion.
@@ -52,6 +61,15 @@ export function HeaderMotionScrollManager({
52
61
  children,
53
62
  scrollId,
54
63
  animatedRef,
64
+ refreshControl,
65
+ refreshing,
66
+ onRefresh,
67
+ progressViewOffset,
68
+ onScroll,
69
+ onScrollBeginDrag,
70
+ onScrollEndDrag,
71
+ onMomentumScrollBegin,
72
+ onMomentumScrollEnd,
55
73
  }: HeaderMotionScrollManagerProps) {
56
74
  if (typeof children !== 'function') {
57
75
  throw new Error(
@@ -61,6 +79,15 @@ export function HeaderMotionScrollManager({
61
79
 
62
80
  const { scrollableProps, headerMotionContext } = useScrollManager(scrollId, {
63
81
  animatedRef,
82
+ refreshControl,
83
+ refreshing,
84
+ onRefresh,
85
+ progressViewOffset,
86
+ onScroll,
87
+ onScrollBeginDrag,
88
+ onScrollEndDrag,
89
+ onMomentumScrollBegin,
90
+ onMomentumScrollEnd,
64
91
  });
65
92
 
66
93
  return children(scrollableProps, headerMotionContext);
@@ -36,18 +36,40 @@ export function HeaderMotionScrollView({
36
36
  animatedRef,
37
37
  children,
38
38
  contentContainerStyle,
39
+ refreshControl,
40
+ onScroll,
41
+ onScrollBeginDrag,
42
+ onScrollEndDrag,
43
+ onMomentumScrollBegin,
44
+ onMomentumScrollEnd,
39
45
  ...props
40
46
  }: HeaderMotionScrollViewProps) {
41
47
  return (
42
- <HeaderMotionScrollManager scrollId={scrollId} animatedRef={animatedRef}>
48
+ <HeaderMotionScrollManager
49
+ scrollId={scrollId}
50
+ animatedRef={animatedRef}
51
+ refreshControl={refreshControl}
52
+ onScroll={onScroll}
53
+ onScrollBeginDrag={onScrollBeginDrag}
54
+ onScrollEndDrag={onScrollEndDrag}
55
+ onMomentumScrollBegin={onMomentumScrollBegin}
56
+ onMomentumScrollEnd={onMomentumScrollEnd}
57
+ >
43
58
  {(
44
- { onScroll, ...scrollViewProps },
59
+ {
60
+ onScroll: managedOnScroll,
61
+ refreshControl: managedRefreshControl,
62
+ ...scrollViewProps
63
+ },
45
64
  { originalHeaderHeight, minHeightContentContainerStyle }
46
65
  ) => (
47
66
  <Animated.ScrollView
48
67
  {...scrollViewProps}
49
68
  {...props}
50
- onScroll={onScroll}
69
+ onScroll={managedOnScroll}
70
+ {...(managedRefreshControl && {
71
+ refreshControl: managedRefreshControl,
72
+ })}
51
73
  >
52
74
  <Animated.View
53
75
  style={[
@@ -0,0 +1,55 @@
1
+ import {
2
+ cloneElement,
3
+ createElement,
4
+ isValidElement,
5
+ type ReactElement,
6
+ } from 'react';
7
+ import { RefreshControl, type RefreshControlProps } from 'react-native';
8
+ import type { SharedValue } from 'react-native-reanimated';
9
+
10
+ type MaybeShared<T> = T | SharedValue<T | undefined>;
11
+
12
+ export interface ResolveRefreshControlOptions {
13
+ refreshControl?: MaybeShared<ReactElement<RefreshControlProps>>;
14
+ refreshing?: MaybeShared<boolean>;
15
+ onRefresh?: MaybeShared<() => void>;
16
+ progressViewOffset: MaybeShared<number>;
17
+ }
18
+
19
+ function injectProgressViewOffset(
20
+ refreshControl: ReactElement<RefreshControlProps>,
21
+ progressViewOffset: MaybeShared<number>
22
+ ) {
23
+ if (refreshControl.props.progressViewOffset !== undefined) {
24
+ return refreshControl;
25
+ }
26
+
27
+ return cloneElement(refreshControl, {
28
+ progressViewOffset: progressViewOffset as number,
29
+ });
30
+ }
31
+
32
+ export function resolveRefreshControl({
33
+ refreshControl,
34
+ refreshing,
35
+ onRefresh,
36
+ progressViewOffset,
37
+ }: ResolveRefreshControlOptions):
38
+ | ReactElement<RefreshControlProps>
39
+ | undefined {
40
+ if (refreshControl) {
41
+ return isValidElement<RefreshControlProps>(refreshControl)
42
+ ? injectProgressViewOffset(refreshControl, progressViewOffset)
43
+ : undefined;
44
+ }
45
+
46
+ if (!onRefresh) {
47
+ return undefined;
48
+ }
49
+
50
+ return createElement(RefreshControl, {
51
+ refreshing: (refreshing as boolean) ?? false,
52
+ onRefresh: onRefresh as () => void,
53
+ progressViewOffset: progressViewOffset as number,
54
+ }) as unknown as ReactElement<RefreshControlProps>;
55
+ }
@@ -0,0 +1,148 @@
1
+ import { useCallback } from 'react';
2
+ import {
3
+ useComposedEventHandler,
4
+ type AnimatedScrollViewProps,
5
+ type ScrollHandler,
6
+ type ScrollHandlerProcessed,
7
+ } from 'react-native-reanimated';
8
+ import { scheduleOnRN } from 'react-native-worklets';
9
+ import type { ScrollHandlerContext } from '../types';
10
+
11
+ type ConsumerScrollHandler = (event: unknown) => void;
12
+ type AnimatedScrollViewOnScroll = AnimatedScrollViewProps['onScroll'];
13
+ type ScrollEvent = Parameters<ScrollHandler<Record<string, unknown>>>[0];
14
+
15
+ export type ConsumerScrollEventHandlers = Pick<
16
+ AnimatedScrollViewProps,
17
+ | 'onScroll'
18
+ | 'onScrollBeginDrag'
19
+ | 'onScrollEndDrag'
20
+ | 'onMomentumScrollBegin'
21
+ | 'onMomentumScrollEnd'
22
+ >;
23
+
24
+ export interface ConsumerScrollBridges {
25
+ onScroll?: (event: ScrollEvent) => void;
26
+ onBeginDrag?: (event: ScrollEvent) => void;
27
+ onEndDrag?: (event: ScrollEvent) => void;
28
+ onMomentumBegin?: (event: ScrollEvent) => void;
29
+ onMomentumEnd?: (event: ScrollEvent) => void;
30
+ }
31
+
32
+ export function useConsumerScrollHandlers({
33
+ onScroll,
34
+ onScrollBeginDrag,
35
+ onScrollEndDrag,
36
+ onMomentumScrollBegin,
37
+ onMomentumScrollEnd,
38
+ }: ConsumerScrollEventHandlers): ConsumerScrollBridges {
39
+ const consumerOnScroll =
40
+ typeof onScroll === 'function'
41
+ ? (onScroll as ConsumerScrollHandler)
42
+ : undefined;
43
+ const consumerOnScrollBeginDrag =
44
+ typeof onScrollBeginDrag === 'function'
45
+ ? (onScrollBeginDrag as ConsumerScrollHandler)
46
+ : undefined;
47
+ const consumerOnScrollEndDrag =
48
+ typeof onScrollEndDrag === 'function'
49
+ ? (onScrollEndDrag as ConsumerScrollHandler)
50
+ : undefined;
51
+ const consumerOnMomentumScrollBegin =
52
+ typeof onMomentumScrollBegin === 'function'
53
+ ? (onMomentumScrollBegin as ConsumerScrollHandler)
54
+ : undefined;
55
+ const consumerOnMomentumScrollEnd =
56
+ typeof onMomentumScrollEnd === 'function'
57
+ ? (onMomentumScrollEnd as ConsumerScrollHandler)
58
+ : undefined;
59
+
60
+ const onScrollBridge = useCallback(
61
+ (event: ScrollEvent) => {
62
+ 'worklet';
63
+ if (!consumerOnScroll) {
64
+ return;
65
+ }
66
+ scheduleOnRN(consumerOnScroll, { nativeEvent: event } as unknown);
67
+ },
68
+ [consumerOnScroll]
69
+ );
70
+
71
+ const onBeginDragBridge = useCallback(
72
+ (event: ScrollEvent) => {
73
+ 'worklet';
74
+ if (!consumerOnScrollBeginDrag) {
75
+ return;
76
+ }
77
+ scheduleOnRN(consumerOnScrollBeginDrag, {
78
+ nativeEvent: event,
79
+ } as unknown);
80
+ },
81
+ [consumerOnScrollBeginDrag]
82
+ );
83
+
84
+ const onEndDragBridge = useCallback(
85
+ (event: ScrollEvent) => {
86
+ 'worklet';
87
+ if (!consumerOnScrollEndDrag) {
88
+ return;
89
+ }
90
+ scheduleOnRN(consumerOnScrollEndDrag, { nativeEvent: event } as unknown);
91
+ },
92
+ [consumerOnScrollEndDrag]
93
+ );
94
+
95
+ const onMomentumBeginBridge = useCallback(
96
+ (event: ScrollEvent) => {
97
+ 'worklet';
98
+ if (!consumerOnMomentumScrollBegin) {
99
+ return;
100
+ }
101
+ scheduleOnRN(consumerOnMomentumScrollBegin, {
102
+ nativeEvent: event,
103
+ } as unknown);
104
+ },
105
+ [consumerOnMomentumScrollBegin]
106
+ );
107
+
108
+ const onMomentumEndBridge = useCallback(
109
+ (event: ScrollEvent) => {
110
+ 'worklet';
111
+ if (!consumerOnMomentumScrollEnd) {
112
+ return;
113
+ }
114
+ scheduleOnRN(consumerOnMomentumScrollEnd, {
115
+ nativeEvent: event,
116
+ } as unknown);
117
+ },
118
+ [consumerOnMomentumScrollEnd]
119
+ );
120
+
121
+ return {
122
+ onScroll: onScrollBridge,
123
+ onBeginDrag: onBeginDragBridge,
124
+ onEndDrag: onEndDragBridge,
125
+ onMomentumBegin: onMomentumBeginBridge,
126
+ onMomentumEnd: onMomentumEndBridge,
127
+ };
128
+ }
129
+
130
+ export function useScrollHandlerComposition(
131
+ ownScrollHandler: ScrollHandlerProcessed<ScrollHandlerContext>,
132
+ consumerScrollHandler: AnimatedScrollViewOnScroll | undefined
133
+ ) {
134
+ // TODO: I guess the typing here could be more precise
135
+ const consumerWorkletHandler = isAnimatedScrollHandler(consumerScrollHandler)
136
+ ? (consumerScrollHandler as ScrollHandlerProcessed<ScrollHandlerContext>)
137
+ : null;
138
+
139
+ return useComposedEventHandler([ownScrollHandler, consumerWorkletHandler]);
140
+ }
141
+
142
+ function isAnimatedScrollHandler(
143
+ handler: AnimatedScrollViewOnScroll | undefined
144
+ ): handler is AnimatedScrollViewOnScroll {
145
+ // FUTURE: we could be checking just by typeof handler === 'object'?
146
+ // This seems safer for now, unless Reanimated changes this shape. Revisit
147
+ return !!handler && 'workletEventHandler' in handler;
148
+ }
@@ -13,6 +13,15 @@ import { RuntimeKind, scheduleOnUI } from 'react-native-worklets';
13
13
  import { HeaderMotionContext } from '../context';
14
14
  import type { ScrollManagerConfig, ScrollValues } from '../types';
15
15
  import { DEFAULT_SCROLL_ID, getInitialScrollValue } from '../utils';
16
+ import {
17
+ resolveRefreshControl,
18
+ type ResolveRefreshControlOptions,
19
+ } from './refreshControl';
20
+ import {
21
+ useConsumerScrollHandlers,
22
+ useScrollHandlerComposition,
23
+ type ConsumerScrollEventHandlers,
24
+ } from './useConsumerScrollHandlers';
16
25
 
17
26
  /**
18
27
  * Hook that manages scroll tracking and synchronization for header animations.
@@ -51,12 +60,19 @@ import { DEFAULT_SCROLL_ID, getInitialScrollValue } from '../utils';
51
60
  * }
52
61
  * ```
53
62
  */
54
- export interface UseScrollManagerOptions {
63
+ export interface UseScrollManagerOptions
64
+ extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'>,
65
+ ConsumerScrollEventHandlers {
55
66
  /**
56
67
  * Optional animated ref to use instead of creating one internally.
57
68
  * Useful when you need access to the scroll view ref from outside.
58
69
  */
59
70
  animatedRef?: AnimatedRef<any>;
71
+ /**
72
+ * Optional refresh progress offset override.
73
+ * When provided, it takes precedence over the automatic offset based on header height.
74
+ */
75
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
60
76
  }
61
77
 
62
78
  export function useScrollManager(
@@ -81,6 +97,20 @@ export function useScrollManager(
81
97
 
82
98
  const localRef = useAnimatedRef<any>(); // TODO: better typing
83
99
  const animatedRef = options?.animatedRef ?? localRef;
100
+ const refreshControl = options?.refreshControl;
101
+ const refreshing = options?.refreshing;
102
+ const onRefresh = options?.onRefresh;
103
+ const progressViewOffset =
104
+ options?.progressViewOffset ?? originalHeaderHeight;
105
+
106
+ const { onScroll, onBeginDrag, onEndDrag, onMomentumBegin, onMomentumEnd } =
107
+ useConsumerScrollHandlers({
108
+ onScroll: options?.onScroll,
109
+ onScrollBeginDrag: options?.onScrollBeginDrag,
110
+ onScrollEndDrag: options?.onScrollEndDrag,
111
+ onMomentumScrollBegin: options?.onMomentumScrollBegin,
112
+ onMomentumScrollEnd: options?.onMomentumScrollEnd,
113
+ });
84
114
 
85
115
  useEffect(() => {
86
116
  return () => {
@@ -142,6 +172,7 @@ export function useScrollManager(
142
172
  const scrollHandler = useCallback<ScrollHandler>(
143
173
  (e) => {
144
174
  'worklet';
175
+ onScroll?.(e);
145
176
 
146
177
  scrollValues.modify((value) => {
147
178
  if (!value[id]) {
@@ -167,10 +198,16 @@ export function useScrollManager(
167
198
  return value;
168
199
  });
169
200
  },
170
- [scrollValues, id, activeScrollId, progressThreshold]
201
+ [scrollValues, id, activeScrollId, progressThreshold, onScroll]
171
202
  );
172
203
 
173
- const onScroll = useAnimatedScrollHandler(scrollHandler);
204
+ const animatedScrollHandler = useAnimatedScrollHandler({
205
+ onScroll: scrollHandler,
206
+ onBeginDrag,
207
+ onEndDrag,
208
+ onMomentumBegin,
209
+ onMomentumEnd,
210
+ });
174
211
 
175
212
  const minHeightContentContainerStyle = useAnimatedStyle(() => {
176
213
  if (globalThis.__RUNTIME_KIND === RuntimeKind.ReactNative) {
@@ -188,10 +225,21 @@ export function useScrollManager(
188
225
  };
189
226
  });
190
227
 
228
+ const resolvedRefreshControl = resolveRefreshControl({
229
+ refreshControl,
230
+ refreshing,
231
+ onRefresh,
232
+ progressViewOffset,
233
+ });
234
+
191
235
  const scrollableProps = {
192
- onScroll,
236
+ onScroll: useScrollHandlerComposition(
237
+ animatedScrollHandler,
238
+ options?.onScroll
239
+ ),
193
240
  scrollEventThrottle: 16,
194
241
  ref: animatedRef,
242
+ refreshControl: resolvedRefreshControl,
195
243
  };
196
244
  const headerMotionContext = {
197
245
  originalHeaderHeight,
package/src/types.ts CHANGED
@@ -1,4 +1,9 @@
1
- import type { LayoutChangeEvent, ScrollViewProps } from 'react-native';
1
+ import type { ReactElement } from 'react';
2
+ import type {
3
+ LayoutChangeEvent,
4
+ RefreshControlProps,
5
+ ScrollViewProps,
6
+ } from 'react-native';
2
7
  import type { AnimatedRef, SharedValue } from 'react-native-reanimated';
3
8
  import { DEFAULT_SCROLL_ID } from './utils/defaults';
4
9
 
@@ -56,7 +61,12 @@ export interface ScrollManagerConfig {
56
61
  scrollableProps: Required<
57
62
  Pick<ScrollViewProps, 'onScroll' | 'scrollEventThrottle'>
58
63
  > & {
64
+ refreshControl?: ReactElement<RefreshControlProps>;
59
65
  ref: AnimatedRef<any>; // TODO: better typing
60
66
  };
61
67
  headerMotionContext: ScrollManagerHeaderMotionContext;
62
68
  }
69
+
70
+ export type ScrollHandlerContext = {
71
+ lastOffset: number | undefined;
72
+ };