@k2b/ui 0.51.0 → 0.52.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.
- package/dist/base.css +3 -0
- package/dist/browser/actions/Toolbar.js +8 -2
- package/dist/browser/actions/Toolbar.js.map +1 -1
- package/dist/browser/charts/core/bar-labels.js +5 -0
- package/dist/browser/charts/core/bar-labels.js.map +1 -0
- package/dist/browser/charts/core/bubble.js +166 -0
- package/dist/browser/charts/core/bubble.js.map +1 -0
- package/dist/browser/charts/core/default-styles.js +83 -0
- package/dist/browser/charts/core/default-styles.js.map +1 -0
- package/dist/browser/charts/core/funnel-layout.js +79 -0
- package/dist/browser/charts/core/funnel-layout.js.map +1 -0
- package/dist/browser/charts/core/funnel.js +27 -0
- package/dist/browser/charts/core/funnel.js.map +1 -0
- package/dist/browser/charts/core/index.js +6 -1
- package/dist/browser/charts/core/index.js.map +1 -1
- package/dist/browser/charts/core/pareto.js +120 -0
- package/dist/browser/charts/core/pareto.js.map +1 -0
- package/dist/browser/charts/core/radar.js +101 -0
- package/dist/browser/charts/core/radar.js.map +1 -0
- package/dist/browser/charts/core/registry.js +11 -1
- package/dist/browser/charts/core/registry.js.map +1 -1
- package/dist/browser/charts/core/render-size.js +3 -1
- package/dist/browser/charts/core/render-size.js.map +1 -1
- package/dist/browser/charts/core/render.js +19 -0
- package/dist/browser/charts/core/render.js.map +1 -1
- package/dist/browser/charts/core/snapshot.js +1 -1
- package/dist/browser/charts/core/snapshot.js.map +1 -1
- package/dist/browser/charts/core/svg-barGauge.js +67 -0
- package/dist/browser/charts/core/svg-barGauge.js.map +1 -0
- package/dist/browser/charts/core/svg-boxplot.js +127 -0
- package/dist/browser/charts/core/svg-boxplot.js.map +1 -0
- package/dist/browser/charts/core/svg-common.js +1065 -0
- package/dist/browser/charts/core/svg-common.js.map +1 -0
- package/dist/browser/charts/core/svg-gauge.js +185 -0
- package/dist/browser/charts/core/svg-gauge.js.map +1 -0
- package/dist/browser/charts/core/svg-heatmap.js +80 -0
- package/dist/browser/charts/core/svg-heatmap.js.map +1 -0
- package/dist/browser/charts/core/svg-histogram.js +73 -0
- package/dist/browser/charts/core/svg-histogram.js.map +1 -0
- package/dist/browser/charts/core/svg-renderers.js +9 -1777
- package/dist/browser/charts/core/svg-renderers.js.map +1 -1
- package/dist/browser/charts/core/svg-scatter.js +114 -0
- package/dist/browser/charts/core/svg-scatter.js.map +1 -0
- package/dist/browser/charts/core/treemap.js +138 -0
- package/dist/browser/charts/core/treemap.js.map +1 -0
- package/dist/browser/charts/description.js.map +1 -1
- package/dist/browser/content/ChartRoot.js +21 -7
- package/dist/browser/content/ChartRoot.js.map +1 -1
- package/dist/browser/content/ChartSnapshotView.js +4 -1
- package/dist/browser/content/ChartSnapshotView.js.map +1 -1
- package/dist/browser/content/DataTable.js +186 -193
- package/dist/browser/content/DataTable.js.map +1 -1
- package/dist/browser/content/Lightbox.js +55 -23
- package/dist/browser/content/Lightbox.js.map +1 -1
- package/dist/browser/content/ThumbnailStrip.js +174 -0
- package/dist/browser/content/ThumbnailStrip.js.map +1 -0
- package/dist/browser/content/chart-bar.js +98 -0
- package/dist/browser/content/chart-bar.js.map +1 -1
- package/dist/browser/content/chart-inspection-core.js +28 -8
- package/dist/browser/content/chart-inspection-core.js.map +1 -1
- package/dist/browser/content/chart-message-catalog.js +18 -0
- package/dist/browser/content/chart-message-catalog.js.map +1 -1
- package/dist/browser/content/index.js +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/thumbnail-strip-messages.js +24 -0
- package/dist/browser/content/thumbnail-strip-messages.js.map +1 -0
- package/dist/browser/inputs/ChoiceInputs.js +132 -101
- package/dist/browser/inputs/ChoiceInputs.js.map +1 -1
- package/dist/browser/inputs/index.js +1 -0
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/inputs/markdown/MarkdownSelectionToolbar.js +330 -0
- package/dist/browser/inputs/markdown/MarkdownSelectionToolbar.js.map +1 -0
- package/dist/browser/internal/field.js +96 -77
- package/dist/browser/internal/field.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +7 -5
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/PanelDialog.js +92 -68
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +82 -70
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/surfaces/stat-cell-messages.js +4 -2
- package/dist/browser/surfaces/stat-cell-messages.js.map +1 -1
- package/dist/browser/widgets/DashboardFrame.js +93 -88
- package/dist/browser/widgets/DashboardFrame.js.map +1 -1
- package/dist/ssr/actions/Toolbar.js +8 -2
- package/dist/ssr/actions/Toolbar.js.map +1 -1
- package/dist/ssr/charts/core/bar-labels.js +5 -0
- package/dist/ssr/charts/core/bar-labels.js.map +1 -0
- package/dist/ssr/charts/core/bubble.js +166 -0
- package/dist/ssr/charts/core/bubble.js.map +1 -0
- package/dist/ssr/charts/core/default-styles.js +83 -0
- package/dist/ssr/charts/core/default-styles.js.map +1 -0
- package/dist/ssr/charts/core/funnel-layout.js +79 -0
- package/dist/ssr/charts/core/funnel-layout.js.map +1 -0
- package/dist/ssr/charts/core/funnel.js +27 -0
- package/dist/ssr/charts/core/funnel.js.map +1 -0
- package/dist/ssr/charts/core/index.js +6 -1
- package/dist/ssr/charts/core/index.js.map +1 -1
- package/dist/ssr/charts/core/pareto.js +120 -0
- package/dist/ssr/charts/core/pareto.js.map +1 -0
- package/dist/ssr/charts/core/radar.js +101 -0
- package/dist/ssr/charts/core/radar.js.map +1 -0
- package/dist/ssr/charts/core/registry.js +11 -1
- package/dist/ssr/charts/core/registry.js.map +1 -1
- package/dist/ssr/charts/core/render-size.js +3 -1
- package/dist/ssr/charts/core/render-size.js.map +1 -1
- package/dist/ssr/charts/core/render.js +19 -0
- package/dist/ssr/charts/core/render.js.map +1 -1
- package/dist/ssr/charts/core/snapshot.js +1 -1
- package/dist/ssr/charts/core/snapshot.js.map +1 -1
- package/dist/ssr/charts/core/svg-barGauge.js +67 -0
- package/dist/ssr/charts/core/svg-barGauge.js.map +1 -0
- package/dist/ssr/charts/core/svg-boxplot.js +127 -0
- package/dist/ssr/charts/core/svg-boxplot.js.map +1 -0
- package/dist/ssr/charts/core/svg-common.js +1065 -0
- package/dist/ssr/charts/core/svg-common.js.map +1 -0
- package/dist/ssr/charts/core/svg-gauge.js +185 -0
- package/dist/ssr/charts/core/svg-gauge.js.map +1 -0
- package/dist/ssr/charts/core/svg-heatmap.js +80 -0
- package/dist/ssr/charts/core/svg-heatmap.js.map +1 -0
- package/dist/ssr/charts/core/svg-histogram.js +73 -0
- package/dist/ssr/charts/core/svg-histogram.js.map +1 -0
- package/dist/ssr/charts/core/svg-renderers.js +9 -1777
- package/dist/ssr/charts/core/svg-renderers.js.map +1 -1
- package/dist/ssr/charts/core/svg-scatter.js +114 -0
- package/dist/ssr/charts/core/svg-scatter.js.map +1 -0
- package/dist/ssr/charts/core/treemap.js +138 -0
- package/dist/ssr/charts/core/treemap.js.map +1 -0
- package/dist/ssr/charts/description.js.map +1 -1
- package/dist/ssr/content/ChartRoot.js +21 -7
- package/dist/ssr/content/ChartRoot.js.map +1 -1
- package/dist/ssr/content/ChartSnapshotView.js +1 -0
- package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
- package/dist/ssr/content/DataTable.js +12 -16
- package/dist/ssr/content/DataTable.js.map +1 -1
- package/dist/ssr/content/Lightbox.js +32 -3
- package/dist/ssr/content/Lightbox.js.map +1 -1
- package/dist/ssr/content/ThumbnailStrip.js +103 -0
- package/dist/ssr/content/ThumbnailStrip.js.map +1 -0
- package/dist/ssr/content/chart-bar.js +98 -0
- package/dist/ssr/content/chart-bar.js.map +1 -1
- package/dist/ssr/content/chart-inspection-core.js +28 -8
- package/dist/ssr/content/chart-inspection-core.js.map +1 -1
- package/dist/ssr/content/chart-message-catalog.js +18 -0
- package/dist/ssr/content/chart-message-catalog.js.map +1 -1
- package/dist/ssr/content/index.js +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/thumbnail-strip-messages.js +24 -0
- package/dist/ssr/content/thumbnail-strip-messages.js.map +1 -0
- package/dist/ssr/inputs/ChoiceInputs.js +55 -40
- package/dist/ssr/inputs/ChoiceInputs.js.map +1 -1
- package/dist/ssr/inputs/index.js +1 -0
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/inputs/markdown/MarkdownSelectionToolbar.js +293 -0
- package/dist/ssr/inputs/markdown/MarkdownSelectionToolbar.js.map +1 -0
- package/dist/ssr/internal/field.js +36 -24
- package/dist/ssr/internal/field.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +5 -1
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/PanelDialog.js +40 -26
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +29 -18
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/surfaces/stat-cell-messages.js +4 -2
- package/dist/ssr/surfaces/stat-cell-messages.js.map +1 -1
- package/dist/ssr/widgets/DashboardFrame.js +6 -11
- package/dist/ssr/widgets/DashboardFrame.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Toolbar.d.ts +2 -0
- package/dist/types/charts/core/bar-labels.d.ts +1 -0
- package/dist/types/charts/core/bubble.d.ts +66 -0
- package/dist/types/charts/core/default-styles.d.ts +1 -0
- package/dist/types/charts/core/funnel-layout.d.ts +43 -0
- package/dist/types/charts/core/funnel.d.ts +13 -0
- package/dist/types/charts/core/index.d.ts +6 -1
- package/dist/types/charts/core/pareto.d.ts +40 -0
- package/dist/types/charts/core/radar.d.ts +47 -0
- package/dist/types/charts/core/registry.d.ts +10 -0
- package/dist/types/charts/core/render-size.d.ts +1 -1
- package/dist/types/charts/core/svg-barGauge.d.ts +3 -0
- package/dist/types/charts/core/svg-boxplot.d.ts +18 -0
- package/dist/types/charts/core/svg-common.d.ts +612 -0
- package/dist/types/charts/core/svg-gauge.d.ts +6 -0
- package/dist/types/charts/core/svg-heatmap.d.ts +6 -0
- package/dist/types/charts/core/svg-histogram.d.ts +16 -0
- package/dist/types/charts/core/svg-renderers.d.ts +8 -612
- package/dist/types/charts/core/svg-scatter.d.ts +23 -0
- package/dist/types/charts/core/treemap.d.ts +45 -0
- package/dist/types/charts/description.d.ts +63 -0
- package/dist/types/content/ChartRoot.d.ts +1 -1
- package/dist/types/content/Lightbox.d.ts +2 -0
- package/dist/types/content/ThumbnailStrip.d.ts +29 -0
- package/dist/types/content/chart-bar.d.ts +38 -2
- package/dist/types/content/chart-inspection-core.d.ts +7 -0
- package/dist/types/content/chart-inspection.d.ts +1 -0
- package/dist/types/content/chart-message-catalog.d.ts +8 -0
- package/dist/types/content/index.d.ts +1 -0
- package/dist/types/content/thumbnail-strip-messages.d.ts +10 -0
- package/dist/types/inputs/ChoiceInputs.d.ts +2 -0
- package/dist/types/inputs/index.d.ts +2 -0
- package/dist/types/inputs/markdown/MarkdownSelectionToolbar.d.ts +19 -0
- package/dist/types/internal/field.d.ts +2 -0
- package/dist/types/layout/PanelDialog.d.ts +5 -0
- package/dist/types/surfaces/stat-cell-messages.d.ts +1 -0
- package/dist/types/widgets/DashboardFrame.d.ts +4 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/DataTable.tsx"],"sourcesContent":["import {\n type Accessor,\n createContext,\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n For,\n type JSX,\n Match,\n on,\n onCleanup,\n onMount,\n Show,\n Switch,\n useContext,\n} from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport { announce } from \"../feedback/announce\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\nimport { useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { PanelHeader } from \"../layout/PanelHeader\";\nimport { DeltaBadge } from \"../surfaces/delta-badge\";\nimport { Paper } from \"../surfaces/Paper\";\nimport Placeholder from \"../surfaces/Placeholder\";\nimport { StatusBadge } from \"../surfaces/StatusBadge\";\nimport type { CollectionSelection } from \"./collection-selection\";\nimport {\n type DataTableTypedColumn,\n formatTableNumber,\n groupRows,\n isEmptyCell,\n isNumericColumnType,\n readTableValue,\n tableCellText,\n} from \"./data-table-columns\";\nimport { useDataTableMessages } from \"./data-table-messages\";\nimport { FlowAmount } from \"./FlowAmount\";\n\nexport type DataTableColumn<T> = {\n id: string;\n header: JSX.Element | ((ctx: { col: DataTableColumn<T> }) => JSX.Element);\n subtitle?: JSX.Element | ((ctx: { col: DataTableColumn<T> }) => JSX.Element);\n value?: keyof T | ((row: T) => unknown);\n class?: string;\n headerClass?: string;\n cellClass?: string;\n /** Defaults to right for numeric values and left for everything else. */\n align?: \"left\" | \"center\" | \"right\";\n /**\n * Keeps each value on one line, so the column is at least as wide as its\n * longest value. For dates, times, numbers, amounts, and short codes.\n * Defaults to true when the column's first value is a number or date. The\n * default cell wrapper already keeps every value on one line; this option\n * decides wrapping for content under a custom `cellContentClass`, and a\n * `white-space` that class sets itself wins.\n */\n nowrap?: boolean;\n /**\n * Marks the column sortable. Pass a string when the server's sort key\n * differs from the column id — they often do, because one column can show a\n * rate while another sorts by the absolute count behind it.\n */\n sortable?: boolean | string;\n /** What the column holds; see `DataTableColumnType`. */\n type?: DataTableTypedColumn[\"type\"];\n format?: DataTableTypedColumn[\"format\"];\n /** Labels and tones of a status column, by stored value. */\n states?: DataTableTypedColumn[\"states\"];\n /** The value a bar column fills its track at; defaults to its largest value. */\n max?: number;\n /** The zone a date column with a time reads in; defaults to the reader's. */\n timeZone?: string;\n /** How a delta column reads and rates its change. */\n delta?: DataTableTypedColumn[\"delta\"];\n /**\n * How much a narrow table needs the column: 1 (default) always shows; 3 hides below a table width of 560 px,\n * 2 below 420 px. Hidden values stay one tap away in the row's details.\n */\n priority?: 1 | 2 | 3;\n};\n\nexport type DataTableSort = { key: string; direction: \"asc\" | \"desc\" };\n\nexport type DataTableRenderCell<T> = (ctx: {\n row: T;\n col: DataTableColumn<T>;\n value: unknown;\n render: (value: unknown) => JSX.Element;\n}) => JSX.Element;\n\nexport type DataTableRenderHeader<T> = (ctx: { col: DataTableColumn<T>; render: () => JSX.Element }) => JSX.Element;\n\nexport type DataTableFooter<T> = {\n values?: Record<string, unknown>;\n renderCell?: (ctx: { col: DataTableColumn<T>; value: unknown; render: (value: unknown) => JSX.Element }) => JSX.Element;\n};\n\nexport type DataTableProps<T> = {\n rows: readonly T[];\n columns: readonly DataTableColumn<T>[];\n /** Accessible name for a standalone table region. Defaults to \"Data table\". */\n ariaLabel?: string;\n /** ID of a visible heading that labels the table region. Takes precedence over ariaLabel. */\n ariaLabelledBy?: string;\n getRowId?: (row: T) => string;\n /** Current server-side ordering, or null when the default applies. */\n sort?: DataTableSort | null;\n /**\n * Link target for a sortable header. Link-based because every admin table is\n * server-rendered: sorting is a query change, not client state.\n */\n sortHref?: (next: DataTableSort) => string;\n /**\n * Sorts on the client instead: sortable headers become buttons that report the\n * next order, with the same look and order of directions as `sortHref`.\n */\n onSortChange?: (next: DataTableSort) => void;\n selectedRowId?: string | null;\n /** Optional multi-selection shared with another collection view. Requires getRowId. */\n selection?: CollectionSelection;\n rowClass?: string | ((row: T) => string | undefined);\n hoverRows?: boolean;\n onRowClick?: (row: T) => void;\n onRowDoubleClick?: (row: T) => void;\n onRowContextMenu?: (row: T) => void;\n renderCell?: DataTableRenderCell<T>;\n renderHeader?: DataTableRenderHeader<T>;\n footer?: DataTableFooter<T>;\n hasMore?: boolean;\n loadingMore?: boolean;\n loading?: boolean;\n /** Initial placeholder count, clamped to an integer from 1 to 50. Defaults to 5. */\n loadingRows?: number;\n onLoadMore?: () => void;\n empty?: JSX.Element;\n density?: \"compact\" | \"normal\";\n stickyHeader?: boolean;\n highlightColumns?: boolean;\n verticalAlign?: \"top\" | \"middle\" | \"bottom\";\n cellContentClass?: string;\n fillHeight?: boolean;\n /** Visual frame for a standalone table. Defaults preserve the legacy class-based behavior. */\n surface?: \"paper\" | \"plain\";\n class?: string;\n /** Additional classes for the table element. Core table geometry is always retained. */\n tableClass?: string;\n /** Additional classes for the scrolling region, such as `k2b-detail-trail`. */\n scrollClass?: string;\n scrollPreserveKey?: string | false;\n /**\n * The id of the column whose values split the rows into groups, each its own `<tbody>` under a row with the\n * group's value and count, in the order the groups first appear.\n */\n groupBy?: string;\n /**\n * The host's search text. With no rows left, the table says that nothing matches it and offers to clear it\n * through `onClearQuery`, instead of `empty`. Filter the rows with `filterRows`.\n */\n query?: string;\n onClearQuery?: () => void;\n};\n\nexport type DataTablePanelProps = {\n children: JSX.Element;\n class?: string;\n};\n\nexport type DataTableHeaderProps = {\n title: string;\n subtitle?: string;\n children?: JSX.Element;\n as?: \"h1\" | \"h2\" | \"h3\";\n size?: \"sm\" | \"md\";\n class?: string;\n};\n\nexport type DataTableControlsProps = {\n children: JSX.Element;\n class?: string;\n};\n\nexport type DataTablePanelFooterProps = {\n children: JSX.Element;\n class?: string;\n};\n\ntype DataTablePanelContextValue = {\n headingId: string;\n hasHeading: Accessor<boolean>;\n registerHeading: () => void;\n};\n\nconst DataTablePanelContext = createContext<DataTablePanelContextValue>();\n\nconst defaultRender = (\n value: unknown,\n locale: string,\n numbers: Intl.NumberFormat,\n messages: ReturnType<ReturnType<typeof useUiMessages>>,\n): JSX.Element => {\n if (value === null || value === undefined || value === \"\") return \"—\";\n if (value instanceof Date) return value.toLocaleString(locale);\n if (typeof value === \"boolean\") return value ? messages.yes : messages.no;\n // Numbers read in the reader's language: grouping and decimal mark follow the locale, at most three decimals.\n if (typeof value === \"number\" || typeof value === \"bigint\") return numbers.format(Object.is(value, -0) ? 0 : value);\n if (typeof value === \"string\") return value;\n return JSON.stringify(value);\n};\n\nconst renderColumnPart = <T,>(\n part: DataTableColumn<T>[\"header\"] | DataTableColumn<T>[\"subtitle\"],\n col: DataTableColumn<T>,\n): JSX.Element => {\n if (typeof part === \"function\") return part({ col });\n return part;\n};\n\nconst rowInteractiveSelector = [\n \"a[href]\",\n \"button\",\n \"input\",\n \"label\",\n \"select\",\n \"textarea\",\n \"summary\",\n \"[contenteditable]\",\n \"[role='button']\",\n \"[role='checkbox']\",\n \"[role='link']\",\n \"[role='menuitem']\",\n \"[role='option']\",\n \"[role='radio']\",\n \"[role='switch']\",\n \"[role='tab']\",\n \"[tabindex]\",\n].join(\",\");\n\nconst isNestedRowControl = (event: Event): boolean =>\n event.target instanceof Element && event.target.closest(rowInteractiveSelector) !== event.currentTarget;\n\n/** Distance in pixels before the table's end at which the next page is requested. */\nconst loadMoreMargin = 240;\n\ntype DataTableScrollbarAxis = \"x\" | \"y\";\ntype DataTableScrollbarMetrics = { overflow: boolean; offset: number; size: number };\n\nconst scrollbarMetrics = (viewportSize: number, contentSize: number, scrollOffset: number): DataTableScrollbarMetrics => {\n if (viewportSize <= 0 || contentSize <= viewportSize + 1) return { overflow: false, offset: 0, size: 0 };\n const size = Math.min(viewportSize, Math.max(24, (viewportSize * viewportSize) / contentSize));\n const offset = (scrollOffset / (contentSize - viewportSize)) * (viewportSize - size);\n return { overflow: true, offset, size };\n};\n\nfunction DataTableRoot<T>(props: DataTableProps<T>) {\n const messages = useUiMessages();\n const dataTableMessages = useDataTableMessages();\n const locale = useLocale();\n const [hoveredColumn, setHoveredColumn] = createSignal<number | null>(null);\n const [scrollbars, setScrollbars] = createSignal<Record<DataTableScrollbarAxis, DataTableScrollbarMetrics>>({\n x: { overflow: false, offset: 0, size: 0 },\n y: { overflow: false, offset: 0, size: 0 },\n });\n const [scrollbarEnhanced, setScrollbarEnhanced] = createSignal(false);\n const [scrolling, setScrolling] = createSignal(false);\n const panel = useContext(DataTablePanelContext);\n let tableRef: HTMLTableElement | undefined;\n let scrollRef: HTMLDivElement | undefined;\n let loadMoreRef: HTMLDivElement | undefined;\n let scrollingTimeout: ReturnType<typeof setTimeout> | undefined;\n let scrollbarDragOffset = 0;\n let hasMore = false;\n let loadingMore = false;\n let onLoadMore: (() => void) | undefined;\n let loadMoreRequested = false;\n let previousRowsLength = props.rows.length;\n let previousLoadingMore = !!props.loadingMore;\n let previousHasMore = !!props.hasMore;\n const loadingRows = () => Math.min(50, Math.max(1, Math.trunc(Number.isNaN(props.loadingRows) ? 5 : (props.loadingRows ?? 5))));\n const rowId = (row: T) => props.getRowId?.(row);\n const isInteractive = () => !!props.selection || !!props.onRowClick || !!props.onRowDoubleClick;\n const shouldHoverRows = () => props.hoverRows ?? isInteractive();\n const shouldRenderLoadMoreSentinel = () => !!props.onLoadMore;\n const labelledBy = () => props.ariaLabelledBy ?? (panel?.hasHeading() ? panel.headingId : undefined);\n const surface = () => props.surface ?? (props.class ? \"plain\" : \"paper\");\n const cellContentClass = () => props.cellContentClass ?? \"k2b-data-table__cell-text\";\n const tableClass = () => `k2b-data-table ${props.tableClass ?? \"\"}`.trim();\n const columnHighlighted = (index: number) =>\n props.highlightColumns !== false && shouldHoverRows() && hoveredColumn() === index ? \"true\" : undefined;\n const setHoveredColumnIfEnabled = (index: number) => {\n if (shouldHoverRows()) setHoveredColumn(index);\n };\n\n /**\n * A bounded table scrolls its own viewport. A table that grows with its rows\n * leaves scrolling to the page or an ancestor, so its end is measured against\n * the browser viewport instead.\n */\n const isNearBottom = () => {\n if (!scrollRef || !loadMoreRef) return false;\n if (scrollRef.scrollHeight > scrollRef.clientHeight + 1) {\n return scrollRef.scrollTop + scrollRef.clientHeight >= scrollRef.scrollHeight - loadMoreMargin;\n }\n return loadMoreRef.getBoundingClientRect().top <= window.innerHeight + loadMoreMargin;\n };\n\n const maybeLoadMore = () => {\n if (!hasMore || loadingMore || !onLoadMore) return;\n if (!isNearBottom()) {\n // Leaving the end re-arms a request the owner declined, for example while its first page was still loading.\n loadMoreRequested = false;\n return;\n }\n if (loadMoreRequested) return;\n loadMoreRequested = true;\n try {\n onLoadMore();\n } catch (error) {\n loadMoreRequested = false;\n throw error;\n }\n };\n\n const syncScrollbars = () => {\n if (!scrollRef) return;\n setScrollbars({\n x: scrollbarMetrics(scrollRef.clientWidth, scrollRef.scrollWidth, scrollRef.scrollLeft),\n y: scrollbarMetrics(scrollRef.clientHeight, scrollRef.scrollHeight, scrollRef.scrollTop),\n });\n };\n\n const revealScrollbars = () => {\n setScrolling(true);\n if (scrollingTimeout !== undefined) clearTimeout(scrollingTimeout);\n scrollingTimeout = setTimeout(() => {\n setScrolling(false);\n scrollingTimeout = undefined;\n }, 700);\n };\n\n const onScroll = () => {\n syncScrollbars();\n revealScrollbars();\n maybeLoadMore();\n };\n\n const scrollFromPointer = (event: PointerEvent & { currentTarget: HTMLDivElement }, axis: DataTableScrollbarAxis) => {\n if (!scrollRef) return;\n const track = event.currentTarget;\n const metrics = scrollbars()[axis];\n const rect = track.getBoundingClientRect();\n const trackSize = axis === \"y\" ? rect.height : rect.width;\n const pointerOffset = axis === \"y\" ? event.clientY - rect.top : event.clientX - rect.left;\n const available = Math.max(1, trackSize - metrics.size);\n const thumbOffset = Math.min(available, Math.max(0, pointerOffset - scrollbarDragOffset));\n const maxScroll = axis === \"y\" ? scrollRef.scrollHeight - scrollRef.clientHeight : scrollRef.scrollWidth - scrollRef.clientWidth;\n if (axis === \"y\") scrollRef.scrollTop = (thumbOffset / available) * maxScroll;\n else scrollRef.scrollLeft = (thumbOffset / available) * maxScroll;\n syncScrollbars();\n revealScrollbars();\n };\n\n const startScrollbarDrag = (event: PointerEvent & { currentTarget: HTMLDivElement }, axis: DataTableScrollbarAxis) => {\n if (event.button !== 0) return;\n event.preventDefault();\n const metrics = scrollbars()[axis];\n const rect = event.currentTarget.getBoundingClientRect();\n const pointerOffset = axis === \"y\" ? event.clientY - rect.top : event.clientX - rect.left;\n scrollbarDragOffset =\n event.target === event.currentTarget ? metrics.size / 2 : Math.min(metrics.size, Math.max(0, pointerOffset - metrics.offset));\n event.currentTarget.setPointerCapture(event.pointerId);\n // The track's own pointerup or pointercancel ends the hold.\n suppressTextSelection(event.pointerId);\n scrollFromPointer(event, axis);\n };\n\n const valueOf = (row: T, col: DataTableColumn<T>) => readTableValue(row, col);\n\n const columnPresentation = createMemo(() => {\n const presentation = new Map<string, { align: NonNullable<DataTableColumn<T>[\"align\"]>; nowrap: boolean }>();\n for (const col of props.columns) {\n // A typed column says what it holds; only an untyped one is read from its first value.\n let numeric = isNumericColumnType(col.type);\n let date = col.type === \"date\";\n if (!col.type && (col.align === undefined || col.nowrap === undefined)) {\n for (const row of props.rows) {\n const value = valueOf(row, col);\n if (value === null || value === undefined || value === \"\") continue;\n numeric = typeof value === \"number\" || typeof value === \"bigint\";\n date = value instanceof Date;\n break;\n }\n }\n presentation.set(col.id, { align: col.align ?? (numeric ? \"right\" : \"left\"), nowrap: col.nowrap ?? (numeric || date) });\n }\n return presentation;\n });\n\n /** `data-align` mirrors Cloud's `text-left/center/right` on the same cell. */\n const alignAttr = (col: DataTableColumn<T>) => {\n const align = columnPresentation().get(col.id)?.align ?? \"left\";\n return align === \"left\" ? undefined : align;\n };\n\n const nowrapAttr = (col: DataTableColumn<T>) => (columnPresentation().get(col.id)?.nowrap ? \"true\" : undefined);\n /** Text columns wrap inside their cell; every other value keeps one line. */\n const wrapAttr = (col: DataTableColumn<T>) => (col.type === \"text\" && col.nowrap !== true ? \"true\" : undefined);\n const priorityAttr = (col: DataTableColumn<T>) => (col.priority === 2 || col.priority === 3 ? String(col.priority) : undefined);\n /** The lowest priority present: 3 shows the details toggle below 560 px, 2 below 420 px. */\n const detailsPriority = createMemo(() => {\n const priorities = props.columns.map((col) => col.priority ?? 1);\n return priorities.includes(3) ? \"3\" : priorities.includes(2) ? \"2\" : undefined;\n });\n const hiddenColumns = () => props.columns.filter((col) => priorityAttr(col));\n const columnCount = () => props.columns.length + (detailsPriority() ? 1 : 0);\n const [openDetails, setOpenDetails] = createSignal<ReadonlySet<T>>(new Set());\n const toggleDetails = (row: T) =>\n setOpenDetails((open) => {\n const next = new Set(open);\n if (!next.delete(row)) next.add(row);\n return next;\n });\n /** A bar column fills its track at `max`, or else at its largest value. */\n const barMax = createMemo(() => {\n const max = new Map<string, number>();\n for (const col of props.columns) {\n if (col.type !== \"bar\") continue;\n if (col.max !== undefined && col.max > 0) {\n max.set(col.id, col.max);\n continue;\n }\n let largest = 0;\n for (const row of props.rows) {\n const value = Number(valueOf(row, col));\n if (Number.isFinite(value)) largest = Math.max(largest, Math.abs(value));\n }\n max.set(col.id, largest);\n }\n return max;\n });\n const groups = createMemo(() => {\n const col = props.groupBy ? props.columns.find((entry) => entry.id === props.groupBy) : undefined;\n return col ? groupRows(props.rows, col, locale()) : null;\n });\n\n const sortKeyOf = (col: DataTableColumn<T>): string | null =>\n col.sortable === true ? col.id : typeof col.sortable === \"string\" ? col.sortable : null;\n\n /**\n * Sorting is a link by default: server-rendered tables keep the order in the\n * URL. Client tables pass onSortChange instead. Clicking the active column\n * flips its direction.\n */\n const nextSortFor = (key: string): DataTableSort => ({\n key,\n direction: props.sort?.key === key && props.sort?.direction === \"desc\" ? \"asc\" : \"desc\",\n });\n\n /** Only a sortable column carries a sort state; the rest carry none at all. */\n const ariaSortFor = (col: DataTableColumn<T>): \"ascending\" | \"descending\" | \"none\" | undefined => {\n const key = sortKeyOf(col);\n if (!key || (!props.sortHref && !props.onSortChange && !props.renderHeader)) return undefined;\n if (props.sort?.key !== key) return \"none\";\n return props.sort?.direction === \"asc\" ? \"ascending\" : \"descending\";\n };\n\n const renderHeaderDefault = (col: DataTableColumn<T>): JSX.Element => {\n const key = sortKeyOf(col);\n // Only how a column sorts decides the element. The order lives in its attributes, so a header button keeps\n // keyboard focus when a click sorts the table and the reader can press it again to reverse the order.\n const mode = createMemo(() => (!key ? null : props.sortHref ? \"link\" : props.onSortChange ? \"button\" : null));\n const active = () => key !== null && props.sort?.key === key;\n const title = () => (\n <>\n <span class=\"k2b-data-table__header-title\">{renderColumnPart(col.header, col)}</span>\n <Show when={col.subtitle !== undefined}>\n <span class=\"k2b-data-table__header-subtitle\">{renderColumnPart(col.subtitle, col)}</span>\n </Show>\n </>\n );\n const line = () => (\n <span class=\"k2b-data-table__header-line\">\n {title()}\n {/* Inactive columns keep a dimmed marker so the row reads as sortable. */}\n <i\n class={`k2b-data-table__sort-icon ti ${active() && props.sort?.direction === \"asc\" ? \"ti-arrow-up\" : \"ti-arrow-down\"}`}\n data-active={active() ? \"true\" : undefined}\n aria-hidden=\"true\"\n />\n </span>\n );\n\n return (\n <Switch\n fallback={\n <div class=\"k2b-data-table__header-content\" data-align={alignAttr(col)}>\n {title()}\n </div>\n }\n >\n <Match when={mode() === \"link\"}>\n <a\n href={key ? props.sortHref?.(nextSortFor(key)) : undefined}\n class=\"k2b-data-table__header-content k2b-data-table__sort\"\n data-align={alignAttr(col)}\n >\n {line()}\n </a>\n </Match>\n <Match when={mode() === \"button\"}>\n <button\n type=\"button\"\n class=\"k2b-data-table__header-content k2b-data-table__sort\"\n data-align={alignAttr(col)}\n onClick={() => key && props.onSortChange?.(nextSortFor(key))}\n >\n {line()}\n </button>\n </Match>\n </Switch>\n );\n };\n\n const numberFormat = createMemo(() => new Intl.NumberFormat(locale()));\n const renderValueDefault = (value: unknown) => defaultRender(value, locale(), numberFormat(), messages());\n /** A typed column shows its value the way its type reads; an untyped one falls back to the plain rendering. */\n const renderTypedValue = (col: DataTableColumn<T>, value: unknown): JSX.Element => {\n if (!col.type || isEmptyCell(value)) return renderValueDefault(value);\n if (col.type === \"status\") {\n const state = col.states?.[String(value)];\n return state ? <StatusBadge tone={state.tone} label={state.label} variant=\"dot\" /> : String(value);\n }\n if (col.type === \"flow\" && col.format?.currency && Number.isFinite(Number(value)))\n return <FlowAmount value={Number(value)} currency={col.format.currency} decimals={col.format.decimals} />;\n if (col.type === \"delta\" && Number.isFinite(Number(value)))\n return <DeltaBadge delta={{ value: Number(value), unit: col.delta?.unit, better: col.delta?.better }} />;\n if (col.type === \"bar\") {\n const number = Number(value);\n const max = barMax().get(col.id) ?? 0;\n if (!Number.isFinite(number)) return String(value);\n return (\n <span class=\"k2b-data-table__bar\">\n {formatTableNumber(number, col, locale())}\n <span class=\"k2b-data-table__bar-track\" aria-hidden=\"true\">\n <span style={{ width: `${max > 0 ? Math.min(100, (Math.abs(number) / max) * 100) : 0}%` }} />\n </span>\n </span>\n );\n }\n return tableCellText(value, col, locale());\n };\n\n const onRowKeyDown = (event: KeyboardEvent, row: T) => {\n if (!isInteractive()) return;\n if (isNestedRowControl(event)) return;\n const id = rowId(row);\n if (id !== undefined && props.selection?.keyDown(event, id)) return;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n (props.selection ? props.onRowDoubleClick : (props.onRowClick ?? props.onRowDoubleClick))?.(row);\n };\n\n const onRowClick = (event: MouseEvent, row: T) => {\n if (isNestedRowControl(event)) return;\n const id = rowId(row);\n if (id !== undefined) props.selection?.select(id, event);\n props.onRowClick?.(row);\n };\n\n const onRowDoubleClick = (event: MouseEvent, row: T) => {\n if (isNestedRowControl(event)) return;\n props.onRowDoubleClick?.(row);\n };\n\n const rowClass = (row: T) => {\n if (typeof props.rowClass === \"function\") return props.rowClass(row) ?? \"\";\n return props.rowClass ?? \"\";\n };\n\n // A heading given as a JSX node lives in the head; each details line needs its own copy, so it takes text or a fresh call.\n const detailLabel = (col: DataTableColumn<T>) =>\n typeof col.header === \"function\"\n ? col.header({ col })\n : typeof col.header === \"string\" || typeof col.header === \"number\"\n ? col.header\n : col.id;\n const cellContent = (row: T, col: DataTableColumn<T>, value: unknown) =>\n props.renderCell ? props.renderCell({ row, col, value, render: (v) => renderTypedValue(col, v) }) : renderTypedValue(col, value);\n\n /** `last` marks the final row of its body when details rows follow every row, so the frame keeps the only edge. */\n const renderRow = (row: T, last: () => boolean) => {\n const id = () => rowId(row);\n const isSelected = () =>\n props.selection ? props.selection.selected().has(id() ?? \"\") : props.selectedRowId && id() === props.selectedRowId;\n const detailsId = `k2b-data-table-${createUniqueId()}-details`;\n const open = () => openDetails().has(row);\n return (\n <>\n <tr\n ref={(element) => {\n const key = id();\n if (key !== undefined) props.selection?.register(key, element);\n }}\n class={`k2b-data-table__row ${rowClass(row)}`}\n data-hover={shouldHoverRows() ? \"true\" : undefined}\n data-clickable={shouldHoverRows() && isInteractive() ? \"true\" : undefined}\n data-selected={isSelected() ? \"true\" : undefined}\n data-details-open={open() ? \"true\" : undefined}\n data-last={detailsPriority() && last() ? \"true\" : undefined}\n aria-selected={props.selection ? !!isSelected() : undefined}\n tabIndex={props.selection ? (props.selection.focused() === id() ? 0 : -1) : isInteractive() ? 0 : undefined}\n onFocus={() => {\n const key = id();\n if (key !== undefined) props.selection?.markFocused(key);\n }}\n onClick={(event) => onRowClick(event, row)}\n onDblClick={(event) => onRowDoubleClick(event, row)}\n onContextMenu={() => props.onRowContextMenu?.(row)}\n onKeyDown={(e) => onRowKeyDown(e, row)}\n >\n <For each={props.columns}>\n {(col, index) => {\n const value = () => valueOf(row, col);\n return (\n <td\n class={`${col.cellClass ?? \"\"} ${col.class ?? \"\"}`}\n data-nowrap={nowrapAttr(col)}\n data-wrap={wrapAttr(col)}\n data-align={alignAttr(col)}\n data-priority={priorityAttr(col)}\n data-valign={props.verticalAlign && props.verticalAlign !== \"middle\" ? props.verticalAlign : undefined}\n data-highlighted={columnHighlighted(index())}\n onMouseEnter={() => setHoveredColumnIfEnabled(index())}\n >\n <div class={cellContentClass()}>{cellContent(row, col, value())}</div>\n </td>\n );\n }}\n </For>\n <Show when={detailsPriority()}>\n <td class=\"k2b-data-table__details-toggle\">\n <button\n type=\"button\"\n class=\"k2b-data-table__details-button\"\n aria-expanded={open()}\n aria-controls={detailsId}\n aria-label={dataTableMessages().showDetails}\n onClick={() => toggleDetails(row)}\n >\n <i class={`ti ${open() ? \"ti-chevron-up\" : \"ti-chevron-down\"}`} aria-hidden=\"true\" />\n </button>\n </td>\n </Show>\n </tr>\n <Show when={detailsPriority()}>\n {/* Only the values the table's width hides appear here; the rest are in the row above. */}\n <tr class=\"k2b-data-table__details\" id={detailsId} hidden={!open()}>\n <td colspan={columnCount()}>\n <dl>\n <For each={hiddenColumns()}>\n {(col) => (\n <div data-priority={priorityAttr(col)}>\n <dt>{detailLabel(col)}</dt>\n <dd>{cellContent(row, col, valueOf(row, col))}</dd>\n </div>\n )}\n </For>\n </dl>\n </td>\n </tr>\n </Show>\n </>\n );\n };\n\n onMount(() => {\n if (typeof IntersectionObserver === \"undefined\" || !loadMoreRef) return;\n // The viewport root notices the end whichever element scrolls; `isNearBottom` decides.\n const observer = new IntersectionObserver(maybeLoadMore, { rootMargin: `${loadMoreMargin}px` });\n observer.observe(loadMoreRef);\n onCleanup(() => observer.disconnect());\n });\n\n onMount(() => {\n setScrollbarEnhanced(true);\n syncScrollbars();\n const observer = typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(syncScrollbars);\n if (scrollRef) observer?.observe(scrollRef);\n if (tableRef) observer?.observe(tableRef);\n onCleanup(() => {\n observer?.disconnect();\n if (scrollingTimeout !== undefined) clearTimeout(scrollingTimeout);\n });\n });\n\n // Announced once per wait, outside the region that `aria-busy` keeps quiet.\n createEffect(\n on(\n () => !!props.loading && props.rows.length === 0,\n (waiting) => {\n if (waiting) announce(dataTableMessages().loadingRows);\n },\n ),\n );\n\n createEffect(() => {\n const rowsLength = props.rows.length;\n const nextHasMore = !!props.hasMore;\n const nextLoadingMore = !!props.loadingMore;\n if (rowsLength !== previousRowsLength || (previousLoadingMore && !nextLoadingMore) || (!previousHasMore && nextHasMore)) {\n loadMoreRequested = false;\n }\n previousRowsLength = rowsLength;\n previousLoadingMore = nextLoadingMore;\n previousHasMore = nextHasMore;\n hasMore = nextHasMore;\n loadingMore = nextLoadingMore;\n onLoadMore = props.onLoadMore;\n maybeLoadMore();\n queueMicrotask(syncScrollbars);\n });\n\n return (\n <Show when={props.columns.length > 0} fallback={<Placeholder surface=\"paper\" description={<>{dataTableMessages().noColumns}</>} />}>\n <Dynamic\n component={surface() === \"paper\" ? Paper : \"div\"}\n class={`k2b-table-shell ${props.class ?? \"\"}`}\n data-surface={surface()}\n data-has-footer={props.footer ? \"true\" : undefined}\n data-priorities={detailsPriority()}\n data-overflow-x={scrollbars().x.overflow ? \"true\" : undefined}\n data-overflow-y={scrollbars().y.overflow ? \"true\" : undefined}\n data-scrollbar-enhanced={scrollbarEnhanced() ? \"true\" : undefined}\n data-scrolling={scrolling() ? \"true\" : undefined}\n onMouseLeave={() => setHoveredColumn(null)}\n >\n <div\n ref={scrollRef}\n role=\"region\"\n aria-label={labelledBy() ? undefined : (props.ariaLabel ?? dataTableMessages().dataTable)}\n aria-labelledby={labelledBy()}\n aria-busy={props.loading ? \"true\" : undefined}\n tabIndex={0}\n class={`k2b-table-wrap${props.scrollClass ? ` ${props.scrollClass}` : \"\"}`}\n data-density={props.density === \"compact\" ? \"compact\" : undefined}\n data-has-footer={props.footer ? \"true\" : undefined}\n data-surface={surface()}\n data-scroll-preserve={props.scrollPreserveKey || undefined}\n onScroll={onScroll}\n >\n <table ref={tableRef} class={tableClass()} data-fill={props.fillHeight ? \"true\" : undefined}>\n <Show when={props.loading}>\n {/* Names the table while it waits; the announcement goes through the shared live region outside the busy region. */}\n <caption class=\"k2b-sr-only\">{dataTableMessages().loadingRows}</caption>\n </Show>\n <thead class=\"k2b-data-table__head\" data-sticky={props.stickyHeader === false ? undefined : \"true\"}>\n <tr class=\"k2b-data-table__head-row\">\n <For each={props.columns}>\n {(col, index) => (\n <th\n scope=\"col\"\n class={`${col.headerClass ?? \"\"} ${col.class ?? \"\"}`}\n data-align={alignAttr(col)}\n data-priority={priorityAttr(col)}\n data-highlighted={columnHighlighted(index())}\n aria-sort={ariaSortFor(col)}\n onMouseEnter={() => setHoveredColumnIfEnabled(index())}\n >\n {props.renderHeader ? props.renderHeader({ col, render: () => renderHeaderDefault(col) }) : renderHeaderDefault(col)}\n </th>\n )}\n </For>\n <Show when={detailsPriority()}>\n <th scope=\"col\" class=\"k2b-data-table__details-toggle\">\n <span class=\"k2b-sr-only\">{dataTableMessages().details}</span>\n </th>\n </Show>\n </tr>\n </thead>\n <Show\n when={props.rows.length > 0}\n fallback={\n <tbody>\n <Show\n when={props.loading}\n fallback={\n <tr>\n <Show\n when={props.query?.trim()}\n fallback={\n <td class=\"k2b-data-table__empty\" colspan={columnCount()}>\n <Placeholder description={<>{props.empty ?? dataTableMessages().noRecords}</>} />\n </td>\n }\n >\n {(query) => (\n <td class=\"k2b-data-table__no-match\" colspan={columnCount()}>\n {dataTableMessages().noMatch({ query: query() })}{\" \"}\n <Show when={props.onClearQuery}>\n <button type=\"button\" class=\"k2b-data-table__clear-query\" onClick={() => props.onClearQuery?.()}>\n {dataTableMessages().clearSearch}\n </button>\n </Show>\n </td>\n )}\n </Show>\n </tr>\n }\n >\n <For each={Array.from({ length: loadingRows() })}>\n {() => (\n <tr class=\"k2b-data-table__row\" data-loading=\"true\" aria-hidden=\"true\">\n <For each={props.columns}>\n {(col) => (\n <td data-align={alignAttr(col)} data-priority={priorityAttr(col)}>\n <span class=\"k2b-data-table__skeleton\" />\n </td>\n )}\n </For>\n <Show when={detailsPriority()}>\n <td class=\"k2b-data-table__details-toggle\" />\n </Show>\n </tr>\n )}\n </For>\n {/* The spacer takes the spare height while loading too, so rows keep their height when data arrives. */}\n <Show when={props.fillHeight}>\n <tr aria-hidden=\"true\">\n <td class=\"k2b-data-table__fill\" colspan={columnCount()} />\n </tr>\n </Show>\n </Show>\n </tbody>\n }\n >\n <Show\n when={groups()}\n fallback={\n <tbody>\n <For each={props.rows}>{(row, index) => renderRow(row, () => index() === props.rows.length - 1)}</For>\n <Show when={props.fillHeight}>\n <tr aria-hidden=\"true\">\n <td class=\"k2b-data-table__fill\" colspan={columnCount()} />\n </tr>\n </Show>\n </tbody>\n }\n >\n {(list) => (\n <>\n <For each={list()}>\n {(group) => (\n <tbody class=\"k2b-data-table__group\">\n <tr class=\"k2b-data-table__group-row\">\n <th scope=\"rowgroup\" colspan={columnCount()}>\n {group.label || \"—\"}\n <span class=\"k2b-data-table__group-count\">\n <span aria-hidden=\"true\">{group.rows.length}</span>\n <span class=\"k2b-sr-only\">, {dataTableMessages().rowCount({ count: group.rows.length })}</span>\n </span>\n </th>\n </tr>\n <For each={group.rows}>{(row, index) => renderRow(row, () => index() === group.rows.length - 1)}</For>\n </tbody>\n )}\n </For>\n <Show when={props.fillHeight}>\n <tbody aria-hidden=\"true\">\n <tr>\n <td class=\"k2b-data-table__fill\" colspan={columnCount()} />\n </tr>\n </tbody>\n </Show>\n </>\n )}\n </Show>\n </Show>\n <Show when={props.footer}>\n {(footer) => (\n <tfoot class=\"k2b-data-table__foot\" data-sticky=\"true\">\n <tr class=\"k2b-data-table__foot-row\">\n <For each={props.columns}>\n {(col, index) => {\n const value = () => footer().values?.[col.id];\n return (\n <td\n class=\"k2b-data-table__footer-cell\"\n data-nowrap={nowrapAttr(col)}\n data-align={alignAttr(col)}\n data-priority={priorityAttr(col)}\n data-highlighted={columnHighlighted(index())}\n onMouseEnter={() => setHoveredColumnIfEnabled(index())}\n >\n {footer().renderCell\n ? footer().renderCell!({ col, value: value(), render: (v) => renderTypedValue(col, v) })\n : renderTypedValue(col, value())}\n </td>\n );\n }}\n </For>\n <Show when={detailsPriority()}>\n <td class=\"k2b-data-table__footer-cell k2b-data-table__details-toggle\" />\n </Show>\n </tr>\n {/* Totals of hidden columns stay readable under the totals row while the width hides them. */}\n <Show when={detailsPriority()}>\n <tr class=\"k2b-data-table__details\" data-footer=\"true\">\n <td colspan={columnCount()}>\n <dl>\n <For each={hiddenColumns()}>\n {(col) => (\n <div data-priority={priorityAttr(col)}>\n <dt>{detailLabel(col)}</dt>\n <dd>\n {footer().renderCell\n ? footer().renderCell!({\n col,\n value: footer().values?.[col.id],\n render: (v) => renderTypedValue(col, v),\n })\n : renderTypedValue(col, footer().values?.[col.id])}\n </dd>\n </div>\n )}\n </For>\n </dl>\n </td>\n </tr>\n </Show>\n </tfoot>\n )}\n </Show>\n </table>\n <Show when={shouldRenderLoadMoreSentinel()}>\n <div ref={loadMoreRef} class=\"k2b-data-table__sentinel\" aria-hidden=\"true\" />\n </Show>\n </div>\n <For each={[\"y\", \"x\"] as const}>\n {(axis) => (\n <div\n class=\"k2b-data-table__scrollbar\"\n data-axis={axis}\n data-overflow={scrollbars()[axis].overflow ? \"true\" : undefined}\n aria-hidden=\"true\"\n onPointerDown={(event) => startScrollbarDrag(event, axis)}\n onPointerMove={(event) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) scrollFromPointer(event, axis);\n }}\n onPointerUp={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n onPointerCancel={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n >\n <span\n style={{\n \"--k2b-data-table-scroll-offset\": `${scrollbars()[axis].offset}px`,\n \"--k2b-data-table-scroll-size\": `${scrollbars()[axis].size}px`,\n }}\n />\n </div>\n )}\n </For>\n </Dynamic>\n </Show>\n );\n}\n\nconst DataTablePanel = (props: DataTablePanelProps): JSX.Element => {\n const headingId = `k2b-data-table-${createUniqueId()}-heading`;\n const [hasHeading, setHasHeading] = createSignal(false);\n const context: DataTablePanelContextValue = {\n headingId,\n hasHeading,\n registerHeading: () => setHasHeading(true),\n };\n\n return (\n <DataTablePanelContext.Provider value={context}>\n <Paper as=\"section\" class={`k2b-data-panel ${props.class ?? \"\"}`}>\n {props.children}\n </Paper>\n </DataTablePanelContext.Provider>\n );\n};\n\nconst DataTableHeader = (props: DataTableHeaderProps): JSX.Element => {\n const panel = useContext(DataTablePanelContext);\n panel?.registerHeading();\n\n return (\n <div class={`k2b-data-panel__header ${props.class ?? \"\"}`}>\n <PanelHeader\n title={<span id={panel?.headingId}>{props.title}</span>}\n subtitle={props.subtitle}\n actions={props.children}\n as={props.as}\n size={props.size}\n />\n </div>\n );\n};\n\nconst DataTableControls = (props: DataTableControlsProps): JSX.Element => (\n <div class={`k2b-data-panel__controls ${props.class ?? \"\"}`}>{props.children}</div>\n);\n\nconst DataTablePanelFooter = (props: DataTablePanelFooterProps): JSX.Element => (\n <footer class={`k2b-data-panel__footer ${props.class ?? \"\"}`}>{props.children}</footer>\n);\n\ntype DataTableComponent = {\n <T>(props: DataTableProps<T>): JSX.Element;\n Panel: (props: DataTablePanelProps) => JSX.Element;\n Header: (props: DataTableHeaderProps) => JSX.Element;\n Controls: (props: DataTableControlsProps) => JSX.Element;\n Footer: (props: DataTablePanelFooterProps) => JSX.Element;\n};\n\nconst DataTable = DataTableRoot as DataTableComponent;\nDataTable.Panel = DataTablePanel;\nDataTable.Header = DataTableHeader;\nDataTable.Controls = DataTableControls;\nDataTable.Footer = DataTablePanelFooter;\n\nexport default DataTable;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/DataTable.tsx"],"sourcesContent":["import {\n type Accessor,\n createContext,\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n For,\n type JSX,\n Match,\n on,\n onCleanup,\n onMount,\n Show,\n Switch,\n useContext,\n} from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport { announce } from \"../feedback/announce\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\nimport { useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { PanelHeader } from \"../layout/PanelHeader\";\nimport { DeltaBadge } from \"../surfaces/delta-badge\";\nimport { Paper } from \"../surfaces/Paper\";\nimport Placeholder from \"../surfaces/Placeholder\";\nimport { StatusBadge } from \"../surfaces/StatusBadge\";\nimport type { CollectionSelection } from \"./collection-selection\";\nimport {\n type DataTableTypedColumn,\n formatTableNumber,\n groupRows,\n isEmptyCell,\n isNumericColumnType,\n readTableValue,\n tableCellText,\n} from \"./data-table-columns\";\nimport { useDataTableMessages } from \"./data-table-messages\";\nimport { FlowAmount } from \"./FlowAmount\";\n\nexport type DataTableColumn<T> = {\n id: string;\n header: JSX.Element | ((ctx: { col: DataTableColumn<T> }) => JSX.Element);\n subtitle?: JSX.Element | ((ctx: { col: DataTableColumn<T> }) => JSX.Element);\n value?: keyof T | ((row: T) => unknown);\n class?: string;\n headerClass?: string;\n cellClass?: string;\n /** Defaults to right for numeric values and left for everything else. */\n align?: \"left\" | \"center\" | \"right\";\n /**\n * Keeps each value on one line, so the column is at least as wide as its\n * longest value. For dates, times, numbers, amounts, and short codes.\n * Defaults to true when the column's first value is a number or date. The\n * default cell wrapper already keeps every value on one line; this option\n * decides wrapping for content under a custom `cellContentClass`, and a\n * `white-space` that class sets itself wins.\n */\n nowrap?: boolean;\n /**\n * Marks the column sortable. Pass a string when the server's sort key\n * differs from the column id — they often do, because one column can show a\n * rate while another sorts by the absolute count behind it.\n */\n sortable?: boolean | string;\n /** What the column holds; see `DataTableColumnType`. */\n type?: DataTableTypedColumn[\"type\"];\n format?: DataTableTypedColumn[\"format\"];\n /** Labels and tones of a status column, by stored value. */\n states?: DataTableTypedColumn[\"states\"];\n /** The value a bar column fills its track at; defaults to its largest value. */\n max?: number;\n /** The zone a date column with a time reads in; defaults to the reader's. */\n timeZone?: string;\n /** How a delta column reads and rates its change. */\n delta?: DataTableTypedColumn[\"delta\"];\n /**\n * How much a narrow table needs the column: 1 (default) always shows; 3 hides below a table width of 560 px,\n * 2 below 420 px. Hidden values stay one tap away in the row's details.\n */\n priority?: 1 | 2 | 3;\n};\n\nexport type DataTableSort = { key: string; direction: \"asc\" | \"desc\" };\n\nexport type DataTableRenderCell<T> = (ctx: {\n row: T;\n col: DataTableColumn<T>;\n value: unknown;\n render: (value: unknown) => JSX.Element;\n}) => JSX.Element;\n\nexport type DataTableRenderHeader<T> = (ctx: { col: DataTableColumn<T>; render: () => JSX.Element }) => JSX.Element;\n\nexport type DataTableFooter<T> = {\n values?: Record<string, unknown>;\n renderCell?: (ctx: { col: DataTableColumn<T>; value: unknown; render: (value: unknown) => JSX.Element }) => JSX.Element;\n};\n\nexport type DataTableProps<T> = {\n rows: readonly T[];\n columns: readonly DataTableColumn<T>[];\n /** Accessible name for a standalone table region. Defaults to \"Data table\". */\n ariaLabel?: string;\n /** ID of a visible heading that labels the table region. Takes precedence over ariaLabel. */\n ariaLabelledBy?: string;\n getRowId?: (row: T) => string;\n /** Current server-side ordering, or null when the default applies. */\n sort?: DataTableSort | null;\n /**\n * Link target for a sortable header. Link-based because every admin table is\n * server-rendered: sorting is a query change, not client state.\n */\n sortHref?: (next: DataTableSort) => string;\n /**\n * Sorts on the client instead: sortable headers become buttons that report the\n * next order, with the same look and order of directions as `sortHref`.\n */\n onSortChange?: (next: DataTableSort) => void;\n selectedRowId?: string | null;\n /** Optional multi-selection shared with another collection view. Requires getRowId. */\n selection?: CollectionSelection;\n rowClass?: string | ((row: T) => string | undefined);\n hoverRows?: boolean;\n onRowClick?: (row: T) => void;\n onRowDoubleClick?: (row: T) => void;\n onRowContextMenu?: (row: T) => void;\n renderCell?: DataTableRenderCell<T>;\n renderHeader?: DataTableRenderHeader<T>;\n footer?: DataTableFooter<T>;\n hasMore?: boolean;\n loadingMore?: boolean;\n loading?: boolean;\n /** Initial placeholder count, clamped to an integer from 1 to 50. Defaults to 5. */\n loadingRows?: number;\n onLoadMore?: () => void;\n empty?: JSX.Element;\n density?: \"compact\" | \"normal\";\n stickyHeader?: boolean;\n highlightColumns?: boolean;\n verticalAlign?: \"top\" | \"middle\" | \"bottom\";\n cellContentClass?: string;\n fillHeight?: boolean;\n /** Visual frame for a standalone table. Defaults preserve the legacy class-based behavior. */\n surface?: \"paper\" | \"plain\";\n class?: string;\n /** Additional classes for the table element. Core table geometry is always retained. */\n tableClass?: string;\n /** Additional classes for the scrolling region, such as `k2b-detail-trail`. */\n scrollClass?: string;\n scrollPreserveKey?: string | false;\n /**\n * The id of the column whose values split the rows into groups, each its own `<tbody>` under a row with the\n * group's value and count, in the order the groups first appear.\n */\n groupBy?: string;\n /**\n * The host's search text. With no rows left, the table says that nothing matches it and offers to clear it\n * through `onClearQuery`, instead of `empty`. Filter the rows with `filterRows`.\n */\n query?: string;\n onClearQuery?: () => void;\n};\n\nexport type DataTablePanelProps = {\n children: JSX.Element;\n class?: string;\n};\n\nexport type DataTableHeaderProps = {\n title: string;\n subtitle?: string;\n children?: JSX.Element;\n as?: \"h1\" | \"h2\" | \"h3\";\n size?: \"sm\" | \"md\";\n class?: string;\n};\n\nexport type DataTableControlsProps = {\n children: JSX.Element;\n class?: string;\n};\n\nexport type DataTablePanelFooterProps = {\n children: JSX.Element;\n class?: string;\n};\n\ntype DataTablePanelContextValue = {\n headingId: string;\n hasHeading: Accessor<boolean>;\n registerHeading: () => void;\n};\n\nconst DataTablePanelContext = createContext<DataTablePanelContextValue>();\n\nconst defaultRender = (\n value: unknown,\n locale: string,\n numbers: Intl.NumberFormat,\n messages: ReturnType<ReturnType<typeof useUiMessages>>,\n): JSX.Element => {\n if (value === null || value === undefined || value === \"\") return \"—\";\n if (value instanceof Date) return value.toLocaleString(locale);\n if (typeof value === \"boolean\") return value ? messages.yes : messages.no;\n // Numbers read in the reader's language: grouping and decimal mark follow the locale, at most three decimals.\n if (typeof value === \"number\" || typeof value === \"bigint\") return numbers.format(Object.is(value, -0) ? 0 : value);\n if (typeof value === \"string\") return value;\n return JSON.stringify(value);\n};\n\nconst renderColumnPart = <T,>(\n part: DataTableColumn<T>[\"header\"] | DataTableColumn<T>[\"subtitle\"],\n col: DataTableColumn<T>,\n): JSX.Element => {\n if (typeof part === \"function\") return part({ col });\n return part;\n};\n\nconst rowInteractiveSelector = [\n \"a[href]\",\n \"button\",\n \"input\",\n \"label\",\n \"select\",\n \"textarea\",\n \"summary\",\n \"[contenteditable]\",\n \"[role='button']\",\n \"[role='checkbox']\",\n \"[role='link']\",\n \"[role='menuitem']\",\n \"[role='option']\",\n \"[role='radio']\",\n \"[role='switch']\",\n \"[role='tab']\",\n \"[tabindex]\",\n].join(\",\");\n\nconst isNestedRowControl = (event: Event): boolean =>\n event.target instanceof Element && event.target.closest(rowInteractiveSelector) !== event.currentTarget;\n\n/** Distance in pixels before the table's end at which the next page is requested. */\nconst loadMoreMargin = 240;\n\ntype DataTableScrollbarAxis = \"x\" | \"y\";\ntype DataTableScrollbarMetrics = { overflow: boolean; offset: number; size: number };\n\nconst scrollbarMetrics = (viewportSize: number, contentSize: number, scrollOffset: number): DataTableScrollbarMetrics => {\n if (viewportSize <= 0 || contentSize <= viewportSize + 1) return { overflow: false, offset: 0, size: 0 };\n const size = Math.min(viewportSize, Math.max(24, (viewportSize * viewportSize) / contentSize));\n const offset = (scrollOffset / (contentSize - viewportSize)) * (viewportSize - size);\n return { overflow: true, offset, size };\n};\n\nfunction DataTableRoot<T>(props: DataTableProps<T>) {\n const messages = useUiMessages();\n const dataTableMessages = useDataTableMessages();\n const locale = useLocale();\n const [hoveredColumn, setHoveredColumn] = createSignal<number | null>(null);\n const [scrollbars, setScrollbars] = createSignal<Record<DataTableScrollbarAxis, DataTableScrollbarMetrics>>({\n x: { overflow: false, offset: 0, size: 0 },\n y: { overflow: false, offset: 0, size: 0 },\n });\n const [scrollbarEnhanced, setScrollbarEnhanced] = createSignal(false);\n const [scrolling, setScrolling] = createSignal(false);\n const panel = useContext(DataTablePanelContext);\n let tableRef: HTMLTableElement | undefined;\n let scrollRef: HTMLDivElement | undefined;\n let loadMoreRef: HTMLDivElement | undefined;\n let scrollingTimeout: ReturnType<typeof setTimeout> | undefined;\n let scrollbarDragOffset = 0;\n let hasMore = false;\n let loadingMore = false;\n let onLoadMore: (() => void) | undefined;\n let loadMoreRequested = false;\n let previousRowsLength = props.rows.length;\n let previousLoadingMore = !!props.loadingMore;\n let previousHasMore = !!props.hasMore;\n const loadingRows = () => Math.min(50, Math.max(1, Math.trunc(Number.isNaN(props.loadingRows) ? 5 : (props.loadingRows ?? 5))));\n const rowId = (row: T) => props.getRowId?.(row);\n const isInteractive = () => !!props.selection || !!props.onRowClick || !!props.onRowDoubleClick;\n const shouldHoverRows = () => props.hoverRows ?? isInteractive();\n const shouldRenderLoadMoreSentinel = () => !!props.onLoadMore;\n const labelledBy = () => props.ariaLabelledBy ?? (panel?.hasHeading() ? panel.headingId : undefined);\n const surface = () => props.surface ?? (props.class ? \"plain\" : \"paper\");\n const cellContentClass = () => props.cellContentClass ?? \"k2b-data-table__cell-text\";\n const tableClass = () => `k2b-data-table ${props.tableClass ?? \"\"}`.trim();\n const columnHighlighted = (index: number) =>\n props.highlightColumns !== false && shouldHoverRows() && hoveredColumn() === index ? \"true\" : undefined;\n const setHoveredColumnIfEnabled = (index: number) => {\n if (shouldHoverRows()) setHoveredColumn(index);\n };\n\n /**\n * A bounded table scrolls its own viewport. A table that grows with its rows\n * leaves scrolling to the page or an ancestor, so its end is measured against\n * the browser viewport instead.\n */\n const isNearBottom = () => {\n if (!scrollRef || !loadMoreRef) return false;\n if (scrollRef.scrollHeight > scrollRef.clientHeight + 1) {\n return scrollRef.scrollTop + scrollRef.clientHeight >= scrollRef.scrollHeight - loadMoreMargin;\n }\n return loadMoreRef.getBoundingClientRect().top <= window.innerHeight + loadMoreMargin;\n };\n\n const maybeLoadMore = () => {\n if (!hasMore || loadingMore || !onLoadMore) return;\n if (!isNearBottom()) {\n // Leaving the end re-arms a request the owner declined, for example while its first page was still loading.\n loadMoreRequested = false;\n return;\n }\n if (loadMoreRequested) return;\n loadMoreRequested = true;\n try {\n onLoadMore();\n } catch (error) {\n loadMoreRequested = false;\n throw error;\n }\n };\n\n const syncScrollbars = () => {\n if (!scrollRef) return;\n setScrollbars({\n x: scrollbarMetrics(scrollRef.clientWidth, scrollRef.scrollWidth, scrollRef.scrollLeft),\n y: scrollbarMetrics(scrollRef.clientHeight, scrollRef.scrollHeight, scrollRef.scrollTop),\n });\n };\n\n const revealScrollbars = () => {\n setScrolling(true);\n if (scrollingTimeout !== undefined) clearTimeout(scrollingTimeout);\n scrollingTimeout = setTimeout(() => {\n setScrolling(false);\n scrollingTimeout = undefined;\n }, 700);\n };\n\n const onScroll = () => {\n syncScrollbars();\n revealScrollbars();\n maybeLoadMore();\n };\n\n const scrollFromPointer = (event: PointerEvent & { currentTarget: HTMLDivElement }, axis: DataTableScrollbarAxis) => {\n if (!scrollRef) return;\n const track = event.currentTarget;\n const metrics = scrollbars()[axis];\n const rect = track.getBoundingClientRect();\n const trackSize = axis === \"y\" ? rect.height : rect.width;\n const pointerOffset = axis === \"y\" ? event.clientY - rect.top : event.clientX - rect.left;\n const available = Math.max(1, trackSize - metrics.size);\n const thumbOffset = Math.min(available, Math.max(0, pointerOffset - scrollbarDragOffset));\n const maxScroll = axis === \"y\" ? scrollRef.scrollHeight - scrollRef.clientHeight : scrollRef.scrollWidth - scrollRef.clientWidth;\n if (axis === \"y\") scrollRef.scrollTop = (thumbOffset / available) * maxScroll;\n else scrollRef.scrollLeft = (thumbOffset / available) * maxScroll;\n syncScrollbars();\n revealScrollbars();\n };\n\n const startScrollbarDrag = (event: PointerEvent & { currentTarget: HTMLDivElement }, axis: DataTableScrollbarAxis) => {\n if (event.button !== 0) return;\n event.preventDefault();\n const metrics = scrollbars()[axis];\n const rect = event.currentTarget.getBoundingClientRect();\n const pointerOffset = axis === \"y\" ? event.clientY - rect.top : event.clientX - rect.left;\n scrollbarDragOffset =\n event.target === event.currentTarget ? metrics.size / 2 : Math.min(metrics.size, Math.max(0, pointerOffset - metrics.offset));\n event.currentTarget.setPointerCapture(event.pointerId);\n // The track's own pointerup or pointercancel ends the hold.\n suppressTextSelection(event.pointerId);\n scrollFromPointer(event, axis);\n };\n\n const valueOf = (row: T, col: DataTableColumn<T>) => readTableValue(row, col);\n\n const columnPresentation = createMemo(() => {\n const presentation = new Map<string, { align: NonNullable<DataTableColumn<T>[\"align\"]>; nowrap: boolean }>();\n for (const col of props.columns) {\n // A typed column says what it holds; only an untyped one is read from its first value.\n let numeric = isNumericColumnType(col.type);\n let date = col.type === \"date\";\n if (!col.type && (col.align === undefined || col.nowrap === undefined)) {\n for (const row of props.rows) {\n const value = valueOf(row, col);\n if (value === null || value === undefined || value === \"\") continue;\n numeric = typeof value === \"number\" || typeof value === \"bigint\";\n date = value instanceof Date;\n break;\n }\n }\n presentation.set(col.id, { align: col.align ?? (numeric ? \"right\" : \"left\"), nowrap: col.nowrap ?? (numeric || date) });\n }\n return presentation;\n });\n\n /** `data-align` mirrors Cloud's `text-left/center/right` on the same cell. */\n const alignAttr = (col: DataTableColumn<T>) => {\n const align = columnPresentation().get(col.id)?.align ?? \"left\";\n return align === \"left\" ? undefined : align;\n };\n\n const nowrapAttr = (col: DataTableColumn<T>) => (columnPresentation().get(col.id)?.nowrap ? \"true\" : undefined);\n /** Text columns wrap inside their cell; every other value keeps one line. */\n const wrapAttr = (col: DataTableColumn<T>) => (col.type === \"text\" && col.nowrap !== true ? \"true\" : undefined);\n const priorityAttr = (col: DataTableColumn<T>) => (col.priority === 2 || col.priority === 3 ? String(col.priority) : undefined);\n /** The lowest priority present: 3 shows the details toggle below 560 px, 2 below 420 px. */\n const detailsPriority = createMemo(() => {\n const priorities = props.columns.map((col) => col.priority ?? 1);\n return priorities.includes(3) ? \"3\" : priorities.includes(2) ? \"2\" : undefined;\n });\n // Keep the row's last child a cell in both SSR and the browser. Trailing conditional anchors\n // change WebKit's rendered text between the header and the first body row.\n const headerColumns = createMemo(() => (detailsPriority() ? [...props.columns, null] : props.columns));\n const hiddenColumns = () => props.columns.filter((col) => priorityAttr(col));\n const columnCount = () => props.columns.length + (detailsPriority() ? 1 : 0);\n const [openDetails, setOpenDetails] = createSignal<ReadonlySet<T>>(new Set());\n const toggleDetails = (row: T) =>\n setOpenDetails((open) => {\n const next = new Set(open);\n if (!next.delete(row)) next.add(row);\n return next;\n });\n /** A bar column fills its track at `max`, or else at its largest value. */\n const barMax = createMemo(() => {\n const max = new Map<string, number>();\n for (const col of props.columns) {\n if (col.type !== \"bar\") continue;\n if (col.max !== undefined && col.max > 0) {\n max.set(col.id, col.max);\n continue;\n }\n let largest = 0;\n for (const row of props.rows) {\n const value = Number(valueOf(row, col));\n if (Number.isFinite(value)) largest = Math.max(largest, Math.abs(value));\n }\n max.set(col.id, largest);\n }\n return max;\n });\n const groups = createMemo(() => {\n const col = props.groupBy ? props.columns.find((entry) => entry.id === props.groupBy) : undefined;\n return col ? groupRows(props.rows, col, locale()) : null;\n });\n\n const sortKeyOf = (col: DataTableColumn<T>): string | null =>\n col.sortable === true ? col.id : typeof col.sortable === \"string\" ? col.sortable : null;\n\n /**\n * Sorting is a link by default: server-rendered tables keep the order in the\n * URL. Client tables pass onSortChange instead. Clicking the active column\n * flips its direction.\n */\n const nextSortFor = (key: string): DataTableSort => ({\n key,\n direction: props.sort?.key === key && props.sort?.direction === \"desc\" ? \"asc\" : \"desc\",\n });\n\n /** Only a sortable column carries a sort state; the rest carry none at all. */\n const ariaSortFor = (col: DataTableColumn<T>): \"ascending\" | \"descending\" | \"none\" | undefined => {\n const key = sortKeyOf(col);\n if (!key || (!props.sortHref && !props.onSortChange && !props.renderHeader)) return undefined;\n if (props.sort?.key !== key) return \"none\";\n return props.sort?.direction === \"asc\" ? \"ascending\" : \"descending\";\n };\n\n const renderHeaderDefault = (col: DataTableColumn<T>): JSX.Element => {\n const key = sortKeyOf(col);\n // Only how a column sorts decides the element. The order lives in its attributes, so a header button keeps\n // keyboard focus when a click sorts the table and the reader can press it again to reverse the order.\n const mode = createMemo(() => (!key ? null : props.sortHref ? \"link\" : props.onSortChange ? \"button\" : null));\n const active = () => key !== null && props.sort?.key === key;\n const title = () => (\n <>\n <span class=\"k2b-data-table__header-title\">{renderColumnPart(col.header, col)}</span>\n <Show when={col.subtitle !== undefined}>\n <span class=\"k2b-data-table__header-subtitle\">{renderColumnPart(col.subtitle, col)}</span>\n </Show>\n </>\n );\n const line = () => (\n <span class=\"k2b-data-table__header-line\">\n {title()}\n {/* Inactive columns keep a dimmed marker so the row reads as sortable. */}\n <i\n class={`k2b-data-table__sort-icon ti ${active() && props.sort?.direction === \"asc\" ? \"ti-arrow-up\" : \"ti-arrow-down\"}`}\n data-active={active() ? \"true\" : undefined}\n aria-hidden=\"true\"\n />\n </span>\n );\n\n return (\n <Switch\n fallback={\n <div class=\"k2b-data-table__header-content\" data-align={alignAttr(col)}>\n {title()}\n </div>\n }\n >\n <Match when={mode() === \"link\"}>\n <a\n href={key ? props.sortHref?.(nextSortFor(key)) : undefined}\n class=\"k2b-data-table__header-content k2b-data-table__sort\"\n data-align={alignAttr(col)}\n >\n {line()}\n </a>\n </Match>\n <Match when={mode() === \"button\"}>\n <button\n type=\"button\"\n class=\"k2b-data-table__header-content k2b-data-table__sort\"\n data-align={alignAttr(col)}\n onClick={() => key && props.onSortChange?.(nextSortFor(key))}\n >\n {line()}\n </button>\n </Match>\n </Switch>\n );\n };\n\n const numberFormat = createMemo(() => new Intl.NumberFormat(locale()));\n const renderValueDefault = (value: unknown) => defaultRender(value, locale(), numberFormat(), messages());\n /** A typed column shows its value the way its type reads; an untyped one falls back to the plain rendering. */\n const renderTypedValue = (col: DataTableColumn<T>, value: unknown): JSX.Element => {\n if (!col.type || isEmptyCell(value)) return renderValueDefault(value);\n if (col.type === \"status\") {\n const state = col.states?.[String(value)];\n return state ? <StatusBadge tone={state.tone} label={state.label} variant=\"dot\" /> : String(value);\n }\n if (col.type === \"flow\" && col.format?.currency && Number.isFinite(Number(value)))\n return <FlowAmount value={Number(value)} currency={col.format.currency} decimals={col.format.decimals} />;\n if (col.type === \"delta\" && Number.isFinite(Number(value)))\n return <DeltaBadge delta={{ value: Number(value), unit: col.delta?.unit, better: col.delta?.better }} />;\n if (col.type === \"bar\") {\n const number = Number(value);\n const max = barMax().get(col.id) ?? 0;\n if (!Number.isFinite(number)) return String(value);\n return (\n <span class=\"k2b-data-table__bar\">\n {formatTableNumber(number, col, locale())}\n <span class=\"k2b-data-table__bar-track\" aria-hidden=\"true\">\n <span style={{ width: `${max > 0 ? Math.min(100, (Math.abs(number) / max) * 100) : 0}%` }} />\n </span>\n </span>\n );\n }\n return tableCellText(value, col, locale());\n };\n\n const onRowKeyDown = (event: KeyboardEvent, row: T) => {\n if (!isInteractive()) return;\n if (isNestedRowControl(event)) return;\n const id = rowId(row);\n if (id !== undefined && props.selection?.keyDown(event, id)) return;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n (props.selection ? props.onRowDoubleClick : (props.onRowClick ?? props.onRowDoubleClick))?.(row);\n };\n\n const onRowClick = (event: MouseEvent, row: T) => {\n if (isNestedRowControl(event)) return;\n const id = rowId(row);\n if (id !== undefined) props.selection?.select(id, event);\n props.onRowClick?.(row);\n };\n\n const onRowDoubleClick = (event: MouseEvent, row: T) => {\n if (isNestedRowControl(event)) return;\n props.onRowDoubleClick?.(row);\n };\n\n const rowClass = (row: T) => {\n if (typeof props.rowClass === \"function\") return props.rowClass(row) ?? \"\";\n return props.rowClass ?? \"\";\n };\n\n // A heading given as a JSX node lives in the head; each details line needs its own copy, so it takes text or a fresh call.\n const detailLabel = (col: DataTableColumn<T>) =>\n typeof col.header === \"function\"\n ? col.header({ col })\n : typeof col.header === \"string\" || typeof col.header === \"number\"\n ? col.header\n : col.id;\n const cellContent = (row: T, col: DataTableColumn<T>, value: unknown) =>\n props.renderCell ? props.renderCell({ row, col, value, render: (v) => renderTypedValue(col, v) }) : renderTypedValue(col, value);\n\n /** `last` marks the final row of its body when details rows follow every row, so the frame keeps the only edge. */\n const renderRow = (row: T, last: () => boolean) => {\n const id = () => rowId(row);\n const isSelected = () =>\n props.selection ? props.selection.selected().has(id() ?? \"\") : props.selectedRowId && id() === props.selectedRowId;\n const detailsId = `k2b-data-table-${createUniqueId()}-details`;\n const open = () => openDetails().has(row);\n return (\n <>\n <tr\n ref={(element) => {\n const key = id();\n if (key !== undefined) props.selection?.register(key, element);\n }}\n class={`k2b-data-table__row ${rowClass(row)}`}\n data-hover={shouldHoverRows() ? \"true\" : undefined}\n data-clickable={shouldHoverRows() && isInteractive() ? \"true\" : undefined}\n data-selected={isSelected() ? \"true\" : undefined}\n data-details-open={open() ? \"true\" : undefined}\n data-last={detailsPriority() && last() ? \"true\" : undefined}\n aria-selected={props.selection ? !!isSelected() : undefined}\n tabIndex={props.selection ? (props.selection.focused() === id() ? 0 : -1) : isInteractive() ? 0 : undefined}\n onFocus={() => {\n const key = id();\n if (key !== undefined) props.selection?.markFocused(key);\n }}\n onClick={(event) => onRowClick(event, row)}\n onDblClick={(event) => onRowDoubleClick(event, row)}\n onContextMenu={() => props.onRowContextMenu?.(row)}\n onKeyDown={(e) => onRowKeyDown(e, row)}\n >\n <For each={props.columns}>\n {(col, index) => {\n const value = () => valueOf(row, col);\n return (\n <td\n class={`${col.cellClass ?? \"\"} ${col.class ?? \"\"}`}\n data-nowrap={nowrapAttr(col)}\n data-wrap={wrapAttr(col)}\n data-align={alignAttr(col)}\n data-priority={priorityAttr(col)}\n data-valign={props.verticalAlign && props.verticalAlign !== \"middle\" ? props.verticalAlign : undefined}\n data-highlighted={columnHighlighted(index())}\n onMouseEnter={() => setHoveredColumnIfEnabled(index())}\n >\n <div class={cellContentClass()}>{cellContent(row, col, value())}</div>\n </td>\n );\n }}\n </For>\n <Show when={detailsPriority()}>\n <td class=\"k2b-data-table__details-toggle\">\n <button\n type=\"button\"\n class=\"k2b-data-table__details-button\"\n aria-expanded={open()}\n aria-controls={detailsId}\n aria-label={dataTableMessages().showDetails}\n onClick={() => toggleDetails(row)}\n >\n <i class={`ti ${open() ? \"ti-chevron-up\" : \"ti-chevron-down\"}`} aria-hidden=\"true\" />\n </button>\n </td>\n </Show>\n </tr>\n <Show when={detailsPriority()}>\n {/* Only the values the table's width hides appear here; the rest are in the row above. */}\n <tr class=\"k2b-data-table__details\" id={detailsId} hidden={!open()}>\n <td colspan={columnCount()}>\n <dl>\n <For each={hiddenColumns()}>\n {(col) => (\n <div data-priority={priorityAttr(col)}>\n <dt>{detailLabel(col)}</dt>\n <dd>{cellContent(row, col, valueOf(row, col))}</dd>\n </div>\n )}\n </For>\n </dl>\n </td>\n </tr>\n </Show>\n </>\n );\n };\n\n onMount(() => {\n if (typeof IntersectionObserver === \"undefined\" || !loadMoreRef) return;\n // The viewport root notices the end whichever element scrolls; `isNearBottom` decides.\n const observer = new IntersectionObserver(maybeLoadMore, { rootMargin: `${loadMoreMargin}px` });\n observer.observe(loadMoreRef);\n onCleanup(() => observer.disconnect());\n });\n\n onMount(() => {\n setScrollbarEnhanced(true);\n syncScrollbars();\n const observer = typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(syncScrollbars);\n if (scrollRef) observer?.observe(scrollRef);\n if (tableRef) observer?.observe(tableRef);\n onCleanup(() => {\n observer?.disconnect();\n if (scrollingTimeout !== undefined) clearTimeout(scrollingTimeout);\n });\n });\n\n // Announced once per wait, outside the region that `aria-busy` keeps quiet.\n createEffect(\n on(\n () => !!props.loading && props.rows.length === 0,\n (waiting) => {\n if (waiting) announce(dataTableMessages().loadingRows);\n },\n ),\n );\n\n createEffect(() => {\n const rowsLength = props.rows.length;\n const nextHasMore = !!props.hasMore;\n const nextLoadingMore = !!props.loadingMore;\n if (rowsLength !== previousRowsLength || (previousLoadingMore && !nextLoadingMore) || (!previousHasMore && nextHasMore)) {\n loadMoreRequested = false;\n }\n previousRowsLength = rowsLength;\n previousLoadingMore = nextLoadingMore;\n previousHasMore = nextHasMore;\n hasMore = nextHasMore;\n loadingMore = nextLoadingMore;\n onLoadMore = props.onLoadMore;\n maybeLoadMore();\n queueMicrotask(syncScrollbars);\n });\n\n return (\n <Show when={props.columns.length > 0} fallback={<Placeholder surface=\"paper\" description={<>{dataTableMessages().noColumns}</>} />}>\n <Dynamic\n component={surface() === \"paper\" ? Paper : \"div\"}\n class={`k2b-table-shell ${props.class ?? \"\"}`}\n data-surface={surface()}\n data-has-footer={props.footer ? \"true\" : undefined}\n data-priorities={detailsPriority()}\n data-overflow-x={scrollbars().x.overflow ? \"true\" : undefined}\n data-overflow-y={scrollbars().y.overflow ? \"true\" : undefined}\n data-scrollbar-enhanced={scrollbarEnhanced() ? \"true\" : undefined}\n data-scrolling={scrolling() ? \"true\" : undefined}\n onMouseLeave={() => setHoveredColumn(null)}\n >\n <div\n ref={scrollRef}\n role=\"region\"\n aria-label={labelledBy() ? undefined : (props.ariaLabel ?? dataTableMessages().dataTable)}\n aria-labelledby={labelledBy()}\n aria-busy={props.loading ? \"true\" : undefined}\n tabIndex={0}\n class={`k2b-table-wrap${props.scrollClass ? ` ${props.scrollClass}` : \"\"}`}\n data-density={props.density === \"compact\" ? \"compact\" : undefined}\n data-has-footer={props.footer ? \"true\" : undefined}\n data-surface={surface()}\n data-scroll-preserve={props.scrollPreserveKey || undefined}\n onScroll={onScroll}\n >\n <table ref={tableRef} class={tableClass()} data-fill={props.fillHeight ? \"true\" : undefined}>\n <Show when={props.loading}>\n {/* Names the table while it waits; the announcement goes through the shared live region outside the busy region. */}\n <caption class=\"k2b-sr-only\">{dataTableMessages().loadingRows}</caption>\n </Show>\n <thead class=\"k2b-data-table__head\" data-sticky={props.stickyHeader === false ? undefined : \"true\"}>\n <tr class=\"k2b-data-table__head-row\">\n <For each={headerColumns()}>\n {(col, index) =>\n col ? (\n <th\n scope=\"col\"\n class={`${col.headerClass ?? \"\"} ${col.class ?? \"\"}`}\n data-align={alignAttr(col)}\n data-priority={priorityAttr(col)}\n data-highlighted={columnHighlighted(index())}\n aria-sort={ariaSortFor(col)}\n onMouseEnter={() => setHoveredColumnIfEnabled(index())}\n >\n {props.renderHeader\n ? props.renderHeader({ col, render: () => renderHeaderDefault(col) })\n : renderHeaderDefault(col)}\n </th>\n ) : (\n <th scope=\"col\" class=\"k2b-data-table__details-toggle\">\n <span class=\"k2b-sr-only\">{dataTableMessages().details}</span>\n </th>\n )\n }\n </For>\n </tr>\n </thead>\n <Show\n when={props.rows.length > 0}\n fallback={\n <tbody>\n <Show\n when={props.loading}\n fallback={\n <tr>\n <Show\n when={props.query?.trim()}\n fallback={\n <td class=\"k2b-data-table__empty\" colspan={columnCount()}>\n <Placeholder description={<>{props.empty ?? dataTableMessages().noRecords}</>} />\n </td>\n }\n >\n {(query) => (\n <td class=\"k2b-data-table__no-match\" colspan={columnCount()}>\n {dataTableMessages().noMatch({ query: query() })}{\" \"}\n <Show when={props.onClearQuery}>\n <button type=\"button\" class=\"k2b-data-table__clear-query\" onClick={() => props.onClearQuery?.()}>\n {dataTableMessages().clearSearch}\n </button>\n </Show>\n </td>\n )}\n </Show>\n </tr>\n }\n >\n <For each={Array.from({ length: loadingRows() })}>\n {() => (\n <tr class=\"k2b-data-table__row\" data-loading=\"true\" aria-hidden=\"true\">\n <For each={props.columns}>\n {(col) => (\n <td data-align={alignAttr(col)} data-priority={priorityAttr(col)}>\n <span class=\"k2b-data-table__skeleton\" />\n </td>\n )}\n </For>\n <Show when={detailsPriority()}>\n <td class=\"k2b-data-table__details-toggle\" />\n </Show>\n </tr>\n )}\n </For>\n {/* The spacer takes the spare height while loading too, so rows keep their height when data arrives. */}\n <Show when={props.fillHeight}>\n <tr aria-hidden=\"true\">\n <td class=\"k2b-data-table__fill\" colspan={columnCount()} />\n </tr>\n </Show>\n </Show>\n </tbody>\n }\n >\n <Show\n when={groups()}\n fallback={\n <tbody>\n <For each={props.rows}>{(row, index) => renderRow(row, () => index() === props.rows.length - 1)}</For>\n <Show when={props.fillHeight}>\n <tr aria-hidden=\"true\">\n <td class=\"k2b-data-table__fill\" colspan={columnCount()} />\n </tr>\n </Show>\n </tbody>\n }\n >\n {(list) => (\n <>\n <For each={list()}>\n {(group) => (\n <tbody class=\"k2b-data-table__group\">\n <tr class=\"k2b-data-table__group-row\">\n <th scope=\"rowgroup\" colspan={columnCount()}>\n {group.label || \"—\"}\n <span class=\"k2b-data-table__group-count\">\n <span aria-hidden=\"true\">{group.rows.length}</span>\n <span class=\"k2b-sr-only\">, {dataTableMessages().rowCount({ count: group.rows.length })}</span>\n </span>\n </th>\n </tr>\n <For each={group.rows}>{(row, index) => renderRow(row, () => index() === group.rows.length - 1)}</For>\n </tbody>\n )}\n </For>\n <Show when={props.fillHeight}>\n <tbody aria-hidden=\"true\">\n <tr>\n <td class=\"k2b-data-table__fill\" colspan={columnCount()} />\n </tr>\n </tbody>\n </Show>\n </>\n )}\n </Show>\n </Show>\n <Show when={props.footer}>\n {(footer) => (\n <tfoot class=\"k2b-data-table__foot\" data-sticky=\"true\">\n <tr class=\"k2b-data-table__foot-row\">\n <For each={props.columns}>\n {(col, index) => {\n const value = () => footer().values?.[col.id];\n return (\n <td\n class=\"k2b-data-table__footer-cell\"\n data-nowrap={nowrapAttr(col)}\n data-align={alignAttr(col)}\n data-priority={priorityAttr(col)}\n data-highlighted={columnHighlighted(index())}\n onMouseEnter={() => setHoveredColumnIfEnabled(index())}\n >\n {footer().renderCell\n ? footer().renderCell!({ col, value: value(), render: (v) => renderTypedValue(col, v) })\n : renderTypedValue(col, value())}\n </td>\n );\n }}\n </For>\n <Show when={detailsPriority()}>\n <td class=\"k2b-data-table__footer-cell k2b-data-table__details-toggle\" />\n </Show>\n </tr>\n {/* Totals of hidden columns stay readable under the totals row while the width hides them. */}\n <Show when={detailsPriority()}>\n <tr class=\"k2b-data-table__details\" data-footer=\"true\">\n <td colspan={columnCount()}>\n <dl>\n <For each={hiddenColumns()}>\n {(col) => (\n <div data-priority={priorityAttr(col)}>\n <dt>{detailLabel(col)}</dt>\n <dd>\n {footer().renderCell\n ? footer().renderCell!({\n col,\n value: footer().values?.[col.id],\n render: (v) => renderTypedValue(col, v),\n })\n : renderTypedValue(col, footer().values?.[col.id])}\n </dd>\n </div>\n )}\n </For>\n </dl>\n </td>\n </tr>\n </Show>\n </tfoot>\n )}\n </Show>\n </table>\n <Show when={shouldRenderLoadMoreSentinel()}>\n <div ref={loadMoreRef} class=\"k2b-data-table__sentinel\" aria-hidden=\"true\" />\n </Show>\n </div>\n <For each={[\"y\", \"x\"] as const}>\n {(axis) => (\n <div\n class=\"k2b-data-table__scrollbar\"\n data-axis={axis}\n data-overflow={scrollbars()[axis].overflow ? \"true\" : undefined}\n aria-hidden=\"true\"\n onPointerDown={(event) => startScrollbarDrag(event, axis)}\n onPointerMove={(event) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) scrollFromPointer(event, axis);\n }}\n onPointerUp={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n onPointerCancel={(event) => event.currentTarget.releasePointerCapture(event.pointerId)}\n >\n <span\n style={{\n \"--k2b-data-table-scroll-offset\": `${scrollbars()[axis].offset}px`,\n \"--k2b-data-table-scroll-size\": `${scrollbars()[axis].size}px`,\n }}\n />\n </div>\n )}\n </For>\n </Dynamic>\n </Show>\n );\n}\n\nconst DataTablePanel = (props: DataTablePanelProps): JSX.Element => {\n const headingId = `k2b-data-table-${createUniqueId()}-heading`;\n const [hasHeading, setHasHeading] = createSignal(false);\n const context: DataTablePanelContextValue = {\n headingId,\n hasHeading,\n registerHeading: () => setHasHeading(true),\n };\n\n return (\n <DataTablePanelContext.Provider value={context}>\n <Paper as=\"section\" class={`k2b-data-panel ${props.class ?? \"\"}`}>\n {props.children}\n </Paper>\n </DataTablePanelContext.Provider>\n );\n};\n\nconst DataTableHeader = (props: DataTableHeaderProps): JSX.Element => {\n const panel = useContext(DataTablePanelContext);\n panel?.registerHeading();\n\n return (\n <div class={`k2b-data-panel__header ${props.class ?? \"\"}`}>\n <PanelHeader\n title={<span id={panel?.headingId}>{props.title}</span>}\n subtitle={props.subtitle}\n actions={props.children}\n as={props.as}\n size={props.size}\n />\n </div>\n );\n};\n\nconst DataTableControls = (props: DataTableControlsProps): JSX.Element => (\n <div class={`k2b-data-panel__controls ${props.class ?? \"\"}`}>{props.children}</div>\n);\n\nconst DataTablePanelFooter = (props: DataTablePanelFooterProps): JSX.Element => (\n <footer class={`k2b-data-panel__footer ${props.class ?? \"\"}`}>{props.children}</footer>\n);\n\ntype DataTableComponent = {\n <T>(props: DataTableProps<T>): JSX.Element;\n Panel: (props: DataTablePanelProps) => JSX.Element;\n Header: (props: DataTableHeaderProps) => JSX.Element;\n Controls: (props: DataTableControlsProps) => JSX.Element;\n Footer: (props: DataTablePanelFooterProps) => JSX.Element;\n};\n\nconst DataTable = DataTableRoot as DataTableComponent;\nDataTable.Panel = DataTablePanel;\nDataTable.Header = DataTableHeader;\nDataTable.Controls = DataTableControls;\nDataTable.Footer = DataTablePanelFooter;\n\nexport default DataTable;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -9,7 +9,7 @@ var _tmpl$ = ["<span class=\"k2b-content-lightbox__counter k2b-overlay-surface\"
|
|
|
9
9
|
_tmpl$4 = ["<button type=\"button\" class=\"k2b-content-lightbox__nav k2b-overlay-surface\" data-direction=\"previous\"", "><i class=\"ti ti-chevron-left\" aria-hidden=\"true\"></i></button>"],
|
|
10
10
|
_tmpl$5 = ["<button type=\"button\" class=\"k2b-content-lightbox__nav k2b-overlay-surface\" data-direction=\"next\"", "><i class=\"ti ti-chevron-right\" aria-hidden=\"true\"></i></button>"],
|
|
11
11
|
_tmpl$6 = ["<div class=\"k2b-content-lightbox__dots k2b-overlay-surface\" role=\"group\"", ">", "</div>"],
|
|
12
|
-
_tmpl$7 = ["<dialog class=\"k2b-content-lightbox\"", "><div class=\"k2b-content-lightbox__bar\"><div class=\"k2b-content-lightbox__meta\">", "", "</div><div class=\"k2b-content-lightbox__actions\">", "", "<button type=\"button\" class=\"k2b-content-lightbox__button k2b-overlay-surface\"", "><i class=\"ti ti-x\" aria-hidden=\"true\"></i><span class=\"k2b-content-lightbox__button-label\">", "</span></button></div></div><div class=\"k2b-content-lightbox__stage\">", "</div>", "", "</dialog>"],
|
|
12
|
+
_tmpl$7 = ["<dialog class=\"k2b-content-lightbox\"", "><div class=\"k2b-content-lightbox__bar\"><div class=\"k2b-content-lightbox__meta\">", "", "</div><div class=\"k2b-content-lightbox__actions\">", "", "<button type=\"button\" class=\"k2b-content-lightbox__button k2b-overlay-surface\"", "><i class=\"ti ti-x\" aria-hidden=\"true\"></i><span class=\"k2b-content-lightbox__button-label\">", "</span></button></div></div><div class=\"k2b-content-lightbox__stage\">", "</div>", "", "", "</dialog>"],
|
|
13
13
|
_tmpl$8 = ["<button type=\"button\" class=\"k2b-content-lightbox__button k2b-overlay-surface\"", "><i", " aria-hidden=\"true\"></i><span class=\"k2b-content-lightbox__button-label\">", "</span></button>"],
|
|
14
14
|
_tmpl$9 = ["<img", " class=\"k2b-content-lightbox__image\" draggable=\"false\">"],
|
|
15
15
|
_tmpl$0 = ["<button type=\"button\" class=\"k2b-content-lightbox__dot\"", "></button>"];
|
|
@@ -17,9 +17,12 @@ import { createEffect, createSignal, For, onCleanup, onMount, Show } from "solid
|
|
|
17
17
|
import { returnFocus, ringOnReturn } from "../internal/focus-return";
|
|
18
18
|
import { useUiMessages } from "../intl/messages";
|
|
19
19
|
import { useLightboxMessages } from "./lightbox-messages";
|
|
20
|
+
import { ThumbnailStrip } from "./ThumbnailStrip";
|
|
20
21
|
|
|
21
22
|
/** One more thing to do with the shown image, beside Download: a short label, its icon class, and what it does. */
|
|
22
23
|
|
|
24
|
+
/** From this many images the gallery shows a thumbnail strip instead of dots. */
|
|
25
|
+
const STRIP_FROM = 4;
|
|
23
26
|
/**
|
|
24
27
|
* Minimal, accessible lightbox using native <dialog>.
|
|
25
28
|
* Supports keyboard navigation, touch swipe gestures, and screen readers.
|
|
@@ -76,7 +79,8 @@ export default function Lightbox(props) {
|
|
|
76
79
|
|
|
77
80
|
// Keyboard navigation
|
|
78
81
|
const handleKeyDown = e => {
|
|
79
|
-
|
|
82
|
+
// A part that handled the key itself, such as the thumbnail strip moving its focus, keeps it.
|
|
83
|
+
if (e.defaultPrevented || !ownsKey(e.target)) return;
|
|
80
84
|
switch (e.key) {
|
|
81
85
|
case "Escape":
|
|
82
86
|
// Handled here, so WebKit does not light the returned focus for this key.
|
|
@@ -181,7 +185,32 @@ export default function Lightbox(props) {
|
|
|
181
185
|
}
|
|
182
186
|
})), _$escape(_$createComponent(Show, {
|
|
183
187
|
get when() {
|
|
184
|
-
return
|
|
188
|
+
return props.images.length >= STRIP_FROM;
|
|
189
|
+
},
|
|
190
|
+
get children() {
|
|
191
|
+
return _$createComponent(ThumbnailStrip, {
|
|
192
|
+
"class": "k2b-content-lightbox__strip k2b-overlay-surface",
|
|
193
|
+
get label() {
|
|
194
|
+
return lightboxMessages().imageNavigation;
|
|
195
|
+
},
|
|
196
|
+
get items() {
|
|
197
|
+
return props.images.map((image, i) => ({
|
|
198
|
+
id: String(i),
|
|
199
|
+
name: image.alt || lightboxMessages().goToImage({
|
|
200
|
+
index: i + 1
|
|
201
|
+
}),
|
|
202
|
+
thumbnail: image.thumbnail ?? image.src
|
|
203
|
+
}));
|
|
204
|
+
},
|
|
205
|
+
get currentItem() {
|
|
206
|
+
return String(index());
|
|
207
|
+
},
|
|
208
|
+
onSelectItem: id => setIndex(Number(id))
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
})), _$escape(_$createComponent(Show, {
|
|
212
|
+
get when() {
|
|
213
|
+
return _$memo(() => !!isMultiple())() && props.images.length < STRIP_FROM;
|
|
185
214
|
},
|
|
186
215
|
get children() {
|
|
187
216
|
return _$ssr(_tmpl$6, _$ssrAttribute("aria-label", _$escape(lightboxMessages().imageNavigation, true), false), _$escape(_$createComponent(For, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/Lightbox.tsx"],"sourcesContent":["import { createEffect, createSignal, For, onCleanup, onMount, Show } from \"solid-js\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { useLightboxMessages } from \"./lightbox-messages\";\n\n/** One more thing to do with the shown image, beside Download: a short label, its icon class, and what it does. */\nexport type LightboxAction = {\n label: string;\n icon: string;\n onClick: () => void;\n};\n\nexport type LightboxImage = {\n src: string;\n alt?: string;\n downloadUrl?: string;\n /** Actions for this image, shown before Download in the same style. */\n actions?: readonly LightboxAction[];\n};\n\ntype LightboxProps = {\n images: LightboxImage[];\n initialIndex?: number;\n onClose: () => void;\n};\n\n/**\n * Minimal, accessible lightbox using native <dialog>.\n * Supports keyboard navigation, touch swipe gestures, and screen readers.\n */\nexport default function Lightbox(props: LightboxProps) {\n const messages = useUiMessages();\n const lightboxMessages = useLightboxMessages();\n const clampIndex = (value: number, images = props.images): number =>\n images.length === 0 ? 0 : Math.max(0, Math.min(value, images.length - 1));\n const [index, setIndex] = createSignal(clampIndex(props.initialIndex ?? 0));\n let dialogRef!: HTMLDialogElement;\n let opener: HTMLElement | null = null;\n let openerRing = true;\n\n createEffect(\n (previous: { images: LightboxImage[]; initialIndex: number | undefined }) => {\n const images = props.images;\n const initialIndex = props.initialIndex;\n setIndex((currentIndex) => {\n if (initialIndex !== previous.initialIndex) return clampIndex(initialIndex ?? 0, images);\n const previousImage = previous.images[currentIndex];\n const retained = previousImage ? images.findIndex((image) => image === previousImage || image.src === previousImage.src) : -1;\n return retained >= 0 ? retained : clampIndex(currentIndex, images);\n });\n return { images, initialIndex };\n },\n { images: props.images, initialIndex: props.initialIndex },\n );\n\n // Touch gesture tracking\n let touchStartX = 0;\n let touchStartY = 0;\n const SWIPE_THRESHOLD = 50;\n\n const current = () => props.images[index()];\n const isMultiple = () => props.images.length > 1;\n const prev = () => {\n if (!isMultiple()) return;\n setIndex((i) => (i - 1 + props.images.length) % props.images.length);\n };\n const next = () => {\n if (!isMultiple()) return;\n setIndex((i) => (i + 1) % props.images.length);\n };\n\n const close = () => {\n dialogRef.close();\n returnFocus(opener, openerRing);\n props.onClose();\n };\n\n // A key belongs to the Lightbox while focus is inside it, or on the page with no other dialog open. A dialog opened\n // from one of its actions keeps its own keys: Escape closes that dialog, and arrows stay in its fields.\n const ownsKey = (target: EventTarget | null) =>\n target instanceof Node &&\n (dialogRef.contains(target) ||\n (target === document.body && Array.from(document.querySelectorAll(\"dialog[open]\")).every((dialog) => dialog === dialogRef)));\n\n // Keyboard navigation\n const handleKeyDown = (e: KeyboardEvent) => {\n if (!ownsKey(e.target)) return;\n switch (e.key) {\n case \"Escape\":\n // Handled here, so WebKit does not light the returned focus for this key.\n e.preventDefault();\n close();\n break;\n case \"ArrowLeft\":\n prev();\n break;\n case \"ArrowRight\":\n next();\n break;\n }\n };\n\n // Touch handlers for swipe gestures\n const handleTouchStart = (e: TouchEvent) => {\n const touch = e.touches[0];\n if (touch) {\n touchStartX = touch.clientX;\n touchStartY = touch.clientY;\n }\n };\n\n const handleTouchEnd = (e: TouchEvent) => {\n const touch = e.changedTouches[0];\n if (!touch) return;\n\n const deltaX = touch.clientX - touchStartX;\n const deltaY = touch.clientY - touchStartY;\n\n // Only trigger swipe if horizontal movement is dominant\n if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > SWIPE_THRESHOLD) {\n if (deltaX > 0) {\n prev();\n } else {\n next();\n }\n }\n };\n\n // Click on backdrop closes lightbox\n const handleBackdropClick = (e: MouseEvent) => {\n if (e.target === dialogRef) {\n close();\n }\n };\n\n // The browser cancels the dialog itself, as on the Android back gesture;\n // closing here still returns focus and tells the owner.\n const handleCancel = (e: Event) => {\n e.preventDefault();\n close();\n };\n\n // Registration and teardown both live in onMount: onCleanup also runs when an\n // SSR render is disposed, where `document` does not exist.\n onMount(() => {\n opener = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n openerRing = ringOnReturn(opener);\n // The native dialog would return focus with a ring of the browser's choosing.\n opener?.blur();\n dialogRef.showModal();\n document.addEventListener(\"keydown\", handleKeyDown);\n onCleanup(() => document.removeEventListener(\"keydown\", handleKeyDown));\n });\n\n return (\n <dialog\n ref={dialogRef}\n class=\"k2b-content-lightbox\"\n onMouseDown={handleBackdropClick}\n onCancel={handleCancel}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n aria-label={lightboxMessages().imageLightbox}\n >\n {/* Top bar */}\n <div class=\"k2b-content-lightbox__bar\">\n <div class=\"k2b-content-lightbox__meta\">\n <Show when={isMultiple()}>\n <span class=\"k2b-content-lightbox__counter k2b-overlay-surface\" aria-live=\"polite\">\n {index() + 1} / {props.images.length}\n </span>\n </Show>\n <Show when={current()?.alt}>\n <div class=\"k2b-content-lightbox__caption k2b-overlay-surface\">\n <div class=\"k2b-content-lightbox__caption-text\">{current()?.alt}</div>\n </div>\n </Show>\n </div>\n\n <div class=\"k2b-content-lightbox__actions\">\n <For each={current()?.actions ?? []}>\n {(action) => (\n <button\n type=\"button\"\n onClick={() => action.onClick()}\n class=\"k2b-content-lightbox__button k2b-overlay-surface\"\n aria-label={action.label}\n >\n <i class={action.icon} aria-hidden=\"true\" />\n <span class=\"k2b-content-lightbox__button-label\">{action.label}</span>\n </button>\n )}\n </For>\n <Show when={current()?.downloadUrl}>\n <a\n href={current()!.downloadUrl}\n download=\"\"\n class=\"k2b-content-lightbox__button k2b-overlay-surface\"\n aria-label={lightboxMessages().downloadImage}\n >\n <i class=\"ti ti-download\" aria-hidden=\"true\" />\n <span class=\"k2b-content-lightbox__button-label\">{messages().download}</span>\n </a>\n </Show>\n <button\n type=\"button\"\n onClick={close}\n class=\"k2b-content-lightbox__button k2b-overlay-surface\"\n aria-label={lightboxMessages().closeLightbox}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n <span class=\"k2b-content-lightbox__button-label\">{messages().close}</span>\n </button>\n </div>\n </div>\n\n <div class=\"k2b-content-lightbox__stage\">\n <Show when={current()}>\n {(image) => <img src={image().src} alt={image().alt ?? \"\"} class=\"k2b-content-lightbox__image\" draggable={false} />}\n </Show>\n </div>\n\n <Show when={isMultiple()}>\n <button\n type=\"button\"\n onClick={prev}\n class=\"k2b-content-lightbox__nav k2b-overlay-surface\"\n data-direction=\"previous\"\n aria-label={lightboxMessages().previousImage}\n >\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n onClick={next}\n class=\"k2b-content-lightbox__nav k2b-overlay-surface\"\n data-direction=\"next\"\n aria-label={lightboxMessages().nextImage}\n >\n <i class=\"ti ti-chevron-right\" aria-hidden=\"true\" />\n </button>\n </Show>\n\n <Show when={isMultiple() && props.images.length <= 10}>\n <div class=\"k2b-content-lightbox__dots k2b-overlay-surface\" role=\"group\" aria-label={lightboxMessages().imageNavigation}>\n <For each={props.images}>\n {(_, i) => (\n <button\n type=\"button\"\n onClick={() => setIndex(i())}\n class=\"k2b-content-lightbox__dot\"\n aria-current={index() === i() ? \"true\" : undefined}\n aria-label={lightboxMessages().goToImage({ index: i() + 1 })}\n />\n )}\n </For>\n </div>\n </Show>\n </dialog>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/Lightbox.tsx"],"sourcesContent":["import { createEffect, createSignal, For, onCleanup, onMount, Show } from \"solid-js\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { useLightboxMessages } from \"./lightbox-messages\";\nimport { ThumbnailStrip } from \"./ThumbnailStrip\";\n\n/** One more thing to do with the shown image, beside Download: a short label, its icon class, and what it does. */\nexport type LightboxAction = {\n label: string;\n icon: string;\n onClick: () => void;\n};\n\nexport type LightboxImage = {\n src: string;\n alt?: string;\n downloadUrl?: string;\n /** Actions for this image, shown before Download in the same style. */\n actions?: readonly LightboxAction[];\n /** A small version for the thumbnail strip, shown from four images on; without it the strip loads `src`. */\n thumbnail?: string;\n};\n\n/** From this many images the gallery shows a thumbnail strip instead of dots. */\nconst STRIP_FROM = 4;\n\ntype LightboxProps = {\n images: LightboxImage[];\n initialIndex?: number;\n onClose: () => void;\n};\n\n/**\n * Minimal, accessible lightbox using native <dialog>.\n * Supports keyboard navigation, touch swipe gestures, and screen readers.\n */\nexport default function Lightbox(props: LightboxProps) {\n const messages = useUiMessages();\n const lightboxMessages = useLightboxMessages();\n const clampIndex = (value: number, images = props.images): number =>\n images.length === 0 ? 0 : Math.max(0, Math.min(value, images.length - 1));\n const [index, setIndex] = createSignal(clampIndex(props.initialIndex ?? 0));\n let dialogRef!: HTMLDialogElement;\n let opener: HTMLElement | null = null;\n let openerRing = true;\n\n createEffect(\n (previous: { images: LightboxImage[]; initialIndex: number | undefined }) => {\n const images = props.images;\n const initialIndex = props.initialIndex;\n setIndex((currentIndex) => {\n if (initialIndex !== previous.initialIndex) return clampIndex(initialIndex ?? 0, images);\n const previousImage = previous.images[currentIndex];\n const retained = previousImage ? images.findIndex((image) => image === previousImage || image.src === previousImage.src) : -1;\n return retained >= 0 ? retained : clampIndex(currentIndex, images);\n });\n return { images, initialIndex };\n },\n { images: props.images, initialIndex: props.initialIndex },\n );\n\n // Touch gesture tracking\n let touchStartX = 0;\n let touchStartY = 0;\n const SWIPE_THRESHOLD = 50;\n\n const current = () => props.images[index()];\n const isMultiple = () => props.images.length > 1;\n const prev = () => {\n if (!isMultiple()) return;\n setIndex((i) => (i - 1 + props.images.length) % props.images.length);\n };\n const next = () => {\n if (!isMultiple()) return;\n setIndex((i) => (i + 1) % props.images.length);\n };\n\n const close = () => {\n dialogRef.close();\n returnFocus(opener, openerRing);\n props.onClose();\n };\n\n // A key belongs to the Lightbox while focus is inside it, or on the page with no other dialog open. A dialog opened\n // from one of its actions keeps its own keys: Escape closes that dialog, and arrows stay in its fields.\n const ownsKey = (target: EventTarget | null) =>\n target instanceof Node &&\n (dialogRef.contains(target) ||\n (target === document.body && Array.from(document.querySelectorAll(\"dialog[open]\")).every((dialog) => dialog === dialogRef)));\n\n // Keyboard navigation\n const handleKeyDown = (e: KeyboardEvent) => {\n // A part that handled the key itself, such as the thumbnail strip moving its focus, keeps it.\n if (e.defaultPrevented || !ownsKey(e.target)) return;\n switch (e.key) {\n case \"Escape\":\n // Handled here, so WebKit does not light the returned focus for this key.\n e.preventDefault();\n close();\n break;\n case \"ArrowLeft\":\n prev();\n break;\n case \"ArrowRight\":\n next();\n break;\n }\n };\n\n // Touch handlers for swipe gestures\n const handleTouchStart = (e: TouchEvent) => {\n const touch = e.touches[0];\n if (touch) {\n touchStartX = touch.clientX;\n touchStartY = touch.clientY;\n }\n };\n\n const handleTouchEnd = (e: TouchEvent) => {\n const touch = e.changedTouches[0];\n if (!touch) return;\n\n const deltaX = touch.clientX - touchStartX;\n const deltaY = touch.clientY - touchStartY;\n\n // Only trigger swipe if horizontal movement is dominant\n if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > SWIPE_THRESHOLD) {\n if (deltaX > 0) {\n prev();\n } else {\n next();\n }\n }\n };\n\n // Click on backdrop closes lightbox\n const handleBackdropClick = (e: MouseEvent) => {\n if (e.target === dialogRef) {\n close();\n }\n };\n\n // The browser cancels the dialog itself, as on the Android back gesture;\n // closing here still returns focus and tells the owner.\n const handleCancel = (e: Event) => {\n e.preventDefault();\n close();\n };\n\n // Registration and teardown both live in onMount: onCleanup also runs when an\n // SSR render is disposed, where `document` does not exist.\n onMount(() => {\n opener = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n openerRing = ringOnReturn(opener);\n // The native dialog would return focus with a ring of the browser's choosing.\n opener?.blur();\n dialogRef.showModal();\n document.addEventListener(\"keydown\", handleKeyDown);\n onCleanup(() => document.removeEventListener(\"keydown\", handleKeyDown));\n });\n\n return (\n <dialog\n ref={dialogRef}\n class=\"k2b-content-lightbox\"\n onMouseDown={handleBackdropClick}\n onCancel={handleCancel}\n onTouchStart={handleTouchStart}\n onTouchEnd={handleTouchEnd}\n aria-label={lightboxMessages().imageLightbox}\n >\n {/* Top bar */}\n <div class=\"k2b-content-lightbox__bar\">\n <div class=\"k2b-content-lightbox__meta\">\n <Show when={isMultiple()}>\n <span class=\"k2b-content-lightbox__counter k2b-overlay-surface\" aria-live=\"polite\">\n {index() + 1} / {props.images.length}\n </span>\n </Show>\n <Show when={current()?.alt}>\n <div class=\"k2b-content-lightbox__caption k2b-overlay-surface\">\n <div class=\"k2b-content-lightbox__caption-text\">{current()?.alt}</div>\n </div>\n </Show>\n </div>\n\n <div class=\"k2b-content-lightbox__actions\">\n <For each={current()?.actions ?? []}>\n {(action) => (\n <button\n type=\"button\"\n onClick={() => action.onClick()}\n class=\"k2b-content-lightbox__button k2b-overlay-surface\"\n aria-label={action.label}\n >\n <i class={action.icon} aria-hidden=\"true\" />\n <span class=\"k2b-content-lightbox__button-label\">{action.label}</span>\n </button>\n )}\n </For>\n <Show when={current()?.downloadUrl}>\n <a\n href={current()!.downloadUrl}\n download=\"\"\n class=\"k2b-content-lightbox__button k2b-overlay-surface\"\n aria-label={lightboxMessages().downloadImage}\n >\n <i class=\"ti ti-download\" aria-hidden=\"true\" />\n <span class=\"k2b-content-lightbox__button-label\">{messages().download}</span>\n </a>\n </Show>\n <button\n type=\"button\"\n onClick={close}\n class=\"k2b-content-lightbox__button k2b-overlay-surface\"\n aria-label={lightboxMessages().closeLightbox}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n <span class=\"k2b-content-lightbox__button-label\">{messages().close}</span>\n </button>\n </div>\n </div>\n\n <div class=\"k2b-content-lightbox__stage\">\n <Show when={current()}>\n {(image) => <img src={image().src} alt={image().alt ?? \"\"} class=\"k2b-content-lightbox__image\" draggable={false} />}\n </Show>\n </div>\n\n <Show when={isMultiple()}>\n <button\n type=\"button\"\n onClick={prev}\n class=\"k2b-content-lightbox__nav k2b-overlay-surface\"\n data-direction=\"previous\"\n aria-label={lightboxMessages().previousImage}\n >\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n onClick={next}\n class=\"k2b-content-lightbox__nav k2b-overlay-surface\"\n data-direction=\"next\"\n aria-label={lightboxMessages().nextImage}\n >\n <i class=\"ti ti-chevron-right\" aria-hidden=\"true\" />\n </button>\n </Show>\n\n <Show when={props.images.length >= STRIP_FROM}>\n <ThumbnailStrip\n class=\"k2b-content-lightbox__strip k2b-overlay-surface\"\n label={lightboxMessages().imageNavigation}\n items={props.images.map((image, i) => ({\n id: String(i),\n name: image.alt || lightboxMessages().goToImage({ index: i + 1 }),\n thumbnail: image.thumbnail ?? image.src,\n }))}\n currentItem={String(index())}\n onSelectItem={(id) => setIndex(Number(id))}\n />\n </Show>\n\n <Show when={isMultiple() && props.images.length < STRIP_FROM}>\n <div class=\"k2b-content-lightbox__dots k2b-overlay-surface\" role=\"group\" aria-label={lightboxMessages().imageNavigation}>\n <For each={props.images}>\n {(_, i) => (\n <button\n type=\"button\"\n onClick={() => setIndex(i())}\n class=\"k2b-content-lightbox__dot\"\n aria-current={index() === i() ? \"true\" : undefined}\n aria-label={lightboxMessages().goToImage({ index: i() + 1 })}\n />\n )}\n </For>\n </div>\n </Show>\n </dialog>\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { ssr as _$ssr } from "solid-js/web";
|
|
2
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
|
+
import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
|
|
4
|
+
import { escape as _$escape } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = ["<nav class=\"", "\"", "><ul data-scroll-fade-mode=\"both\" data-scroll-fade-axis=\"horizontal\">", "", "</ul></nav>"],
|
|
6
|
+
_tmpl$2 = "<span class=\"k2b-thumbnail-strip__dirty\" aria-hidden=\"true\"></span>",
|
|
7
|
+
_tmpl$3 = ["<li><button type=\"button\" class=\"k2b-thumbnail-strip__thumb\"", " aria-label=\"", "\"", ">", "", "</button></li>"],
|
|
8
|
+
_tmpl$4 = ["<img", " alt loading=\"lazy\" decoding=\"async\" draggable=\"false\">"],
|
|
9
|
+
_tmpl$5 = "<i class=\"ti ti-plus\" aria-hidden=\"true\"></i>",
|
|
10
|
+
_tmpl$6 = ["<li>", "</li>"];
|
|
11
|
+
import { createEffect, For, on, Show } from "solid-js";
|
|
12
|
+
import { IconButton } from "../actions/Button";
|
|
13
|
+
import { createScrollFade } from "../layout/scroll-fade";
|
|
14
|
+
import { useThumbnailStripMessages } from "./thumbnail-strip-messages";
|
|
15
|
+
|
|
16
|
+
/** One image in a `ThumbnailStrip`. */
|
|
17
|
+
|
|
18
|
+
/** Room an item keeps from a fading edge when keyboard focus scrolls it into view. */
|
|
19
|
+
const EDGE = 48;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A row of image thumbnails, 44 px high, that scrolls sideways and fades softly only on the side where more images
|
|
23
|
+
* follow. The current image is ringed and is the strip's one tab stop; the arrow keys, Home, and End move focus between
|
|
24
|
+
* images, and Enter or a click shows one. A dot marks unsaved edits. The host decides where the strip sits, also on a
|
|
25
|
+
* phone, and whether it floats over a picture.
|
|
26
|
+
*/
|
|
27
|
+
export function ThumbnailStrip(props) {
|
|
28
|
+
const messages = useThumbnailStripMessages();
|
|
29
|
+
let list;
|
|
30
|
+
createScrollFade(() => list, () => true);
|
|
31
|
+
|
|
32
|
+
// The current image scrolls into the middle whenever it or the list changes.
|
|
33
|
+
createEffect(on(() => [props.currentItem, props.items.length], () => queueMicrotask(() => {
|
|
34
|
+
const current = list?.querySelector('[aria-current="true"]');
|
|
35
|
+
if (!list || !current) return;
|
|
36
|
+
list.style.scrollBehavior = "auto";
|
|
37
|
+
list.scrollLeft = current.offsetLeft - (list.clientWidth - current.offsetWidth) / 2;
|
|
38
|
+
list.style.scrollBehavior = "";
|
|
39
|
+
})));
|
|
40
|
+
|
|
41
|
+
// A native listener, so a host that handles arrow keys itself, such as a lightbox, does not also see them.
|
|
42
|
+
const keys = event => {
|
|
43
|
+
// The "+" tile takes part in the arrow keys, so the keyboard reaches it without a tab stop of its own.
|
|
44
|
+
const thumbs = [...(list?.querySelectorAll(".k2b-thumbnail-strip__thumb, .k2b-thumbnail-strip__add") ?? [])];
|
|
45
|
+
const at = thumbs.findIndex(thumb => thumb === document.activeElement);
|
|
46
|
+
if (at < 0 || !list) return;
|
|
47
|
+
const to = {
|
|
48
|
+
ArrowRight: Math.min(thumbs.length - 1, at + 1),
|
|
49
|
+
ArrowLeft: Math.max(0, at - 1),
|
|
50
|
+
Home: 0,
|
|
51
|
+
End: thumbs.length - 1
|
|
52
|
+
}[event.key];
|
|
53
|
+
if (to === undefined) return;
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
thumbs.forEach((thumb, index) => {
|
|
57
|
+
thumb.tabIndex = index === to ? 0 : -1;
|
|
58
|
+
});
|
|
59
|
+
const target = thumbs[to];
|
|
60
|
+
if (!target) return;
|
|
61
|
+
target.focus({
|
|
62
|
+
preventScroll: true
|
|
63
|
+
});
|
|
64
|
+
if (target.offsetLeft < list.scrollLeft + EDGE) list.scrollLeft = target.offsetLeft - EDGE;else if (target.offsetLeft + target.offsetWidth > list.scrollLeft + list.clientWidth - EDGE) list.scrollLeft = target.offsetLeft + target.offsetWidth - list.clientWidth + EDGE;
|
|
65
|
+
};
|
|
66
|
+
return _$ssr(_tmpl$, `k2b-thumbnail-strip ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("aria-label", _$escape(props.label, true), false), _$escape(_$createComponent(For, {
|
|
67
|
+
get each() {
|
|
68
|
+
return props.items;
|
|
69
|
+
},
|
|
70
|
+
children: item => {
|
|
71
|
+
const current = () => item.id === props.currentItem;
|
|
72
|
+
return _$ssr(_tmpl$3, _$ssrAttribute("aria-current", _$escape(current(), true), false) + _$ssrAttribute("tabindex", current() ? 0 : -1, false), `${_$escape(item.name, true)}${current() ? `, ${_$escape(messages().thumbnailCurrent, true)}` : ""}${item.dirty ? `, ${_$escape(messages().thumbnailUnsaved, true)}` : ""}`, _$ssrAttribute("title", _$escape(item.name, true), false), (() => {
|
|
73
|
+
const thumbnail = item.thumbnail;
|
|
74
|
+
if (typeof thumbnail === "function") return thumbnail();
|
|
75
|
+
return thumbnail ? _$ssr(_tmpl$4, _$ssrAttribute("src", _$escape(thumbnail, true), false)) : _$escape(null);
|
|
76
|
+
})(), _$escape(_$createComponent(Show, {
|
|
77
|
+
get when() {
|
|
78
|
+
return item.dirty;
|
|
79
|
+
},
|
|
80
|
+
get children() {
|
|
81
|
+
return _$ssr(_tmpl$2);
|
|
82
|
+
}
|
|
83
|
+
})));
|
|
84
|
+
}
|
|
85
|
+
})), _$escape(_$createComponent(Show, {
|
|
86
|
+
get when() {
|
|
87
|
+
return props.onAddItems;
|
|
88
|
+
},
|
|
89
|
+
children: add => _$ssr(_tmpl$6, _$escape(_$createComponent(IconButton, {
|
|
90
|
+
"class": "k2b-thumbnail-strip__add",
|
|
91
|
+
size: "sm",
|
|
92
|
+
tabindex: "-1",
|
|
93
|
+
get label() {
|
|
94
|
+
return messages().thumbnailAdd;
|
|
95
|
+
},
|
|
96
|
+
onClick: () => add()(),
|
|
97
|
+
get children() {
|
|
98
|
+
return _$ssr(_tmpl$5);
|
|
99
|
+
}
|
|
100
|
+
})))
|
|
101
|
+
})));
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=ThumbnailStrip.js.map
|