@dt-dds/react-pagination 1.0.0-beta.46 → 1.0.0-beta.48

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,20 @@
1
1
  # @dt-ui/react-pagination
2
2
 
3
+ ## 1.0.0-beta.48
4
+
5
+ ### Patch Changes
6
+
7
+ - fix: pagination render
8
+ - refactor: backwards and forward pagination
9
+
10
+ ## 1.0.0-beta.47
11
+
12
+ ### Patch Changes
13
+
14
+ - fix: multi select option styling
15
+ - Updated dependencies
16
+ - @dt-dds/react-select@1.0.0-beta.97
17
+
3
18
  ## 1.0.0-beta.46
4
19
 
5
20
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -31,7 +31,15 @@ declare const FIRST_PAGE = 1;
31
31
  declare const PAGINATION_BUTTON_SIZES = 24;
32
32
  declare const ITEMS_PER_PAGE_WIDTH = 200;
33
33
 
34
- declare const getPageNumbers: (currentPage: number, totalPages: number) => (number | "ellipsis")[];
34
+ interface PageRenderData {
35
+ shouldRenderFirstPage: boolean;
36
+ shouldRenderLastPage: boolean;
37
+ shouldRenderLeftEllipsis: boolean;
38
+ shouldRenderRightEllipsis: boolean;
39
+ pages: number[];
40
+ }
41
+ type PaginationDirection = 'FORWARD' | 'BACKWARD';
42
+ declare const getPageNumbers: (currentPage: number, lastPage: number, direction?: PaginationDirection) => PageRenderData;
35
43
 
36
44
  declare module '@emotion/react' {
37
45
  interface Theme extends CustomTheme {
package/dist/index.d.ts CHANGED
@@ -31,7 +31,15 @@ declare const FIRST_PAGE = 1;
31
31
  declare const PAGINATION_BUTTON_SIZES = 24;
32
32
  declare const ITEMS_PER_PAGE_WIDTH = 200;
33
33
 
34
- declare const getPageNumbers: (currentPage: number, totalPages: number) => (number | "ellipsis")[];
34
+ interface PageRenderData {
35
+ shouldRenderFirstPage: boolean;
36
+ shouldRenderLastPage: boolean;
37
+ shouldRenderLeftEllipsis: boolean;
38
+ shouldRenderRightEllipsis: boolean;
39
+ pages: number[];
40
+ }
41
+ type PaginationDirection = 'FORWARD' | 'BACKWARD';
42
+ declare const getPageNumbers: (currentPage: number, lastPage: number, direction?: PaginationDirection) => PageRenderData;
35
43
 
36
44
  declare module '@emotion/react' {
37
45
  interface Theme extends CustomTheme {
package/dist/index.js CHANGED
@@ -221,35 +221,98 @@ var PaginationNavButton = ({
221
221
  PaginationNavButton.displayName = "PaginationNavButton";
222
222
 
223
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);
224
+ var getCompactPageNumbers = (firstPage, lastPage) => ({
225
+ pages: Array.from(
226
+ { length: Math.max(lastPage - firstPage + 1, 0) },
227
+ (_, index) => firstPage + index
228
+ ),
229
+ shouldRenderFirstPage: false,
230
+ shouldRenderLastPage: false,
231
+ shouldRenderLeftEllipsis: false,
232
+ shouldRenderRightEllipsis: false
233
+ });
234
+ var getForwardPageNumbers = (currentPage, firstPage, lastPage) => {
235
+ if (currentPage <= firstPage + 1) {
236
+ return {
237
+ pages: [firstPage, firstPage + 1, firstPage + 2],
238
+ shouldRenderFirstPage: false,
239
+ shouldRenderLastPage: true,
240
+ shouldRenderLeftEllipsis: false,
241
+ shouldRenderRightEllipsis: true
242
+ };
243
+ }
244
+ if (currentPage <= lastPage - 3) {
245
+ return {
246
+ pages: [currentPage - 1, currentPage, currentPage + 1],
247
+ shouldRenderFirstPage: false,
248
+ shouldRenderLastPage: true,
249
+ shouldRenderLeftEllipsis: false,
250
+ shouldRenderRightEllipsis: true
251
+ };
231
252
  }
232
- const showLeftEllipsis = currentPage > START_BOUNDARY;
233
- const showRightEllipsis = currentPage < totalPages - END_OFFSET;
234
- if (!showLeftEllipsis && showRightEllipsis) {
235
- return [1, 2, 3, "ellipsis", totalPages];
253
+ return {
254
+ pages: [lastPage - 2, lastPage - 1, lastPage],
255
+ shouldRenderFirstPage: true,
256
+ shouldRenderLastPage: false,
257
+ shouldRenderLeftEllipsis: true,
258
+ shouldRenderRightEllipsis: false
259
+ };
260
+ };
261
+ var getBackwardPageNumbers = (currentPage, firstPage, lastPage) => {
262
+ if (currentPage <= firstPage + 2) {
263
+ return {
264
+ pages: [firstPage, firstPage + 1, firstPage + 2],
265
+ shouldRenderFirstPage: false,
266
+ shouldRenderLastPage: true,
267
+ shouldRenderLeftEllipsis: false,
268
+ shouldRenderRightEllipsis: true
269
+ };
236
270
  }
237
- if (showLeftEllipsis && !showRightEllipsis) {
238
- return [1, "ellipsis", totalPages - 2, totalPages - 1, totalPages];
271
+ if (currentPage >= lastPage - 1) {
272
+ return {
273
+ pages: [lastPage - 2, lastPage - 1, lastPage],
274
+ shouldRenderFirstPage: true,
275
+ shouldRenderLastPage: false,
276
+ shouldRenderLeftEllipsis: true,
277
+ shouldRenderRightEllipsis: false
278
+ };
279
+ }
280
+ return {
281
+ pages: [currentPage - 1, currentPage, currentPage + 1],
282
+ shouldRenderFirstPage: true,
283
+ shouldRenderLastPage: false,
284
+ shouldRenderLeftEllipsis: true,
285
+ shouldRenderRightEllipsis: false
286
+ };
287
+ };
288
+ var getPageNumbers = (currentPage, lastPage, direction = "FORWARD") => {
289
+ const firstPage = FIRST_PAGE;
290
+ const cursor = Math.max(Math.min(currentPage, lastPage), firstPage);
291
+ if (lastPage <= firstPage + 4) {
292
+ return getCompactPageNumbers(firstPage, lastPage);
293
+ }
294
+ if (direction === "BACKWARD") {
295
+ return getBackwardPageNumbers(cursor, firstPage, lastPage);
296
+ } else {
297
+ return getForwardPageNumbers(cursor, firstPage, lastPage);
239
298
  }
240
- return [
241
- 1,
242
- "ellipsis",
243
- currentPage - NEIGHBOR_COUNT,
244
- currentPage,
245
- currentPage + NEIGHBOR_COUNT,
246
- "ellipsis",
247
- totalPages
248
- ];
249
299
  };
250
300
 
251
301
  // src/Pagination.tsx
252
302
  var import_jsx_runtime2 = require("react/jsx-runtime");
303
+ var renderPage = (page, isCurrentPage, handleClick) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
304
+ PaginationPageButtonStyled,
305
+ {
306
+ $isActive: isCurrentPage,
307
+ "aria-current": isCurrentPage ? "page" : false,
308
+ "aria-label": `Go to page ${page}`,
309
+ "data-testid": isCurrentPage ? "pagination-current-page" : `pagination-page-${page}`,
310
+ onClick: () => handleClick(page),
311
+ title: `Go to page ${page}`,
312
+ children: page
313
+ },
314
+ page
315
+ );
253
316
  var Pagination = ({
254
317
  currentPage,
255
318
  totalPages,
@@ -262,12 +325,23 @@ var Pagination = ({
262
325
  itemsPerPageOptions = ITEMS_PER_PAGE_OPTIONS,
263
326
  dataTestId
264
327
  }) => {
265
- const pageNumbers = (0, import_react.useMemo)(
266
- () => getPageNumbers(currentPage, totalPages),
267
- [currentPage, totalPages]
268
- );
328
+ const LAST_PAGE = totalPages;
329
+ const previousPageRef = (0, import_react.useRef)(currentPage);
330
+ const paginationDirection = currentPage < previousPageRef.current ? "BACKWARD" : "FORWARD";
331
+ (0, import_react.useEffect)(() => {
332
+ if (currentPage < 2 || currentPage > LAST_PAGE - 1) {
333
+ previousPageRef.current = currentPage;
334
+ }
335
+ }, [currentPage, LAST_PAGE]);
336
+ const isLastPage = currentPage === LAST_PAGE;
269
337
  const isFirstPage = currentPage === FIRST_PAGE;
270
- const isLastPage = currentPage === totalPages;
338
+ const {
339
+ pages,
340
+ shouldRenderFirstPage,
341
+ shouldRenderLastPage,
342
+ shouldRenderLeftEllipsis,
343
+ shouldRenderRightEllipsis
344
+ } = getPageNumbers(currentPage, LAST_PAGE, paginationDirection);
271
345
  const itemsBeforeCurrentPage = (currentPage - FIRST_PAGE) * itemsPerPage;
272
346
  const remainingItems = Math.max(
273
347
  0,
@@ -277,12 +351,12 @@ var Pagination = ({
277
351
  const hasInfoSection = showItemsPerPage || showItemsInfo && totalItems !== void 0;
278
352
  const handlePageChange = (0, import_react.useCallback)(
279
353
  (page) => {
280
- const canNavigateToPage = page !== currentPage && page >= FIRST_PAGE && page <= totalPages;
354
+ const canNavigateToPage = page !== currentPage && page >= FIRST_PAGE && page <= LAST_PAGE;
281
355
  if (canNavigateToPage) {
282
356
  onPageChange(page);
283
357
  }
284
358
  },
285
- [currentPage, totalPages, onPageChange]
359
+ [currentPage, LAST_PAGE, onPageChange]
286
360
  );
287
361
  const handleItemsPerPageChange = (0, import_react.useCallback)(
288
362
  (value) => {
@@ -351,31 +425,27 @@ var Pagination = ({
351
425
  tooltipLabel: "Previous page"
352
426
  }
353
427
  ),
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": page === currentPage ? "pagination-current-page" : `pagination-page-${page}`,
372
- onClick: () => handlePageChange(page),
373
- title: `Go to page ${page}`,
374
- children: page
375
- },
376
- page
377
- );
378
- }),
428
+ shouldRenderFirstPage ? renderPage(FIRST_PAGE, isFirstPage, handlePageChange) : null,
429
+ shouldRenderLeftEllipsis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
430
+ TruncationTextStyled,
431
+ {
432
+ "data-testid": "pagination-ellipsis",
433
+ children: "..."
434
+ },
435
+ "ellipsis-left"
436
+ ) : null,
437
+ pages.map(
438
+ (page) => renderPage(page, page === currentPage, handlePageChange)
439
+ ),
440
+ shouldRenderRightEllipsis ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
441
+ TruncationTextStyled,
442
+ {
443
+ "data-testid": "pagination-ellipsis",
444
+ children: "..."
445
+ },
446
+ "ellipsis-right"
447
+ ) : null,
448
+ shouldRenderLastPage ? renderPage(LAST_PAGE, isLastPage, handlePageChange) : null,
379
449
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
380
450
  PaginationNavButton,
381
451
  {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/Pagination.tsx
2
- import { useMemo, useCallback } from "react";
2
+ import { useCallback, useEffect, useRef } from "react";
3
3
  import { Select } from "@dt-dds/react-select";
4
4
 
5
5
  // src/components/PaginationNavButton/PaginationNavButton.tsx
@@ -180,35 +180,98 @@ var PaginationNavButton = ({
180
180
  PaginationNavButton.displayName = "PaginationNavButton";
181
181
 
182
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);
183
+ var getCompactPageNumbers = (firstPage, lastPage) => ({
184
+ pages: Array.from(
185
+ { length: Math.max(lastPage - firstPage + 1, 0) },
186
+ (_, index) => firstPage + index
187
+ ),
188
+ shouldRenderFirstPage: false,
189
+ shouldRenderLastPage: false,
190
+ shouldRenderLeftEllipsis: false,
191
+ shouldRenderRightEllipsis: false
192
+ });
193
+ var getForwardPageNumbers = (currentPage, firstPage, lastPage) => {
194
+ if (currentPage <= firstPage + 1) {
195
+ return {
196
+ pages: [firstPage, firstPage + 1, firstPage + 2],
197
+ shouldRenderFirstPage: false,
198
+ shouldRenderLastPage: true,
199
+ shouldRenderLeftEllipsis: false,
200
+ shouldRenderRightEllipsis: true
201
+ };
190
202
  }
191
- const showLeftEllipsis = currentPage > START_BOUNDARY;
192
- const showRightEllipsis = currentPage < totalPages - END_OFFSET;
193
- if (!showLeftEllipsis && showRightEllipsis) {
194
- return [1, 2, 3, "ellipsis", totalPages];
203
+ if (currentPage <= lastPage - 3) {
204
+ return {
205
+ pages: [currentPage - 1, currentPage, currentPage + 1],
206
+ shouldRenderFirstPage: false,
207
+ shouldRenderLastPage: true,
208
+ shouldRenderLeftEllipsis: false,
209
+ shouldRenderRightEllipsis: true
210
+ };
195
211
  }
196
- if (showLeftEllipsis && !showRightEllipsis) {
197
- return [1, "ellipsis", totalPages - 2, totalPages - 1, totalPages];
212
+ return {
213
+ pages: [lastPage - 2, lastPage - 1, lastPage],
214
+ shouldRenderFirstPage: true,
215
+ shouldRenderLastPage: false,
216
+ shouldRenderLeftEllipsis: true,
217
+ shouldRenderRightEllipsis: false
218
+ };
219
+ };
220
+ var getBackwardPageNumbers = (currentPage, firstPage, lastPage) => {
221
+ if (currentPage <= firstPage + 2) {
222
+ return {
223
+ pages: [firstPage, firstPage + 1, firstPage + 2],
224
+ shouldRenderFirstPage: false,
225
+ shouldRenderLastPage: true,
226
+ shouldRenderLeftEllipsis: false,
227
+ shouldRenderRightEllipsis: true
228
+ };
229
+ }
230
+ if (currentPage >= lastPage - 1) {
231
+ return {
232
+ pages: [lastPage - 2, lastPage - 1, lastPage],
233
+ shouldRenderFirstPage: true,
234
+ shouldRenderLastPage: false,
235
+ shouldRenderLeftEllipsis: true,
236
+ shouldRenderRightEllipsis: false
237
+ };
238
+ }
239
+ return {
240
+ pages: [currentPage - 1, currentPage, currentPage + 1],
241
+ shouldRenderFirstPage: true,
242
+ shouldRenderLastPage: false,
243
+ shouldRenderLeftEllipsis: true,
244
+ shouldRenderRightEllipsis: false
245
+ };
246
+ };
247
+ var getPageNumbers = (currentPage, lastPage, direction = "FORWARD") => {
248
+ const firstPage = FIRST_PAGE;
249
+ const cursor = Math.max(Math.min(currentPage, lastPage), firstPage);
250
+ if (lastPage <= firstPage + 4) {
251
+ return getCompactPageNumbers(firstPage, lastPage);
252
+ }
253
+ if (direction === "BACKWARD") {
254
+ return getBackwardPageNumbers(cursor, firstPage, lastPage);
255
+ } else {
256
+ return getForwardPageNumbers(cursor, firstPage, lastPage);
198
257
  }
199
- return [
200
- 1,
201
- "ellipsis",
202
- currentPage - NEIGHBOR_COUNT,
203
- currentPage,
204
- currentPage + NEIGHBOR_COUNT,
205
- "ellipsis",
206
- totalPages
207
- ];
208
258
  };
209
259
 
210
260
  // src/Pagination.tsx
211
261
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
262
+ var renderPage = (page, isCurrentPage, handleClick) => /* @__PURE__ */ jsx2(
263
+ PaginationPageButtonStyled,
264
+ {
265
+ $isActive: isCurrentPage,
266
+ "aria-current": isCurrentPage ? "page" : false,
267
+ "aria-label": `Go to page ${page}`,
268
+ "data-testid": isCurrentPage ? "pagination-current-page" : `pagination-page-${page}`,
269
+ onClick: () => handleClick(page),
270
+ title: `Go to page ${page}`,
271
+ children: page
272
+ },
273
+ page
274
+ );
212
275
  var Pagination = ({
213
276
  currentPage,
214
277
  totalPages,
@@ -221,12 +284,23 @@ var Pagination = ({
221
284
  itemsPerPageOptions = ITEMS_PER_PAGE_OPTIONS,
222
285
  dataTestId
223
286
  }) => {
224
- const pageNumbers = useMemo(
225
- () => getPageNumbers(currentPage, totalPages),
226
- [currentPage, totalPages]
227
- );
287
+ const LAST_PAGE = totalPages;
288
+ const previousPageRef = useRef(currentPage);
289
+ const paginationDirection = currentPage < previousPageRef.current ? "BACKWARD" : "FORWARD";
290
+ useEffect(() => {
291
+ if (currentPage < 2 || currentPage > LAST_PAGE - 1) {
292
+ previousPageRef.current = currentPage;
293
+ }
294
+ }, [currentPage, LAST_PAGE]);
295
+ const isLastPage = currentPage === LAST_PAGE;
228
296
  const isFirstPage = currentPage === FIRST_PAGE;
229
- const isLastPage = currentPage === totalPages;
297
+ const {
298
+ pages,
299
+ shouldRenderFirstPage,
300
+ shouldRenderLastPage,
301
+ shouldRenderLeftEllipsis,
302
+ shouldRenderRightEllipsis
303
+ } = getPageNumbers(currentPage, LAST_PAGE, paginationDirection);
230
304
  const itemsBeforeCurrentPage = (currentPage - FIRST_PAGE) * itemsPerPage;
231
305
  const remainingItems = Math.max(
232
306
  0,
@@ -236,12 +310,12 @@ var Pagination = ({
236
310
  const hasInfoSection = showItemsPerPage || showItemsInfo && totalItems !== void 0;
237
311
  const handlePageChange = useCallback(
238
312
  (page) => {
239
- const canNavigateToPage = page !== currentPage && page >= FIRST_PAGE && page <= totalPages;
313
+ const canNavigateToPage = page !== currentPage && page >= FIRST_PAGE && page <= LAST_PAGE;
240
314
  if (canNavigateToPage) {
241
315
  onPageChange(page);
242
316
  }
243
317
  },
244
- [currentPage, totalPages, onPageChange]
318
+ [currentPage, LAST_PAGE, onPageChange]
245
319
  );
246
320
  const handleItemsPerPageChange = useCallback(
247
321
  (value) => {
@@ -310,31 +384,27 @@ var Pagination = ({
310
384
  tooltipLabel: "Previous page"
311
385
  }
312
386
  ),
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": page === currentPage ? "pagination-current-page" : `pagination-page-${page}`,
331
- onClick: () => handlePageChange(page),
332
- title: `Go to page ${page}`,
333
- children: page
334
- },
335
- page
336
- );
337
- }),
387
+ shouldRenderFirstPage ? renderPage(FIRST_PAGE, isFirstPage, handlePageChange) : null,
388
+ shouldRenderLeftEllipsis ? /* @__PURE__ */ jsx2(
389
+ TruncationTextStyled,
390
+ {
391
+ "data-testid": "pagination-ellipsis",
392
+ children: "..."
393
+ },
394
+ "ellipsis-left"
395
+ ) : null,
396
+ pages.map(
397
+ (page) => renderPage(page, page === currentPage, handlePageChange)
398
+ ),
399
+ shouldRenderRightEllipsis ? /* @__PURE__ */ jsx2(
400
+ TruncationTextStyled,
401
+ {
402
+ "data-testid": "pagination-ellipsis",
403
+ children: "..."
404
+ },
405
+ "ellipsis-right"
406
+ ) : null,
407
+ shouldRenderLastPage ? renderPage(LAST_PAGE, isLastPage, handlePageChange) : null,
338
408
  /* @__PURE__ */ jsx2(
339
409
  PaginationNavButton,
340
410
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dt-dds/react-pagination",
3
- "version": "1.0.0-beta.46",
3
+ "version": "1.0.0-beta.48",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./dist/index.js"
@@ -24,7 +24,7 @@
24
24
  "@dt-dds/react-typography": "1.0.0-beta.50",
25
25
  "@dt-dds/react-icon": "1.0.0-beta.63",
26
26
  "@dt-dds/icons": "1.0.0-beta.6",
27
- "@dt-dds/react-select": "1.0.0-beta.96",
27
+ "@dt-dds/react-select": "1.0.0-beta.97",
28
28
  "@dt-dds/react-tooltip": "1.0.0-beta.69",
29
29
  "@dt-dds/themes": "1.0.0-beta.14"
30
30
  },