1
+ /* eslint-disable @typescript-eslint/no-shadow */
1
2
import { useCallback , useRef , useState } from 'react' ;
2
- import type { List , Options } from './types' ;
3
+ import type {
4
+ List ,
5
+ Options ,
6
+ ScrollToIndexOptions ,
7
+ ScrollToPageOptions ,
8
+ } from './types' ;
3
9
import { isSectionList , isVirtualizedList } from './utils' ;
4
10
import type { SectionList } from 'react-native' ;
5
11
import type { VirtualizedList } from 'react-native' ;
6
12
import type { ViewToken } from 'react-native' ;
7
13
import type { ViewabilityConfig } from 'react-native' ;
8
14
15
+ function getDataCountFromRef ( listRef : List ) : number {
16
+ if ( ! listRef . current ) return 0 ;
17
+
18
+ if ( isVirtualizedList ( listRef ) )
19
+ return (
20
+ ( listRef . current as VirtualizedList < any > ) . props . getItemCount ?.( null ) || 0
21
+ ) ;
22
+
23
+ if ( isSectionList ( listRef ) )
24
+ return ( listRef . current as SectionList ) . props . sections . reduce (
25
+ ( count , item ) => count + item . data . length ,
26
+ 0
27
+ ) ;
28
+
29
+ return listRef . current . props . data ?. length || 0 ;
30
+ }
9
31
export function usePagination ( listRef : List , options : Options ) {
10
32
const [ pageIndex , setPageIndex ] = useState ( 0 ) ;
11
33
const [ sectionItemIndex , setSectionItemIndex ] = useState ( 0 ) ;
12
34
const [ sectionIndex , setSectionIndex ] = useState ( 0 ) ;
13
35
14
- const scrollToIndex = ( index : number ) => {
15
- if ( ! listRef ?. current ) return ;
36
+ function scrollToIndex ( index : number ) : void ;
37
+ function scrollToIndex ( options : ScrollToIndexOptions ) : void ;
16
38
17
- let dataCount = 0 ;
18
- if ( isVirtualizedList ( listRef ) ) {
19
- dataCount =
20
- ( listRef . current as VirtualizedList < any > ) . props . getItemCount ?.( null ) ||
21
- 0 ;
22
- } else if ( isSectionList ( listRef ) ) {
23
- dataCount = ( listRef . current as SectionList ) . props . sections . reduce (
24
- ( count , item ) => count + item . data . length ,
25
- 0
26
- ) ;
27
- } else {
28
- dataCount = listRef . current . props . data ?. length || 0 ;
29
- }
39
+ function scrollToIndex ( params : number | ScrollToIndexOptions ) {
40
+ if ( ! listRef ?. current ) return ;
30
41
42
+ const dataCount = getDataCountFromRef ( listRef ) ;
31
43
if ( options . debugMode && dataCount === 0 )
32
44
return console . warn ( 'Pagination does not work on empty lists.' ) ;
33
45
46
+ let index : number ;
47
+ if ( typeof params === 'number' ) index = params ;
48
+ else index = params . index ;
49
+
34
50
if ( index < 0 || index >= dataCount ) {
35
51
if ( options . loopPages ) {
36
52
index = ( index + dataCount ) % dataCount ; // loop around
@@ -45,7 +61,13 @@ export function usePagination(listRef: List, options: Options) {
45
61
46
62
if ( 'scrollToIndex' in listRef . current ) {
47
63
setPageIndex ( index ) ;
48
- listRef . current . scrollToIndex ( { index } ) ;
64
+ if ( typeof params === 'number' ) listRef . current . scrollToIndex ( { index } ) ;
65
+ else
66
+ listRef . current . scrollToIndex ( {
67
+ index,
68
+ animated : params . animated ,
69
+ viewPosition : params . align ,
70
+ } ) ;
49
71
return ;
50
72
}
51
73
@@ -77,26 +99,42 @@ export function usePagination(listRef: List, options: Options) {
77
99
setSectionIndex ( sectionIndex ) ;
78
100
return ;
79
101
}
80
- } ;
102
+ }
81
103
82
- const nextPage = ( ) => {
83
- scrollToIndex ( pageIndex + 1 ) ;
84
- } ;
85
- const prevPage = ( ) => {
86
- scrollToIndex ( pageIndex - 1 ) ;
87
- } ;
104
+ function nextPage ( ) : void ;
105
+ function nextPage ( options : ScrollToPageOptions ) : void ;
106
+
107
+ function nextPage ( options ?: ScrollToPageOptions ) {
108
+ scrollToIndex ( {
109
+ index : pageIndex + 1 ,
110
+ ...options ,
111
+ } ) ;
112
+ }
113
+
114
+ function prevPage ( ) : void ;
115
+ function prevPage ( options : ScrollToPageOptions ) : void ;
116
+
117
+ function prevPage ( options ?: ScrollToPageOptions ) {
118
+ scrollToIndex ( {
119
+ index : pageIndex - 1 ,
120
+ ...options ,
121
+ } ) ;
122
+ }
88
123
89
124
const viewabilityConfig = useRef < ViewabilityConfig > ( {
90
125
itemVisiblePercentThreshold : 50 ,
91
126
waitForInteraction : true ,
92
127
} ) . current ;
93
128
94
- const isSectionSelected = ( section : any ) : boolean => {
95
- if ( ! listRef ?. current ) return false ;
96
- if ( ! ( 'sections' in listRef . current . props ) ) return false ;
129
+ const isSectionSelected = useCallback (
130
+ ( section : any ) : boolean => {
131
+ if ( ! listRef ?. current ) return false ;
132
+ if ( ! ( 'sections' in listRef . current . props ) ) return false ;
97
133
98
- return listRef . current . props . sections . indexOf ( section ) === sectionIndex ;
99
- } ;
134
+ return listRef . current . props . sections . indexOf ( section ) === sectionIndex ;
135
+ } ,
136
+ [ listRef , sectionIndex ]
137
+ ) ;
100
138
101
139
const onViewableItemsChanged = useCallback (
102
140
( { viewableItems } : { viewableItems : ViewToken [ ] } ) => {
0 commit comments