@automattic/vip-design-system 2.16.1 → 2.17.1
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/build/system/NewForm/FormSelect.d.ts +1 -0
- package/build/system/NewForm/FormSelect.js +8 -3
- package/build/system/NewForm/FormSelectArrow.d.ts +1 -0
- package/build/system/NewForm/FormSelectArrow.js +17 -14
- package/build/system/Pagination/Pagination.d.ts +23 -0
- package/build/system/Pagination/Pagination.js +256 -0
- package/build/system/Pagination/Pagination.stories.d.ts +19 -0
- package/build/system/Pagination/Pagination.stories.js +236 -0
- package/build/system/Pagination/Pagination.test.d.ts +2 -0
- package/build/system/Pagination/Pagination.test.js +425 -0
- package/build/system/Pagination/index.d.ts +2 -0
- package/build/system/Pagination/index.js +1 -0
- package/build/system/Pagination/styles.d.ts +9 -0
- package/build/system/Pagination/styles.js +96 -0
- package/build/system/index.d.ts +2 -1
- package/build/system/index.js +2 -0
- package/package.json +1 -1
- package/src/system/NewForm/FormSelect.tsx +8 -2
- package/src/system/NewForm/FormSelectArrow.tsx +24 -19
- package/src/system/Pagination/Pagination.stories.tsx +210 -0
- package/src/system/Pagination/Pagination.test.tsx +324 -0
- package/src/system/Pagination/Pagination.tsx +306 -0
- package/src/system/Pagination/index.ts +2 -0
- package/src/system/Pagination/styles.ts +106 -0
- package/src/system/index.js +2 -0
|
@@ -17,6 +17,7 @@ interface FormSelectProps {
|
|
|
17
17
|
options: Option[];
|
|
18
18
|
required?: boolean;
|
|
19
19
|
label?: string;
|
|
20
|
+
separator?: boolean;
|
|
20
21
|
getOptionLabel?: (option: Option) => string;
|
|
21
22
|
getOptionValue?: (option: Option) => string | number;
|
|
22
23
|
onChange?: (option: Option | undefined, event: React.ChangeEvent<HTMLSelectElement>) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _excluded = ["disabled", "isInline", "placeholder", "forLabel", "options", "required", "label", "getOptionLabel", "getOptionValue", "onChange", "hasError", "errorMessage", "wrapperSx"],
|
|
1
|
+
var _excluded = ["disabled", "isInline", "placeholder", "forLabel", "options", "required", "label", "getOptionLabel", "getOptionValue", "onChange", "hasError", "errorMessage", "wrapperSx", "separator"],
|
|
2
2
|
_excluded2 = ["options"];
|
|
3
3
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
4
4
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
@@ -63,6 +63,8 @@ var FormSelect = /*#__PURE__*/React.forwardRef(function (_ref2, forwardRef) {
|
|
|
63
63
|
hasError = _ref2.hasError,
|
|
64
64
|
errorMessage = _ref2.errorMessage,
|
|
65
65
|
wrapperSx = _ref2.wrapperSx,
|
|
66
|
+
_ref2$separator = _ref2.separator,
|
|
67
|
+
separator = _ref2$separator === void 0 ? true : _ref2$separator,
|
|
66
68
|
props = _objectWithoutPropertiesLoose(_ref2, _excluded);
|
|
67
69
|
if (isDev && options.length > MAX_SUGGESTED_OPTIONS) {
|
|
68
70
|
// eslint-disable-next-line no-console
|
|
@@ -112,7 +114,9 @@ var FormSelect = /*#__PURE__*/React.forwardRef(function (_ref2, forwardRef) {
|
|
|
112
114
|
ref: forwardRef,
|
|
113
115
|
sx: _extends({
|
|
114
116
|
cursor: disabled ? 'not-allowed' : 'pointer'
|
|
115
|
-
}, defaultStyles
|
|
117
|
+
}, defaultStyles, !separator && {
|
|
118
|
+
paddingRight: 6
|
|
119
|
+
}),
|
|
116
120
|
required: required,
|
|
117
121
|
disabled: disabled,
|
|
118
122
|
"aria-required": required,
|
|
@@ -127,7 +131,8 @@ var FormSelect = /*#__PURE__*/React.forwardRef(function (_ref2, forwardRef) {
|
|
|
127
131
|
return groupOptions ? renderGroup(optionLabel(option), groupOptions) : renderOption(optionLabel(option), optionValue(option));
|
|
128
132
|
})]
|
|
129
133
|
})), _jsx(FormSelectArrow, {
|
|
130
|
-
iconSize: ICON_SIZE
|
|
134
|
+
iconSize: ICON_SIZE,
|
|
135
|
+
separator: separator
|
|
131
136
|
})]
|
|
132
137
|
}), hasError && errorMessage && _jsx(Validation, {
|
|
133
138
|
isValid: false,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _excluded = ["iconSize"];
|
|
1
|
+
var _excluded = ["iconSize", "separator"];
|
|
2
2
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
3
3
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
4
4
|
/** @jsxImportSource theme-ui */
|
|
@@ -13,23 +13,26 @@ import { MdExpandMore } from 'react-icons/md';
|
|
|
13
13
|
*/
|
|
14
14
|
import { baseControlBorderStyle as borderStyle } from '../Form/Input.styles';
|
|
15
15
|
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
16
|
-
var arrowStyles = {
|
|
17
|
-
position: 'absolute',
|
|
18
|
-
paddingLeft: 2,
|
|
19
|
-
borderLeftWidth: borderStyle.borderWidth,
|
|
20
|
-
borderLeftStyle: borderStyle.borderStyle,
|
|
21
|
-
borderLeftColor: borderStyle.borderColor,
|
|
22
|
-
right: 3,
|
|
23
|
-
top: '7px',
|
|
24
|
-
pointerEvents: 'none',
|
|
25
|
-
svg: {
|
|
26
|
-
fill: borderStyle.borderColor
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
16
|
export var FormSelectArrow = /*#__PURE__*/React.forwardRef(function (_ref, forwardRef) {
|
|
30
17
|
var _ref$iconSize = _ref.iconSize,
|
|
31
18
|
iconSize = _ref$iconSize === void 0 ? 24 : _ref$iconSize,
|
|
19
|
+
_ref$separator = _ref.separator,
|
|
20
|
+
separator = _ref$separator === void 0 ? true : _ref$separator,
|
|
32
21
|
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
22
|
+
var arrowStyles = _extends({
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
right: 3,
|
|
25
|
+
top: '7px',
|
|
26
|
+
pointerEvents: 'none',
|
|
27
|
+
svg: {
|
|
28
|
+
fill: borderStyle.borderColor
|
|
29
|
+
}
|
|
30
|
+
}, separator && {
|
|
31
|
+
paddingLeft: 2,
|
|
32
|
+
borderLeftWidth: borderStyle.borderWidth,
|
|
33
|
+
borderLeftStyle: borderStyle.borderStyle,
|
|
34
|
+
borderLeftColor: borderStyle.borderColor
|
|
35
|
+
});
|
|
33
36
|
return _jsx("div", {
|
|
34
37
|
ref: forwardRef,
|
|
35
38
|
children: _jsx(MdExpandMore, _extends({
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
/// <reference types="react" />
|
|
3
|
+
import { ThemeUIStyleObject } from 'theme-ui';
|
|
4
|
+
export type PaginationVariant = 'full' | 'compact';
|
|
5
|
+
export interface PaginationProps {
|
|
6
|
+
displayItemsPerPageSelector?: boolean;
|
|
7
|
+
currentPage: number;
|
|
8
|
+
totalItems?: number;
|
|
9
|
+
totalPages?: number;
|
|
10
|
+
itemsPerPage: number;
|
|
11
|
+
onPageChange: (page: number) => void;
|
|
12
|
+
onItemsPerPageChange: (itemsPerPage: number) => void;
|
|
13
|
+
hasNextPage?: boolean;
|
|
14
|
+
maxReachablePage?: number;
|
|
15
|
+
variant?: PaginationVariant;
|
|
16
|
+
pageSizeOptions?: number[];
|
|
17
|
+
className?: string;
|
|
18
|
+
sx?: ThemeUIStyleObject;
|
|
19
|
+
children?: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export type PageNumberItem = number | 'ellipsis';
|
|
22
|
+
export declare function getPageNumbers(currentPage: number, totalPages?: number, hasNextPage?: boolean, maxReachablePage?: number): PageNumberItem[];
|
|
23
|
+
export declare const Pagination: import("react").ForwardRefExoticComponent<PaginationProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
var _excluded = ["displayItemsPerPageSelector", "currentPage", "totalItems", "totalPages", "itemsPerPage", "onPageChange", "onItemsPerPageChange", "hasNextPage", "maxReachablePage", "variant", "pageSizeOptions", "className", "sx", "children"];
|
|
2
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
3
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
4
|
+
/** @jsxImportSource theme-ui */
|
|
5
|
+
|
|
6
|
+
import classNames from 'classnames';
|
|
7
|
+
import { forwardRef } from 'react';
|
|
8
|
+
import { BiDotsHorizontalRounded } from 'react-icons/bi';
|
|
9
|
+
import { MdChevronLeft, MdChevronRight } from 'react-icons/md';
|
|
10
|
+
import { Flex } from 'theme-ui';
|
|
11
|
+
import { containerStyles, navigationStyles, pageButtonStyles, activePageButtonStyles, arrowButtonStyles, compactTextStyles } from './styles';
|
|
12
|
+
import { Box } from '../Box';
|
|
13
|
+
import { Button } from '../Button';
|
|
14
|
+
import { Select } from '../NewForm';
|
|
15
|
+
import { Text } from '../Text';
|
|
16
|
+
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
17
|
+
import { Fragment as _Fragment } from "theme-ui/jsx-runtime";
|
|
18
|
+
import { jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
19
|
+
function range(start, end) {
|
|
20
|
+
return Array.from({
|
|
21
|
+
length: end - start + 1
|
|
22
|
+
}, function (_, i) {
|
|
23
|
+
return start + i;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Total number of visible items (page numbers + ellipsis indicators) in the pagination bar. */
|
|
28
|
+
var VISIBLE_PAGE_SLOTS = 8;
|
|
29
|
+
|
|
30
|
+
/** When currentPage <= this value, the "near start" layout is used (no leading ellipsis). */
|
|
31
|
+
var NEAR_START_THRESHOLD = 5;
|
|
32
|
+
|
|
33
|
+
/** Pages shown before the current page in the middle layout. */
|
|
34
|
+
var PAGES_BEFORE_CURRENT = 1;
|
|
35
|
+
|
|
36
|
+
/** Pages shown after the current page in the bounded middle layout. */
|
|
37
|
+
var PAGES_AFTER_CURRENT = 2;
|
|
38
|
+
export function getPageNumbers(currentPage, totalPages, hasNextPage, maxReachablePage) {
|
|
39
|
+
var _last;
|
|
40
|
+
// Resolve the last known page
|
|
41
|
+
var last;
|
|
42
|
+
if (totalPages !== undefined) {
|
|
43
|
+
last = Math.max(1, Number(totalPages));
|
|
44
|
+
} else if (hasNextPage === false) {
|
|
45
|
+
last = currentPage;
|
|
46
|
+
}
|
|
47
|
+
if (last !== undefined && (!Number.isFinite(last) || last < 1)) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Effective end anchor: known last page, or capped reachable page
|
|
52
|
+
var end = (_last = last) != null ? _last : maxReachablePage !== undefined ? Math.max(currentPage, maxReachablePage) : undefined;
|
|
53
|
+
|
|
54
|
+
// Small page count — show all without ellipsis
|
|
55
|
+
if (end !== undefined && end <= VISIBLE_PAGE_SLOTS) {
|
|
56
|
+
return range(1, end);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Near start
|
|
60
|
+
if (currentPage <= NEAR_START_THRESHOLD) {
|
|
61
|
+
if (end !== undefined) return [].concat(range(1, NEAR_START_THRESHOLD + 1), ['ellipsis', end]);
|
|
62
|
+
return [].concat(range(1, VISIBLE_PAGE_SLOTS - 1), ['ellipsis']);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Near end (bounded only — open-ended has no "end zone")
|
|
66
|
+
if (last !== undefined && currentPage >= last - (NEAR_START_THRESHOLD - 1)) {
|
|
67
|
+
return [1, 'ellipsis'].concat(range(last - NEAR_START_THRESHOLD, last));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Middle
|
|
71
|
+
if (end !== undefined) {
|
|
72
|
+
var rangeEnd = Math.min(currentPage + PAGES_AFTER_CURRENT, end);
|
|
73
|
+
var middle = range(currentPage - PAGES_BEFORE_CURRENT, rangeEnd);
|
|
74
|
+
if (rangeEnd >= end) return [1, 'ellipsis'].concat(middle);
|
|
75
|
+
return [1, 'ellipsis'].concat(middle, ['ellipsis', end]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Fully open-ended middle
|
|
79
|
+
return [1, 'ellipsis'].concat(range(currentPage - PAGES_BEFORE_CURRENT, currentPage + PAGES_AFTER_CURRENT + 1), ['ellipsis']);
|
|
80
|
+
}
|
|
81
|
+
var ItemsPerPageSelect = function ItemsPerPageSelect(_ref) {
|
|
82
|
+
var itemsPerPage = _ref.itemsPerPage,
|
|
83
|
+
pageSizeOptions = _ref.pageSizeOptions,
|
|
84
|
+
onItemsPerPageChange = _ref.onItemsPerPageChange;
|
|
85
|
+
return _jsx(Select, {
|
|
86
|
+
id: "items-per-page",
|
|
87
|
+
"aria-label": "Items per page",
|
|
88
|
+
separator: false,
|
|
89
|
+
value: itemsPerPage,
|
|
90
|
+
options: pageSizeOptions.map(function (size) {
|
|
91
|
+
return {
|
|
92
|
+
value: size,
|
|
93
|
+
label: size.toString() + " / page"
|
|
94
|
+
};
|
|
95
|
+
}),
|
|
96
|
+
onChange: function onChange(option) {
|
|
97
|
+
return onItemsPerPageChange(Number(option == null ? void 0 : option.value));
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
var PageNumbers = function PageNumbers(_ref2) {
|
|
102
|
+
var currentPage = _ref2.currentPage,
|
|
103
|
+
totalPages = _ref2.totalPages,
|
|
104
|
+
hasNextPage = _ref2.hasNextPage,
|
|
105
|
+
maxReachablePage = _ref2.maxReachablePage,
|
|
106
|
+
onPageChange = _ref2.onPageChange;
|
|
107
|
+
var pages = getPageNumbers(currentPage, totalPages, hasNextPage, maxReachablePage);
|
|
108
|
+
return _jsx(_Fragment, {
|
|
109
|
+
children: pages.map(function (page, index) {
|
|
110
|
+
if (page === 'ellipsis') {
|
|
111
|
+
return _jsx(BiDotsHorizontalRounded, {}, "ellipsis-" + index);
|
|
112
|
+
}
|
|
113
|
+
var isActive = page === currentPage;
|
|
114
|
+
return _jsx(Button, {
|
|
115
|
+
type: "button",
|
|
116
|
+
onClick: function onClick() {
|
|
117
|
+
return onPageChange(page);
|
|
118
|
+
},
|
|
119
|
+
"aria-label": "Go to page " + page,
|
|
120
|
+
"aria-current": isActive ? 'page' : undefined,
|
|
121
|
+
sx: isActive ? activePageButtonStyles : pageButtonStyles,
|
|
122
|
+
children: page
|
|
123
|
+
}, page);
|
|
124
|
+
})
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
var CompactPageSelector = function CompactPageSelector(_ref3) {
|
|
128
|
+
var currentPage = _ref3.currentPage,
|
|
129
|
+
totalPages = _ref3.totalPages,
|
|
130
|
+
maxReachablePage = _ref3.maxReachablePage,
|
|
131
|
+
onPageChange = _ref3.onPageChange;
|
|
132
|
+
var isOpenEnded = totalPages === undefined;
|
|
133
|
+
var upperBound = isOpenEnded ? maxReachablePage != null ? maxReachablePage : currentPage + 1 : totalPages;
|
|
134
|
+
var pageOptions = Array.from({
|
|
135
|
+
length: upperBound
|
|
136
|
+
}, function (_, i) {
|
|
137
|
+
return i + 1;
|
|
138
|
+
});
|
|
139
|
+
return _jsxs(Flex, {
|
|
140
|
+
sx: compactTextStyles,
|
|
141
|
+
children: [_jsx(Text, {
|
|
142
|
+
as: "span",
|
|
143
|
+
sx: {
|
|
144
|
+
fontSize: 2,
|
|
145
|
+
color: 'heading',
|
|
146
|
+
mb: 0
|
|
147
|
+
},
|
|
148
|
+
children: "Page"
|
|
149
|
+
}), _jsx(Select, {
|
|
150
|
+
id: "page",
|
|
151
|
+
"aria-label": "Page",
|
|
152
|
+
separator: false,
|
|
153
|
+
value: currentPage,
|
|
154
|
+
onChange: function onChange(option) {
|
|
155
|
+
return onPageChange(Number(option == null ? void 0 : option.value));
|
|
156
|
+
},
|
|
157
|
+
options: pageOptions.map(function (page) {
|
|
158
|
+
return {
|
|
159
|
+
value: page,
|
|
160
|
+
label: page.toString()
|
|
161
|
+
};
|
|
162
|
+
}),
|
|
163
|
+
sx: {
|
|
164
|
+
minWidth: '70px',
|
|
165
|
+
mx: 1
|
|
166
|
+
}
|
|
167
|
+
}), !isOpenEnded && _jsxs(Text, {
|
|
168
|
+
as: "span",
|
|
169
|
+
sx: {
|
|
170
|
+
fontSize: 2,
|
|
171
|
+
color: 'heading',
|
|
172
|
+
mb: 0
|
|
173
|
+
},
|
|
174
|
+
children: ["of ", totalPages]
|
|
175
|
+
})]
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
export var Pagination = /*#__PURE__*/forwardRef(function (_ref4, ref) {
|
|
179
|
+
var _ref4$displayItemsPer = _ref4.displayItemsPerPageSelector,
|
|
180
|
+
displayItemsPerPageSelector = _ref4$displayItemsPer === void 0 ? false : _ref4$displayItemsPer,
|
|
181
|
+
currentPage = _ref4.currentPage,
|
|
182
|
+
totalItems = _ref4.totalItems,
|
|
183
|
+
totalPages = _ref4.totalPages,
|
|
184
|
+
itemsPerPage = _ref4.itemsPerPage,
|
|
185
|
+
onPageChange = _ref4.onPageChange,
|
|
186
|
+
onItemsPerPageChange = _ref4.onItemsPerPageChange,
|
|
187
|
+
hasNextPage = _ref4.hasNextPage,
|
|
188
|
+
maxReachablePage = _ref4.maxReachablePage,
|
|
189
|
+
_ref4$variant = _ref4.variant,
|
|
190
|
+
variant = _ref4$variant === void 0 ? 'full' : _ref4$variant,
|
|
191
|
+
_ref4$pageSizeOptions = _ref4.pageSizeOptions,
|
|
192
|
+
pageSizeOptions = _ref4$pageSizeOptions === void 0 ? [20, 50, 100] : _ref4$pageSizeOptions,
|
|
193
|
+
className = _ref4.className,
|
|
194
|
+
sx = _ref4.sx,
|
|
195
|
+
children = _ref4.children,
|
|
196
|
+
rest = _objectWithoutPropertiesLoose(_ref4, _excluded);
|
|
197
|
+
var resolvedTotalPages = totalPages != null ? totalPages : totalItems !== undefined ? Math.ceil(totalItems / itemsPerPage) : undefined;
|
|
198
|
+
var isFirstPage = currentPage <= 1;
|
|
199
|
+
var isLastPage = resolvedTotalPages !== undefined ? currentPage >= resolvedTotalPages : hasNextPage === false;
|
|
200
|
+
return _jsxs("nav", _extends({
|
|
201
|
+
ref: ref,
|
|
202
|
+
"aria-label": "Pagination",
|
|
203
|
+
className: classNames('vip-pagination-component', className),
|
|
204
|
+
sx: _extends({}, containerStyles, sx)
|
|
205
|
+
}, rest, {
|
|
206
|
+
children: [_jsx(Box, {
|
|
207
|
+
children: displayItemsPerPageSelector && _jsx(ItemsPerPageSelect, {
|
|
208
|
+
itemsPerPage: itemsPerPage,
|
|
209
|
+
pageSizeOptions: pageSizeOptions,
|
|
210
|
+
onItemsPerPageChange: onItemsPerPageChange
|
|
211
|
+
})
|
|
212
|
+
}), _jsx(Box, {
|
|
213
|
+
sx: {
|
|
214
|
+
flex: 1
|
|
215
|
+
},
|
|
216
|
+
children: children
|
|
217
|
+
}), _jsxs(Flex, {
|
|
218
|
+
sx: navigationStyles,
|
|
219
|
+
children: [variant === 'full' && _jsx(PageNumbers, {
|
|
220
|
+
currentPage: currentPage,
|
|
221
|
+
totalPages: resolvedTotalPages,
|
|
222
|
+
hasNextPage: hasNextPage,
|
|
223
|
+
maxReachablePage: maxReachablePage,
|
|
224
|
+
onPageChange: onPageChange
|
|
225
|
+
}), variant === 'compact' && _jsx(CompactPageSelector, {
|
|
226
|
+
currentPage: currentPage,
|
|
227
|
+
totalPages: resolvedTotalPages,
|
|
228
|
+
maxReachablePage: maxReachablePage,
|
|
229
|
+
onPageChange: onPageChange
|
|
230
|
+
}), _jsx(Button, {
|
|
231
|
+
"aria-label": "Previous page",
|
|
232
|
+
disabled: isFirstPage,
|
|
233
|
+
onClick: function onClick() {
|
|
234
|
+
return onPageChange(currentPage - 1);
|
|
235
|
+
},
|
|
236
|
+
sx: _extends({}, arrowButtonStyles, {
|
|
237
|
+
ml: 4
|
|
238
|
+
}),
|
|
239
|
+
children: _jsx(MdChevronLeft, {
|
|
240
|
+
size: 20
|
|
241
|
+
})
|
|
242
|
+
}), _jsx(Button, {
|
|
243
|
+
"aria-label": "Next page",
|
|
244
|
+
disabled: isLastPage,
|
|
245
|
+
onClick: function onClick() {
|
|
246
|
+
return onPageChange(currentPage + 1);
|
|
247
|
+
},
|
|
248
|
+
sx: arrowButtonStyles,
|
|
249
|
+
children: _jsx(MdChevronRight, {
|
|
250
|
+
size: 20
|
|
251
|
+
})
|
|
252
|
+
})]
|
|
253
|
+
})]
|
|
254
|
+
}));
|
|
255
|
+
});
|
|
256
|
+
Pagination.displayName = 'Pagination';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
/**
|
|
3
|
+
* Internal dependencies
|
|
4
|
+
*/
|
|
5
|
+
import { Pagination } from './Pagination';
|
|
6
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
7
|
+
declare const meta: Meta<typeof Pagination>;
|
|
8
|
+
export default meta;
|
|
9
|
+
type Story = StoryObj<typeof Pagination>;
|
|
10
|
+
export declare const Default: Story;
|
|
11
|
+
export declare const Compact: Story;
|
|
12
|
+
export declare const FewPages: Story;
|
|
13
|
+
export declare const MiddlePage: Story;
|
|
14
|
+
export declare const CustomPageSizes: Story;
|
|
15
|
+
export declare const WithItemsPerPageSelector: Story;
|
|
16
|
+
export declare const OpenEndedCursorBased: Story;
|
|
17
|
+
export declare const OpenEnded: Story;
|
|
18
|
+
export declare const OpenEndedCompact: Story;
|
|
19
|
+
export declare const OpenEndedLastPage: Story;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
var _excluded = ["initialPage", "totalItems", "initialItemsPerPage", "displayItemsPerPageSelector"],
|
|
2
|
+
_excluded2 = ["initialPage", "initialItemsPerPage", "hasNextPage"];
|
|
3
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
4
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
5
|
+
/** @jsxImportSource theme-ui */
|
|
6
|
+
|
|
7
|
+
import { useState } from 'react';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
import { Pagination } from './Pagination';
|
|
13
|
+
import { Badge } from '../Badge';
|
|
14
|
+
import { Flex } from '../Flex';
|
|
15
|
+
import { Text } from '../Text';
|
|
16
|
+
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
17
|
+
import { jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
18
|
+
var meta = {
|
|
19
|
+
title: 'Pagination',
|
|
20
|
+
component: Pagination,
|
|
21
|
+
parameters: {
|
|
22
|
+
docs: {
|
|
23
|
+
description: {
|
|
24
|
+
component: "\nA Pagination component for navigating paged data.\n\n## Variants\n\n- **full** (default): Shows individual page number buttons with ellipsis for large page counts.\n- **compact**: Shows a dropdown page selector instead of individual page numbers.\n\n## Component Properties\n"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export default meta;
|
|
30
|
+
var PaginationWithState = function PaginationWithState(_ref) {
|
|
31
|
+
var _ref$initialPage = _ref.initialPage,
|
|
32
|
+
initialPage = _ref$initialPage === void 0 ? 1 : _ref$initialPage,
|
|
33
|
+
_ref$totalItems = _ref.totalItems,
|
|
34
|
+
totalItems = _ref$totalItems === void 0 ? 200 : _ref$totalItems,
|
|
35
|
+
_ref$initialItemsPerP = _ref.initialItemsPerPage,
|
|
36
|
+
initialItemsPerPage = _ref$initialItemsPerP === void 0 ? 20 : _ref$initialItemsPerP,
|
|
37
|
+
_ref$displayItemsPerP = _ref.displayItemsPerPageSelector,
|
|
38
|
+
displayItemsPerPageSelector = _ref$displayItemsPerP === void 0 ? false : _ref$displayItemsPerP,
|
|
39
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
40
|
+
var _useState = useState(initialPage),
|
|
41
|
+
currentPage = _useState[0],
|
|
42
|
+
setCurrentPage = _useState[1];
|
|
43
|
+
var _useState2 = useState(initialItemsPerPage),
|
|
44
|
+
itemsPerPage = _useState2[0],
|
|
45
|
+
setItemsPerPage = _useState2[1];
|
|
46
|
+
var totalPages = Math.ceil(totalItems / itemsPerPage);
|
|
47
|
+
return _jsx(Pagination, _extends({
|
|
48
|
+
currentPage: currentPage,
|
|
49
|
+
totalItems: totalItems,
|
|
50
|
+
itemsPerPage: itemsPerPage,
|
|
51
|
+
onPageChange: setCurrentPage,
|
|
52
|
+
displayItemsPerPageSelector: displayItemsPerPageSelector,
|
|
53
|
+
onItemsPerPageChange: function onItemsPerPageChange(size) {
|
|
54
|
+
setItemsPerPage(size);
|
|
55
|
+
setCurrentPage(1);
|
|
56
|
+
}
|
|
57
|
+
}, props, {
|
|
58
|
+
children: _jsxs(Flex, {
|
|
59
|
+
sx: {
|
|
60
|
+
justifyContent: 'center',
|
|
61
|
+
alignItems: 'center',
|
|
62
|
+
verticalAlign: 'middle'
|
|
63
|
+
},
|
|
64
|
+
children: [_jsx(Badge, {
|
|
65
|
+
variant: "gold",
|
|
66
|
+
sx: {
|
|
67
|
+
mr: 2
|
|
68
|
+
},
|
|
69
|
+
children: "DEBUG"
|
|
70
|
+
}), _jsxs(Text, {
|
|
71
|
+
children: ["Page ", currentPage, " of ", totalPages]
|
|
72
|
+
})]
|
|
73
|
+
})
|
|
74
|
+
}));
|
|
75
|
+
};
|
|
76
|
+
var OpenEndedPaginationWithState = function OpenEndedPaginationWithState(_ref2) {
|
|
77
|
+
var _ref2$initialPage = _ref2.initialPage,
|
|
78
|
+
initialPage = _ref2$initialPage === void 0 ? 1 : _ref2$initialPage,
|
|
79
|
+
_ref2$initialItemsPer = _ref2.initialItemsPerPage,
|
|
80
|
+
initialItemsPerPage = _ref2$initialItemsPer === void 0 ? 20 : _ref2$initialItemsPer,
|
|
81
|
+
hasNextPage = _ref2.hasNextPage,
|
|
82
|
+
props = _objectWithoutPropertiesLoose(_ref2, _excluded2);
|
|
83
|
+
var _useState3 = useState(initialPage),
|
|
84
|
+
currentPage = _useState3[0],
|
|
85
|
+
setCurrentPage = _useState3[1];
|
|
86
|
+
var _useState4 = useState(initialItemsPerPage),
|
|
87
|
+
itemsPerPage = _useState4[0],
|
|
88
|
+
setItemsPerPage = _useState4[1];
|
|
89
|
+
return _jsx(Pagination, _extends({
|
|
90
|
+
currentPage: currentPage,
|
|
91
|
+
itemsPerPage: itemsPerPage,
|
|
92
|
+
onPageChange: setCurrentPage,
|
|
93
|
+
onItemsPerPageChange: function onItemsPerPageChange(size) {
|
|
94
|
+
setItemsPerPage(size);
|
|
95
|
+
setCurrentPage(1);
|
|
96
|
+
},
|
|
97
|
+
hasNextPage: hasNextPage
|
|
98
|
+
}, props, {
|
|
99
|
+
children: _jsxs(Flex, {
|
|
100
|
+
sx: {
|
|
101
|
+
justifyContent: 'center',
|
|
102
|
+
alignItems: 'center',
|
|
103
|
+
verticalAlign: 'middle'
|
|
104
|
+
},
|
|
105
|
+
children: [_jsx(Badge, {
|
|
106
|
+
variant: "gold",
|
|
107
|
+
sx: {
|
|
108
|
+
mr: 2
|
|
109
|
+
},
|
|
110
|
+
children: "DEBUG"
|
|
111
|
+
}), _jsxs(Text, {
|
|
112
|
+
children: ["Page ", currentPage, " (open-ended)"]
|
|
113
|
+
})]
|
|
114
|
+
})
|
|
115
|
+
}));
|
|
116
|
+
};
|
|
117
|
+
export var Default = {
|
|
118
|
+
render: function render() {
|
|
119
|
+
return _jsx(PaginationWithState, {});
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
export var Compact = {
|
|
123
|
+
render: function render() {
|
|
124
|
+
return _jsx(PaginationWithState, {
|
|
125
|
+
variant: "compact"
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
export var FewPages = {
|
|
130
|
+
render: function render() {
|
|
131
|
+
return _jsx(PaginationWithState, {
|
|
132
|
+
totalItems: 200,
|
|
133
|
+
initialItemsPerPage: 10
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
export var MiddlePage = {
|
|
138
|
+
render: function render() {
|
|
139
|
+
return _jsx(PaginationWithState, {
|
|
140
|
+
totalItems: 500,
|
|
141
|
+
initialItemsPerPage: 10,
|
|
142
|
+
initialPage: 25
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
export var CustomPageSizes = {
|
|
147
|
+
render: function render() {
|
|
148
|
+
return _jsx(PaginationWithState, {
|
|
149
|
+
totalItems: 1000,
|
|
150
|
+
initialItemsPerPage: 25,
|
|
151
|
+
pageSizeOptions: [25, 50, 100, 250]
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
export var WithItemsPerPageSelector = {
|
|
156
|
+
render: function render() {
|
|
157
|
+
return _jsx(PaginationWithState, {
|
|
158
|
+
totalItems: 100,
|
|
159
|
+
initialItemsPerPage: 25,
|
|
160
|
+
displayItemsPerPageSelector: true
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var CursorBasedPaginationWithState = function CursorBasedPaginationWithState() {
|
|
165
|
+
var _useState5 = useState(1),
|
|
166
|
+
currentPage = _useState5[0],
|
|
167
|
+
setCurrentPage = _useState5[1];
|
|
168
|
+
var _useState6 = useState(20),
|
|
169
|
+
itemsPerPage = _useState6[0],
|
|
170
|
+
setItemsPerPage = _useState6[1];
|
|
171
|
+
var _useState7 = useState(1),
|
|
172
|
+
maxVisited = _useState7[0],
|
|
173
|
+
setMaxVisited = _useState7[1];
|
|
174
|
+
var handlePageChange = function handlePageChange(page) {
|
|
175
|
+
setCurrentPage(page);
|
|
176
|
+
setMaxVisited(function (prev) {
|
|
177
|
+
return Math.max(prev, page);
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
var hasNextPage = true; // Simulate always having a next page
|
|
181
|
+
var maxReachablePage = hasNextPage ? maxVisited + 1 : maxVisited;
|
|
182
|
+
return _jsx(Pagination, {
|
|
183
|
+
currentPage: currentPage,
|
|
184
|
+
itemsPerPage: itemsPerPage,
|
|
185
|
+
onPageChange: handlePageChange,
|
|
186
|
+
onItemsPerPageChange: function onItemsPerPageChange(size) {
|
|
187
|
+
setItemsPerPage(size);
|
|
188
|
+
setCurrentPage(1);
|
|
189
|
+
setMaxVisited(1);
|
|
190
|
+
},
|
|
191
|
+
hasNextPage: hasNextPage,
|
|
192
|
+
maxReachablePage: maxReachablePage,
|
|
193
|
+
displayItemsPerPageSelector: true,
|
|
194
|
+
children: _jsxs(Flex, {
|
|
195
|
+
sx: {
|
|
196
|
+
justifyContent: 'center',
|
|
197
|
+
alignItems: 'center',
|
|
198
|
+
verticalAlign: 'middle'
|
|
199
|
+
},
|
|
200
|
+
children: [_jsx(Badge, {
|
|
201
|
+
variant: "gold",
|
|
202
|
+
sx: {
|
|
203
|
+
mr: 2
|
|
204
|
+
},
|
|
205
|
+
children: "DEBUG"
|
|
206
|
+
}), _jsxs(Text, {
|
|
207
|
+
children: ["Page ", currentPage, " \u2014 max reachable: ", maxReachablePage]
|
|
208
|
+
})]
|
|
209
|
+
})
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
export var OpenEndedCursorBased = {
|
|
213
|
+
render: function render() {
|
|
214
|
+
return _jsx(CursorBasedPaginationWithState, {});
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
export var OpenEnded = {
|
|
218
|
+
render: function render() {
|
|
219
|
+
return _jsx(OpenEndedPaginationWithState, {});
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
export var OpenEndedCompact = {
|
|
223
|
+
render: function render() {
|
|
224
|
+
return _jsx(OpenEndedPaginationWithState, {
|
|
225
|
+
variant: "compact"
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
export var OpenEndedLastPage = {
|
|
230
|
+
render: function render() {
|
|
231
|
+
return _jsx(OpenEndedPaginationWithState, {
|
|
232
|
+
hasNextPage: false,
|
|
233
|
+
initialPage: 15
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
};
|