react-native-header-motion 0.1.1 → 0.3.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 (30) hide show
  1. package/README.md +58 -0
  2. package/lib/module/components/FlatList.js +12 -2
  3. package/lib/module/components/FlatList.js.map +1 -1
  4. package/lib/module/components/ScrollManager.js +13 -2
  5. package/lib/module/components/ScrollManager.js.map +1 -1
  6. package/lib/module/components/ScrollView.js +8 -0
  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/useScrollManager.js +20 -4
  11. package/lib/module/hooks/useScrollManager.js.map +1 -1
  12. package/lib/typescript/src/components/FlatList.d.ts +8 -5
  13. package/lib/typescript/src/components/FlatList.d.ts.map +1 -1
  14. package/lib/typescript/src/components/ScrollManager.d.ts +14 -2
  15. package/lib/typescript/src/components/ScrollManager.d.ts.map +1 -1
  16. package/lib/typescript/src/components/ScrollView.d.ts +7 -2
  17. package/lib/typescript/src/components/ScrollView.d.ts.map +1 -1
  18. package/lib/typescript/src/hooks/refreshControl.d.ts +13 -0
  19. package/lib/typescript/src/hooks/refreshControl.d.ts.map +1 -0
  20. package/lib/typescript/src/hooks/useScrollManager.d.ts +18 -1
  21. package/lib/typescript/src/hooks/useScrollManager.d.ts.map +1 -1
  22. package/lib/typescript/src/types.d.ts +3 -1
  23. package/lib/typescript/src/types.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/components/FlatList.tsx +23 -9
  26. package/src/components/ScrollManager.tsx +26 -2
  27. package/src/components/ScrollView.tsx +17 -2
  28. package/src/hooks/refreshControl.ts +55 -0
  29. package/src/hooks/useScrollManager.ts +41 -2
  30. package/src/types.ts +7 -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)
@@ -23,13 +23,20 @@ import { jsx as _jsx } from "react/jsx-runtime";
23
23
  */
24
24
  export function HeaderMotionFlatList({
25
25
  scrollId,
26
+ animatedRef,
26
27
  contentContainerStyle,
27
28
  ...props
28
29
  }) {
29
30
  return /*#__PURE__*/_jsx(HeaderMotionScrollManager, {
30
31
  scrollId: scrollId,
32
+ animatedRef: animatedRef,
33
+ refreshControl: props.refreshControl,
34
+ refreshing: props.refreshing,
35
+ onRefresh: props.onRefresh,
36
+ progressViewOffset: props.progressViewOffset,
31
37
  children: ({
32
38
  onScroll,
39
+ refreshControl: managedRefreshControl,
33
40
  ...scrollViewProps
34
41
  }, {
35
42
  originalHeaderHeight,
@@ -38,8 +45,11 @@ export function HeaderMotionFlatList({
38
45
  ...scrollViewProps,
39
46
  ...props,
40
47
  onScroll: onScroll,
41
- renderScrollComponent: propsz => /*#__PURE__*/_jsx(AnimatedScrollContainer, {
42
- ...propsz,
48
+ ...(managedRefreshControl && {
49
+ refreshControl: managedRefreshControl
50
+ }),
51
+ renderScrollComponent: scrollComponentProps => /*#__PURE__*/_jsx(AnimatedScrollContainer, {
52
+ ...scrollComponentProps,
43
53
  contentContainerStyle: [minHeightContentContainerStyle, {
44
54
  paddingTop: originalHeaderHeight
45
55
  }, contentContainerStyle]
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionFlatList","scrollId","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,MAAM,yBAAyB;AAC9C,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAgB5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAAU;EAC5CC,QAAQ;EACRC,qBAAqB;EACrB,GAAGC;AACyB,CAAC,EAAE;EAC/B,oBACEJ,IAAA,CAACF,yBAAyB;IAACI,QAAQ,EAAEA,QAAS;IAAAG,QAAA,EAC3CA,CACC;MAAEC,QAAQ;MAAE,GAAGC;IAAgB,CAAC,EAChC;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDT,IAAA,CAACH,QAAQ,CAACa,QAAQ;MAAA,GACZH,eAAe;MAAA,GACfH,KAAK;MACTE,QAAQ,EAAEA,QAAS;MACnBK,qBAAqB,EAAGC,MAAM,iBAC5BZ,IAAA,CAACa,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,gBAAGjB,UAAU,CAGxC,CAAC;EAAES,QAAQ;EAAEF,qBAAqB;EAAE,GAAGY;AAAK,CAAC,EAAEC,GAAG,KAAK;EACvD,oBACEhB,IAAA,CAACH,QAAQ,CAACoB,UAAU;IAAA,GAAKF,IAAI;IAAEC,GAAG,EAAEA,GAAI;IAAAX,QAAA,eACtCL,IAAA,CAACH,QAAQ,CAACqB,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","props","refreshControl","refreshing","onRefresh","progressViewOffset","children","onScroll","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;EACrB,GAAGC;AACyB,CAAC,EAAE;EAC/B,oBACEL,IAAA,CAACF,yBAAyB;IACxBI,QAAQ,EAAEA,QAAS;IACnBC,WAAW,EAAEA,WAAY;IACzBG,cAAc,EAAED,KAAK,CAACC,cAAe;IACrCC,UAAU,EAAEF,KAAK,CAACE,UAAW;IAC7BC,SAAS,EAAEH,KAAK,CAACG,SAAU;IAC3BC,kBAAkB,EAAEJ,KAAK,CAACI,kBAAmB;IAAAC,QAAA,EAE5CA,CACC;MAAEC,QAAQ;MAAEL,cAAc,EAAEM,qBAAqB;MAAE,GAAGC;IAAgB,CAAC,EACvE;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDf,IAAA,CAACH,QAAQ,CAACmB,QAAQ;MAAA,GACZH,eAAe;MAAA,GACfR,KAAK;MACTM,QAAQ,EAAEA,QAAS;MAAA,IACdC,qBAAqB,IAAI;QAC5BN,cAAc,EAAEM;MAClB,CAAC;MACDK,qBAAqB,EAAGC,oBAAoB,iBAC1ClB,IAAA,CAACmB,uBAAuB;QAAA,GAClBD,oBAAoB;QACxBd,qBAAqB,EAAE,CACrBW,8BAA8B,EAC9B;UAAEK,UAAU,EAAEN;QAAqB,CAAC,EACpCV,qBAAqB;MACrB,CACH;IACD,CACH;EACF,CACwB,CAAC;AAEhC;AAEA,MAAMe,uBAAuB,gBAAGvB,UAAU,CAGxC,CAAC;EAAEc,QAAQ;EAAEN,qBAAqB;EAAE,GAAGiB;AAAK,CAAC,EAAEC,GAAG,KAAK;EACvD,oBACEtB,IAAA,CAACH,QAAQ,CAAC0B,UAAU;IAAA,GAAKF,IAAI;IAAEC,GAAG,EAAEA,GAAI;IAAAZ,QAAA,eACtCV,IAAA,CAACH,QAAQ,CAAC2B,IAAI;MAACC,KAAK,EAAErB,qBAAsB;MAAAM,QAAA,EAAEA;IAAQ,CAAgB;EAAC,CACpD,CAAC;AAE1B,CAAC,CAAC","ignoreList":[]}
@@ -25,7 +25,12 @@ import { useScrollManager } from "../hooks/index.js";
25
25
  */
26
26
  export function HeaderMotionScrollManager({
27
27
  children,
28
- scrollId
28
+ scrollId,
29
+ animatedRef,
30
+ refreshControl,
31
+ refreshing,
32
+ onRefresh,
33
+ progressViewOffset
29
34
  }) {
30
35
  if (typeof children !== 'function') {
31
36
  throw new Error('HeaderMotion.ScrollManager only accepts render function as the only child.');
@@ -33,7 +38,13 @@ export function HeaderMotionScrollManager({
33
38
  const {
34
39
  scrollableProps,
35
40
  headerMotionContext
36
- } = useScrollManager(scrollId);
41
+ } = useScrollManager(scrollId, {
42
+ animatedRef,
43
+ refreshControl,
44
+ refreshing,
45
+ onRefresh,
46
+ progressViewOffset
47
+ });
37
48
  return children(scrollableProps, headerMotionContext);
38
49
  }
39
50
  //# sourceMappingURL=ScrollManager.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useScrollManager","HeaderMotionScrollManager","children","scrollId","Error","scrollableProps","headerMotionContext"],"sourceRoot":"../../../src","sources":["components/ScrollManager.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,mBAAU;AAsB3C;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;AAC8B,CAAC,EAAE;EACjC,IAAI,OAAOD,QAAQ,KAAK,UAAU,EAAE;IAClC,MAAM,IAAIE,KAAK,CACb,4EACF,CAAC;EACH;EAEA,MAAM;IAAEC,eAAe;IAAEC;EAAoB,CAAC,GAAGN,gBAAgB,CAACG,QAAQ,CAAC;EAE3E,OAAOD,QAAQ,CAACG,eAAe,EAAEC,mBAAmB,CAAC;AACvD","ignoreList":[]}
1
+ {"version":3,"names":["useScrollManager","HeaderMotionScrollManager","children","scrollId","animatedRef","refreshControl","refreshing","onRefresh","progressViewOffset","Error","scrollableProps","headerMotionContext"],"sourceRoot":"../../../src","sources":["components/ScrollManager.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAQ,mBAAU;AAmC3C;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;AAC8B,CAAC,EAAE;EACjC,IAAI,OAAON,QAAQ,KAAK,UAAU,EAAE;IAClC,MAAM,IAAIO,KAAK,CACb,4EACF,CAAC;EACH;EAEA,MAAM;IAAEC,eAAe;IAAEC;EAAoB,CAAC,GAAGX,gBAAgB,CAACG,QAAQ,EAAE;IAC1EC,WAAW;IACXC,cAAc;IACdC,UAAU;IACVC,SAAS;IACTC;EACF,CAAC,CAAC;EAEF,OAAON,QAAQ,CAACQ,eAAe,EAAEC,mBAAmB,CAAC;AACvD","ignoreList":[]}
@@ -19,14 +19,19 @@ import { jsx as _jsx } from "react/jsx-runtime";
19
19
  */
20
20
  export function HeaderMotionScrollView({
21
21
  scrollId,
22
+ animatedRef,
22
23
  children,
23
24
  contentContainerStyle,
25
+ refreshControl,
24
26
  ...props
25
27
  }) {
26
28
  return /*#__PURE__*/_jsx(HeaderMotionScrollManager, {
27
29
  scrollId: scrollId,
30
+ animatedRef: animatedRef,
31
+ refreshControl: refreshControl,
28
32
  children: ({
29
33
  onScroll,
34
+ refreshControl: managedRefreshControl,
30
35
  ...scrollViewProps
31
36
  }, {
32
37
  originalHeaderHeight,
@@ -35,6 +40,9 @@ export function HeaderMotionScrollView({
35
40
  ...scrollViewProps,
36
41
  ...props,
37
42
  onScroll: onScroll,
43
+ ...(managedRefreshControl && {
44
+ refreshControl: managedRefreshControl
45
+ }),
38
46
  children: /*#__PURE__*/_jsx(Animated.View, {
39
47
  style: [minHeightContentContainerStyle, {
40
48
  paddingTop: originalHeaderHeight
@@ -1 +1 @@
1
- {"version":3,"names":["Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionScrollView","scrollId","children","contentContainerStyle","props","onScroll","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","ScrollView","View","style","paddingTop"],"sourceRoot":"../../../src","sources":["components/ScrollView.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAER,yBAAyB;AAChC,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAU5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CAAC;EACrCC,QAAQ;EACRC,QAAQ;EACRC,qBAAqB;EACrB,GAAGC;AACwB,CAAC,EAAE;EAC9B,oBACEL,IAAA,CAACF,yBAAyB;IAACI,QAAQ,EAAEA,QAAS;IAAAC,QAAA,EAC3CA,CACC;MAAEG,QAAQ;MAAE,GAAGC;IAAgB,CAAC,EAChC;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDT,IAAA,CAACH,QAAQ,CAACa,UAAU;MAAA,GACdH,eAAe;MAAA,GACfF,KAAK;MACTC,QAAQ,EAAEA,QAAS;MAAAH,QAAA,eAEnBH,IAAA,CAACH,QAAQ,CAACc,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","props","onScroll","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;EACd,GAAGC;AACwB,CAAC,EAAE;EAC9B,oBACEP,IAAA,CAACF,yBAAyB;IACxBI,QAAQ,EAAEA,QAAS;IACnBC,WAAW,EAAEA,WAAY;IACzBG,cAAc,EAAEA,cAAe;IAAAF,QAAA,EAE9BA,CACC;MAAEI,QAAQ;MAAEF,cAAc,EAAEG,qBAAqB;MAAE,GAAGC;IAAgB,CAAC,EACvE;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDZ,IAAA,CAACH,QAAQ,CAACgB,UAAU;MAAA,GACdH,eAAe;MAAA,GACfH,KAAK;MACTC,QAAQ,EAAEA,QAAS;MAAA,IACdC,qBAAqB,IAAI;QAC5BH,cAAc,EAAEG;MAClB,CAAC;MAAAL,QAAA,eAEDJ,IAAA,CAACH,QAAQ,CAACiB,IAAI;QACZC,KAAK,EAAE,CACLH,8BAA8B,EAC9B;UAAEI,UAAU,EAAEL;QAAqB,CAAC,EACpCN,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":[]}
@@ -5,6 +5,7 @@ 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";
8
9
 
9
10
  /**
10
11
  * Hook that manages scroll tracking and synchronization for header animations.
@@ -19,6 +20,9 @@ import { DEFAULT_SCROLL_ID, getInitialScrollValue } from "../utils/index.js";
19
20
  *
20
21
  * @param scrollId - Optional unique identifier for the related scrollable.
21
22
  * Use when you have multiple scrollables (e.g., in tabs).
23
+ * @param options - Optional configuration object.
24
+ * @param options.animatedRef - Optional animated ref to use instead of creating one internally.
25
+ * Useful when you need access to the scroll view ref from outside.
22
26
  * @returns Configuration object containing:
23
27
  * - `scrollableProps`: Props to apply to scrollable component (onScroll, scrollEventThrottle, ref)
24
28
  * - `headerMotionContext`: Header context values (originalHeaderHeight, minHeightContentContainerStyle)
@@ -40,7 +44,8 @@ import { DEFAULT_SCROLL_ID, getInitialScrollValue } from "../utils/index.js";
40
44
  * }
41
45
  * ```
42
46
  */
43
- export function useScrollManager(scrollId) {
47
+
48
+ export function useScrollManager(scrollId, options) {
44
49
  const ctxValue = useContext(HeaderMotionContext);
45
50
  if (!ctxValue) {
46
51
  throw new Error('useScrollManager must be used within a HeaderMotion component');
@@ -53,8 +58,12 @@ export function useScrollManager(scrollId) {
53
58
  originalHeaderHeight
54
59
  } = ctxValue;
55
60
  const id = scrollId ?? DEFAULT_SCROLL_ID;
56
- const animatedRef = useAnimatedRef(); // TODO: better typing
57
-
61
+ const localRef = useAnimatedRef(); // TODO: better typing
62
+ const animatedRef = options?.animatedRef ?? localRef;
63
+ const refreshControl = options?.refreshControl;
64
+ const refreshing = options?.refreshing;
65
+ const onRefresh = options?.onRefresh;
66
+ const progressViewOffset = options?.progressViewOffset ?? originalHeaderHeight;
58
67
  useEffect(() => {
59
68
  return () => {
60
69
  scheduleOnUI(scrollIdToDelete => {
@@ -133,10 +142,17 @@ export function useScrollManager(scrollId) {
133
142
  minHeight: measurement.height + progressThreshold
134
143
  };
135
144
  });
145
+ const resolvedRefreshControl = resolveRefreshControl({
146
+ refreshControl,
147
+ refreshing,
148
+ onRefresh,
149
+ progressViewOffset
150
+ });
136
151
  const scrollableProps = {
137
152
  onScroll,
138
153
  scrollEventThrottle: 16,
139
- ref: animatedRef
154
+ ref: animatedRef,
155
+ refreshControl: resolvedRefreshControl
140
156
  };
141
157
  const headerMotionContext = {
142
158
  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","ctxValue","Error","scrollValues","progress","activeScrollId","progressThreshold","originalHeaderHeight","id","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","useScrollManager","scrollId","options","ctxValue","Error","scrollValues","progress","activeScrollId","progressThreshold","originalHeaderHeight","id","localRef","animatedRef","refreshControl","refreshing","onRefresh","progressViewOffset","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","resolvedRefreshControl","scrollableProps","scrollEventThrottle","ref","headerMotionContext"],"sourceRoot":"../../../src","sources":["hooks/useScrollManager.ts"],"mappings":"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","ignoreList":[]}
@@ -1,12 +1,16 @@
1
1
  import { type ComponentProps } from 'react';
2
- import Animated from 'react-native-reanimated';
3
- type AnimatedFlatListProps<T = any> = ComponentProps<typeof Animated.FlatList<T>>;
4
- export type HeaderMotionFlatListProps<T = any> = AnimatedFlatListProps<T> & {
2
+ import Animated, { type AnimatedRef } from 'react-native-reanimated';
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.
8
7
  */
9
8
  scrollId?: string;
9
+ /**
10
+ * Optional animated ref to use for the flat list.
11
+ * When provided, the scroll manager will use this ref instead of creating its own.
12
+ */
13
+ animatedRef?: AnimatedRef<any>;
10
14
  };
11
15
  /**
12
16
  * Animated FlatList component that integrates with HeaderMotion.
@@ -25,6 +29,5 @@ export type HeaderMotionFlatListProps<T = any> = AnimatedFlatListProps<T> & {
25
29
  * </HeaderMotion>
26
30
  * ```
27
31
  */
28
- export declare function HeaderMotionFlatList<T = any>({ scrollId, contentContainerStyle, ...props }: HeaderMotionFlatListProps<T>): import("react/jsx-runtime").JSX.Element;
29
- export {};
32
+ export declare function HeaderMotionFlatList<T = any>({ scrollId, animatedRef, contentContainerStyle, ...props }: HeaderMotionFlatListProps<T>): import("react/jsx-runtime").JSX.Element;
30
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,MAAM,yBAAyB,CAAC;AAK/C,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;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,GAAG,EAAE,EAC5C,QAAQ,EACR,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,GAAG,KAAK,EACT,EAAE,yBAAyB,CAAC,CAAC,CAAC,2CAmC9B"}
@@ -1,12 +1,24 @@
1
1
  import type { ScrollManagerConfig } from '../types';
2
+ import type { ResolveRefreshControlOptions } from '../hooks/refreshControl';
2
3
  import type { ReactNode } from 'react';
4
+ import type { AnimatedRef } from 'react-native-reanimated';
3
5
  type ScrollManagerRenderChildren = (scrollableProps: ScrollManagerConfig['scrollableProps'], options: ScrollManagerConfig['headerMotionContext']) => ReactNode;
4
- export interface HeaderMotionScrollManagerProps {
6
+ export interface HeaderMotionScrollManagerProps extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'> {
5
7
  /**
6
8
  * Optional unique identifier for this scroll view.
7
9
  * Use this when you have multiple scroll views (e.g., in tabs) to track them separately.
8
10
  */
9
11
  scrollId?: string;
12
+ /**
13
+ * Optional animated ref to use for the scroll view.
14
+ * When provided, the scroll manager will use this ref instead of creating its own.
15
+ */
16
+ animatedRef?: AnimatedRef<any>;
17
+ /**
18
+ * Optional refresh progress offset override.
19
+ * When provided, it takes precedence over the automatic offset based on header height.
20
+ */
21
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
10
22
  /**
11
23
  * Render function that receives scroll props and header context.
12
24
  * Use this to create custom scroll implementations that integrate with HeaderMotion.
@@ -35,6 +47,6 @@ export interface HeaderMotionScrollManagerProps {
35
47
  * </HeaderMotion>
36
48
  * ```
37
49
  */
38
- export declare function HeaderMotionScrollManager({ children, scrollId, }: HeaderMotionScrollManagerProps): ReactNode;
50
+ export declare function HeaderMotionScrollManager({ children, scrollId, animatedRef, refreshControl, refreshing, onRefresh, progressViewOffset, }: HeaderMotionScrollManagerProps): ReactNode;
39
51
  export {};
40
52
  //# 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;AAEvC,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,QAAQ,EAAE,2BAA2B,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,QAAQ,GACT,EAAE,8BAA8B,aAUhC"}
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;AAE3D,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;IAChE;;;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,GACnB,EAAE,8BAA8B,aAgBhC"}
@@ -1,10 +1,15 @@
1
- import { type AnimatedScrollViewProps } from 'react-native-reanimated';
1
+ import { type AnimatedRef, type AnimatedScrollViewProps } from 'react-native-reanimated';
2
2
  export type HeaderMotionScrollViewProps = AnimatedScrollViewProps & {
3
3
  /**
4
4
  * Optional unique identifier for this scroll view.
5
5
  * Use this when you have multiple scroll views (e.g. in tabs) to track them separately.
6
6
  */
7
7
  scrollId?: string;
8
+ /**
9
+ * Optional animated ref to use for the scroll view.
10
+ * When provided, the scroll manager will use this ref instead of creating its own.
11
+ */
12
+ animatedRef?: AnimatedRef<any>;
8
13
  };
9
14
  /**
10
15
  * Animated ScrollView component that integrates with HeaderMotion.
@@ -20,5 +25,5 @@ export type HeaderMotionScrollViewProps = AnimatedScrollViewProps & {
20
25
  * </HeaderMotion>
21
26
  * ```
22
27
  */
23
- export declare function HeaderMotionScrollView({ scrollId, children, contentContainerStyle, ...props }: HeaderMotionScrollViewProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function HeaderMotionScrollView({ scrollId, animatedRef, children, contentContainerStyle, refreshControl, ...props }: HeaderMotionScrollViewProps): import("react/jsx-runtime").JSX.Element;
24
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,uBAAuB,EAC7B,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,2BAA2B,GAAG,uBAAuB,GAAG;IAClE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,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,GAAG,KAAK,EACT,EAAE,2BAA2B,2CAgC7B"}
@@ -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"}
@@ -1,4 +1,6 @@
1
+ import { type AnimatedRef } from 'react-native-reanimated';
1
2
  import type { ScrollManagerConfig } from '../types';
3
+ import { type ResolveRefreshControlOptions } from './refreshControl';
2
4
  /**
3
5
  * Hook that manages scroll tracking and synchronization for header animations.
4
6
  * Returns props to apply to scrollable components and additional values that help with adjusting styling of the scrollables to header's dimensions.
@@ -12,6 +14,9 @@ import type { ScrollManagerConfig } from '../types';
12
14
  *
13
15
  * @param scrollId - Optional unique identifier for the related scrollable.
14
16
  * Use when you have multiple scrollables (e.g., in tabs).
17
+ * @param options - Optional configuration object.
18
+ * @param options.animatedRef - Optional animated ref to use instead of creating one internally.
19
+ * Useful when you need access to the scroll view ref from outside.
15
20
  * @returns Configuration object containing:
16
21
  * - `scrollableProps`: Props to apply to scrollable component (onScroll, scrollEventThrottle, ref)
17
22
  * - `headerMotionContext`: Header context values (originalHeaderHeight, minHeightContentContainerStyle)
@@ -33,5 +38,17 @@ import type { ScrollManagerConfig } from '../types';
33
38
  * }
34
39
  * ```
35
40
  */
36
- export declare function useScrollManager(scrollId?: string): ScrollManagerConfig;
41
+ export interface UseScrollManagerOptions extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'> {
42
+ /**
43
+ * Optional animated ref to use instead of creating one internally.
44
+ * Useful when you need access to the scroll view ref from outside.
45
+ */
46
+ animatedRef?: AnimatedRef<any>;
47
+ /**
48
+ * Optional refresh progress offset override.
49
+ * When provided, it takes precedence over the automatic offset based on header height.
50
+ */
51
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
52
+ }
53
+ export declare function useScrollManager(scrollId?: string, options?: UseScrollManagerOptions): ScrollManagerConfig;
37
54
  //# sourceMappingURL=useScrollManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollManager.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useScrollManager.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,UAAU,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAwIvE"}
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;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,4BAA4B,EAAE,oBAAoB,CAAC;IAChE;;;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,CAsJrB"}
@@ -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,6 +37,7 @@ 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;
@@ -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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-header-motion",
3
- "version": "0.1.1",
3
+ "version": "0.3.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",
@@ -1,19 +1,22 @@
1
1
  import { forwardRef, type ComponentProps, type ComponentRef } from 'react';
2
- import Animated from 'react-native-reanimated';
2
+ import Animated, { type AnimatedRef } from 'react-native-reanimated';
3
3
  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.
15
13
  */
16
14
  scrollId?: string;
15
+ /**
16
+ * Optional animated ref to use for the flat list.
17
+ * When provided, the scroll manager will use this ref instead of creating its own.
18
+ */
19
+ animatedRef?: AnimatedRef<any>;
17
20
  };
18
21
 
19
22
  /**
@@ -35,22 +38,33 @@ export type HeaderMotionFlatListProps<T = any> = AnimatedFlatListProps<T> & {
35
38
  */
36
39
  export function HeaderMotionFlatList<T = any>({
37
40
  scrollId,
41
+ animatedRef,
38
42
  contentContainerStyle,
39
43
  ...props
40
44
  }: HeaderMotionFlatListProps<T>) {
41
45
  return (
42
- <HeaderMotionScrollManager scrollId={scrollId}>
46
+ <HeaderMotionScrollManager
47
+ scrollId={scrollId}
48
+ animatedRef={animatedRef}
49
+ refreshControl={props.refreshControl}
50
+ refreshing={props.refreshing}
51
+ onRefresh={props.onRefresh}
52
+ progressViewOffset={props.progressViewOffset}
53
+ >
43
54
  {(
44
- { onScroll, ...scrollViewProps },
55
+ { onScroll, refreshControl: managedRefreshControl, ...scrollViewProps },
45
56
  { originalHeaderHeight, minHeightContentContainerStyle }
46
57
  ) => (
47
58
  <Animated.FlatList
48
59
  {...scrollViewProps}
49
60
  {...props}
50
61
  onScroll={onScroll}
51
- renderScrollComponent={(propsz) => (
62
+ {...(managedRefreshControl && {
63
+ refreshControl: managedRefreshControl,
64
+ })}
65
+ renderScrollComponent={(scrollComponentProps) => (
52
66
  <AnimatedScrollContainer
53
- {...propsz}
67
+ {...scrollComponentProps}
54
68
  contentContainerStyle={[
55
69
  minHeightContentContainerStyle,
56
70
  { paddingTop: originalHeaderHeight },
@@ -1,18 +1,31 @@
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';
5
+ import type { AnimatedRef } from 'react-native-reanimated';
4
6
 
5
7
  type ScrollManagerRenderChildren = (
6
8
  scrollableProps: ScrollManagerConfig['scrollableProps'],
7
9
  options: ScrollManagerConfig['headerMotionContext']
8
10
  ) => ReactNode;
9
11
 
10
- export interface HeaderMotionScrollManagerProps {
12
+ export interface HeaderMotionScrollManagerProps
13
+ extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'> {
11
14
  /**
12
15
  * Optional unique identifier for this scroll view.
13
16
  * Use this when you have multiple scroll views (e.g., in tabs) to track them separately.
14
17
  */
15
18
  scrollId?: string;
19
+ /**
20
+ * Optional animated ref to use for the scroll view.
21
+ * When provided, the scroll manager will use this ref instead of creating its own.
22
+ */
23
+ animatedRef?: AnimatedRef<any>;
24
+ /**
25
+ * Optional refresh progress offset override.
26
+ * When provided, it takes precedence over the automatic offset based on header height.
27
+ */
28
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
16
29
  /**
17
30
  * Render function that receives scroll props and header context.
18
31
  * Use this to create custom scroll implementations that integrate with HeaderMotion.
@@ -45,6 +58,11 @@ export interface HeaderMotionScrollManagerProps {
45
58
  export function HeaderMotionScrollManager({
46
59
  children,
47
60
  scrollId,
61
+ animatedRef,
62
+ refreshControl,
63
+ refreshing,
64
+ onRefresh,
65
+ progressViewOffset,
48
66
  }: HeaderMotionScrollManagerProps) {
49
67
  if (typeof children !== 'function') {
50
68
  throw new Error(
@@ -52,7 +70,13 @@ export function HeaderMotionScrollManager({
52
70
  );
53
71
  }
54
72
 
55
- const { scrollableProps, headerMotionContext } = useScrollManager(scrollId);
73
+ const { scrollableProps, headerMotionContext } = useScrollManager(scrollId, {
74
+ animatedRef,
75
+ refreshControl,
76
+ refreshing,
77
+ onRefresh,
78
+ progressViewOffset,
79
+ });
56
80
 
57
81
  return children(scrollableProps, headerMotionContext);
58
82
  }
@@ -1,4 +1,5 @@
1
1
  import Animated, {
2
+ type AnimatedRef,
2
3
  type AnimatedScrollViewProps,
3
4
  } from 'react-native-reanimated';
4
5
  import { HeaderMotionScrollManager } from './ScrollManager';
@@ -9,6 +10,11 @@ export type HeaderMotionScrollViewProps = AnimatedScrollViewProps & {
9
10
  * Use this when you have multiple scroll views (e.g. in tabs) to track them separately.
10
11
  */
11
12
  scrollId?: string;
13
+ /**
14
+ * Optional animated ref to use for the scroll view.
15
+ * When provided, the scroll manager will use this ref instead of creating its own.
16
+ */
17
+ animatedRef?: AnimatedRef<any>;
12
18
  };
13
19
 
14
20
  /**
@@ -27,20 +33,29 @@ export type HeaderMotionScrollViewProps = AnimatedScrollViewProps & {
27
33
  */
28
34
  export function HeaderMotionScrollView({
29
35
  scrollId,
36
+ animatedRef,
30
37
  children,
31
38
  contentContainerStyle,
39
+ refreshControl,
32
40
  ...props
33
41
  }: HeaderMotionScrollViewProps) {
34
42
  return (
35
- <HeaderMotionScrollManager scrollId={scrollId}>
43
+ <HeaderMotionScrollManager
44
+ scrollId={scrollId}
45
+ animatedRef={animatedRef}
46
+ refreshControl={refreshControl}
47
+ >
36
48
  {(
37
- { onScroll, ...scrollViewProps },
49
+ { onScroll, refreshControl: managedRefreshControl, ...scrollViewProps },
38
50
  { originalHeaderHeight, minHeightContentContainerStyle }
39
51
  ) => (
40
52
  <Animated.ScrollView
41
53
  {...scrollViewProps}
42
54
  {...props}
43
55
  onScroll={onScroll}
56
+ {...(managedRefreshControl && {
57
+ refreshControl: managedRefreshControl,
58
+ })}
44
59
  >
45
60
  <Animated.View
46
61
  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
+ }
@@ -6,12 +6,17 @@ import {
6
6
  useAnimatedRef,
7
7
  useAnimatedScrollHandler,
8
8
  useAnimatedStyle,
9
+ type AnimatedRef,
9
10
  type ScrollHandler,
10
11
  } from 'react-native-reanimated';
11
12
  import { RuntimeKind, scheduleOnUI } from 'react-native-worklets';
12
13
  import { HeaderMotionContext } from '../context';
13
14
  import type { ScrollManagerConfig, ScrollValues } from '../types';
14
15
  import { DEFAULT_SCROLL_ID, getInitialScrollValue } from '../utils';
16
+ import {
17
+ resolveRefreshControl,
18
+ type ResolveRefreshControlOptions,
19
+ } from './refreshControl';
15
20
 
16
21
  /**
17
22
  * Hook that manages scroll tracking and synchronization for header animations.
@@ -26,6 +31,9 @@ import { DEFAULT_SCROLL_ID, getInitialScrollValue } from '../utils';
26
31
  *
27
32
  * @param scrollId - Optional unique identifier for the related scrollable.
28
33
  * Use when you have multiple scrollables (e.g., in tabs).
34
+ * @param options - Optional configuration object.
35
+ * @param options.animatedRef - Optional animated ref to use instead of creating one internally.
36
+ * Useful when you need access to the scroll view ref from outside.
29
37
  * @returns Configuration object containing:
30
38
  * - `scrollableProps`: Props to apply to scrollable component (onScroll, scrollEventThrottle, ref)
31
39
  * - `headerMotionContext`: Header context values (originalHeaderHeight, minHeightContentContainerStyle)
@@ -47,7 +55,24 @@ import { DEFAULT_SCROLL_ID, getInitialScrollValue } from '../utils';
47
55
  * }
48
56
  * ```
49
57
  */
50
- export function useScrollManager(scrollId?: string): ScrollManagerConfig {
58
+ export interface UseScrollManagerOptions
59
+ extends Omit<ResolveRefreshControlOptions, 'progressViewOffset'> {
60
+ /**
61
+ * Optional animated ref to use instead of creating one internally.
62
+ * Useful when you need access to the scroll view ref from outside.
63
+ */
64
+ animatedRef?: AnimatedRef<any>;
65
+ /**
66
+ * Optional refresh progress offset override.
67
+ * When provided, it takes precedence over the automatic offset based on header height.
68
+ */
69
+ progressViewOffset?: ResolveRefreshControlOptions['progressViewOffset'];
70
+ }
71
+
72
+ export function useScrollManager(
73
+ scrollId?: string,
74
+ options?: UseScrollManagerOptions
75
+ ): ScrollManagerConfig {
51
76
  const ctxValue = useContext(HeaderMotionContext);
52
77
  if (!ctxValue) {
53
78
  throw new Error(
@@ -64,7 +89,13 @@ export function useScrollManager(scrollId?: string): ScrollManagerConfig {
64
89
  } = ctxValue;
65
90
  const id = scrollId ?? DEFAULT_SCROLL_ID;
66
91
 
67
- const animatedRef = useAnimatedRef<any>(); // TODO: better typing
92
+ const localRef = useAnimatedRef<any>(); // TODO: better typing
93
+ const animatedRef = options?.animatedRef ?? localRef;
94
+ const refreshControl = options?.refreshControl;
95
+ const refreshing = options?.refreshing;
96
+ const onRefresh = options?.onRefresh;
97
+ const progressViewOffset =
98
+ options?.progressViewOffset ?? originalHeaderHeight;
68
99
 
69
100
  useEffect(() => {
70
101
  return () => {
@@ -172,10 +203,18 @@ export function useScrollManager(scrollId?: string): ScrollManagerConfig {
172
203
  };
173
204
  });
174
205
 
206
+ const resolvedRefreshControl = resolveRefreshControl({
207
+ refreshControl,
208
+ refreshing,
209
+ onRefresh,
210
+ progressViewOffset,
211
+ });
212
+
175
213
  const scrollableProps = {
176
214
  onScroll,
177
215
  scrollEventThrottle: 16,
178
216
  ref: animatedRef,
217
+ refreshControl: resolvedRefreshControl,
179
218
  };
180
219
  const headerMotionContext = {
181
220
  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,6 +61,7 @@ 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;