carbon-components-svelte/src/Pagination/Pagination.svelte
metonym 78d3f1328a
feat(select): support selected prop number type (#1355)
* feat(select): support number type

* Run "yarn build:docs"

* refactor(pagination): do not coerce `pageSize`, `page` to be numbers

* test(select): assert selected prop number type
2022-06-18 11:09:41 -07:00

181 lines
5.2 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script>
/**
* @event {{ pageSize: number; page: number; }} update
* @event {{ page: number; }} click:button--previous
* @event {{ page: number; }} click:button--next
*/
/** Specify the current page index */
export let page = 1;
/** Specify the total number of items */
export let totalItems = 0;
/** Set to `true` to disable the pagination */
export let disabled = false;
/** Specify the forward button text */
export let forwardText = "Next page";
/** Specify the backward button text */
export let backwardText = "Previous page";
/** Specify the items per page text */
export let itemsPerPageText = "Items per page:";
/**
* Override the item text
* @type {(min: number, max: number) => string}
*/
export let itemText = (min, max) => `${min}${max} items`;
/**
* Override the item range text
* @type {(min: number, max: number, total: number) => string}
*/
export let itemRangeText = (min, max, total) =>
`${min}${max} of ${total} items`;
/** Set to `true` to disable the page input */
export let pageInputDisabled = false;
/** Set to `true` to disable the page size input */
export let pageSizeInputDisabled = false;
/** Specify the number of items to display in a page */
export let pageSize = 10;
/**
* Specify the available page sizes
* @type {ReadonlyArray<number>}
*/
export let pageSizes = [10];
/** Set to `true` if the number of pages is unknown */
export let pagesUnknown = false;
/**
* Override the page text
* @type {(page: number) => string}
*/
export let pageText = (page) => `page ${page}`;
/**
* Override the page range text
* @type {(current: number, total: number) => string}
*/
export let pageRangeText = (current, total) =>
`of ${total} page${total === 1 ? "" : "s"}`;
/** Set an id for the top-level element */
export let id = "ccs-" + Math.random().toString(36);
import { afterUpdate, createEventDispatcher } from "svelte";
import CaretLeft from "../icons/CaretLeft.svelte";
import CaretRight from "../icons/CaretRight.svelte";
import Button from "../Button/Button.svelte";
import Select from "../Select/Select.svelte";
import SelectItem from "../Select/SelectItem.svelte";
const dispatch = createEventDispatcher();
afterUpdate(() => {
if (page > totalPages) {
page = totalPages;
}
});
$: dispatch("update", { pageSize, page });
$: totalPages = Math.max(Math.ceil(totalItems / pageSize), 1);
$: selectItems = Array.from({ length: totalPages }, (_, i) => i);
$: backButtonDisabled = disabled || page === 1;
$: forwardButtonDisabled = disabled || page === totalPages;
</script>
<div id="{id}" class:bx--pagination="{true}" {...$$restProps}>
<div class:bx--pagination__left="{true}">
{#if !pageSizeInputDisabled}
<label
id="bx--pagination-select-{id}-count-label"
for="bx--pagination-select-{id}"
class:bx--pagination__text="{true}"
>
{itemsPerPageText}
</label>
<Select
id="bx--pagination-select-{id}"
class="bx--select__item-count"
hideLabel
noLabel
inline
bind:selected="{pageSize}"
>
{#each pageSizes as size, i (size)}
<SelectItem value="{size}" text="{size.toString()}" />
{/each}
</Select>
{/if}
<span class:bx--pagination__text="{!pageSizeInputDisabled}">
{#if pagesUnknown}
{itemText(pageSize * (page - 1) + 1, page * pageSize)}
{:else}
{itemRangeText(
Math.min(pageSize * (page - 1) + 1, totalItems),
Math.min(page * pageSize, totalItems),
totalItems
)}
{/if}
</span>
</div>
<div class:bx--pagination__right="{true}">
{#if !pageInputDisabled}
<Select
id="bx--pagination-select-{id + 2}"
class="bx--select__page-number"
labelText="Page number, of {totalPages} pages"
inline
hideLabel
bind:selected="{page}"
>
{#each selectItems as size, i (size)}
<SelectItem value="{size + 1}" text="{(size + 1).toString()}" />
{/each}
</Select>
<span class:bx--pagination__text="{true}">
{#if pagesUnknown}
{pageText(page)}
{:else}{pageRangeText(page, totalPages)}{/if}
</span>
{/if}
<Button
kind="ghost"
tooltipAlignment="center"
tooltipPosition="top"
icon="{CaretLeft}"
iconDescription="{backwardText}"
disabled="{backButtonDisabled}"
class="bx--pagination__button bx--pagination__button--backward {backButtonDisabled
? 'bx--pagination__button--no-index'
: ''}"
on:click="{() => {
page--;
dispatch('click:button--previous', { page });
}}"
/>
<Button
kind="ghost"
tooltipAlignment="end"
tooltipPosition="top"
icon="{CaretRight}"
iconDescription="{forwardText}"
disabled="{forwardButtonDisabled}"
class="bx--pagination__button bx--pagination__button--forward {forwardButtonDisabled
? 'bx--pagination__button--no-index'
: ''}"
on:click="{() => {
page++;
dispatch('click:button--next', { page });
}}"
/>
</div>
</div>