@rific/scroll-view 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -38,7 +38,7 @@ import { ScrollViewSettingsProvider } from '@rific/scroll-view'
38
38
 
39
39
  export default function RootLayout({ children }) {
40
40
  return (
41
- <ScrollViewSettingsProvider value={{ snapBack: true }}>
41
+ <ScrollViewSettingsProvider initialValue={{ snapBack: true }}>
42
42
  {children}
43
43
  </ScrollViewSettingsProvider>
44
44
  )
@@ -49,6 +49,18 @@ export default function RootLayout({ children }) {
49
49
 
50
50
  ## Components
51
51
 
52
+ ### `ScrollViewSettingsProvider`
53
+
54
+ App-wide defaults for scroll settings. Wrap your root layout to set global defaults.
55
+
56
+ | Prop | Type | Description |
57
+ |------|------|-------------|
58
+ | `children` | `ReactNode` | — |
59
+ | `initialValue` | `Partial<ScrollViewSettings>` | Initial settings applied once on mount |
60
+ | `onChange` | `(settings: ScrollViewSettings) => void` | Called whenever settings change |
61
+
62
+ ---
63
+
52
64
  ### `ScrollViewProvider`
53
65
 
54
66
  Screen-level provider that owns header/footer state and scroll position. Must wrap `ScrollViewHeader`, `ScrollViewFooter`, and the scroll component.
@@ -105,14 +117,17 @@ Drop-in for React Native's `ScrollView`. Accepts all `ScrollViewProps` plus:
105
117
 
106
118
  | Prop | Type | Description |
107
119
  |------|------|-------------|
120
+ | `chipProps` | `ChipProps` | Customize the scroll-to-top chip (label, style, etc.) |
121
+ | `chipThreshold` | `number` | Scroll offset (px) before the chip appears. Default `100` |
108
122
  | `footerFixed` | `boolean` | Pin footer for this scroll view; overrides provider |
109
- | `headerFixed` | `boolean` | Pin header for this scroll view; overrides provider |
110
123
  | `gesture` | `GestureType` | Compose with an external RNGH gesture |
124
+ | `headerFixed` | `boolean` | Pin header for this scroll view; overrides provider |
111
125
  | `keyboardAware` | `boolean` | Add keyboard height to bottom content inset |
126
+ | `onChipPress` | `() => void` | Additional callback fired when the chip is pressed |
112
127
  | `onRefresh` | `() => void` | Enables pull-to-refresh |
113
- | `refreshing` | `boolean` | Controlled refreshing state |
114
128
  | `pullSearchHeight` | `number` | Reserve space above content for `PullSearch` |
115
129
  | `ref` | `RefObject<RNScrollView>` | Forward ref to the underlying scroll view |
130
+ | `refreshing` | `boolean` | Controlled refreshing state |
116
131
 
117
132
  ---
118
133
 
@@ -122,14 +137,17 @@ Drop-in for React Native's `FlatList`. Accepts all `FlatListProps<T>` plus:
122
137
 
123
138
  | Prop | Type | Description |
124
139
  |------|------|-------------|
125
- | `renderFilters` | `ReactNode` | Rendered below `ListHeaderComponent`, above list items |
140
+ | `chipProps` | `ChipProps` | Customize the scroll-to-top/start chip (label, style, etc.) |
141
+ | `chipThreshold` | `number` | Scroll offset (px) before the chip appears. Default `100` |
126
142
  | `footerFixed` | `boolean` | Pin footer for this list; overrides provider |
127
- | `headerFixed` | `boolean` | Pin header for this list; overrides provider |
128
143
  | `gesture` | `GestureType` | Compose with an external RNGH gesture |
144
+ | `headerFixed` | `boolean` | Pin header for this list; overrides provider |
129
145
  | `keyboardAware` | `boolean` | Add keyboard height to bottom content inset |
146
+ | `onChipPress` | `() => void` | Additional callback fired when the chip is pressed |
130
147
  | `onRefresh` | `() => Promise<void> \| void` | Enables pull-to-refresh |
131
148
  | `pullSearchHeight` | `number` | Reserve space above content for `PullSearch` |
132
149
  | `ref` | `RefObject<RNFlatList>` | Forward ref to the underlying list |
150
+ | `renderFilters` | `ReactNode` | Rendered below `ListHeaderComponent`, above list items |
133
151
 
134
152
  Performance props are user-overridable with sensible defaults:
135
153
 
@@ -165,20 +183,41 @@ import { CustomList } from '@rific/scroll-view'
165
183
 
166
184
  | Prop | Type | Description |
167
185
  |------|------|-------------|
186
+ | `chipProps` | `ChipProps` | Customize the scroll-to-top chip (label, style, etc.) |
168
187
  | `component` | `ComponentType<P>` | The list component to render |
169
- | `renderFilters` | `ReactNode` | Rendered below `ListHeaderComponent`, above list items |
170
188
  | `footerFixed` | `boolean` | Pin footer; overrides provider |
171
- | `headerFixed` | `boolean` | Pin header; overrides provider |
172
189
  | `gesture` | `GestureType` | Compose with an external RNGH gesture |
190
+ | `headerFixed` | `boolean` | Pin header; overrides provider |
173
191
  | `keyboardAware` | `boolean` | Add keyboard height to bottom content inset |
174
192
  | `onRefresh` | `() => Promise<void> \| void` | Enables pull-to-refresh |
175
193
  | `pullSearchHeight` | `number` | Reserve space above content for `PullSearch` |
194
+ | `renderFilters` | `ReactNode` | Rendered below `ListHeaderComponent`, above list items |
176
195
  | `scrollRef` | `RefObject<{ scrollToOffset }>` | Forward ref to the underlying list |
177
196
 
178
197
  The underlying component receives `contentInset`, `contentOffset`, `onScroll`, `refreshControl`, and `scrollEventThrottle` — props it must support for the library to function.
179
198
 
180
199
  ---
181
200
 
201
+ ### `ChipProps`
202
+
203
+ Passed via `chipProps` on any scroll component to customise the floating scroll-to-top chip. Accepts all `Chip` props from `@rific/auto-paper` except `compact`, `icon`, and `onPress` (which are managed by the library), plus:
204
+
205
+ | Prop | Type | Description |
206
+ |------|------|-------------|
207
+ | `label` | `ReactNode` | Override the default label ("Top" / "Start") |
208
+ | `style` | `ViewStyle` | Merged with the chip's default style |
209
+
210
+ ```tsx
211
+ <FlatList
212
+ chipProps={{ label: 'Back to top', style: { opacity: 0.9 } }}
213
+ data={items}
214
+ renderItem={renderItem}
215
+ keyExtractor={(item) => item.id}
216
+ />
217
+ ```
218
+
219
+ ---
220
+
182
221
  ### `PullSearch`
183
222
 
184
223
  A search bar that lives above the list content and is revealed by pulling down. Use alongside `pullSearchHeight` on the scroll component.
package/dist/index.d.mts CHANGED
@@ -1,13 +1,18 @@
1
1
  import * as react from 'react';
2
- import { ComponentType, ReactNode, RefObject } from 'react';
2
+ import { ReactNode, ComponentType, RefObject } from 'react';
3
3
  import { NativeSyntheticEvent, NativeScrollEvent, StyleProp, ViewStyle, FlatListProps as FlatListProps$1, FlatList as FlatList$1, ScrollViewProps as ScrollViewProps$1, ScrollView as ScrollView$1, SectionListProps as SectionListProps$1, SectionList as SectionList$1 } from 'react-native';
4
4
  import { GestureType } from 'react-native-gesture-handler';
5
+ import { ChipProps as ChipProps$1 } from '@rific/auto-paper';
5
6
  import * as redux from 'redux';
6
7
  import * as _reduxjs_toolkit from '@reduxjs/toolkit';
7
8
  import { PayloadAction } from '@reduxjs/toolkit';
8
9
  import * as react_native_reanimated from 'react-native-reanimated';
9
10
  import { SharedValue } from 'react-native-reanimated';
10
11
 
12
+ type ChipProps = Omit<ChipProps$1, 'compact' | 'icon' | 'onPress'> & {
13
+ label?: ReactNode;
14
+ };
15
+
11
16
  type ScrollToOffsetRef = {
12
17
  scrollToOffset: (params: {
13
18
  animated?: boolean;
@@ -15,12 +20,15 @@ type ScrollToOffsetRef = {
15
20
  }) => void;
16
21
  };
17
22
  type CustomListProps<P extends object> = Omit<P, 'contentInset' | 'contentOffset' | 'onScroll' | 'refreshControl' | 'scrollEventThrottle'> & {
23
+ chipProps?: ChipProps;
24
+ chipThreshold?: number;
18
25
  component: ComponentType<P>;
19
26
  renderFilters?: ReactNode;
20
27
  footerFixed?: boolean;
21
28
  gesture?: GestureType;
22
29
  headerFixed?: boolean;
23
30
  keyboardAware?: boolean;
31
+ onChipPress?: () => void;
24
32
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
25
33
  onRefresh?: () => Promise<void> | void;
26
34
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -29,15 +37,18 @@ type CustomListProps<P extends object> = Omit<P, 'contentInset' | 'contentOffset
29
37
  scrollRef?: RefObject<ScrollToOffsetRef | null>;
30
38
  style?: StyleProp<ViewStyle>;
31
39
  };
32
- declare const CustomListInner: <P extends object>({ component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }: CustomListProps<P>) => react.JSX.Element;
40
+ declare const CustomListInner: <P extends object>({ chipProps, chipThreshold, component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }: CustomListProps<P>) => react.JSX.Element;
33
41
  declare const CustomList: typeof CustomListInner;
34
42
 
35
43
  type FlatListProps<T> = Omit<FlatListProps$1<T>, 'onRefresh' | 'refreshing'> & {
44
+ chipProps?: ChipProps;
45
+ chipThreshold?: number;
36
46
  renderFilters?: ReactNode;
37
47
  footerFixed?: boolean;
38
48
  gesture?: GestureType;
39
49
  headerFixed?: boolean;
40
50
  keyboardAware?: boolean;
51
+ onChipPress?: () => void;
41
52
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
42
53
  onRefresh?: () => Promise<void> | void;
43
54
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -45,7 +56,7 @@ type FlatListProps<T> = Omit<FlatListProps$1<T>, 'onRefresh' | 'refreshing'> & {
45
56
  pullSearchHeight?: number;
46
57
  ref?: RefObject<FlatList$1 | null>;
47
58
  };
48
- declare const FlatListInner: <T>({ contentContainerStyle: externalContentContainerStyle, data, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize, ...props }: FlatListProps<T>) => react.JSX.Element;
59
+ declare const FlatListInner: <T>({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize, ...props }: FlatListProps<T>) => react.JSX.Element;
49
60
  declare const FlatList: typeof FlatListInner;
50
61
 
51
62
  type PullSearchHandle = {
@@ -89,10 +100,13 @@ declare const scrollViewActions: _reduxjs_toolkit.CaseReducerActions<{
89
100
  declare const scrollViewReducer: redux.Reducer<ScrollViewSettings>;
90
101
 
91
102
  type ScrollViewProps = ScrollViewProps$1 & {
103
+ chipProps?: ChipProps;
104
+ chipThreshold?: number;
92
105
  footerFixed?: boolean;
93
106
  gesture?: GestureType;
94
107
  headerFixed?: boolean;
95
108
  keyboardAware?: boolean;
109
+ onChipPress?: () => void;
96
110
  onRefresh?: () => void;
97
111
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
98
112
  onScrollEndDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -100,7 +114,7 @@ type ScrollViewProps = ScrollViewProps$1 & {
100
114
  ref?: RefObject<ScrollView$1 | null>;
101
115
  refreshing?: boolean;
102
116
  };
103
- declare const ScrollViewInner: ({ children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }: ScrollViewProps) => react.JSX.Element;
117
+ declare const ScrollViewInner: ({ chipProps, chipThreshold, children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }: ScrollViewProps) => react.JSX.Element;
104
118
  declare const ScrollView: typeof ScrollViewInner;
105
119
 
106
120
  type ScrollViewContextType = {
@@ -167,20 +181,23 @@ declare const ScrollViewProvider: ({ blur, children, fixed, footerFixed, headerF
167
181
  type ScrollViewSettingsProviderProps = {
168
182
  children: ReactNode;
169
183
  onChange?: (settings: ScrollViewSettings) => void;
170
- value?: Partial<ScrollViewSettings>;
184
+ initialValue?: Partial<ScrollViewSettings>;
171
185
  };
172
- declare const ScrollViewSettingsProvider: ({ children, onChange, value }: ScrollViewSettingsProviderProps) => react.JSX.Element;
186
+ declare const ScrollViewSettingsProvider: ({ children, onChange, initialValue }: ScrollViewSettingsProviderProps) => react.JSX.Element;
173
187
 
174
188
  type SectionListProps<ItemT, SectionT extends {
175
189
  data: ReadonlyArray<ItemT>;
176
190
  } = {
177
191
  data: ReadonlyArray<ItemT>;
178
192
  }> = Omit<SectionListProps$1<ItemT, SectionT>, 'horizontal'> & {
193
+ chipProps?: ChipProps;
194
+ chipThreshold?: number;
179
195
  renderFilters?: ReactNode;
180
196
  footerFixed?: boolean;
181
197
  gesture?: GestureType;
182
198
  headerFixed?: boolean;
183
199
  keyboardAware?: boolean;
200
+ onChipPress?: () => void;
184
201
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
185
202
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
186
203
  onScrollEndDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -191,7 +208,7 @@ declare const SectionListInner: <ItemT, SectionT extends {
191
208
  data: ReadonlyArray<ItemT>;
192
209
  } = {
193
210
  data: ReadonlyArray<ItemT>;
194
- }>({ contentContainerStyle: externalContentContainerStyle, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize, ...props }: SectionListProps<ItemT, SectionT>) => react.JSX.Element;
211
+ }>({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize, ...props }: SectionListProps<ItemT, SectionT>) => react.JSX.Element;
195
212
  declare const SectionList: typeof SectionListInner;
196
213
 
197
214
  declare const useKeyboardInset: () => number;
@@ -207,4 +224,4 @@ declare const useScrollView: () => {
207
224
 
208
225
  declare const useScrollViewSettings: () => ScrollViewSettingsContextType;
209
226
 
210
- export { CustomList, type CustomListProps, FlatList, type FlatListProps, PullSearch, type PullSearchHandle, type PullSearchProps, ScrollView, ScrollViewContext, type ScrollViewContextType, ScrollViewFooter, type ScrollViewFooterProps, ScrollViewHeader, type ScrollViewHeaderProps, type ScrollViewProps, ScrollViewProvider, type ScrollViewProviderProps, type ScrollViewSettings, ScrollViewSettingsContext, type ScrollViewSettingsContextType, ScrollViewSettingsProvider, type ScrollViewSettingsProviderProps, SectionList, type SectionListProps, defaultScrollViewSettings, scrollViewActions, scrollViewReducer, useKeyboardInset, useScrollView, useScrollViewSettings };
227
+ export { type ChipProps, CustomList, type CustomListProps, FlatList, type FlatListProps, PullSearch, type PullSearchHandle, type PullSearchProps, ScrollView, ScrollViewContext, type ScrollViewContextType, ScrollViewFooter, type ScrollViewFooterProps, ScrollViewHeader, type ScrollViewHeaderProps, type ScrollViewProps, ScrollViewProvider, type ScrollViewProviderProps, type ScrollViewSettings, ScrollViewSettingsContext, type ScrollViewSettingsContextType, ScrollViewSettingsProvider, type ScrollViewSettingsProviderProps, SectionList, type SectionListProps, defaultScrollViewSettings, scrollViewActions, scrollViewReducer, useKeyboardInset, useScrollView, useScrollViewSettings };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  import * as react from 'react';
2
- import { ComponentType, ReactNode, RefObject } from 'react';
2
+ import { ReactNode, ComponentType, RefObject } from 'react';
3
3
  import { NativeSyntheticEvent, NativeScrollEvent, StyleProp, ViewStyle, FlatListProps as FlatListProps$1, FlatList as FlatList$1, ScrollViewProps as ScrollViewProps$1, ScrollView as ScrollView$1, SectionListProps as SectionListProps$1, SectionList as SectionList$1 } from 'react-native';
4
4
  import { GestureType } from 'react-native-gesture-handler';
5
+ import { ChipProps as ChipProps$1 } from '@rific/auto-paper';
5
6
  import * as redux from 'redux';
6
7
  import * as _reduxjs_toolkit from '@reduxjs/toolkit';
7
8
  import { PayloadAction } from '@reduxjs/toolkit';
8
9
  import * as react_native_reanimated from 'react-native-reanimated';
9
10
  import { SharedValue } from 'react-native-reanimated';
10
11
 
12
+ type ChipProps = Omit<ChipProps$1, 'compact' | 'icon' | 'onPress'> & {
13
+ label?: ReactNode;
14
+ };
15
+
11
16
  type ScrollToOffsetRef = {
12
17
  scrollToOffset: (params: {
13
18
  animated?: boolean;
@@ -15,12 +20,15 @@ type ScrollToOffsetRef = {
15
20
  }) => void;
16
21
  };
17
22
  type CustomListProps<P extends object> = Omit<P, 'contentInset' | 'contentOffset' | 'onScroll' | 'refreshControl' | 'scrollEventThrottle'> & {
23
+ chipProps?: ChipProps;
24
+ chipThreshold?: number;
18
25
  component: ComponentType<P>;
19
26
  renderFilters?: ReactNode;
20
27
  footerFixed?: boolean;
21
28
  gesture?: GestureType;
22
29
  headerFixed?: boolean;
23
30
  keyboardAware?: boolean;
31
+ onChipPress?: () => void;
24
32
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
25
33
  onRefresh?: () => Promise<void> | void;
26
34
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -29,15 +37,18 @@ type CustomListProps<P extends object> = Omit<P, 'contentInset' | 'contentOffset
29
37
  scrollRef?: RefObject<ScrollToOffsetRef | null>;
30
38
  style?: StyleProp<ViewStyle>;
31
39
  };
32
- declare const CustomListInner: <P extends object>({ component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }: CustomListProps<P>) => react.JSX.Element;
40
+ declare const CustomListInner: <P extends object>({ chipProps, chipThreshold, component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }: CustomListProps<P>) => react.JSX.Element;
33
41
  declare const CustomList: typeof CustomListInner;
34
42
 
35
43
  type FlatListProps<T> = Omit<FlatListProps$1<T>, 'onRefresh' | 'refreshing'> & {
44
+ chipProps?: ChipProps;
45
+ chipThreshold?: number;
36
46
  renderFilters?: ReactNode;
37
47
  footerFixed?: boolean;
38
48
  gesture?: GestureType;
39
49
  headerFixed?: boolean;
40
50
  keyboardAware?: boolean;
51
+ onChipPress?: () => void;
41
52
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
42
53
  onRefresh?: () => Promise<void> | void;
43
54
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -45,7 +56,7 @@ type FlatListProps<T> = Omit<FlatListProps$1<T>, 'onRefresh' | 'refreshing'> & {
45
56
  pullSearchHeight?: number;
46
57
  ref?: RefObject<FlatList$1 | null>;
47
58
  };
48
- declare const FlatListInner: <T>({ contentContainerStyle: externalContentContainerStyle, data, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize, ...props }: FlatListProps<T>) => react.JSX.Element;
59
+ declare const FlatListInner: <T>({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize, ...props }: FlatListProps<T>) => react.JSX.Element;
49
60
  declare const FlatList: typeof FlatListInner;
50
61
 
51
62
  type PullSearchHandle = {
@@ -89,10 +100,13 @@ declare const scrollViewActions: _reduxjs_toolkit.CaseReducerActions<{
89
100
  declare const scrollViewReducer: redux.Reducer<ScrollViewSettings>;
90
101
 
91
102
  type ScrollViewProps = ScrollViewProps$1 & {
103
+ chipProps?: ChipProps;
104
+ chipThreshold?: number;
92
105
  footerFixed?: boolean;
93
106
  gesture?: GestureType;
94
107
  headerFixed?: boolean;
95
108
  keyboardAware?: boolean;
109
+ onChipPress?: () => void;
96
110
  onRefresh?: () => void;
97
111
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
98
112
  onScrollEndDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -100,7 +114,7 @@ type ScrollViewProps = ScrollViewProps$1 & {
100
114
  ref?: RefObject<ScrollView$1 | null>;
101
115
  refreshing?: boolean;
102
116
  };
103
- declare const ScrollViewInner: ({ children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }: ScrollViewProps) => react.JSX.Element;
117
+ declare const ScrollViewInner: ({ chipProps, chipThreshold, children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }: ScrollViewProps) => react.JSX.Element;
104
118
  declare const ScrollView: typeof ScrollViewInner;
105
119
 
106
120
  type ScrollViewContextType = {
@@ -167,20 +181,23 @@ declare const ScrollViewProvider: ({ blur, children, fixed, footerFixed, headerF
167
181
  type ScrollViewSettingsProviderProps = {
168
182
  children: ReactNode;
169
183
  onChange?: (settings: ScrollViewSettings) => void;
170
- value?: Partial<ScrollViewSettings>;
184
+ initialValue?: Partial<ScrollViewSettings>;
171
185
  };
172
- declare const ScrollViewSettingsProvider: ({ children, onChange, value }: ScrollViewSettingsProviderProps) => react.JSX.Element;
186
+ declare const ScrollViewSettingsProvider: ({ children, onChange, initialValue }: ScrollViewSettingsProviderProps) => react.JSX.Element;
173
187
 
174
188
  type SectionListProps<ItemT, SectionT extends {
175
189
  data: ReadonlyArray<ItemT>;
176
190
  } = {
177
191
  data: ReadonlyArray<ItemT>;
178
192
  }> = Omit<SectionListProps$1<ItemT, SectionT>, 'horizontal'> & {
193
+ chipProps?: ChipProps;
194
+ chipThreshold?: number;
179
195
  renderFilters?: ReactNode;
180
196
  footerFixed?: boolean;
181
197
  gesture?: GestureType;
182
198
  headerFixed?: boolean;
183
199
  keyboardAware?: boolean;
200
+ onChipPress?: () => void;
184
201
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
185
202
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
186
203
  onScrollEndDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -191,7 +208,7 @@ declare const SectionListInner: <ItemT, SectionT extends {
191
208
  data: ReadonlyArray<ItemT>;
192
209
  } = {
193
210
  data: ReadonlyArray<ItemT>;
194
- }>({ contentContainerStyle: externalContentContainerStyle, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize, ...props }: SectionListProps<ItemT, SectionT>) => react.JSX.Element;
211
+ }>({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender, maxToRenderPerBatch, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize, ...props }: SectionListProps<ItemT, SectionT>) => react.JSX.Element;
195
212
  declare const SectionList: typeof SectionListInner;
196
213
 
197
214
  declare const useKeyboardInset: () => number;
@@ -207,4 +224,4 @@ declare const useScrollView: () => {
207
224
 
208
225
  declare const useScrollViewSettings: () => ScrollViewSettingsContextType;
209
226
 
210
- export { CustomList, type CustomListProps, FlatList, type FlatListProps, PullSearch, type PullSearchHandle, type PullSearchProps, ScrollView, ScrollViewContext, type ScrollViewContextType, ScrollViewFooter, type ScrollViewFooterProps, ScrollViewHeader, type ScrollViewHeaderProps, type ScrollViewProps, ScrollViewProvider, type ScrollViewProviderProps, type ScrollViewSettings, ScrollViewSettingsContext, type ScrollViewSettingsContextType, ScrollViewSettingsProvider, type ScrollViewSettingsProviderProps, SectionList, type SectionListProps, defaultScrollViewSettings, scrollViewActions, scrollViewReducer, useKeyboardInset, useScrollView, useScrollViewSettings };
227
+ export { type ChipProps, CustomList, type CustomListProps, FlatList, type FlatListProps, PullSearch, type PullSearchHandle, type PullSearchProps, ScrollView, ScrollViewContext, type ScrollViewContextType, ScrollViewFooter, type ScrollViewFooterProps, ScrollViewHeader, type ScrollViewHeaderProps, type ScrollViewProps, ScrollViewProvider, type ScrollViewProviderProps, type ScrollViewSettings, ScrollViewSettingsContext, type ScrollViewSettingsContextType, ScrollViewSettingsProvider, type ScrollViewSettingsProviderProps, SectionList, type SectionListProps, defaultScrollViewSettings, scrollViewActions, scrollViewReducer, useKeyboardInset, useScrollView, useScrollViewSettings };
package/dist/index.js CHANGED
@@ -63,11 +63,18 @@ var import_jsx_runtime = require("react/jsx-runtime");
63
63
  var RefreshControl = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.RefreshControl, { refreshing: false, ...props });
64
64
 
65
65
  // src/internal/ScrollViewChip.tsx
66
+ var import_auto_paper = require("@rific/auto-paper");
66
67
  var import_react_native2 = require("react-native");
67
- var import_react_native_paper = require("react-native-paper");
68
68
  var import_react_native_reanimated = __toESM(require("react-native-reanimated"));
69
69
  var import_jsx_runtime2 = require("react/jsx-runtime");
70
- var ScrollViewChip = ({ isHorizontal, onPress, style }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_reanimated.default.View, { style: [styles.chip, style], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_paper.Chip, { compact: true, icon: isHorizontal ? "chevron-left" : "chevron-up", onPress, style: styles.chipInner, children: isHorizontal ? "Start" : "Top" }) });
70
+ var ScrollViewChip = ({ chipProps, isHorizontal, onChipPress, onPress, style }) => {
71
+ const { label, style: chipStyle, ...restChipProps } = chipProps ?? {};
72
+ const handlePress = onChipPress ? () => {
73
+ onPress();
74
+ onChipPress();
75
+ } : onPress;
76
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native_reanimated.default.View, { style: [styles.chip, style], children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_auto_paper.Chip, { compact: true, ...restChipProps, icon: isHorizontal ? "chevron-left" : "chevron-up", onPress: handlePress, style: [styles.chipInner, chipStyle], children: label ?? (isHorizontal ? "Start" : "Top") }) });
77
+ };
71
78
  var styles = import_react_native2.StyleSheet.create({
72
79
  chip: { alignItems: "center", left: 0, position: "absolute", right: 0, zIndex: 3 },
73
80
  chipInner: { elevation: 2, shadowColor: "#000", shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.15, shadowRadius: 2 }
@@ -108,7 +115,7 @@ var ScrollViewContext = (0, import_react.createContext)({
108
115
  });
109
116
 
110
117
  // src/internal/useScrollHandler.ts
111
- function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter }) {
118
+ function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter }) {
112
119
  const { footerHeightShared, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared } = (0, import_react2.useContext)(ScrollViewContext);
113
120
  const snapUpAccum = (0, import_react_native_reanimated2.useSharedValue)(0);
114
121
  const fromBottomBounce = (0, import_react_native_reanimated2.useSharedValue)(false);
@@ -120,12 +127,12 @@ function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal,
120
127
  "worklet";
121
128
  if (isHorizontal) {
122
129
  scrollPosition.value = x;
123
- chipHidden.value = x < 100 ? 1 : 0;
130
+ chipHidden.value = x < chipThreshold ? 1 : 0;
124
131
  return;
125
132
  }
126
133
  const delta = y - scrollPosition.value;
127
134
  scrollPosition.value = y;
128
- chipHidden.value = y < 100 ? 1 : 0;
135
+ chipHidden.value = y < chipThreshold ? 1 : 0;
129
136
  const maxScroll = contentHeight - layoutHeight;
130
137
  if (maxScroll > 0 && y >= maxScroll) {
131
138
  fromBottomBounce.value = true;
@@ -191,7 +198,7 @@ function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal,
191
198
  snapUpAccum.value = 0;
192
199
  }
193
200
  },
194
- [headerFixed, footerFixed, isHorizontal, onPullSearchZoneEnter]
201
+ [headerFixed, footerFixed, isHorizontal, chipThreshold, onPullSearchZoneEnter]
195
202
  );
196
203
  }
197
204
 
@@ -341,7 +348,7 @@ function useScrollInit({ listHeaderComponent, onMomentumScrollEnd: externalMomen
341
348
 
342
349
  // src/CustomList.tsx
343
350
  var import_jsx_runtime3 = require("react/jsx-runtime");
344
- var CustomListInner = ({ component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }) => {
351
+ var CustomListInner = ({ chipProps, chipThreshold, component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }) => {
345
352
  const { ListHeaderComponent: listHeaderComponent, contentContainerStyle: externalContentContainerStyle, ...restProps } = props;
346
353
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
347
354
  const scrollViewInternal = (0, import_react6.useRef)(null);
@@ -384,7 +391,7 @@ var CustomListInner = ({ component: List, renderFilters, footerFixed: footerFixe
384
391
  if (!pullSearchHeight) return;
385
392
  scrollViewInternal.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true });
386
393
  }, [contentInset.top, pullSearchHeight]);
387
- const onScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
394
+ const onScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
388
395
  const handleScrollToTop = (0, import_react6.useCallback)(() => {
389
396
  const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
390
397
  scrollViewInternal.current?.scrollToOffset({ offset, animated: true });
@@ -397,7 +404,7 @@ var CustomListInner = ({ component: List, renderFilters, footerFixed: footerFixe
397
404
  const content = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native4.View, { style: containerStyle, children: [
398
405
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TypedList, { ...restProps, contentContainerStyle, contentInset, contentOffset, ListHeaderComponent: activeListHeader, onMomentumScrollEnd: handleMomentumScrollEnd, onScroll, onScrollBeginDrag: handleScrollBeginDrag, onScrollEndDrag: handleScrollEndDrag, ref: handleRef, refreshControl, scrollEventThrottle: 16 }),
399
406
  hiddenHeader && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native4.View, { pointerEvents: "none", style: styles2.measureContainer, children: hiddenHeader }),
400
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ScrollViewChip, { onPress: handleScrollToTop, style: chipStyle })
407
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle })
401
408
  ] });
402
409
  return detectorGesture ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_gesture_handler.GestureDetector, { gesture: detectorGesture, children: content }) : content;
403
410
  };
@@ -411,10 +418,10 @@ var import_react_native_gesture_handler2 = require("react-native-gesture-handler
411
418
  var import_react_native_reanimated6 = __toESM(require("react-native-reanimated"));
412
419
 
413
420
  // src/internal/HorizontalDots.tsx
414
- var import_auto_paper = require("@rific/auto-paper");
421
+ var import_auto_paper2 = require("@rific/auto-paper");
415
422
  var import_react7 = require("react");
416
423
  var import_react_native5 = require("react-native");
417
- var import_react_native_paper2 = require("react-native-paper");
424
+ var import_react_native_paper = require("react-native-paper");
418
425
  var import_react_native_reanimated5 = __toESM(require("react-native-reanimated"));
419
426
  var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
420
427
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -444,7 +451,7 @@ var HorizontalDots = ({ total }) => {
444
451
  const { blur, footerHeightShared, scrollPosition } = (0, import_react7.useContext)(ScrollViewContext);
445
452
  const { width } = (0, import_react_native5.useWindowDimensions)();
446
453
  const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
447
- const theme = (0, import_react_native_paper2.useTheme)();
454
+ const theme = (0, import_react_native_paper.useTheme)();
448
455
  const insetsBottom = insets.bottom;
449
456
  const activeColor = theme.colors.primary;
450
457
  const inactiveColor = theme.colors.outlineVariant;
@@ -458,7 +465,7 @@ var HorizontalDots = ({ total }) => {
458
465
  return { transform: [{ translateX: -offset }] };
459
466
  });
460
467
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated5.default.View, { pointerEvents: "none", style: [styles3.pillContainer, pillContainerStyle], children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native5.View, { style: styles3.pill, children: [
461
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_auto_paper.BlurView, { blur, style: import_react_native5.StyleSheet.absoluteFill }),
468
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_auto_paper2.BlurView, { blur, style: import_react_native5.StyleSheet.absoluteFill }),
462
469
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native5.View, { style: styles3.dotsClip, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native_reanimated5.default.View, { style: [styles3.dotsRow, rowStyle], children: Array.from({ length: total }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dot, { activeColor, index: i, inactiveColor, pageWidth: width, scrollPosition }, i)) }) })
463
470
  ] }) });
464
471
  };
@@ -479,7 +486,7 @@ var styles3 = import_react_native5.StyleSheet.create({
479
486
 
480
487
  // src/FlatList.tsx
481
488
  var import_jsx_runtime5 = require("react/jsx-runtime");
482
- var FlatListInner = ({ contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }) => {
489
+ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }) => {
483
490
  const scrollView = (0, import_react8.useRef)(null);
484
491
  const isHorizontal = horizontal === true;
485
492
  const showDots = isHorizontal && pagingEnabled === true && (data?.length ?? 0) > 1;
@@ -516,7 +523,7 @@ var FlatListInner = ({ contentContainerStyle: externalContentContainerStyle, dat
516
523
  if (!pullSearchHeight) return;
517
524
  scrollView.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true });
518
525
  }, [contentInset.top, pullSearchHeight]);
519
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
526
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
520
527
  const handleScrollToTop = (0, import_react8.useCallback)(() => {
521
528
  if (isHorizontal) {
522
529
  scrollView.current?.scrollToOffset({ offset: 0, animated: true });
@@ -567,7 +574,7 @@ var FlatListInner = ({ contentContainerStyle: externalContentContainerStyle, dat
567
574
  }
568
575
  ),
569
576
  hiddenHeader && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native6.View, { pointerEvents: "none", style: styles4.measureContainer, children: hiddenHeader }),
570
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ScrollViewChip, { isHorizontal, onPress: handleScrollToTop, style: chipStyle }),
577
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ScrollViewChip, { chipProps, isHorizontal, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
571
578
  showDots && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(HorizontalDots, { total: data?.length ?? 0 })
572
579
  ] });
573
580
  return detectorGesture ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native_gesture_handler2.GestureDetector, { gesture: detectorGesture, children: content }) : content;
@@ -578,12 +585,12 @@ var FlatList = (0, import_react8.memo)(FlatListInner);
578
585
  // src/PullSearch.tsx
579
586
  var import_react9 = require("react");
580
587
  var import_react_native7 = require("react-native");
581
- var import_react_native_paper3 = require("react-native-paper");
588
+ var import_react_native_paper2 = require("react-native-paper");
582
589
  var import_react_native_reanimated7 = __toESM(require("react-native-reanimated"));
583
590
  var import_jsx_runtime6 = require("react/jsx-runtime");
584
591
  var PullSearch = (0, import_react9.forwardRef)(function PullSearch2({ debounce, onChangeText, onHeightChange, placeholder, value: propValue }, ref) {
585
592
  const { headerHeight, scrollPosition } = (0, import_react9.useContext)(ScrollViewContext);
586
- const theme = (0, import_react_native_paper3.useTheme)();
593
+ const theme = (0, import_react_native_paper2.useTheme)();
587
594
  const inputRef = (0, import_react9.useRef)(null);
588
595
  const [barHeight, setBarHeight] = (0, import_react9.useState)(0);
589
596
  const [value, setValue] = (0, import_react9.useState)(propValue ?? "");
@@ -637,7 +644,7 @@ var PullSearch = (0, import_react9.forwardRef)(function PullSearch2({ debounce,
637
644
  const hideY = -headerHeight + barHeight;
638
645
  return { opacity: (0, import_react_native_reanimated7.interpolate)(scrollPosition.value, [showY, hideY], [1, 0], import_react_native_reanimated7.Extrapolation.CLAMP) };
639
646
  }, [barHeight, headerHeight]);
640
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated7.default.View, { onLayout: handleLayout, style: [styles5.container, animatedStyle], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper3.Searchbar, { autoCorrect: false, onChangeText: (text) => setValue((text || "").trimStart()), onClearIconPress: handleClear, placeholder, placeholderTextColor: theme.colors.onSurfaceVariant, ref: inputRef, spellCheck: false, style: styles5.input, value }) });
647
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_reanimated7.default.View, { onLayout: handleLayout, style: [styles5.container, animatedStyle], children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native_paper2.Searchbar, { autoCorrect: false, onChangeText: (text) => setValue((text || "").trimStart()), onClearIconPress: handleClear, placeholder, placeholderTextColor: theme.colors.onSurfaceVariant, ref: inputRef, spellCheck: false, style: styles5.input, value }) });
641
648
  });
642
649
  var styles5 = import_react_native7.StyleSheet.create({
643
650
  container: { paddingVertical: 8 },
@@ -2213,7 +2220,7 @@ var import_react_native8 = require("react-native");
2213
2220
  var import_react_native_gesture_handler3 = require("react-native-gesture-handler");
2214
2221
  var import_react_native_reanimated8 = __toESM(require("react-native-reanimated"));
2215
2222
  var import_jsx_runtime7 = require("react/jsx-runtime");
2216
- var ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }) => {
2223
+ var ScrollViewInner = ({ chipProps, chipThreshold, children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }) => {
2217
2224
  const scrollView = (0, import_react11.useRef)(null);
2218
2225
  const isHorizontal = horizontal === true;
2219
2226
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, isHorizontal, keyboardAware, pullSearchHeight, style });
@@ -2231,7 +2238,7 @@ var ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, header
2231
2238
  if (!pullSearchHeight) return;
2232
2239
  scrollTo(-contentInset.top + pullSearchHeight, true);
2233
2240
  }, [contentInset.top, pullSearchHeight, scrollTo]);
2234
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2241
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2235
2242
  const handleScrollToTop = (0, import_react11.useCallback)(() => {
2236
2243
  if (isHorizontal) {
2237
2244
  scrollView.current?.scrollTo({ x: 0, animated: true });
@@ -2264,14 +2271,14 @@ var ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, header
2264
2271
  children
2265
2272
  }
2266
2273
  ),
2267
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ScrollViewChip, { isHorizontal, onPress: handleScrollToTop, style: chipStyle })
2274
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ScrollViewChip, { chipProps, isHorizontal, onChipPress, onPress: handleScrollToTop, style: chipStyle })
2268
2275
  ] });
2269
2276
  return detectorGesture ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native_gesture_handler3.GestureDetector, { gesture: detectorGesture, children: content }) : content;
2270
2277
  };
2271
2278
  var ScrollView = (0, import_react11.memo)(ScrollViewInner);
2272
2279
 
2273
2280
  // src/ScrollViewFooter.tsx
2274
- var import_auto_paper2 = require("@rific/auto-paper");
2281
+ var import_auto_paper3 = require("@rific/auto-paper");
2275
2282
  var import_react12 = require("react");
2276
2283
  var import_react_native9 = require("react-native");
2277
2284
  var import_react_native_reanimated9 = __toESM(require("react-native-reanimated"));
@@ -2301,7 +2308,7 @@ var ScrollViewFooter = ({ children, style }) => {
2301
2308
  return { transform: [{ translateY: Math.min(effective, footerHeight) }] };
2302
2309
  }, [footerHeight, footerFixed]);
2303
2310
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native_reanimated9.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [styles6.footer, footerStyle], children: [
2304
- footerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper2.BlurView, { blur, style: import_react_native9.StyleSheet.absoluteFill }),
2311
+ footerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_auto_paper3.BlurView, { blur, style: import_react_native9.StyleSheet.absoluteFill }),
2305
2312
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native9.View, { style: [styles6.row, { paddingBottom: insets.bottom }, style], children })
2306
2313
  ] });
2307
2314
  };
@@ -2311,20 +2318,20 @@ var styles6 = import_react_native9.StyleSheet.create({
2311
2318
  });
2312
2319
 
2313
2320
  // src/ScrollViewHeader.tsx
2314
- var import_auto_paper3 = require("@rific/auto-paper");
2321
+ var import_auto_paper4 = require("@rific/auto-paper");
2315
2322
  var import_react13 = require("react");
2316
2323
  var import_react_native10 = require("react-native");
2317
- var import_react_native_paper4 = require("react-native-paper");
2324
+ var import_react_native_paper3 = require("react-native-paper");
2318
2325
  var import_react_native_reanimated10 = __toESM(require("react-native-reanimated"));
2319
2326
  var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
2320
2327
  var import_jsx_runtime9 = require("react/jsx-runtime");
2321
- var ActionBg = ({ blur, style }) => blur ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [import_react_native10.StyleSheet.absoluteFill, styles7.actionBg, style], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper3.BlurView, { blur: true, style: import_react_native10.StyleSheet.absoluteFill }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [import_react_native10.StyleSheet.absoluteFill, styles7.actionBg, style], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper4.Surface, { style: import_react_native10.StyleSheet.absoluteFill, elevation: 1, children: null }) });
2328
+ var ActionBg = ({ blur, style }) => blur ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [import_react_native10.StyleSheet.absoluteFill, styles7.actionBg, style], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper4.BlurView, { blur: true, style: import_react_native10.StyleSheet.absoluteFill }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [import_react_native10.StyleSheet.absoluteFill, styles7.actionBg, style], pointerEvents: "none", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper3.Surface, { style: import_react_native10.StyleSheet.absoluteFill, elevation: 1, children: null }) });
2322
2329
  var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionFixed, caption, centerContent, children, iconSize, style, title, topInset = true, trailingAction, trailingActionFixed = true }) => {
2323
2330
  const { blur, headerHeight, headerFixed, headerOffset, progress, progressing, pullSearchHeightShared, scrollPosition, setHeaderHeight, snapBackHeaderShared } = (0, import_react13.useContext)(ScrollViewContext);
2324
2331
  const { settings } = (0, import_react13.useContext)(ScrollViewSettingsContext);
2325
2332
  const effectiveBackActionFixed = backActionFixed ?? settings.backActionFixed;
2326
2333
  const insets = (0, import_react_native_safe_area_context4.useSafeAreaInsets)();
2327
- const theme = (0, import_react_native_paper4.useTheme)();
2334
+ const theme = (0, import_react_native_paper3.useTheme)();
2328
2335
  const top = topInset ? insets.top : 0;
2329
2336
  const handleLayout = ({
2330
2337
  nativeEvent: {
@@ -2359,7 +2366,7 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionFi
2359
2366
  const leadingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", left: actionMargin, position: "absolute", top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
2360
2367
  const trailingStyle = { alignItems: "center", height: actionSize, justifyContent: "center", position: "absolute", right: actionMargin, top: actionTop, width: actionSize, zIndex: 3, ...actionShadow };
2361
2368
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2362
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_reanimated10.default.View, { pointerEvents: "none", style: [styles7.blur, blurStyle], children: headerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper3.BlurView, { blur, style: [styles7.blurInner, { height: headerHeight }] }) }),
2369
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_reanimated10.default.View, { pointerEvents: "none", style: [styles7.blur, blurStyle], children: headerHeight > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_auto_paper4.BlurView, { blur, style: [styles7.blurInner, { height: headerHeight }] }) }),
2363
2370
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_reanimated10.default.View, { onLayout: handleLayout, pointerEvents: "box-none", style: [headerHeight === 0 ? styles7.headerInit : styles7.header, translateStyle], children: [
2364
2371
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [{ paddingTop: top }, style], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: [styles7.content, { minHeight: contentMinHeight }], children: [
2365
2372
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: styles7.side }),
@@ -2372,13 +2379,13 @@ var ScrollViewHeader = ({ actionSize = 48, actionStyle, backAction, backActionFi
2372
2379
  ] }) }),
2373
2380
  !blur && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native10.View, { style: [styles7.divider, { backgroundColor: theme.colors.outlineVariant }] })
2374
2381
  ] }),
2375
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_reanimated10.default.View, { pointerEvents: "none", style: [styles7.progress, progressStyle], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper4.ProgressBar, { indeterminate: progress === null, visible: progressing, progress: progress ?? void 0 }) }),
2382
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_reanimated10.default.View, { pointerEvents: "none", style: [styles7.progress, progressStyle], children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper3.ProgressBar, { indeterminate: progress === null, visible: progressing, progress: progress ?? void 0 }) }),
2376
2383
  backAction && (effectiveBackActionFixed ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_reanimated10.default.View, { style: leadingStyle, children: [
2377
2384
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ActionBg, { blur, style: actionStyle }),
2378
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper4.Appbar.BackAction, { onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle })
2385
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper3.Appbar.BackAction, { onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle })
2379
2386
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native_reanimated10.default.View, { style: [leadingStyle, translateStyle], children: [
2380
2387
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ActionBg, { blur, style: actionStyle }),
2381
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper4.Appbar.BackAction, { onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle })
2388
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_paper3.Appbar.BackAction, { onPress: backAction, size: iconSize ?? actionSize / 2, style: buttonStyle })
2382
2389
  ] })),
2383
2390
  trailingAction && (trailingActionFixed ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native10.View, { style: trailingStyle, children: [
2384
2391
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ActionBg, { blur, style: actionStyle }),
@@ -2406,14 +2413,14 @@ var styles7 = import_react_native10.StyleSheet.create({
2406
2413
  });
2407
2414
 
2408
2415
  // src/ScrollViewProvider.tsx
2409
- var import_auto_paper4 = require("@rific/auto-paper");
2416
+ var import_auto_paper5 = require("@rific/auto-paper");
2410
2417
  var import_react14 = require("react");
2411
2418
  var import_react_native11 = require("react-native");
2412
2419
  var import_react_native_reanimated11 = require("react-native-reanimated");
2413
2420
  var import_jsx_runtime10 = require("react/jsx-runtime");
2414
2421
  var ScrollViewProvider = ({ blur, children, fixed = false, footerFixed, headerFixed, snapBack, snapBackFooter, snapBackHeader, tabBarHeight = 60 }) => {
2415
2422
  const { settings } = (0, import_react14.useContext)(ScrollViewSettingsContext);
2416
- const effectiveBlur = (0, import_auto_paper4.useBlur)(blur);
2423
+ const effectiveBlur = (0, import_auto_paper5.useBlur)(blur);
2417
2424
  const effectiveSnapBack = snapBack ?? settings.snapBack;
2418
2425
  const effectiveSnapBackHeader = snapBackHeader ?? settings.snapBackHeader;
2419
2426
  const effectiveSnapBackFooter = snapBackFooter ?? settings.snapBackFooter;
@@ -2457,10 +2464,10 @@ var ScrollViewProvider = ({ blur, children, fixed = false, footerFixed, headerFi
2457
2464
  // src/ScrollViewSettingsProvider.tsx
2458
2465
  var import_react15 = require("react");
2459
2466
  var import_jsx_runtime11 = require("react/jsx-runtime");
2460
- var ScrollViewSettingsProvider = ({ children, onChange, value }) => {
2467
+ var ScrollViewSettingsProvider = ({ children, onChange, initialValue }) => {
2461
2468
  const [settings, setSettings] = (0, import_react15.useState)(() => ({
2462
2469
  ...defaultScrollViewSettings,
2463
- ...value
2470
+ ...initialValue
2464
2471
  }));
2465
2472
  const set2 = (0, import_react15.useCallback)(
2466
2473
  (patch) => {
@@ -2594,7 +2601,7 @@ function useStickyHeaders(headerFixed, enabled) {
2594
2601
  // src/SectionList.tsx
2595
2602
  var import_jsx_runtime12 = require("react/jsx-runtime");
2596
2603
  var AnimatedSectionList = (0, import_react_native_reanimated13.createAnimatedComponent)(import_react_native12.SectionList);
2597
- var SectionListInner = ({ contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }) => {
2604
+ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }) => {
2598
2605
  const scrollView = (0, import_react17.useRef)(null);
2599
2606
  const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props;
2600
2607
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed, headerHeight } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
@@ -2669,7 +2676,7 @@ var SectionListInner = ({ contentContainerStyle: externalContentContainerStyle,
2669
2676
  if (!pullSearchHeight) return;
2670
2677
  scrollTo(-contentInset.top + pullSearchHeight, true);
2671
2678
  }, [contentInset.top, pullSearchHeight, scrollTo]);
2672
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2679
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2673
2680
  const handleScrollToTop = (0, import_react17.useCallback)(() => {
2674
2681
  const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
2675
2682
  scrollView.current?.getScrollResponder()?.scrollTo({ y: offset, animated: true });
@@ -2716,7 +2723,7 @@ var SectionListInner = ({ contentContainerStyle: externalContentContainerStyle,
2716
2723
  headerHeight > 0 ? 1 : 0
2717
2724
  ),
2718
2725
  hiddenHeader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.View, { pointerEvents: "none", style: styles8.measureContainer, children: hiddenHeader }),
2719
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollViewChip, { onPress: handleScrollToTop, style: chipStyle }),
2726
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
2720
2727
  usesCustomSticky && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_reanimated13.default.View, { pointerEvents: "none", style: [styles8.stickyClip, clipStyle], children: activeIndex >= 0 && activeIndex < sections.length && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_reanimated13.default.View, { style: [styles8.stickyOverlay, overlayStyle], children: renderSectionHeader({ section: sections[activeIndex] }) }) })
2721
2728
  ] });
2722
2729
  return detectorGesture ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native_gesture_handler4.GestureDetector, { gesture: detectorGesture, children: content }) : content;
package/dist/index.mjs CHANGED
@@ -13,11 +13,18 @@ import { jsx } from "react/jsx-runtime";
13
13
  var RefreshControl = (props) => /* @__PURE__ */ jsx(RNRefreshControl, { refreshing: false, ...props });
14
14
 
15
15
  // src/internal/ScrollViewChip.tsx
16
+ import { Chip } from "@rific/auto-paper";
16
17
  import { StyleSheet } from "react-native";
17
- import { Chip } from "react-native-paper";
18
18
  import Animated from "react-native-reanimated";
19
19
  import { jsx as jsx2 } from "react/jsx-runtime";
20
- var ScrollViewChip = ({ isHorizontal, onPress, style }) => /* @__PURE__ */ jsx2(Animated.View, { style: [styles.chip, style], children: /* @__PURE__ */ jsx2(Chip, { compact: true, icon: isHorizontal ? "chevron-left" : "chevron-up", onPress, style: styles.chipInner, children: isHorizontal ? "Start" : "Top" }) });
20
+ var ScrollViewChip = ({ chipProps, isHorizontal, onChipPress, onPress, style }) => {
21
+ const { label, style: chipStyle, ...restChipProps } = chipProps ?? {};
22
+ const handlePress = onChipPress ? () => {
23
+ onPress();
24
+ onChipPress();
25
+ } : onPress;
26
+ return /* @__PURE__ */ jsx2(Animated.View, { style: [styles.chip, style], children: /* @__PURE__ */ jsx2(Chip, { compact: true, ...restChipProps, icon: isHorizontal ? "chevron-left" : "chevron-up", onPress: handlePress, style: [styles.chipInner, chipStyle], children: label ?? (isHorizontal ? "Start" : "Top") }) });
27
+ };
21
28
  var styles = StyleSheet.create({
22
29
  chip: { alignItems: "center", left: 0, position: "absolute", right: 0, zIndex: 3 },
23
30
  chipInner: { elevation: 2, shadowColor: "#000", shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.15, shadowRadius: 2 }
@@ -58,7 +65,7 @@ var ScrollViewContext = createContext({
58
65
  });
59
66
 
60
67
  // src/internal/useScrollHandler.ts
61
- function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter }) {
68
+ function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter }) {
62
69
  const { footerHeightShared, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared } = useContext(ScrollViewContext);
63
70
  const snapUpAccum = useSharedValue(0);
64
71
  const fromBottomBounce = useSharedValue(false);
@@ -70,12 +77,12 @@ function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal,
70
77
  "worklet";
71
78
  if (isHorizontal) {
72
79
  scrollPosition.value = x;
73
- chipHidden.value = x < 100 ? 1 : 0;
80
+ chipHidden.value = x < chipThreshold ? 1 : 0;
74
81
  return;
75
82
  }
76
83
  const delta = y - scrollPosition.value;
77
84
  scrollPosition.value = y;
78
- chipHidden.value = y < 100 ? 1 : 0;
85
+ chipHidden.value = y < chipThreshold ? 1 : 0;
79
86
  const maxScroll = contentHeight - layoutHeight;
80
87
  if (maxScroll > 0 && y >= maxScroll) {
81
88
  fromBottomBounce.value = true;
@@ -141,7 +148,7 @@ function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal,
141
148
  snapUpAccum.value = 0;
142
149
  }
143
150
  },
144
- [headerFixed, footerFixed, isHorizontal, onPullSearchZoneEnter]
151
+ [headerFixed, footerFixed, isHorizontal, chipThreshold, onPullSearchZoneEnter]
145
152
  );
146
153
  }
147
154
 
@@ -291,7 +298,7 @@ function useScrollInit({ listHeaderComponent, onMomentumScrollEnd: externalMomen
291
298
 
292
299
  // src/CustomList.tsx
293
300
  import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
294
- var CustomListInner = ({ component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }) => {
301
+ var CustomListInner = ({ chipProps, chipThreshold, component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }) => {
295
302
  const { ListHeaderComponent: listHeaderComponent, contentContainerStyle: externalContentContainerStyle, ...restProps } = props;
296
303
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
297
304
  const scrollViewInternal = useRef2(null);
@@ -334,7 +341,7 @@ var CustomListInner = ({ component: List, renderFilters, footerFixed: footerFixe
334
341
  if (!pullSearchHeight) return;
335
342
  scrollViewInternal.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true });
336
343
  }, [contentInset.top, pullSearchHeight]);
337
- const onScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
344
+ const onScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
338
345
  const handleScrollToTop = useCallback2(() => {
339
346
  const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
340
347
  scrollViewInternal.current?.scrollToOffset({ offset, animated: true });
@@ -347,7 +354,7 @@ var CustomListInner = ({ component: List, renderFilters, footerFixed: footerFixe
347
354
  const content = /* @__PURE__ */ jsxs(View, { style: containerStyle, children: [
348
355
  /* @__PURE__ */ jsx3(TypedList, { ...restProps, contentContainerStyle, contentInset, contentOffset, ListHeaderComponent: activeListHeader, onMomentumScrollEnd: handleMomentumScrollEnd, onScroll, onScrollBeginDrag: handleScrollBeginDrag, onScrollEndDrag: handleScrollEndDrag, ref: handleRef, refreshControl, scrollEventThrottle: 16 }),
349
356
  hiddenHeader && /* @__PURE__ */ jsx3(View, { pointerEvents: "none", style: styles2.measureContainer, children: hiddenHeader }),
350
- /* @__PURE__ */ jsx3(ScrollViewChip, { onPress: handleScrollToTop, style: chipStyle })
357
+ /* @__PURE__ */ jsx3(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle })
351
358
  ] });
352
359
  return detectorGesture ? /* @__PURE__ */ jsx3(GestureDetector, { gesture: detectorGesture, children: content }) : content;
353
360
  };
@@ -429,7 +436,7 @@ var styles3 = StyleSheet3.create({
429
436
 
430
437
  // src/FlatList.tsx
431
438
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
432
- var FlatListInner = ({ contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }) => {
439
+ var FlatListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }) => {
433
440
  const scrollView = useRef3(null);
434
441
  const isHorizontal = horizontal === true;
435
442
  const showDots = isHorizontal && pagingEnabled === true && (data?.length ?? 0) > 1;
@@ -466,7 +473,7 @@ var FlatListInner = ({ contentContainerStyle: externalContentContainerStyle, dat
466
473
  if (!pullSearchHeight) return;
467
474
  scrollView.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true });
468
475
  }, [contentInset.top, pullSearchHeight]);
469
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
476
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
470
477
  const handleScrollToTop = useCallback3(() => {
471
478
  if (isHorizontal) {
472
479
  scrollView.current?.scrollToOffset({ offset: 0, animated: true });
@@ -517,7 +524,7 @@ var FlatListInner = ({ contentContainerStyle: externalContentContainerStyle, dat
517
524
  }
518
525
  ),
519
526
  hiddenHeader && /* @__PURE__ */ jsx5(View3, { pointerEvents: "none", style: styles4.measureContainer, children: hiddenHeader }),
520
- /* @__PURE__ */ jsx5(ScrollViewChip, { isHorizontal, onPress: handleScrollToTop, style: chipStyle }),
527
+ /* @__PURE__ */ jsx5(ScrollViewChip, { chipProps, isHorizontal, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
521
528
  showDots && /* @__PURE__ */ jsx5(HorizontalDots, { total: data?.length ?? 0 })
522
529
  ] });
523
530
  return detectorGesture ? /* @__PURE__ */ jsx5(GestureDetector2, { gesture: detectorGesture, children: content }) : content;
@@ -2163,7 +2170,7 @@ import { View as View4 } from "react-native";
2163
2170
  import { Gesture as Gesture3, GestureDetector as GestureDetector3 } from "react-native-gesture-handler";
2164
2171
  import Animated5 from "react-native-reanimated";
2165
2172
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
2166
- var ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }) => {
2173
+ var ScrollViewInner = ({ chipProps, chipThreshold, children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }) => {
2167
2174
  const scrollView = useRef5(null);
2168
2175
  const isHorizontal = horizontal === true;
2169
2176
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, isHorizontal, keyboardAware, pullSearchHeight, style });
@@ -2181,7 +2188,7 @@ var ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, header
2181
2188
  if (!pullSearchHeight) return;
2182
2189
  scrollTo(-contentInset.top + pullSearchHeight, true);
2183
2190
  }, [contentInset.top, pullSearchHeight, scrollTo]);
2184
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2191
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2185
2192
  const handleScrollToTop = useCallback5(() => {
2186
2193
  if (isHorizontal) {
2187
2194
  scrollView.current?.scrollTo({ x: 0, animated: true });
@@ -2214,7 +2221,7 @@ var ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, header
2214
2221
  children
2215
2222
  }
2216
2223
  ),
2217
- /* @__PURE__ */ jsx7(ScrollViewChip, { isHorizontal, onPress: handleScrollToTop, style: chipStyle })
2224
+ /* @__PURE__ */ jsx7(ScrollViewChip, { chipProps, isHorizontal, onChipPress, onPress: handleScrollToTop, style: chipStyle })
2218
2225
  ] });
2219
2226
  return detectorGesture ? /* @__PURE__ */ jsx7(GestureDetector3, { gesture: detectorGesture, children: content }) : content;
2220
2227
  };
@@ -2407,10 +2414,10 @@ var ScrollViewProvider = ({ blur, children, fixed = false, footerFixed, headerFi
2407
2414
  // src/ScrollViewSettingsProvider.tsx
2408
2415
  import { useCallback as useCallback7, useMemo as useMemo6, useState as useState5 } from "react";
2409
2416
  import { jsx as jsx11 } from "react/jsx-runtime";
2410
- var ScrollViewSettingsProvider = ({ children, onChange, value }) => {
2417
+ var ScrollViewSettingsProvider = ({ children, onChange, initialValue }) => {
2411
2418
  const [settings, setSettings] = useState5(() => ({
2412
2419
  ...defaultScrollViewSettings,
2413
- ...value
2420
+ ...initialValue
2414
2421
  }));
2415
2422
  const set2 = useCallback7(
2416
2423
  (patch) => {
@@ -2544,7 +2551,7 @@ function useStickyHeaders(headerFixed, enabled) {
2544
2551
  // src/SectionList.tsx
2545
2552
  import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
2546
2553
  var AnimatedSectionList = createAnimatedComponent(RNSectionList);
2547
- var SectionListInner = ({ contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }) => {
2554
+ var SectionListInner = ({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }) => {
2548
2555
  const scrollView = useRef7(null);
2549
2556
  const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props;
2550
2557
  const { chipHidden, chipStyle, containerStyle, contentInset, contentOffset, footerFixed, headerFixed, headerHeight } = useScrollList({ footerFixed: footerFixedProp, headerFixed: headerFixedProp, keyboardAware, pullSearchHeight, style });
@@ -2619,7 +2626,7 @@ var SectionListInner = ({ contentContainerStyle: externalContentContainerStyle,
2619
2626
  if (!pullSearchHeight) return;
2620
2627
  scrollTo(-contentInset.top + pullSearchHeight, true);
2621
2628
  }, [contentInset.top, pullSearchHeight, scrollTo]);
2622
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2629
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : void 0 });
2623
2630
  const handleScrollToTop = useCallback9(() => {
2624
2631
  const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top;
2625
2632
  scrollView.current?.getScrollResponder()?.scrollTo({ y: offset, animated: true });
@@ -2666,7 +2673,7 @@ var SectionListInner = ({ contentContainerStyle: externalContentContainerStyle,
2666
2673
  headerHeight > 0 ? 1 : 0
2667
2674
  ),
2668
2675
  hiddenHeader && /* @__PURE__ */ jsx12(View7, { pointerEvents: "none", style: styles8.measureContainer, children: hiddenHeader }),
2669
- /* @__PURE__ */ jsx12(ScrollViewChip, { onPress: handleScrollToTop, style: chipStyle }),
2676
+ /* @__PURE__ */ jsx12(ScrollViewChip, { chipProps, onChipPress, onPress: handleScrollToTop, style: chipStyle }),
2670
2677
  usesCustomSticky && /* @__PURE__ */ jsx12(Animated8.View, { pointerEvents: "none", style: [styles8.stickyClip, clipStyle], children: activeIndex >= 0 && activeIndex < sections.length && /* @__PURE__ */ jsx12(Animated8.View, { style: [styles8.stickyOverlay, overlayStyle], children: renderSectionHeader({ section: sections[activeIndex] }) }) })
2671
2678
  ] });
2672
2679
  return detectorGesture ? /* @__PURE__ */ jsx12(GestureDetector4, { gesture: detectorGesture, children: content }) : content;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rific/scroll-view",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Blur styled scroll system for React Native. Floating headers/footers, keyboard awareness, and scroll-away chrome",
5
5
  "keywords": [
6
6
  "react-native",
@@ -3,7 +3,7 @@ import { Dimensions, type NativeScrollEvent, type NativeSyntheticEvent, type Sty
3
3
  import { Gesture, GestureDetector, type GestureType } from 'react-native-gesture-handler'
4
4
 
5
5
  import { RefreshControl } from './internal/RefreshControl'
6
- import { ScrollViewChip } from './internal/ScrollViewChip'
6
+ import { type ChipProps, ScrollViewChip } from './internal/ScrollViewChip'
7
7
  import { useScrollHandler } from './internal/useScrollHandler'
8
8
  import { useScrollList } from './internal/useScrollList'
9
9
  import { useScrollInit } from './useScrollInit'
@@ -11,12 +11,15 @@ import { useScrollInit } from './useScrollInit'
11
11
  type ScrollToOffsetRef = { scrollToOffset: (params: { animated?: boolean; offset: number }) => void }
12
12
 
13
13
  export type CustomListProps<P extends object> = Omit<P, 'contentInset' | 'contentOffset' | 'onScroll' | 'refreshControl' | 'scrollEventThrottle'> & {
14
+ chipProps?: ChipProps
15
+ chipThreshold?: number
14
16
  component: ComponentType<P>
15
17
  renderFilters?: ReactNode
16
18
  footerFixed?: boolean
17
19
  gesture?: GestureType
18
20
  headerFixed?: boolean
19
21
  keyboardAware?: boolean
22
+ onChipPress?: () => void
20
23
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
21
24
  onRefresh?: () => Promise<void> | void
22
25
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
@@ -26,7 +29,7 @@ export type CustomListProps<P extends object> = Omit<P, 'contentInset' | 'conten
26
29
  style?: StyleProp<ViewStyle>
27
30
  }
28
31
 
29
- const CustomListInner = <P extends object>({ component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }: CustomListProps<P>) => {
32
+ const CustomListInner = <P extends object>({ chipProps, chipThreshold, component: List, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, scrollRef, style, ...props }: CustomListProps<P>) => {
30
33
  // Intercept ListHeaderComponent so useScrollInit can apply the same 2-phase measurement as FlatList.
31
34
  const { ListHeaderComponent: listHeaderComponent, contentContainerStyle: externalContentContainerStyle, ...restProps } = props as Record<string, unknown>
32
35
 
@@ -81,7 +84,7 @@ const CustomListInner = <P extends object>({ component: List, renderFilters, foo
81
84
  scrollViewInternal.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true })
82
85
  }, [contentInset.top, pullSearchHeight])
83
86
 
84
- const onScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
87
+ const onScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
85
88
 
86
89
  const handleScrollToTop = useCallback(() => {
87
90
  const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top
@@ -116,7 +119,7 @@ const CustomListInner = <P extends object>({ component: List, renderFilters, foo
116
119
  {hiddenHeader}
117
120
  </View>
118
121
  )}
119
- <ScrollViewChip onPress={handleScrollToTop} style={chipStyle} />
122
+ <ScrollViewChip chipProps={chipProps} onChipPress={onChipPress} onPress={handleScrollToTop} style={chipStyle} />
120
123
  </View>
121
124
  )
122
125
  return detectorGesture ? <GestureDetector gesture={detectorGesture}>{content}</GestureDetector> : content
package/src/FlatList.tsx CHANGED
@@ -5,17 +5,20 @@ import Animated from 'react-native-reanimated'
5
5
 
6
6
  import { HorizontalDots } from './internal/HorizontalDots'
7
7
  import { RefreshControl } from './internal/RefreshControl'
8
- import { ScrollViewChip } from './internal/ScrollViewChip'
8
+ import { type ChipProps, ScrollViewChip } from './internal/ScrollViewChip'
9
9
  import { useScrollHandler } from './internal/useScrollHandler'
10
10
  import { useScrollList } from './internal/useScrollList'
11
11
  import { useScrollInit } from './useScrollInit'
12
12
 
13
13
  export type FlatListProps<T> = Omit<RNFlatListProps<T>, 'onRefresh' | 'refreshing'> & {
14
+ chipProps?: ChipProps
15
+ chipThreshold?: number
14
16
  renderFilters?: ReactNode
15
17
  footerFixed?: boolean
16
18
  gesture?: GestureType
17
19
  headerFixed?: boolean
18
20
  keyboardAware?: boolean
21
+ onChipPress?: () => void
19
22
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
20
23
  onRefresh?: () => Promise<void> | void
21
24
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
@@ -24,7 +27,7 @@ export type FlatListProps<T> = Omit<RNFlatListProps<T>, 'onRefresh' | 'refreshin
24
27
  ref?: RefObject<RNFlatList | null>
25
28
  }
26
29
 
27
- const FlatListInner = <T,>({ contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }: FlatListProps<T>) => {
30
+ const FlatListInner = <T,>({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, data, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pagingEnabled, pullSearchHeight, removeClippedSubviews = false, showsHorizontalScrollIndicator, showsVerticalScrollIndicator, style, onContentSizeChange, ref: externalRef, windowSize = 100, ...props }: FlatListProps<T>) => {
28
31
  const scrollView = useRef<RNFlatList>(null)
29
32
  const isHorizontal = horizontal === true
30
33
  const showDots = isHorizontal && pagingEnabled === true && (data?.length ?? 0) > 1
@@ -70,7 +73,7 @@ const FlatListInner = <T,>({ contentContainerStyle: externalContentContainerStyl
70
73
  scrollView.current?.scrollToOffset({ offset: -contentInset.top + pullSearchHeight, animated: true })
71
74
  }, [contentInset.top, pullSearchHeight])
72
75
 
73
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
76
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
74
77
 
75
78
  const handleScrollToTop = useCallback(() => {
76
79
  if (isHorizontal) {
@@ -127,7 +130,7 @@ const FlatListInner = <T,>({ contentContainerStyle: externalContentContainerStyl
127
130
  {hiddenHeader}
128
131
  </View>
129
132
  )}
130
- <ScrollViewChip isHorizontal={isHorizontal} onPress={handleScrollToTop} style={chipStyle} />
133
+ <ScrollViewChip chipProps={chipProps} isHorizontal={isHorizontal} onChipPress={onChipPress} onPress={handleScrollToTop} style={chipStyle} />
131
134
  {showDots && <HorizontalDots total={data?.length ?? 0} />}
132
135
  </View>
133
136
  )
@@ -4,16 +4,19 @@ import { Gesture, GestureDetector, type GestureType } from 'react-native-gesture
4
4
  import Animated from 'react-native-reanimated'
5
5
 
6
6
  import { RefreshControl } from './internal/RefreshControl'
7
- import { ScrollViewChip } from './internal/ScrollViewChip'
7
+ import { type ChipProps, ScrollViewChip } from './internal/ScrollViewChip'
8
8
  import { useScrollHandler } from './internal/useScrollHandler'
9
9
  import { useScrollList } from './internal/useScrollList'
10
10
  import { useScrollInit } from './useScrollInit'
11
11
 
12
12
  export type ScrollViewProps = RNScrollViewProps & {
13
+ chipProps?: ChipProps
14
+ chipThreshold?: number
13
15
  footerFixed?: boolean
14
16
  gesture?: GestureType
15
17
  headerFixed?: boolean
16
18
  keyboardAware?: boolean
19
+ onChipPress?: () => void
17
20
  onRefresh?: () => void
18
21
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
19
22
  onScrollEndDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
@@ -22,7 +25,7 @@ export type ScrollViewProps = RNScrollViewProps & {
22
25
  refreshing?: boolean
23
26
  }
24
27
 
25
- const ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }: ScrollViewProps) => {
28
+ const ScrollViewInner = ({ chipProps, chipThreshold, children, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, horizontal, keyboardAware, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, style, ...props }: ScrollViewProps) => {
26
29
  const scrollView = useRef<RNScrollView>(null)
27
30
  const isHorizontal = horizontal === true
28
31
 
@@ -45,7 +48,7 @@ const ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, head
45
48
  scrollTo(-contentInset.top + pullSearchHeight, true)
46
49
  }, [contentInset.top, pullSearchHeight, scrollTo])
47
50
 
48
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
51
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
49
52
 
50
53
  const handleScrollToTop = useCallback(() => {
51
54
  if (isHorizontal) {
@@ -80,7 +83,7 @@ const ScrollViewInner = ({ children, footerFixed: footerFixedProp, gesture, head
80
83
  >
81
84
  {children}
82
85
  </Animated.ScrollView>
83
- <ScrollViewChip isHorizontal={isHorizontal} onPress={handleScrollToTop} style={chipStyle} />
86
+ <ScrollViewChip chipProps={chipProps} isHorizontal={isHorizontal} onChipPress={onChipPress} onPress={handleScrollToTop} style={chipStyle} />
84
87
  </View>
85
88
  )
86
89
  return detectorGesture ? <GestureDetector gesture={detectorGesture}>{content}</GestureDetector> : content
@@ -5,13 +5,13 @@ import { defaultScrollViewSettings, type ScrollViewSettings, ScrollViewSettingsC
5
5
  export type ScrollViewSettingsProviderProps = {
6
6
  children: ReactNode
7
7
  onChange?: (settings: ScrollViewSettings) => void
8
- value?: Partial<ScrollViewSettings>
8
+ initialValue?: Partial<ScrollViewSettings>
9
9
  }
10
10
 
11
- export const ScrollViewSettingsProvider = ({ children, onChange, value }: ScrollViewSettingsProviderProps) => {
11
+ export const ScrollViewSettingsProvider = ({ children, onChange, initialValue }: ScrollViewSettingsProviderProps) => {
12
12
  const [settings, setSettings] = useState<ScrollViewSettings>(() => ({
13
13
  ...defaultScrollViewSettings,
14
- ...value
14
+ ...initialValue
15
15
  }))
16
16
 
17
17
  const set = useCallback(
@@ -4,7 +4,7 @@ import { Gesture, GestureDetector, type GestureType } from 'react-native-gesture
4
4
  import Animated, { createAnimatedComponent } from 'react-native-reanimated'
5
5
 
6
6
  import { RefreshControl } from './internal/RefreshControl'
7
- import { ScrollViewChip } from './internal/ScrollViewChip'
7
+ import { type ChipProps, ScrollViewChip } from './internal/ScrollViewChip'
8
8
  import { useScrollHandler } from './internal/useScrollHandler'
9
9
  import { useScrollList } from './internal/useScrollList'
10
10
  import { useStickyHeaders } from './internal/useStickyHeaders'
@@ -13,11 +13,14 @@ import { useScrollInit } from './useScrollInit'
13
13
  const AnimatedSectionList = createAnimatedComponent(RNSectionList) as unknown as typeof RNSectionList
14
14
 
15
15
  export type SectionListProps<ItemT, SectionT extends { data: ReadonlyArray<ItemT> } = { data: ReadonlyArray<ItemT> }> = Omit<RNSectionListProps<ItemT, SectionT>, 'horizontal'> & {
16
+ chipProps?: ChipProps
17
+ chipThreshold?: number
16
18
  renderFilters?: ReactNode
17
19
  footerFixed?: boolean
18
20
  gesture?: GestureType
19
21
  headerFixed?: boolean
20
22
  keyboardAware?: boolean
23
+ onChipPress?: () => void
21
24
  onMomentumScrollEnd?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
22
25
  onScrollBeginDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
23
26
  onScrollEndDrag?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void
@@ -25,7 +28,7 @@ export type SectionListProps<ItemT, SectionT extends { data: ReadonlyArray<ItemT
25
28
  ref?: RefObject<RNSectionList<ItemT, SectionT> | null>
26
29
  }
27
30
 
28
- const SectionListInner = <ItemT, SectionT extends { data: ReadonlyArray<ItemT> } = { data: ReadonlyArray<ItemT> }>({ contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }: SectionListProps<ItemT, SectionT>) => {
31
+ const SectionListInner = <ItemT, SectionT extends { data: ReadonlyArray<ItemT> } = { data: ReadonlyArray<ItemT> }>({ chipProps, chipThreshold, contentContainerStyle: externalContentContainerStyle, initialNumToRender = 20, maxToRenderPerBatch = 50, renderFilters, footerFixed: footerFixedProp, gesture, headerFixed: headerFixedProp, keyboardAware, ListHeaderComponent: externalListHeaderComponent, onChipPress, onMomentumScrollEnd: externalMomentumScrollEnd, onRefresh, onContentSizeChange, onScrollBeginDrag: externalScrollBeginDrag, onScrollEndDrag: externalScrollEndDrag, pullSearchHeight, refreshing, removeClippedSubviews = false, sections, showsVerticalScrollIndicator, style, ref: externalRef, windowSize = 100, ...props }: SectionListProps<ItemT, SectionT>) => {
29
32
  const scrollView = useRef<RNSectionList<ItemT, SectionT>>(null)
30
33
 
31
34
  const { stickySectionHeadersEnabled = true, renderSectionHeader, ...passThroughProps } = props as RNSectionListProps<ItemT, SectionT>
@@ -122,7 +125,7 @@ const SectionListInner = <ItemT, SectionT extends { data: ReadonlyArray<ItemT> }
122
125
  scrollTo(-contentInset.top + pullSearchHeight, true)
123
126
  }, [contentInset.top, pullSearchHeight, scrollTo])
124
127
 
125
- const handleScroll = useScrollHandler({ chipHidden, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
128
+ const handleScroll = useScrollHandler({ chipHidden, chipThreshold, footerFixed, headerFixed, onPullSearchZoneEnter: pullSearchHeight ? onPullSearchZoneEnter : undefined })
126
129
 
127
130
  const handleScrollToTop = useCallback(() => {
128
131
  const offset = pullSearchHeight ? -contentInset.top + pullSearchHeight : -contentInset.top
@@ -175,7 +178,7 @@ const SectionListInner = <ItemT, SectionT extends { data: ReadonlyArray<ItemT> }
175
178
  {hiddenHeader}
176
179
  </View>
177
180
  )}
178
- <ScrollViewChip onPress={handleScrollToTop} style={chipStyle} />
181
+ <ScrollViewChip chipProps={chipProps} onChipPress={onChipPress} onPress={handleScrollToTop} style={chipStyle} />
179
182
  {usesCustomSticky && (
180
183
  <Animated.View pointerEvents='none' style={[styles.stickyClip, clipStyle]}>
181
184
  {activeIndex >= 0 && activeIndex < sections.length && <Animated.View style={[styles.stickyOverlay, overlayStyle]}>{renderSectionHeader({ section: sections[activeIndex] })}</Animated.View>}
@@ -3,6 +3,7 @@ import React from 'react'
3
3
  const stub = ({ children }: { children?: React.ReactNode }) => children ?? null
4
4
 
5
5
  export const BlurView = jest.fn(stub)
6
+ export const Chip = jest.fn(stub)
6
7
  export const FAB = jest.fn(stub)
7
8
  export const usePaperDefaults = () => ({ FAB: {} })
8
9
  export const useBlur = (blur?: boolean) => blur ?? false
@@ -1,4 +1,4 @@
1
- import { render } from '@testing-library/react'
1
+ import { act, render } from '@testing-library/react'
2
2
  import React, { useContext } from 'react'
3
3
 
4
4
  import { ScrollViewContext } from '../ScrollViewContext'
@@ -54,7 +54,7 @@ describe('ScrollViewProvider', () => {
54
54
  <ContextReader onRead={(v) => { capturedValue = v }} />
55
55
  </ScrollViewProvider>
56
56
  )
57
- capturedValue?.setProgress(0.5)
57
+ act(() => { capturedValue?.setProgress(0.5) })
58
58
  rerender(
59
59
  <ScrollViewProvider>
60
60
  <ContextReader onRead={(v) => { capturedValue = v }} />
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export type { CustomListProps } from './CustomList'
2
2
  export { CustomList } from './CustomList'
3
3
  export type { FlatListProps } from './FlatList'
4
4
  export { FlatList } from './FlatList'
5
+ export type { ChipProps } from './internal/ScrollViewChip'
5
6
  export type { PullSearchHandle, PullSearchProps } from './PullSearch'
6
7
  export { PullSearch } from './PullSearch'
7
8
  export { scrollViewActions, scrollViewReducer } from './redux/scrollViewSlice'
@@ -1,20 +1,36 @@
1
+ import { Chip, type ChipProps as AutoPaperChipProps } from '@rific/auto-paper'
2
+ import { type ReactNode } from 'react'
1
3
  import { StyleSheet, type ViewStyle } from 'react-native'
2
- import { Chip } from 'react-native-paper'
3
4
  import Animated, { type AnimatedStyle } from 'react-native-reanimated'
4
5
 
6
+ export type ChipProps = Omit<AutoPaperChipProps, 'compact' | 'icon' | 'onPress'> & {
7
+ label?: ReactNode
8
+ }
9
+
5
10
  type Props = {
11
+ chipProps?: ChipProps
6
12
  isHorizontal?: boolean
13
+ onChipPress?: () => void
7
14
  onPress: () => void
8
15
  style: AnimatedStyle<ViewStyle>
9
16
  }
10
17
 
11
- export const ScrollViewChip = ({ isHorizontal, onPress, style }: Props) => (
12
- <Animated.View style={[styles.chip, style]}>
13
- <Chip compact icon={isHorizontal ? 'chevron-left' : 'chevron-up'} onPress={onPress} style={styles.chipInner}>
14
- {isHorizontal ? 'Start' : 'Top'}
15
- </Chip>
16
- </Animated.View>
17
- )
18
+ export const ScrollViewChip = ({ chipProps, isHorizontal, onChipPress, onPress, style }: Props) => {
19
+ const { label, style: chipStyle, ...restChipProps } = (chipProps ?? {}) as Partial<ChipProps>
20
+ const handlePress = onChipPress
21
+ ? () => {
22
+ onPress()
23
+ onChipPress()
24
+ }
25
+ : onPress
26
+ return (
27
+ <Animated.View style={[styles.chip, style]}>
28
+ <Chip compact {...restChipProps} icon={isHorizontal ? 'chevron-left' : 'chevron-up'} onPress={handlePress} style={[styles.chipInner, chipStyle]}>
29
+ {label ?? (isHorizontal ? 'Start' : 'Top')}
30
+ </Chip>
31
+ </Animated.View>
32
+ )
33
+ }
18
34
 
19
35
  const styles = StyleSheet.create({
20
36
  chip: { alignItems: 'center', left: 0, position: 'absolute', right: 0, zIndex: 3 },
@@ -6,13 +6,14 @@ import { ScrollViewContext } from '../ScrollViewContext'
6
6
 
7
7
  type UseScrollHandlerOptions = {
8
8
  chipHidden: SharedValue<number>
9
+ chipThreshold?: number
9
10
  footerFixed: boolean
10
11
  headerFixed: boolean
11
12
  isHorizontal?: boolean
12
13
  onPullSearchZoneEnter?: () => void
13
14
  }
14
15
 
15
- export function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter }: UseScrollHandlerOptions) {
16
+ export function useScrollHandler({ chipHidden, chipThreshold = 100, footerFixed, headerFixed, isHorizontal, onPullSearchZoneEnter }: UseScrollHandlerOptions) {
16
17
  const { footerHeightShared, footerOffset, headerHeightShared, headerOffset, pullSearchHeightShared, scrollPosition, snapBackFooterShared, snapBackHeaderShared } = useContext(ScrollViewContext)
17
18
  const snapUpAccum = useSharedValue(0)
18
19
  const fromBottomBounce = useSharedValue(false)
@@ -25,12 +26,12 @@ export function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHoriz
25
26
  'worklet'
26
27
  if (isHorizontal) {
27
28
  scrollPosition.value = x
28
- chipHidden.value = x < 100 ? 1 : 0
29
+ chipHidden.value = x < chipThreshold ? 1 : 0
29
30
  return
30
31
  }
31
32
  const delta = y - scrollPosition.value
32
33
  scrollPosition.value = y
33
- chipHidden.value = y < 100 ? 1 : 0
34
+ chipHidden.value = y < chipThreshold ? 1 : 0
34
35
  const maxScroll = contentHeight - layoutHeight
35
36
  if (maxScroll > 0 && y >= maxScroll) {
36
37
  fromBottomBounce.value = true
@@ -96,6 +97,6 @@ export function useScrollHandler({ chipHidden, footerFixed, headerFixed, isHoriz
96
97
  snapUpAccum.value = 0
97
98
  }
98
99
  },
99
- [headerFixed, footerFixed, isHorizontal, onPullSearchZoneEnter]
100
+ [headerFixed, footerFixed, isHorizontal, chipThreshold, onPullSearchZoneEnter]
100
101
  )
101
102
  }