1 | import * as React from 'react';
|
2 | import {
|
3 | StyleSheet,
|
4 | StyleProp,
|
5 | View,
|
6 | ViewStyle,
|
7 | I18nManager,
|
8 | } from 'react-native';
|
9 | import color from 'color';
|
10 | import IconButton from '../IconButton';
|
11 | import Text from '../Typography/Text';
|
12 | import { withTheme, useTheme } from '../../core/theming';
|
13 | import MaterialCommunityIcon from '../MaterialCommunityIcon';
|
14 | import Menu from '../Menu/Menu';
|
15 | import Button from '../Button';
|
16 |
|
17 | type Props = React.ComponentPropsWithRef<typeof View> &
|
18 | PaginationControlsProps &
|
19 | PaginationDropdownProps & {
|
20 | |
21 |
|
22 |
|
23 | label?: React.ReactNode;
|
24 | |
25 |
|
26 |
|
27 | accessibilityLabel?: string;
|
28 | |
29 |
|
30 |
|
31 | selectPageDropdownLabel?: React.ReactNode;
|
32 | |
33 |
|
34 |
|
35 | selectPageDropdownAccessibilityLabel?: string;
|
36 | style?: StyleProp<ViewStyle>;
|
37 | |
38 |
|
39 |
|
40 | theme: ReactNativePaper.Theme;
|
41 | };
|
42 |
|
43 | type PaginationDropdownProps = {
|
44 | |
45 |
|
46 |
|
47 | numberOfItemsPerPage?: number;
|
48 | |
49 |
|
50 |
|
51 | numberOfItemsPerPageList?: Array<number>;
|
52 | |
53 |
|
54 |
|
55 | onItemsPerPageChange?: (numberOfItemsPerPage: number) => void;
|
56 | };
|
57 |
|
58 | type PaginationControlsProps = {
|
59 | |
60 |
|
61 |
|
62 | page: number;
|
63 | |
64 |
|
65 |
|
66 | numberOfPages: number;
|
67 | |
68 |
|
69 |
|
70 | onPageChange: (page: number) => void;
|
71 | |
72 |
|
73 |
|
74 | showFastPaginationControls?: boolean;
|
75 | };
|
76 |
|
77 | const PaginationControls = ({
|
78 | page,
|
79 | numberOfPages,
|
80 | onPageChange,
|
81 | showFastPaginationControls,
|
82 | }: PaginationControlsProps) => {
|
83 | const { colors } = useTheme();
|
84 | return (
|
85 | <>
|
86 | {showFastPaginationControls ? (
|
87 | <IconButton
|
88 | icon={({ size, color }) => (
|
89 | <MaterialCommunityIcon
|
90 | name="page-first"
|
91 | color={color}
|
92 | size={size}
|
93 | direction={I18nManager.isRTL ? 'rtl' : 'ltr'}
|
94 | />
|
95 | )}
|
96 | color={colors.text}
|
97 | disabled={page === 0}
|
98 | onPress={() => onPageChange(0)}
|
99 | accessibilityLabel="page-first"
|
100 | />
|
101 | ) : null}
|
102 | <IconButton
|
103 | icon={({ size, color }) => (
|
104 | <MaterialCommunityIcon
|
105 | name="chevron-left"
|
106 | color={color}
|
107 | size={size}
|
108 | direction={I18nManager.isRTL ? 'rtl' : 'ltr'}
|
109 | />
|
110 | )}
|
111 | color={colors.text}
|
112 | disabled={page === 0}
|
113 | onPress={() => onPageChange(page - 1)}
|
114 | accessibilityLabel="chevron-left"
|
115 | />
|
116 | <IconButton
|
117 | icon={({ size, color }) => (
|
118 | <MaterialCommunityIcon
|
119 | name="chevron-right"
|
120 | color={color}
|
121 | size={size}
|
122 | direction={I18nManager.isRTL ? 'rtl' : 'ltr'}
|
123 | />
|
124 | )}
|
125 | color={colors.text}
|
126 | disabled={numberOfPages === 0 || page === numberOfPages - 1}
|
127 | onPress={() => onPageChange(page + 1)}
|
128 | accessibilityLabel="chevron-right"
|
129 | />
|
130 | {showFastPaginationControls ? (
|
131 | <IconButton
|
132 | icon={({ size, color }) => (
|
133 | <MaterialCommunityIcon
|
134 | name="page-last"
|
135 | color={color}
|
136 | size={size}
|
137 | direction={I18nManager.isRTL ? 'rtl' : 'ltr'}
|
138 | />
|
139 | )}
|
140 | color={colors.text}
|
141 | disabled={numberOfPages === 0 || page === numberOfPages - 1}
|
142 | onPress={() => onPageChange(numberOfPages - 1)}
|
143 | accessibilityLabel="page-last"
|
144 | />
|
145 | ) : null}
|
146 | </>
|
147 | );
|
148 | };
|
149 |
|
150 | const PaginationDropdown = ({
|
151 | numberOfItemsPerPageList,
|
152 | numberOfItemsPerPage,
|
153 | onItemsPerPageChange,
|
154 | }: PaginationDropdownProps) => {
|
155 | const { colors } = useTheme();
|
156 | const [showSelect, toggleSelect] = React.useState<boolean>(false);
|
157 |
|
158 | return (
|
159 | <Menu
|
160 | visible={showSelect}
|
161 | onDismiss={() => toggleSelect(!showSelect)}
|
162 | anchor={
|
163 | <Button
|
164 | mode="outlined"
|
165 | onPress={() => toggleSelect(true)}
|
166 | style={styles.button}
|
167 | icon="menu-down"
|
168 | contentStyle={styles.contentStyle}
|
169 | >
|
170 | {`${numberOfItemsPerPage}`}
|
171 | </Button>
|
172 | }
|
173 | >
|
174 | {numberOfItemsPerPageList?.map((option) => (
|
175 | <Menu.Item
|
176 | key={option}
|
177 | titleStyle={
|
178 | option === numberOfItemsPerPage && {
|
179 | color: colors.primary,
|
180 | }
|
181 | }
|
182 | onPress={() => {
|
183 | onItemsPerPageChange?.(option);
|
184 | toggleSelect(false);
|
185 | }}
|
186 | title={option}
|
187 | />
|
188 | ))}
|
189 | </Menu>
|
190 | );
|
191 | };
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 | const DataTablePagination = ({
|
256 | label,
|
257 | accessibilityLabel,
|
258 | page,
|
259 | numberOfPages,
|
260 | onPageChange,
|
261 | style,
|
262 | theme,
|
263 | showFastPaginationControls = false,
|
264 | numberOfItemsPerPageList,
|
265 | numberOfItemsPerPage,
|
266 | onItemsPerPageChange,
|
267 | selectPageDropdownLabel,
|
268 | selectPageDropdownAccessibilityLabel,
|
269 | ...rest
|
270 | }: Props) => {
|
271 | const labelColor = color(theme.colors.text).alpha(0.6).rgb().string();
|
272 |
|
273 | return (
|
274 | <View
|
275 | {...rest}
|
276 | style={[styles.container, style]}
|
277 | accessibilityLabel="pagination-container"
|
278 | >
|
279 | {numberOfItemsPerPageList &&
|
280 | numberOfItemsPerPage &&
|
281 | onItemsPerPageChange && (
|
282 | <View
|
283 | accessibilityLabel="Options Select"
|
284 | style={styles.optionsContainer}
|
285 | >
|
286 | <Text
|
287 | style={[styles.label, { color: labelColor }]}
|
288 | numberOfLines={3}
|
289 | accessibilityLabel={
|
290 | selectPageDropdownAccessibilityLabel ||
|
291 | 'selectPageDropdownLabel'
|
292 | }
|
293 | >
|
294 | {selectPageDropdownLabel}
|
295 | </Text>
|
296 | <PaginationDropdown
|
297 | numberOfItemsPerPageList={numberOfItemsPerPageList}
|
298 | numberOfItemsPerPage={numberOfItemsPerPage}
|
299 | onItemsPerPageChange={onItemsPerPageChange}
|
300 | />
|
301 | </View>
|
302 | )}
|
303 | <Text
|
304 | style={[styles.label, { color: labelColor }]}
|
305 | numberOfLines={3}
|
306 | accessibilityLabel={accessibilityLabel || 'label'}
|
307 | >
|
308 | {label}
|
309 | </Text>
|
310 | <View style={styles.iconsContainer}>
|
311 | <PaginationControls
|
312 | showFastPaginationControls={showFastPaginationControls}
|
313 | onPageChange={onPageChange}
|
314 | page={page}
|
315 | numberOfPages={numberOfPages}
|
316 | />
|
317 | </View>
|
318 | </View>
|
319 | );
|
320 | };
|
321 |
|
322 | DataTablePagination.displayName = 'DataTable.Pagination';
|
323 |
|
324 | const styles = StyleSheet.create({
|
325 | container: {
|
326 | justifyContent: 'flex-end',
|
327 | flexDirection: 'row',
|
328 | alignItems: 'center',
|
329 | paddingLeft: 16,
|
330 | flexWrap: 'wrap',
|
331 | },
|
332 | optionsContainer: {
|
333 | flexDirection: 'row',
|
334 | alignItems: 'center',
|
335 | marginVertical: 6,
|
336 | },
|
337 | label: {
|
338 | fontSize: 12,
|
339 | marginRight: 16,
|
340 | },
|
341 | button: {
|
342 | textAlign: 'center',
|
343 | marginRight: 16,
|
344 | },
|
345 | iconsContainer: {
|
346 | flexDirection: 'row',
|
347 | },
|
348 | contentStyle: {
|
349 | flexDirection: 'row-reverse',
|
350 | },
|
351 | });
|
352 |
|
353 | export default withTheme(DataTablePagination);
|
354 |
|
355 |
|
356 | export { DataTablePagination };
|