gridsmith-ui 0.12.0 → 0.14.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/components/DataGrid.tsx"],"names":[],"mappings":"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","file":"data-grid.js","sourcesContent":["import { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport { useShellPreferences } from \"../lib/preferences\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getPaginationRowModel,\n flexRender,\n type CellContext,\n type ColumnDef,\n type SortingState,\n} from \"@tanstack/react-table\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Tooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useBreakpoint, type BreakpointKey } from \"../lib/use-breakpoint\";\nimport { inferColumnKinds, type ColumnKind } from \"../lib/table-utils\";\nimport { CardValue } from \"../lib/card-cell\";\nimport { TableCardCtx } from \"../lib/surface-context\";\n\n/** Column meta for opt-in truncation. Set on ColumnDef.meta. */\nexport interface DataGridColumnMeta {\n /** true = single-line, or { lines: N } for multi-line clamp. */\n truncate?: boolean | { lines: number };\n /** CSS max-width for the column. */\n maxWidth?: string;\n /** CSS width for the column — sibling grids that share a column set line up when their columns carry the same widths (round 14). */\n width?: string;\n /** CSS min-width for the column. */\n minWidth?: string;\n /** Explicit column kind. When omitted the DataGrid infers it from data values. */\n kind?: ColumnKind;\n /** Horizontal alignment of the header and the cells; a block element (a Checkbox, a Button) is laid out with flex so it follows too (round 14). Default: numbers right, everything else left. */\n align?: \"left\" | \"center\" | \"right\";\n}\n\nfunction TruncCell({ children, lines }: { children: ReactNode; lines: number }) {\n const { ref, isTruncated } = useTextOverflow({ lines });\n const clampClass = lines === 1 ? \"truncate\" : `line-clamp-${lines}`;\n const cell = <span ref={ref} className={cn(clampClass, \"block\")}>{children}</span>;\n if (!isTruncated) return cell;\n return <Tooltip content={children}>{cell}</Tooltip>;\n}\n\nexport interface DataGridProps<T> {\n data: T[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- public API: columns may carry any value type\n columns: ColumnDef<T, any>[];\n pageSize?: number;\n editable?: boolean;\n onCellEdit?: (rowIndex: number, columnId: string, value: unknown) => void;\n /** Breakpoint at which the grid switches to card layout. Defaults to \"md\" (768px). */\n mobileBreakpoint?: BreakpointKey;\n className?: string;\n}\n\nexport function DataGrid<T>({\n data,\n columns,\n pageSize = 10,\n editable = false,\n onCellEdit,\n mobileBreakpoint: mobileBreakpointProp,\n className,\n}: DataGridProps<T>) {\n // Sprint 25.6 (B9): responsive.tableToCardsBreakpoint reaches the table through the shell; a prop wins; md outside any shell.\n const preferences = useShellPreferences();\n const mobileBreakpoint: BreakpointKey = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? \"md\";\n const isMobile = useBreakpoint(mobileBreakpoint);\n const [sorting, setSorting] = useState<SortingState>([]);\n const [editCell, setEditCell] = useState<{ row: number; col: string } | null>(null);\n const [editValue, setEditValue] = useState(\"\");\n\n /* ── Column kind inference ─────────────────────────────────────────── */\n const columnKeys = useMemo(() => columns.map((c) => c.id ?? (\"accessorKey\" in c ? String(c.accessorKey) : \"\")).filter(Boolean), [columns]);\n const inferredKinds = useMemo(\n () => inferColumnKinds(data as Record<string, unknown>[], columnKeys),\n [data, columnKeys],\n );\n const kindOf = useCallback(\n (colId: string, meta: DataGridColumnMeta | undefined) => meta?.kind ?? inferredKinds.get(colId),\n [inferredKinds],\n );\n\n const tableColumns = useMemo(() => {\n if (!editable) return columns;\n return columns.map((col) => ({\n ...col,\n cell: (info: CellContext<T, unknown>) => {\n const rowIdx = info.row.index;\n const colId = info.column.id;\n const isEditing = editCell?.row === rowIdx && editCell?.col === colId;\n\n if (isEditing) {\n return (\n <input\n autoFocus\n className={cn(\n \"w-full h-full bg-transparent text-sm text-[var(--ds-text-primary)]\",\n \"outline-none border-none px-0\",\n )}\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onBlur={() => {\n onCellEdit?.(rowIdx, colId, editValue);\n setEditCell(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n onCellEdit?.(rowIdx, colId, editValue);\n setEditCell(null);\n } else if (e.key === \"Escape\") {\n setEditCell(null);\n }\n }}\n />\n );\n }\n\n const rendered = typeof col.cell === \"function\" ? col.cell(info) : info.getValue();\n return (\n <span\n onDoubleClick={() => {\n setEditCell({ row: rowIdx, col: colId });\n setEditValue(String(info.getValue() ?? \"\"));\n }}\n className=\"cursor-default\"\n >\n {rendered as React.ReactNode}\n </span>\n );\n },\n }));\n }, [columns, editable, editCell, editValue, onCellEdit]);\n\n // TanStack Table returns functions the React Compiler cannot memoise; the\n // compiler would skip this component, which is fine — the project does not\n // use it. The note is informational, not a defect.\n // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table is not compiler-compatible\n const table = useReactTable({\n data,\n columns: tableColumns,\n state: { sorting },\n onSortingChange: setSorting,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n initialState: { pagination: { pageSize } },\n });\n\n const handlePageChange = useCallback(\n (page: number) => table.setPageIndex(page),\n [table],\n );\n\n const pageCount = table.getPageCount();\n const currentPage = table.getState().pagination.pageIndex;\n\n if (isMobile) {\n return (\n <div className={cn(\"space-y-ds-3\", className)}>\n <TableCardCtx value={true}>\n <div className=\"flex flex-col gap-ds-3\">\n {table.getRowModel().rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]\",\n \"p-ds-4 space-y-ds-3\",\n )}\n >\n {row.getVisibleCells().map((cell) => (\n <div key={cell.id} className=\"flex justify-between gap-ds-2 text-sm\">\n <span className=\"shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider\">\n {typeof cell.column.columnDef.header === \"string\"\n ? cell.column.columnDef.header\n : cell.column.id}\n </span>\n <CardValue value={flexRender(cell.column.columnDef.cell, cell.getContext())} />\n </div>\n ))}\n </div>\n ))}\n </div>\n </TableCardCtx>\n\n {pageCount > 1 && (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-[var(--ds-text-muted)]\">\n Page {currentPage + 1} of {pageCount}\n </span>\n <div className=\"flex items-center gap-ds-1\">\n <PagerBtn onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 0} label=\"Prev\" />\n <PagerBtn onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage >= pageCount - 1} label=\"Next\" />\n </div>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div className={cn(\"space-y-ds-3\", className)}>\n <div\n className={cn(\n \"w-full overflow-auto rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"shadow-[var(--ds-shadow-card)]\",\n \"bg-[var(--ds-bg-surface)]\",\n )}\n >\n <table className=\"w-full text-sm\">\n <thead className=\"bg-[var(--ds-bg-muted)]\">\n {table.getHeaderGroups().map((hg) => (\n <tr key={hg.id} className=\"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {hg.headers.map((header) => {\n const canSort = header.column.getCanSort();\n const sorted = header.column.getIsSorted();\n const meta = header.column.columnDef.meta as DataGridColumnMeta | undefined;\n const headerKind = kindOf(header.column.id, meta);\n const headerAlign = meta?.align ?? (headerKind === \"number\" ? \"right\" : \"left\");\n const shrink = (headerKind === \"number\" || headerKind === \"date\") && !meta?.maxWidth;\n return (\n <th\n key={header.id}\n className={cn(\n \"px-ds-4 py-ds-3 text-xs font-[var(--ds-weight-heading)] uppercase tracking-wider\",\n headerAlign === \"right\" ? \"text-right\" : headerAlign === \"center\" ? \"text-center\" : \"text-left\",\n shrink && \"w-px whitespace-nowrap\",\n \"text-[var(--ds-text-secondary)]\",\n canSort && \"cursor-pointer select-none hover:text-[var(--ds-text-primary)]\",\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth } : undefined}\n onClick={canSort ? header.column.getToggleSortingHandler() : undefined}\n >\n <span className={cn(\"flex items-center gap-ds-1\", headerAlign === \"right\" && \"justify-end\", headerAlign === \"center\" && \"justify-center\")}>\n {flexRender(header.column.columnDef.header, header.getContext())}\n {canSort && (\n <span className=\"inline-flex flex-col -space-y-ds-1.5\">\n <Icon\n name=\"chevron-up\"\n size={10}\n className={sorted === \"asc\" ? \"text-[var(--ds-accent-primary)]\" : \"opacity-30\"}\n />\n <Icon\n name=\"chevron-down\"\n size={10}\n className={sorted === \"desc\" ? \"text-[var(--ds-accent-primary)]\" : \"opacity-30\"}\n />\n </span>\n )}\n </span>\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => (\n <tr\n key={row.id}\n className={cn(\n \"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0\",\n \"hover:bg-[var(--ds-bg-muted)] transition-colors\",\n )}\n >\n {row.getVisibleCells().map((cell) => {\n const meta = cell.column.columnDef.meta as DataGridColumnMeta | undefined;\n const truncLines = meta?.truncate === true ? 1 : meta?.truncate ? meta.truncate.lines : 0;\n const kind = kindOf(cell.column.id, meta);\n const rendered = flexRender(cell.column.columnDef.cell, cell.getContext());\n\n const shrink = (kind === \"number\" || kind === \"date\") && !meta?.maxWidth;\n let inner: ReactNode;\n if (truncLines > 0) {\n inner = <TruncCell lines={truncLines}>{rendered}</TruncCell>;\n } else if (kind === \"email\") {\n inner = (\n <span className=\"max-w-[40ch] truncate inline-block align-bottom\" title={typeof cell.getValue() === \"string\" ? cell.getValue() as string : undefined}>\n {rendered}\n </span>\n );\n } else {\n inner = rendered;\n }\n // Round 14 (50.2): a centred or right-aligned column lays a block element out with flex — text-align moves inline content only.\n const align = meta?.align ?? (kind === \"number\" ? \"right\" : \"left\");\n const value = cell.getValue();\n if (align !== \"left\" && typeof value !== \"string\" && typeof value !== \"number\" && value !== null && value !== undefined) {\n inner = <div className={cn(\"flex items-center\", align === \"center\" ? \"justify-center\" : \"justify-end\")}>{inner}</div>;\n }\n\n return (\n <td\n key={cell.id}\n className={cn(\n \"px-ds-4 py-ds-3 text-[var(--ds-text-primary)]\",\n align === \"right\" && \"text-right\",\n align === \"center\" && \"text-center\",\n shrink && \"w-px whitespace-nowrap\",\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth } : undefined}\n >\n {inner}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {pageCount > 1 && (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-[var(--ds-text-muted)]\">\n Page {currentPage + 1} of {pageCount}\n </span>\n <div className=\"flex items-center gap-ds-1\">\n <PagerBtn\n onClick={() => handlePageChange(0)}\n disabled={currentPage === 0}\n label=\"First\"\n />\n <PagerBtn\n onClick={() => handlePageChange(currentPage - 1)}\n disabled={currentPage === 0}\n label=\"Prev\"\n />\n {Array.from({ length: Math.min(pageCount, 5) }, (_, i) => {\n let page: number;\n if (pageCount <= 5) {\n page = i;\n } else if (currentPage < 3) {\n page = i;\n } else if (currentPage > pageCount - 4) {\n page = pageCount - 5 + i;\n } else {\n page = currentPage - 2 + i;\n }\n return (\n <PagerBtn\n key={page}\n onClick={() => handlePageChange(page)}\n active={page === currentPage}\n label={String(page + 1)}\n />\n );\n })}\n <PagerBtn\n onClick={() => handlePageChange(currentPage + 1)}\n disabled={currentPage >= pageCount - 1}\n label=\"Next\"\n />\n <PagerBtn\n onClick={() => handlePageChange(pageCount - 1)}\n disabled={currentPage >= pageCount - 1}\n label=\"Last\"\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction PagerBtn({\n onClick,\n disabled,\n active,\n label,\n}: {\n onClick: () => void;\n disabled?: boolean;\n active?: boolean;\n label: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={cn(\n \"h-8 min-w-[32px] px-ds-2 text-xs font-medium rounded-[var(--ds-radius-sm)]\",\n \"transition-colors duration-[var(--ds-transition-speed)] cursor-pointer\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\",\n active\n ? \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\"\n : \"text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n )}\n >\n {label}\n </button>\n );\n}\n"]}
1
+ {"version":3,"sources":["../../../showcase/src/components/DataGrid.tsx"],"names":[],"mappings":"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","file":"data-grid.js","sourcesContent":["import { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport { useShellPreferences } from \"../lib/preferences\";\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getPaginationRowModel,\n flexRender,\n type CellContext,\n type ColumnDef,\n type SortingState,\n} from \"@tanstack/react-table\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Tooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport { useBreakpoint, type BreakpointKey } from \"../lib/use-breakpoint\";\nimport { inferColumnKinds, type ColumnKind } from \"../lib/table-utils\";\nimport { CardValue } from \"../lib/card-cell\";\nimport { TableCardCtx } from \"../lib/surface-context\";\n\n/** Column meta for opt-in truncation. Set on ColumnDef.meta. */\nexport interface DataGridColumnMeta {\n /** true = single-line, or { lines: N } for multi-line clamp. */\n truncate?: boolean | { lines: number };\n /** CSS max-width for the column. */\n maxWidth?: string;\n /** CSS width for the column — sibling grids that share a column set line up when their columns carry the same widths (round 14). */\n width?: string;\n /** CSS min-width for the column. */\n minWidth?: string;\n /** Explicit column kind. When omitted the DataGrid infers it from data values. */\n kind?: ColumnKind;\n /** Horizontal alignment of the header and the cells; a block element (a Checkbox, a Button) is laid out with flex so it follows too (round 14). Default: numbers right, everything else left. */\n align?: \"left\" | \"center\" | \"right\";\n}\n\nfunction TruncCell({ children, lines }: { children: ReactNode; lines: number }) {\n const { ref, isTruncated } = useTextOverflow({ lines });\n const clampClass = lines === 1 ? \"truncate\" : `line-clamp-${lines}`;\n const cell = <span ref={ref} className={cn(clampClass, \"block\")}>{children}</span>;\n if (!isTruncated) return cell;\n return <Tooltip content={children}>{cell}</Tooltip>;\n}\n\nexport interface DataGridProps<T> {\n data: T[];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- public API: columns may carry any value type\n columns: ColumnDef<T, any>[];\n pageSize?: number;\n editable?: boolean;\n onCellEdit?: (rowIndex: number, columnId: string, value: unknown) => void;\n /** Breakpoint at which the grid switches to card layout. Defaults to \"md\" (768px). */\n mobileBreakpoint?: BreakpointKey;\n className?: string;\n}\n\nexport function DataGrid<T>({\n data,\n columns,\n pageSize = 10,\n editable = false,\n onCellEdit,\n mobileBreakpoint: mobileBreakpointProp,\n className,\n}: DataGridProps<T>) {\n // Sprint 25.6 (B9): responsive.tableToCardsBreakpoint reaches the table through the shell; a prop wins; md outside any shell.\n const preferences = useShellPreferences();\n const mobileBreakpoint: BreakpointKey = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? \"md\";\n const isMobile = useBreakpoint(mobileBreakpoint);\n const [sorting, setSorting] = useState<SortingState>([]);\n const [editCell, setEditCell] = useState<{ row: number; col: string } | null>(null);\n const [editValue, setEditValue] = useState(\"\");\n\n /* ── Column kind inference ─────────────────────────────────────────── */\n const columnKeys = useMemo(() => columns.map((c) => c.id ?? (\"accessorKey\" in c ? String(c.accessorKey) : \"\")).filter(Boolean), [columns]);\n const inferredKinds = useMemo(\n () => inferColumnKinds(data as Record<string, unknown>[], columnKeys),\n [data, columnKeys],\n );\n const kindOf = useCallback(\n (colId: string, meta: DataGridColumnMeta | undefined) => meta?.kind ?? inferredKinds.get(colId),\n [inferredKinds],\n );\n\n const tableColumns = useMemo(() => {\n if (!editable) return columns;\n return columns.map((col) => ({\n ...col,\n cell: (info: CellContext<T, unknown>) => {\n const rowIdx = info.row.index;\n const colId = info.column.id;\n const isEditing = editCell?.row === rowIdx && editCell?.col === colId;\n\n if (isEditing) {\n return (\n <input\n autoFocus\n className={cn(\n \"w-full h-full bg-transparent text-sm text-[var(--ds-text-primary)]\",\n \"outline-none border-none px-0\",\n )}\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onBlur={() => {\n onCellEdit?.(rowIdx, colId, editValue);\n setEditCell(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n onCellEdit?.(rowIdx, colId, editValue);\n setEditCell(null);\n } else if (e.key === \"Escape\") {\n setEditCell(null);\n }\n }}\n />\n );\n }\n\n const rendered = typeof col.cell === \"function\" ? col.cell(info) : info.getValue();\n return (\n <span\n onDoubleClick={() => {\n setEditCell({ row: rowIdx, col: colId });\n setEditValue(String(info.getValue() ?? \"\"));\n }}\n className=\"cursor-default\"\n >\n {rendered as React.ReactNode}\n </span>\n );\n },\n }));\n }, [columns, editable, editCell, editValue, onCellEdit]);\n\n // TanStack Table returns functions the React Compiler cannot memoise; the\n // compiler would skip this component, which is fine — the project does not\n // use it. The note is informational, not a defect.\n // eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table is not compiler-compatible\n const table = useReactTable({\n data,\n columns: tableColumns,\n state: { sorting },\n onSortingChange: setSorting,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n initialState: { pagination: { pageSize } },\n });\n\n const handlePageChange = useCallback(\n (page: number) => table.setPageIndex(page),\n [table],\n );\n\n const pageCount = table.getPageCount();\n const currentPage = table.getState().pagination.pageIndex;\n\n if (isMobile) {\n return (\n <div data-ds-list=\"\" className={cn(\"space-y-ds-3\", className)}>\n <TableCardCtx value={true}>\n <div className=\"flex flex-col gap-ds-3\">\n {table.getRowModel().rows.map((row) => (\n <div\n key={row.id}\n className={cn(\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]\",\n \"p-ds-4 space-y-ds-3\",\n )}\n >\n {row.getVisibleCells().map((cell) => (\n <div key={cell.id} className=\"flex justify-between gap-ds-2 text-sm\">\n <span className=\"shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider\">\n {typeof cell.column.columnDef.header === \"string\"\n ? cell.column.columnDef.header\n : cell.column.id}\n </span>\n <CardValue value={flexRender(cell.column.columnDef.cell, cell.getContext())} />\n </div>\n ))}\n </div>\n ))}\n </div>\n </TableCardCtx>\n\n {pageCount > 1 && (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-[var(--ds-text-muted)]\">\n Page {currentPage + 1} of {pageCount}\n </span>\n <div className=\"flex items-center gap-ds-1\">\n <PagerBtn onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 0} label=\"Prev\" />\n <PagerBtn onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage >= pageCount - 1} label=\"Next\" />\n </div>\n </div>\n )}\n </div>\n );\n }\n\n return (\n <div data-ds-list=\"\" className={cn(\"space-y-ds-3\", className)}>\n <div\n className={cn(\n \"w-full overflow-auto rounded-[var(--ds-radius-md)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"shadow-[var(--ds-shadow-card)]\",\n \"bg-[var(--ds-bg-surface)]\",\n )}\n >\n <table className=\"w-full text-sm\">\n <thead className=\"bg-[var(--ds-bg-muted)]\">\n {table.getHeaderGroups().map((hg) => (\n <tr key={hg.id} className=\"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]\">\n {hg.headers.map((header) => {\n const canSort = header.column.getCanSort();\n const sorted = header.column.getIsSorted();\n const meta = header.column.columnDef.meta as DataGridColumnMeta | undefined;\n const headerKind = kindOf(header.column.id, meta);\n const headerAlign = meta?.align ?? (headerKind === \"number\" ? \"right\" : \"left\");\n const shrink = (headerKind === \"number\" || headerKind === \"date\") && !meta?.maxWidth;\n return (\n <th\n key={header.id}\n className={cn(\n \"px-ds-4 py-ds-3 text-xs font-[var(--ds-weight-heading)] uppercase tracking-wider\",\n headerAlign === \"right\" ? \"text-right\" : headerAlign === \"center\" ? \"text-center\" : \"text-left\",\n shrink && \"w-px whitespace-nowrap\",\n \"text-[var(--ds-text-secondary)]\",\n canSort && \"cursor-pointer select-none hover:text-[var(--ds-text-primary)]\",\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth } : undefined}\n onClick={canSort ? header.column.getToggleSortingHandler() : undefined}\n >\n <span className={cn(\"flex items-center gap-ds-1\", headerAlign === \"right\" && \"justify-end\", headerAlign === \"center\" && \"justify-center\")}>\n {flexRender(header.column.columnDef.header, header.getContext())}\n {canSort && (\n <span className=\"inline-flex flex-col -space-y-ds-1.5\">\n <Icon\n name=\"chevron-up\"\n size={10}\n className={sorted === \"asc\" ? \"text-[var(--ds-accent-primary)]\" : \"opacity-30\"}\n />\n <Icon\n name=\"chevron-down\"\n size={10}\n className={sorted === \"desc\" ? \"text-[var(--ds-accent-primary)]\" : \"opacity-30\"}\n />\n </span>\n )}\n </span>\n </th>\n );\n })}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows.map((row) => (\n <tr\n key={row.id}\n className={cn(\n \"border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0\",\n \"hover:bg-[var(--ds-bg-muted)] transition-colors\",\n )}\n >\n {row.getVisibleCells().map((cell) => {\n const meta = cell.column.columnDef.meta as DataGridColumnMeta | undefined;\n const truncLines = meta?.truncate === true ? 1 : meta?.truncate ? meta.truncate.lines : 0;\n const kind = kindOf(cell.column.id, meta);\n const rendered = flexRender(cell.column.columnDef.cell, cell.getContext());\n\n const shrink = (kind === \"number\" || kind === \"date\") && !meta?.maxWidth;\n let inner: ReactNode;\n if (truncLines > 0) {\n inner = <TruncCell lines={truncLines}>{rendered}</TruncCell>;\n } else if (kind === \"email\") {\n inner = (\n <span className=\"max-w-[40ch] truncate inline-block align-bottom\" title={typeof cell.getValue() === \"string\" ? cell.getValue() as string : undefined}>\n {rendered}\n </span>\n );\n } else {\n inner = rendered;\n }\n // Round 14 (50.2): a centred or right-aligned column lays a block element out with flex — text-align moves inline content only.\n const align = meta?.align ?? (kind === \"number\" ? \"right\" : \"left\");\n const value = cell.getValue();\n if (align !== \"left\" && typeof value !== \"string\" && typeof value !== \"number\" && value !== null && value !== undefined) {\n inner = <div className={cn(\"flex items-center\", align === \"center\" ? \"justify-center\" : \"justify-end\")}>{inner}</div>;\n }\n\n return (\n <td\n key={cell.id}\n className={cn(\n \"px-ds-4 py-ds-3 text-[var(--ds-text-primary)]\",\n align === \"right\" && \"text-right\",\n align === \"center\" && \"text-center\",\n shrink && \"w-px whitespace-nowrap\",\n )}\n style={meta?.maxWidth || meta?.width || meta?.minWidth ? { maxWidth: meta?.maxWidth, width: meta?.width, minWidth: meta?.minWidth } : undefined}\n >\n {inner}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {pageCount > 1 && (\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-[var(--ds-text-muted)]\">\n Page {currentPage + 1} of {pageCount}\n </span>\n <div className=\"flex items-center gap-ds-1\">\n <PagerBtn\n onClick={() => handlePageChange(0)}\n disabled={currentPage === 0}\n label=\"First\"\n />\n <PagerBtn\n onClick={() => handlePageChange(currentPage - 1)}\n disabled={currentPage === 0}\n label=\"Prev\"\n />\n {Array.from({ length: Math.min(pageCount, 5) }, (_, i) => {\n let page: number;\n if (pageCount <= 5) {\n page = i;\n } else if (currentPage < 3) {\n page = i;\n } else if (currentPage > pageCount - 4) {\n page = pageCount - 5 + i;\n } else {\n page = currentPage - 2 + i;\n }\n return (\n <PagerBtn\n key={page}\n onClick={() => handlePageChange(page)}\n active={page === currentPage}\n label={String(page + 1)}\n />\n );\n })}\n <PagerBtn\n onClick={() => handlePageChange(currentPage + 1)}\n disabled={currentPage >= pageCount - 1}\n label=\"Next\"\n />\n <PagerBtn\n onClick={() => handlePageChange(pageCount - 1)}\n disabled={currentPage >= pageCount - 1}\n label=\"Last\"\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nfunction PagerBtn({\n onClick,\n disabled,\n active,\n label,\n}: {\n onClick: () => void;\n disabled?: boolean;\n active?: boolean;\n label: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={cn(\n \"h-8 min-w-[32px] px-ds-2 text-xs font-medium rounded-[var(--ds-radius-sm)]\",\n \"transition-colors duration-[var(--ds-transition-speed)] cursor-pointer\",\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n \"disabled:opacity-disabled disabled:cursor-not-allowed\",\n active\n ? \"bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]\"\n : \"text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]\",\n )}\n >\n {label}\n </button>\n );\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -434,10 +434,10 @@ interface FormWrapperProps {
434
434
  actions?: ReactNode;
435
435
  actionsAlign?: "start" | "end";
436
436
  /**
437
- * Renders a secondary Cancel before the actions. Inside a Drawer, Sheet or Dialog it closes the overlay through its
438
- * unsaved-changes check — the question Escape and the close control ask while the form is dirty — and the overlay's
439
- * onClose runs; anywhere else this function runs. Never hand-wire a Cancel to the overlay's close: it skips the
440
- * question (round 21, run 58).
437
+ * Renders a secondary Cancel before the actions. Inside a Drawer, a Dialog, or a Sheet given `dirty`, it closes the
438
+ * overlay through its unsaved-changes check — the question Escape and the close control ask while the form is dirty —
439
+ * and then this function runs, unless it is the overlay's own onClose; it does not run when the user keeps editing.
440
+ * Anywhere else this function runs. Never hand-wire a Cancel to the overlay's close: it skips the question (round 21).
441
441
  */
442
442
  onCancel?: () => void;
443
443
  /** The Cancel button's label (default "Cancel"). */
@@ -864,12 +864,15 @@ interface TableToolbarProps {
864
864
  * The list is paged: pass the `usePagination` result and the count says which rows are showing — "Showing 51–100 of
865
865
  * 200 events" — instead of a bare total the table does not show (round 21, the owner's call); one page reads
866
866
  * "12 events". Under tabs that carry the counts, pass the pager alone (no resultCount): the line then shows only the
867
- * range, and only while the list spans pages — the tabs already say how many (gs:count-duplicated-by-tabs).
867
+ * range, and only while the list spans pages — the tabs already say how many (gs:count-duplicated-by-tabs). A list that
868
+ * grows (load more, loading on scroll) reads "Showing 40 of 120 members" until every row is shown (round 22).
868
869
  */
869
870
  pagination?: {
870
871
  page: number;
871
872
  pageSize: number;
872
873
  totalItems?: number;
874
+ style?: "pagination" | "load-more" | "infinite-scroll";
875
+ shown?: number;
873
876
  };
874
877
  /** Utility actions on the right — an overflow DropdownMenu, an export button. Primary actions belong in the PageHeader. */
875
878
  actions?: ReactNode;
@@ -892,6 +895,7 @@ interface TimelineItem {
892
895
  title: string;
893
896
  description?: string;
894
897
  timestamp?: string;
898
+ /** Takes the dot's place — the actor's Avatar (size="sm") on an activity feed, or an Icon. `variant` colours the dot only. */
895
899
  icon?: ReactNode;
896
900
  variant?: "default" | "success" | "warning" | "error";
897
901
  }
@@ -1478,9 +1482,21 @@ interface PaginationProps {
1478
1482
  pageSize?: number;
1479
1483
  pageSizeOptions?: number[];
1480
1484
  onPageSizeChange?: (size: number) => void;
1485
+ /**
1486
+ * How the list shows more (round 22): page numbers, a Load more button, or loading as the user scrolls (with the
1487
+ * button kept for keyboard users). `usePagination` passes the project's dataDisplay.paginationStyle here in
1488
+ * `pager.props`, so `<Pagination {...pager.props} />` follows the project's style with nothing written on the page.
1489
+ */
1490
+ mode?: "pagination" | "load-more" | "infinite-scroll";
1491
+ /** Rows left to load (load-more and infinite-scroll). */
1492
+ hasMore?: boolean;
1493
+ /** Load the next rows (load-more and infinite-scroll). */
1494
+ onLoadMore?: () => void;
1495
+ /** The Load more button's label (default "Load more"). */
1496
+ loadMoreLabel?: string;
1481
1497
  className?: string;
1482
1498
  }
1483
- declare function Pagination({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }: PaginationProps): react_jsx_runtime.JSX.Element;
1499
+ declare function Pagination(props: PaginationProps): react_jsx_runtime.JSX.Element;
1484
1500
 
1485
1501
  interface Step {
1486
1502
  label: string;
@@ -1953,6 +1969,14 @@ interface SheetProps {
1953
1969
  footer?: ReactNode;
1954
1970
  /** A strip between the content and the footer (the Drawer's unsaved-changes question). */
1955
1971
  confirm?: ReactNode;
1972
+ /**
1973
+ * The content has unsaved changes: every close path — Escape, the backdrop, dragging it down, the close control and a
1974
+ * FormWrapper's Cancel — asks before discarding them, inside the sheet, as a Drawer and a Dialog do (the review of
1975
+ * 23 September: a sheet holding a form threw it away with no question).
1976
+ */
1977
+ dirty?: boolean;
1978
+ /** Runs when the user discards unsaved changes, before onClose (reset the form here). */
1979
+ onDiscard?: () => void;
1956
1980
  /** Heights the sheet snaps to, as fractions of the viewport (or container). Default [0.5, 0.92]. */
1957
1981
  snapPoints?: number[];
1958
1982
  /** Render inside this element (absolute positioning, no body scroll lock) instead of document.body. */
@@ -1966,7 +1990,7 @@ interface SheetProps {
1966
1990
  /** id of the element that names the dialog when no title is rendered. */
1967
1991
  labelledBy?: string;
1968
1992
  }
1969
- declare function Sheet({ open, onClose, title, children, footer, confirm, snapPoints, container, flush, keepMounted, id, labelledBy }: SheetProps): react.ReactPortal | null;
1993
+ declare function Sheet({ open, onClose: onCloseProp, title, children, footer, confirm, dirty, onDiscard, snapPoints, container, flush, keepMounted, id, labelledBy }: SheetProps): react.ReactPortal | null;
1970
1994
 
1971
1995
  interface Notification {
1972
1996
  id: string;
@@ -2165,6 +2189,8 @@ type PreferenceBreakpoint = "sm" | "md" | "lg";
2165
2189
  type PreferenceEmptyStyle = "illustration-cta" | "text-cta" | "redirect";
2166
2190
  type PreferenceLoadingStyle = "skeleton" | "spinner" | "progress-bar";
2167
2191
  type PreferenceDestructiveMode = "dialog" | "undo";
2192
+ /** dataDisplay.paginationStyle — how a long list shows more: page numbers, a Load more button, or loading as the user scrolls. */
2193
+ type PreferencePaginationStyle = "pagination" | "load-more" | "infinite-scroll";
2168
2194
  interface AppShellPreferences {
2169
2195
  /** forms.validationTiming — when a field first shows its error. */
2170
2196
  validationTiming?: PreferenceValidationTiming;
@@ -2175,6 +2201,8 @@ interface AppShellPreferences {
2175
2201
  };
2176
2202
  /** dataDisplay.itemsPerPage — the page size of a paged or load-more list. */
2177
2203
  itemsPerPage?: number;
2204
+ /** dataDisplay.paginationStyle — page numbers, a Load more button, or loading on scroll; usePagination and Pagination follow it (round 22). */
2205
+ paginationStyle?: PreferencePaginationStyle;
2178
2206
  /** responsive.tableToCardsBreakpoint — below this width a Table becomes stacked cards. */
2179
2207
  tableToCardsBreakpoint?: PreferenceBreakpoint;
2180
2208
  /** emptyStates.emptyStyle — illustration with an action, text with an action, or redirect to creation. */
@@ -2199,6 +2227,7 @@ interface ResolvedPreferences {
2199
2227
  placement: "auto" | "inline";
2200
2228
  };
2201
2229
  itemsPerPage: number;
2230
+ paginationStyle: PreferencePaginationStyle;
2202
2231
  tableToCardsBreakpoint: PreferenceBreakpoint;
2203
2232
  emptyStyle: PreferenceEmptyStyle;
2204
2233
  loadingStyle: PreferenceLoadingStyle;
@@ -2320,12 +2349,14 @@ interface AppShellProps {
2320
2349
  declare const AppShell: react.ForwardRefExoticComponent<AppShellProps & react.RefAttributes<HTMLDivElement>>;
2321
2350
 
2322
2351
  /**
2323
- * A paged list in one hook (round 21). The page size is the project's `dataDisplay.itemsPerPage`, read from the
2324
- * shell, so a mid-build `update_rule` reaches every paged list with no page edited; the page gets its slice, the
2325
- * props for `<Pagination>` and the numbers the count line needs ("Showing 51–100 of 200 events").
2352
+ * A long list in one hook (round 21; all three list styles since round 22). The page size and the list style are the
2353
+ * project's `dataDisplay.itemsPerPage` and `dataDisplay.paginationStyle`, read from the shell, so a mid-build
2354
+ * `update_rule` on either reaches every list with no page edited. The page gets what to show, the props for
2355
+ * `<Pagination>` — page numbers, a Load more button or loading on scroll, whichever the project's style is — and the
2356
+ * numbers the count line needs ("Showing 51–100 of 200 events", or "Showing 40 of 120 members" while a list grows).
2326
2357
  *
2327
- * Run 58 showed why: both pages hand-wrote the same slicing, a `totalPages` sum and a fallback page size of their
2328
- * own, and the count line above the table said "200 events" while the table showed fifty.
2358
+ * Run 58 hand-wrote the paging; runs 59 and 60 hand-wrote load-more and scroll loading — an IntersectionObserver, a
2359
+ * visible count and a page size copied in as a constant, twice in one app — because the library had no way to.
2329
2360
  *
2330
2361
  * const pager = usePagination(sortedEvents, { resetOn: [sortKey, sortDir] })
2331
2362
  * <TableToolbar resultCount={sortedEvents.length} resultNoun={["event", "events"]} pagination={pager} />
@@ -2333,25 +2364,36 @@ declare const AppShell: react.ForwardRefExoticComponent<AppShellProps & react.Re
2333
2364
  * <Pagination {...pager.props} />
2334
2365
  */
2335
2366
  interface Pager<T> {
2336
- /** This page's slice of the list. */
2367
+ /** The list style this list follows: the project's, unless `style` was passed. */
2368
+ style: PreferencePaginationStyle;
2369
+ /** What to show: the current page's rows, or every row loaded so far on a list that grows. */
2337
2370
  items: T[];
2338
- /** The current page, from 1. */
2371
+ /** The current page, from 1; on a growing list, how many pages are loaded. */
2339
2372
  page: number;
2340
2373
  pageSize: number;
2341
2374
  totalItems: number;
2342
2375
  totalPages: number;
2343
- /** The first and last item numbers on this page, from 1 ("Showing 51–100"); [0, 0] for an empty list. */
2376
+ /** The first and last row numbers on screen, from 1 ("Showing 51–100"); [0, 0] for an empty list. */
2344
2377
  range: [number, number];
2378
+ /** How many rows are on screen. */
2379
+ shown: number;
2380
+ /** Rows left to show: a next page, or more to load. */
2381
+ hasMore: boolean;
2382
+ /** The next page, or the next `pageSize` rows on a growing list. */
2383
+ loadMore: () => void;
2345
2384
  setPage: (page: number) => void;
2346
2385
  /** A page-size selector's choice; it wins over the project's page size and starts again at page 1. */
2347
2386
  setPageSize: (size: number) => void;
2348
- /** Spread onto <Pagination>. */
2387
+ /** Spread onto <Pagination>: it renders page numbers, a Load more button or the scroll trigger, as `style` says. */
2349
2388
  props: {
2350
2389
  currentPage: number;
2351
2390
  totalPages: number;
2352
2391
  onPageChange: (page: number) => void;
2353
2392
  pageSize: number;
2354
2393
  onPageSizeChange: (size: number) => void;
2394
+ mode: PreferencePaginationStyle;
2395
+ hasMore: boolean;
2396
+ onLoadMore: () => void;
2355
2397
  };
2356
2398
  }
2357
2399
  interface PaginationOptions {
@@ -2359,6 +2401,12 @@ interface PaginationOptions {
2359
2401
  pageSize?: number;
2360
2402
  /** Values that start the list again at page 1 when they change — the sort column and direction, a search query. */
2361
2403
  resetOn?: unknown;
2404
+ /**
2405
+ * A list style for this list only, over the project's. Leave it out: the project's style is the rule. Passing one that
2406
+ * differs is overriding a rule in force — ask the user first, and put `// @gridsmith-override
2407
+ * dataDisplay.paginationStyle: <their reason>` above the call.
2408
+ */
2409
+ style?: PreferencePaginationStyle;
2362
2410
  }
2363
2411
  declare function usePagination<T>(list: readonly T[], options?: PaginationOptions): Pager<T>;
2364
2412
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useAppShell, ControlSizeContext, Button, Spinner, OverlayCloseCtx, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, useDirtyGuard, DiscardConfirm, defaultMaxWidth } from './chunk-HL3KYWOK.js';
2
- export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-HL3KYWOK.js';
1
+ import { useAppShell, ControlSizeContext, Button, Spinner, OverlayCloseCtx, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, useDirtyGuard, DiscardConfirm, defaultMaxWidth } from './chunk-JSQPVRHQ.js';
2
+ export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-JSQPVRHQ.js';
3
3
  import { Skeleton } from './chunk-M3AARGLI.js';
4
4
  export { Skeleton } from './chunk-M3AARGLI.js';
5
5
  import { useOverlayLayer, useCloseOnFocusOut, focusInitial, rovingTabStop, OVERLAY_CLOSE_ATTR, useNonModalDialog, useFocusTrap } from './chunk-NHQCMOAN.js';
@@ -8,8 +8,8 @@ export { CodeBlock, Divider, Link } from './chunk-QJBCZ7BR.js';
8
8
  import { Badge } from './chunk-U2JT37GJ.js';
9
9
  export { Badge } from './chunk-U2JT37GJ.js';
10
10
  import { inferColumnKinds, CardValue } from './chunk-CR2KF73R.js';
11
- import { SplitPaneCtx, useShellPreferences, TableCardCtx, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-YO7JVPXK.js';
12
- export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-YO7JVPXK.js';
11
+ import { SplitPaneCtx, useShellPreferences, TableCardCtx, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-TKVTZWBN.js';
12
+ export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-TKVTZWBN.js';
13
13
  import { useBreakpoint } from './chunk-CRQ6KCRD.js';
14
14
  export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
15
15
  import { useTextOverflow, Tooltip, usePosition } from './chunk-IYD6ZDM2.js';
@@ -3866,7 +3866,7 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
3866
3866
  const overlayClose = useContext(OverlayCloseCtx);
3867
3867
  const actions = useMemo(() => {
3868
3868
  if (!onCancel) return actionsProp;
3869
- const cancel = /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: () => (overlayClose ?? onCancel)(), children: cancelLabel }, "gs-form-cancel");
3869
+ const cancel = /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: () => overlayClose ? overlayClose(onCancel) : onCancel(), children: cancelLabel }, "gs-form-cancel");
3870
3870
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3871
3871
  cancel,
3872
3872
  actionsProp
@@ -5268,12 +5268,12 @@ function Table({
5268
5268
  const isMobile = useBreakpoint(mobileBreakpoint);
5269
5269
  if (isMobile) {
5270
5270
  if (loading) {
5271
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center justify-center py-ds-10", className), children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" }) });
5271
+ return /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", className: cn("flex items-center justify-center py-ds-10", className), children: /* @__PURE__ */ jsx(Spinner, { label: "Loading table data" }) });
5272
5272
  }
5273
5273
  if (data.length === 0 && emptyState) {
5274
- return /* @__PURE__ */ jsx("div", { ref, className: cn("py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", className), children: emptyState });
5274
+ return /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", className: cn("py-ds-10 text-center text-sm text-[var(--ds-text-muted)]", className), children: emptyState });
5275
5275
  }
5276
- return /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col gap-ds-3 overflow-y-auto", className), children: sortedWithIndices.map(({ row, originalIdx }, i) => {
5276
+ return /* @__PURE__ */ jsx(TableCardCtx, { value: true, children: /* @__PURE__ */ jsx("div", { ref, "data-ds-list": "", className: cn("flex flex-col gap-ds-3 overflow-y-auto", className), children: sortedWithIndices.map(({ row, originalIdx }, i) => {
5277
5277
  const isSelected = selectedSet.has(originalIdx);
5278
5278
  return /* @__PURE__ */ jsxs(
5279
5279
  "div",
@@ -5311,6 +5311,7 @@ function Table({
5311
5311
  "div",
5312
5312
  {
5313
5313
  ref,
5314
+ "data-ds-list": "",
5314
5315
  className: cn(
5315
5316
  "w-full overflow-x-auto",
5316
5317
  "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
@@ -7328,9 +7329,11 @@ function TableToolbar({
7328
7329
  const searchFills = inPane || !primaryFilter && !filters && !actions;
7329
7330
  const hasControls = !!(search || primaryFilter || filters || actions);
7330
7331
  const noun = (n) => n === 1 ? resultNoun[0] : resultNoun[1];
7331
- const total = resultCount ?? pagination?.totalItems;
7332
+ const total = pagination?.totalItems ?? resultCount;
7333
+ const grows = !!pagination?.style && pagination.style !== "pagination";
7334
+ const shown = grows ? Math.min(pagination.shown ?? pagination.page * pagination.pageSize, total ?? Infinity) : 0;
7332
7335
  const paged = total !== void 0 && !!pagination && pagination.pageSize > 0 && total > pagination.pageSize;
7333
- const countText = total === void 0 ? null : paged ? `Showing ${Math.min((pagination.page - 1) * pagination.pageSize + 1, total)}\u2013${Math.min(pagination.page * pagination.pageSize, total)} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${resultCount} ${noun(resultCount)}` : null;
7336
+ const countText = total === void 0 ? null : grows ? shown < total ? `Showing ${shown} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${total} ${noun(total)}` : null : paged ? `Showing ${Math.min((pagination.page - 1) * pagination.pageSize + 1, total)}\u2013${Math.min(pagination.page * pagination.pageSize, total)} of ${total} ${noun(total)}` : resultCount !== void 0 ? `${total} ${noun(total)}` : null;
7334
7337
  if (!hasControls && countText === null && !hasChips) return null;
7335
7338
  return /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-3 min-w-0 mb-ds-3 last:mb-0", className), "data-table-toolbar": "", children: [
7336
7339
  hasControls && /* @__PURE__ */ jsxs("div", { ref: rowRef, className: "flex items-center gap-ds-2 flex-wrap", children: [
@@ -7393,6 +7396,22 @@ function TableToolbar({
7393
7396
  ] })
7394
7397
  ] }) });
7395
7398
  }
7399
+ var ICON_TEXT_OFFSET = "calc((2rem - 1.25rem) / 2)";
7400
+ function Marker({ item, vertical }) {
7401
+ if (item.icon) {
7402
+ return /* @__PURE__ */ jsx("div", { "data-timeline-icon": "", className: "shrink-0 w-8 h-8 flex items-center justify-center *:max-w-8 *:max-h-8", children: item.icon });
7403
+ }
7404
+ return /* @__PURE__ */ jsx(
7405
+ "div",
7406
+ {
7407
+ className: cn(
7408
+ "shrink-0 w-3 h-3 rounded-[var(--ds-radius-full)]",
7409
+ vertical && "mt-ds-1",
7410
+ dotVariant[item.variant ?? "default"]
7411
+ )
7412
+ }
7413
+ );
7414
+ }
7396
7415
  var dotVariant = {
7397
7416
  default: "bg-[var(--ds-accent-primary)] shadow-[0_0_0_3px_var(--ds-accent-primary)]/20",
7398
7417
  success: "bg-[var(--ds-status-success)] shadow-[0_0_0_3px_var(--ds-status-success)]/20",
@@ -7441,15 +7460,7 @@ function HorizontalLayout({ items, minItemWidth, className }) {
7441
7460
  )
7442
7461
  }
7443
7462
  ),
7444
- /* @__PURE__ */ jsx(
7445
- "div",
7446
- {
7447
- className: cn(
7448
- "shrink-0 w-3 h-3 rounded-[var(--ds-radius-full)]",
7449
- dotVariant[item.variant ?? "default"]
7450
- )
7451
- }
7452
- ),
7463
+ /* @__PURE__ */ jsx(Marker, { item, vertical: false }),
7453
7464
  /* @__PURE__ */ jsx(
7454
7465
  "div",
7455
7466
  {
@@ -7471,18 +7482,10 @@ function HorizontalLayout({ items, minItemWidth, className }) {
7471
7482
  function VerticalLayout({ items, className }) {
7472
7483
  return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-ds-4", children: [
7473
7484
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
7474
- /* @__PURE__ */ jsx(
7475
- "div",
7476
- {
7477
- className: cn(
7478
- "shrink-0 w-3 h-3 rounded-[var(--ds-radius-full)] mt-ds-1",
7479
- dotVariant[item.variant ?? "default"]
7480
- )
7481
- }
7482
- ),
7485
+ /* @__PURE__ */ jsx(Marker, { item, vertical: true }),
7483
7486
  i < items.length - 1 && /* @__PURE__ */ jsx("div", { className: "w-[2px] flex-1 bg-[var(--ds-border-subtle)] my-ds-1" })
7484
7487
  ] }),
7485
- /* @__PURE__ */ jsxs("div", { className: cn("pb-ds-6", i === items.length - 1 && "pb-0"), children: [
7488
+ /* @__PURE__ */ jsxs("div", { className: cn("pb-ds-6 min-w-0", i === items.length - 1 && "pb-0"), style: item.icon ? { paddingTop: ICON_TEXT_OFFSET } : void 0, children: [
7486
7489
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: item.title }),
7487
7490
  item.description && /* @__PURE__ */ jsx(ExpandableDescription, { children: item.description }),
7488
7491
  item.timestamp && /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: item.timestamp })
@@ -7499,7 +7502,7 @@ function Timeline({ items, orientation = "vertical", minItemWidth = 200, classNa
7499
7502
  }, [ref]);
7500
7503
  const fits = width === 0 || width >= items.length * minItemWidth;
7501
7504
  const horizontal = orientation === "horizontal" || orientation === "responsive" && fits;
7502
- return /* @__PURE__ */ jsx("div", { ref: setRefs, "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) });
7505
+ return /* @__PURE__ */ jsx("div", { ref: setRefs, "data-ds-list": "", "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) });
7503
7506
  }
7504
7507
  var CollapsibleContext = createContext(null);
7505
7508
  function useCollapsible() {
@@ -8766,6 +8769,7 @@ var StackedList = forwardRef(function StackedList2({
8766
8769
  "ul",
8767
8770
  {
8768
8771
  ref,
8772
+ "data-ds-list": "",
8769
8773
  className: cn(
8770
8774
  divided && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
8771
8775
  className
@@ -9847,11 +9851,50 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
9847
9851
  )
9848
9852
  ] });
9849
9853
  }
9850
- function Pagination({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }) {
9854
+ function Pagination(props) {
9855
+ if ((props.mode === "load-more" || props.mode === "infinite-scroll") && props.onLoadMore) return /* @__PURE__ */ jsx(LoadMore, { ...props, onLoadMore: props.onLoadMore, scroll: props.mode === "infinite-scroll" });
9856
+ return /* @__PURE__ */ jsx(PageNumbers, { ...props });
9857
+ }
9858
+ function contentTop(el) {
9859
+ let top = el.getBoundingClientRect().top + window.scrollY;
9860
+ for (let n = el.parentElement; n && n !== document.documentElement; n = n.parentElement) top += n.scrollTop;
9861
+ return top;
9862
+ }
9863
+ function LoadMore({ hasMore, onLoadMore, loadMoreLabel, currentPage, scroll, className }) {
9864
+ const marker = useRef(null);
9865
+ const load = useLatest(onLoadMore);
9866
+ const loadedAt = useRef(null);
9867
+ useEffect(() => {
9868
+ const el = marker.current;
9869
+ if (!scroll || !hasMore || !el || typeof IntersectionObserver === "undefined") return;
9870
+ const observer = new IntersectionObserver((entries) => {
9871
+ if (!entries.some((e) => e.isIntersecting)) return;
9872
+ const at = contentTop(el);
9873
+ if (loadedAt.current !== null && Math.abs(at - loadedAt.current) < 1) return;
9874
+ loadedAt.current = at;
9875
+ load.current();
9876
+ }, { rootMargin: "200px 0px" });
9877
+ observer.observe(el);
9878
+ const rearm = () => {
9879
+ loadedAt.current = null;
9880
+ };
9881
+ window.addEventListener("scroll", rearm, { capture: true, passive: true });
9882
+ return () => {
9883
+ observer.disconnect();
9884
+ window.removeEventListener("scroll", rearm, { capture: true });
9885
+ };
9886
+ }, [scroll, hasMore, currentPage, load]);
9887
+ if (!hasMore) return null;
9888
+ return /* @__PURE__ */ jsxs("div", { "data-ds-pager": "", "data-pagination-mode": scroll ? "infinite-scroll" : "load-more", className: cn("flex flex-col items-center", className), children: [
9889
+ scroll && /* @__PURE__ */ jsx("div", { ref: marker, "data-load-more-trigger": "", "aria-hidden": "true", className: "h-px w-full" }),
9890
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onLoadMore, children: loadMoreLabel ?? "Load more" })
9891
+ ] });
9892
+ }
9893
+ function PageNumbers({ currentPage, totalPages, onPageChange, pageSize: pageSizeProp, pageSizeOptions, onPageSizeChange, className }) {
9851
9894
  const pages = buildPageRange(currentPage, totalPages);
9852
9895
  const preferences = useShellPreferences();
9853
9896
  const pageSize = pageSizeProp ?? preferences.itemsPerPage;
9854
- return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", className: cn("flex flex-wrap items-center gap-ds-3", className), children: [
9897
+ return /* @__PURE__ */ jsxs("nav", { "aria-label": "Pagination", "data-ds-pager": "", className: cn("flex flex-wrap items-center gap-ds-3", className), children: [
9855
9898
  pageSizeOptions && pageSize != null && onPageSizeChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
9856
9899
  /* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--ds-text-muted)] whitespace-nowrap", children: "Rows per page" }),
9857
9900
  /* @__PURE__ */ jsx(
@@ -14108,6 +14151,7 @@ function signature(list, resetOn) {
14108
14151
  }
14109
14152
  function usePagination(list, options = {}) {
14110
14153
  const shell = useShellPreferences();
14154
+ const style = options.style ?? shell.paginationStyle ?? PREFERENCE_HOUSE_DEFAULTS.paginationStyle;
14111
14155
  const [chosenSize, setChosenSize] = useState(null);
14112
14156
  const pageSize = Math.max(1, Math.floor(chosenSize ?? options.pageSize ?? shell.itemsPerPage ?? PREFERENCE_HOUSE_DEFAULTS.itemsPerPage));
14113
14157
  const [page, setPageState] = useState(1);
@@ -14120,24 +14164,31 @@ function usePagination(list, options = {}) {
14120
14164
  const totalItems = list.length;
14121
14165
  const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
14122
14166
  const current = Math.min(Math.max(1, seen !== sig ? 1 : page), totalPages);
14123
- const start = (current - 1) * pageSize;
14124
- const items = list.slice(start, start + pageSize);
14125
- const range = totalItems === 0 ? [0, 0] : [start + 1, start + items.length];
14167
+ const grows = style !== "pagination";
14168
+ const start = grows ? 0 : (current - 1) * pageSize;
14169
+ const items = list.slice(start, current * pageSize);
14170
+ const range = items.length === 0 ? [0, 0] : [start + 1, start + items.length];
14171
+ const hasMore = current < totalPages;
14126
14172
  const setPage = (next) => setPageState(Math.min(Math.max(1, Math.floor(next)), totalPages));
14173
+ const loadMore = () => setPageState((p) => Math.min(p + 1, totalPages));
14127
14174
  const setPageSize = (size) => {
14128
14175
  setChosenSize(Math.max(1, Math.floor(size)));
14129
14176
  setPageState(1);
14130
14177
  };
14131
14178
  return {
14179
+ style,
14132
14180
  items,
14133
14181
  page: current,
14134
14182
  pageSize,
14135
14183
  totalItems,
14136
14184
  totalPages,
14137
14185
  range,
14186
+ shown: items.length,
14187
+ hasMore,
14188
+ loadMore,
14138
14189
  setPage,
14139
14190
  setPageSize,
14140
- props: { currentPage: current, totalPages, onPageChange: setPage, pageSize, onPageSizeChange: setPageSize }
14191
+ props: { currentPage: current, totalPages, onPageChange: setPage, pageSize, onPageSizeChange: setPageSize, mode: style, hasMore, onLoadMore: loadMore }
14141
14192
  };
14142
14193
  }
14143
14194
  function useDestructiveAction(options) {