mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
fix(pagination): window totalItems
This commit is contained in:
parent
96d37cc490
commit
0575737913
7 changed files with 102 additions and 20 deletions
|
@ -2681,24 +2681,25 @@ None.
|
|||
|
||||
### Props
|
||||
|
||||
| Prop name | Required | Kind | Reactive | Type | Default value | Description |
|
||||
| :-------------------- | :------- | :--------------- | :------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
||||
| pageSize | No | <code>let</code> | Yes | <code>number</code> | <code>10</code> | Specify the number of items to display in a page |
|
||||
| page | No | <code>let</code> | Yes | <code>number</code> | <code>1</code> | Specify the current page index |
|
||||
| totalItems | No | <code>let</code> | No | <code>number</code> | <code>0</code> | Specify the total number of items |
|
||||
| disabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the pagination |
|
||||
| forwardText | No | <code>let</code> | No | <code>string</code> | <code>"Next page"</code> | Specify the forward button text |
|
||||
| backwardText | No | <code>let</code> | No | <code>string</code> | <code>"Previous page"</code> | Specify the backward button text |
|
||||
| itemsPerPageText | No | <code>let</code> | No | <code>string</code> | <code>"Items per page:"</code> | Specify the items per page text |
|
||||
| itemText | No | <code>let</code> | No | <code>(min: number, max: number) => string</code> | <code>(min, max) => \`${min}–${max} item${max === 1 ? "" : "s"}\`</code> | Override the item text |
|
||||
| itemRangeText | No | <code>let</code> | No | <code>(min: number, max: number, total: number) => string</code> | <code>(min, max, total) => \`${min}–${max} of ${total} item${max === 1 ? "" : "s"}\`</code> | Override the item range text |
|
||||
| pageInputDisabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the page input |
|
||||
| pageSizeInputDisabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the page size input |
|
||||
| pageSizes | No | <code>let</code> | No | <code>ReadonlyArray<number></code> | <code>[10]</code> | Specify the available page sizes |
|
||||
| pagesUnknown | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` if the number of pages is unknown |
|
||||
| pageText | No | <code>let</code> | No | <code>(page: number) => string</code> | <code>(page) => \`page ${page}\`</code> | Override the page text |
|
||||
| pageRangeText | No | <code>let</code> | No | <code>(current: number, total: number) => string</code> | <code>(current, total) => \`of ${total} page${total === 1 ? "" : "s"}\`</code> | Override the page range text |
|
||||
| id | No | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the top-level element |
|
||||
| Prop name | Required | Kind | Reactive | Type | Default value | Description |
|
||||
| :-------------------- | :------- | :--------------- | :------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| pageSize | No | <code>let</code> | Yes | <code>number</code> | <code>10</code> | Specify the number of items to display in a page |
|
||||
| page | No | <code>let</code> | Yes | <code>number</code> | <code>1</code> | Specify the current page index |
|
||||
| totalItems | No | <code>let</code> | No | <code>number</code> | <code>0</code> | Specify the total number of items |
|
||||
| pageWindow | No | <code>let</code> | No | <code>number</code> | <code>1000</code> | If `totalItems` is a large number, it can affect the<br />rendering performance of this component since its value<br />is used to calculate the number of pages in the native<br />select dropdown. This value creates a small window of<br />pages rendered around the current page. By default,<br />a maximum of 1000 select items are rendered. |
|
||||
| disabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the pagination |
|
||||
| forwardText | No | <code>let</code> | No | <code>string</code> | <code>"Next page"</code> | Specify the forward button text |
|
||||
| backwardText | No | <code>let</code> | No | <code>string</code> | <code>"Previous page"</code> | Specify the backward button text |
|
||||
| itemsPerPageText | No | <code>let</code> | No | <code>string</code> | <code>"Items per page:"</code> | Specify the items per page text |
|
||||
| itemText | No | <code>let</code> | No | <code>(min: number, max: number) => string</code> | <code>(min, max) => \`${min}–${max} item${max === 1 ? "" : "s"}\`</code> | Override the item text |
|
||||
| itemRangeText | No | <code>let</code> | No | <code>(min: number, max: number, total: number) => string</code> | <code>(min, max, total) => \`${min}–${max} of ${total} item${max === 1 ? "" : "s"}\`</code> | Override the item range text |
|
||||
| pageInputDisabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the page input |
|
||||
| pageSizeInputDisabled | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to disable the page size input |
|
||||
| pageSizes | No | <code>let</code> | No | <code>ReadonlyArray<number></code> | <code>[10]</code> | Specify the available page sizes |
|
||||
| pagesUnknown | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` if the number of pages is unknown |
|
||||
| pageText | No | <code>let</code> | No | <code>(page: number) => string</code> | <code>(page) => \`page ${page}\`</code> | Override the page text |
|
||||
| pageRangeText | No | <code>let</code> | No | <code>(current: number, total: number) => string</code> | <code>(current, total) => \`of ${total} page${total === 1 ? "" : "s"}\`</code> | Override the page range text |
|
||||
| id | No | <code>let</code> | No | <code>string</code> | <code>"ccs-" + Math.random().toString(36)</code> | Set an id for the top-level element |
|
||||
|
||||
### Slots
|
||||
|
||||
|
|
|
@ -10048,6 +10048,18 @@
|
|||
"constant": false,
|
||||
"reactive": false
|
||||
},
|
||||
{
|
||||
"name": "pageWindow",
|
||||
"kind": "let",
|
||||
"description": "If `totalItems` is a large number, it can affect the\nrendering performance of this component since its value\nis used to calculate the number of pages in the native\nselect dropdown. This value creates a small window of\npages rendered around the current page. By default,\na maximum of 1000 select items are rendered.",
|
||||
"type": "number",
|
||||
"value": "1000",
|
||||
"isFunction": false,
|
||||
"isFunctionDeclaration": false,
|
||||
"isRequired": false,
|
||||
"constant": false,
|
||||
"reactive": false
|
||||
},
|
||||
{
|
||||
"name": "disabled",
|
||||
"kind": "let",
|
||||
|
|
|
@ -19,6 +19,19 @@ components: ["Pagination", "PaginationSkeleton"]
|
|||
|
||||
<Pagination totalItems={102} pageSizes="{[16, 36, 99]}" pageSize="{36}" />
|
||||
|
||||
## Page window
|
||||
|
||||
The number of native select items rendered is derived from the value of `totalItems`.
|
||||
|
||||
If `totalItems` is a very large number, this can impact rendering performance since
|
||||
thousands of elements may be rendered. By default, the window of rendered items is
|
||||
capped at 1,000. For example, if `totalItems=100_000` and the `pageSize=10`,
|
||||
1,000 select options are rendered.
|
||||
|
||||
Use the `pageWindow` prop to increase this value.
|
||||
|
||||
<Pagination totalItems={100_000} pageSizes={[10, 15, 20]} />
|
||||
|
||||
## Hidden page input
|
||||
|
||||
<Pagination totalItems={102} pageInputDisabled />
|
||||
|
|
|
@ -12,6 +12,16 @@
|
|||
/** Specify the total number of items */
|
||||
export let totalItems = 0;
|
||||
|
||||
/**
|
||||
* If `totalItems` is a large number, it can affect the
|
||||
* rendering performance of this component since its value
|
||||
* is used to calculate the number of pages in the native
|
||||
* select dropdown. This value creates a small window of
|
||||
* pages rendered around the current page. By default,
|
||||
* a maximum of 1000 select items are rendered.
|
||||
*/
|
||||
export let pageWindow = 1000;
|
||||
|
||||
/** Set to `true` to disable the pagination */
|
||||
export let disabled = false;
|
||||
|
||||
|
@ -81,6 +91,21 @@
|
|||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
/**
|
||||
* Returns a subset of page numbers centered around the current page to prevent
|
||||
* performance issues with large datasets. Creates a capped window of pages
|
||||
* instead of potentially thousands, improving render speed and memory usage.
|
||||
* @param {number} currentPage - The current page number
|
||||
* @param {number} totalPages - Total number of pages
|
||||
* @param {number} window - How many pages to show before/after current page
|
||||
* @returns {number[]} Array of page numbers to display
|
||||
*/
|
||||
function getWindowedPages(currentPage, totalPages, window) {
|
||||
const start = Math.max(1, currentPage - window);
|
||||
const end = Math.min(totalPages, currentPage + window);
|
||||
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
||||
}
|
||||
|
||||
afterUpdate(() => {
|
||||
if (page > totalPages) {
|
||||
page = totalPages;
|
||||
|
@ -89,7 +114,7 @@
|
|||
|
||||
$: dispatch("update", { pageSize, page });
|
||||
$: totalPages = Math.max(Math.ceil(totalItems / pageSize), 1);
|
||||
$: selectItems = Array.from({ length: totalPages }, (_, i) => i);
|
||||
$: selectItems = getWindowedPages(page, totalPages, pageWindow);
|
||||
$: backButtonDisabled = disabled || page === 1;
|
||||
$: forwardButtonDisabled = disabled || page === totalPages;
|
||||
</script>
|
||||
|
@ -146,7 +171,7 @@
|
|||
bind:selected={page}
|
||||
>
|
||||
{#each selectItems as size, i (size)}
|
||||
<SelectItem value={size + 1} text={(size + 1).toString()} />
|
||||
<SelectItem value={size} text={size.toString()} />
|
||||
{/each}
|
||||
</Select>
|
||||
<span class:bx--pagination__text={true}>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
export let pageSizeInputDisabled = false;
|
||||
export let pageSize = 10;
|
||||
export let pageSizes: ReadonlyArray<number> = [10];
|
||||
export let pageWindow: undefined | number = undefined;
|
||||
export let pagesUnknown = false;
|
||||
</script>
|
||||
|
||||
|
@ -23,6 +24,7 @@
|
|||
{itemsPerPageText}
|
||||
{pageInputDisabled}
|
||||
{pageSizeInputDisabled}
|
||||
{pageWindow}
|
||||
bind:pageSize
|
||||
{pageSizes}
|
||||
{pagesUnknown}
|
||||
|
|
|
@ -196,4 +196,22 @@ describe("Pagination", () => {
|
|||
|
||||
expect(screen.getByText("0–0 of 0 items")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders a cap of 1000 page numbers by default", () => {
|
||||
render(Pagination, {
|
||||
props: { totalItems: 100_000 },
|
||||
});
|
||||
|
||||
const pageNumbers = screen.getByLabelText(/Page number, of 10000 pages/);
|
||||
expect(pageNumbers).toHaveLength(1_000 + 1);
|
||||
});
|
||||
|
||||
it("renders a custom page window", () => {
|
||||
render(Pagination, {
|
||||
props: { totalItems: 100_000, pageWindow: 100 },
|
||||
});
|
||||
|
||||
const pageNumbers = screen.getByLabelText(/Page number, of 10000 pages/);
|
||||
expect(pageNumbers).toHaveLength(100 + 1);
|
||||
});
|
||||
});
|
||||
|
|
11
types/Pagination/Pagination.svelte.d.ts
vendored
11
types/Pagination/Pagination.svelte.d.ts
vendored
|
@ -16,6 +16,17 @@ type $Props = {
|
|||
*/
|
||||
totalItems?: number;
|
||||
|
||||
/**
|
||||
* If `totalItems` is a large number, it can affect the
|
||||
* rendering performance of this component since its value
|
||||
* is used to calculate the number of pages in the native
|
||||
* select dropdown. This value creates a small window of
|
||||
* pages rendered around the current page. By default,
|
||||
* a maximum of 1000 select items are rendered.
|
||||
* @default 1000
|
||||
*/
|
||||
pageWindow?: number;
|
||||
|
||||
/**
|
||||
* Set to `true` to disable the pagination
|
||||
* @default false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue