@sportsdataverse/sdvtables 0.1.0 → 0.2.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/README.md +70 -112
- package/data/table_themes.json +12136 -0
- package/data/table_themes.json.sha256 +1 -0
- package/dist/aggrid.d.ts +104 -0
- package/dist/aggrid.js +230 -0
- package/dist/aggrid.js.map +1 -0
- package/dist/chunk-3TJR7TKS.js +223 -0
- package/dist/chunk-3TJR7TKS.js.map +1 -0
- package/dist/{chunk-UCRLJGDL.js → chunk-R375P3MN.js} +963 -276
- package/dist/chunk-R375P3MN.js.map +1 -0
- package/dist/chunk-UTOVFIFT.js +15176 -0
- package/dist/chunk-UTOVFIFT.js.map +1 -0
- package/dist/{chunk-U6W6MWKW.js → chunk-VLF2S6VW.js} +7 -5
- package/dist/chunk-VLF2S6VW.js.map +1 -0
- package/dist/chunk-WBTFIGYK.js +189 -0
- package/dist/chunk-WBTFIGYK.js.map +1 -0
- package/dist/{engine-CkfxYXAL.d.ts → engine-BFIPJUlC.d.ts} +1 -1
- package/dist/export.d.ts +1 -1
- package/dist/export.js +4 -3
- package/dist/export.js.map +1 -1
- package/dist/html.d.ts +8 -5
- package/dist/html.js +4 -3
- package/dist/index.d.ts +121 -8
- package/dist/index.js +51 -3
- package/dist/index.js.map +1 -1
- package/dist/mui.d.ts +134 -0
- package/dist/mui.js +193 -0
- package/dist/mui.js.map +1 -0
- package/dist/react.d.ts +2 -2
- package/dist/react.js +3 -2
- package/dist/react.js.map +1 -1
- package/dist/spec-A88vJX5A.d.ts +748 -0
- package/dist/tanstack-table.d.ts +113 -0
- package/dist/tanstack-table.js +98 -0
- package/dist/tanstack-table.js.map +1 -0
- package/dist/{tokens-CpYFsFtf.d.ts → tokens-CHwBt9gs.d.ts} +1 -1
- package/package.json +40 -3
- package/dist/chunk-4VKYHOHL.js +0 -2081
- package/dist/chunk-4VKYHOHL.js.map +0 -1
- package/dist/chunk-U6W6MWKW.js.map +0 -1
- package/dist/chunk-UCRLJGDL.js.map +0 -1
- package/dist/spec-BEhLDtj_.d.ts +0 -430
package/dist/mui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mui.ts"],"names":["t"],"mappings":"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","file":"mui.js","sourcesContent":["/**\n * The MUI X Data Grid adapter (`@mui/x-data-grid` 9, the MIT community package only): an sdvtables spec as a\n * `<DataGrid>`'s props. Columns keep sdvtables' number formats, alignment and px widths; logo, wordmark and headshot\n * columns draw their images through `renderCell`; team-coloured rows and cells take sdvplot's team palette with\n * black or white text by contrast; the theme's tokens (fonts, colours, density, stripes) become the grid's `sx`.\n * Pure: MUI is never imported (the props here are structural, read from `@mui/x-data-grid` 9.15 and checked against\n * its own types); React's `createElement` builds the images, so the grid also renders on the server.\n */\nimport {\n type IdSystem,\n type League,\n type SeasonInput,\n type Which,\n hex6,\n mix,\n onColor,\n} from \"@sportsdataverse/sdvplot\";\nimport { teamColorPalette } from \"@sportsdataverse/sdvplot/mui\";\nimport { Fragment, type ReactElement, createElement } from \"react\";\nimport {\n type Fill,\n type GridName,\n cell,\n checkHeight,\n formatterFor,\n headshotUrls,\n logoMarks,\n missingLast,\n opaque,\n pxWidth,\n rankParts,\n rowIds,\n scaleNotes,\n teamColorOf,\n teamRowFills,\n tint,\n unmapped,\n value,\n} from \"./_grid.js\";\nimport { NUMERIC_KINDS } from \"./engine.js\";\nimport { toNumber } from \"./format.js\";\nimport { alignOf, labelOf } from \"./html/parts.js\";\nimport type { Align, ColumnSpec, TableSpec } from \"./spec.js\";\nimport { teamNameSync } from \"./team-name.js\";\nimport { resolveTheme } from \"./themes/index.js\";\nimport type { ThemeTokens } from \"./themes/tokens.js\";\n\n/** What MUI hands a column's `renderCell` and `cellClassName`: the subset read here. */\nexport interface GridCellParamsLike<Row> {\n /** The row the cell is in. */\n readonly row: Row;\n /** The cell's value: `row[field]`. */\n readonly value?: unknown;\n}\n/** What MUI hands `getRowClassName`: the subset read here. */\nexport interface GridRowClassParamsLike<Row> {\n /** The row. */\n readonly row: Row;\n /** The row's index on the current page, from 0: odd rows take the theme's stripe. */\n readonly indexRelativeToCurrentPage: number;\n}\n/** One MUI `GridColDef`: the fields this adapter sets. */\nexport interface SdvGridColDef<Row> {\n /** The row key the column reads. */\n field: string;\n /** The column's label, as the HTML table writes it. */\n headerName: string;\n /** The spec's `subheader`, shown as the header's tooltip. */\n description?: string;\n /** \"number\" for sdvtables' numeric kinds (MUI then sorts and filters as numbers). */\n type?: \"string\" | \"number\";\n align: Align;\n headerAlign: Align;\n /** The spec's px width as a number; other CSS widths are left to MUI (with one warning). */\n width?: number;\n sortable?: boolean;\n filterable?: boolean;\n /** \"flex\" for image cells, so MUI centres them vertically. */\n display?: \"text\" | \"flex\";\n /** Numeric kinds: the cell's number, `null` for a blank or unparseable value (so MUI never reads \"\" as 0). */\n valueGetter?: (value: never) => number | null;\n /** The cell's text through sdvtables' number formats. */\n valueFormatter?: (value: never) => string;\n /** sdvtables' own sort for the column (its `compare`, else by kind), missing values last in both directions. */\n getSortComparator?: (\n direction: \"asc\" | \"desc\" | null | undefined,\n ) => ((a: unknown, b: unknown) => number) | undefined;\n /** A logo, wordmark or headshot image, or a rank with a superscript suffix. */\n renderCell?: (params: GridCellParamsLike<Row>) => ReactElement | string;\n /** A team colour class (`teamColorBg`, `teamColorBar`) styled by the grid's `sx`. */\n cellClassName?: (params: GridCellParamsLike<Row>) => string;\n}\n/** A nested `sx` style object: selectors map to CSS properties (and CSS variables). */\nexport interface GridSx {\n readonly [selectorOrProperty: string]: string | number | GridSx;\n}\n/** What `dataGridProps` returns: spread it onto `<DataGrid rows={rows} {...props} />`. */\nexport interface SdvDataGridProps<Row> {\n columns: SdvGridColDef<Row>[];\n /** `String(row[spec.rowKey])`, else the row's index in `rows`; checked unique and not blank when built. */\n getRowId: (row: Row) => string;\n /** The row's team colour class (`teamRows`), else the theme's stripe on odd rows. */\n getRowClassName: (params: GridRowClassParamsLike<Row>) => string;\n /** The theme as MUI X Data Grid styles, plus the team colour classes. */\n sx: GridSx;\n /** The theme's density as MUI's: compact is \"compact\", comfortable is \"standard\" and social is \"comfortable\". */\n density: \"compact\" | \"standard\" | \"comfortable\";\n /** MUI's base row height (MUI multiplies it by the density's factor), tall enough for the tallest image. */\n rowHeight: number;\n}\n/** `dataGridProps` options. */\nexport interface DataGridPropsOptions<Row> {\n /**\n * Fill each row with its team's colour, from the row's `key` value (an abbreviation, a name or a numeric id).\n * The colours are sdvplot's team palette for the theme's background (`teamColorPalette` from\n * `@sportsdataverse/sdvplot/mui`: 3:1 against it, distinct between teams) laid over it at `alpha` (default 0.4),\n * with black or white text, whichever reads better on the fill. A row whose team is not found keeps the theme.\n */\n teamRows?: {\n key: keyof Row & string;\n league: League;\n /** \"primary\" (default) or \"secondary\". */\n which?: Which;\n /** The fill's opacity over the theme's background, 0 to 1. Default 0.4 (as the `teamColorBg` column). */\n alpha?: number;\n season?: SeasonInput;\n idSystem?: IdSystem;\n };\n}\n\n// MUI's base row height and its density factors (@mui/x-data-grid 9.15 densitySelector)\nconst MUI_ROW_HEIGHT = 52;\nconst DENSITY = { compact: \"compact\", comfortable: \"standard\", social: \"comfortable\" } as const;\nconst FACTOR = { compact: 0.7, standard: 1, comfortable: 1.3 } as const;\nconst MUI: GridName = {\n fn: \"dataGridProps\",\n ns: \"mui\",\n grid: \"MUI X Data Grid\",\n short: \"MUI\",\n built: \"props\",\n};\nconst fillClass = (fill: string): string => `sdvt-fill-${fill.slice(1)}`;\n\nfunction image(src: string, alt: string, height: number, id: string, kind: string): ReactElement {\n return createElement(\"img\", {\n src,\n alt,\n height,\n style: { height: `${height}px`, width: \"auto\" },\n \"data-sdv-id\": id,\n \"data-sdv-kind\": kind,\n });\n}\n/**\n * An sdvtables spec as MUI X Data Grid props: `<DataGrid rows={rows} {...dataGridProps(spec, rows)} />`.\n *\n * - **Columns**: one `GridColDef` per spec column, with the HTML table's label, alignment and px `width`; numbers\n * (`num`, `int`, `pct`, `rank`) keep sdvtables' formats and sort as numbers.\n * - **Images**: `logo`, `wordmark` and `headshot` columns draw `<img>` cells `height` px tall. A team or player with no\n * image keeps its text, with one warning. Team values may be abbreviations, names or numeric ids.\n * - **Team colours**: `teamColorBg` and `teamColorBar` columns, and whole rows with `teamRows`, take sdvplot's team\n * palette for the theme's background, with black or white text by contrast.\n * - **Theme**: the theme's fonts, colours, header style, rules and stripes as the grid's `sx`, its density as MUI's.\n *\n * Other column kinds (pills, bars, sparklines...) show their plain value, with one warning per kind. Synchronous: call\n * `await prepare(spec)` (`@sportsdataverse/sdvtables/html`) first. Images and colours are worked out once, from\n * `rows`: build the props again (or `useMemo` on `rows`) when the rows change. MIT `@mui/x-data-grid` only: nothing\n * here needs the Pro or Premium packages.\n *\n * @example\n * ```tsx\n * import { DataGrid } from \"@mui/x-data-grid\";\n * import { defineTable } from \"@sportsdataverse/sdvtables\";\n * import { prepare } from \"@sportsdataverse/sdvtables/html\";\n * import { dataGridProps } from \"@sportsdataverse/sdvtables/mui\";\n *\n * // 2024 regular season, nflverse games\n * const rows = [\n * { team: \"KC\", wins: 15, pf: 385, pa: 326 },\n * { team: \"BUF\", wins: 13, pf: 525, pa: 368 },\n * { team: \"LAC\", wins: 11, pf: 402, pa: 301 },\n * ];\n * const spec = defineTable<(typeof rows)[number]>()\n * .columns((c) => [c.logo(\"team\", { league: \"nfl\", height: 28 }), c.int(\"wins\"), c.int(\"pf\"), c.int(\"pa\")])\n * .theme(\"sdv\")\n * .rowKey(\"team\")\n * .build();\n * await prepare(spec);\n * <DataGrid rows={rows} {...dataGridProps(spec, rows, { teamRows: { key: \"team\", league: \"nfl\" } })} />;\n * ```\n */\nexport function dataGridProps<Row>(\n spec: TableSpec<Row>,\n rows: readonly Row[],\n o: DataGridPropsOptions<Row> = {},\n): SdvDataGridProps<Row> {\n const theme = resolveTheme(spec.theme);\n const t = theme.tokens;\n const bg = opaque(t);\n const fills = new Map<string, Fill>(); // class -> colours, written into sx\n const bars = new Map<string, { width: number; color: string }>();\n let tallest = 0;\n const { scaled, labelSuffix } = scaleNotes(spec);\n\n const columns = spec.columns.map((col): SdvGridColDef<Row> => {\n const align = alignOf(col);\n const sortBy = missingLast(col, rows);\n const def: SdvGridColDef<Row> = {\n field: col.key,\n headerName: labelOf(col) + (labelSuffix.get(col.key) ?? \"\"),\n getSortComparator: (dir) => (dir === \"asc\" || dir === \"desc\" ? sortBy(dir) : undefined),\n align,\n headerAlign: align,\n ...(col.subheader === undefined ? {} : { description: col.subheader }),\n ...(col.sortable === undefined ? {} : { sortable: col.sortable }),\n ...(col.filterable === undefined ? {} : { filterable: col.filterable }),\n ...(NUMERIC_KINDS.has(col.kind)\n ? { type: \"number\" as const, valueGetter: (v: never) => toNumber(v) }\n : {}),\n };\n const width = pxWidth(col, MUI);\n if (width !== undefined) def.width = width;\n const format = formatterFor(col, scaled);\n return { ...def, ...(format === undefined ? {} : { valueFormatter: format }), ...kindProps(col) };\n });\n\n function kindProps(col: ColumnSpec<Row>): Partial<SdvGridColDef<Row>> {\n switch (col.kind) {\n case \"text\":\n case \"num\":\n case \"int\":\n case \"pct\":\n return {};\n case \"rank\":\n return col.superscript\n ? {\n // the HTML table's superscript suffix: 1<sup>st</sup>\n renderCell: ({ value: v }: GridCellParamsLike<Row>) => {\n const r = rankParts(v);\n if (r === null) return \"\";\n const sup = createElement(\"sup\", { style: { fontSize: col.suffixSize } }, r.suffix);\n return createElement(Fragment, null, r.num, sup);\n },\n }\n : {};\n case \"logo\":\n case \"wordmark\": {\n const h = checkHeight(col.height, col.kind);\n tallest = Math.max(tallest, h);\n const marks = logoMarks(col, rows);\n const includeName = col.kind === \"logo\" && col.includeName;\n const kind = col.kind;\n return {\n display: \"flex\",\n renderCell: ({ value: raw }) => {\n const text = cell(raw);\n const m = marks.get(text);\n if (m === undefined) return text; // blank, unknown team or no image: the text, as the HTML table keeps it\n const img = image(m.url, teamNameSync(col.league, m.id) ?? text, h, m.id, kind);\n return includeName\n ? createElement(\n \"span\",\n { style: { display: \"inline-flex\", alignItems: \"center\", gap: \"0.4em\" } },\n img,\n text,\n )\n : img;\n },\n };\n }\n case \"headshot\": {\n const h = checkHeight(col.height, \"headshot\");\n tallest = Math.max(tallest, h);\n const urls = headshotUrls(col, rows, MUI);\n return {\n display: \"flex\",\n renderCell: ({ value: raw }) => {\n const text = cell(raw);\n const url = urls.get(text);\n // decorative: the spec gives a headshot no name, and the player's name sits in its row\n return url === undefined ? text : image(url, \"\", h, text, \"headshot\");\n },\n };\n }\n case \"teamColorBg\":\n case \"teamColorBar\": {\n const colorOf = teamColorOf(col, rows, bg, teamColorPalette);\n const classOf = (raw: unknown): string => {\n const color = colorOf(raw);\n if (col.kind === \"teamColorBar\") {\n const c = hex6(color, { dropAlpha: true });\n const name = `sdvt-bar-${col.barWidth}-${c.slice(1)}`;\n bars.set(name, { width: col.barWidth, color: c });\n return name;\n }\n const f = tint(color, col.alpha, bg);\n fills.set(fillClass(f.fill), f);\n return fillClass(f.fill);\n };\n // ponytail: every row's class is worked out now, so the sx below already holds each one's rule\n for (const r of rows) classOf(value(r, col.key));\n return { cellClassName: ({ value: raw }) => classOf(raw) };\n }\n default:\n unmapped(col.kind, MUI);\n return {};\n }\n }\n\n // team rows: each row's class by its team's fill\n const rowFill = new Map<string, string>();\n if (o.teamRows)\n for (const [v, f] of teamRowFills(rows, o.teamRows, bg, teamColorPalette)) {\n fills.set(fillClass(f.fill), f);\n rowFill.set(v, fillClass(f.fill));\n }\n const striped = t.stripe !== \"transparent\";\n const getRowClassName = ({ row, indexRelativeToCurrentPage }: GridRowClassParamsLike<Row>): string => {\n const team = o.teamRows === undefined ? undefined : rowFill.get(cell(value(row, o.teamRows.key)));\n return team ?? (striped && indexRelativeToCurrentPage % 2 === 1 ? \"sdvt-stripe\" : \"\");\n };\n\n const getRowId = rowIds(rows, spec.rowKey, MUI);\n const density = DENSITY[spec.theme.density];\n const rowHeight = Math.max(MUI_ROW_HEIGHT, Math.ceil((tallest + 8) / FACTOR[density]));\n return { columns, getRowId, getRowClassName, sx: themeSx(t, fills, bars), density, rowHeight };\n}\n\n/** The theme's tokens as MUI X Data Grid styles: its CSS variables (on `&&`, so they beat MUI's own) and header rules. */\nfunction themeSx(\n t: ThemeTokens,\n fills: ReadonlyMap<string, { fill: string; ink: string }>,\n bars: ReadonlyMap<string, { width: number; color: string }>,\n): GridSx {\n const set = (v: string): boolean => v !== \"transparent\" && v !== \"inherit\" && v !== \"none\";\n const bg = set(t.bg) ? t.bg : undefined;\n const head = set(t.labelBg) ? t.labelBg : bg;\n const vars: Record<string, string> = {\n \"--DataGrid-t-color-foreground-base\": t.text,\n \"--DataGrid-t-color-foreground-muted\": t.muted,\n \"--DataGrid-t-color-border-base\": t.rule,\n \"--DataGrid-t-typography-font-family-base\": t.fontBody,\n \"--DataGrid-t-typography-font-body\": `${t.bodyWeight} ${t.bodySize} ${t.fontBody}`,\n ...(bg === undefined\n ? {}\n : { \"--DataGrid-t-color-background-base\": bg, \"--DataGrid-t-cell-background-pinned\": bg }),\n ...(head === undefined ? {} : { \"--DataGrid-t-header-background-base\": head }),\n };\n const sx: Record<string, GridSx> = {\n \"&&\": vars,\n // MUI's material pieces (pager, icon buttons) read the MUI theme, not the grid's variables: give them the ink\n \"& .MuiTablePagination-root, & .MuiIconButton-root\": { color: \"inherit\" },\n \"& .MuiDataGrid-columnHeaderTitle\": {\n fontFamily: t.fontLabel,\n fontWeight: t.labelWeight,\n fontSize: t.labelSize,\n fontStyle: t.labelStyle,\n textTransform: t.labelTransform,\n letterSpacing: t.labelTracking,\n },\n ...(set(t.labelColor) ? { \"& .MuiDataGrid-columnHeader\": { color: t.labelColor } } : {}),\n ...(t.stripe === \"transparent\"\n ? {}\n : { \"& .MuiDataGrid-row.sdvt-stripe\": { backgroundColor: t.stripe } }),\n };\n for (const [name, f] of fills) {\n sx[`& .${name}`] = { backgroundColor: f.fill, color: f.ink };\n // MUI's row :hover and .Mui-selected rules outrank the class above: keep a shade of the fill, its ink recomputed\n const shade = (t: number): GridSx => {\n const c = mix(f.fill, f.ink, t);\n return { backgroundColor: c, color: onColor(c) };\n };\n sx[`& .MuiDataGrid-row.${name}:hover`] = shade(0.06);\n sx[`& .MuiDataGrid-row.${name}.Mui-selected`] = shade(0.1);\n sx[`& .MuiDataGrid-row.${name}.Mui-selected:hover`] = shade(0.14);\n }\n for (const [name, b] of bars)\n sx[`& .MuiDataGrid-cell.${name}`] = { borderLeft: `${b.width}px solid ${b.color}` };\n return sx;\n}\n"]}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
|
-
import { S as Sort, a as Table, e as TableOptions, f as TableSnapshot } from './engine-
|
|
3
|
-
import { T as TableSpec } from './spec-
|
|
2
|
+
import { S as Sort, a as Table, e as TableOptions, f as TableSnapshot } from './engine-BFIPJUlC.js';
|
|
3
|
+
import { T as TableSpec } from './spec-A88vJX5A.js';
|
|
4
4
|
import '@sportsdataverse/sdvplot';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/react.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { SR_ONLY,
|
|
3
|
-
import {
|
|
2
|
+
import { SR_ONLY, applyHover, captureFocus, tableRenderOptions, pagerLabel, handleKeydown, handleHover, handleClick, filterInputs, handleInput } from './chunk-3TJR7TKS.js';
|
|
3
|
+
import { renderParts, tableHTML } from './chunk-R375P3MN.js';
|
|
4
|
+
import { createTable } from './chunk-UTOVFIFT.js';
|
|
4
5
|
import { useSyncExternalStore, createElement, useRef, useCallback, useState, useEffect, useLayoutEffect, Fragment } from 'react';
|
|
5
6
|
|
|
6
7
|
function useOwnedTable(spec, rows, options) {
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/index.tsx"],"names":[],"mappings":";;;;;AAiCA,SAAS,aAAA,CAAmB,IAAA,EAAsB,IAAA,EAAsB,OAAA,EAAmC;AAGzG,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAC/B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,WAAA,CAAY,IAAA,EAAM,IAAA,EAAM,OAAO,GAAE,CAAE,CAAA;AACzF,EAAA,IAAI,QAAQ,IAAA,CAAK,KAAA;AACjB,EAAA,IAAI,IAAA,CAAK,QAAQ,GAAA,EAAK;AACpB,IAAA,KAAA,GAAQ,WAAA,CAAY,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AACvC,IAAA,OAAA,CAAQ,EAAE,GAAA,EAAK,KAAA,EAAO,CAAA;AAAA,EACxB;AAEA,EAAA,kBAAA,CAAmB,MAAM;AACvB,IAAA,IAAI,KAAA,CAAM,OAAA,KAAY,IAAA,EAAM,KAAA,CAAM,QAAQ,IAAI,CAAA;AAAA,EAChD,CAAA,EAAG,CAAC,KAAA,EAAO,IAAI,CAAC,CAAA;AAChB,EAAA,OAAO,KAAA;AACT;AAOO,SAAS,QAAA,CACd,IAAA,EACA,IAAA,EACA,OAAA,GAAwB,EAAC,EAC4B;AACrD,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAC/C,EAAA,MAAM,WAAW,oBAAA,CAAqB,KAAA,CAAM,WAAW,KAAA,CAAM,WAAA,EAAa,MAAM,WAAW,CAAA;AAC3F,EAAA,OAAO,EAAE,OAAO,QAAA,EAAS;AAC3B;AA4CA,SAAS,aAAa,CAAA,EAA0C;AAC9D,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAA,CAAE,YAAA,CAAa,KAAA,IAAS,EAAA;AAAA,IACnC,EAAA,EAAI,CAAA,CAAE,YAAA,CAAa,EAAA,IAAM,EAAA;AAAA,IACzB,iBAAA,EAAmB,CAAA,CAAE,YAAA,CAAa,iBAAiB,CAAA,IAAK,EAAA;AAAA,IACxD,mBAAA,EAAqB,CAAA,CAAE,YAAA,CAAa,mBAAmB,CAAA,IAAK;AAAA,GAC9D;AACF;AAEA,IAAM,GAAA,GAAM,CAAC,IAAA,MAAsC,EAAE,QAAQ,IAAA,EAAK,CAAA;AAElE,IAAM,WAAW,MAAA,CAAO,WAAA;AAAA,EACtB,QAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM;AAC5B,IAAA,MAAM,CAAC,IAAI,EAAA,EAAI,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,MAAM,GAAG,CAAA;AACpC,IAAA,OAAO,CAAC,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAA,EAAG,EAAA,KAAe,EAAA,CAAG,WAAA,EAAa,CAAA,EAAG,CAAC,CAAA;AAAA,EACrE,CAAC;AACH,CAAA;AAEA,IAAM,kBAAA,GAAqB,OAAO,QAAA,KAAa,WAAA,GAAc,SAAA,GAAY,eAAA;AAGzE,SAAS,SAAA,CACP,KACA,EAAA,EACA,KAAA,EACA,KACA,IAAA,EACA,KAAA,EACA,QAAA,EACA,WAAA,GAAsB,KAAA,EACR;AACd,EAAA,OAAO,aAAA;AAAA,IACL,QAAA;AAAA,IACA,EAAE,GAAA,EAAI;AAAA,IACN,aAAA,CAAc,SAAS,EAAE,OAAA,EAAS,IAAI,KAAA,EAAO,QAAA,IAAY,KAAK,CAAA;AAAA,IAC9D,aAAA,CAAc,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,EAAA,EAAI,SAAA,EAAW,GAAA,EAAK,GAAG,IAAA,EAAM,WAAA,EAAa,KAAA,EAAO,UAAU;AAAA,GACtG;AACF;AAiBO,SAAS,SAAc,KAAA,EAAyC;AACrE,EAAA,MAAM,EAAE,WAAA,GAAc,KAAA,EAAO,GAAA,EAAI,GAAI,KAAA;AACrC,EAAA,IAAI,MAAM,KAAA,KAAU,MAAA;AAClB,IAAA,OAAO,aAAA,CAAc,WAAgB,EAAE,KAAA,EAAO,MAAM,KAAA,EAAO,WAAA,EAAa,KAAK,CAAA;AAC/E,EAAA,IAAI,WAAA,EAAa,OAAO,aAAA,CAAc,UAAA,EAAiB,KAAK,CAAA;AAC5D,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,MAAM,IAAA,EAAM,EAAE,KAAA,EAAO,KAAA,EAAO,GAAI,GAAA,KAAQ,MAAA,IAAa,EAAE,GAAA,IAAQ,CAAA;AACjG,EAAA,OAAO,YAAY,CAAC,CAAA;AACtB;AAGA,SAAS,YAAY,CAAA,EAAgC;AACnD,EAAA,MAAM,KAAA,GAAQ,CAAA,EAAG,CAAA,CAAE,KAAA,GAAQ,CAAA,OAAA,EAAU,CAAA,CAAE,KAAK,CAAA,QAAA,CAAA,GAAa,EAAE,CAAA,EAAG,SAAA,CAAU,CAAC,CAAC,CAAA,CAAA;AAC1E,EAAA,OAAO,aAAA,CAAc,KAAA,EAAO,EAAE,GAAG,YAAA,CAAa,CAAC,CAAA,EAAG,uBAAA,EAAyB,GAAA,CAAI,KAAK,CAAA,EAAG,CAAA;AACzF;AAGA,SAAS,WAAgB,EAAE,IAAA,EAAM,MAAM,QAAA,EAAU,IAAA,EAAM,KAAI,EAAwC;AACjG,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM;AAAA,IACtC,GAAI,QAAA,KAAa,MAAA,IAAa,EAAE,QAAA,EAAS;AAAA,IACzC,GAAI,IAAA,KAAS,MAAA,IAAa,EAAE,IAAA;AAAK,GAClC,CAAA;AACD,EAAA,OAAO,cAAc,SAAA,EAAgB,EAAE,OAAO,WAAA,EAAa,IAAA,EAAM,KAAK,CAAA;AACxE;AAEA,SAAS,SAAA,CAAe;AAAA,EACtB,KAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,EAIiB;AACf,EAAA,MAAM,GAAA,GAAM,OAAuB,IAAI,CAAA;AACvC,EAAA,MAAM,OAAA,GAAU,OAA4B,IAAI,CAAA;AAGhD,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,QAAA,KACC,KAAA,CAAM,SAAA,CAAU,CAAC,CAAA,KAAM;AACrB,MAAA,IAAI,CAAA,CAAE,SAAS,OAAA,EAAS;AACtB,QAAA,IAAI,IAAI,OAAA,EAAS,UAAA,CAAW,IAAI,OAAA,EAAS,KAAA,EAAO,EAAE,EAAE,CAAA;AAAA,MACtD,CAAA,MAAA,IAAW,OAAA,CAAQ,OAAA,KAAY,IAAA,IAAQ,GAAA,CAAI,SAAS,OAAA,CAAQ,OAAA,GAAU,YAAA,CAAa,GAAA,CAAI,OAAO,CAAA;AAC9F,MAAA,QAAA,EAAS;AAAA,IACX,CAAC,CAAA;AAAA,IACH,CAAC,KAAK;AAAA,GACR;AACA,EAAA,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,WAAA,EAAa,KAAA,CAAM,WAAW,CAAA;AACpE,EAAA,kBAAA,CAAmB,MAAM;AAEvB,IAAA,IAAI,GAAA,CAAI,SAAS,UAAA,CAAW,GAAA,CAAI,SAAS,KAAA,EAAO,KAAA,CAAM,UAAU,CAAA;AAChE,IAAA,OAAA,CAAQ,OAAA,IAAU;AAClB,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,EACpB,CAAC,CAAA;AACD,EAAA,MAAM,IAAA,GAAsB,EAAE,KAAA,EAAO,KAAA,EAAO,GAAI,GAAA,KAAQ,MAAA,IAAa,EAAE,GAAA,EAAI,EAAG;AAE9E,EAAA,IAAI,CAAC,WAAA;AACH,IAAA,OAAO,WAAA;AAAA,MACL,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,MAAM,EAAE,GAAG,IAAA,EAAM,GAAG,kBAAA,CAAmB,KAAK,CAAA,EAAG,WAAA,EAAa,OAAO;AAAA,KACnG;AAEF,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,EAAE,GAAG,IAAA,EAAM,GAAG,kBAAA,CAAmB,KAAK,GAAG,CAAA;AACvF,EAAA,MAAM,UAAU,CAAC,CAAA,KAA4B,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AACxE,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,IAAA,KAAS,CAAA;AACrC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,IAAA,IAAQ,MAAM,SAAA,GAAY,CAAA;AAEpD,EAAA,MAAM,QACJ,KAAA,CAAM,KAAA,CAAM,QAAA,KAAa,MAAA,CAAO,oBAC5B,IAAA,GACA,aAAA;AAAA,IACE,KAAA;AAAA,IACA,EAAE,SAAA,EAAW,YAAA,EAAc,gBAAA,EAAkB,EAAA,EAAI,cAAc,YAAA,EAAa;AAAA,IAC5E,aAAA;AAAA,MACE,QAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,WAAA;AAAA,QACX,eAAA,EAAiB,MAAA;AAAA,QACjB,YAAA,EAAc,eAAA;AAAA,QACd,eAAA,EAAiB,UAAU,MAAA,GAAS;AAAA,OACtC;AAAA,MACA;AAAA,KACF;AAAA,IACA,aAAA;AAAA,MACE,MAAA;AAAA,MACA,EAAE,SAAA,EAAW,iBAAA,EAAmB,qBAAA,EAAuB,EAAA,EAAI,aAAa,QAAA,EAAS;AAAA,MACjF,WAAW,KAAK;AAAA,KAClB;AAAA,IACA,aAAA;AAAA,MACE,QAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,WAAA;AAAA,QACX,eAAA,EAAiB,MAAA;AAAA,QACjB,YAAA,EAAc,WAAA;AAAA,QACd,eAAA,EAAiB,QAAQ,MAAA,GAAS;AAAA,OACpC;AAAA,MACA;AAAA;AACF,GACF;AACN,EAAA,OAAO,aAAA;AAAA,IACL,KAAA;AAAA,IACA;AAAA,MACE,GAAG,aAAa,CAAC,CAAA;AAAA,MACjB,GAAA;AAAA,MACA,SAAS,CAAC,CAAA,KAAsB,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA,MAC3D,aAAa,CAAC,CAAA,KAAsB,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA;AAAA,MAC/D,cAAc,CAAC,CAAA,KAAsB,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA;AAAA,MAEhE,SAAA,EAAW,CAAC,CAAA,KAA0B;AACpC,QAAA,IAAI,IAAI,OAAA,EAAS,aAAA,CAAc,OAAO,GAAA,CAAI,OAAA,EAAS,EAAE,WAAW,CAAA;AAAA,MAClE;AAAA,KACF;AAAA;AAAA,IAEA,CAAA,CAAE,KAAA,GAAQ,aAAA,CAAc,OAAA,EAAS,EAAE,uBAAA,EAAyB,GAAA,CAAI,CAAA,CAAE,KAAK,CAAA,EAAG,CAAA,GAAI,IAAA;AAAA,IAC9E,aAAA;AAAA,MACE,KAAA;AAAA,MACA,EAAE,WAAW,cAAA,EAAe;AAAA,MAC5B,SAAA;AAAA,QACE,EAAA;AAAA,QACA,CAAA,EAAG,EAAE,EAAE,CAAA,OAAA,CAAA;AAAA,QACP,oBAAA;AAAA,QACA,oBAAA;AAAA,QACA,EAAE,0BAA0B,EAAA,EAAG;AAAA,QAC/B,MAAM,KAAA,CAAM,YAAA;AAAA,QACZ,OAAA;AAAA,QACA;AAAA,OACF;AAAA;AAAA,MAEA,YAAA,CAAa,KAAA,EAAO,CAAA,CAAE,MAAM,CAAA,CAAE,GAAA;AAAA,QAAI,CAAC,GAAG,CAAA,KACpC,SAAA;AAAA,UACE,CAAA,CAAE,GAAA;AAAA,UACF,CAAA,EAAG,CAAA,CAAE,EAAE,CAAA,QAAA,EAAW,CAAC,CAAA,CAAA;AAAA,UACnB,CAAA,OAAA,EAAU,EAAE,KAAK,CAAA,CAAA;AAAA,UACjB,aAAA;AAAA,UACA,EAAE,iBAAA,EAAmB,CAAA,CAAE,GAAA,EAAI;AAAA,UAC3B,CAAA,CAAE,KAAA;AAAA,UACF;AAAA;AACF;AACF,KACF;AAAA,IACA,cAAc,KAAA,EAAO;AAAA,MACnB,SAAA,EAAW,WAAA;AAAA,MACX,eAAA,EAAiB,EAAA;AAAA;AAAA,MAEjB,uBAAA,EAAyB,GAAA,CAAI,SAAA,CAAU,CAAC,CAAC;AAAA,KAC1C,CAAA;AAAA,IACD;AAAA,GACF;AACF","file":"react.js","sourcesContent":["import {\n type CSSProperties,\n Fragment,\n type ReactElement,\n type KeyboardEvent as ReactKeyboardEvent,\n type SyntheticEvent,\n createElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { type Sort, type Table, type TableOptions, type TableSnapshot, createTable } from \"../engine.js\";\nimport {\n applyHover,\n captureFocus,\n handleClick,\n handleHover,\n handleInput,\n handleKeydown,\n} from \"../html/controls.js\";\nimport { SR_ONLY, filterInputs, pagerLabel, tableRenderOptions } from \"../html/interactive.js\";\nimport { type RenderOptions, type RenderedParts, renderParts, tableHTML } from \"../html/parts.js\";\nimport type { TableSpec } from \"../spec.js\";\n\n/**\n * The engine behind `useTable` and an owned `<SdvTable/>`, created ONCE per component instance. A new `rows` array\n * (even an equal copy) goes to `table.setRows`, so the user's sort, filters, page and selection survive a parent\n * re-render; only a STRUCTURAL spec change (its JSON, functions dropped) builds a new engine from the current props.\n * Function-valued spec fields (formatters, comparators) are therefore read from the spec the engine was built with.\n */\nfunction useOwnedTable<Row>(spec: TableSpec<Row>, rows: readonly Row[], options: TableOptions): Table<Row> {\n // Not tableId(spec): an explicit spec.id short-circuits it, so a column change under a fixed id would keep a stale engine.\n // ponytail: one JSON.stringify per render, the same work tableId does for an id-less spec.\n const key = JSON.stringify(spec);\n const [held, setHeld] = useState(() => ({ key, table: createTable(spec, rows, options) }));\n let table = held.table;\n if (held.key !== key) {\n table = createTable(spec, rows, options); // React re-runs this render at once with the stored engine\n setHeld({ key, table });\n }\n // after the commit, never during render: setRows notifies subscribers, and React forbids updates from a render\n useIsoLayoutEffect(() => {\n if (table.allRows !== rows) table.setRows(rows);\n }, [table, rows]);\n return table;\n}\n\n/**\n * Subscribe a component to a `createTable` engine via useSyncExternalStore. The engine is created once per component:\n * a new `rows` array is handed to `table.setRows` (sort, filters, page and selection kept), and only a structural\n * `spec` change rebuilds it, so neither needs to be memoized. `options` are INITIAL state: a later change is ignored.\n */\nexport function useTable<Row>(\n spec: TableSpec<Row>,\n rows: readonly Row[],\n options: TableOptions = {},\n): { table: Table<Row>; snapshot: TableSnapshot<Row> } {\n const table = useOwnedTable(spec, rows, options);\n const snapshot = useSyncExternalStore(table.subscribe, table.getSnapshot, table.getSnapshot);\n return { table, snapshot };\n}\n\n/** `<SdvTable/>` building and owning its engine from `spec` and `rows`. */\nexport interface SdvTableOwnProps<Row> {\n /** the table to build; a later change with the same JSON (functions dropped) keeps the engine and its state */\n spec: TableSpec<Row>;\n /** the source rows; a new array (an equal copy included) keeps the user's sort, filters, page and selection */\n rows: readonly Row[];\n /** toolbar filters, sort headers and a pager driven by the engine; without it no engine is built */\n interactive?: boolean;\n /** INITIAL page size (beats `spec.interactive.pageSize`); like a React `default*` prop, a later change is ignored */\n pageSize?: number;\n /** INITIAL sort; like a React `default*` prop, a later change is ignored */\n sort?: Sort;\n /** `\"none\"` leaves the theme stylesheet out */\n css?: \"inline\" | \"none\";\n /** absent: pass a `table` to render an engine you own (`SdvTableLinkedProps`) */\n table?: undefined;\n}\n/**\n * J31 (A8): `<SdvTable/>` rendering an engine you own (from `createTable` or `useTable`, linked with\n * `linkSelection`). Its own spec and rows are rendered; `spec` and `rows` passed beside it are accepted and IGNORED\n * (change the rows with `table.setRows`). Initial state (`pageSize`, `sort`) belongs to that engine, so it is rejected.\n */\nexport interface SdvTableLinkedProps<Row> {\n /** the engine to render; the component re-renders on its changes */\n table: Table<Row>;\n /** ignored: the engine's own spec is rendered */\n spec?: TableSpec<Row>;\n /** ignored: the engine's own rows are rendered */\n rows?: readonly Row[];\n /** toolbar filters, sort headers and a pager; without it, the engine's current page as a static table */\n interactive?: boolean;\n /** `\"none\"` leaves the theme stylesheet out */\n css?: \"inline\" | \"none\";\n /** rejected: set it on the engine (`createTable(spec, rows, { pageSize })`) */\n pageSize?: undefined;\n /** rejected: set it on the engine (`createTable(spec, rows, { sort })`) */\n sort?: undefined;\n}\n/** Either an engine to render (`{ table }`) or the data to build one from (`{ spec, rows }`). */\nexport type SdvTableProps<Row> = SdvTableOwnProps<Row> | SdvTableLinkedProps<Row>;\n\n/** Wrapper attributes in the string renderer's order: class, id, data-sdvt-theme, data-sdvt-density. */\nfunction wrapperProps(p: RenderedParts): Record<string, string> {\n return {\n className: p.wrapperAttrs.class ?? \"\",\n id: p.wrapperAttrs.id ?? \"\",\n \"data-sdvt-theme\": p.wrapperAttrs[\"data-sdvt-theme\"] ?? \"\",\n \"data-sdvt-density\": p.wrapperAttrs[\"data-sdvt-density\"] ?? \"\",\n };\n}\n// Every string below comes from the escaping string renderer (parts.ts), never from raw data.\nconst raw = (html: string): { __html: string } => ({ __html: html });\n// the string renderer's visually hidden <label> style, as the camelCase object React writes back in the same order\nconst SR_STYLE = Object.fromEntries(\n SR_ONLY.split(\";\").map((d) => {\n const [k = \"\", v = \"\"] = d.split(\":\");\n return [k.replace(/-(\\w)/g, (_, ch: string) => ch.toUpperCase()), v];\n }),\n) as CSSProperties;\n// no layout effects during SSR (React 18 warns about them there)\nconst useIsoLayoutEffect = typeof document === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** A visually hidden <label> + search <input>, the same markup as the string renderer's toolbar inputs. */\nfunction searchBox(\n key: string,\n id: string,\n label: string,\n cls: string,\n data: Record<string, string>,\n value: string,\n onChange: (e: SyntheticEvent) => void,\n placeholder: string = label,\n): ReactElement {\n return createElement(\n Fragment,\n { key },\n createElement(\"label\", { htmlFor: id, style: SR_STYLE }, label),\n createElement(\"input\", { type: \"search\", id, className: cls, ...data, placeholder, value, onChange }),\n );\n}\n\n/**\n * Same markup as `renderHTML` (test-enforced). Two forms: `{ spec, rows }` builds an engine (only when `interactive`;\n * a static table needs none) that lives as long as the component; `{ table }` renders an engine you own, statically\n * (its current page: filtered, sorted, sliced) or with controls. The table block is the string renderer's output;\n * React owns only the toolbar inputs and the pager, so typing in a filter never re-creates the input. The inputs are\n * controlled by the engine state, so a filter set from outside (another component, a linked selection) shows in its\n * box. A control or focusable cell element that a re-render replaces gets focus back, as in `hydrate`. The\n * Google-Fonts link is NOT rendered: put `fontsLinkFor(spec)` in the page head.\n *\n * Two cases remount the owned engine (`{ spec, rows }` form only; an engine passed as `table` is yours and is kept):\n * toggling `interactive` remounts it, losing the user's sort, filters, page and selection, since a static render\n * builds no engine. And the engine is keyed by the spec's JSON, which drops functions, so a deliberately changed\n * formatter or comparator under an otherwise equal spec does NOT take effect: change the element's React `key` to\n * rebuild the engine from the new spec.\n */\nexport function SdvTable<Row>(props: SdvTableProps<Row>): ReactElement {\n const { interactive = false, css } = props;\n if (props.table !== undefined)\n return createElement(TableView<Row>, { table: props.table, interactive, css });\n if (interactive) return createElement(OwnedTable<Row>, props);\n const p = renderParts(props.spec, props.rows, { fonts: false, ...(css !== undefined && { css }) });\n return staticBlock(p);\n}\n\n/** The static table: wrapper, theme sheet and table block, as one string-renderer HTML blob. */\nfunction staticBlock(p: RenderedParts): ReactElement {\n const inner = `${p.sheet ? `<style>${p.sheet}</style>` : \"\"}${tableHTML(p)}`;\n return createElement(\"div\", { ...wrapperProps(p), dangerouslySetInnerHTML: raw(inner) });\n}\n\n/** I2: the owned engine exists only here, so `{ table }` and static renders never build one. */\nfunction OwnedTable<Row>({ spec, rows, pageSize, sort, css }: SdvTableOwnProps<Row>): ReactElement {\n const table = useOwnedTable(spec, rows, {\n ...(pageSize !== undefined && { pageSize }),\n ...(sort !== undefined && { sort }),\n });\n return createElement(TableView<Row>, { table, interactive: true, css });\n}\n\nfunction TableView<Row>({\n table,\n interactive,\n css,\n}: {\n table: Table<Row>;\n interactive: boolean;\n css: \"inline\" | \"none\" | undefined;\n}): ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const restore = useRef<(() => void) | null>(null);\n // A50: remember the focused control while the DOM still holds it (the engine notifies before React re-renders).\n // A hover is a class toggle on the rendered rows, never a re-render (that would replace the row under the pointer).\n const subscribe = useCallback(\n (onChange: () => void) =>\n table.subscribe((e) => {\n if (e.type === \"hover\") {\n if (ref.current) applyHover(ref.current, table, e.id);\n } else if (restore.current === null && ref.current) restore.current = captureFocus(ref.current);\n onChange();\n }),\n [table],\n );\n useSyncExternalStore(subscribe, table.getSnapshot, table.getSnapshot); // J31: an external engine re-renders us too\n useIsoLayoutEffect(() => {\n // a render may have rebuilt the body rows; getHover, not a ref, so a (re)mount or a new table shows its own hover\n if (ref.current) applyHover(ref.current, table, table.getHover());\n restore.current?.();\n restore.current = null;\n });\n const base: RenderOptions = { fonts: false, ...(css !== undefined && { css }) };\n // M3: without controls, the engine's current page, coloured from all its rows (A49)\n if (!interactive)\n return staticBlock(\n renderParts(table.spec, table.rows, { ...base, ...tableRenderOptions(table), interactive: false }),\n );\n\n const p = renderParts(table.spec, table.rows, { ...base, ...tableRenderOptions(table) });\n const onInput = (e: SyntheticEvent): void => handleInput(table, e.target);\n const atStart = table.state.page === 0;\n const atEnd = table.state.page >= table.pageCount - 1;\n // A50: the hydrated SSR markup: an edge button is aria-disabled (not disabled), the label a polite live region\n const pager =\n table.state.pageSize === Number.POSITIVE_INFINITY\n ? null\n : createElement(\n \"nav\",\n { className: \"sdvt-pager\", \"data-sdv-pager\": \"\", \"aria-label\": \"Pagination\" },\n createElement(\n \"button\",\n {\n type: \"button\",\n className: \"sdvt-page\",\n \"data-sdv-page\": \"prev\",\n \"aria-label\": \"Previous page\",\n \"aria-disabled\": atStart ? \"true\" : undefined,\n },\n \"‹\",\n ),\n createElement(\n \"span\",\n { className: \"sdvt-page-label\", \"data-sdv-page-label\": \"\", \"aria-live\": \"polite\" },\n pagerLabel(table),\n ),\n createElement(\n \"button\",\n {\n type: \"button\",\n className: \"sdvt-page\",\n \"data-sdv-page\": \"next\",\n \"aria-label\": \"Next page\",\n \"aria-disabled\": atEnd ? \"true\" : undefined,\n },\n \"›\",\n ),\n );\n return createElement(\n \"div\",\n {\n ...wrapperProps(p),\n ref,\n onClick: (e: SyntheticEvent) => handleClick(table, e.target),\n onMouseOver: (e: SyntheticEvent) => handleHover(table, e.target), // J31 (A8): no attribute, so SSR is unchanged\n onMouseLeave: (e: SyntheticEvent) => handleHover(table, e.target),\n // Task 10: hotkeys and the grid's keys, as in hydrate; an event prop writes no attribute\n onKeyDown: (e: ReactKeyboardEvent) => {\n if (ref.current) handleKeydown(table, ref.current, e.nativeEvent);\n },\n },\n // biome-ignore lint/security/noDangerouslySetInnerHtml: escaped renderer output (see `raw`)\n p.sheet ? createElement(\"style\", { dangerouslySetInnerHTML: raw(p.sheet) }) : null,\n createElement(\n \"div\",\n { className: \"sdvt-toolbar\" },\n searchBox(\n \"\",\n `${p.id}-search`,\n \"Search all columns\",\n \"sdvt-global-filter\",\n { \"data-sdv-global-filter\": \"\" },\n table.state.globalFilter,\n onInput,\n \"Search\",\n ),\n // keyed by column, so hiding a column never hands another column's input (and its focus) over\n filterInputs(table, p.labels).map((f, j) =>\n searchBox(\n f.key,\n `${p.id}-filter-${j}`,\n `Filter ${f.label}`,\n \"sdvt-filter\",\n { \"data-sdv-filter\": f.key },\n f.value,\n onInput,\n ),\n ),\n ),\n createElement(\"div\", {\n className: \"sdvt-body\",\n \"data-sdv-body\": \"\",\n // biome-ignore lint/security/noDangerouslySetInnerHtml: escaped renderer output (see `raw`)\n dangerouslySetInnerHTML: raw(tableHTML(p)),\n }),\n pager,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/index.tsx"],"names":[],"mappings":";;;;;;AAiCA,SAAS,aAAA,CAAmB,IAAA,EAAsB,IAAA,EAAsB,OAAA,EAAmC;AAGzG,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAC/B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,WAAA,CAAY,IAAA,EAAM,IAAA,EAAM,OAAO,GAAE,CAAE,CAAA;AACzF,EAAA,IAAI,QAAQ,IAAA,CAAK,KAAA;AACjB,EAAA,IAAI,IAAA,CAAK,QAAQ,GAAA,EAAK;AACpB,IAAA,KAAA,GAAQ,WAAA,CAAY,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AACvC,IAAA,OAAA,CAAQ,EAAE,GAAA,EAAK,KAAA,EAAO,CAAA;AAAA,EACxB;AAEA,EAAA,kBAAA,CAAmB,MAAM;AACvB,IAAA,IAAI,KAAA,CAAM,OAAA,KAAY,IAAA,EAAM,KAAA,CAAM,QAAQ,IAAI,CAAA;AAAA,EAChD,CAAA,EAAG,CAAC,KAAA,EAAO,IAAI,CAAC,CAAA;AAChB,EAAA,OAAO,KAAA;AACT;AAOO,SAAS,QAAA,CACd,IAAA,EACA,IAAA,EACA,OAAA,GAAwB,EAAC,EAC4B;AACrD,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAC/C,EAAA,MAAM,WAAW,oBAAA,CAAqB,KAAA,CAAM,WAAW,KAAA,CAAM,WAAA,EAAa,MAAM,WAAW,CAAA;AAC3F,EAAA,OAAO,EAAE,OAAO,QAAA,EAAS;AAC3B;AA4CA,SAAS,aAAa,CAAA,EAA0C;AAC9D,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAA,CAAE,YAAA,CAAa,KAAA,IAAS,EAAA;AAAA,IACnC,EAAA,EAAI,CAAA,CAAE,YAAA,CAAa,EAAA,IAAM,EAAA;AAAA,IACzB,iBAAA,EAAmB,CAAA,CAAE,YAAA,CAAa,iBAAiB,CAAA,IAAK,EAAA;AAAA,IACxD,mBAAA,EAAqB,CAAA,CAAE,YAAA,CAAa,mBAAmB,CAAA,IAAK;AAAA,GAC9D;AACF;AAEA,IAAM,GAAA,GAAM,CAAC,IAAA,MAAsC,EAAE,QAAQ,IAAA,EAAK,CAAA;AAElE,IAAM,WAAW,MAAA,CAAO,WAAA;AAAA,EACtB,QAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM;AAC5B,IAAA,MAAM,CAAC,IAAI,EAAA,EAAI,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,MAAM,GAAG,CAAA;AACpC,IAAA,OAAO,CAAC,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAA,EAAG,EAAA,KAAe,EAAA,CAAG,WAAA,EAAa,CAAA,EAAG,CAAC,CAAA;AAAA,EACrE,CAAC;AACH,CAAA;AAEA,IAAM,kBAAA,GAAqB,OAAO,QAAA,KAAa,WAAA,GAAc,SAAA,GAAY,eAAA;AAGzE,SAAS,SAAA,CACP,KACA,EAAA,EACA,KAAA,EACA,KACA,IAAA,EACA,KAAA,EACA,QAAA,EACA,WAAA,GAAsB,KAAA,EACR;AACd,EAAA,OAAO,aAAA;AAAA,IACL,QAAA;AAAA,IACA,EAAE,GAAA,EAAI;AAAA,IACN,aAAA,CAAc,SAAS,EAAE,OAAA,EAAS,IAAI,KAAA,EAAO,QAAA,IAAY,KAAK,CAAA;AAAA,IAC9D,aAAA,CAAc,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,EAAA,EAAI,SAAA,EAAW,GAAA,EAAK,GAAG,IAAA,EAAM,WAAA,EAAa,KAAA,EAAO,UAAU;AAAA,GACtG;AACF;AAiBO,SAAS,SAAc,KAAA,EAAyC;AACrE,EAAA,MAAM,EAAE,WAAA,GAAc,KAAA,EAAO,GAAA,EAAI,GAAI,KAAA;AACrC,EAAA,IAAI,MAAM,KAAA,KAAU,MAAA;AAClB,IAAA,OAAO,aAAA,CAAc,WAAgB,EAAE,KAAA,EAAO,MAAM,KAAA,EAAO,WAAA,EAAa,KAAK,CAAA;AAC/E,EAAA,IAAI,WAAA,EAAa,OAAO,aAAA,CAAc,UAAA,EAAiB,KAAK,CAAA;AAC5D,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,MAAM,IAAA,EAAM,EAAE,KAAA,EAAO,KAAA,EAAO,GAAI,GAAA,KAAQ,MAAA,IAAa,EAAE,GAAA,IAAQ,CAAA;AACjG,EAAA,OAAO,YAAY,CAAC,CAAA;AACtB;AAGA,SAAS,YAAY,CAAA,EAAgC;AACnD,EAAA,MAAM,KAAA,GAAQ,CAAA,EAAG,CAAA,CAAE,KAAA,GAAQ,CAAA,OAAA,EAAU,CAAA,CAAE,KAAK,CAAA,QAAA,CAAA,GAAa,EAAE,CAAA,EAAG,SAAA,CAAU,CAAC,CAAC,CAAA,CAAA;AAC1E,EAAA,OAAO,aAAA,CAAc,KAAA,EAAO,EAAE,GAAG,YAAA,CAAa,CAAC,CAAA,EAAG,uBAAA,EAAyB,GAAA,CAAI,KAAK,CAAA,EAAG,CAAA;AACzF;AAGA,SAAS,WAAgB,EAAE,IAAA,EAAM,MAAM,QAAA,EAAU,IAAA,EAAM,KAAI,EAAwC;AACjG,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM;AAAA,IACtC,GAAI,QAAA,KAAa,MAAA,IAAa,EAAE,QAAA,EAAS;AAAA,IACzC,GAAI,IAAA,KAAS,MAAA,IAAa,EAAE,IAAA;AAAK,GAClC,CAAA;AACD,EAAA,OAAO,cAAc,SAAA,EAAgB,EAAE,OAAO,WAAA,EAAa,IAAA,EAAM,KAAK,CAAA;AACxE;AAEA,SAAS,SAAA,CAAe;AAAA,EACtB,KAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,EAIiB;AACf,EAAA,MAAM,GAAA,GAAM,OAAuB,IAAI,CAAA;AACvC,EAAA,MAAM,OAAA,GAAU,OAA4B,IAAI,CAAA;AAGhD,EAAA,MAAM,SAAA,GAAY,WAAA;AAAA,IAChB,CAAC,QAAA,KACC,KAAA,CAAM,SAAA,CAAU,CAAC,CAAA,KAAM;AACrB,MAAA,IAAI,CAAA,CAAE,SAAS,OAAA,EAAS;AACtB,QAAA,IAAI,IAAI,OAAA,EAAS,UAAA,CAAW,IAAI,OAAA,EAAS,KAAA,EAAO,EAAE,EAAE,CAAA;AAAA,MACtD,CAAA,MAAA,IAAW,OAAA,CAAQ,OAAA,KAAY,IAAA,IAAQ,GAAA,CAAI,SAAS,OAAA,CAAQ,OAAA,GAAU,YAAA,CAAa,GAAA,CAAI,OAAO,CAAA;AAC9F,MAAA,QAAA,EAAS;AAAA,IACX,CAAC,CAAA;AAAA,IACH,CAAC,KAAK;AAAA,GACR;AACA,EAAA,oBAAA,CAAqB,SAAA,EAAW,KAAA,CAAM,WAAA,EAAa,KAAA,CAAM,WAAW,CAAA;AACpE,EAAA,kBAAA,CAAmB,MAAM;AAEvB,IAAA,IAAI,GAAA,CAAI,SAAS,UAAA,CAAW,GAAA,CAAI,SAAS,KAAA,EAAO,KAAA,CAAM,UAAU,CAAA;AAChE,IAAA,OAAA,CAAQ,OAAA,IAAU;AAClB,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,EACpB,CAAC,CAAA;AACD,EAAA,MAAM,IAAA,GAAsB,EAAE,KAAA,EAAO,KAAA,EAAO,GAAI,GAAA,KAAQ,MAAA,IAAa,EAAE,GAAA,EAAI,EAAG;AAE9E,EAAA,IAAI,CAAC,WAAA;AACH,IAAA,OAAO,WAAA;AAAA,MACL,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,MAAM,EAAE,GAAG,IAAA,EAAM,GAAG,kBAAA,CAAmB,KAAK,CAAA,EAAG,WAAA,EAAa,OAAO;AAAA,KACnG;AAEF,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,EAAE,GAAG,IAAA,EAAM,GAAG,kBAAA,CAAmB,KAAK,GAAG,CAAA;AACvF,EAAA,MAAM,UAAU,CAAC,CAAA,KAA4B,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AACxE,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,IAAA,KAAS,CAAA;AACrC,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,IAAA,IAAQ,MAAM,SAAA,GAAY,CAAA;AAEpD,EAAA,MAAM,QACJ,KAAA,CAAM,KAAA,CAAM,QAAA,KAAa,MAAA,CAAO,oBAC5B,IAAA,GACA,aAAA;AAAA,IACE,KAAA;AAAA,IACA,EAAE,SAAA,EAAW,YAAA,EAAc,gBAAA,EAAkB,EAAA,EAAI,cAAc,YAAA,EAAa;AAAA,IAC5E,aAAA;AAAA,MACE,QAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,WAAA;AAAA,QACX,eAAA,EAAiB,MAAA;AAAA,QACjB,YAAA,EAAc,eAAA;AAAA,QACd,eAAA,EAAiB,UAAU,MAAA,GAAS;AAAA,OACtC;AAAA,MACA;AAAA,KACF;AAAA,IACA,aAAA;AAAA,MACE,MAAA;AAAA,MACA,EAAE,SAAA,EAAW,iBAAA,EAAmB,qBAAA,EAAuB,EAAA,EAAI,aAAa,QAAA,EAAS;AAAA,MACjF,WAAW,KAAK;AAAA,KAClB;AAAA,IACA,aAAA;AAAA,MACE,QAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,WAAA;AAAA,QACX,eAAA,EAAiB,MAAA;AAAA,QACjB,YAAA,EAAc,WAAA;AAAA,QACd,eAAA,EAAiB,QAAQ,MAAA,GAAS;AAAA,OACpC;AAAA,MACA;AAAA;AACF,GACF;AACN,EAAA,OAAO,aAAA;AAAA,IACL,KAAA;AAAA,IACA;AAAA,MACE,GAAG,aAAa,CAAC,CAAA;AAAA,MACjB,GAAA;AAAA,MACA,SAAS,CAAC,CAAA,KAAsB,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA,MAC3D,aAAa,CAAC,CAAA,KAAsB,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA;AAAA,MAC/D,cAAc,CAAC,CAAA,KAAsB,WAAA,CAAY,KAAA,EAAO,EAAE,MAAM,CAAA;AAAA;AAAA,MAEhE,SAAA,EAAW,CAAC,CAAA,KAA0B;AACpC,QAAA,IAAI,IAAI,OAAA,EAAS,aAAA,CAAc,OAAO,GAAA,CAAI,OAAA,EAAS,EAAE,WAAW,CAAA;AAAA,MAClE;AAAA,KACF;AAAA;AAAA,IAEA,CAAA,CAAE,KAAA,GAAQ,aAAA,CAAc,OAAA,EAAS,EAAE,uBAAA,EAAyB,GAAA,CAAI,CAAA,CAAE,KAAK,CAAA,EAAG,CAAA,GAAI,IAAA;AAAA,IAC9E,aAAA;AAAA,MACE,KAAA;AAAA,MACA,EAAE,WAAW,cAAA,EAAe;AAAA,MAC5B,SAAA;AAAA,QACE,EAAA;AAAA,QACA,CAAA,EAAG,EAAE,EAAE,CAAA,OAAA,CAAA;AAAA,QACP,oBAAA;AAAA,QACA,oBAAA;AAAA,QACA,EAAE,0BAA0B,EAAA,EAAG;AAAA,QAC/B,MAAM,KAAA,CAAM,YAAA;AAAA,QACZ,OAAA;AAAA,QACA;AAAA,OACF;AAAA;AAAA,MAEA,YAAA,CAAa,KAAA,EAAO,CAAA,CAAE,MAAM,CAAA,CAAE,GAAA;AAAA,QAAI,CAAC,GAAG,CAAA,KACpC,SAAA;AAAA,UACE,CAAA,CAAE,GAAA;AAAA,UACF,CAAA,EAAG,CAAA,CAAE,EAAE,CAAA,QAAA,EAAW,CAAC,CAAA,CAAA;AAAA,UACnB,CAAA,OAAA,EAAU,EAAE,KAAK,CAAA,CAAA;AAAA,UACjB,aAAA;AAAA,UACA,EAAE,iBAAA,EAAmB,CAAA,CAAE,GAAA,EAAI;AAAA,UAC3B,CAAA,CAAE,KAAA;AAAA,UACF;AAAA;AACF;AACF,KACF;AAAA,IACA,cAAc,KAAA,EAAO;AAAA,MACnB,SAAA,EAAW,WAAA;AAAA,MACX,eAAA,EAAiB,EAAA;AAAA;AAAA,MAEjB,uBAAA,EAAyB,GAAA,CAAI,SAAA,CAAU,CAAC,CAAC;AAAA,KAC1C,CAAA;AAAA,IACD;AAAA,GACF;AACF","file":"react.js","sourcesContent":["import {\n type CSSProperties,\n Fragment,\n type ReactElement,\n type KeyboardEvent as ReactKeyboardEvent,\n type SyntheticEvent,\n createElement,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { type Sort, type Table, type TableOptions, type TableSnapshot, createTable } from \"../engine.js\";\nimport {\n applyHover,\n captureFocus,\n handleClick,\n handleHover,\n handleInput,\n handleKeydown,\n} from \"../html/controls.js\";\nimport { SR_ONLY, filterInputs, pagerLabel, tableRenderOptions } from \"../html/interactive.js\";\nimport { type RenderOptions, type RenderedParts, renderParts, tableHTML } from \"../html/parts.js\";\nimport type { TableSpec } from \"../spec.js\";\n\n/**\n * The engine behind `useTable` and an owned `<SdvTable/>`, created ONCE per component instance. A new `rows` array\n * (even an equal copy) goes to `table.setRows`, so the user's sort, filters, page and selection survive a parent\n * re-render; only a STRUCTURAL spec change (its JSON, functions dropped) builds a new engine from the current props.\n * Function-valued spec fields (formatters, comparators) are therefore read from the spec the engine was built with.\n */\nfunction useOwnedTable<Row>(spec: TableSpec<Row>, rows: readonly Row[], options: TableOptions): Table<Row> {\n // Not tableId(spec): an explicit spec.id short-circuits it, so a column change under a fixed id would keep a stale engine.\n // ponytail: one JSON.stringify per render, the same work tableId does for an id-less spec.\n const key = JSON.stringify(spec);\n const [held, setHeld] = useState(() => ({ key, table: createTable(spec, rows, options) }));\n let table = held.table;\n if (held.key !== key) {\n table = createTable(spec, rows, options); // React re-runs this render at once with the stored engine\n setHeld({ key, table });\n }\n // after the commit, never during render: setRows notifies subscribers, and React forbids updates from a render\n useIsoLayoutEffect(() => {\n if (table.allRows !== rows) table.setRows(rows);\n }, [table, rows]);\n return table;\n}\n\n/**\n * Subscribe a component to a `createTable` engine via useSyncExternalStore. The engine is created once per component:\n * a new `rows` array is handed to `table.setRows` (sort, filters, page and selection kept), and only a structural\n * `spec` change rebuilds it, so neither needs to be memoized. `options` are INITIAL state: a later change is ignored.\n */\nexport function useTable<Row>(\n spec: TableSpec<Row>,\n rows: readonly Row[],\n options: TableOptions = {},\n): { table: Table<Row>; snapshot: TableSnapshot<Row> } {\n const table = useOwnedTable(spec, rows, options);\n const snapshot = useSyncExternalStore(table.subscribe, table.getSnapshot, table.getSnapshot);\n return { table, snapshot };\n}\n\n/** `<SdvTable/>` building and owning its engine from `spec` and `rows`. */\nexport interface SdvTableOwnProps<Row> {\n /** the table to build; a later change with the same JSON (functions dropped) keeps the engine and its state */\n spec: TableSpec<Row>;\n /** the source rows; a new array (an equal copy included) keeps the user's sort, filters, page and selection */\n rows: readonly Row[];\n /** toolbar filters, sort headers and a pager driven by the engine; without it no engine is built */\n interactive?: boolean;\n /** INITIAL page size (beats `spec.interactive.pageSize`); like a React `default*` prop, a later change is ignored */\n pageSize?: number;\n /** INITIAL sort; like a React `default*` prop, a later change is ignored */\n sort?: Sort;\n /** `\"none\"` leaves the theme stylesheet out */\n css?: \"inline\" | \"none\";\n /** absent: pass a `table` to render an engine you own (`SdvTableLinkedProps`) */\n table?: undefined;\n}\n/**\n * J31 (A8): `<SdvTable/>` rendering an engine you own (from `createTable` or `useTable`, linked with\n * `linkSelection`). Its own spec and rows are rendered; `spec` and `rows` passed beside it are accepted and IGNORED\n * (change the rows with `table.setRows`). Initial state (`pageSize`, `sort`) belongs to that engine, so it is rejected.\n */\nexport interface SdvTableLinkedProps<Row> {\n /** the engine to render; the component re-renders on its changes */\n table: Table<Row>;\n /** ignored: the engine's own spec is rendered */\n spec?: TableSpec<Row>;\n /** ignored: the engine's own rows are rendered */\n rows?: readonly Row[];\n /** toolbar filters, sort headers and a pager; without it, the engine's current page as a static table */\n interactive?: boolean;\n /** `\"none\"` leaves the theme stylesheet out */\n css?: \"inline\" | \"none\";\n /** rejected: set it on the engine (`createTable(spec, rows, { pageSize })`) */\n pageSize?: undefined;\n /** rejected: set it on the engine (`createTable(spec, rows, { sort })`) */\n sort?: undefined;\n}\n/** Either an engine to render (`{ table }`) or the data to build one from (`{ spec, rows }`). */\nexport type SdvTableProps<Row> = SdvTableOwnProps<Row> | SdvTableLinkedProps<Row>;\n\n/** Wrapper attributes in the string renderer's order: class, id, data-sdvt-theme, data-sdvt-density. */\nfunction wrapperProps(p: RenderedParts): Record<string, string> {\n return {\n className: p.wrapperAttrs.class ?? \"\",\n id: p.wrapperAttrs.id ?? \"\",\n \"data-sdvt-theme\": p.wrapperAttrs[\"data-sdvt-theme\"] ?? \"\",\n \"data-sdvt-density\": p.wrapperAttrs[\"data-sdvt-density\"] ?? \"\",\n };\n}\n// Every string below comes from the escaping string renderer (parts.ts), never from raw data.\nconst raw = (html: string): { __html: string } => ({ __html: html });\n// the string renderer's visually hidden <label> style, as the camelCase object React writes back in the same order\nconst SR_STYLE = Object.fromEntries(\n SR_ONLY.split(\";\").map((d) => {\n const [k = \"\", v = \"\"] = d.split(\":\");\n return [k.replace(/-(\\w)/g, (_, ch: string) => ch.toUpperCase()), v];\n }),\n) as CSSProperties;\n// no layout effects during SSR (React 18 warns about them there)\nconst useIsoLayoutEffect = typeof document === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** A visually hidden <label> + search <input>, the same markup as the string renderer's toolbar inputs. */\nfunction searchBox(\n key: string,\n id: string,\n label: string,\n cls: string,\n data: Record<string, string>,\n value: string,\n onChange: (e: SyntheticEvent) => void,\n placeholder: string = label,\n): ReactElement {\n return createElement(\n Fragment,\n { key },\n createElement(\"label\", { htmlFor: id, style: SR_STYLE }, label),\n createElement(\"input\", { type: \"search\", id, className: cls, ...data, placeholder, value, onChange }),\n );\n}\n\n/**\n * Same markup as `renderHTML` (test-enforced). Two forms: `{ spec, rows }` builds an engine (only when `interactive`;\n * a static table needs none) that lives as long as the component; `{ table }` renders an engine you own, statically\n * (its current page: filtered, sorted, sliced) or with controls. The table block is the string renderer's output;\n * React owns only the toolbar inputs and the pager, so typing in a filter never re-creates the input. The inputs are\n * controlled by the engine state, so a filter set from outside (another component, a linked selection) shows in its\n * box. A control or focusable cell element that a re-render replaces gets focus back, as in `hydrate`. The\n * Google-Fonts link is NOT rendered: put `fontsLinkFor(spec)` in the page head.\n *\n * Two cases remount the owned engine (`{ spec, rows }` form only; an engine passed as `table` is yours and is kept):\n * toggling `interactive` remounts it, losing the user's sort, filters, page and selection, since a static render\n * builds no engine. And the engine is keyed by the spec's JSON, which drops functions, so a deliberately changed\n * formatter or comparator under an otherwise equal spec does NOT take effect: change the element's React `key` to\n * rebuild the engine from the new spec.\n */\nexport function SdvTable<Row>(props: SdvTableProps<Row>): ReactElement {\n const { interactive = false, css } = props;\n if (props.table !== undefined)\n return createElement(TableView<Row>, { table: props.table, interactive, css });\n if (interactive) return createElement(OwnedTable<Row>, props);\n const p = renderParts(props.spec, props.rows, { fonts: false, ...(css !== undefined && { css }) });\n return staticBlock(p);\n}\n\n/** The static table: wrapper, theme sheet and table block, as one string-renderer HTML blob. */\nfunction staticBlock(p: RenderedParts): ReactElement {\n const inner = `${p.sheet ? `<style>${p.sheet}</style>` : \"\"}${tableHTML(p)}`;\n return createElement(\"div\", { ...wrapperProps(p), dangerouslySetInnerHTML: raw(inner) });\n}\n\n/** I2: the owned engine exists only here, so `{ table }` and static renders never build one. */\nfunction OwnedTable<Row>({ spec, rows, pageSize, sort, css }: SdvTableOwnProps<Row>): ReactElement {\n const table = useOwnedTable(spec, rows, {\n ...(pageSize !== undefined && { pageSize }),\n ...(sort !== undefined && { sort }),\n });\n return createElement(TableView<Row>, { table, interactive: true, css });\n}\n\nfunction TableView<Row>({\n table,\n interactive,\n css,\n}: {\n table: Table<Row>;\n interactive: boolean;\n css: \"inline\" | \"none\" | undefined;\n}): ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const restore = useRef<(() => void) | null>(null);\n // A50: remember the focused control while the DOM still holds it (the engine notifies before React re-renders).\n // A hover is a class toggle on the rendered rows, never a re-render (that would replace the row under the pointer).\n const subscribe = useCallback(\n (onChange: () => void) =>\n table.subscribe((e) => {\n if (e.type === \"hover\") {\n if (ref.current) applyHover(ref.current, table, e.id);\n } else if (restore.current === null && ref.current) restore.current = captureFocus(ref.current);\n onChange();\n }),\n [table],\n );\n useSyncExternalStore(subscribe, table.getSnapshot, table.getSnapshot); // J31: an external engine re-renders us too\n useIsoLayoutEffect(() => {\n // a render may have rebuilt the body rows; getHover, not a ref, so a (re)mount or a new table shows its own hover\n if (ref.current) applyHover(ref.current, table, table.getHover());\n restore.current?.();\n restore.current = null;\n });\n const base: RenderOptions = { fonts: false, ...(css !== undefined && { css }) };\n // M3: without controls, the engine's current page, coloured from all its rows (A49)\n if (!interactive)\n return staticBlock(\n renderParts(table.spec, table.rows, { ...base, ...tableRenderOptions(table), interactive: false }),\n );\n\n const p = renderParts(table.spec, table.rows, { ...base, ...tableRenderOptions(table) });\n const onInput = (e: SyntheticEvent): void => handleInput(table, e.target);\n const atStart = table.state.page === 0;\n const atEnd = table.state.page >= table.pageCount - 1;\n // A50: the hydrated SSR markup: an edge button is aria-disabled (not disabled), the label a polite live region\n const pager =\n table.state.pageSize === Number.POSITIVE_INFINITY\n ? null\n : createElement(\n \"nav\",\n { className: \"sdvt-pager\", \"data-sdv-pager\": \"\", \"aria-label\": \"Pagination\" },\n createElement(\n \"button\",\n {\n type: \"button\",\n className: \"sdvt-page\",\n \"data-sdv-page\": \"prev\",\n \"aria-label\": \"Previous page\",\n \"aria-disabled\": atStart ? \"true\" : undefined,\n },\n \"‹\",\n ),\n createElement(\n \"span\",\n { className: \"sdvt-page-label\", \"data-sdv-page-label\": \"\", \"aria-live\": \"polite\" },\n pagerLabel(table),\n ),\n createElement(\n \"button\",\n {\n type: \"button\",\n className: \"sdvt-page\",\n \"data-sdv-page\": \"next\",\n \"aria-label\": \"Next page\",\n \"aria-disabled\": atEnd ? \"true\" : undefined,\n },\n \"›\",\n ),\n );\n return createElement(\n \"div\",\n {\n ...wrapperProps(p),\n ref,\n onClick: (e: SyntheticEvent) => handleClick(table, e.target),\n onMouseOver: (e: SyntheticEvent) => handleHover(table, e.target), // J31 (A8): no attribute, so SSR is unchanged\n onMouseLeave: (e: SyntheticEvent) => handleHover(table, e.target),\n // Task 10: hotkeys and the grid's keys, as in hydrate; an event prop writes no attribute\n onKeyDown: (e: ReactKeyboardEvent) => {\n if (ref.current) handleKeydown(table, ref.current, e.nativeEvent);\n },\n },\n // biome-ignore lint/security/noDangerouslySetInnerHtml: escaped renderer output (see `raw`)\n p.sheet ? createElement(\"style\", { dangerouslySetInnerHTML: raw(p.sheet) }) : null,\n createElement(\n \"div\",\n { className: \"sdvt-toolbar\" },\n searchBox(\n \"\",\n `${p.id}-search`,\n \"Search all columns\",\n \"sdvt-global-filter\",\n { \"data-sdv-global-filter\": \"\" },\n table.state.globalFilter,\n onInput,\n \"Search\",\n ),\n // keyed by column, so hiding a column never hands another column's input (and its focus) over\n filterInputs(table, p.labels).map((f, j) =>\n searchBox(\n f.key,\n `${p.id}-filter-${j}`,\n `Filter ${f.label}`,\n \"sdvt-filter\",\n { \"data-sdv-filter\": f.key },\n f.value,\n onInput,\n ),\n ),\n ),\n createElement(\"div\", {\n className: \"sdvt-body\",\n \"data-sdv-body\": \"\",\n // biome-ignore lint/security/noDangerouslySetInnerHtml: escaped renderer output (see `raw`)\n dangerouslySetInnerHTML: raw(tableHTML(p)),\n }),\n pager,\n );\n}\n"]}
|