@dt-dds/react-pagination 1.0.0-beta.40 → 1.0.0-beta.41

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @dt-ui/react-pagination
2
2
 
3
+ ## 1.0.0-beta.41
4
+
5
+ ### Minor Changes
6
+
7
+ - feat: refactor pagination
8
+
9
+ ### Patch Changes
10
+
11
+ - fix: pagination dependency
12
+
3
13
  ## 1.0.0-beta.40
4
14
 
5
15
  ### Patch Changes
package/README.md CHANGED
@@ -1,77 +1,45 @@
1
1
  # Pagination Package
2
2
 
3
- The Pagination component enables the user to select a specific page from a range of pages.
3
+ The Pagination component provides page navigation with optional items-per-page selection and item count information.
4
4
 
5
5
  ## Pagination Usage
6
6
 
7
7
  ```jsx
8
- import { Pagination, PaginationInput, usePagination } from '@dt-dds/react';
9
- const totalPages = 10;
10
-
11
- const { currentPage, handleChange, handleUserInput } = usePagination();
12
-
13
- return (
14
- <Pagination>
15
- <Pagination.PreviousItem
16
- disabled={currentPage <= 1 || currentPage > totalPages}
17
- onClick={() => handleChange(currentPage - 1)}
18
- />
19
- <PaginationInput
20
- value={currentPage}
21
- totalPages={totalPages}
22
- onHandleKeyDown={handleUserInput}
23
- onChange={handleChange}
24
- />
25
- <Pagination.Content
26
- totalPages={totalPages}
27
- onClick={() => handleChange(totalPages)}
8
+ import { Pagination } from '@dt-dds/react';
9
+
10
+ const Example = () => {
11
+ const [currentPage, setCurrentPage] = useState(1);
12
+ const [itemsPerPage, setItemsPerPage] = useState(10);
13
+
14
+ return (
15
+ <Pagination
16
+ currentPage={currentPage}
17
+ totalPages={20}
18
+ totalItems={200}
19
+ itemsPerPage={itemsPerPage}
20
+ onPageChange={setCurrentPage}
21
+ onItemsPerPageChange={setItemsPerPage}
22
+ showItemsPerPage
23
+ showItemsInfo
28
24
  />
29
- <Pagination.NextItem
30
- disabled={currentPage >= totalPages || currentPage < 1}
31
- onClick={() => handleChange(currentPage + 1)}
32
- />
33
- </Pagination>
34
- );
25
+ );
26
+ };
35
27
  ```
36
28
 
37
29
  ## Properties
38
30
 
39
- ### Pagination
40
-
41
- | Property | Type | Default | Description |
42
- | ------------ | ----------- | ------------------ | ------------------------------- |
43
- | `children` | `ReactNode` | - | Child components to be rendered |
44
- | `dataTestId` | `string` | pagination-wrapper | Customizable test identifier |
45
-
46
- ### Pagination.PreviousItem
47
-
48
- | Property | Type | Default | Description |
49
- | ---------- | ---------- | ------- | ------------------------------------------------- |
50
- | `onClick` | `function` | - | The triggered function when clicked on the button |
51
- | `disabled` | `boolean` | false | Determines the disabled state of the button |
52
-
53
- ### Pagination.NextItem
54
-
55
- | Property | Type | Default | Description |
56
- | ---------- | ---------- | ------- | ------------------------------------------------- |
57
- | `onClick` | `function` | - | The triggered function when clicked on the button |
58
- | `disabled` | `boolean` | false | Determines the disabled state of the button |
59
-
60
- ### Pagination.Content
61
-
62
- | Property | Type | Default | Description |
63
- | ------------ | ---------- | ------- | ------------------------------------------------- |
64
- | `onClick` | `function` | - | The triggered function when clicked on the button |
65
- | `totalPages` | `number` | - | It will be the number displayed on the button |
66
-
67
- ### PaginationInput
68
-
69
- | Property | Type | Default | Description |
70
- | ----------------- | ---------- | ------- | ---------------------------------------------------- |
71
- | `totalPages` | `number` | - | Total number of pages |
72
- | `onChange` | `function` | - | Function to be executed when debounced value changes |
73
- | `onHandleKeyDown` | `function` | - | Event fired when a key is pressed |
74
- | `value` | `number` | - | Value to be displayed on the input |
31
+ | Property | Type | Default | Description |
32
+ | ---------------------- | ------------------------- | ------------------- | ------------------------------------------------------ |
33
+ | `currentPage` | `number` | | Currently selected page (1-based index) |
34
+ | `totalPages` | `number` | | Total number of available pages |
35
+ | `totalItems` | `number` | | Total number of items across all pages |
36
+ | `itemsPerPage` | `number` | `10` | Number of items displayed per page |
37
+ | `onPageChange` | `(page: number) => void` | — | Callback fired when the current page changes |
38
+ | `onItemsPerPageChange` | `(items: number) => void` | — | Callback fired when items-per-page value changes |
39
+ | `showItemsPerPage` | `boolean` | `false` | Controls visibility of the items-per-page selector |
40
+ | `showItemsInfo` | `boolean` | `true` | Controls visibility of the items information text |
41
+ | `itemsPerPageOptions` | `number[]` | `[10, 20, 50, 100]` | Available options for items per page |
42
+ | `dataTestId` | `string` | `pagination` | Custom test identifier for the pagination root element |
75
43
 
76
44
  ## Stack
77
45
 
package/dist/index.d.mts CHANGED
@@ -1,39 +1,41 @@
1
1
  import { CustomTheme } from '@dt-dds/themes';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import React$1 from 'react';
3
+ import { Code } from '@dt-dds/icons';
4
4
  import { BaseProps } from '@dt-dds/react-core';
5
5
 
6
- interface ContentProps {
6
+ interface PaginationProps extends BaseProps {
7
+ currentPage: number;
7
8
  totalPages: number;
8
- onClick: () => void;
9
- }
10
- interface ArrowProps {
11
- onClick: () => void;
12
- disabled?: boolean;
9
+ totalItems?: number;
10
+ itemsPerPage?: number;
11
+ onPageChange: (page: number) => void;
12
+ onItemsPerPageChange?: (itemsPerPage: number) => void;
13
+ showItemsPerPage?: boolean;
14
+ showItemsInfo?: boolean;
15
+ itemsPerPageOptions?: number[];
13
16
  }
14
- interface PaginationInputProps {
15
- totalPages: number;
16
- onChange: (value: number) => void;
17
- onHandleKeyDown: (event: React$1.KeyboardEvent<HTMLInputElement>) => void;
18
- value?: number;
17
+ interface PaginationNavButtonProps {
18
+ ariaLabel: string;
19
+ tooltipLabel: string;
20
+ icon: Code;
21
+ targetPage: number;
22
+ isDisabled: boolean;
23
+ testId: string;
24
+ onClick: (page: number) => void;
19
25
  }
20
- declare const Pagination: {
21
- ({ children, dataTestId }: BaseProps): react_jsx_runtime.JSX.Element;
22
- Content({ totalPages, onClick }: ContentProps): react_jsx_runtime.JSX.Element;
23
- NextItem({ onClick, disabled }: ArrowProps): react_jsx_runtime.JSX.Element;
24
- PreviousItem({ onClick, disabled }: ArrowProps): react_jsx_runtime.JSX.Element;
25
- };
26
- declare const PaginationInput: ({ totalPages, onHandleKeyDown, value, onChange, }: PaginationInputProps) => react_jsx_runtime.JSX.Element;
27
26
 
28
- declare const usePagination: () => {
29
- currentPage: number;
30
- handleChange: (value: number) => void;
31
- handleUserInput: (e: React.KeyboardEvent<HTMLInputElement>) => void;
32
- };
27
+ declare const Pagination: ({ currentPage, totalPages, totalItems, itemsPerPage, onPageChange, onItemsPerPageChange, showItemsPerPage, showItemsInfo, itemsPerPageOptions, dataTestId, }: PaginationProps) => react_jsx_runtime.JSX.Element;
28
+
29
+ declare const ITEMS_PER_PAGE_OPTIONS: number[];
30
+ declare const FIRST_PAGE = 1;
31
+ declare const PAGINATION_BUTTON_SIZES = 24;
32
+ declare const ITEMS_PER_PAGE_WIDTH = 200;
33
+
34
+ declare const getPageNumbers: (currentPage: number, totalPages: number) => (number | "ellipsis")[];
33
35
 
34
36
  declare module '@emotion/react' {
35
37
  interface Theme extends CustomTheme {
36
38
  }
37
39
  }
38
40
 
39
- export { type ArrowProps, type ContentProps, Pagination, PaginationInput, type PaginationInputProps, usePagination };
41
+ export { FIRST_PAGE, ITEMS_PER_PAGE_OPTIONS, ITEMS_PER_PAGE_WIDTH, PAGINATION_BUTTON_SIZES, Pagination, type PaginationNavButtonProps, type PaginationProps, getPageNumbers };
package/dist/index.d.ts CHANGED
@@ -1,39 +1,41 @@
1
1
  import { CustomTheme } from '@dt-dds/themes';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
- import React$1 from 'react';
3
+ import { Code } from '@dt-dds/icons';
4
4
  import { BaseProps } from '@dt-dds/react-core';
5
5
 
6
- interface ContentProps {
6
+ interface PaginationProps extends BaseProps {
7
+ currentPage: number;
7
8
  totalPages: number;
8
- onClick: () => void;
9
- }
10
- interface ArrowProps {
11
- onClick: () => void;
12
- disabled?: boolean;
9
+ totalItems?: number;
10
+ itemsPerPage?: number;
11
+ onPageChange: (page: number) => void;
12
+ onItemsPerPageChange?: (itemsPerPage: number) => void;
13
+ showItemsPerPage?: boolean;
14
+ showItemsInfo?: boolean;
15
+ itemsPerPageOptions?: number[];
13
16
  }
14
- interface PaginationInputProps {
15
- totalPages: number;
16
- onChange: (value: number) => void;
17
- onHandleKeyDown: (event: React$1.KeyboardEvent<HTMLInputElement>) => void;
18
- value?: number;
17
+ interface PaginationNavButtonProps {
18
+ ariaLabel: string;
19
+ tooltipLabel: string;
20
+ icon: Code;
21
+ targetPage: number;
22
+ isDisabled: boolean;
23
+ testId: string;
24
+ onClick: (page: number) => void;
19
25
  }
20
- declare const Pagination: {
21
- ({ children, dataTestId }: BaseProps): react_jsx_runtime.JSX.Element;
22
- Content({ totalPages, onClick }: ContentProps): react_jsx_runtime.JSX.Element;
23
- NextItem({ onClick, disabled }: ArrowProps): react_jsx_runtime.JSX.Element;
24
- PreviousItem({ onClick, disabled }: ArrowProps): react_jsx_runtime.JSX.Element;
25
- };
26
- declare const PaginationInput: ({ totalPages, onHandleKeyDown, value, onChange, }: PaginationInputProps) => react_jsx_runtime.JSX.Element;
27
26
 
28
- declare const usePagination: () => {
29
- currentPage: number;
30
- handleChange: (value: number) => void;
31
- handleUserInput: (e: React.KeyboardEvent<HTMLInputElement>) => void;
32
- };
27
+ declare const Pagination: ({ currentPage, totalPages, totalItems, itemsPerPage, onPageChange, onItemsPerPageChange, showItemsPerPage, showItemsInfo, itemsPerPageOptions, dataTestId, }: PaginationProps) => react_jsx_runtime.JSX.Element;
28
+
29
+ declare const ITEMS_PER_PAGE_OPTIONS: number[];
30
+ declare const FIRST_PAGE = 1;
31
+ declare const PAGINATION_BUTTON_SIZES = 24;
32
+ declare const ITEMS_PER_PAGE_WIDTH = 200;
33
+
34
+ declare const getPageNumbers: (currentPage: number, totalPages: number) => (number | "ellipsis")[];
33
35
 
34
36
  declare module '@emotion/react' {
35
37
  interface Theme extends CustomTheme {
36
38
  }
37
39
  }
38
40
 
39
- export { type ArrowProps, type ContentProps, Pagination, PaginationInput, type PaginationInputProps, usePagination };
41
+ export { FIRST_PAGE, ITEMS_PER_PAGE_OPTIONS, ITEMS_PER_PAGE_WIDTH, PAGINATION_BUTTON_SIZES, Pagination, type PaginationNavButtonProps, type PaginationProps, getPageNumbers };
package/dist/index.js CHANGED
@@ -30,171 +30,385 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ FIRST_PAGE: () => FIRST_PAGE,
34
+ ITEMS_PER_PAGE_OPTIONS: () => ITEMS_PER_PAGE_OPTIONS,
35
+ ITEMS_PER_PAGE_WIDTH: () => ITEMS_PER_PAGE_WIDTH,
36
+ PAGINATION_BUTTON_SIZES: () => PAGINATION_BUTTON_SIZES,
33
37
  Pagination: () => Pagination,
34
- PaginationInput: () => PaginationInput,
35
- usePagination: () => usePagination
38
+ getPageNumbers: () => getPageNumbers
36
39
  });
37
40
  module.exports = __toCommonJS(index_exports);
38
41
 
39
42
  // src/Pagination.tsx
40
43
  var import_react = require("react");
41
- var import_react_core = require("@dt-dds/react-core");
44
+ var import_react_select = require("@dt-dds/react-select");
45
+
46
+ // src/components/PaginationNavButton/PaginationNavButton.tsx
42
47
  var import_react_icon = require("@dt-dds/react-icon");
43
- var import_react_typography = require("@dt-dds/react-typography");
48
+ var import_react_tooltip = require("@dt-dds/react-tooltip");
44
49
 
45
50
  // src/Pagination.styled.ts
51
+ var import_is_prop_valid = __toESM(require("@emotion/is-prop-valid"));
46
52
  var import_styled = __toESM(require("@emotion/styled"));
53
+
54
+ // src/constants/index.ts
55
+ var ITEMS_PER_PAGE_OPTIONS = [10, 20, 50, 100];
56
+ var FIRST_PAGE = 1;
57
+ var PAGINATION_BUTTON_SIZES = 24;
58
+ var ITEMS_PER_PAGE_WIDTH = 200;
59
+
60
+ // src/Pagination.styled.ts
47
61
  var PaginationStyled = import_styled.default.div`
48
62
  display: flex;
63
+ flex-direction: column-reverse;
49
64
  align-items: center;
50
- gap: 8px;
51
- margin-top: 48px;
65
+ width: 100%;
66
+ gap: 12px;
67
+
68
+ @media screen and (min-width: ${({ theme }) => theme.breakpoints.mq3}px) {
69
+ flex-direction: row;
70
+ justify-content: center;
71
+
72
+ &:has(> *:nth-of-type(2)) {
73
+ justify-content: space-between;
74
+ }
75
+ }
52
76
  `;
53
- var LastPageStyled = import_styled.default.button`
77
+ var InfoWrapperStyled = import_styled.default.div`
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ gap: 12px;
82
+
83
+ @media screen and (min-width: ${({ theme }) => theme.breakpoints.mq3}px) {
84
+ width: auto;
85
+ flex-shrink: 0;
86
+ }
87
+ `;
88
+ var NavigationWrapperStyled = import_styled.default.div`
89
+ display: flex;
90
+ align-items: center;
91
+ gap: 4px;
92
+ padding: 10px 0;
93
+ flex-shrink: 0;
94
+ flex-wrap: nowrap;
95
+ `;
96
+ var PaginationButtonStyled = import_styled.default.button`
54
97
  ${({ theme }) => `
55
- background-color: transparent;
56
- color: ${theme.palette.primary.default};
98
+ display: flex;
99
+ align-items: center;
100
+ justify-content: center;
101
+ width: ${PAGINATION_BUTTON_SIZES}px;
102
+ height: ${PAGINATION_BUTTON_SIZES}px;
103
+ padding: 0;
57
104
  border: none;
105
+ position: relative;
106
+ background-color: transparent;
107
+ color: ${theme.palette.content.default};
58
108
  cursor: pointer;
109
+
110
+ &:disabled {
111
+ i {
112
+ color: ${theme.palette.content.light};
113
+ }
114
+ cursor: not-allowed;
115
+ }
116
+
117
+ &:hover:not(:disabled) {
118
+ background-color: ${theme.palette.informative.light};
119
+ }
120
+
121
+ &:focus-visible {
122
+ outline: 2px solid ${theme.palette.primary.default};
123
+ outline-offset: 1px;
124
+ }
59
125
  `}
60
126
  `;
61
- var ArrowStyled = import_styled.default.button`
62
- ${({ theme, disabled }) => `
127
+ var PaginationPageButtonStyled = (0, import_styled.default)("button", {
128
+ shouldForwardProp: (prop) => (0, import_is_prop_valid.default)(prop) && !prop.startsWith("$")
129
+ })`
130
+ ${({ theme, $isActive }) => `
131
+ ${theme.fontStyles.bodyXsBold};
63
132
  display: flex;
133
+ align-items: center;
64
134
  justify-content: center;
65
- background-color: ${theme.palette.surface.contrast};
135
+ width: ${PAGINATION_BUTTON_SIZES}px;
136
+ height: ${PAGINATION_BUTTON_SIZES}px;
66
137
  border: none;
67
- border-radius: 3px;
68
- cursor: ${disabled ? "default" : "pointer"};
138
+ transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
139
+ background-color: transparent;
140
+ color: ${theme.palette.content.default};
141
+ cursor: pointer;
142
+
143
+ &:focus-visible {
144
+ outline: 2px solid ${theme.palette.primary.default};
145
+ outline-offset: 1px;
146
+ transition: none;
147
+ }
148
+
149
+ &:hover {
150
+ background-color: ${theme.palette.informative.light};
151
+ }
152
+
153
+ ${$isActive && `
154
+ background-color: ${theme.palette.primary.default};
155
+ color: ${theme.palette.content.contrast};
156
+ cursor: default;
157
+
158
+ &:hover {
159
+ background-color: ${theme.palette.primary.default};
160
+ }
161
+ `}
69
162
  `}
70
163
  `;
71
- var InputStyled = import_styled.default.input`
72
- ${({ theme, hasError }) => `
73
- ${theme.fontStyles.bodyMdRegularXSmall};
74
- text-align: center;
75
- padding: 6px 8px;
76
- margin: 0px;
77
- width: 50px;
78
- height: 32px;
79
- background-color: ${theme.palette.surface.contrast};
164
+ var TruncationTextStyled = import_styled.default.span`
165
+ ${({ theme }) => `
166
+ ${theme.fontStyles.bodyMdRegular};
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ width: ${PAGINATION_BUTTON_SIZES}px;
171
+ height: ${PAGINATION_BUTTON_SIZES}px;
80
172
  color: ${theme.palette.content.default};
81
- border: ${hasError ? `2px solid ${theme.palette.error.default}` : `1px solid ${theme.palette.border.default}`};
82
- border-radius: 3px;
173
+ user-select: none;
174
+ `}
175
+ `;
176
+ var ItemsPerPageWrapperStyled = import_styled.default.div`
177
+ ${({ theme }) => `
178
+ label:empty {
179
+ display: none;
180
+ }
83
181
 
84
- &:focus {
85
- ${!hasError && `border-bottom: 2px solid ${theme.palette.primary.default}`};
182
+ @media screen and (min-width: ${theme.breakpoints.mq3}px) {
183
+ min-width: ${ITEMS_PER_PAGE_WIDTH}px;
86
184
  }
87
185
  `}
88
186
  `;
187
+ var ItemsInfoTextStyled = import_styled.default.span`
188
+ ${({ theme }) => `
189
+ ${theme.fontStyles.bodySmRegular};
190
+ white-space: nowrap;
191
+ `}
192
+ `;
89
193
 
90
- // src/Pagination.tsx
194
+ // src/components/PaginationNavButton/PaginationNavButton.tsx
91
195
  var import_jsx_runtime = require("react/jsx-runtime");
92
- var Pagination = ({ children, dataTestId }) => {
93
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PaginationStyled, { "data-testid": dataTestId != null ? dataTestId : "pagination-wrapper", children });
94
- };
95
- Pagination.Content = ({ totalPages, onClick }) => {
96
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_typography.Typography, { color: "grey_90", fontStyles: "bodyXsRegular", children: [
97
- "of",
98
- " ",
99
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
100
- LastPageStyled,
101
- {
102
- "data-testid": "pagination-last-page",
103
- onClick,
104
- title: "Go to last page",
105
- children: totalPages
106
- }
107
- )
108
- ] });
109
- };
110
- Pagination.NextItem = ({ onClick, disabled }) => {
111
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
- ArrowStyled,
196
+ var PaginationNavButton = ({
197
+ ariaLabel,
198
+ tooltipLabel,
199
+ icon,
200
+ targetPage,
201
+ isDisabled,
202
+ testId,
203
+ onClick
204
+ }) => {
205
+ const button = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
206
+ PaginationButtonStyled,
113
207
  {
114
- "data-testid": "pagination-next-item",
115
- disabled,
116
- onClick,
117
- title: "Go to next page",
118
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_icon.Icon, { code: "arrow_forward_ios", size: "small" })
208
+ "aria-label": ariaLabel,
209
+ "data-testid": testId,
210
+ disabled: isDisabled,
211
+ onClick: () => onClick(targetPage),
212
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_icon.Icon, { code: icon, size: "small" })
119
213
  }
120
214
  );
215
+ if (isDisabled) return button;
216
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_tooltip.Tooltip, { children: [
217
+ button,
218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_tooltip.Tooltip.Content, { background: "full", direction: "top", children: tooltipLabel })
219
+ ] });
121
220
  };
122
- Pagination.PreviousItem = ({ onClick, disabled }) => {
123
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
124
- ArrowStyled,
125
- {
126
- "data-testid": "pagination-previous-item",
127
- disabled,
128
- onClick,
129
- title: "Go to previous page",
130
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_icon.Icon, { code: "arrow_back_ios", size: "small" })
131
- }
132
- );
221
+ PaginationNavButton.displayName = "PaginationNavButton";
222
+
223
+ // src/utils/getPageNumbers.ts
224
+ var PAGINATION_THRESHOLD = 5;
225
+ var START_BOUNDARY = 3;
226
+ var END_OFFSET = 2;
227
+ var NEIGHBOR_COUNT = 1;
228
+ var getPageNumbers = (currentPage, totalPages) => {
229
+ if (totalPages <= PAGINATION_THRESHOLD) {
230
+ return Array.from({ length: totalPages }, (_, i) => i + 1);
231
+ }
232
+ const showLeftEllipsis = currentPage > START_BOUNDARY;
233
+ const showRightEllipsis = currentPage < totalPages - END_OFFSET;
234
+ if (!showLeftEllipsis && showRightEllipsis) {
235
+ return [1, 2, 3, "ellipsis", totalPages];
236
+ }
237
+ if (showLeftEllipsis && !showRightEllipsis) {
238
+ return [1, "ellipsis", totalPages - 2, totalPages - 1, totalPages];
239
+ }
240
+ return [
241
+ 1,
242
+ "ellipsis",
243
+ currentPage - NEIGHBOR_COUNT,
244
+ currentPage,
245
+ currentPage + NEIGHBOR_COUNT,
246
+ "ellipsis",
247
+ totalPages
248
+ ];
133
249
  };
134
- var PaginationInput = ({
250
+
251
+ // src/Pagination.tsx
252
+ var import_jsx_runtime2 = require("react/jsx-runtime");
253
+ var Pagination = ({
254
+ currentPage,
135
255
  totalPages,
136
- onHandleKeyDown,
137
- value,
138
- onChange
256
+ totalItems,
257
+ itemsPerPage = 10,
258
+ onPageChange,
259
+ onItemsPerPageChange,
260
+ showItemsPerPage = false,
261
+ showItemsInfo = true,
262
+ itemsPerPageOptions = ITEMS_PER_PAGE_OPTIONS,
263
+ dataTestId
139
264
  }) => {
140
- const [inputValue, setInputValue] = (0, import_react.useState)(1);
141
- const [hasError, setHasError] = (0, import_react.useState)(false);
142
- const debouncedFn = (0, import_react.useMemo)(() => (0, import_react_core.debounce)((fn) => fn(), 500), []);
143
- (0, import_react.useEffect)(() => {
144
- if (value !== void 0) {
145
- setInputValue(value);
146
- }
147
- }, [value]);
148
- (0, import_react.useEffect)(() => {
149
- if (inputValue && inputValue <= totalPages) {
150
- debouncedFn(() => {
151
- onChange(inputValue);
152
- });
153
- }
154
- }, [debouncedFn, inputValue, onChange, totalPages]);
155
- const handleChange = (event) => {
156
- const value2 = Number(event.target.value);
157
- setInputValue(value2);
158
- if (value2 > totalPages || value2 === 0) {
159
- setHasError(true);
160
- } else {
161
- setHasError(false);
162
- }
163
- };
164
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
165
- InputStyled,
166
- {
167
- "data-testid": "pagination-input",
168
- hasError,
169
- onChange: handleChange,
170
- onKeyDown: onHandleKeyDown,
171
- value: inputValue
172
- }
265
+ const pageNumbers = (0, import_react.useMemo)(
266
+ () => getPageNumbers(currentPage, totalPages),
267
+ [currentPage, totalPages]
173
268
  );
174
- };
175
-
176
- // src/hooks/usePagination.tsx
177
- var import_react2 = require("react");
178
- var usePagination = () => {
179
- const [currentPage, setCurrentPage] = (0, import_react2.useState)(1);
180
- const handleUserInput = (e) => {
181
- const validCodes = ["Enter", "Backspace", "Tab"];
182
- if (!/Digit\d/.test(e.code) && !validCodes.includes(e.code)) {
183
- e.preventDefault();
184
- }
185
- };
186
- const handleChange = (0, import_react2.useCallback)((value) => {
187
- setCurrentPage(value);
188
- }, []);
189
- return {
190
- currentPage,
191
- handleChange,
192
- handleUserInput
193
- };
269
+ const isFirstPage = currentPage === FIRST_PAGE;
270
+ const isLastPage = currentPage === totalPages;
271
+ const itemsBeforeCurrentPage = (currentPage - FIRST_PAGE) * itemsPerPage;
272
+ const remainingItems = Math.max(
273
+ 0,
274
+ (totalItems != null ? totalItems : 0) - itemsBeforeCurrentPage
275
+ );
276
+ const shownItems = Math.min(itemsPerPage, remainingItems);
277
+ const hasInfoSection = showItemsPerPage || showItemsInfo && totalItems !== void 0;
278
+ const handlePageChange = (0, import_react.useCallback)(
279
+ (page) => {
280
+ const canNavigateToPage = page !== currentPage && page >= FIRST_PAGE && page <= totalPages;
281
+ if (canNavigateToPage) {
282
+ onPageChange(page);
283
+ }
284
+ },
285
+ [currentPage, totalPages, onPageChange]
286
+ );
287
+ const handleItemsPerPageChange = (0, import_react.useCallback)(
288
+ (value) => {
289
+ onItemsPerPageChange == null ? void 0 : onItemsPerPageChange(Number(value));
290
+ },
291
+ [onItemsPerPageChange]
292
+ );
293
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(PaginationStyled, { "data-testid": dataTestId != null ? dataTestId : "pagination", children: [
294
+ hasInfoSection ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(InfoWrapperStyled, { children: [
295
+ showItemsPerPage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ItemsPerPageWrapperStyled, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
296
+ import_react_select.Select,
297
+ {
298
+ dataTestId: "pagination-items-per-page",
299
+ fill: "contrast",
300
+ isFloatingLabel: false,
301
+ label: "",
302
+ onChange: handleItemsPerPageChange,
303
+ placeholder: "Items per page",
304
+ scale: "compact",
305
+ value: itemsPerPage.toString(),
306
+ children: itemsPerPageOptions.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
307
+ import_react_select.Select.Option,
308
+ {
309
+ index,
310
+ value: option.toString(),
311
+ children: [
312
+ option,
313
+ " per page"
314
+ ]
315
+ },
316
+ option
317
+ ))
318
+ }
319
+ ) }) : null,
320
+ showItemsInfo && totalItems !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(ItemsInfoTextStyled, { "data-testid": "pagination-items-info", children: [
321
+ "Showing ",
322
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: shownItems }),
323
+ " of",
324
+ " ",
325
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: totalItems }),
326
+ " entries"
327
+ ] }) : null
328
+ ] }) : null,
329
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(NavigationWrapperStyled, { children: [
330
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
331
+ PaginationNavButton,
332
+ {
333
+ ariaLabel: "Go to first page",
334
+ icon: "first_page",
335
+ isDisabled: isFirstPage,
336
+ onClick: handlePageChange,
337
+ targetPage: FIRST_PAGE,
338
+ testId: "pagination-first-page",
339
+ tooltipLabel: "First page"
340
+ }
341
+ ),
342
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
343
+ PaginationNavButton,
344
+ {
345
+ ariaLabel: "Go to previous page",
346
+ icon: "chevron_left",
347
+ isDisabled: isFirstPage,
348
+ onClick: handlePageChange,
349
+ targetPage: currentPage - 1,
350
+ testId: "pagination-previous-page",
351
+ tooltipLabel: "Previous page"
352
+ }
353
+ ),
354
+ pageNumbers.map((page) => {
355
+ if (page === "ellipsis") {
356
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
357
+ TruncationTextStyled,
358
+ {
359
+ "data-testid": "pagination-ellipsis",
360
+ children: "..."
361
+ },
362
+ `ellipsis-${page}`
363
+ );
364
+ }
365
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
366
+ PaginationPageButtonStyled,
367
+ {
368
+ $isActive: page === currentPage,
369
+ "aria-current": page === currentPage ? "page" : void 0,
370
+ "aria-label": `Go to page ${page}`,
371
+ "data-testid": `pagination-page-${page}`,
372
+ onClick: () => handlePageChange(page),
373
+ title: `Go to page ${page}`,
374
+ children: page
375
+ },
376
+ page
377
+ );
378
+ }),
379
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
380
+ PaginationNavButton,
381
+ {
382
+ ariaLabel: "Go to next page",
383
+ icon: "chevron_right",
384
+ isDisabled: isLastPage,
385
+ onClick: handlePageChange,
386
+ targetPage: currentPage + 1,
387
+ testId: "pagination-next-page",
388
+ tooltipLabel: "Next page"
389
+ }
390
+ ),
391
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
392
+ PaginationNavButton,
393
+ {
394
+ ariaLabel: "Go to last page",
395
+ icon: "last_page",
396
+ isDisabled: isLastPage,
397
+ onClick: handlePageChange,
398
+ targetPage: totalPages,
399
+ testId: "pagination-last-page",
400
+ tooltipLabel: "Last page"
401
+ }
402
+ )
403
+ ] })
404
+ ] });
194
405
  };
195
406
  // Annotate the CommonJS export names for ESM import in node:
196
407
  0 && (module.exports = {
408
+ FIRST_PAGE,
409
+ ITEMS_PER_PAGE_OPTIONS,
410
+ ITEMS_PER_PAGE_WIDTH,
411
+ PAGINATION_BUTTON_SIZES,
197
412
  Pagination,
198
- PaginationInput,
199
- usePagination
413
+ getPageNumbers
200
414
  });
package/dist/index.mjs CHANGED
@@ -1,161 +1,372 @@
1
1
  // src/Pagination.tsx
2
- import { useEffect, useMemo, useState } from "react";
3
- import { debounce } from "@dt-dds/react-core";
2
+ import { useMemo, useCallback } from "react";
3
+ import { Select } from "@dt-dds/react-select";
4
+
5
+ // src/components/PaginationNavButton/PaginationNavButton.tsx
4
6
  import { Icon } from "@dt-dds/react-icon";
5
- import { Typography } from "@dt-dds/react-typography";
7
+ import { Tooltip } from "@dt-dds/react-tooltip";
6
8
 
7
9
  // src/Pagination.styled.ts
10
+ import isPropValid from "@emotion/is-prop-valid";
8
11
  import styled from "@emotion/styled";
12
+
13
+ // src/constants/index.ts
14
+ var ITEMS_PER_PAGE_OPTIONS = [10, 20, 50, 100];
15
+ var FIRST_PAGE = 1;
16
+ var PAGINATION_BUTTON_SIZES = 24;
17
+ var ITEMS_PER_PAGE_WIDTH = 200;
18
+
19
+ // src/Pagination.styled.ts
9
20
  var PaginationStyled = styled.div`
21
+ display: flex;
22
+ flex-direction: column-reverse;
23
+ align-items: center;
24
+ width: 100%;
25
+ gap: 12px;
26
+
27
+ @media screen and (min-width: ${({ theme }) => theme.breakpoints.mq3}px) {
28
+ flex-direction: row;
29
+ justify-content: center;
30
+
31
+ &:has(> *:nth-of-type(2)) {
32
+ justify-content: space-between;
33
+ }
34
+ }
35
+ `;
36
+ var InfoWrapperStyled = styled.div`
10
37
  display: flex;
11
38
  align-items: center;
12
- gap: 8px;
13
- margin-top: 48px;
39
+ justify-content: center;
40
+ gap: 12px;
41
+
42
+ @media screen and (min-width: ${({ theme }) => theme.breakpoints.mq3}px) {
43
+ width: auto;
44
+ flex-shrink: 0;
45
+ }
14
46
  `;
15
- var LastPageStyled = styled.button`
47
+ var NavigationWrapperStyled = styled.div`
48
+ display: flex;
49
+ align-items: center;
50
+ gap: 4px;
51
+ padding: 10px 0;
52
+ flex-shrink: 0;
53
+ flex-wrap: nowrap;
54
+ `;
55
+ var PaginationButtonStyled = styled.button`
16
56
  ${({ theme }) => `
17
- background-color: transparent;
18
- color: ${theme.palette.primary.default};
57
+ display: flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ width: ${PAGINATION_BUTTON_SIZES}px;
61
+ height: ${PAGINATION_BUTTON_SIZES}px;
62
+ padding: 0;
19
63
  border: none;
64
+ position: relative;
65
+ background-color: transparent;
66
+ color: ${theme.palette.content.default};
20
67
  cursor: pointer;
68
+
69
+ &:disabled {
70
+ i {
71
+ color: ${theme.palette.content.light};
72
+ }
73
+ cursor: not-allowed;
74
+ }
75
+
76
+ &:hover:not(:disabled) {
77
+ background-color: ${theme.palette.informative.light};
78
+ }
79
+
80
+ &:focus-visible {
81
+ outline: 2px solid ${theme.palette.primary.default};
82
+ outline-offset: 1px;
83
+ }
21
84
  `}
22
85
  `;
23
- var ArrowStyled = styled.button`
24
- ${({ theme, disabled }) => `
86
+ var PaginationPageButtonStyled = styled("button", {
87
+ shouldForwardProp: (prop) => isPropValid(prop) && !prop.startsWith("$")
88
+ })`
89
+ ${({ theme, $isActive }) => `
90
+ ${theme.fontStyles.bodyXsBold};
25
91
  display: flex;
92
+ align-items: center;
26
93
  justify-content: center;
27
- background-color: ${theme.palette.surface.contrast};
94
+ width: ${PAGINATION_BUTTON_SIZES}px;
95
+ height: ${PAGINATION_BUTTON_SIZES}px;
28
96
  border: none;
29
- border-radius: 3px;
30
- cursor: ${disabled ? "default" : "pointer"};
97
+ transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
98
+ background-color: transparent;
99
+ color: ${theme.palette.content.default};
100
+ cursor: pointer;
101
+
102
+ &:focus-visible {
103
+ outline: 2px solid ${theme.palette.primary.default};
104
+ outline-offset: 1px;
105
+ transition: none;
106
+ }
107
+
108
+ &:hover {
109
+ background-color: ${theme.palette.informative.light};
110
+ }
111
+
112
+ ${$isActive && `
113
+ background-color: ${theme.palette.primary.default};
114
+ color: ${theme.palette.content.contrast};
115
+ cursor: default;
116
+
117
+ &:hover {
118
+ background-color: ${theme.palette.primary.default};
119
+ }
120
+ `}
31
121
  `}
32
122
  `;
33
- var InputStyled = styled.input`
34
- ${({ theme, hasError }) => `
35
- ${theme.fontStyles.bodyMdRegularXSmall};
36
- text-align: center;
37
- padding: 6px 8px;
38
- margin: 0px;
39
- width: 50px;
40
- height: 32px;
41
- background-color: ${theme.palette.surface.contrast};
123
+ var TruncationTextStyled = styled.span`
124
+ ${({ theme }) => `
125
+ ${theme.fontStyles.bodyMdRegular};
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ width: ${PAGINATION_BUTTON_SIZES}px;
130
+ height: ${PAGINATION_BUTTON_SIZES}px;
42
131
  color: ${theme.palette.content.default};
43
- border: ${hasError ? `2px solid ${theme.palette.error.default}` : `1px solid ${theme.palette.border.default}`};
44
- border-radius: 3px;
132
+ user-select: none;
133
+ `}
134
+ `;
135
+ var ItemsPerPageWrapperStyled = styled.div`
136
+ ${({ theme }) => `
137
+ label:empty {
138
+ display: none;
139
+ }
45
140
 
46
- &:focus {
47
- ${!hasError && `border-bottom: 2px solid ${theme.palette.primary.default}`};
141
+ @media screen and (min-width: ${theme.breakpoints.mq3}px) {
142
+ min-width: ${ITEMS_PER_PAGE_WIDTH}px;
48
143
  }
49
144
  `}
50
145
  `;
146
+ var ItemsInfoTextStyled = styled.span`
147
+ ${({ theme }) => `
148
+ ${theme.fontStyles.bodySmRegular};
149
+ white-space: nowrap;
150
+ `}
151
+ `;
51
152
 
52
- // src/Pagination.tsx
153
+ // src/components/PaginationNavButton/PaginationNavButton.tsx
53
154
  import { jsx, jsxs } from "react/jsx-runtime";
54
- var Pagination = ({ children, dataTestId }) => {
55
- return /* @__PURE__ */ jsx(PaginationStyled, { "data-testid": dataTestId != null ? dataTestId : "pagination-wrapper", children });
56
- };
57
- Pagination.Content = ({ totalPages, onClick }) => {
58
- return /* @__PURE__ */ jsxs(Typography, { color: "grey_90", fontStyles: "bodyXsRegular", children: [
59
- "of",
60
- " ",
61
- /* @__PURE__ */ jsx(
62
- LastPageStyled,
63
- {
64
- "data-testid": "pagination-last-page",
65
- onClick,
66
- title: "Go to last page",
67
- children: totalPages
68
- }
69
- )
70
- ] });
71
- };
72
- Pagination.NextItem = ({ onClick, disabled }) => {
73
- return /* @__PURE__ */ jsx(
74
- ArrowStyled,
155
+ var PaginationNavButton = ({
156
+ ariaLabel,
157
+ tooltipLabel,
158
+ icon,
159
+ targetPage,
160
+ isDisabled,
161
+ testId,
162
+ onClick
163
+ }) => {
164
+ const button = /* @__PURE__ */ jsx(
165
+ PaginationButtonStyled,
75
166
  {
76
- "data-testid": "pagination-next-item",
77
- disabled,
78
- onClick,
79
- title: "Go to next page",
80
- children: /* @__PURE__ */ jsx(Icon, { code: "arrow_forward_ios", size: "small" })
167
+ "aria-label": ariaLabel,
168
+ "data-testid": testId,
169
+ disabled: isDisabled,
170
+ onClick: () => onClick(targetPage),
171
+ children: /* @__PURE__ */ jsx(Icon, { code: icon, size: "small" })
81
172
  }
82
173
  );
174
+ if (isDisabled) return button;
175
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
176
+ button,
177
+ /* @__PURE__ */ jsx(Tooltip.Content, { background: "full", direction: "top", children: tooltipLabel })
178
+ ] });
83
179
  };
84
- Pagination.PreviousItem = ({ onClick, disabled }) => {
85
- return /* @__PURE__ */ jsx(
86
- ArrowStyled,
87
- {
88
- "data-testid": "pagination-previous-item",
89
- disabled,
90
- onClick,
91
- title: "Go to previous page",
92
- children: /* @__PURE__ */ jsx(Icon, { code: "arrow_back_ios", size: "small" })
93
- }
94
- );
180
+ PaginationNavButton.displayName = "PaginationNavButton";
181
+
182
+ // src/utils/getPageNumbers.ts
183
+ var PAGINATION_THRESHOLD = 5;
184
+ var START_BOUNDARY = 3;
185
+ var END_OFFSET = 2;
186
+ var NEIGHBOR_COUNT = 1;
187
+ var getPageNumbers = (currentPage, totalPages) => {
188
+ if (totalPages <= PAGINATION_THRESHOLD) {
189
+ return Array.from({ length: totalPages }, (_, i) => i + 1);
190
+ }
191
+ const showLeftEllipsis = currentPage > START_BOUNDARY;
192
+ const showRightEllipsis = currentPage < totalPages - END_OFFSET;
193
+ if (!showLeftEllipsis && showRightEllipsis) {
194
+ return [1, 2, 3, "ellipsis", totalPages];
195
+ }
196
+ if (showLeftEllipsis && !showRightEllipsis) {
197
+ return [1, "ellipsis", totalPages - 2, totalPages - 1, totalPages];
198
+ }
199
+ return [
200
+ 1,
201
+ "ellipsis",
202
+ currentPage - NEIGHBOR_COUNT,
203
+ currentPage,
204
+ currentPage + NEIGHBOR_COUNT,
205
+ "ellipsis",
206
+ totalPages
207
+ ];
95
208
  };
96
- var PaginationInput = ({
209
+
210
+ // src/Pagination.tsx
211
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
212
+ var Pagination = ({
213
+ currentPage,
97
214
  totalPages,
98
- onHandleKeyDown,
99
- value,
100
- onChange
215
+ totalItems,
216
+ itemsPerPage = 10,
217
+ onPageChange,
218
+ onItemsPerPageChange,
219
+ showItemsPerPage = false,
220
+ showItemsInfo = true,
221
+ itemsPerPageOptions = ITEMS_PER_PAGE_OPTIONS,
222
+ dataTestId
101
223
  }) => {
102
- const [inputValue, setInputValue] = useState(1);
103
- const [hasError, setHasError] = useState(false);
104
- const debouncedFn = useMemo(() => debounce((fn) => fn(), 500), []);
105
- useEffect(() => {
106
- if (value !== void 0) {
107
- setInputValue(value);
108
- }
109
- }, [value]);
110
- useEffect(() => {
111
- if (inputValue && inputValue <= totalPages) {
112
- debouncedFn(() => {
113
- onChange(inputValue);
114
- });
115
- }
116
- }, [debouncedFn, inputValue, onChange, totalPages]);
117
- const handleChange = (event) => {
118
- const value2 = Number(event.target.value);
119
- setInputValue(value2);
120
- if (value2 > totalPages || value2 === 0) {
121
- setHasError(true);
122
- } else {
123
- setHasError(false);
124
- }
125
- };
126
- return /* @__PURE__ */ jsx(
127
- InputStyled,
128
- {
129
- "data-testid": "pagination-input",
130
- hasError,
131
- onChange: handleChange,
132
- onKeyDown: onHandleKeyDown,
133
- value: inputValue
134
- }
224
+ const pageNumbers = useMemo(
225
+ () => getPageNumbers(currentPage, totalPages),
226
+ [currentPage, totalPages]
135
227
  );
136
- };
137
-
138
- // src/hooks/usePagination.tsx
139
- import { useCallback, useState as useState2 } from "react";
140
- var usePagination = () => {
141
- const [currentPage, setCurrentPage] = useState2(1);
142
- const handleUserInput = (e) => {
143
- const validCodes = ["Enter", "Backspace", "Tab"];
144
- if (!/Digit\d/.test(e.code) && !validCodes.includes(e.code)) {
145
- e.preventDefault();
146
- }
147
- };
148
- const handleChange = useCallback((value) => {
149
- setCurrentPage(value);
150
- }, []);
151
- return {
152
- currentPage,
153
- handleChange,
154
- handleUserInput
155
- };
228
+ const isFirstPage = currentPage === FIRST_PAGE;
229
+ const isLastPage = currentPage === totalPages;
230
+ const itemsBeforeCurrentPage = (currentPage - FIRST_PAGE) * itemsPerPage;
231
+ const remainingItems = Math.max(
232
+ 0,
233
+ (totalItems != null ? totalItems : 0) - itemsBeforeCurrentPage
234
+ );
235
+ const shownItems = Math.min(itemsPerPage, remainingItems);
236
+ const hasInfoSection = showItemsPerPage || showItemsInfo && totalItems !== void 0;
237
+ const handlePageChange = useCallback(
238
+ (page) => {
239
+ const canNavigateToPage = page !== currentPage && page >= FIRST_PAGE && page <= totalPages;
240
+ if (canNavigateToPage) {
241
+ onPageChange(page);
242
+ }
243
+ },
244
+ [currentPage, totalPages, onPageChange]
245
+ );
246
+ const handleItemsPerPageChange = useCallback(
247
+ (value) => {
248
+ onItemsPerPageChange == null ? void 0 : onItemsPerPageChange(Number(value));
249
+ },
250
+ [onItemsPerPageChange]
251
+ );
252
+ return /* @__PURE__ */ jsxs2(PaginationStyled, { "data-testid": dataTestId != null ? dataTestId : "pagination", children: [
253
+ hasInfoSection ? /* @__PURE__ */ jsxs2(InfoWrapperStyled, { children: [
254
+ showItemsPerPage ? /* @__PURE__ */ jsx2(ItemsPerPageWrapperStyled, { children: /* @__PURE__ */ jsx2(
255
+ Select,
256
+ {
257
+ dataTestId: "pagination-items-per-page",
258
+ fill: "contrast",
259
+ isFloatingLabel: false,
260
+ label: "",
261
+ onChange: handleItemsPerPageChange,
262
+ placeholder: "Items per page",
263
+ scale: "compact",
264
+ value: itemsPerPage.toString(),
265
+ children: itemsPerPageOptions.map((option, index) => /* @__PURE__ */ jsxs2(
266
+ Select.Option,
267
+ {
268
+ index,
269
+ value: option.toString(),
270
+ children: [
271
+ option,
272
+ " per page"
273
+ ]
274
+ },
275
+ option
276
+ ))
277
+ }
278
+ ) }) : null,
279
+ showItemsInfo && totalItems !== void 0 ? /* @__PURE__ */ jsxs2(ItemsInfoTextStyled, { "data-testid": "pagination-items-info", children: [
280
+ "Showing ",
281
+ /* @__PURE__ */ jsx2("strong", { children: shownItems }),
282
+ " of",
283
+ " ",
284
+ /* @__PURE__ */ jsx2("strong", { children: totalItems }),
285
+ " entries"
286
+ ] }) : null
287
+ ] }) : null,
288
+ /* @__PURE__ */ jsxs2(NavigationWrapperStyled, { children: [
289
+ /* @__PURE__ */ jsx2(
290
+ PaginationNavButton,
291
+ {
292
+ ariaLabel: "Go to first page",
293
+ icon: "first_page",
294
+ isDisabled: isFirstPage,
295
+ onClick: handlePageChange,
296
+ targetPage: FIRST_PAGE,
297
+ testId: "pagination-first-page",
298
+ tooltipLabel: "First page"
299
+ }
300
+ ),
301
+ /* @__PURE__ */ jsx2(
302
+ PaginationNavButton,
303
+ {
304
+ ariaLabel: "Go to previous page",
305
+ icon: "chevron_left",
306
+ isDisabled: isFirstPage,
307
+ onClick: handlePageChange,
308
+ targetPage: currentPage - 1,
309
+ testId: "pagination-previous-page",
310
+ tooltipLabel: "Previous page"
311
+ }
312
+ ),
313
+ pageNumbers.map((page) => {
314
+ if (page === "ellipsis") {
315
+ return /* @__PURE__ */ jsx2(
316
+ TruncationTextStyled,
317
+ {
318
+ "data-testid": "pagination-ellipsis",
319
+ children: "..."
320
+ },
321
+ `ellipsis-${page}`
322
+ );
323
+ }
324
+ return /* @__PURE__ */ jsx2(
325
+ PaginationPageButtonStyled,
326
+ {
327
+ $isActive: page === currentPage,
328
+ "aria-current": page === currentPage ? "page" : void 0,
329
+ "aria-label": `Go to page ${page}`,
330
+ "data-testid": `pagination-page-${page}`,
331
+ onClick: () => handlePageChange(page),
332
+ title: `Go to page ${page}`,
333
+ children: page
334
+ },
335
+ page
336
+ );
337
+ }),
338
+ /* @__PURE__ */ jsx2(
339
+ PaginationNavButton,
340
+ {
341
+ ariaLabel: "Go to next page",
342
+ icon: "chevron_right",
343
+ isDisabled: isLastPage,
344
+ onClick: handlePageChange,
345
+ targetPage: currentPage + 1,
346
+ testId: "pagination-next-page",
347
+ tooltipLabel: "Next page"
348
+ }
349
+ ),
350
+ /* @__PURE__ */ jsx2(
351
+ PaginationNavButton,
352
+ {
353
+ ariaLabel: "Go to last page",
354
+ icon: "last_page",
355
+ isDisabled: isLastPage,
356
+ onClick: handlePageChange,
357
+ targetPage: totalPages,
358
+ testId: "pagination-last-page",
359
+ tooltipLabel: "Last page"
360
+ }
361
+ )
362
+ ] })
363
+ ] });
156
364
  };
157
365
  export {
366
+ FIRST_PAGE,
367
+ ITEMS_PER_PAGE_OPTIONS,
368
+ ITEMS_PER_PAGE_WIDTH,
369
+ PAGINATION_BUTTON_SIZES,
158
370
  Pagination,
159
- PaginationInput,
160
- usePagination
371
+ getPageNumbers
161
372
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dt-dds/react-pagination",
3
- "version": "1.0.0-beta.40",
3
+ "version": "1.0.0-beta.41",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js"
@@ -23,6 +23,9 @@
23
23
  "@dt-dds/react-core": "1.0.0-beta.58",
24
24
  "@dt-dds/react-typography": "1.0.0-beta.49",
25
25
  "@dt-dds/react-icon": "1.0.0-beta.61",
26
+ "@dt-dds/icons": "1.0.0-beta.6",
27
+ "@dt-dds/react-select": "1.0.0-beta.93",
28
+ "@dt-dds/react-tooltip": "1.0.0-beta.68",
26
29
  "@dt-dds/themes": "1.0.0-beta.13"
27
30
  },
28
31
  "devDependencies": {