Skip to content

Commit d6a167b

Browse files
committed
feat: overload goToPage, nextPage and prevPage functions with aditional animated and align options
1 parent 0cb45ed commit d6a167b

File tree

3 files changed

+93
-31
lines changed

3 files changed

+93
-31
lines changed

example/examples/AdvancedFlatListPaginationExample.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useRef } from 'react';
22
import { FlatList, StyleSheet, Text, View } from 'react-native';
33
import { Button, ListItem } from '../src/components';
44
import { useList } from 'react-native-use-list';
5+
import { Alignments } from '../../src/types';
56

67
const DATA = [
78
{
@@ -73,10 +74,16 @@ export const AdvancedFlatListPaginationExample = () => {
7374
<Button text="<" onPress={prevPage} />
7475
<Button
7576
text="Random"
76-
onPress={() => goToPage(Math.floor(Math.random() * DATA.length))}
77+
onPress={() =>
78+
goToPage({
79+
index: Math.floor(Math.random() * DATA.length),
80+
animated: true,
81+
align: Alignments.CENTER,
82+
})
83+
}
7784
/>
7885
<Text style={styles.footerIndex}>{pageIndex}</Text>
79-
<Button text=">" onPress={nextPage} />
86+
<Button text=">" onPress={() => nextPage({ align: Alignments.END })} />
8087
</View>
8188
</>
8289
);

src/types.ts

+17
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,20 @@ export type Options = {
1010
loopPages?: boolean;
1111
debugMode?: boolean;
1212
};
13+
14+
export enum Alignments {
15+
START = 0,
16+
CENTER = 0.5,
17+
END = 1,
18+
}
19+
20+
export type ScrollToIndexOptions = {
21+
index: number;
22+
animated?: boolean;
23+
align?: Alignments;
24+
};
25+
26+
export type ScrollToPageOptions = {
27+
animated?: boolean;
28+
align?: Alignments;
29+
};

src/usePagination.tsx

+67-29
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,52 @@
1+
/* eslint-disable @typescript-eslint/no-shadow */
12
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';
39
import { isSectionList, isVirtualizedList } from './utils';
410
import type { SectionList } from 'react-native';
511
import type { VirtualizedList } from 'react-native';
612
import type { ViewToken } from 'react-native';
713
import type { ViewabilityConfig } from 'react-native';
814

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+
}
931
export function usePagination(listRef: List, options: Options) {
1032
const [pageIndex, setPageIndex] = useState(0);
1133
const [sectionItemIndex, setSectionItemIndex] = useState(0);
1234
const [sectionIndex, setSectionIndex] = useState(0);
1335

14-
const scrollToIndex = (index: number) => {
15-
if (!listRef?.current) return;
36+
function scrollToIndex(index: number): void;
37+
function scrollToIndex(options: ScrollToIndexOptions): void;
1638

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;
3041

42+
const dataCount = getDataCountFromRef(listRef);
3143
if (options.debugMode && dataCount === 0)
3244
return console.warn('Pagination does not work on empty lists.');
3345

46+
let index: number;
47+
if (typeof params === 'number') index = params;
48+
else index = params.index;
49+
3450
if (index < 0 || index >= dataCount) {
3551
if (options.loopPages) {
3652
index = (index + dataCount) % dataCount; // loop around
@@ -45,7 +61,13 @@ export function usePagination(listRef: List, options: Options) {
4561

4662
if ('scrollToIndex' in listRef.current) {
4763
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+
});
4971
return;
5072
}
5173

@@ -77,26 +99,42 @@ export function usePagination(listRef: List, options: Options) {
7799
setSectionIndex(sectionIndex);
78100
return;
79101
}
80-
};
102+
}
81103

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+
}
88123

89124
const viewabilityConfig = useRef<ViewabilityConfig>({
90125
itemVisiblePercentThreshold: 50,
91126
waitForInteraction: true,
92127
}).current;
93128

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;
97133

98-
return listRef.current.props.sections.indexOf(section) === sectionIndex;
99-
};
134+
return listRef.current.props.sections.indexOf(section) === sectionIndex;
135+
},
136+
[listRef, sectionIndex]
137+
);
100138

101139
const onViewableItemsChanged = useCallback(
102140
({ viewableItems }: { viewableItems: ViewToken[] }) => {

0 commit comments

Comments
 (0)