@automattic/vip-design-system 2.18.0 → 2.18.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/Pagination/Pagination.d.ts +10 -20
- package/build/system/Pagination/Pagination.js +50 -68
- package/build/system/Pagination/Pagination.stories.js +13 -11
- package/build/system/Pagination/Pagination.test.js +4 -4
- package/build/system/Pagination/PaginationLayout.d.ts +27 -0
- package/build/system/Pagination/PaginationLayout.js +63 -0
- package/build/system/Pagination/SimplePagination.d.ts +26 -0
- package/build/system/Pagination/SimplePagination.js +76 -0
- package/build/system/Pagination/SimplePagination.stories.d.ts +13 -0
- package/build/system/Pagination/SimplePagination.stories.js +130 -0
- package/build/system/Pagination/SimplePagination.test.d.ts +2 -0
- package/build/system/Pagination/SimplePagination.test.js +171 -0
- package/build/system/Pagination/index.d.ts +3 -1
- package/build/system/Pagination/index.js +2 -1
- package/build/system/index.d.ts +2 -2
- package/build/system/index.js +2 -2
- package/package.json +1 -1
- package/src/system/Pagination/Pagination.stories.tsx +13 -10
- package/src/system/Pagination/Pagination.test.tsx +4 -6
- package/src/system/Pagination/Pagination.tsx +36 -71
- package/src/system/Pagination/PaginationLayout.tsx +93 -0
- package/src/system/Pagination/SimplePagination.stories.tsx +127 -0
- package/src/system/Pagination/SimplePagination.test.tsx +120 -0
- package/src/system/Pagination/SimplePagination.tsx +97 -0
- package/src/system/Pagination/index.ts +3 -1
- package/src/system/index.ts +2 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Internal dependencies
|
|
7
|
+
*/
|
|
8
|
+
import { SimplePagination } from './SimplePagination';
|
|
9
|
+
import { Badge } from '../Badge';
|
|
10
|
+
import { Flex } from '../Flex';
|
|
11
|
+
import { Text } from '../Text';
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
13
|
+
var meta = {
|
|
14
|
+
title: 'SimplePagination',
|
|
15
|
+
component: SimplePagination,
|
|
16
|
+
parameters: {
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: "\nA pagination control with only previous/next arrow buttons.\nDesigned for cursor-based pagination APIs with custom param names (e.g., `after`/`before`).\n\nFor page-number based pagination, see `Pagination`.\n\n## Component Properties\n"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export default meta;
|
|
25
|
+
var pageTokens = ['start', 'abc123', 'def456', 'ghi789', 'jkl012', 'end'];
|
|
26
|
+
var SimplePaginationWithState = function SimplePaginationWithState(_ref) {
|
|
27
|
+
var _ref$initialIndex = _ref.initialIndex,
|
|
28
|
+
initialIndex = _ref$initialIndex === void 0 ? 0 : _ref$initialIndex,
|
|
29
|
+
_ref$displayItemsPerP = _ref.displayItemsPerPageSelector,
|
|
30
|
+
displayItemsPerPageSelector = _ref$displayItemsPerP === void 0 ? false : _ref$displayItemsPerP;
|
|
31
|
+
var _useState = useState(initialIndex),
|
|
32
|
+
index = _useState[0],
|
|
33
|
+
setIndex = _useState[1];
|
|
34
|
+
var _useState2 = useState(20),
|
|
35
|
+
itemsPerPage = _useState2[0],
|
|
36
|
+
setItemsPerPage = _useState2[1];
|
|
37
|
+
var hasPreviousPage = index > 0;
|
|
38
|
+
var hasNextPage = index < pageTokens.length - 1;
|
|
39
|
+
return _jsx(SimplePagination, {
|
|
40
|
+
hasNextPage: hasNextPage,
|
|
41
|
+
hasPreviousPage: hasPreviousPage,
|
|
42
|
+
nextParam: hasNextPage ? {
|
|
43
|
+
param: 'after',
|
|
44
|
+
value: pageTokens[index + 1]
|
|
45
|
+
} : undefined,
|
|
46
|
+
previousParam: hasPreviousPage ? {
|
|
47
|
+
param: 'before',
|
|
48
|
+
value: pageTokens[index]
|
|
49
|
+
} : undefined,
|
|
50
|
+
onNavigate: function onNavigate(param) {
|
|
51
|
+
if (param === 'after') {
|
|
52
|
+
setIndex(function (i) {
|
|
53
|
+
return i + 1;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (param === 'before') {
|
|
57
|
+
setIndex(function (i) {
|
|
58
|
+
return i - 1;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
displayItemsPerPageSelector: displayItemsPerPageSelector,
|
|
63
|
+
itemsPerPage: displayItemsPerPageSelector ? itemsPerPage : undefined,
|
|
64
|
+
onItemsPerPageChange: displayItemsPerPageSelector ? function (size) {
|
|
65
|
+
setItemsPerPage(size);
|
|
66
|
+
setIndex(0);
|
|
67
|
+
} : undefined,
|
|
68
|
+
children: _jsxs(Flex, {
|
|
69
|
+
sx: {
|
|
70
|
+
justifyContent: 'center',
|
|
71
|
+
alignItems: 'center',
|
|
72
|
+
verticalAlign: 'middle'
|
|
73
|
+
},
|
|
74
|
+
children: [_jsx(Badge, {
|
|
75
|
+
variant: "gold",
|
|
76
|
+
sx: {
|
|
77
|
+
mr: 2
|
|
78
|
+
},
|
|
79
|
+
children: "DEBUG"
|
|
80
|
+
}), _jsxs(Text, {
|
|
81
|
+
children: ["Index: ", index, " \u2014 token: ", pageTokens[index]]
|
|
82
|
+
})]
|
|
83
|
+
})
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
export var Default = {
|
|
87
|
+
render: function render() {
|
|
88
|
+
return _jsx(SimplePaginationWithState, {});
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
export var FirstPage = {
|
|
92
|
+
render: function render() {
|
|
93
|
+
return _jsx(SimplePaginationWithState, {});
|
|
94
|
+
},
|
|
95
|
+
parameters: {
|
|
96
|
+
docs: {
|
|
97
|
+
description: {
|
|
98
|
+
story: 'On the first page — Previous button is disabled.'
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
export var LastPage = {
|
|
104
|
+
render: function render() {
|
|
105
|
+
return _jsx(SimplePaginationWithState, {
|
|
106
|
+
initialIndex: pageTokens.length - 1
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
parameters: {
|
|
110
|
+
docs: {
|
|
111
|
+
description: {
|
|
112
|
+
story: 'On the last page — Next button is disabled.'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
export var WithPageSize = {
|
|
118
|
+
render: function render() {
|
|
119
|
+
return _jsx(SimplePaginationWithState, {
|
|
120
|
+
displayItemsPerPageSelector: true
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
parameters: {
|
|
124
|
+
docs: {
|
|
125
|
+
description: {
|
|
126
|
+
story: 'With an items-per-page selector.'
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
2
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
3
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
4
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
5
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
6
|
+
/** @jsxImportSource theme-ui */
|
|
7
|
+
|
|
8
|
+
import { render, screen } from '@testing-library/react';
|
|
9
|
+
import userEvent from '@testing-library/user-event';
|
|
10
|
+
import { axe } from 'jest-axe';
|
|
11
|
+
import '@testing-library/jest-dom';
|
|
12
|
+
import { SimplePagination } from './SimplePagination';
|
|
13
|
+
import { jsx as _jsx } from "theme-ui/jsx-runtime";
|
|
14
|
+
var defaultProps = {
|
|
15
|
+
hasNextPage: true,
|
|
16
|
+
hasPreviousPage: true,
|
|
17
|
+
nextParam: {
|
|
18
|
+
param: 'after',
|
|
19
|
+
value: 'cursor_abc'
|
|
20
|
+
},
|
|
21
|
+
previousParam: {
|
|
22
|
+
param: 'before',
|
|
23
|
+
value: 'cursor_xyz'
|
|
24
|
+
},
|
|
25
|
+
onNavigate: jest.fn()
|
|
26
|
+
};
|
|
27
|
+
describe('<SimplePagination />', function () {
|
|
28
|
+
beforeEach(function () {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
});
|
|
31
|
+
it('renders a nav landmark with aria-label', function () {
|
|
32
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps)));
|
|
33
|
+
expect(screen.getByRole('navigation', {
|
|
34
|
+
name: 'Pagination'
|
|
35
|
+
})).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
it('renders prev and next arrow buttons', function () {
|
|
38
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps)));
|
|
39
|
+
expect(screen.getByRole('button', {
|
|
40
|
+
name: 'Previous page'
|
|
41
|
+
})).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByRole('button', {
|
|
43
|
+
name: 'Next page'
|
|
44
|
+
})).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
it('does not render page number buttons', function () {
|
|
47
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps)));
|
|
48
|
+
expect(screen.queryByRole('button', {
|
|
49
|
+
name: /Go to page/
|
|
50
|
+
})).not.toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
it('disables previous button when hasPreviousPage is false', function () {
|
|
53
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
54
|
+
hasPreviousPage: false
|
|
55
|
+
})));
|
|
56
|
+
expect(screen.getByRole('button', {
|
|
57
|
+
name: 'Previous page'
|
|
58
|
+
})).toBeDisabled();
|
|
59
|
+
});
|
|
60
|
+
it('disables next button when hasNextPage is false', function () {
|
|
61
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
62
|
+
hasNextPage: false
|
|
63
|
+
})));
|
|
64
|
+
expect(screen.getByRole('button', {
|
|
65
|
+
name: 'Next page'
|
|
66
|
+
})).toBeDisabled();
|
|
67
|
+
});
|
|
68
|
+
it('disables previous button when previousParam is undefined', function () {
|
|
69
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
70
|
+
previousParam: undefined
|
|
71
|
+
})));
|
|
72
|
+
expect(screen.getByRole('button', {
|
|
73
|
+
name: 'Previous page'
|
|
74
|
+
})).toBeDisabled();
|
|
75
|
+
});
|
|
76
|
+
it('disables next button when nextParam is undefined', function () {
|
|
77
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
78
|
+
nextParam: undefined
|
|
79
|
+
})));
|
|
80
|
+
expect(screen.getByRole('button', {
|
|
81
|
+
name: 'Next page'
|
|
82
|
+
})).toBeDisabled();
|
|
83
|
+
});
|
|
84
|
+
it('calls onNavigate with correct param and value when clicking next', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
85
|
+
var user;
|
|
86
|
+
return _regenerator().w(function (_context) {
|
|
87
|
+
while (1) switch (_context.n) {
|
|
88
|
+
case 0:
|
|
89
|
+
user = userEvent.setup();
|
|
90
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps)));
|
|
91
|
+
_context.n = 1;
|
|
92
|
+
return user.click(screen.getByRole('button', {
|
|
93
|
+
name: 'Next page'
|
|
94
|
+
}));
|
|
95
|
+
case 1:
|
|
96
|
+
expect(defaultProps.onNavigate).toHaveBeenCalledWith('after', 'cursor_abc');
|
|
97
|
+
case 2:
|
|
98
|
+
return _context.a(2);
|
|
99
|
+
}
|
|
100
|
+
}, _callee);
|
|
101
|
+
})));
|
|
102
|
+
it('calls onNavigate with correct param and value when clicking previous', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
103
|
+
var user;
|
|
104
|
+
return _regenerator().w(function (_context2) {
|
|
105
|
+
while (1) switch (_context2.n) {
|
|
106
|
+
case 0:
|
|
107
|
+
user = userEvent.setup();
|
|
108
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps)));
|
|
109
|
+
_context2.n = 1;
|
|
110
|
+
return user.click(screen.getByRole('button', {
|
|
111
|
+
name: 'Previous page'
|
|
112
|
+
}));
|
|
113
|
+
case 1:
|
|
114
|
+
expect(defaultProps.onNavigate).toHaveBeenCalledWith('before', 'cursor_xyz');
|
|
115
|
+
case 2:
|
|
116
|
+
return _context2.a(2);
|
|
117
|
+
}
|
|
118
|
+
}, _callee2);
|
|
119
|
+
})));
|
|
120
|
+
it('renders children content', function () {
|
|
121
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
122
|
+
children: _jsx("span", {
|
|
123
|
+
children: "Showing results"
|
|
124
|
+
})
|
|
125
|
+
})));
|
|
126
|
+
expect(screen.getByText('Showing results')).toBeInTheDocument();
|
|
127
|
+
});
|
|
128
|
+
it('renders items-per-page selector when enabled', function () {
|
|
129
|
+
render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
130
|
+
displayItemsPerPageSelector: true,
|
|
131
|
+
itemsPerPage: 20,
|
|
132
|
+
onItemsPerPageChange: jest.fn()
|
|
133
|
+
})));
|
|
134
|
+
expect(screen.getByRole('combobox')).toBeInTheDocument();
|
|
135
|
+
});
|
|
136
|
+
it('has no accessibility violations', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
137
|
+
var _render, container, _t;
|
|
138
|
+
return _regenerator().w(function (_context3) {
|
|
139
|
+
while (1) switch (_context3.n) {
|
|
140
|
+
case 0:
|
|
141
|
+
_render = render(_jsx(SimplePagination, _extends({}, defaultProps))), container = _render.container;
|
|
142
|
+
_t = expect;
|
|
143
|
+
_context3.n = 1;
|
|
144
|
+
return axe(container);
|
|
145
|
+
case 1:
|
|
146
|
+
_t(_context3.v).toHaveNoViolations();
|
|
147
|
+
case 2:
|
|
148
|
+
return _context3.a(2);
|
|
149
|
+
}
|
|
150
|
+
}, _callee3);
|
|
151
|
+
})));
|
|
152
|
+
it('has no accessibility violations with both buttons disabled', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
153
|
+
var _render2, container, _t2;
|
|
154
|
+
return _regenerator().w(function (_context4) {
|
|
155
|
+
while (1) switch (_context4.n) {
|
|
156
|
+
case 0:
|
|
157
|
+
_render2 = render(_jsx(SimplePagination, _extends({}, defaultProps, {
|
|
158
|
+
hasNextPage: false,
|
|
159
|
+
hasPreviousPage: false
|
|
160
|
+
}))), container = _render2.container;
|
|
161
|
+
_t2 = expect;
|
|
162
|
+
_context4.n = 1;
|
|
163
|
+
return axe(container);
|
|
164
|
+
case 1:
|
|
165
|
+
_t2(_context4.v).toHaveNoViolations();
|
|
166
|
+
case 2:
|
|
167
|
+
return _context4.a(2);
|
|
168
|
+
}
|
|
169
|
+
}, _callee4);
|
|
170
|
+
})));
|
|
171
|
+
});
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { Pagination, getPageNumbers } from './Pagination';
|
|
2
|
-
export
|
|
2
|
+
export { SimplePagination } from './SimplePagination';
|
|
3
|
+
export type { PaginationProps, PageNumberItem } from './Pagination';
|
|
4
|
+
export type { SimplePaginationProps, SimpleNavigationParam } from './SimplePagination';
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { Pagination, getPageNumbers } from './Pagination';
|
|
1
|
+
export { Pagination, getPageNumbers } from './Pagination';
|
|
2
|
+
export { SimplePagination } from './SimplePagination';
|
package/build/system/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ import * as Form from './NewForm';
|
|
|
31
31
|
import { NewTooltip } from './NewTooltip';
|
|
32
32
|
import { Notice } from './Notice';
|
|
33
33
|
import { OptionRow } from './OptionRow';
|
|
34
|
-
import { Pagination } from './Pagination';
|
|
34
|
+
import { SimplePagination, Pagination } from './Pagination';
|
|
35
35
|
import { Progress } from './Progress';
|
|
36
36
|
import { ScreenReaderText } from './ScreenReaderText';
|
|
37
37
|
import { Skeleton } from './Skeleton';
|
|
@@ -44,4 +44,4 @@ import { Toolbar } from './Toolbar';
|
|
|
44
44
|
import { Tooltip } from './Tooltip';
|
|
45
45
|
import { Wizard, WizardStep } from './Wizard';
|
|
46
46
|
import theme from './theme';
|
|
47
|
-
export { Accordion, Avatar, Badge, Box, Breadcrumbs, Button, ButtonSubmit, ButtonVariant, Card, Checkbox, Code, Dialog, NewDialog, Form, Drawer, Dropdown, DialogButton, DialogMenu, DialogMenuItem, DialogDivider, DialogContent, DialogTrigger, DescriptionList, ConfirmationDialog, MobileMenu, MobileMenuTrigger, MobileMenuWrapper, NewConfirmationDialog, NewTooltip, Grid, FilterDropdown, Flex, Notice, OptionRow, Pagination, Heading, Hr, Input, Label, ScreenReaderText, Spinner, Table, TableRow, TableCell, Tooltip, Link, LinkExternal, Radio, RadioBoxGroup, RadioGroupChip, Textarea, Progress, Text, Tabs, Nav, NavItem, Skeleton, TabsTrigger, TabsContent, TabsList, Toggle, ToggleRow, Toolbar, Snackbar, Validation, Wizard, WizardStep, theme, };
|
|
47
|
+
export { Accordion, Avatar, Badge, Box, Breadcrumbs, Button, ButtonSubmit, ButtonVariant, Card, Checkbox, Code, Dialog, NewDialog, Form, Drawer, Dropdown, DialogButton, DialogMenu, DialogMenuItem, DialogDivider, DialogContent, DialogTrigger, DescriptionList, ConfirmationDialog, MobileMenu, MobileMenuTrigger, MobileMenuWrapper, NewConfirmationDialog, NewTooltip, Grid, FilterDropdown, Flex, Notice, OptionRow, SimplePagination, Pagination, Heading, Hr, Input, Label, ScreenReaderText, Spinner, Table, TableRow, TableCell, Tooltip, Link, LinkExternal, Radio, RadioBoxGroup, RadioGroupChip, Textarea, Progress, Text, Tabs, Nav, NavItem, Skeleton, TabsTrigger, TabsContent, TabsList, Toggle, ToggleRow, Toolbar, Snackbar, Validation, Wizard, WizardStep, theme, };
|
package/build/system/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import * as Form from './NewForm';
|
|
|
31
31
|
import { NewTooltip } from './NewTooltip';
|
|
32
32
|
import { Notice } from './Notice';
|
|
33
33
|
import { OptionRow } from './OptionRow';
|
|
34
|
-
import { Pagination } from './Pagination';
|
|
34
|
+
import { SimplePagination, Pagination } from './Pagination';
|
|
35
35
|
import { Progress } from './Progress';
|
|
36
36
|
import { ScreenReaderText } from './ScreenReaderText';
|
|
37
37
|
import { Skeleton } from './Skeleton';
|
|
@@ -44,4 +44,4 @@ import { Toolbar } from './Toolbar';
|
|
|
44
44
|
import { Tooltip } from './Tooltip';
|
|
45
45
|
import { Wizard, WizardStep } from './Wizard';
|
|
46
46
|
import theme from './theme';
|
|
47
|
-
export { Accordion, Avatar, Badge, Box, Breadcrumbs, Button, ButtonSubmit, ButtonVariant, Card, Checkbox, Code, Dialog, NewDialog, Form, Drawer, Dropdown, DialogButton, DialogMenu, DialogMenuItem, DialogDivider, DialogContent, DialogTrigger, DescriptionList, ConfirmationDialog, MobileMenu, MobileMenuTrigger, MobileMenuWrapper, NewConfirmationDialog, NewTooltip, Grid, FilterDropdown, Flex, Notice, OptionRow, Pagination, Heading, Hr, Input, Label, ScreenReaderText, Spinner, Table, TableRow, TableCell, Tooltip, Link, LinkExternal, Radio, RadioBoxGroup, RadioGroupChip, Textarea, Progress, Text, Tabs, Nav, NavItem, Skeleton, TabsTrigger, TabsContent, TabsList, Toggle, ToggleRow, Toolbar, Snackbar, Validation, Wizard, WizardStep, theme };
|
|
47
|
+
export { Accordion, Avatar, Badge, Box, Breadcrumbs, Button, ButtonSubmit, ButtonVariant, Card, Checkbox, Code, Dialog, NewDialog, Form, Drawer, Dropdown, DialogButton, DialogMenu, DialogMenuItem, DialogDivider, DialogContent, DialogTrigger, DescriptionList, ConfirmationDialog, MobileMenu, MobileMenuTrigger, MobileMenuWrapper, NewConfirmationDialog, NewTooltip, Grid, FilterDropdown, Flex, Notice, OptionRow, SimplePagination, Pagination, Heading, Hr, Input, Label, ScreenReaderText, Spinner, Table, TableRow, TableCell, Tooltip, Link, LinkExternal, Radio, RadioBoxGroup, RadioGroupChip, Textarea, Progress, Text, Tabs, Nav, NavItem, Skeleton, TabsTrigger, TabsContent, TabsList, Toggle, ToggleRow, Toolbar, Snackbar, Validation, Wizard, WizardStep, theme };
|
package/package.json
CHANGED
|
@@ -21,10 +21,12 @@ const meta: Meta< typeof Pagination > = {
|
|
|
21
21
|
component: `
|
|
22
22
|
A Pagination component for navigating paged data.
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## Modes
|
|
25
25
|
|
|
26
|
-
- **
|
|
27
|
-
- **compact
|
|
26
|
+
- **Default**: Shows individual page number buttons with ellipsis for large page counts.
|
|
27
|
+
- **Compact** (\`compact\` prop): Shows a dropdown page selector instead of individual page numbers.
|
|
28
|
+
|
|
29
|
+
For cursor-based pagination with only prev/next arrows, see \`SimplePagination\`.
|
|
28
30
|
|
|
29
31
|
## Component Properties
|
|
30
32
|
`,
|
|
@@ -42,12 +44,13 @@ const PaginationWithState = ( {
|
|
|
42
44
|
totalItems = 200,
|
|
43
45
|
initialItemsPerPage = 20,
|
|
44
46
|
displayItemsPerPageSelector = false,
|
|
47
|
+
compact = false,
|
|
45
48
|
...props
|
|
46
49
|
}: {
|
|
47
50
|
initialPage?: number;
|
|
48
51
|
totalItems?: number;
|
|
49
52
|
initialItemsPerPage?: number;
|
|
50
|
-
|
|
53
|
+
compact?: boolean;
|
|
51
54
|
pageSizeOptions?: number[];
|
|
52
55
|
displayItemsPerPageSelector?: boolean;
|
|
53
56
|
} ) => {
|
|
@@ -62,6 +65,7 @@ const PaginationWithState = ( {
|
|
|
62
65
|
itemsPerPage={ itemsPerPage }
|
|
63
66
|
onPageChange={ setCurrentPage }
|
|
64
67
|
displayItemsPerPageSelector={ displayItemsPerPageSelector }
|
|
68
|
+
compact={ compact }
|
|
65
69
|
onItemsPerPageChange={ size => {
|
|
66
70
|
setItemsPerPage( size );
|
|
67
71
|
setCurrentPage( 1 );
|
|
@@ -84,12 +88,12 @@ const OpenEndedPaginationWithState = ( {
|
|
|
84
88
|
initialPage = 1,
|
|
85
89
|
initialItemsPerPage = 20,
|
|
86
90
|
hasNextPage,
|
|
87
|
-
|
|
91
|
+
compact = false,
|
|
88
92
|
}: {
|
|
89
93
|
initialPage?: number;
|
|
90
94
|
initialItemsPerPage?: number;
|
|
91
95
|
hasNextPage?: boolean;
|
|
92
|
-
|
|
96
|
+
compact?: boolean;
|
|
93
97
|
} ) => {
|
|
94
98
|
const [ currentPage, setCurrentPage ] = useState( initialPage );
|
|
95
99
|
const [ itemsPerPage, setItemsPerPage ] = useState( initialItemsPerPage );
|
|
@@ -104,7 +108,7 @@ const OpenEndedPaginationWithState = ( {
|
|
|
104
108
|
setCurrentPage( 1 );
|
|
105
109
|
} }
|
|
106
110
|
hasNextPage={ hasNextPage }
|
|
107
|
-
{
|
|
111
|
+
compact={ compact }
|
|
108
112
|
>
|
|
109
113
|
<Flex sx={ { justifyContent: 'center', alignItems: 'center', verticalAlign: 'middle' } }>
|
|
110
114
|
<Badge variant="gold" sx={ { mr: 2 } }>
|
|
@@ -121,7 +125,6 @@ export const Primary: Story = {
|
|
|
121
125
|
currentPage: 1,
|
|
122
126
|
totalItems: 200,
|
|
123
127
|
itemsPerPage: 20,
|
|
124
|
-
variant: 'full',
|
|
125
128
|
displayItemsPerPageSelector: false,
|
|
126
129
|
},
|
|
127
130
|
};
|
|
@@ -131,7 +134,7 @@ export const Default: Story = {
|
|
|
131
134
|
};
|
|
132
135
|
|
|
133
136
|
export const Compact: Story = {
|
|
134
|
-
render: () => <PaginationWithState
|
|
137
|
+
render: () => <PaginationWithState compact />,
|
|
135
138
|
};
|
|
136
139
|
|
|
137
140
|
export const FewPages: Story = {
|
|
@@ -212,7 +215,7 @@ export const OpenEnded: Story = {
|
|
|
212
215
|
};
|
|
213
216
|
|
|
214
217
|
export const OpenEndedCompact: Story = {
|
|
215
|
-
render: () => <OpenEndedPaginationWithState
|
|
218
|
+
render: () => <OpenEndedPaginationWithState compact />,
|
|
216
219
|
};
|
|
217
220
|
|
|
218
221
|
export const OpenEndedLastPage: Story = {
|
|
@@ -109,7 +109,7 @@ describe( '<Pagination />', () => {
|
|
|
109
109
|
} );
|
|
110
110
|
|
|
111
111
|
it( 'renders compact variant with Page text', () => {
|
|
112
|
-
render( <Pagination { ...defaultProps }
|
|
112
|
+
render( <Pagination { ...defaultProps } compact currentPage={ 3 } /> );
|
|
113
113
|
|
|
114
114
|
expect( screen.getByText( 'Page' ) ).toBeInTheDocument();
|
|
115
115
|
expect( screen.getByText( 'of 10' ) ).toBeInTheDocument();
|
|
@@ -136,9 +136,7 @@ describe( '<Pagination />', () => {
|
|
|
136
136
|
} );
|
|
137
137
|
|
|
138
138
|
it( 'has no accessibility violations (compact variant)', async () => {
|
|
139
|
-
const { container } = render(
|
|
140
|
-
<Pagination { ...defaultProps } variant="compact" currentPage={ 5 } />
|
|
141
|
-
);
|
|
139
|
+
const { container } = render( <Pagination { ...defaultProps } compact currentPage={ 5 } /> );
|
|
142
140
|
|
|
143
141
|
expect( await axe( container ) ).toHaveNoViolations();
|
|
144
142
|
} );
|
|
@@ -304,7 +302,7 @@ describe( '<Pagination /> open-ended mode', () => {
|
|
|
304
302
|
} );
|
|
305
303
|
|
|
306
304
|
it( 'renders compact variant with "Page" but without "of Y"', () => {
|
|
307
|
-
render( <Pagination { ...openEndedProps }
|
|
305
|
+
render( <Pagination { ...openEndedProps } compact /> );
|
|
308
306
|
|
|
309
307
|
expect( screen.getByText( 'Page' ) ).toBeInTheDocument();
|
|
310
308
|
expect( screen.queryByText( /of \d+/ ) ).not.toBeInTheDocument();
|
|
@@ -317,7 +315,7 @@ describe( '<Pagination /> open-ended mode', () => {
|
|
|
317
315
|
} );
|
|
318
316
|
|
|
319
317
|
it( 'has no accessibility violations (open-ended compact)', async () => {
|
|
320
|
-
const { container } = render( <Pagination { ...openEndedProps }
|
|
318
|
+
const { container } = render( <Pagination { ...openEndedProps } compact /> );
|
|
321
319
|
|
|
322
320
|
expect( await axe( container ) ).toHaveNoViolations();
|
|
323
321
|
} );
|