stories/Pagination.svelte (114 lines of code) (raw):

<script> import BackButton from "../src/components/icons/BackButton.svelte"; import ForwardButton from "../src/components/icons/ForwardButton.svelte"; export let itemsPerPage; export let totalItems; let from; let to; let lastPage; let currentPage = 1; const truncatedPagination = (current, last) => { const center = [ current - 2, current - 1, current, current + 1, current + 2, ]; const filteredCenter = center.filter((p) => p > 1 && p < last); const includeThreeLeft = current === 5; const includeThreeRight = current === last - 4; const includeLeftDots = current > 5; const includeRightDots = current < last - 4; if (includeThreeLeft) filteredCenter.unshift(2); if (includeThreeRight) filteredCenter.push(last - 1); if (includeLeftDots) filteredCenter.unshift("..."); if (includeRightDots) filteredCenter.push("..."); return [1, ...filteredCenter, last]; }; function changePage(page) { if (page !== currentPage) { currentPage = page; } } $: { lastPage = Math.ceil(totalItems / itemsPerPage); from = 1 + itemsPerPage * (currentPage - 1); if (currentPage * itemsPerPage > totalItems) { to = totalItems; } else { to = currentPage * itemsPerPage; } } </script> <div class="pagination-position"> <p> Page <code>{currentPage}</code> of <code>{lastPage}</code> (<code>{from}</code> - <code>{to}</code> on <code>{totalItems}</code> items) </p> </div> {#if itemsPerPage < totalItems} <div class="pagination-bar"> <div on:click|preventDefault={() => changePage(currentPage !== 1 ? currentPage - 1 : 1)} class="pagination-button {currentPage === 1 ? 'current-page' : ''}" > <BackButton /> </div> <div class="pages"> {#each truncatedPagination(currentPage, lastPage) as page} <div on:click|preventDefault={() => changePage(Number.isInteger(page) ? page : currentPage)} class="page {page === currentPage ? 'current-page' : ''}" > {page} </div> {/each} </div> <div on:click|preventDefault={() => changePage(currentPage !== lastPage ? currentPage + 1 : lastPage)} class="pagination-button {currentPage === lastPage ? 'current-page' : ''}" > <ForwardButton /> </div> </div> {/if} <style lang="scss"> .pagination-position { margin-top: 3rem; } .pagination-bar { display: flex; justify-content: center; .pagination-button { height: 2.5rem; width: 2.5rem; } .pages { display: flex; justify-content: center; .page { @include text-body-md; height: 3rem; font-weight: bold; margin: $spacing-sm; cursor: pointer; } } .current-page { color: $color-light-gray-70; cursor: not-allowed; } } </style>