import type { Snippet } from 'svelte'; import type { HTMLAttributes } from 'svelte/elements'; import type { MintProp } from '../../mint/index.js'; import type { InteractiveTier } from '../../utils/tier-context.js'; import type { PaginationSlots, PaginationVariants } from './pagination.variants.js'; export interface PaginationPageItem { label: string; value: number; href?: string; active?: boolean; disabled?: boolean; } /** * Context handed to the `renderItem` snippet for a single numbered page button. * Bundles the page number, its active/disabled state, the style props forwarded * from the Pagination (so a custom item stays visually consistent), and a * `select` callback that changes the page (guarded against disabled / no-op / * out-of-range internally). */ export interface PaginationItemContext { /** The 1-based page number this item represents. */ page: number; /** Whether this item is the currently active page. */ active: boolean; /** Whether the item is inert (component `disabled` or `loading`). */ disabled: boolean; /** Button size forwarded from the Pagination props. */ size: 'sm' | 'md' | 'lg'; /** Button variant forwarded from the Pagination props. * @summary How much weight the page buttons carry. */ variant: 'outlined' | 'filled' | 'ghost'; /** Semantic intent forwarded from the Pagination props. */ intent: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral'; /** Semantic radius tier forwarded from the Pagination props. */ tier?: InteractiveTier; /** Micro-interaction preset forwarded from the Pagination props. */ mint: MintProp; /** Navigate to this page. No-op when disabled, already active, or out of range. */ select: () => void; } /** * @summary Page through a longer list, in whichever layout fits. * @description Navigation control for paged data sets. * Supports multiple layouts, intents, button variants, and configurable ellipsis behaviour. * * @tag navigation * @related Table * * @example * ```svelte * page = p} * /> * ``` */ export interface PaginationProps extends Omit, Omit, 'class'> { /** 1-based index of the currently active page. */ currentPage: number; /** Total number of pages in the data set. */ totalPages: number; /** * Visual weight of pagination buttons. The current page carries its own * encoding regardless (a filled face on `outlined`, a subtle fill plus ring * on `ghost`), so the quiet default keeps a nine-button page window from * reading as a row of equally loud pills. * * @default 'ghost' * @summary Visual weight of the page buttons; the current page is marked either way. */ variant?: 'outlined' | 'filled' | 'ghost'; /** Semantic color applied to every pagination button. @default 'primary' */ intent?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'neutral'; /** Button dimensions. Affects page numbers, prev/next, and first/last. @default 'md' */ size?: 'sm' | 'md' | 'lg'; /** Semantic radius tier forwarded to pagination buttons. */ tier?: InteractiveTier; /** Maximum number of page buttons shown between the ellipsis indicators. */ visiblePages?: number; /** * Show "First" / "Last" boundary buttons when the current page is far from * the edges. Deliberately redundancy-gated to the number window: the buttons * render only beside a start/end ellipsis, so without `showNumbers` there is * no number window, no ellipsis — and no First/Last buttons. That coupling is * intentional (a compact prev/next-only bar stays compact), not a bug. * Setting `showFirstLast` explicitly while `showNumbers` is `false` warns * once per instance in dev. @default true * @summary Adds First / Last buttons when the current page is far from either end. */ showFirstLast?: boolean; /** Show "Previous" / "Next" navigation buttons. */ showPreviousNext?: boolean; /** Show numbered page buttons. Set to false for a compact prev/next-only bar. */ showNumbers?: boolean; /** Show a text summary such as "Page 3 of 10" beneath the controls. */ showInfo?: boolean; /** Label for the "Previous" button. Falls back to i18n key `pagination.previous`. */ previousLabel?: string; /** Label for the "Next" button. Falls back to i18n key `pagination.next`. */ nextLabel?: string; /** Label for the "First" button. Falls back to i18n key `pagination.first`. */ firstLabel?: string; /** Label for the "Last" button. Falls back to i18n key `pagination.last`. */ lastLabel?: string; /** Prefix for the info text (e.g. "Page"). Falls back to i18n key `pagination.page`. */ pageLabel?: string; /** Override the auto-generated info text with a fully custom string. */ infoText?: string; /** Custom icon rendered inside the "Previous" button. */ previousIcon?: Snippet; /** Custom icon rendered inside the "Next" button. */ nextIcon?: Snippet; /** Custom icon rendered inside the "First" button. */ firstIcon?: Snippet; /** Custom icon rendered inside the "Last" button. */ lastIcon?: Snippet; /** * Render each numbered page button yourself. Receives a {@link PaginationItemContext} * with the page number, its active/disabled state, the forwarded style props * (size, variant, intent, tier, mint) and a `select` callback. Only affects the * numbered page buttons in the default layout — prev/next/first/last keep their * own icon snippets, and the ellipsis is unaffected. * * @example * ```svelte * * {#snippet renderItem({ page, active, disabled, select })} * * {/snippet} * * ``` */ renderItem?: Snippet<[PaginationItemContext]>; /** Items shown per page. Used by the table layout to compute "Showing X to Y of Z". */ itemsPerPage?: number; /** Total number of items across all pages. Used by the table layout info text. */ totalItems?: number; /** Override the calculated start item number for the info text. */ startItem?: number; /** Override the calculated end item number for the info text. */ endItem?: number; /** Fires when the user selects a different page. Receives the 1-based page number. */ onPageChange?: (page: number) => void; /** Disables all buttons and dims the component. */ disabled?: boolean; /** Shows a loading state with reduced opacity. */ loading?: boolean; /** * Micro-interaction preset forwarded to the inner buttons (page items, * prev/next, first/last). * @default 'none' */ mint?: MintProp; /** Additional CSS classes merged onto the root `