@datakable/react 2.0.2 → 2.0.3

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.
@@ -223,6 +223,13 @@ function pages(view, page, count, server) {
223
223
  return { ...page, pageCount, canPrev: index > 0, canNext: index + 1 < pageCount };
224
224
  }
225
225
  var ariaSort = (dir) => dir === "asc" ? "ascending" : dir === "desc" ? "descending" : "none";
226
+ function focusTable(t) {
227
+ if (!t.hasAttribute("tabindex")) {
228
+ t.setAttribute("tabindex", "-1");
229
+ t.addEventListener("blur", () => t.removeAttribute("tabindex"), { once: true });
230
+ }
231
+ t.focus();
232
+ }
226
233
  function DataTableView(props) {
227
234
  const view = props.table;
228
235
  const parts = props.components ?? {};
@@ -244,21 +251,40 @@ function DataTableView(props) {
244
251
  const sortBy = state.sorting?.by;
245
252
  const searchState = state.search;
246
253
  const paged = typeof view.getPageCount === "function";
247
- const loading = isInitialLoad && (LOADING.includes(status) || status === "pending" && hasAsyncSource(view));
248
- const failed = isInitialLoad && status === "error";
254
+ const [retrying, setRetrying] = (0, import_react.useState)(false);
255
+ const inFlight = (0, import_react.useRef)(false);
256
+ const reloading = retrying && status === "error";
257
+ const loading = isInitialLoad && (reloading || LOADING.includes(status) || status === "pending" && hasAsyncSource(view));
258
+ const failed = isInitialLoad && status === "error" && !reloading;
249
259
  const span = Math.max(columns.length, 1);
250
260
  const tableEl = (0, import_react.useRef)(null);
251
- const keepFocus = () => {
261
+ const focusedState = () => {
252
262
  const t = tableEl.current;
253
263
  const from = document.activeElement?.closest("[data-dk-state],[data-dk-refresh]");
254
- if (t && from && t.parentElement?.contains(from)) {
255
- t.tabIndex = -1;
256
- t.focus();
257
- }
264
+ return t && from && t.parentElement?.contains(from) ? document.activeElement : null;
258
265
  };
266
+ const keepFocus = () => {
267
+ const t = tableEl.current;
268
+ if (t && focusedState()) focusTable(t);
269
+ };
270
+ const focusFrom = (0, import_react.useRef)(null);
271
+ useIsomorphicLayoutEffect(() => {
272
+ const from = focusFrom.current;
273
+ const t = tableEl.current;
274
+ focusFrom.current = null;
275
+ if (!from || !t || from.isConnected) return;
276
+ const now = document.activeElement;
277
+ if (now === null || now === document.body) focusTable(t);
278
+ });
259
279
  const retryLoad = () => {
260
- keepFocus();
261
- void view.refetch();
280
+ if (inFlight.current) return;
281
+ inFlight.current = true;
282
+ focusFrom.current = focusedState();
283
+ setRetrying(true);
284
+ void view.refetch().finally(() => {
285
+ inFlight.current = false;
286
+ setRetrying(false);
287
+ });
262
288
  };
263
289
  const server = paged && serverPaged(view);
264
290
  const pager = paged ? pages(view, state.pagination, rowModel.filteredCount, server) : null;
@@ -285,7 +311,7 @@ function DataTableView(props) {
285
311
  const ErrorState = parts.Error ?? DefaultError;
286
312
  let body;
287
313
  if (loading) {
288
- body = stateRow(span, "loading", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loading, { status }));
314
+ body = stateRow(span, "loading", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Loading, { status: reloading ? "fetching" : status }));
289
315
  } else if (failed) {
290
316
  body = stateRow(span, "error", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ErrorState, { status, reason: "load", retry: retryLoad }));
291
317
  } else if (rows.length === 0) {
@@ -325,7 +351,7 @@ function DataTableView(props) {
325
351
  "data-datakable": "",
326
352
  "data-status": status,
327
353
  "data-initial-load": isInitialLoad ? "true" : "false",
328
- "aria-busy": BUSY.includes(status) ? "true" : void 0,
354
+ "aria-busy": reloading || BUSY.includes(status) ? "true" : void 0,
329
355
  children: [
330
356
  searchState && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-dk-search": "", "data-status": searchState.status, children: part(table, "SearchInput", parts.SearchInput, DefaultSearchInput, {
331
357
  value: searchState.input,
@@ -335,7 +361,7 @@ function DataTableView(props) {
335
361
  onClear: () => view.clearSearch?.(),
336
362
  label: named ? `Search ${named}` : "Search"
337
363
  }) }),
338
- !loading && !failed && status !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshIndicator, { status, retry: retryLoad }),
364
+ !loading && !failed && status !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshIndicator, { status: reloading ? "fetching" : status, retry: retryLoad }),
339
365
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { ref: tableEl, children: [
340
366
  props.caption != null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("caption", { children: props.caption }),
341
367
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", { children: columns.map((col) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n boundaryDiagnostics,\n defaultFormat,\n deriveColumns,\n describeReturn,\n emitTableDiagnostic,\n type InvalidRowsMode,\n keepDiagnostics,\n matchesSlot,\n pipelineDiagnostics,\n type RowIssue,\n type RowModelStatus,\n type SearchStatus,\n slotDiagnostics,\n type TableSchema,\n type TableState,\n} from '@datakable/core'\nimport {\n Component,\n type ComponentType,\n type CSSProperties,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react'\nimport {\n cellSlot,\n invalidCellSlot,\n registerRenderOperations,\n renderDiagnostics,\n} from './render-codes'\nimport { type UseDataTableOptions, useDataTable } from './use-data-table'\n\n// The codes this module emits (bundlers keep the definitions; see core's `keepDiagnostics`).\nkeepDiagnostics(renderDiagnostics, boundaryDiagnostics, slotDiagnostics, pipelineDiagnostics)\n\n// The ops its boundaries stand for (§3.4: `render:table`, `render:cell`). Registered at import:\n// the dist is one file per module (T37), so hook-only bundles (`useDataTable` without\n// `<DataTable />`) never include this module, and this call ships only with `<DataTable />`.\nregisterRenderOperations()\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n// --- public types --------------------------------------------------------------------------------\n\n/** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */\nexport interface SearchInputProps {\n /** `state.search.input` (updates as the user types). */\n value: string\n /** `state.search.status`: `pending` while a debounce waits, `searching` while a request runs. */\n status: SearchStatus\n /** `setSearch(value)`. */\n onChange(value: string): void\n /** `flushSearch()` (Enter). */\n onSubmit(): void\n /** `clearSearch()` (Esc). */\n onClear(): void\n /** The input's accessible name: `'Search <caption>'` with a text `caption`, else `'Search'`. */\n label: string\n}\n\n/** Props of `components.Pagination` (the pagination feature's state and API). */\nexport interface PaginationProps {\n pageIndex: number\n pageSize: number\n pageCount: number\n canPrev: boolean\n canNext: boolean\n prev(): void\n next(): void\n setPageIndex(index: number): void\n setPageSize(size: number): void\n /** The pager's accessible name: `'<caption> pagination'` with a text `caption`, else `'Pagination'`. */\n label: string\n}\n\n/** Props of `components.Empty`: shown when the table has loaded and has no rows to show. */\nexport interface EmptyProps {\n /** `true` when there is data but filters / search removed every row. */\n filtered: boolean\n}\n\n/** Props of `components.Loading`: the first load (`isInitialLoad`, nothing to show yet). */\nexport interface LoadingProps {\n status: RowModelStatus\n}\n\n/** Props of `components.Error`: the first load failed, or the body failed to render. */\nexport interface ErrorProps {\n status: RowModelStatus\n /**\n * `'load'`: `status === 'error'` on the first load. `'render'`: a component in the body outside\n * the cells threw (a component inside a cell renders `⚠` in that cell only).\n */\n reason: 'load' | 'render'\n /** `'load'`: `refetch()`. `'render'`: renders the body again. */\n retry(): void\n}\n\n/** `<DataTable components={...} />`: replaces the default parts (unstyled, `data-*` hooks only). */\nexport interface DataTableComponents {\n SearchInput?: ComponentType<SearchInputProps>\n Pagination?: ComponentType<PaginationProps>\n Empty?: ComponentType<EmptyProps>\n Loading?: ComponentType<LoadingProps>\n Error?: ComponentType<ErrorProps>\n}\n\n/** What `<DataTable table={...} />` reads: the value `useDataTable` returns. */\nexport interface DataTableSource {\n readonly state: TableState\n readonly rowModel: {\n readonly rows: readonly DataTableRow[]\n readonly filteredCount: number\n readonly totalCount: number\n readonly status: RowModelStatus\n readonly isInitialLoad: boolean\n }\n getOptions(): { readonly columns?: readonly unknown[] | undefined }\n getData(): readonly unknown[]\n refetch(): Promise<unknown>\n}\n\n/** The part of a `Row` (§6.6) `<DataTable />` renders from. */\ninterface DataTableRow {\n readonly key: string | number\n readonly index: number\n readonly original: unknown\n readonly valid: boolean\n readonly issues: readonly RowIssue[]\n getValue(id: string): unknown\n getCellIssues(id: string): readonly RowIssue[]\n}\n\n/** `<DataTable />`'s own props, next to `table` or the `useDataTable` options. */\nexport interface DataTableOwnProps {\n components?: DataTableComponents | undefined\n caption?: ReactNode\n}\n\n/**\n * `<DataTable table={useDataTable(...)} />`, or `<DataTable data={rows} />` with the\n * `useDataTable` options as props (zero-config: columns derived from the data).\n */\nexport type DataTableProps<\n T = unknown,\n Sch = undefined,\n M extends InvalidRowsMode = InvalidRowsMode,\n> = DataTableOwnProps &\n (\n | { table: DataTableSource }\n | (UseDataTableOptions<T, TableState, Sch, M> & {\n features?: readonly AnyFeature[]\n table?: undefined\n })\n )\n\n// --- component -----------------------------------------------------------------------------------\n\n/**\n * The zero-config table (§10). Renders what the installed features provide: sort buttons with\n * `aria-sort`, a search input bound to `input` (Enter = `flushSearch`, Esc = `clearSearch`),\n * pagination, and the Loading / Error / Empty states from `status` + `isInitialLoad` (§6.6).\n * Unstyled: style it through the `data-*` hooks (`data-status`, `data-initial-load`,\n * `data-invalid`, `data-sort`, …) or replace parts with `components`.\n *\n * `@datakable/react`'s `DataTable` installs no features with `data`; `datakable`'s installs the\n * default preset.\n */\nexport function DataTable<\n T,\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(props: DataTableProps<T, Sch, M>): ReactNode\nexport function DataTable(\n props: DataTableOwnProps & { table?: DataTableSource | undefined },\n): ReactNode {\n if (props.table !== undefined) {\n return (\n <DataTableView table={props.table} components={props.components} caption={props.caption} />\n )\n }\n return <ZeroConfig {...(props as DataTableOwnProps & { table?: undefined })} />\n}\n\nfunction ZeroConfig(props: DataTableOwnProps & { table?: undefined }) {\n const { components, caption, table: _, ...options } = props\n const view = useDataTable(options as never) as unknown as DataTableSource\n return <DataTableView table={view} components={components} caption={caption} />\n}\n\n/** Loose access to the installed features' APIs (the table is typed per feature set). */\ntype Api = DataTableSource & {\n toggleSort?(id: string, opts?: { multi?: boolean }): void\n setSearch?(q: string): Promise<unknown>\n flushSearch?(): Promise<unknown>\n clearSearch?(): void\n setPageIndex?(i: number): void\n setPageSize?(n: number): void\n nextPage?(): void\n prevPage?(): void\n getPageCount?(): number\n canNextPage?(): boolean\n canPrevPage?(): boolean\n}\n\n/** The column fields `<DataTable />` reads (types are checked where the columns are written). */\ninterface ColumnLike {\n key?: unknown\n id?: unknown\n header?: unknown\n sortable?: unknown\n cell?: (ctx: { row: unknown; value: unknown }) => ReactNode\n format?: (value: unknown) => unknown\n invalidCell?: (ctx: {\n original: unknown\n value: unknown\n issues: readonly RowIssue[]\n }) => ReactNode\n}\n\ninterface Column {\n readonly def: ColumnLike\n readonly index: number\n readonly id: string\n readonly header: ReactNode\n}\n\n/** A cell callback that threw or broke its contract during this render (reported after commit). */\ninterface Failure {\n slot: string\n column: string\n row: number\n error?: unknown\n /** Bad return: what the contract expects and the type received. */\n expected?: string\n received?: string\n /** A value the default formatter cannot render (`DK_UNRENDERABLE_VALUE`): its type. */\n lost?: string\n index?: number\n}\n\nconst WARN = '⚠'\n/** A failed cell's content: the `⚠` with its text alternative (#60). One element for every cell. */\nconst FAILED = (\n <span role=\"img\" aria-label=\"Could not display this value\">\n {WARN}\n </span>\n)\nconst BUSY: readonly RowModelStatus[] = ['validating', 'pending', 'searching', 'fetching']\nconst LOADING: readonly RowModelStatus[] = ['validating', 'searching', 'fetching']\n\n/**\n * The table loads its rows asynchronously: a `fetcher`, or a feature with a `searchFn` (its\n * `defineOptions` values). With nothing applied yet, its `'pending'` is a load waiting to start\n * (deferred until the client, §7.2), so `<DataTable />` shows Loading — also in the server HTML.\n */\nfunction hasAsyncSource(table: DataTableSource): boolean {\n const options = table.getOptions() as { fetcher?: unknown; features?: unknown }\n if (typeof options.fetcher === 'function') return true\n if (!Array.isArray(options.features)) return false\n for (const f of options.features as readonly {\n options?: { values?: { searchFn?: unknown } }\n }[]) {\n if (typeof f?.options?.values?.searchFn === 'function') return true\n }\n return false\n}\n\nfunction resolveColumns(defs: readonly unknown[]): Column[] {\n const out: Column[] = []\n for (let index = 0; index < defs.length; index++) {\n const def = defs[index] as ColumnLike | null | undefined\n if (def === null || typeof def !== 'object') continue\n const id = typeof def.key === 'string' ? def.key : def.id\n if (typeof id !== 'string') continue\n out.push({ def, index, id, header: typeof def.header === 'string' ? def.header : id })\n }\n return out\n}\n\nconst segment = (s: PropertyKey | { readonly key: PropertyKey }) =>\n String(typeof s === 'object' ? s.key : s)\n\n/**\n * The redacted issue text for `title` (§5.1): the issue paths only. Schema messages embed the\n * received value, so they are never shown.\n */\nfunction issueTitle(issues: readonly RowIssue[]): string {\n const paths = new Set<string>()\n for (const i of issues) paths.add(i.path?.length ? i.path.map(segment).join('.') : '(row)')\n return `Invalid: ${[...paths].join(', ')}`\n}\n\n/** The table behind a `useDataTable` view (its prototype), for reporting diagnostics. */\nconst tableOf = (view: object): object =>\n Object.hasOwn(view, 'rowModel') ? (Object.getPrototypeOf(view) as object) : view\n\nfunction report(table: object, failures: readonly Failure[]) {\n const bySlot = new Map<string, Failure[]>()\n for (const f of failures) {\n const k = `${f.slot}\\0${f.lost ? '' : f.expected === undefined ? 'throw' : 'return'}`\n const list = bySlot.get(k)\n if (list) list.push(f)\n else bySlot.set(k, [f])\n }\n for (const list of bySlot.values()) {\n const first = list[0] as Failure\n const rows = list.slice(0, 3).map((f) => f.row)\n const fallback = 'cells-warn' // prose key: 'those cells rendered ⚠'\n try {\n if (first.lost !== undefined) {\n // Deduped by the table per column and data reference, like the column cache's report.\n emitTableDiagnostic(table, 'DK_UNRENDERABLE_VALUE', {\n column: first.column,\n index: first.index as number,\n count: list.length,\n rows,\n valueType: first.lost,\n })\n } else if (first.expected === undefined) {\n const e = first.error\n emitTableDiagnostic(\n table,\n 'DK_CALLBACK_FAILED',\n {\n slot: first.slot,\n column: first.column,\n rows,\n count: list.length,\n fallback,\n ...(e instanceof Error ? { errorName: e.name } : {}),\n },\n { cause: e },\n )\n } else if (process.env.NODE_ENV !== 'production') {\n emitTableDiagnostic(table, 'DK_CALLBACK_BAD_RETURN', {\n slot: first.slot,\n column: first.column,\n expected: first.expected,\n received: first.received ?? 'undefined',\n count: list.length,\n rows,\n fallback,\n })\n }\n } catch {\n // Not a table made by createTable (a hand-made `table` prop): nothing to report to.\n }\n }\n}\n\n/**\n * The value `defaultFormat` could not render in the current cell (an object, array or function,\n * never `undefined`). One module-level callback: no closure per cell.\n */\nlet lost: unknown\nconst onLost = (v: unknown) => {\n lost = v\n}\n\n/**\n * Renders one cell's content; a throwing or contract-breaking callback renders `⚠`. An object\n * returned by `cell` / `invalidCell` (an element, an array) may hold components that throw while\n * React renders them, so it gets its own boundary; primitives cannot, so they get none (no cost).\n */\nfunction cellContent(\n col: Column,\n row: DataTableRow,\n failures: Failure[],\n table: object,\n): ReactNode {\n const def = col.def\n const value = row.getValue(col.id)\n const issues = row.valid ? undefined : row.getCellIssues(col.id)\n let slot = 'cell'\n try {\n if (issues !== undefined && issues.length > 0) {\n if (def.invalidCell) {\n slot = 'invalidCell'\n const out = def.invalidCell({ original: row.original, value, issues })\n if (matchesSlot(invalidCellSlot, out)) return guard(out, table, col, row, 'invalidCell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n return (\n <>\n {defaultFormat(value)}{' '}\n <span data-dk-invalid-marker=\"\" aria-hidden=\"true\">\n {WARN}\n </span>\n </>\n )\n }\n if (def.cell) {\n const out = def.cell({ row: row.original, value })\n if (matchesSlot(cellSlot, out)) return guard(out, table, col, row, 'cell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n if (def.format) {\n slot = 'format'\n const out = def.format(value)\n if (typeof out === 'string') return out\n bad(failures, col, row, slot, 'a string', out)\n return defaultFormat(value)\n }\n const text = defaultFormat(value, onLost)\n if (lost !== undefined) {\n const { id: column, index } = col\n const type = Array.isArray(lost) ? 'array' : typeof lost\n failures.push({ slot: `columns[${index}]`, column, index, row: row.index, lost: type })\n lost = undefined\n }\n return text\n } catch (error) {\n failures.push({ slot: `columns[${col.index}].${slot}`, column: col.id, row: row.index, error })\n return FAILED\n }\n}\n\n/** Wraps object content in a per-cell boundary (`render:cell`); primitives pass through as-is. */\nfunction guard(\n out: ReactNode,\n table: object,\n col: Column,\n row: DataTableRow,\n slot: 'cell' | 'invalidCell',\n): ReactNode {\n if (typeof out !== 'object' || out === null) return out\n return (\n <Boundary\n table={table}\n col={col}\n slot={slot}\n row={row.index}\n resetKey={row.original}\n fallback={failedCell}\n >\n {out}\n </Boundary>\n )\n}\n\nfunction bad(\n failures: Failure[],\n col: Column,\n row: DataTableRow,\n slot: string,\n expected: string,\n out: unknown,\n): ReactNode {\n failures.push({\n slot: `columns[${col.index}].${slot}`,\n column: col.id,\n row: row.index,\n expected,\n received: describeReturn(out),\n })\n return FAILED\n}\n\ntype Page = { pageIndex: number; pageSize: number }\n\n/** Visually hidden, still read by screen readers (inline: the table ships no CSS). */\nconst HIDDEN: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n}\n\nconst serverPaged = (view: Api) =>\n (view.getOptions() as { features?: readonly { stage?: string; mode?: string }[] }).features?.some(\n (f) => f?.stage === 'paginate' && f.mode === 'server',\n ) === true\n\n/**\n * The pager of the rendered snapshot, like the pagination API computes it live: the hydrating\n * render must match the server HTML even when the table changed meanwhile (#16). Client mode\n * pages over the row model's `filteredCount`; server mode over the fetched `rowCount`, which only\n * the table knows (and no render changes).\n */\nfunction pages(view: Api, page: Page, count: number, server: boolean) {\n if (server) {\n return {\n ...page,\n pageCount: view.getPageCount?.() ?? 0,\n canPrev: view.canPrevPage?.() ?? false,\n canNext: view.canNextPage?.() ?? false,\n }\n }\n const pageCount = Math.ceil(count / page.pageSize)\n const index = Math.min(page.pageIndex, Math.max(pageCount - 1, 0))\n return { ...page, pageCount, canPrev: index > 0, canNext: index + 1 < pageCount }\n}\n\nconst ariaSort = (dir: 'asc' | 'desc' | false) =>\n dir === 'asc' ? 'ascending' : dir === 'desc' ? 'descending' : 'none'\n\nfunction DataTableView(props: {\n table: DataTableSource\n components: DataTableComponents | undefined\n caption: ReactNode\n}) {\n const view = props.table as Api\n const parts = props.components ?? {}\n const { state, rowModel } = view\n const { rows, status, isInitialLoad } = rowModel\n const defs = view.getOptions().columns\n const data = view.getData()\n // Zero-config columns follow the data; given columns follow their reference (§10).\n const derivedFrom = defs === undefined ? data : undefined\n const columns = useMemo(\n () => resolveColumns(defs ?? (derivedFrom ? deriveColumns(derivedFrom) : [])),\n [defs, derivedFrom],\n )\n const failures: Failure[] = []\n const table = tableOf(view)\n // After commit, never during render: a sink may set state.\n useIsomorphicLayoutEffect(() => {\n if (failures.length > 0) report(table, failures)\n })\n\n const sortable = typeof view.toggleSort === 'function'\n const sortBy = (state.sorting as { by: readonly { id: string; desc?: boolean }[] } | undefined)\n ?.by\n const searchState = state.search as { input: string; status: SearchStatus } | undefined\n const paged = typeof view.getPageCount === 'function'\n // Loading (§6.6, §10): nothing to show yet and rows on their way — in flight, or deferred async\n // work that has not started (SSR, §7.2: 'pending').\n const loading =\n isInitialLoad && (LOADING.includes(status) || (status === 'pending' && hasAsyncSource(view)))\n const failed = isInitialLoad && status === 'error'\n const span = Math.max(columns.length, 1)\n const tableEl = useRef<HTMLTableElement>(null)\n /**\n * Retry unmounts the focused Retry button (Error → Loading → rows, or the refresh error): focus\n * the table first, else it falls to `<body>` (#56). Only when focus is in a state row or the\n * refresh indicator, so a retry called from elsewhere leaves focus alone.\n */\n const keepFocus = () => {\n const t = tableEl.current\n const from = document.activeElement?.closest('[data-dk-state],[data-dk-refresh]')\n if (t && from && t.parentElement?.contains(from)) {\n t.tabIndex = -1\n t.focus()\n }\n }\n const retryLoad = () => {\n keepFocus()\n void view.refetch()\n }\n const server = paged && serverPaged(view)\n const pager = paged ? pages(view, state.pagination as Page, rowModel.filteredCount, server) : null\n\n // Status messages (#54): one polite live region, in the markup from the first render (a region\n // inserted with its text is often not announced). Written after commit, only when the message\n // changes, so the first render (and the hydrating one) matches the server HTML.\n // Worded unlike the visible parts (\"No rows\", \"Searching…\"), so a text query finds one element.\n const n = rowModel.filteredCount\n const count = `${n} row${n === 1 ? '' : 's'}`\n const page = pager ? `${pager.pageIndex + 1} of ${Math.max(pager.pageCount, 1)}` : ''\n let said = ''\n if (searchState?.status === 'pending' || searchState?.status === 'searching') {\n said = 'Searching rows…'\n } else if (status === 'idle' && !loading) {\n // Server mode: `filteredCount` is the page's rows, so only the page (or \"0 rows\").\n said = server && n ? `Page ${page}` : page ? `${count}, page ${page}` : count\n }\n const liveEl = useRef<HTMLDivElement>(null)\n const saidBefore = useRef<string | null>(null)\n useEffect(() => {\n const el = liveEl.current\n if (el && saidBefore.current !== null && saidBefore.current !== said) el.textContent = said\n saidBefore.current = said\n })\n\n // A text caption names the search box and the pager, so two tables get distinct names (#59).\n const cap = props.caption\n const named = typeof cap === 'string' || typeof cap === 'number' ? `${cap}` : ''\n\n const Empty = parts.Empty ?? DefaultEmpty\n const Loading = parts.Loading ?? DefaultLoading\n const ErrorState = parts.Error ?? DefaultError\n\n let body: ReactNode\n if (loading) {\n body = stateRow(span, 'loading', <Loading status={status} />)\n } else if (failed) {\n body = stateRow(span, 'error', <ErrorState status={status} reason=\"load\" retry={retryLoad} />)\n } else if (rows.length === 0) {\n body = stateRow(span, 'empty', <Empty filtered={rowModel.totalCount > 0} />)\n } else {\n body = rows.map((row) => {\n const valid = row.valid\n return (\n <tr\n key={row.key}\n data-invalid={valid ? undefined : 'true'}\n aria-invalid={valid ? undefined : 'true'}\n title={valid ? undefined : issueTitle(row.issues)}\n >\n {columns.map((col) => {\n const issues = valid ? undefined : row.getCellIssues(col.id)\n const broken = issues !== undefined && issues.length > 0\n return (\n <td\n key={col.index}\n data-invalid={broken ? 'true' : undefined}\n aria-invalid={broken ? 'true' : undefined}\n title={broken ? issueTitle(issues) : undefined}\n >\n {cellContent(col, row, failures, table)}\n </td>\n )\n })}\n </tr>\n )\n })\n }\n\n // The server runs no effects: report now (setting state is a no-op there).\n if (typeof window === 'undefined' && failures.length > 0) report(table, failures)\n\n return (\n <div\n data-datakable=\"\"\n data-status={status}\n data-initial-load={isInitialLoad ? 'true' : 'false'}\n aria-busy={BUSY.includes(status) ? 'true' : undefined}\n >\n {searchState && (\n <div data-dk-search=\"\" data-status={searchState.status}>\n {part(table, 'SearchInput', parts.SearchInput, DefaultSearchInput, {\n value: searchState.input,\n status: searchState.status,\n onChange: (q) => void view.setSearch?.(q),\n onSubmit: () => void view.flushSearch?.(),\n onClear: () => view.clearSearch?.(),\n label: named ? `Search ${named}` : 'Search',\n })}\n </div>\n )}\n {!loading && !failed && status !== 'idle' && (\n <RefreshIndicator status={status} retry={retryLoad} />\n )}\n <table ref={tableEl}>\n {props.caption != null && <caption>{props.caption}</caption>}\n <thead>\n <tr>\n {columns.map((col) => {\n const canSort = sortable && col.def.sortable !== false\n // From the rendered state, not the live table (the hydrating render, #16).\n const e = canSort ? sortBy?.find((x) => x.id === col.id) : undefined\n const dir = e ? (e.desc ? 'desc' : 'asc') : false\n return (\n <th\n key={col.index}\n scope=\"col\"\n aria-sort={canSort ? ariaSort(dir) : undefined}\n data-sort={dir || undefined}\n >\n {canSort ? (\n <button\n type=\"button\"\n onClick={(e) => view.toggleSort?.(col.id, { multi: e.shiftKey })}\n >\n {col.header}\n <span data-dk-sort-indicator=\"\" aria-hidden=\"true\">\n {dir === 'asc' ? ' ▲' : dir === 'desc' ? ' ▼' : ''}\n </span>\n </button>\n ) : (\n col.header\n )}\n </th>\n )\n })}\n </tr>\n </thead>\n <tbody>\n <Boundary\n table={table}\n resetKey={rowModel}\n fallback={(retry) =>\n stateRow(\n span,\n 'error',\n <ErrorState\n status={status}\n reason=\"render\"\n retry={() => {\n keepFocus()\n retry()\n }}\n />,\n )\n }\n >\n {body}\n </Boundary>\n </tbody>\n </table>\n {pager &&\n part(table, 'Pagination', parts.Pagination, DefaultPagination, {\n ...pager,\n prev: () => view.prevPage?.(),\n next: () => view.nextPage?.(),\n setPageIndex: (i) => view.setPageIndex?.(i),\n setPageSize: (n) => view.setPageSize?.(n),\n label: named ? `${named} pagination` : 'Pagination',\n })}\n <div aria-live=\"polite\" style={HIDDEN} ref={liveEl} />\n </div>\n )\n}\n\n/**\n * A search / pager part (outside the body): a custom one that throws is replaced by the default\n * part (`DK_RENDER_FAILED` at `components.<name>`) until another component is passed.\n */\nfunction part<P extends object>(\n table: object,\n name: 'SearchInput' | 'Pagination',\n Custom: ComponentType<P> | undefined,\n Default: ComponentType<P>,\n props: P,\n): ReactNode {\n if (!Custom) return <Default {...props} />\n return (\n <Boundary\n table={table}\n slot={`components.${name}`}\n resetKey={Custom}\n fallback={() => <Default {...props} />}\n >\n <Custom {...props} />\n </Boundary>\n )\n}\n\nfunction stateRow(span: number, kind: string, content: ReactNode) {\n return (\n <tr data-dk-state={kind}>\n <td colSpan={span}>{content}</td>\n </tr>\n )\n}\n\n// --- error boundaries (DK_RENDER_FAILED) ---------------------------------------------------------\n\ninterface BoundaryProps {\n table: object\n /**\n * A part outside the body: `components.SearchInput` (reported as the slot). A cell boundary:\n * `cell` / `invalidCell` (reported as `columns[<index>].<slot>`).\n */\n slot?: string\n /** A cell boundary (`render:cell`): the cell's column. A new `def` renders a failed cell again. */\n col?: Column\n /** A cell boundary: the row's index in the data (`row.index`). */\n row?: number\n /** A new value (the next row model; a cell's row data) renders the children again. */\n resetKey: unknown\n fallback(retry: () => void): ReactNode\n children: ReactNode\n}\n\ninterface BoundaryState {\n failed: boolean\n key: unknown\n def: ColumnLike | undefined\n}\n\n/**\n * Catches a component that throws (`DK_RENDER_FAILED`) and renders `fallback` instead; the rest of\n * the table keeps working. Three uses: the body outside any cell (`render:table`, §10: a\n * `components.Empty` / `Loading` / `Error` part) shows the Error state; a custom search / pager\n * part (`render:table` at `components.<name>`) is replaced by the default part; and one cell\n * (`render:cell`, §3.4, with `col`): a component returned by `cell` / `invalidCell` renders `⚠` in\n * that cell only (deduped per column). A cell boundary only wraps object content (see `guard`).\n */\nclass Boundary extends Component<BoundaryProps, BoundaryState> {\n override state: BoundaryState = {\n failed: false,\n key: this.props.resetKey,\n def: this.props.col?.def,\n }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n static getDerivedStateFromProps(props: BoundaryProps, state: BoundaryState) {\n const def = props.col?.def\n return props.resetKey === state.key && def === state.def\n ? null\n : { failed: false, key: props.resetKey, def }\n }\n\n override componentDidCatch(error: unknown) {\n const { table, col, slot, row } = this.props\n try {\n emitTableDiagnostic(\n table,\n 'DK_RENDER_FAILED',\n {\n op: col ? 'render:cell' : 'render:table',\n ...(slot ? { slot: col ? `columns[${col.index}].${slot}` : slot } : {}),\n ...(col ? { column: col.id, row: row as number } : {}),\n ...(error instanceof Error ? { errorName: error.name } : {}),\n },\n { cause: error },\n )\n } catch {\n // Not a table made by createTable: nothing to report to.\n }\n }\n\n retry = () => this.setState({ failed: false })\n\n override render() {\n return this.state.failed ? this.props.fallback(this.retry) : this.props.children\n }\n}\n\n/** A failed cell's fallback (one function for every cell boundary: no closure per cell). */\nconst failedCell = () => FAILED\n\n// --- default parts (unstyled) --------------------------------------------------------------------\n\nfunction DefaultSearchInput({\n value,\n status,\n onChange,\n onSubmit,\n onClear,\n label,\n}: SearchInputProps) {\n return (\n <>\n <input\n type=\"search\"\n aria-label={label}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSubmit()\n else if (e.key === 'Escape') onClear()\n }}\n />\n {(status === 'pending' || status === 'searching') && (\n // Decorative: the live region says \"Searching…\" (an empty status announces nothing).\n <span data-dk-spinner=\"\" aria-hidden=\"true\" />\n )}\n </>\n )\n}\n\n/**\n * `aria-disabled`, not `disabled`, at the first / last page: a disabled button loses focus (to\n * `<body>`) the moment paging makes it unavailable (#55).\n */\nfunction DefaultPagination(p: PaginationProps) {\n return (\n <nav aria-label={p.label} data-dk-pagination=\"\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n aria-disabled={!p.canPrev || undefined}\n onClick={p.canPrev ? p.prev : undefined}\n >\n ‹\n </button>\n <span data-dk-page=\"\">\n Page {p.pageIndex + 1} of {Math.max(p.pageCount, 1)}\n </span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n aria-disabled={!p.canNext || undefined}\n onClick={p.canNext ? p.next : undefined}\n >\n ›\n </button>\n </nav>\n )\n}\n\nconst DefaultEmpty = ({ filtered }: EmptyProps) => <>{filtered ? 'No matching rows' : 'No rows'}</>\n\nconst DefaultLoading = (_: LoadingProps) => <span role=\"status\">Loading…</span>\n\nfunction DefaultError({ reason, retry }: ErrorProps) {\n return (\n <div role=\"alert\">\n {reason === 'load' ? 'Could not load the rows.' : 'Could not display the rows.'}{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n}\n\n/** Over stale rows (§6.6): the table is busy, or a later update failed. */\nfunction RefreshIndicator({ status, retry }: { status: RowModelStatus; retry(): void }) {\n if (status === 'error') {\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"alert\">\n Could not refresh; showing the previous rows.{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n }\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"status\">\n Updating…\n </div>\n )\n}\n"],"mappings":"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","names":["e","n"]}
1
+ {"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n boundaryDiagnostics,\n defaultFormat,\n deriveColumns,\n describeReturn,\n emitTableDiagnostic,\n type InvalidRowsMode,\n keepDiagnostics,\n matchesSlot,\n pipelineDiagnostics,\n type RowIssue,\n type RowModelStatus,\n type SearchStatus,\n slotDiagnostics,\n type TableSchema,\n type TableState,\n} from '@datakable/core'\nimport {\n Component,\n type ComponentType,\n type CSSProperties,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n cellSlot,\n invalidCellSlot,\n registerRenderOperations,\n renderDiagnostics,\n} from './render-codes'\nimport { type UseDataTableOptions, useDataTable } from './use-data-table'\n\n// The codes this module emits (bundlers keep the definitions; see core's `keepDiagnostics`).\nkeepDiagnostics(renderDiagnostics, boundaryDiagnostics, slotDiagnostics, pipelineDiagnostics)\n\n// The ops its boundaries stand for (§3.4: `render:table`, `render:cell`). Registered at import:\n// the dist is one file per module (T37), so hook-only bundles (`useDataTable` without\n// `<DataTable />`) never include this module, and this call ships only with `<DataTable />`.\nregisterRenderOperations()\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n// --- public types --------------------------------------------------------------------------------\n\n/** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */\nexport interface SearchInputProps {\n /** `state.search.input` (updates as the user types). */\n value: string\n /** `state.search.status`: `pending` while a debounce waits, `searching` while a request runs. */\n status: SearchStatus\n /** `setSearch(value)`. */\n onChange(value: string): void\n /** `flushSearch()` (Enter). */\n onSubmit(): void\n /** `clearSearch()` (Esc). */\n onClear(): void\n /** The input's accessible name: `'Search <caption>'` with a text `caption`, else `'Search'`. */\n label: string\n}\n\n/** Props of `components.Pagination` (the pagination feature's state and API). */\nexport interface PaginationProps {\n pageIndex: number\n pageSize: number\n pageCount: number\n canPrev: boolean\n canNext: boolean\n prev(): void\n next(): void\n setPageIndex(index: number): void\n setPageSize(size: number): void\n /** The pager's accessible name: `'<caption> pagination'` with a text `caption`, else `'Pagination'`. */\n label: string\n}\n\n/** Props of `components.Empty`: shown when the table has loaded and has no rows to show. */\nexport interface EmptyProps {\n /** `true` when there is data but filters / search removed every row. */\n filtered: boolean\n}\n\n/** Props of `components.Loading`: the first load (`isInitialLoad`, nothing to show yet). */\nexport interface LoadingProps {\n status: RowModelStatus\n}\n\n/** Props of `components.Error`: the first load failed, or the body failed to render. */\nexport interface ErrorProps {\n status: RowModelStatus\n /**\n * `'load'`: `status === 'error'` on the first load. `'render'`: a component in the body outside\n * the cells threw (a component inside a cell renders `⚠` in that cell only).\n */\n reason: 'load' | 'render'\n /** `'load'`: `refetch()`. `'render'`: renders the body again. */\n retry(): void\n}\n\n/** `<DataTable components={...} />`: replaces the default parts (unstyled, `data-*` hooks only). */\nexport interface DataTableComponents {\n SearchInput?: ComponentType<SearchInputProps>\n Pagination?: ComponentType<PaginationProps>\n Empty?: ComponentType<EmptyProps>\n Loading?: ComponentType<LoadingProps>\n Error?: ComponentType<ErrorProps>\n}\n\n/** What `<DataTable table={...} />` reads: the value `useDataTable` returns. */\nexport interface DataTableSource {\n readonly state: TableState\n readonly rowModel: {\n readonly rows: readonly DataTableRow[]\n readonly filteredCount: number\n readonly totalCount: number\n readonly status: RowModelStatus\n readonly isInitialLoad: boolean\n }\n getOptions(): { readonly columns?: readonly unknown[] | undefined }\n getData(): readonly unknown[]\n refetch(): Promise<unknown>\n}\n\n/** The part of a `Row` (§6.6) `<DataTable />` renders from. */\ninterface DataTableRow {\n readonly key: string | number\n readonly index: number\n readonly original: unknown\n readonly valid: boolean\n readonly issues: readonly RowIssue[]\n getValue(id: string): unknown\n getCellIssues(id: string): readonly RowIssue[]\n}\n\n/** `<DataTable />`'s own props, next to `table` or the `useDataTable` options. */\nexport interface DataTableOwnProps {\n components?: DataTableComponents | undefined\n caption?: ReactNode\n}\n\n/**\n * `<DataTable table={useDataTable(...)} />`, or `<DataTable data={rows} />` with the\n * `useDataTable` options as props (zero-config: columns derived from the data).\n */\nexport type DataTableProps<\n T = unknown,\n Sch = undefined,\n M extends InvalidRowsMode = InvalidRowsMode,\n> = DataTableOwnProps &\n (\n | { table: DataTableSource }\n | (UseDataTableOptions<T, TableState, Sch, M> & {\n features?: readonly AnyFeature[]\n table?: undefined\n })\n )\n\n// --- component -----------------------------------------------------------------------------------\n\n/**\n * The zero-config table (§10). Renders what the installed features provide: sort buttons with\n * `aria-sort`, a search input bound to `input` (Enter = `flushSearch`, Esc = `clearSearch`),\n * pagination, and the Loading / Error / Empty states from `status` + `isInitialLoad` (§6.6).\n * Unstyled: style it through the `data-*` hooks (`data-status`, `data-initial-load`,\n * `data-invalid`, `data-sort`, …) or replace parts with `components`.\n *\n * `@datakable/react`'s `DataTable` installs no features with `data`; `datakable`'s installs the\n * default preset.\n */\nexport function DataTable<\n T,\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(props: DataTableProps<T, Sch, M>): ReactNode\nexport function DataTable(\n props: DataTableOwnProps & { table?: DataTableSource | undefined },\n): ReactNode {\n if (props.table !== undefined) {\n return (\n <DataTableView table={props.table} components={props.components} caption={props.caption} />\n )\n }\n return <ZeroConfig {...(props as DataTableOwnProps & { table?: undefined })} />\n}\n\nfunction ZeroConfig(props: DataTableOwnProps & { table?: undefined }) {\n const { components, caption, table: _, ...options } = props\n const view = useDataTable(options as never) as unknown as DataTableSource\n return <DataTableView table={view} components={components} caption={caption} />\n}\n\n/** Loose access to the installed features' APIs (the table is typed per feature set). */\ntype Api = DataTableSource & {\n toggleSort?(id: string, opts?: { multi?: boolean }): void\n setSearch?(q: string): Promise<unknown>\n flushSearch?(): Promise<unknown>\n clearSearch?(): void\n setPageIndex?(i: number): void\n setPageSize?(n: number): void\n nextPage?(): void\n prevPage?(): void\n getPageCount?(): number\n canNextPage?(): boolean\n canPrevPage?(): boolean\n}\n\n/** The column fields `<DataTable />` reads (types are checked where the columns are written). */\ninterface ColumnLike {\n key?: unknown\n id?: unknown\n header?: unknown\n sortable?: unknown\n cell?: (ctx: { row: unknown; value: unknown }) => ReactNode\n format?: (value: unknown) => unknown\n invalidCell?: (ctx: {\n original: unknown\n value: unknown\n issues: readonly RowIssue[]\n }) => ReactNode\n}\n\ninterface Column {\n readonly def: ColumnLike\n readonly index: number\n readonly id: string\n readonly header: ReactNode\n}\n\n/** A cell callback that threw or broke its contract during this render (reported after commit). */\ninterface Failure {\n slot: string\n column: string\n row: number\n error?: unknown\n /** Bad return: what the contract expects and the type received. */\n expected?: string\n received?: string\n /** A value the default formatter cannot render (`DK_UNRENDERABLE_VALUE`): its type. */\n lost?: string\n index?: number\n}\n\nconst WARN = '⚠'\n/** A failed cell's content: the `⚠` with its text alternative (#60). One element for every cell. */\nconst FAILED = (\n <span role=\"img\" aria-label=\"Could not display this value\">\n {WARN}\n </span>\n)\nconst BUSY: readonly RowModelStatus[] = ['validating', 'pending', 'searching', 'fetching']\nconst LOADING: readonly RowModelStatus[] = ['validating', 'searching', 'fetching']\n\n/**\n * The table loads its rows asynchronously: a `fetcher`, or a feature with a `searchFn` (its\n * `defineOptions` values). With nothing applied yet, its `'pending'` is a load waiting to start\n * (deferred until the client, §7.2), so `<DataTable />` shows Loading — also in the server HTML.\n */\nfunction hasAsyncSource(table: DataTableSource): boolean {\n const options = table.getOptions() as { fetcher?: unknown; features?: unknown }\n if (typeof options.fetcher === 'function') return true\n if (!Array.isArray(options.features)) return false\n for (const f of options.features as readonly {\n options?: { values?: { searchFn?: unknown } }\n }[]) {\n if (typeof f?.options?.values?.searchFn === 'function') return true\n }\n return false\n}\n\nfunction resolveColumns(defs: readonly unknown[]): Column[] {\n const out: Column[] = []\n for (let index = 0; index < defs.length; index++) {\n const def = defs[index] as ColumnLike | null | undefined\n if (def === null || typeof def !== 'object') continue\n const id = typeof def.key === 'string' ? def.key : def.id\n if (typeof id !== 'string') continue\n out.push({ def, index, id, header: typeof def.header === 'string' ? def.header : id })\n }\n return out\n}\n\nconst segment = (s: PropertyKey | { readonly key: PropertyKey }) =>\n String(typeof s === 'object' ? s.key : s)\n\n/**\n * The redacted issue text for `title` (§5.1): the issue paths only. Schema messages embed the\n * received value, so they are never shown.\n */\nfunction issueTitle(issues: readonly RowIssue[]): string {\n const paths = new Set<string>()\n for (const i of issues) paths.add(i.path?.length ? i.path.map(segment).join('.') : '(row)')\n return `Invalid: ${[...paths].join(', ')}`\n}\n\n/** The table behind a `useDataTable` view (its prototype), for reporting diagnostics. */\nconst tableOf = (view: object): object =>\n Object.hasOwn(view, 'rowModel') ? (Object.getPrototypeOf(view) as object) : view\n\nfunction report(table: object, failures: readonly Failure[]) {\n const bySlot = new Map<string, Failure[]>()\n for (const f of failures) {\n const k = `${f.slot}\\0${f.lost ? '' : f.expected === undefined ? 'throw' : 'return'}`\n const list = bySlot.get(k)\n if (list) list.push(f)\n else bySlot.set(k, [f])\n }\n for (const list of bySlot.values()) {\n const first = list[0] as Failure\n const rows = list.slice(0, 3).map((f) => f.row)\n const fallback = 'cells-warn' // prose key: 'those cells rendered ⚠'\n try {\n if (first.lost !== undefined) {\n // Deduped by the table per column and data reference, like the column cache's report.\n emitTableDiagnostic(table, 'DK_UNRENDERABLE_VALUE', {\n column: first.column,\n index: first.index as number,\n count: list.length,\n rows,\n valueType: first.lost,\n })\n } else if (first.expected === undefined) {\n const e = first.error\n emitTableDiagnostic(\n table,\n 'DK_CALLBACK_FAILED',\n {\n slot: first.slot,\n column: first.column,\n rows,\n count: list.length,\n fallback,\n ...(e instanceof Error ? { errorName: e.name } : {}),\n },\n { cause: e },\n )\n } else if (process.env.NODE_ENV !== 'production') {\n emitTableDiagnostic(table, 'DK_CALLBACK_BAD_RETURN', {\n slot: first.slot,\n column: first.column,\n expected: first.expected,\n received: first.received ?? 'undefined',\n count: list.length,\n rows,\n fallback,\n })\n }\n } catch {\n // Not a table made by createTable (a hand-made `table` prop): nothing to report to.\n }\n }\n}\n\n/**\n * The value `defaultFormat` could not render in the current cell (an object, array or function,\n * never `undefined`). One module-level callback: no closure per cell.\n */\nlet lost: unknown\nconst onLost = (v: unknown) => {\n lost = v\n}\n\n/**\n * Renders one cell's content; a throwing or contract-breaking callback renders `⚠`. An object\n * returned by `cell` / `invalidCell` (an element, an array) may hold components that throw while\n * React renders them, so it gets its own boundary; primitives cannot, so they get none (no cost).\n */\nfunction cellContent(\n col: Column,\n row: DataTableRow,\n failures: Failure[],\n table: object,\n): ReactNode {\n const def = col.def\n const value = row.getValue(col.id)\n const issues = row.valid ? undefined : row.getCellIssues(col.id)\n let slot = 'cell'\n try {\n if (issues !== undefined && issues.length > 0) {\n if (def.invalidCell) {\n slot = 'invalidCell'\n const out = def.invalidCell({ original: row.original, value, issues })\n if (matchesSlot(invalidCellSlot, out)) return guard(out, table, col, row, 'invalidCell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n return (\n <>\n {defaultFormat(value)}{' '}\n <span data-dk-invalid-marker=\"\" aria-hidden=\"true\">\n {WARN}\n </span>\n </>\n )\n }\n if (def.cell) {\n const out = def.cell({ row: row.original, value })\n if (matchesSlot(cellSlot, out)) return guard(out, table, col, row, 'cell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n if (def.format) {\n slot = 'format'\n const out = def.format(value)\n if (typeof out === 'string') return out\n bad(failures, col, row, slot, 'a string', out)\n return defaultFormat(value)\n }\n const text = defaultFormat(value, onLost)\n if (lost !== undefined) {\n const { id: column, index } = col\n const type = Array.isArray(lost) ? 'array' : typeof lost\n failures.push({ slot: `columns[${index}]`, column, index, row: row.index, lost: type })\n lost = undefined\n }\n return text\n } catch (error) {\n failures.push({ slot: `columns[${col.index}].${slot}`, column: col.id, row: row.index, error })\n return FAILED\n }\n}\n\n/** Wraps object content in a per-cell boundary (`render:cell`); primitives pass through as-is. */\nfunction guard(\n out: ReactNode,\n table: object,\n col: Column,\n row: DataTableRow,\n slot: 'cell' | 'invalidCell',\n): ReactNode {\n if (typeof out !== 'object' || out === null) return out\n return (\n <Boundary\n table={table}\n col={col}\n slot={slot}\n row={row.index}\n resetKey={row.original}\n fallback={failedCell}\n >\n {out}\n </Boundary>\n )\n}\n\nfunction bad(\n failures: Failure[],\n col: Column,\n row: DataTableRow,\n slot: string,\n expected: string,\n out: unknown,\n): ReactNode {\n failures.push({\n slot: `columns[${col.index}].${slot}`,\n column: col.id,\n row: row.index,\n expected,\n received: describeReturn(out),\n })\n return FAILED\n}\n\ntype Page = { pageIndex: number; pageSize: number }\n\n/** Visually hidden, still read by screen readers (inline: the table ships no CSS). */\nconst HIDDEN: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n}\n\nconst serverPaged = (view: Api) =>\n (view.getOptions() as { features?: readonly { stage?: string; mode?: string }[] }).features?.some(\n (f) => f?.stage === 'paginate' && f.mode === 'server',\n ) === true\n\n/**\n * The pager of the rendered snapshot, like the pagination API computes it live: the hydrating\n * render must match the server HTML even when the table changed meanwhile (#16). Client mode\n * pages over the row model's `filteredCount`; server mode over the fetched `rowCount`, which only\n * the table knows (and no render changes).\n */\nfunction pages(view: Api, page: Page, count: number, server: boolean) {\n if (server) {\n return {\n ...page,\n pageCount: view.getPageCount?.() ?? 0,\n canPrev: view.canPrevPage?.() ?? false,\n canNext: view.canNextPage?.() ?? false,\n }\n }\n const pageCount = Math.ceil(count / page.pageSize)\n const index = Math.min(page.pageIndex, Math.max(pageCount - 1, 0))\n return { ...page, pageCount, canPrev: index > 0, canNext: index + 1 < pageCount }\n}\n\nconst ariaSort = (dir: 'asc' | 'desc' | false) =>\n dir === 'asc' ? 'ascending' : dir === 'desc' ? 'descending' : 'none'\n\n/** Focus the table for a Retry (#56); a `tabindex` added for that goes on the next blur (#88). */\nfunction focusTable(t: HTMLTableElement) {\n if (!t.hasAttribute('tabindex')) {\n t.setAttribute('tabindex', '-1')\n t.addEventListener('blur', () => t.removeAttribute('tabindex'), { once: true })\n }\n t.focus()\n}\n\nfunction DataTableView(props: {\n table: DataTableSource\n components: DataTableComponents | undefined\n caption: ReactNode\n}) {\n const view = props.table as Api\n const parts = props.components ?? {}\n const { state, rowModel } = view\n const { rows, status, isInitialLoad } = rowModel\n const defs = view.getOptions().columns\n const data = view.getData()\n // Zero-config columns follow the data; given columns follow their reference (§10).\n const derivedFrom = defs === undefined ? data : undefined\n const columns = useMemo(\n () => resolveColumns(defs ?? (derivedFrom ? deriveColumns(derivedFrom) : [])),\n [defs, derivedFrom],\n )\n const failures: Failure[] = []\n const table = tableOf(view)\n // After commit, never during render: a sink may set state.\n useIsomorphicLayoutEffect(() => {\n if (failures.length > 0) report(table, failures)\n })\n\n const sortable = typeof view.toggleSort === 'function'\n const sortBy = (state.sorting as { by: readonly { id: string; desc?: boolean }[] } | undefined)\n ?.by\n const searchState = state.search as { input: string; status: SearchStatus } | undefined\n const paged = typeof view.getPageCount === 'function'\n // Loading (§6.6, §10): nothing to show yet and rows on their way — in flight, or deferred async\n // work that has not started (SSR, §7.2: 'pending').\n // A Retry of a failed load / refresh in flight (#87). Core keeps `status: 'error'` during a\n // `refetch()` (it outranks `'fetching'`), so the view tracks the retry itself: Loading (or\n // \"Updating…\") instead of the error, `aria-busy`, and repeat retries ignored until it settles.\n const [retrying, setRetrying] = useState(false)\n const inFlight = useRef(false)\n const reloading = retrying && status === 'error'\n const loading =\n isInitialLoad &&\n (reloading || LOADING.includes(status) || (status === 'pending' && hasAsyncSource(view)))\n const failed = isInitialLoad && status === 'error' && !reloading\n const span = Math.max(columns.length, 1)\n const tableEl = useRef<HTMLTableElement>(null)\n /** The focused element in a state row or the refresh indicator, else `null`. */\n const focusedState = () => {\n const t = tableEl.current\n const from = document.activeElement?.closest('[data-dk-state],[data-dk-refresh]')\n return t && from && t.parentElement?.contains(from) ? document.activeElement : null\n }\n /**\n * Retry unmounts the focused Retry button (Error → Loading → rows, or the refresh error): focus\n * the table, else it falls to `<body>` (#56). Only when focus is in a state row or the refresh\n * indicator, so a retry called from elsewhere leaves focus alone.\n */\n const keepFocus = () => {\n const t = tableEl.current\n if (t && focusedState()) focusTable(t)\n }\n // The element focused when a load / refresh Retry was activated, until the next commit: focus\n // moves to the table only if that commit really unmounted it.\n const focusFrom = useRef<Element | null>(null)\n useIsomorphicLayoutEffect(() => {\n const from = focusFrom.current\n const t = tableEl.current\n focusFrom.current = null\n if (!from || !t || from.isConnected) return\n const now = document.activeElement\n if (now === null || now === document.body) focusTable(t)\n })\n const retryLoad = () => {\n if (inFlight.current) return\n inFlight.current = true\n focusFrom.current = focusedState()\n setRetrying(true)\n void view.refetch().finally(() => {\n inFlight.current = false\n setRetrying(false)\n })\n }\n const server = paged && serverPaged(view)\n const pager = paged ? pages(view, state.pagination as Page, rowModel.filteredCount, server) : null\n\n // Status messages (#54): one polite live region, in the markup from the first render (a region\n // inserted with its text is often not announced). Written after commit, only when the message\n // changes, so the first render (and the hydrating one) matches the server HTML.\n // Worded unlike the visible parts (\"No rows\", \"Searching…\"), so a text query finds one element.\n const n = rowModel.filteredCount\n const count = `${n} row${n === 1 ? '' : 's'}`\n const page = pager ? `${pager.pageIndex + 1} of ${Math.max(pager.pageCount, 1)}` : ''\n let said = ''\n if (searchState?.status === 'pending' || searchState?.status === 'searching') {\n said = 'Searching rows…'\n } else if (status === 'idle' && !loading) {\n // Server mode: `filteredCount` is the page's rows, so only the page (or \"0 rows\").\n said = server && n ? `Page ${page}` : page ? `${count}, page ${page}` : count\n }\n const liveEl = useRef<HTMLDivElement>(null)\n const saidBefore = useRef<string | null>(null)\n useEffect(() => {\n const el = liveEl.current\n if (el && saidBefore.current !== null && saidBefore.current !== said) el.textContent = said\n saidBefore.current = said\n })\n\n // A text caption names the search box and the pager, so two tables get distinct names (#59).\n const cap = props.caption\n const named = typeof cap === 'string' || typeof cap === 'number' ? `${cap}` : ''\n\n const Empty = parts.Empty ?? DefaultEmpty\n const Loading = parts.Loading ?? DefaultLoading\n const ErrorState = parts.Error ?? DefaultError\n\n let body: ReactNode\n if (loading) {\n body = stateRow(span, 'loading', <Loading status={reloading ? 'fetching' : status} />)\n } else if (failed) {\n body = stateRow(span, 'error', <ErrorState status={status} reason=\"load\" retry={retryLoad} />)\n } else if (rows.length === 0) {\n body = stateRow(span, 'empty', <Empty filtered={rowModel.totalCount > 0} />)\n } else {\n body = rows.map((row) => {\n const valid = row.valid\n return (\n <tr\n key={row.key}\n data-invalid={valid ? undefined : 'true'}\n aria-invalid={valid ? undefined : 'true'}\n title={valid ? undefined : issueTitle(row.issues)}\n >\n {columns.map((col) => {\n const issues = valid ? undefined : row.getCellIssues(col.id)\n const broken = issues !== undefined && issues.length > 0\n return (\n <td\n key={col.index}\n data-invalid={broken ? 'true' : undefined}\n aria-invalid={broken ? 'true' : undefined}\n title={broken ? issueTitle(issues) : undefined}\n >\n {cellContent(col, row, failures, table)}\n </td>\n )\n })}\n </tr>\n )\n })\n }\n\n // The server runs no effects: report now (setting state is a no-op there).\n if (typeof window === 'undefined' && failures.length > 0) report(table, failures)\n\n return (\n <div\n data-datakable=\"\"\n data-status={status}\n data-initial-load={isInitialLoad ? 'true' : 'false'}\n aria-busy={reloading || BUSY.includes(status) ? 'true' : undefined}\n >\n {searchState && (\n <div data-dk-search=\"\" data-status={searchState.status}>\n {part(table, 'SearchInput', parts.SearchInput, DefaultSearchInput, {\n value: searchState.input,\n status: searchState.status,\n onChange: (q) => void view.setSearch?.(q),\n onSubmit: () => void view.flushSearch?.(),\n onClear: () => view.clearSearch?.(),\n label: named ? `Search ${named}` : 'Search',\n })}\n </div>\n )}\n {!loading && !failed && status !== 'idle' && (\n <RefreshIndicator status={reloading ? 'fetching' : status} retry={retryLoad} />\n )}\n <table ref={tableEl}>\n {props.caption != null && <caption>{props.caption}</caption>}\n <thead>\n <tr>\n {columns.map((col) => {\n const canSort = sortable && col.def.sortable !== false\n // From the rendered state, not the live table (the hydrating render, #16).\n const e = canSort ? sortBy?.find((x) => x.id === col.id) : undefined\n const dir = e ? (e.desc ? 'desc' : 'asc') : false\n return (\n <th\n key={col.index}\n scope=\"col\"\n aria-sort={canSort ? ariaSort(dir) : undefined}\n data-sort={dir || undefined}\n >\n {canSort ? (\n <button\n type=\"button\"\n onClick={(e) => view.toggleSort?.(col.id, { multi: e.shiftKey })}\n >\n {col.header}\n <span data-dk-sort-indicator=\"\" aria-hidden=\"true\">\n {dir === 'asc' ? ' ▲' : dir === 'desc' ? ' ▼' : ''}\n </span>\n </button>\n ) : (\n col.header\n )}\n </th>\n )\n })}\n </tr>\n </thead>\n <tbody>\n <Boundary\n table={table}\n resetKey={rowModel}\n fallback={(retry) =>\n stateRow(\n span,\n 'error',\n <ErrorState\n status={status}\n reason=\"render\"\n retry={() => {\n keepFocus()\n retry()\n }}\n />,\n )\n }\n >\n {body}\n </Boundary>\n </tbody>\n </table>\n {pager &&\n part(table, 'Pagination', parts.Pagination, DefaultPagination, {\n ...pager,\n prev: () => view.prevPage?.(),\n next: () => view.nextPage?.(),\n setPageIndex: (i) => view.setPageIndex?.(i),\n setPageSize: (n) => view.setPageSize?.(n),\n label: named ? `${named} pagination` : 'Pagination',\n })}\n <div aria-live=\"polite\" style={HIDDEN} ref={liveEl} />\n </div>\n )\n}\n\n/**\n * A search / pager part (outside the body): a custom one that throws is replaced by the default\n * part (`DK_RENDER_FAILED` at `components.<name>`) until another component is passed.\n */\nfunction part<P extends object>(\n table: object,\n name: 'SearchInput' | 'Pagination',\n Custom: ComponentType<P> | undefined,\n Default: ComponentType<P>,\n props: P,\n): ReactNode {\n if (!Custom) return <Default {...props} />\n return (\n <Boundary\n table={table}\n slot={`components.${name}`}\n resetKey={Custom}\n fallback={() => <Default {...props} />}\n >\n <Custom {...props} />\n </Boundary>\n )\n}\n\nfunction stateRow(span: number, kind: string, content: ReactNode) {\n return (\n <tr data-dk-state={kind}>\n <td colSpan={span}>{content}</td>\n </tr>\n )\n}\n\n// --- error boundaries (DK_RENDER_FAILED) ---------------------------------------------------------\n\ninterface BoundaryProps {\n table: object\n /**\n * A part outside the body: `components.SearchInput` (reported as the slot). A cell boundary:\n * `cell` / `invalidCell` (reported as `columns[<index>].<slot>`).\n */\n slot?: string\n /** A cell boundary (`render:cell`): the cell's column. A new `def` renders a failed cell again. */\n col?: Column\n /** A cell boundary: the row's index in the data (`row.index`). */\n row?: number\n /** A new value (the next row model; a cell's row data) renders the children again. */\n resetKey: unknown\n fallback(retry: () => void): ReactNode\n children: ReactNode\n}\n\ninterface BoundaryState {\n failed: boolean\n key: unknown\n def: ColumnLike | undefined\n}\n\n/**\n * Catches a component that throws (`DK_RENDER_FAILED`) and renders `fallback` instead; the rest of\n * the table keeps working. Three uses: the body outside any cell (`render:table`, §10: a\n * `components.Empty` / `Loading` / `Error` part) shows the Error state; a custom search / pager\n * part (`render:table` at `components.<name>`) is replaced by the default part; and one cell\n * (`render:cell`, §3.4, with `col`): a component returned by `cell` / `invalidCell` renders `⚠` in\n * that cell only (deduped per column). A cell boundary only wraps object content (see `guard`).\n */\nclass Boundary extends Component<BoundaryProps, BoundaryState> {\n override state: BoundaryState = {\n failed: false,\n key: this.props.resetKey,\n def: this.props.col?.def,\n }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n static getDerivedStateFromProps(props: BoundaryProps, state: BoundaryState) {\n const def = props.col?.def\n return props.resetKey === state.key && def === state.def\n ? null\n : { failed: false, key: props.resetKey, def }\n }\n\n override componentDidCatch(error: unknown) {\n const { table, col, slot, row } = this.props\n try {\n emitTableDiagnostic(\n table,\n 'DK_RENDER_FAILED',\n {\n op: col ? 'render:cell' : 'render:table',\n ...(slot ? { slot: col ? `columns[${col.index}].${slot}` : slot } : {}),\n ...(col ? { column: col.id, row: row as number } : {}),\n ...(error instanceof Error ? { errorName: error.name } : {}),\n },\n { cause: error },\n )\n } catch {\n // Not a table made by createTable: nothing to report to.\n }\n }\n\n retry = () => this.setState({ failed: false })\n\n override render() {\n return this.state.failed ? this.props.fallback(this.retry) : this.props.children\n }\n}\n\n/** A failed cell's fallback (one function for every cell boundary: no closure per cell). */\nconst failedCell = () => FAILED\n\n// --- default parts (unstyled) --------------------------------------------------------------------\n\nfunction DefaultSearchInput({\n value,\n status,\n onChange,\n onSubmit,\n onClear,\n label,\n}: SearchInputProps) {\n return (\n <>\n <input\n type=\"search\"\n aria-label={label}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSubmit()\n else if (e.key === 'Escape') onClear()\n }}\n />\n {(status === 'pending' || status === 'searching') && (\n // Decorative: the live region says \"Searching…\" (an empty status announces nothing).\n <span data-dk-spinner=\"\" aria-hidden=\"true\" />\n )}\n </>\n )\n}\n\n/**\n * `aria-disabled`, not `disabled`, at the first / last page: a disabled button loses focus (to\n * `<body>`) the moment paging makes it unavailable (#55).\n */\nfunction DefaultPagination(p: PaginationProps) {\n return (\n <nav aria-label={p.label} data-dk-pagination=\"\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n aria-disabled={!p.canPrev || undefined}\n onClick={p.canPrev ? p.prev : undefined}\n >\n ‹\n </button>\n <span data-dk-page=\"\">\n Page {p.pageIndex + 1} of {Math.max(p.pageCount, 1)}\n </span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n aria-disabled={!p.canNext || undefined}\n onClick={p.canNext ? p.next : undefined}\n >\n ›\n </button>\n </nav>\n )\n}\n\nconst DefaultEmpty = ({ filtered }: EmptyProps) => <>{filtered ? 'No matching rows' : 'No rows'}</>\n\nconst DefaultLoading = (_: LoadingProps) => <span role=\"status\">Loading…</span>\n\nfunction DefaultError({ reason, retry }: ErrorProps) {\n return (\n <div role=\"alert\">\n {reason === 'load' ? 'Could not load the rows.' : 'Could not display the rows.'}{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n}\n\n/** Over stale rows (§6.6): the table is busy, or a later update failed. */\nfunction RefreshIndicator({ status, retry }: { status: RowModelStatus; retry(): void }) {\n if (status === 'error') {\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"alert\">\n Could not refresh; showing the previous rows.{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n }\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"status\">\n Updating…\n </div>\n )\n}\n"],"mappings":"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","names":["e","n"]}
@@ -17,7 +17,8 @@ import {
17
17
  useEffect,
18
18
  useLayoutEffect,
19
19
  useMemo,
20
- useRef
20
+ useRef,
21
+ useState
21
22
  } from "react";
22
23
  import {
23
24
  cellSlot,
@@ -221,6 +222,13 @@ function pages(view, page, count, server) {
221
222
  return { ...page, pageCount, canPrev: index > 0, canNext: index + 1 < pageCount };
222
223
  }
223
224
  var ariaSort = (dir) => dir === "asc" ? "ascending" : dir === "desc" ? "descending" : "none";
225
+ function focusTable(t) {
226
+ if (!t.hasAttribute("tabindex")) {
227
+ t.setAttribute("tabindex", "-1");
228
+ t.addEventListener("blur", () => t.removeAttribute("tabindex"), { once: true });
229
+ }
230
+ t.focus();
231
+ }
224
232
  function DataTableView(props) {
225
233
  const view = props.table;
226
234
  const parts = props.components ?? {};
@@ -242,21 +250,40 @@ function DataTableView(props) {
242
250
  const sortBy = state.sorting?.by;
243
251
  const searchState = state.search;
244
252
  const paged = typeof view.getPageCount === "function";
245
- const loading = isInitialLoad && (LOADING.includes(status) || status === "pending" && hasAsyncSource(view));
246
- const failed = isInitialLoad && status === "error";
253
+ const [retrying, setRetrying] = useState(false);
254
+ const inFlight = useRef(false);
255
+ const reloading = retrying && status === "error";
256
+ const loading = isInitialLoad && (reloading || LOADING.includes(status) || status === "pending" && hasAsyncSource(view));
257
+ const failed = isInitialLoad && status === "error" && !reloading;
247
258
  const span = Math.max(columns.length, 1);
248
259
  const tableEl = useRef(null);
249
- const keepFocus = () => {
260
+ const focusedState = () => {
250
261
  const t = tableEl.current;
251
262
  const from = document.activeElement?.closest("[data-dk-state],[data-dk-refresh]");
252
- if (t && from && t.parentElement?.contains(from)) {
253
- t.tabIndex = -1;
254
- t.focus();
255
- }
263
+ return t && from && t.parentElement?.contains(from) ? document.activeElement : null;
256
264
  };
265
+ const keepFocus = () => {
266
+ const t = tableEl.current;
267
+ if (t && focusedState()) focusTable(t);
268
+ };
269
+ const focusFrom = useRef(null);
270
+ useIsomorphicLayoutEffect(() => {
271
+ const from = focusFrom.current;
272
+ const t = tableEl.current;
273
+ focusFrom.current = null;
274
+ if (!from || !t || from.isConnected) return;
275
+ const now = document.activeElement;
276
+ if (now === null || now === document.body) focusTable(t);
277
+ });
257
278
  const retryLoad = () => {
258
- keepFocus();
259
- void view.refetch();
279
+ if (inFlight.current) return;
280
+ inFlight.current = true;
281
+ focusFrom.current = focusedState();
282
+ setRetrying(true);
283
+ void view.refetch().finally(() => {
284
+ inFlight.current = false;
285
+ setRetrying(false);
286
+ });
260
287
  };
261
288
  const server = paged && serverPaged(view);
262
289
  const pager = paged ? pages(view, state.pagination, rowModel.filteredCount, server) : null;
@@ -283,7 +310,7 @@ function DataTableView(props) {
283
310
  const ErrorState = parts.Error ?? DefaultError;
284
311
  let body;
285
312
  if (loading) {
286
- body = stateRow(span, "loading", /* @__PURE__ */ jsx(Loading, { status }));
313
+ body = stateRow(span, "loading", /* @__PURE__ */ jsx(Loading, { status: reloading ? "fetching" : status }));
287
314
  } else if (failed) {
288
315
  body = stateRow(span, "error", /* @__PURE__ */ jsx(ErrorState, { status, reason: "load", retry: retryLoad }));
289
316
  } else if (rows.length === 0) {
@@ -323,7 +350,7 @@ function DataTableView(props) {
323
350
  "data-datakable": "",
324
351
  "data-status": status,
325
352
  "data-initial-load": isInitialLoad ? "true" : "false",
326
- "aria-busy": BUSY.includes(status) ? "true" : void 0,
353
+ "aria-busy": reloading || BUSY.includes(status) ? "true" : void 0,
327
354
  children: [
328
355
  searchState && /* @__PURE__ */ jsx("div", { "data-dk-search": "", "data-status": searchState.status, children: part(table, "SearchInput", parts.SearchInput, DefaultSearchInput, {
329
356
  value: searchState.input,
@@ -333,7 +360,7 @@ function DataTableView(props) {
333
360
  onClear: () => view.clearSearch?.(),
334
361
  label: named ? `Search ${named}` : "Search"
335
362
  }) }),
336
- !loading && !failed && status !== "idle" && /* @__PURE__ */ jsx(RefreshIndicator, { status, retry: retryLoad }),
363
+ !loading && !failed && status !== "idle" && /* @__PURE__ */ jsx(RefreshIndicator, { status: reloading ? "fetching" : status, retry: retryLoad }),
337
364
  /* @__PURE__ */ jsxs("table", { ref: tableEl, children: [
338
365
  props.caption != null && /* @__PURE__ */ jsx("caption", { children: props.caption }),
339
366
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n boundaryDiagnostics,\n defaultFormat,\n deriveColumns,\n describeReturn,\n emitTableDiagnostic,\n type InvalidRowsMode,\n keepDiagnostics,\n matchesSlot,\n pipelineDiagnostics,\n type RowIssue,\n type RowModelStatus,\n type SearchStatus,\n slotDiagnostics,\n type TableSchema,\n type TableState,\n} from '@datakable/core'\nimport {\n Component,\n type ComponentType,\n type CSSProperties,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react'\nimport {\n cellSlot,\n invalidCellSlot,\n registerRenderOperations,\n renderDiagnostics,\n} from './render-codes'\nimport { type UseDataTableOptions, useDataTable } from './use-data-table'\n\n// The codes this module emits (bundlers keep the definitions; see core's `keepDiagnostics`).\nkeepDiagnostics(renderDiagnostics, boundaryDiagnostics, slotDiagnostics, pipelineDiagnostics)\n\n// The ops its boundaries stand for (§3.4: `render:table`, `render:cell`). Registered at import:\n// the dist is one file per module (T37), so hook-only bundles (`useDataTable` without\n// `<DataTable />`) never include this module, and this call ships only with `<DataTable />`.\nregisterRenderOperations()\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n// --- public types --------------------------------------------------------------------------------\n\n/** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */\nexport interface SearchInputProps {\n /** `state.search.input` (updates as the user types). */\n value: string\n /** `state.search.status`: `pending` while a debounce waits, `searching` while a request runs. */\n status: SearchStatus\n /** `setSearch(value)`. */\n onChange(value: string): void\n /** `flushSearch()` (Enter). */\n onSubmit(): void\n /** `clearSearch()` (Esc). */\n onClear(): void\n /** The input's accessible name: `'Search <caption>'` with a text `caption`, else `'Search'`. */\n label: string\n}\n\n/** Props of `components.Pagination` (the pagination feature's state and API). */\nexport interface PaginationProps {\n pageIndex: number\n pageSize: number\n pageCount: number\n canPrev: boolean\n canNext: boolean\n prev(): void\n next(): void\n setPageIndex(index: number): void\n setPageSize(size: number): void\n /** The pager's accessible name: `'<caption> pagination'` with a text `caption`, else `'Pagination'`. */\n label: string\n}\n\n/** Props of `components.Empty`: shown when the table has loaded and has no rows to show. */\nexport interface EmptyProps {\n /** `true` when there is data but filters / search removed every row. */\n filtered: boolean\n}\n\n/** Props of `components.Loading`: the first load (`isInitialLoad`, nothing to show yet). */\nexport interface LoadingProps {\n status: RowModelStatus\n}\n\n/** Props of `components.Error`: the first load failed, or the body failed to render. */\nexport interface ErrorProps {\n status: RowModelStatus\n /**\n * `'load'`: `status === 'error'` on the first load. `'render'`: a component in the body outside\n * the cells threw (a component inside a cell renders `⚠` in that cell only).\n */\n reason: 'load' | 'render'\n /** `'load'`: `refetch()`. `'render'`: renders the body again. */\n retry(): void\n}\n\n/** `<DataTable components={...} />`: replaces the default parts (unstyled, `data-*` hooks only). */\nexport interface DataTableComponents {\n SearchInput?: ComponentType<SearchInputProps>\n Pagination?: ComponentType<PaginationProps>\n Empty?: ComponentType<EmptyProps>\n Loading?: ComponentType<LoadingProps>\n Error?: ComponentType<ErrorProps>\n}\n\n/** What `<DataTable table={...} />` reads: the value `useDataTable` returns. */\nexport interface DataTableSource {\n readonly state: TableState\n readonly rowModel: {\n readonly rows: readonly DataTableRow[]\n readonly filteredCount: number\n readonly totalCount: number\n readonly status: RowModelStatus\n readonly isInitialLoad: boolean\n }\n getOptions(): { readonly columns?: readonly unknown[] | undefined }\n getData(): readonly unknown[]\n refetch(): Promise<unknown>\n}\n\n/** The part of a `Row` (§6.6) `<DataTable />` renders from. */\ninterface DataTableRow {\n readonly key: string | number\n readonly index: number\n readonly original: unknown\n readonly valid: boolean\n readonly issues: readonly RowIssue[]\n getValue(id: string): unknown\n getCellIssues(id: string): readonly RowIssue[]\n}\n\n/** `<DataTable />`'s own props, next to `table` or the `useDataTable` options. */\nexport interface DataTableOwnProps {\n components?: DataTableComponents | undefined\n caption?: ReactNode\n}\n\n/**\n * `<DataTable table={useDataTable(...)} />`, or `<DataTable data={rows} />` with the\n * `useDataTable` options as props (zero-config: columns derived from the data).\n */\nexport type DataTableProps<\n T = unknown,\n Sch = undefined,\n M extends InvalidRowsMode = InvalidRowsMode,\n> = DataTableOwnProps &\n (\n | { table: DataTableSource }\n | (UseDataTableOptions<T, TableState, Sch, M> & {\n features?: readonly AnyFeature[]\n table?: undefined\n })\n )\n\n// --- component -----------------------------------------------------------------------------------\n\n/**\n * The zero-config table (§10). Renders what the installed features provide: sort buttons with\n * `aria-sort`, a search input bound to `input` (Enter = `flushSearch`, Esc = `clearSearch`),\n * pagination, and the Loading / Error / Empty states from `status` + `isInitialLoad` (§6.6).\n * Unstyled: style it through the `data-*` hooks (`data-status`, `data-initial-load`,\n * `data-invalid`, `data-sort`, …) or replace parts with `components`.\n *\n * `@datakable/react`'s `DataTable` installs no features with `data`; `datakable`'s installs the\n * default preset.\n */\nexport function DataTable<\n T,\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(props: DataTableProps<T, Sch, M>): ReactNode\nexport function DataTable(\n props: DataTableOwnProps & { table?: DataTableSource | undefined },\n): ReactNode {\n if (props.table !== undefined) {\n return (\n <DataTableView table={props.table} components={props.components} caption={props.caption} />\n )\n }\n return <ZeroConfig {...(props as DataTableOwnProps & { table?: undefined })} />\n}\n\nfunction ZeroConfig(props: DataTableOwnProps & { table?: undefined }) {\n const { components, caption, table: _, ...options } = props\n const view = useDataTable(options as never) as unknown as DataTableSource\n return <DataTableView table={view} components={components} caption={caption} />\n}\n\n/** Loose access to the installed features' APIs (the table is typed per feature set). */\ntype Api = DataTableSource & {\n toggleSort?(id: string, opts?: { multi?: boolean }): void\n setSearch?(q: string): Promise<unknown>\n flushSearch?(): Promise<unknown>\n clearSearch?(): void\n setPageIndex?(i: number): void\n setPageSize?(n: number): void\n nextPage?(): void\n prevPage?(): void\n getPageCount?(): number\n canNextPage?(): boolean\n canPrevPage?(): boolean\n}\n\n/** The column fields `<DataTable />` reads (types are checked where the columns are written). */\ninterface ColumnLike {\n key?: unknown\n id?: unknown\n header?: unknown\n sortable?: unknown\n cell?: (ctx: { row: unknown; value: unknown }) => ReactNode\n format?: (value: unknown) => unknown\n invalidCell?: (ctx: {\n original: unknown\n value: unknown\n issues: readonly RowIssue[]\n }) => ReactNode\n}\n\ninterface Column {\n readonly def: ColumnLike\n readonly index: number\n readonly id: string\n readonly header: ReactNode\n}\n\n/** A cell callback that threw or broke its contract during this render (reported after commit). */\ninterface Failure {\n slot: string\n column: string\n row: number\n error?: unknown\n /** Bad return: what the contract expects and the type received. */\n expected?: string\n received?: string\n /** A value the default formatter cannot render (`DK_UNRENDERABLE_VALUE`): its type. */\n lost?: string\n index?: number\n}\n\nconst WARN = '⚠'\n/** A failed cell's content: the `⚠` with its text alternative (#60). One element for every cell. */\nconst FAILED = (\n <span role=\"img\" aria-label=\"Could not display this value\">\n {WARN}\n </span>\n)\nconst BUSY: readonly RowModelStatus[] = ['validating', 'pending', 'searching', 'fetching']\nconst LOADING: readonly RowModelStatus[] = ['validating', 'searching', 'fetching']\n\n/**\n * The table loads its rows asynchronously: a `fetcher`, or a feature with a `searchFn` (its\n * `defineOptions` values). With nothing applied yet, its `'pending'` is a load waiting to start\n * (deferred until the client, §7.2), so `<DataTable />` shows Loading — also in the server HTML.\n */\nfunction hasAsyncSource(table: DataTableSource): boolean {\n const options = table.getOptions() as { fetcher?: unknown; features?: unknown }\n if (typeof options.fetcher === 'function') return true\n if (!Array.isArray(options.features)) return false\n for (const f of options.features as readonly {\n options?: { values?: { searchFn?: unknown } }\n }[]) {\n if (typeof f?.options?.values?.searchFn === 'function') return true\n }\n return false\n}\n\nfunction resolveColumns(defs: readonly unknown[]): Column[] {\n const out: Column[] = []\n for (let index = 0; index < defs.length; index++) {\n const def = defs[index] as ColumnLike | null | undefined\n if (def === null || typeof def !== 'object') continue\n const id = typeof def.key === 'string' ? def.key : def.id\n if (typeof id !== 'string') continue\n out.push({ def, index, id, header: typeof def.header === 'string' ? def.header : id })\n }\n return out\n}\n\nconst segment = (s: PropertyKey | { readonly key: PropertyKey }) =>\n String(typeof s === 'object' ? s.key : s)\n\n/**\n * The redacted issue text for `title` (§5.1): the issue paths only. Schema messages embed the\n * received value, so they are never shown.\n */\nfunction issueTitle(issues: readonly RowIssue[]): string {\n const paths = new Set<string>()\n for (const i of issues) paths.add(i.path?.length ? i.path.map(segment).join('.') : '(row)')\n return `Invalid: ${[...paths].join(', ')}`\n}\n\n/** The table behind a `useDataTable` view (its prototype), for reporting diagnostics. */\nconst tableOf = (view: object): object =>\n Object.hasOwn(view, 'rowModel') ? (Object.getPrototypeOf(view) as object) : view\n\nfunction report(table: object, failures: readonly Failure[]) {\n const bySlot = new Map<string, Failure[]>()\n for (const f of failures) {\n const k = `${f.slot}\\0${f.lost ? '' : f.expected === undefined ? 'throw' : 'return'}`\n const list = bySlot.get(k)\n if (list) list.push(f)\n else bySlot.set(k, [f])\n }\n for (const list of bySlot.values()) {\n const first = list[0] as Failure\n const rows = list.slice(0, 3).map((f) => f.row)\n const fallback = 'cells-warn' // prose key: 'those cells rendered ⚠'\n try {\n if (first.lost !== undefined) {\n // Deduped by the table per column and data reference, like the column cache's report.\n emitTableDiagnostic(table, 'DK_UNRENDERABLE_VALUE', {\n column: first.column,\n index: first.index as number,\n count: list.length,\n rows,\n valueType: first.lost,\n })\n } else if (first.expected === undefined) {\n const e = first.error\n emitTableDiagnostic(\n table,\n 'DK_CALLBACK_FAILED',\n {\n slot: first.slot,\n column: first.column,\n rows,\n count: list.length,\n fallback,\n ...(e instanceof Error ? { errorName: e.name } : {}),\n },\n { cause: e },\n )\n } else if (process.env.NODE_ENV !== 'production') {\n emitTableDiagnostic(table, 'DK_CALLBACK_BAD_RETURN', {\n slot: first.slot,\n column: first.column,\n expected: first.expected,\n received: first.received ?? 'undefined',\n count: list.length,\n rows,\n fallback,\n })\n }\n } catch {\n // Not a table made by createTable (a hand-made `table` prop): nothing to report to.\n }\n }\n}\n\n/**\n * The value `defaultFormat` could not render in the current cell (an object, array or function,\n * never `undefined`). One module-level callback: no closure per cell.\n */\nlet lost: unknown\nconst onLost = (v: unknown) => {\n lost = v\n}\n\n/**\n * Renders one cell's content; a throwing or contract-breaking callback renders `⚠`. An object\n * returned by `cell` / `invalidCell` (an element, an array) may hold components that throw while\n * React renders them, so it gets its own boundary; primitives cannot, so they get none (no cost).\n */\nfunction cellContent(\n col: Column,\n row: DataTableRow,\n failures: Failure[],\n table: object,\n): ReactNode {\n const def = col.def\n const value = row.getValue(col.id)\n const issues = row.valid ? undefined : row.getCellIssues(col.id)\n let slot = 'cell'\n try {\n if (issues !== undefined && issues.length > 0) {\n if (def.invalidCell) {\n slot = 'invalidCell'\n const out = def.invalidCell({ original: row.original, value, issues })\n if (matchesSlot(invalidCellSlot, out)) return guard(out, table, col, row, 'invalidCell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n return (\n <>\n {defaultFormat(value)}{' '}\n <span data-dk-invalid-marker=\"\" aria-hidden=\"true\">\n {WARN}\n </span>\n </>\n )\n }\n if (def.cell) {\n const out = def.cell({ row: row.original, value })\n if (matchesSlot(cellSlot, out)) return guard(out, table, col, row, 'cell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n if (def.format) {\n slot = 'format'\n const out = def.format(value)\n if (typeof out === 'string') return out\n bad(failures, col, row, slot, 'a string', out)\n return defaultFormat(value)\n }\n const text = defaultFormat(value, onLost)\n if (lost !== undefined) {\n const { id: column, index } = col\n const type = Array.isArray(lost) ? 'array' : typeof lost\n failures.push({ slot: `columns[${index}]`, column, index, row: row.index, lost: type })\n lost = undefined\n }\n return text\n } catch (error) {\n failures.push({ slot: `columns[${col.index}].${slot}`, column: col.id, row: row.index, error })\n return FAILED\n }\n}\n\n/** Wraps object content in a per-cell boundary (`render:cell`); primitives pass through as-is. */\nfunction guard(\n out: ReactNode,\n table: object,\n col: Column,\n row: DataTableRow,\n slot: 'cell' | 'invalidCell',\n): ReactNode {\n if (typeof out !== 'object' || out === null) return out\n return (\n <Boundary\n table={table}\n col={col}\n slot={slot}\n row={row.index}\n resetKey={row.original}\n fallback={failedCell}\n >\n {out}\n </Boundary>\n )\n}\n\nfunction bad(\n failures: Failure[],\n col: Column,\n row: DataTableRow,\n slot: string,\n expected: string,\n out: unknown,\n): ReactNode {\n failures.push({\n slot: `columns[${col.index}].${slot}`,\n column: col.id,\n row: row.index,\n expected,\n received: describeReturn(out),\n })\n return FAILED\n}\n\ntype Page = { pageIndex: number; pageSize: number }\n\n/** Visually hidden, still read by screen readers (inline: the table ships no CSS). */\nconst HIDDEN: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n}\n\nconst serverPaged = (view: Api) =>\n (view.getOptions() as { features?: readonly { stage?: string; mode?: string }[] }).features?.some(\n (f) => f?.stage === 'paginate' && f.mode === 'server',\n ) === true\n\n/**\n * The pager of the rendered snapshot, like the pagination API computes it live: the hydrating\n * render must match the server HTML even when the table changed meanwhile (#16). Client mode\n * pages over the row model's `filteredCount`; server mode over the fetched `rowCount`, which only\n * the table knows (and no render changes).\n */\nfunction pages(view: Api, page: Page, count: number, server: boolean) {\n if (server) {\n return {\n ...page,\n pageCount: view.getPageCount?.() ?? 0,\n canPrev: view.canPrevPage?.() ?? false,\n canNext: view.canNextPage?.() ?? false,\n }\n }\n const pageCount = Math.ceil(count / page.pageSize)\n const index = Math.min(page.pageIndex, Math.max(pageCount - 1, 0))\n return { ...page, pageCount, canPrev: index > 0, canNext: index + 1 < pageCount }\n}\n\nconst ariaSort = (dir: 'asc' | 'desc' | false) =>\n dir === 'asc' ? 'ascending' : dir === 'desc' ? 'descending' : 'none'\n\nfunction DataTableView(props: {\n table: DataTableSource\n components: DataTableComponents | undefined\n caption: ReactNode\n}) {\n const view = props.table as Api\n const parts = props.components ?? {}\n const { state, rowModel } = view\n const { rows, status, isInitialLoad } = rowModel\n const defs = view.getOptions().columns\n const data = view.getData()\n // Zero-config columns follow the data; given columns follow their reference (§10).\n const derivedFrom = defs === undefined ? data : undefined\n const columns = useMemo(\n () => resolveColumns(defs ?? (derivedFrom ? deriveColumns(derivedFrom) : [])),\n [defs, derivedFrom],\n )\n const failures: Failure[] = []\n const table = tableOf(view)\n // After commit, never during render: a sink may set state.\n useIsomorphicLayoutEffect(() => {\n if (failures.length > 0) report(table, failures)\n })\n\n const sortable = typeof view.toggleSort === 'function'\n const sortBy = (state.sorting as { by: readonly { id: string; desc?: boolean }[] } | undefined)\n ?.by\n const searchState = state.search as { input: string; status: SearchStatus } | undefined\n const paged = typeof view.getPageCount === 'function'\n // Loading (§6.6, §10): nothing to show yet and rows on their way — in flight, or deferred async\n // work that has not started (SSR, §7.2: 'pending').\n const loading =\n isInitialLoad && (LOADING.includes(status) || (status === 'pending' && hasAsyncSource(view)))\n const failed = isInitialLoad && status === 'error'\n const span = Math.max(columns.length, 1)\n const tableEl = useRef<HTMLTableElement>(null)\n /**\n * Retry unmounts the focused Retry button (Error → Loading → rows, or the refresh error): focus\n * the table first, else it falls to `<body>` (#56). Only when focus is in a state row or the\n * refresh indicator, so a retry called from elsewhere leaves focus alone.\n */\n const keepFocus = () => {\n const t = tableEl.current\n const from = document.activeElement?.closest('[data-dk-state],[data-dk-refresh]')\n if (t && from && t.parentElement?.contains(from)) {\n t.tabIndex = -1\n t.focus()\n }\n }\n const retryLoad = () => {\n keepFocus()\n void view.refetch()\n }\n const server = paged && serverPaged(view)\n const pager = paged ? pages(view, state.pagination as Page, rowModel.filteredCount, server) : null\n\n // Status messages (#54): one polite live region, in the markup from the first render (a region\n // inserted with its text is often not announced). Written after commit, only when the message\n // changes, so the first render (and the hydrating one) matches the server HTML.\n // Worded unlike the visible parts (\"No rows\", \"Searching…\"), so a text query finds one element.\n const n = rowModel.filteredCount\n const count = `${n} row${n === 1 ? '' : 's'}`\n const page = pager ? `${pager.pageIndex + 1} of ${Math.max(pager.pageCount, 1)}` : ''\n let said = ''\n if (searchState?.status === 'pending' || searchState?.status === 'searching') {\n said = 'Searching rows…'\n } else if (status === 'idle' && !loading) {\n // Server mode: `filteredCount` is the page's rows, so only the page (or \"0 rows\").\n said = server && n ? `Page ${page}` : page ? `${count}, page ${page}` : count\n }\n const liveEl = useRef<HTMLDivElement>(null)\n const saidBefore = useRef<string | null>(null)\n useEffect(() => {\n const el = liveEl.current\n if (el && saidBefore.current !== null && saidBefore.current !== said) el.textContent = said\n saidBefore.current = said\n })\n\n // A text caption names the search box and the pager, so two tables get distinct names (#59).\n const cap = props.caption\n const named = typeof cap === 'string' || typeof cap === 'number' ? `${cap}` : ''\n\n const Empty = parts.Empty ?? DefaultEmpty\n const Loading = parts.Loading ?? DefaultLoading\n const ErrorState = parts.Error ?? DefaultError\n\n let body: ReactNode\n if (loading) {\n body = stateRow(span, 'loading', <Loading status={status} />)\n } else if (failed) {\n body = stateRow(span, 'error', <ErrorState status={status} reason=\"load\" retry={retryLoad} />)\n } else if (rows.length === 0) {\n body = stateRow(span, 'empty', <Empty filtered={rowModel.totalCount > 0} />)\n } else {\n body = rows.map((row) => {\n const valid = row.valid\n return (\n <tr\n key={row.key}\n data-invalid={valid ? undefined : 'true'}\n aria-invalid={valid ? undefined : 'true'}\n title={valid ? undefined : issueTitle(row.issues)}\n >\n {columns.map((col) => {\n const issues = valid ? undefined : row.getCellIssues(col.id)\n const broken = issues !== undefined && issues.length > 0\n return (\n <td\n key={col.index}\n data-invalid={broken ? 'true' : undefined}\n aria-invalid={broken ? 'true' : undefined}\n title={broken ? issueTitle(issues) : undefined}\n >\n {cellContent(col, row, failures, table)}\n </td>\n )\n })}\n </tr>\n )\n })\n }\n\n // The server runs no effects: report now (setting state is a no-op there).\n if (typeof window === 'undefined' && failures.length > 0) report(table, failures)\n\n return (\n <div\n data-datakable=\"\"\n data-status={status}\n data-initial-load={isInitialLoad ? 'true' : 'false'}\n aria-busy={BUSY.includes(status) ? 'true' : undefined}\n >\n {searchState && (\n <div data-dk-search=\"\" data-status={searchState.status}>\n {part(table, 'SearchInput', parts.SearchInput, DefaultSearchInput, {\n value: searchState.input,\n status: searchState.status,\n onChange: (q) => void view.setSearch?.(q),\n onSubmit: () => void view.flushSearch?.(),\n onClear: () => view.clearSearch?.(),\n label: named ? `Search ${named}` : 'Search',\n })}\n </div>\n )}\n {!loading && !failed && status !== 'idle' && (\n <RefreshIndicator status={status} retry={retryLoad} />\n )}\n <table ref={tableEl}>\n {props.caption != null && <caption>{props.caption}</caption>}\n <thead>\n <tr>\n {columns.map((col) => {\n const canSort = sortable && col.def.sortable !== false\n // From the rendered state, not the live table (the hydrating render, #16).\n const e = canSort ? sortBy?.find((x) => x.id === col.id) : undefined\n const dir = e ? (e.desc ? 'desc' : 'asc') : false\n return (\n <th\n key={col.index}\n scope=\"col\"\n aria-sort={canSort ? ariaSort(dir) : undefined}\n data-sort={dir || undefined}\n >\n {canSort ? (\n <button\n type=\"button\"\n onClick={(e) => view.toggleSort?.(col.id, { multi: e.shiftKey })}\n >\n {col.header}\n <span data-dk-sort-indicator=\"\" aria-hidden=\"true\">\n {dir === 'asc' ? ' ▲' : dir === 'desc' ? ' ▼' : ''}\n </span>\n </button>\n ) : (\n col.header\n )}\n </th>\n )\n })}\n </tr>\n </thead>\n <tbody>\n <Boundary\n table={table}\n resetKey={rowModel}\n fallback={(retry) =>\n stateRow(\n span,\n 'error',\n <ErrorState\n status={status}\n reason=\"render\"\n retry={() => {\n keepFocus()\n retry()\n }}\n />,\n )\n }\n >\n {body}\n </Boundary>\n </tbody>\n </table>\n {pager &&\n part(table, 'Pagination', parts.Pagination, DefaultPagination, {\n ...pager,\n prev: () => view.prevPage?.(),\n next: () => view.nextPage?.(),\n setPageIndex: (i) => view.setPageIndex?.(i),\n setPageSize: (n) => view.setPageSize?.(n),\n label: named ? `${named} pagination` : 'Pagination',\n })}\n <div aria-live=\"polite\" style={HIDDEN} ref={liveEl} />\n </div>\n )\n}\n\n/**\n * A search / pager part (outside the body): a custom one that throws is replaced by the default\n * part (`DK_RENDER_FAILED` at `components.<name>`) until another component is passed.\n */\nfunction part<P extends object>(\n table: object,\n name: 'SearchInput' | 'Pagination',\n Custom: ComponentType<P> | undefined,\n Default: ComponentType<P>,\n props: P,\n): ReactNode {\n if (!Custom) return <Default {...props} />\n return (\n <Boundary\n table={table}\n slot={`components.${name}`}\n resetKey={Custom}\n fallback={() => <Default {...props} />}\n >\n <Custom {...props} />\n </Boundary>\n )\n}\n\nfunction stateRow(span: number, kind: string, content: ReactNode) {\n return (\n <tr data-dk-state={kind}>\n <td colSpan={span}>{content}</td>\n </tr>\n )\n}\n\n// --- error boundaries (DK_RENDER_FAILED) ---------------------------------------------------------\n\ninterface BoundaryProps {\n table: object\n /**\n * A part outside the body: `components.SearchInput` (reported as the slot). A cell boundary:\n * `cell` / `invalidCell` (reported as `columns[<index>].<slot>`).\n */\n slot?: string\n /** A cell boundary (`render:cell`): the cell's column. A new `def` renders a failed cell again. */\n col?: Column\n /** A cell boundary: the row's index in the data (`row.index`). */\n row?: number\n /** A new value (the next row model; a cell's row data) renders the children again. */\n resetKey: unknown\n fallback(retry: () => void): ReactNode\n children: ReactNode\n}\n\ninterface BoundaryState {\n failed: boolean\n key: unknown\n def: ColumnLike | undefined\n}\n\n/**\n * Catches a component that throws (`DK_RENDER_FAILED`) and renders `fallback` instead; the rest of\n * the table keeps working. Three uses: the body outside any cell (`render:table`, §10: a\n * `components.Empty` / `Loading` / `Error` part) shows the Error state; a custom search / pager\n * part (`render:table` at `components.<name>`) is replaced by the default part; and one cell\n * (`render:cell`, §3.4, with `col`): a component returned by `cell` / `invalidCell` renders `⚠` in\n * that cell only (deduped per column). A cell boundary only wraps object content (see `guard`).\n */\nclass Boundary extends Component<BoundaryProps, BoundaryState> {\n override state: BoundaryState = {\n failed: false,\n key: this.props.resetKey,\n def: this.props.col?.def,\n }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n static getDerivedStateFromProps(props: BoundaryProps, state: BoundaryState) {\n const def = props.col?.def\n return props.resetKey === state.key && def === state.def\n ? null\n : { failed: false, key: props.resetKey, def }\n }\n\n override componentDidCatch(error: unknown) {\n const { table, col, slot, row } = this.props\n try {\n emitTableDiagnostic(\n table,\n 'DK_RENDER_FAILED',\n {\n op: col ? 'render:cell' : 'render:table',\n ...(slot ? { slot: col ? `columns[${col.index}].${slot}` : slot } : {}),\n ...(col ? { column: col.id, row: row as number } : {}),\n ...(error instanceof Error ? { errorName: error.name } : {}),\n },\n { cause: error },\n )\n } catch {\n // Not a table made by createTable: nothing to report to.\n }\n }\n\n retry = () => this.setState({ failed: false })\n\n override render() {\n return this.state.failed ? this.props.fallback(this.retry) : this.props.children\n }\n}\n\n/** A failed cell's fallback (one function for every cell boundary: no closure per cell). */\nconst failedCell = () => FAILED\n\n// --- default parts (unstyled) --------------------------------------------------------------------\n\nfunction DefaultSearchInput({\n value,\n status,\n onChange,\n onSubmit,\n onClear,\n label,\n}: SearchInputProps) {\n return (\n <>\n <input\n type=\"search\"\n aria-label={label}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSubmit()\n else if (e.key === 'Escape') onClear()\n }}\n />\n {(status === 'pending' || status === 'searching') && (\n // Decorative: the live region says \"Searching…\" (an empty status announces nothing).\n <span data-dk-spinner=\"\" aria-hidden=\"true\" />\n )}\n </>\n )\n}\n\n/**\n * `aria-disabled`, not `disabled`, at the first / last page: a disabled button loses focus (to\n * `<body>`) the moment paging makes it unavailable (#55).\n */\nfunction DefaultPagination(p: PaginationProps) {\n return (\n <nav aria-label={p.label} data-dk-pagination=\"\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n aria-disabled={!p.canPrev || undefined}\n onClick={p.canPrev ? p.prev : undefined}\n >\n ‹\n </button>\n <span data-dk-page=\"\">\n Page {p.pageIndex + 1} of {Math.max(p.pageCount, 1)}\n </span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n aria-disabled={!p.canNext || undefined}\n onClick={p.canNext ? p.next : undefined}\n >\n ›\n </button>\n </nav>\n )\n}\n\nconst DefaultEmpty = ({ filtered }: EmptyProps) => <>{filtered ? 'No matching rows' : 'No rows'}</>\n\nconst DefaultLoading = (_: LoadingProps) => <span role=\"status\">Loading…</span>\n\nfunction DefaultError({ reason, retry }: ErrorProps) {\n return (\n <div role=\"alert\">\n {reason === 'load' ? 'Could not load the rows.' : 'Could not display the rows.'}{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n}\n\n/** Over stale rows (§6.6): the table is busy, or a later update failed. */\nfunction RefreshIndicator({ status, retry }: { status: RowModelStatus; retry(): void }) {\n if (status === 'error') {\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"alert\">\n Could not refresh; showing the previous rows.{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n }\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"status\">\n Updating…\n </div>\n )\n}\n"],"mappings":";;;AAEA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAmC,oBAAoB;AAwJjD,SA8ME,UA9MF,KA8ME,YA9MF;AArJN,gBAAgB,mBAAmB,qBAAqB,iBAAiB,mBAAmB;AAK5F,yBAAyB;AAMzB,IAAM,4BAA4B,OAAO,WAAW,cAAc,YAAY;AAqIvE,SAAS,UACd,OACW;AACX,MAAI,MAAM,UAAU,QAAW;AAC7B,WACE,oBAAC,iBAAc,OAAO,MAAM,OAAO,YAAY,MAAM,YAAY,SAAS,MAAM,SAAS;AAAA,EAE7F;AACA,SAAO,oBAAC,cAAY,GAAI,OAAqD;AAC/E;AAEA,SAAS,WAAW,OAAkD;AACpE,QAAM,EAAE,YAAY,SAAS,OAAO,GAAG,GAAG,QAAQ,IAAI;AACtD,QAAM,OAAO,aAAa,OAAgB;AAC1C,SAAO,oBAAC,iBAAc,OAAO,MAAM,YAAwB,SAAkB;AAC/E;AAqDA,IAAM,OAAO;AAEb,IAAM,SACJ,oBAAC,UAAK,MAAK,OAAM,cAAW,gCACzB,gBACH;AAEF,IAAM,OAAkC,CAAC,cAAc,WAAW,aAAa,UAAU;AACzF,IAAM,UAAqC,CAAC,cAAc,aAAa,UAAU;AAOjF,SAAS,eAAe,OAAiC;AACvD,QAAM,UAAU,MAAM,WAAW;AACjC,MAAI,OAAO,QAAQ,YAAY,WAAY,QAAO;AAClD,MAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,EAAG,QAAO;AAC7C,aAAW,KAAK,QAAQ,UAEnB;AACH,QAAI,OAAO,GAAG,SAAS,QAAQ,aAAa,WAAY,QAAO;AAAA,EACjE;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAoC;AAC1D,QAAM,MAAgB,CAAC;AACvB,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;AAChD,UAAM,MAAM,KAAK,KAAK;AACtB,QAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU;AAC7C,UAAM,KAAK,OAAO,IAAI,QAAQ,WAAW,IAAI,MAAM,IAAI;AACvD,QAAI,OAAO,OAAO,SAAU;AAC5B,QAAI,KAAK,EAAE,KAAK,OAAO,IAAI,QAAQ,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS,GAAG,CAAC;AAAA,EACvF;AACA,SAAO;AACT;AAEA,IAAM,UAAU,CAAC,MACf,OAAO,OAAO,MAAM,WAAW,EAAE,MAAM,CAAC;AAM1C,SAAS,WAAW,QAAqC;AACvD,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,KAAK,OAAQ,OAAM,IAAI,EAAE,MAAM,SAAS,EAAE,KAAK,IAAI,OAAO,EAAE,KAAK,GAAG,IAAI,OAAO;AAC1F,SAAO,YAAY,CAAC,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC;AAC1C;AAGA,IAAM,UAAU,CAAC,SACf,OAAO,OAAO,MAAM,UAAU,IAAK,OAAO,eAAe,IAAI,IAAe;AAE9E,SAAS,OAAO,OAAe,UAA8B;AAC3D,QAAM,SAAS,oBAAI,IAAuB;AAC1C,aAAW,KAAK,UAAU;AACxB,UAAM,IAAI,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,KAAK,EAAE,aAAa,SAAY,UAAU,QAAQ;AACnF,UAAM,OAAO,OAAO,IAAI,CAAC;AACzB,QAAI,KAAM,MAAK,KAAK,CAAC;AAAA,QAChB,QAAO,IAAI,GAAG,CAAC,CAAC,CAAC;AAAA,EACxB;AACA,aAAW,QAAQ,OAAO,OAAO,GAAG;AAClC,UAAM,QAAQ,KAAK,CAAC;AACpB,UAAM,OAAO,KAAK,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAC9C,UAAM,WAAW;AACjB,QAAI;AACF,UAAI,MAAM,SAAS,QAAW;AAE5B,4BAAoB,OAAO,yBAAyB;AAAA,UAClD,QAAQ,MAAM;AAAA,UACd,OAAO,MAAM;AAAA,UACb,OAAO,KAAK;AAAA,UACZ;AAAA,UACA,WAAW,MAAM;AAAA,QACnB,CAAC;AAAA,MACH,WAAW,MAAM,aAAa,QAAW;AACvC,cAAM,IAAI,MAAM;AAChB;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,YACE,MAAM,MAAM;AAAA,YACZ,QAAQ,MAAM;AAAA,YACd;AAAA,YACA,OAAO,KAAK;AAAA,YACZ;AAAA,YACA,GAAI,aAAa,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,UACpD;AAAA,UACA,EAAE,OAAO,EAAE;AAAA,QACb;AAAA,MACF,WAAW,QAAQ,IAAI,aAAa,cAAc;AAChD,4BAAoB,OAAO,0BAA0B;AAAA,UACnD,MAAM,MAAM;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM,YAAY;AAAA,UAC5B,OAAO,KAAK;AAAA,UACZ;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAMA,IAAI;AACJ,IAAM,SAAS,CAAC,MAAe;AAC7B,SAAO;AACT;AAOA,SAAS,YACP,KACA,KACA,UACA,OACW;AACX,QAAM,MAAM,IAAI;AAChB,QAAM,QAAQ,IAAI,SAAS,IAAI,EAAE;AACjC,QAAM,SAAS,IAAI,QAAQ,SAAY,IAAI,cAAc,IAAI,EAAE;AAC/D,MAAI,OAAO;AACX,MAAI;AACF,QAAI,WAAW,UAAa,OAAO,SAAS,GAAG;AAC7C,UAAI,IAAI,aAAa;AACnB,eAAO;AACP,cAAM,MAAM,IAAI,YAAY,EAAE,UAAU,IAAI,UAAU,OAAO,OAAO,CAAC;AACrE,YAAI,YAAY,iBAAiB,GAAG,EAAG,QAAO,MAAM,KAAK,OAAO,KAAK,KAAK,aAAa;AACvF,eAAO,IAAI,UAAU,KAAK,KAAK,MAAM,2BAA2B,GAAG;AAAA,MACrE;AACA,aACE,iCACG;AAAA,sBAAc,KAAK;AAAA,QAAG;AAAA,QACvB,oBAAC,UAAK,0BAAuB,IAAG,eAAY,QACzC,gBACH;AAAA,SACF;AAAA,IAEJ;AACA,QAAI,IAAI,MAAM;AACZ,YAAM,MAAM,IAAI,KAAK,EAAE,KAAK,IAAI,UAAU,MAAM,CAAC;AACjD,UAAI,YAAY,UAAU,GAAG,EAAG,QAAO,MAAM,KAAK,OAAO,KAAK,KAAK,MAAM;AACzE,aAAO,IAAI,UAAU,KAAK,KAAK,MAAM,2BAA2B,GAAG;AAAA,IACrE;AACA,QAAI,IAAI,QAAQ;AACd,aAAO;AACP,YAAM,MAAM,IAAI,OAAO,KAAK;AAC5B,UAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,UAAI,UAAU,KAAK,KAAK,MAAM,YAAY,GAAG;AAC7C,aAAO,cAAc,KAAK;AAAA,IAC5B;AACA,UAAM,OAAO,cAAc,OAAO,MAAM;AACxC,QAAI,SAAS,QAAW;AACtB,YAAM,EAAE,IAAI,QAAQ,MAAM,IAAI;AAC9B,YAAM,OAAO,MAAM,QAAQ,IAAI,IAAI,UAAU,OAAO;AACpD,eAAS,KAAK,EAAE,MAAM,WAAW,KAAK,KAAK,QAAQ,OAAO,KAAK,IAAI,OAAO,MAAM,KAAK,CAAC;AACtF,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,aAAS,KAAK,EAAE,MAAM,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAI,IAAI,KAAK,IAAI,OAAO,MAAM,CAAC;AAC9F,WAAO;AAAA,EACT;AACF;AAGA,SAAS,MACP,KACA,OACA,KACA,KACA,MACW;AACX,MAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM,QAAO;AACpD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,IAAI;AAAA,MACT,UAAU,IAAI;AAAA,MACd,UAAU;AAAA,MAET;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,IACP,UACA,KACA,KACA,MACA,UACA,KACW;AACX,WAAS,KAAK;AAAA,IACZ,MAAM,WAAW,IAAI,KAAK,KAAK,IAAI;AAAA,IACnC,QAAQ,IAAI;AAAA,IACZ,KAAK,IAAI;AAAA,IACT;AAAA,IACA,UAAU,eAAe,GAAG;AAAA,EAC9B,CAAC;AACD,SAAO;AACT;AAKA,IAAM,SAAwB;AAAA,EAC5B,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AACd;AAEA,IAAM,cAAc,CAAC,SAClB,KAAK,WAAW,EAAkE,UAAU;AAAA,EAC3F,CAAC,MAAM,GAAG,UAAU,cAAc,EAAE,SAAS;AAC/C,MAAM;AAQR,SAAS,MAAM,MAAW,MAAY,OAAe,QAAiB;AACpE,MAAI,QAAQ;AACV,WAAO;AAAA,MACL,GAAG;AAAA,MACH,WAAW,KAAK,eAAe,KAAK;AAAA,MACpC,SAAS,KAAK,cAAc,KAAK;AAAA,MACjC,SAAS,KAAK,cAAc,KAAK;AAAA,IACnC;AAAA,EACF;AACA,QAAM,YAAY,KAAK,KAAK,QAAQ,KAAK,QAAQ;AACjD,QAAM,QAAQ,KAAK,IAAI,KAAK,WAAW,KAAK,IAAI,YAAY,GAAG,CAAC,CAAC;AACjE,SAAO,EAAE,GAAG,MAAM,WAAW,SAAS,QAAQ,GAAG,SAAS,QAAQ,IAAI,UAAU;AAClF;AAEA,IAAM,WAAW,CAAC,QAChB,QAAQ,QAAQ,cAAc,QAAQ,SAAS,eAAe;AAEhE,SAAS,cAAc,OAIpB;AACD,QAAM,OAAO,MAAM;AACnB,QAAM,QAAQ,MAAM,cAAc,CAAC;AACnC,QAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,QAAM,EAAE,MAAM,QAAQ,cAAc,IAAI;AACxC,QAAM,OAAO,KAAK,WAAW,EAAE;AAC/B,QAAM,OAAO,KAAK,QAAQ;AAE1B,QAAM,cAAc,SAAS,SAAY,OAAO;AAChD,QAAM,UAAU;AAAA,IACd,MAAM,eAAe,SAAS,cAAc,cAAc,WAAW,IAAI,CAAC,EAAE;AAAA,IAC5E,CAAC,MAAM,WAAW;AAAA,EACpB;AACA,QAAM,WAAsB,CAAC;AAC7B,QAAM,QAAQ,QAAQ,IAAI;AAE1B,4BAA0B,MAAM;AAC9B,QAAI,SAAS,SAAS,EAAG,QAAO,OAAO,QAAQ;AAAA,EACjD,CAAC;AAED,QAAM,WAAW,OAAO,KAAK,eAAe;AAC5C,QAAM,SAAU,MAAM,SAClB;AACJ,QAAM,cAAc,MAAM;AAC1B,QAAM,QAAQ,OAAO,KAAK,iBAAiB;AAG3C,QAAM,UACJ,kBAAkB,QAAQ,SAAS,MAAM,KAAM,WAAW,aAAa,eAAe,IAAI;AAC5F,QAAM,SAAS,iBAAiB,WAAW;AAC3C,QAAM,OAAO,KAAK,IAAI,QAAQ,QAAQ,CAAC;AACvC,QAAM,UAAU,OAAyB,IAAI;AAM7C,QAAM,YAAY,MAAM;AACtB,UAAM,IAAI,QAAQ;AAClB,UAAM,OAAO,SAAS,eAAe,QAAQ,mCAAmC;AAChF,QAAI,KAAK,QAAQ,EAAE,eAAe,SAAS,IAAI,GAAG;AAChD,QAAE,WAAW;AACb,QAAE,MAAM;AAAA,IACV;AAAA,EACF;AACA,QAAM,YAAY,MAAM;AACtB,cAAU;AACV,SAAK,KAAK,QAAQ;AAAA,EACpB;AACA,QAAM,SAAS,SAAS,YAAY,IAAI;AACxC,QAAM,QAAQ,QAAQ,MAAM,MAAM,MAAM,YAAoB,SAAS,eAAe,MAAM,IAAI;AAM9F,QAAM,IAAI,SAAS;AACnB,QAAM,QAAQ,GAAG,CAAC,OAAO,MAAM,IAAI,KAAK,GAAG;AAC3C,QAAM,OAAO,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC,CAAC,KAAK;AACnF,MAAI,OAAO;AACX,MAAI,aAAa,WAAW,aAAa,aAAa,WAAW,aAAa;AAC5E,WAAO;AAAA,EACT,WAAW,WAAW,UAAU,CAAC,SAAS;AAExC,WAAO,UAAU,IAAI,QAAQ,IAAI,KAAK,OAAO,GAAG,KAAK,UAAU,IAAI,KAAK;AAAA,EAC1E;AACA,QAAM,SAAS,OAAuB,IAAI;AAC1C,QAAM,aAAa,OAAsB,IAAI;AAC7C,YAAU,MAAM;AACd,UAAM,KAAK,OAAO;AAClB,QAAI,MAAM,WAAW,YAAY,QAAQ,WAAW,YAAY,KAAM,IAAG,cAAc;AACvF,eAAW,UAAU;AAAA,EACvB,CAAC;AAGD,QAAM,MAAM,MAAM;AAClB,QAAM,QAAQ,OAAO,QAAQ,YAAY,OAAO,QAAQ,WAAW,GAAG,GAAG,KAAK;AAE9E,QAAM,QAAQ,MAAM,SAAS;AAC7B,QAAM,UAAU,MAAM,WAAW;AACjC,QAAM,aAAa,MAAM,SAAS;AAElC,MAAI;AACJ,MAAI,SAAS;AACX,WAAO,SAAS,MAAM,WAAW,oBAAC,WAAQ,QAAgB,CAAE;AAAA,EAC9D,WAAW,QAAQ;AACjB,WAAO,SAAS,MAAM,SAAS,oBAAC,cAAW,QAAgB,QAAO,QAAO,OAAO,WAAW,CAAE;AAAA,EAC/F,WAAW,KAAK,WAAW,GAAG;AAC5B,WAAO,SAAS,MAAM,SAAS,oBAAC,SAAM,UAAU,SAAS,aAAa,GAAG,CAAE;AAAA,EAC7E,OAAO;AACL,WAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,YAAM,QAAQ,IAAI;AAClB,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,gBAAc,QAAQ,SAAY;AAAA,UAClC,gBAAc,QAAQ,SAAY;AAAA,UAClC,OAAO,QAAQ,SAAY,WAAW,IAAI,MAAM;AAAA,UAE/C,kBAAQ,IAAI,CAAC,QAAQ;AACpB,kBAAM,SAAS,QAAQ,SAAY,IAAI,cAAc,IAAI,EAAE;AAC3D,kBAAM,SAAS,WAAW,UAAa,OAAO,SAAS;AACvD,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,gBAAc,SAAS,SAAS;AAAA,gBAChC,gBAAc,SAAS,SAAS;AAAA,gBAChC,OAAO,SAAS,WAAW,MAAM,IAAI;AAAA,gBAEpC,sBAAY,KAAK,KAAK,UAAU,KAAK;AAAA;AAAA,cALjC,IAAI;AAAA,YAMX;AAAA,UAEJ,CAAC;AAAA;AAAA,QAlBI,IAAI;AAAA,MAmBX;AAAA,IAEJ,CAAC;AAAA,EACH;AAGA,MAAI,OAAO,WAAW,eAAe,SAAS,SAAS,EAAG,QAAO,OAAO,QAAQ;AAEhF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,kBAAe;AAAA,MACf,eAAa;AAAA,MACb,qBAAmB,gBAAgB,SAAS;AAAA,MAC5C,aAAW,KAAK,SAAS,MAAM,IAAI,SAAS;AAAA,MAE3C;AAAA,uBACC,oBAAC,SAAI,kBAAe,IAAG,eAAa,YAAY,QAC7C,eAAK,OAAO,eAAe,MAAM,aAAa,oBAAoB;AAAA,UACjE,OAAO,YAAY;AAAA,UACnB,QAAQ,YAAY;AAAA,UACpB,UAAU,CAAC,MAAM,KAAK,KAAK,YAAY,CAAC;AAAA,UACxC,UAAU,MAAM,KAAK,KAAK,cAAc;AAAA,UACxC,SAAS,MAAM,KAAK,cAAc;AAAA,UAClC,OAAO,QAAQ,UAAU,KAAK,KAAK;AAAA,QACrC,CAAC,GACH;AAAA,QAED,CAAC,WAAW,CAAC,UAAU,WAAW,UACjC,oBAAC,oBAAiB,QAAgB,OAAO,WAAW;AAAA,QAEtD,qBAAC,WAAM,KAAK,SACT;AAAA,gBAAM,WAAW,QAAQ,oBAAC,aAAS,gBAAM,SAAQ;AAAA,UAClD,oBAAC,WACC,8BAAC,QACE,kBAAQ,IAAI,CAAC,QAAQ;AACpB,kBAAM,UAAU,YAAY,IAAI,IAAI,aAAa;AAEjD,kBAAM,IAAI,UAAU,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE,IAAI;AAC3D,kBAAM,MAAM,IAAK,EAAE,OAAO,SAAS,QAAS;AAC5C,mBACE;AAAA,cAAC;AAAA;AAAA,gBAEC,OAAM;AAAA,gBACN,aAAW,UAAU,SAAS,GAAG,IAAI;AAAA,gBACrC,aAAW,OAAO;AAAA,gBAEjB,oBACC;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,CAACA,OAAM,KAAK,aAAa,IAAI,IAAI,EAAE,OAAOA,GAAE,SAAS,CAAC;AAAA,oBAE9D;AAAA,0BAAI;AAAA,sBACL,oBAAC,UAAK,0BAAuB,IAAG,eAAY,QACzC,kBAAQ,QAAQ,YAAO,QAAQ,SAAS,YAAO,IAClD;AAAA;AAAA;AAAA,gBACF,IAEA,IAAI;AAAA;AAAA,cAhBD,IAAI;AAAA,YAkBX;AAAA,UAEJ,CAAC,GACH,GACF;AAAA,UACA,oBAAC,WACC;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,UAAU;AAAA,cACV,UAAU,CAAC,UACT;AAAA,gBACE;AAAA,gBACA;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC;AAAA,oBACA,QAAO;AAAA,oBACP,OAAO,MAAM;AACX,gCAAU;AACV,4BAAM;AAAA,oBACR;AAAA;AAAA,gBACF;AAAA,cACF;AAAA,cAGD;AAAA;AAAA,UACH,GACF;AAAA,WACF;AAAA,QACC,SACC,KAAK,OAAO,cAAc,MAAM,YAAY,mBAAmB;AAAA,UAC7D,GAAG;AAAA,UACH,MAAM,MAAM,KAAK,WAAW;AAAA,UAC5B,MAAM,MAAM,KAAK,WAAW;AAAA,UAC5B,cAAc,CAAC,MAAM,KAAK,eAAe,CAAC;AAAA,UAC1C,aAAa,CAACC,OAAM,KAAK,cAAcA,EAAC;AAAA,UACxC,OAAO,QAAQ,GAAG,KAAK,gBAAgB;AAAA,QACzC,CAAC;AAAA,QACH,oBAAC,SAAI,aAAU,UAAS,OAAO,QAAQ,KAAK,QAAQ;AAAA;AAAA;AAAA,EACtD;AAEJ;AAMA,SAAS,KACP,OACA,MACA,QACA,SACA,OACW;AACX,MAAI,CAAC,OAAQ,QAAO,oBAAC,WAAS,GAAG,OAAO;AACxC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,MAAM,cAAc,IAAI;AAAA,MACxB,UAAU;AAAA,MACV,UAAU,MAAM,oBAAC,WAAS,GAAG,OAAO;AAAA,MAEpC,8BAAC,UAAQ,GAAG,OAAO;AAAA;AAAA,EACrB;AAEJ;AAEA,SAAS,SAAS,MAAc,MAAc,SAAoB;AAChE,SACE,oBAAC,QAAG,iBAAe,MACjB,8BAAC,QAAG,SAAS,MAAO,mBAAQ,GAC9B;AAEJ;AAmCA,IAAM,WAAN,cAAuB,UAAwC;AAAA,EAA/D;AAAA;AACE,SAAS,QAAuB;AAAA,MAC9B,QAAQ;AAAA,MACR,KAAK,KAAK,MAAM;AAAA,MAChB,KAAK,KAAK,MAAM,KAAK;AAAA,IACvB;AAgCA,iBAAQ,MAAM,KAAK,SAAS,EAAE,QAAQ,MAAM,CAAC;AAAA;AAAA,EA9B7C,OAAO,2BAA2B;AAChC,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB;AAAA,EAEA,OAAO,yBAAyB,OAAsB,OAAsB;AAC1E,UAAM,MAAM,MAAM,KAAK;AACvB,WAAO,MAAM,aAAa,MAAM,OAAO,QAAQ,MAAM,MACjD,OACA,EAAE,QAAQ,OAAO,KAAK,MAAM,UAAU,IAAI;AAAA,EAChD;AAAA,EAES,kBAAkB,OAAgB;AACzC,UAAM,EAAE,OAAO,KAAK,MAAM,IAAI,IAAI,KAAK;AACvC,QAAI;AACF;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,UACE,IAAI,MAAM,gBAAgB;AAAA,UAC1B,GAAI,OAAO,EAAE,MAAM,MAAM,WAAW,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC;AAAA,UACrE,GAAI,MAAM,EAAE,QAAQ,IAAI,IAAI,IAAmB,IAAI,CAAC;AAAA,UACpD,GAAI,iBAAiB,QAAQ,EAAE,WAAW,MAAM,KAAK,IAAI,CAAC;AAAA,QAC5D;AAAA,QACA,EAAE,OAAO,MAAM;AAAA,MACjB;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAIS,SAAS;AAChB,WAAO,KAAK,MAAM,SAAS,KAAK,MAAM,SAAS,KAAK,KAAK,IAAI,KAAK,MAAM;AAAA,EAC1E;AACF;AAGA,IAAM,aAAa,MAAM;AAIzB,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY;AAAA,QACZ;AAAA,QACA,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAW,CAAC,MAAM;AAChB,cAAI,EAAE,QAAQ,QAAS,UAAS;AAAA,mBACvB,EAAE,QAAQ,SAAU,SAAQ;AAAA,QACvC;AAAA;AAAA,IACF;AAAA,KACE,WAAW,aAAa,WAAW;AAAA,IAEnC,oBAAC,UAAK,mBAAgB,IAAG,eAAY,QAAO;AAAA,KAEhD;AAEJ;AAMA,SAAS,kBAAkB,GAAoB;AAC7C,SACE,qBAAC,SAAI,cAAY,EAAE,OAAO,sBAAmB,IAC3C;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,iBAAe,CAAC,EAAE,WAAW;AAAA,QAC7B,SAAS,EAAE,UAAU,EAAE,OAAO;AAAA,QAC/B;AAAA;AAAA,IAED;AAAA,IACA,qBAAC,UAAK,gBAAa,IAAG;AAAA;AAAA,MACd,EAAE,YAAY;AAAA,MAAE;AAAA,MAAK,KAAK,IAAI,EAAE,WAAW,CAAC;AAAA,OACpD;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,iBAAe,CAAC,EAAE,WAAW;AAAA,QAC7B,SAAS,EAAE,UAAU,EAAE,OAAO;AAAA,QAC/B;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;AAEA,IAAM,eAAe,CAAC,EAAE,SAAS,MAAkB,gCAAG,qBAAW,qBAAqB,WAAU;AAEhG,IAAM,iBAAiB,CAAC,MAAoB,oBAAC,UAAK,MAAK,UAAS,2BAAQ;AAExE,SAAS,aAAa,EAAE,QAAQ,MAAM,GAAe;AACnD,SACE,qBAAC,SAAI,MAAK,SACP;AAAA,eAAW,SAAS,6BAA6B;AAAA,IAA+B;AAAA,IACjF,oBAAC,YAAO,MAAK,UAAS,SAAS,OAAO,mBAEtC;AAAA,KACF;AAEJ;AAGA,SAAS,iBAAiB,EAAE,QAAQ,MAAM,GAA8C;AACtF,MAAI,WAAW,SAAS;AACtB,WACE,qBAAC,SAAI,mBAAgB,IAAG,eAAa,QAAQ,MAAK,SAAQ;AAAA;AAAA,MACV;AAAA,MAC9C,oBAAC,YAAO,MAAK,UAAS,SAAS,OAAO,mBAEtC;AAAA,OACF;AAAA,EAEJ;AACA,SACE,oBAAC,SAAI,mBAAgB,IAAG,eAAa,QAAQ,MAAK,UAAS,4BAE3D;AAEJ;","names":["e","n"]}
1
+ {"version":3,"sources":["../src/data-table.tsx"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n boundaryDiagnostics,\n defaultFormat,\n deriveColumns,\n describeReturn,\n emitTableDiagnostic,\n type InvalidRowsMode,\n keepDiagnostics,\n matchesSlot,\n pipelineDiagnostics,\n type RowIssue,\n type RowModelStatus,\n type SearchStatus,\n slotDiagnostics,\n type TableSchema,\n type TableState,\n} from '@datakable/core'\nimport {\n Component,\n type ComponentType,\n type CSSProperties,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n cellSlot,\n invalidCellSlot,\n registerRenderOperations,\n renderDiagnostics,\n} from './render-codes'\nimport { type UseDataTableOptions, useDataTable } from './use-data-table'\n\n// The codes this module emits (bundlers keep the definitions; see core's `keepDiagnostics`).\nkeepDiagnostics(renderDiagnostics, boundaryDiagnostics, slotDiagnostics, pipelineDiagnostics)\n\n// The ops its boundaries stand for (§3.4: `render:table`, `render:cell`). Registered at import:\n// the dist is one file per module (T37), so hook-only bundles (`useDataTable` without\n// `<DataTable />`) never include this module, and this call ships only with `<DataTable />`.\nregisterRenderOperations()\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n// --- public types --------------------------------------------------------------------------------\n\n/** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */\nexport interface SearchInputProps {\n /** `state.search.input` (updates as the user types). */\n value: string\n /** `state.search.status`: `pending` while a debounce waits, `searching` while a request runs. */\n status: SearchStatus\n /** `setSearch(value)`. */\n onChange(value: string): void\n /** `flushSearch()` (Enter). */\n onSubmit(): void\n /** `clearSearch()` (Esc). */\n onClear(): void\n /** The input's accessible name: `'Search <caption>'` with a text `caption`, else `'Search'`. */\n label: string\n}\n\n/** Props of `components.Pagination` (the pagination feature's state and API). */\nexport interface PaginationProps {\n pageIndex: number\n pageSize: number\n pageCount: number\n canPrev: boolean\n canNext: boolean\n prev(): void\n next(): void\n setPageIndex(index: number): void\n setPageSize(size: number): void\n /** The pager's accessible name: `'<caption> pagination'` with a text `caption`, else `'Pagination'`. */\n label: string\n}\n\n/** Props of `components.Empty`: shown when the table has loaded and has no rows to show. */\nexport interface EmptyProps {\n /** `true` when there is data but filters / search removed every row. */\n filtered: boolean\n}\n\n/** Props of `components.Loading`: the first load (`isInitialLoad`, nothing to show yet). */\nexport interface LoadingProps {\n status: RowModelStatus\n}\n\n/** Props of `components.Error`: the first load failed, or the body failed to render. */\nexport interface ErrorProps {\n status: RowModelStatus\n /**\n * `'load'`: `status === 'error'` on the first load. `'render'`: a component in the body outside\n * the cells threw (a component inside a cell renders `⚠` in that cell only).\n */\n reason: 'load' | 'render'\n /** `'load'`: `refetch()`. `'render'`: renders the body again. */\n retry(): void\n}\n\n/** `<DataTable components={...} />`: replaces the default parts (unstyled, `data-*` hooks only). */\nexport interface DataTableComponents {\n SearchInput?: ComponentType<SearchInputProps>\n Pagination?: ComponentType<PaginationProps>\n Empty?: ComponentType<EmptyProps>\n Loading?: ComponentType<LoadingProps>\n Error?: ComponentType<ErrorProps>\n}\n\n/** What `<DataTable table={...} />` reads: the value `useDataTable` returns. */\nexport interface DataTableSource {\n readonly state: TableState\n readonly rowModel: {\n readonly rows: readonly DataTableRow[]\n readonly filteredCount: number\n readonly totalCount: number\n readonly status: RowModelStatus\n readonly isInitialLoad: boolean\n }\n getOptions(): { readonly columns?: readonly unknown[] | undefined }\n getData(): readonly unknown[]\n refetch(): Promise<unknown>\n}\n\n/** The part of a `Row` (§6.6) `<DataTable />` renders from. */\ninterface DataTableRow {\n readonly key: string | number\n readonly index: number\n readonly original: unknown\n readonly valid: boolean\n readonly issues: readonly RowIssue[]\n getValue(id: string): unknown\n getCellIssues(id: string): readonly RowIssue[]\n}\n\n/** `<DataTable />`'s own props, next to `table` or the `useDataTable` options. */\nexport interface DataTableOwnProps {\n components?: DataTableComponents | undefined\n caption?: ReactNode\n}\n\n/**\n * `<DataTable table={useDataTable(...)} />`, or `<DataTable data={rows} />` with the\n * `useDataTable` options as props (zero-config: columns derived from the data).\n */\nexport type DataTableProps<\n T = unknown,\n Sch = undefined,\n M extends InvalidRowsMode = InvalidRowsMode,\n> = DataTableOwnProps &\n (\n | { table: DataTableSource }\n | (UseDataTableOptions<T, TableState, Sch, M> & {\n features?: readonly AnyFeature[]\n table?: undefined\n })\n )\n\n// --- component -----------------------------------------------------------------------------------\n\n/**\n * The zero-config table (§10). Renders what the installed features provide: sort buttons with\n * `aria-sort`, a search input bound to `input` (Enter = `flushSearch`, Esc = `clearSearch`),\n * pagination, and the Loading / Error / Empty states from `status` + `isInitialLoad` (§6.6).\n * Unstyled: style it through the `data-*` hooks (`data-status`, `data-initial-load`,\n * `data-invalid`, `data-sort`, …) or replace parts with `components`.\n *\n * `@datakable/react`'s `DataTable` installs no features with `data`; `datakable`'s installs the\n * default preset.\n */\nexport function DataTable<\n T,\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(props: DataTableProps<T, Sch, M>): ReactNode\nexport function DataTable(\n props: DataTableOwnProps & { table?: DataTableSource | undefined },\n): ReactNode {\n if (props.table !== undefined) {\n return (\n <DataTableView table={props.table} components={props.components} caption={props.caption} />\n )\n }\n return <ZeroConfig {...(props as DataTableOwnProps & { table?: undefined })} />\n}\n\nfunction ZeroConfig(props: DataTableOwnProps & { table?: undefined }) {\n const { components, caption, table: _, ...options } = props\n const view = useDataTable(options as never) as unknown as DataTableSource\n return <DataTableView table={view} components={components} caption={caption} />\n}\n\n/** Loose access to the installed features' APIs (the table is typed per feature set). */\ntype Api = DataTableSource & {\n toggleSort?(id: string, opts?: { multi?: boolean }): void\n setSearch?(q: string): Promise<unknown>\n flushSearch?(): Promise<unknown>\n clearSearch?(): void\n setPageIndex?(i: number): void\n setPageSize?(n: number): void\n nextPage?(): void\n prevPage?(): void\n getPageCount?(): number\n canNextPage?(): boolean\n canPrevPage?(): boolean\n}\n\n/** The column fields `<DataTable />` reads (types are checked where the columns are written). */\ninterface ColumnLike {\n key?: unknown\n id?: unknown\n header?: unknown\n sortable?: unknown\n cell?: (ctx: { row: unknown; value: unknown }) => ReactNode\n format?: (value: unknown) => unknown\n invalidCell?: (ctx: {\n original: unknown\n value: unknown\n issues: readonly RowIssue[]\n }) => ReactNode\n}\n\ninterface Column {\n readonly def: ColumnLike\n readonly index: number\n readonly id: string\n readonly header: ReactNode\n}\n\n/** A cell callback that threw or broke its contract during this render (reported after commit). */\ninterface Failure {\n slot: string\n column: string\n row: number\n error?: unknown\n /** Bad return: what the contract expects and the type received. */\n expected?: string\n received?: string\n /** A value the default formatter cannot render (`DK_UNRENDERABLE_VALUE`): its type. */\n lost?: string\n index?: number\n}\n\nconst WARN = '⚠'\n/** A failed cell's content: the `⚠` with its text alternative (#60). One element for every cell. */\nconst FAILED = (\n <span role=\"img\" aria-label=\"Could not display this value\">\n {WARN}\n </span>\n)\nconst BUSY: readonly RowModelStatus[] = ['validating', 'pending', 'searching', 'fetching']\nconst LOADING: readonly RowModelStatus[] = ['validating', 'searching', 'fetching']\n\n/**\n * The table loads its rows asynchronously: a `fetcher`, or a feature with a `searchFn` (its\n * `defineOptions` values). With nothing applied yet, its `'pending'` is a load waiting to start\n * (deferred until the client, §7.2), so `<DataTable />` shows Loading — also in the server HTML.\n */\nfunction hasAsyncSource(table: DataTableSource): boolean {\n const options = table.getOptions() as { fetcher?: unknown; features?: unknown }\n if (typeof options.fetcher === 'function') return true\n if (!Array.isArray(options.features)) return false\n for (const f of options.features as readonly {\n options?: { values?: { searchFn?: unknown } }\n }[]) {\n if (typeof f?.options?.values?.searchFn === 'function') return true\n }\n return false\n}\n\nfunction resolveColumns(defs: readonly unknown[]): Column[] {\n const out: Column[] = []\n for (let index = 0; index < defs.length; index++) {\n const def = defs[index] as ColumnLike | null | undefined\n if (def === null || typeof def !== 'object') continue\n const id = typeof def.key === 'string' ? def.key : def.id\n if (typeof id !== 'string') continue\n out.push({ def, index, id, header: typeof def.header === 'string' ? def.header : id })\n }\n return out\n}\n\nconst segment = (s: PropertyKey | { readonly key: PropertyKey }) =>\n String(typeof s === 'object' ? s.key : s)\n\n/**\n * The redacted issue text for `title` (§5.1): the issue paths only. Schema messages embed the\n * received value, so they are never shown.\n */\nfunction issueTitle(issues: readonly RowIssue[]): string {\n const paths = new Set<string>()\n for (const i of issues) paths.add(i.path?.length ? i.path.map(segment).join('.') : '(row)')\n return `Invalid: ${[...paths].join(', ')}`\n}\n\n/** The table behind a `useDataTable` view (its prototype), for reporting diagnostics. */\nconst tableOf = (view: object): object =>\n Object.hasOwn(view, 'rowModel') ? (Object.getPrototypeOf(view) as object) : view\n\nfunction report(table: object, failures: readonly Failure[]) {\n const bySlot = new Map<string, Failure[]>()\n for (const f of failures) {\n const k = `${f.slot}\\0${f.lost ? '' : f.expected === undefined ? 'throw' : 'return'}`\n const list = bySlot.get(k)\n if (list) list.push(f)\n else bySlot.set(k, [f])\n }\n for (const list of bySlot.values()) {\n const first = list[0] as Failure\n const rows = list.slice(0, 3).map((f) => f.row)\n const fallback = 'cells-warn' // prose key: 'those cells rendered ⚠'\n try {\n if (first.lost !== undefined) {\n // Deduped by the table per column and data reference, like the column cache's report.\n emitTableDiagnostic(table, 'DK_UNRENDERABLE_VALUE', {\n column: first.column,\n index: first.index as number,\n count: list.length,\n rows,\n valueType: first.lost,\n })\n } else if (first.expected === undefined) {\n const e = first.error\n emitTableDiagnostic(\n table,\n 'DK_CALLBACK_FAILED',\n {\n slot: first.slot,\n column: first.column,\n rows,\n count: list.length,\n fallback,\n ...(e instanceof Error ? { errorName: e.name } : {}),\n },\n { cause: e },\n )\n } else if (process.env.NODE_ENV !== 'production') {\n emitTableDiagnostic(table, 'DK_CALLBACK_BAD_RETURN', {\n slot: first.slot,\n column: first.column,\n expected: first.expected,\n received: first.received ?? 'undefined',\n count: list.length,\n rows,\n fallback,\n })\n }\n } catch {\n // Not a table made by createTable (a hand-made `table` prop): nothing to report to.\n }\n }\n}\n\n/**\n * The value `defaultFormat` could not render in the current cell (an object, array or function,\n * never `undefined`). One module-level callback: no closure per cell.\n */\nlet lost: unknown\nconst onLost = (v: unknown) => {\n lost = v\n}\n\n/**\n * Renders one cell's content; a throwing or contract-breaking callback renders `⚠`. An object\n * returned by `cell` / `invalidCell` (an element, an array) may hold components that throw while\n * React renders them, so it gets its own boundary; primitives cannot, so they get none (no cost).\n */\nfunction cellContent(\n col: Column,\n row: DataTableRow,\n failures: Failure[],\n table: object,\n): ReactNode {\n const def = col.def\n const value = row.getValue(col.id)\n const issues = row.valid ? undefined : row.getCellIssues(col.id)\n let slot = 'cell'\n try {\n if (issues !== undefined && issues.length > 0) {\n if (def.invalidCell) {\n slot = 'invalidCell'\n const out = def.invalidCell({ original: row.original, value, issues })\n if (matchesSlot(invalidCellSlot, out)) return guard(out, table, col, row, 'invalidCell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n return (\n <>\n {defaultFormat(value)}{' '}\n <span data-dk-invalid-marker=\"\" aria-hidden=\"true\">\n {WARN}\n </span>\n </>\n )\n }\n if (def.cell) {\n const out = def.cell({ row: row.original, value })\n if (matchesSlot(cellSlot, out)) return guard(out, table, col, row, 'cell')\n return bad(failures, col, row, slot, 'a value (not a Promise)', out)\n }\n if (def.format) {\n slot = 'format'\n const out = def.format(value)\n if (typeof out === 'string') return out\n bad(failures, col, row, slot, 'a string', out)\n return defaultFormat(value)\n }\n const text = defaultFormat(value, onLost)\n if (lost !== undefined) {\n const { id: column, index } = col\n const type = Array.isArray(lost) ? 'array' : typeof lost\n failures.push({ slot: `columns[${index}]`, column, index, row: row.index, lost: type })\n lost = undefined\n }\n return text\n } catch (error) {\n failures.push({ slot: `columns[${col.index}].${slot}`, column: col.id, row: row.index, error })\n return FAILED\n }\n}\n\n/** Wraps object content in a per-cell boundary (`render:cell`); primitives pass through as-is. */\nfunction guard(\n out: ReactNode,\n table: object,\n col: Column,\n row: DataTableRow,\n slot: 'cell' | 'invalidCell',\n): ReactNode {\n if (typeof out !== 'object' || out === null) return out\n return (\n <Boundary\n table={table}\n col={col}\n slot={slot}\n row={row.index}\n resetKey={row.original}\n fallback={failedCell}\n >\n {out}\n </Boundary>\n )\n}\n\nfunction bad(\n failures: Failure[],\n col: Column,\n row: DataTableRow,\n slot: string,\n expected: string,\n out: unknown,\n): ReactNode {\n failures.push({\n slot: `columns[${col.index}].${slot}`,\n column: col.id,\n row: row.index,\n expected,\n received: describeReturn(out),\n })\n return FAILED\n}\n\ntype Page = { pageIndex: number; pageSize: number }\n\n/** Visually hidden, still read by screen readers (inline: the table ships no CSS). */\nconst HIDDEN: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n}\n\nconst serverPaged = (view: Api) =>\n (view.getOptions() as { features?: readonly { stage?: string; mode?: string }[] }).features?.some(\n (f) => f?.stage === 'paginate' && f.mode === 'server',\n ) === true\n\n/**\n * The pager of the rendered snapshot, like the pagination API computes it live: the hydrating\n * render must match the server HTML even when the table changed meanwhile (#16). Client mode\n * pages over the row model's `filteredCount`; server mode over the fetched `rowCount`, which only\n * the table knows (and no render changes).\n */\nfunction pages(view: Api, page: Page, count: number, server: boolean) {\n if (server) {\n return {\n ...page,\n pageCount: view.getPageCount?.() ?? 0,\n canPrev: view.canPrevPage?.() ?? false,\n canNext: view.canNextPage?.() ?? false,\n }\n }\n const pageCount = Math.ceil(count / page.pageSize)\n const index = Math.min(page.pageIndex, Math.max(pageCount - 1, 0))\n return { ...page, pageCount, canPrev: index > 0, canNext: index + 1 < pageCount }\n}\n\nconst ariaSort = (dir: 'asc' | 'desc' | false) =>\n dir === 'asc' ? 'ascending' : dir === 'desc' ? 'descending' : 'none'\n\n/** Focus the table for a Retry (#56); a `tabindex` added for that goes on the next blur (#88). */\nfunction focusTable(t: HTMLTableElement) {\n if (!t.hasAttribute('tabindex')) {\n t.setAttribute('tabindex', '-1')\n t.addEventListener('blur', () => t.removeAttribute('tabindex'), { once: true })\n }\n t.focus()\n}\n\nfunction DataTableView(props: {\n table: DataTableSource\n components: DataTableComponents | undefined\n caption: ReactNode\n}) {\n const view = props.table as Api\n const parts = props.components ?? {}\n const { state, rowModel } = view\n const { rows, status, isInitialLoad } = rowModel\n const defs = view.getOptions().columns\n const data = view.getData()\n // Zero-config columns follow the data; given columns follow their reference (§10).\n const derivedFrom = defs === undefined ? data : undefined\n const columns = useMemo(\n () => resolveColumns(defs ?? (derivedFrom ? deriveColumns(derivedFrom) : [])),\n [defs, derivedFrom],\n )\n const failures: Failure[] = []\n const table = tableOf(view)\n // After commit, never during render: a sink may set state.\n useIsomorphicLayoutEffect(() => {\n if (failures.length > 0) report(table, failures)\n })\n\n const sortable = typeof view.toggleSort === 'function'\n const sortBy = (state.sorting as { by: readonly { id: string; desc?: boolean }[] } | undefined)\n ?.by\n const searchState = state.search as { input: string; status: SearchStatus } | undefined\n const paged = typeof view.getPageCount === 'function'\n // Loading (§6.6, §10): nothing to show yet and rows on their way — in flight, or deferred async\n // work that has not started (SSR, §7.2: 'pending').\n // A Retry of a failed load / refresh in flight (#87). Core keeps `status: 'error'` during a\n // `refetch()` (it outranks `'fetching'`), so the view tracks the retry itself: Loading (or\n // \"Updating…\") instead of the error, `aria-busy`, and repeat retries ignored until it settles.\n const [retrying, setRetrying] = useState(false)\n const inFlight = useRef(false)\n const reloading = retrying && status === 'error'\n const loading =\n isInitialLoad &&\n (reloading || LOADING.includes(status) || (status === 'pending' && hasAsyncSource(view)))\n const failed = isInitialLoad && status === 'error' && !reloading\n const span = Math.max(columns.length, 1)\n const tableEl = useRef<HTMLTableElement>(null)\n /** The focused element in a state row or the refresh indicator, else `null`. */\n const focusedState = () => {\n const t = tableEl.current\n const from = document.activeElement?.closest('[data-dk-state],[data-dk-refresh]')\n return t && from && t.parentElement?.contains(from) ? document.activeElement : null\n }\n /**\n * Retry unmounts the focused Retry button (Error → Loading → rows, or the refresh error): focus\n * the table, else it falls to `<body>` (#56). Only when focus is in a state row or the refresh\n * indicator, so a retry called from elsewhere leaves focus alone.\n */\n const keepFocus = () => {\n const t = tableEl.current\n if (t && focusedState()) focusTable(t)\n }\n // The element focused when a load / refresh Retry was activated, until the next commit: focus\n // moves to the table only if that commit really unmounted it.\n const focusFrom = useRef<Element | null>(null)\n useIsomorphicLayoutEffect(() => {\n const from = focusFrom.current\n const t = tableEl.current\n focusFrom.current = null\n if (!from || !t || from.isConnected) return\n const now = document.activeElement\n if (now === null || now === document.body) focusTable(t)\n })\n const retryLoad = () => {\n if (inFlight.current) return\n inFlight.current = true\n focusFrom.current = focusedState()\n setRetrying(true)\n void view.refetch().finally(() => {\n inFlight.current = false\n setRetrying(false)\n })\n }\n const server = paged && serverPaged(view)\n const pager = paged ? pages(view, state.pagination as Page, rowModel.filteredCount, server) : null\n\n // Status messages (#54): one polite live region, in the markup from the first render (a region\n // inserted with its text is often not announced). Written after commit, only when the message\n // changes, so the first render (and the hydrating one) matches the server HTML.\n // Worded unlike the visible parts (\"No rows\", \"Searching…\"), so a text query finds one element.\n const n = rowModel.filteredCount\n const count = `${n} row${n === 1 ? '' : 's'}`\n const page = pager ? `${pager.pageIndex + 1} of ${Math.max(pager.pageCount, 1)}` : ''\n let said = ''\n if (searchState?.status === 'pending' || searchState?.status === 'searching') {\n said = 'Searching rows…'\n } else if (status === 'idle' && !loading) {\n // Server mode: `filteredCount` is the page's rows, so only the page (or \"0 rows\").\n said = server && n ? `Page ${page}` : page ? `${count}, page ${page}` : count\n }\n const liveEl = useRef<HTMLDivElement>(null)\n const saidBefore = useRef<string | null>(null)\n useEffect(() => {\n const el = liveEl.current\n if (el && saidBefore.current !== null && saidBefore.current !== said) el.textContent = said\n saidBefore.current = said\n })\n\n // A text caption names the search box and the pager, so two tables get distinct names (#59).\n const cap = props.caption\n const named = typeof cap === 'string' || typeof cap === 'number' ? `${cap}` : ''\n\n const Empty = parts.Empty ?? DefaultEmpty\n const Loading = parts.Loading ?? DefaultLoading\n const ErrorState = parts.Error ?? DefaultError\n\n let body: ReactNode\n if (loading) {\n body = stateRow(span, 'loading', <Loading status={reloading ? 'fetching' : status} />)\n } else if (failed) {\n body = stateRow(span, 'error', <ErrorState status={status} reason=\"load\" retry={retryLoad} />)\n } else if (rows.length === 0) {\n body = stateRow(span, 'empty', <Empty filtered={rowModel.totalCount > 0} />)\n } else {\n body = rows.map((row) => {\n const valid = row.valid\n return (\n <tr\n key={row.key}\n data-invalid={valid ? undefined : 'true'}\n aria-invalid={valid ? undefined : 'true'}\n title={valid ? undefined : issueTitle(row.issues)}\n >\n {columns.map((col) => {\n const issues = valid ? undefined : row.getCellIssues(col.id)\n const broken = issues !== undefined && issues.length > 0\n return (\n <td\n key={col.index}\n data-invalid={broken ? 'true' : undefined}\n aria-invalid={broken ? 'true' : undefined}\n title={broken ? issueTitle(issues) : undefined}\n >\n {cellContent(col, row, failures, table)}\n </td>\n )\n })}\n </tr>\n )\n })\n }\n\n // The server runs no effects: report now (setting state is a no-op there).\n if (typeof window === 'undefined' && failures.length > 0) report(table, failures)\n\n return (\n <div\n data-datakable=\"\"\n data-status={status}\n data-initial-load={isInitialLoad ? 'true' : 'false'}\n aria-busy={reloading || BUSY.includes(status) ? 'true' : undefined}\n >\n {searchState && (\n <div data-dk-search=\"\" data-status={searchState.status}>\n {part(table, 'SearchInput', parts.SearchInput, DefaultSearchInput, {\n value: searchState.input,\n status: searchState.status,\n onChange: (q) => void view.setSearch?.(q),\n onSubmit: () => void view.flushSearch?.(),\n onClear: () => view.clearSearch?.(),\n label: named ? `Search ${named}` : 'Search',\n })}\n </div>\n )}\n {!loading && !failed && status !== 'idle' && (\n <RefreshIndicator status={reloading ? 'fetching' : status} retry={retryLoad} />\n )}\n <table ref={tableEl}>\n {props.caption != null && <caption>{props.caption}</caption>}\n <thead>\n <tr>\n {columns.map((col) => {\n const canSort = sortable && col.def.sortable !== false\n // From the rendered state, not the live table (the hydrating render, #16).\n const e = canSort ? sortBy?.find((x) => x.id === col.id) : undefined\n const dir = e ? (e.desc ? 'desc' : 'asc') : false\n return (\n <th\n key={col.index}\n scope=\"col\"\n aria-sort={canSort ? ariaSort(dir) : undefined}\n data-sort={dir || undefined}\n >\n {canSort ? (\n <button\n type=\"button\"\n onClick={(e) => view.toggleSort?.(col.id, { multi: e.shiftKey })}\n >\n {col.header}\n <span data-dk-sort-indicator=\"\" aria-hidden=\"true\">\n {dir === 'asc' ? ' ▲' : dir === 'desc' ? ' ▼' : ''}\n </span>\n </button>\n ) : (\n col.header\n )}\n </th>\n )\n })}\n </tr>\n </thead>\n <tbody>\n <Boundary\n table={table}\n resetKey={rowModel}\n fallback={(retry) =>\n stateRow(\n span,\n 'error',\n <ErrorState\n status={status}\n reason=\"render\"\n retry={() => {\n keepFocus()\n retry()\n }}\n />,\n )\n }\n >\n {body}\n </Boundary>\n </tbody>\n </table>\n {pager &&\n part(table, 'Pagination', parts.Pagination, DefaultPagination, {\n ...pager,\n prev: () => view.prevPage?.(),\n next: () => view.nextPage?.(),\n setPageIndex: (i) => view.setPageIndex?.(i),\n setPageSize: (n) => view.setPageSize?.(n),\n label: named ? `${named} pagination` : 'Pagination',\n })}\n <div aria-live=\"polite\" style={HIDDEN} ref={liveEl} />\n </div>\n )\n}\n\n/**\n * A search / pager part (outside the body): a custom one that throws is replaced by the default\n * part (`DK_RENDER_FAILED` at `components.<name>`) until another component is passed.\n */\nfunction part<P extends object>(\n table: object,\n name: 'SearchInput' | 'Pagination',\n Custom: ComponentType<P> | undefined,\n Default: ComponentType<P>,\n props: P,\n): ReactNode {\n if (!Custom) return <Default {...props} />\n return (\n <Boundary\n table={table}\n slot={`components.${name}`}\n resetKey={Custom}\n fallback={() => <Default {...props} />}\n >\n <Custom {...props} />\n </Boundary>\n )\n}\n\nfunction stateRow(span: number, kind: string, content: ReactNode) {\n return (\n <tr data-dk-state={kind}>\n <td colSpan={span}>{content}</td>\n </tr>\n )\n}\n\n// --- error boundaries (DK_RENDER_FAILED) ---------------------------------------------------------\n\ninterface BoundaryProps {\n table: object\n /**\n * A part outside the body: `components.SearchInput` (reported as the slot). A cell boundary:\n * `cell` / `invalidCell` (reported as `columns[<index>].<slot>`).\n */\n slot?: string\n /** A cell boundary (`render:cell`): the cell's column. A new `def` renders a failed cell again. */\n col?: Column\n /** A cell boundary: the row's index in the data (`row.index`). */\n row?: number\n /** A new value (the next row model; a cell's row data) renders the children again. */\n resetKey: unknown\n fallback(retry: () => void): ReactNode\n children: ReactNode\n}\n\ninterface BoundaryState {\n failed: boolean\n key: unknown\n def: ColumnLike | undefined\n}\n\n/**\n * Catches a component that throws (`DK_RENDER_FAILED`) and renders `fallback` instead; the rest of\n * the table keeps working. Three uses: the body outside any cell (`render:table`, §10: a\n * `components.Empty` / `Loading` / `Error` part) shows the Error state; a custom search / pager\n * part (`render:table` at `components.<name>`) is replaced by the default part; and one cell\n * (`render:cell`, §3.4, with `col`): a component returned by `cell` / `invalidCell` renders `⚠` in\n * that cell only (deduped per column). A cell boundary only wraps object content (see `guard`).\n */\nclass Boundary extends Component<BoundaryProps, BoundaryState> {\n override state: BoundaryState = {\n failed: false,\n key: this.props.resetKey,\n def: this.props.col?.def,\n }\n\n static getDerivedStateFromError() {\n return { failed: true }\n }\n\n static getDerivedStateFromProps(props: BoundaryProps, state: BoundaryState) {\n const def = props.col?.def\n return props.resetKey === state.key && def === state.def\n ? null\n : { failed: false, key: props.resetKey, def }\n }\n\n override componentDidCatch(error: unknown) {\n const { table, col, slot, row } = this.props\n try {\n emitTableDiagnostic(\n table,\n 'DK_RENDER_FAILED',\n {\n op: col ? 'render:cell' : 'render:table',\n ...(slot ? { slot: col ? `columns[${col.index}].${slot}` : slot } : {}),\n ...(col ? { column: col.id, row: row as number } : {}),\n ...(error instanceof Error ? { errorName: error.name } : {}),\n },\n { cause: error },\n )\n } catch {\n // Not a table made by createTable: nothing to report to.\n }\n }\n\n retry = () => this.setState({ failed: false })\n\n override render() {\n return this.state.failed ? this.props.fallback(this.retry) : this.props.children\n }\n}\n\n/** A failed cell's fallback (one function for every cell boundary: no closure per cell). */\nconst failedCell = () => FAILED\n\n// --- default parts (unstyled) --------------------------------------------------------------------\n\nfunction DefaultSearchInput({\n value,\n status,\n onChange,\n onSubmit,\n onClear,\n label,\n}: SearchInputProps) {\n return (\n <>\n <input\n type=\"search\"\n aria-label={label}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSubmit()\n else if (e.key === 'Escape') onClear()\n }}\n />\n {(status === 'pending' || status === 'searching') && (\n // Decorative: the live region says \"Searching…\" (an empty status announces nothing).\n <span data-dk-spinner=\"\" aria-hidden=\"true\" />\n )}\n </>\n )\n}\n\n/**\n * `aria-disabled`, not `disabled`, at the first / last page: a disabled button loses focus (to\n * `<body>`) the moment paging makes it unavailable (#55).\n */\nfunction DefaultPagination(p: PaginationProps) {\n return (\n <nav aria-label={p.label} data-dk-pagination=\"\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n aria-disabled={!p.canPrev || undefined}\n onClick={p.canPrev ? p.prev : undefined}\n >\n ‹\n </button>\n <span data-dk-page=\"\">\n Page {p.pageIndex + 1} of {Math.max(p.pageCount, 1)}\n </span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n aria-disabled={!p.canNext || undefined}\n onClick={p.canNext ? p.next : undefined}\n >\n ›\n </button>\n </nav>\n )\n}\n\nconst DefaultEmpty = ({ filtered }: EmptyProps) => <>{filtered ? 'No matching rows' : 'No rows'}</>\n\nconst DefaultLoading = (_: LoadingProps) => <span role=\"status\">Loading…</span>\n\nfunction DefaultError({ reason, retry }: ErrorProps) {\n return (\n <div role=\"alert\">\n {reason === 'load' ? 'Could not load the rows.' : 'Could not display the rows.'}{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n}\n\n/** Over stale rows (§6.6): the table is busy, or a later update failed. */\nfunction RefreshIndicator({ status, retry }: { status: RowModelStatus; retry(): void }) {\n if (status === 'error') {\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"alert\">\n Could not refresh; showing the previous rows.{' '}\n <button type=\"button\" onClick={retry}>\n Retry\n </button>\n </div>\n )\n }\n return (\n <div data-dk-refresh=\"\" data-status={status} role=\"status\">\n Updating…\n </div>\n )\n}\n"],"mappings":"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","names":["e","n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _datakable_core from '@datakable/core';
2
- import { TableState, InvalidRowsMode, CreateTableOptions, ColumnDef, SchemaRow, Table, RowModel, AnyFeature, TableSchema, TableStateFor, ApiOf, SearchStatus, RowModelStatus, RowIssue, DiagnosticMessages } from '@datakable/core';
2
+ import { TableState, InvalidRowsMode, CreateTableOptions, ColumnDef, SchemaRow, Table, RowModel, AnyFeature, TableSchema, TableStateFor, HasSchema, ApiOf, SearchStatus, RowModelStatus, RowIssue, DiagnosticMessages } from '@datakable/core';
3
3
  export * from '@datakable/core';
4
4
  import { ReactNode, ComponentType } from 'react';
5
5
 
@@ -73,9 +73,7 @@ type UseDataTableResult<T, S extends TableState = TableState, M extends InvalidR
73
73
  */
74
74
  declare function useDataTable<T, S extends TableState = never, const Fs extends readonly AnyFeature[] = [], const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {
75
75
  features?: Fs;
76
- }): UseDataTableResult<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, [
77
- Sch
78
- ] extends [TableSchema] ? unknown : T, ApiOf<Fs, SchemaRow<T, Sch>>>;
76
+ }): UseDataTableResult<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, HasSchema<Sch> extends true ? unknown : T, ApiOf<Fs, SchemaRow<T, Sch>>>;
79
77
 
80
78
  /** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */
81
79
  interface SearchInputProps {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _datakable_core from '@datakable/core';
2
- import { TableState, InvalidRowsMode, CreateTableOptions, ColumnDef, SchemaRow, Table, RowModel, AnyFeature, TableSchema, TableStateFor, ApiOf, SearchStatus, RowModelStatus, RowIssue, DiagnosticMessages } from '@datakable/core';
2
+ import { TableState, InvalidRowsMode, CreateTableOptions, ColumnDef, SchemaRow, Table, RowModel, AnyFeature, TableSchema, TableStateFor, HasSchema, ApiOf, SearchStatus, RowModelStatus, RowIssue, DiagnosticMessages } from '@datakable/core';
3
3
  export * from '@datakable/core';
4
4
  import { ReactNode, ComponentType } from 'react';
5
5
 
@@ -73,9 +73,7 @@ type UseDataTableResult<T, S extends TableState = TableState, M extends InvalidR
73
73
  */
74
74
  declare function useDataTable<T, S extends TableState = never, const Fs extends readonly AnyFeature[] = [], const Sch extends TableSchema | undefined = undefined, const M extends InvalidRowsMode = 'drop'>(options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {
75
75
  features?: Fs;
76
- }): UseDataTableResult<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, [
77
- Sch
78
- ] extends [TableSchema] ? unknown : T, ApiOf<Fs, SchemaRow<T, Sch>>>;
76
+ }): UseDataTableResult<SchemaRow<T, Sch>, TableStateFor<S, Fs, SchemaRow<T, Sch>>, M, HasSchema<Sch> extends true ? unknown : T, ApiOf<Fs, SchemaRow<T, Sch>>>;
79
77
 
80
78
  /** Props of `components.SearchInput`: the search feature's `input`, bound both ways. */
81
79
  interface SearchInputProps {
@@ -28,7 +28,7 @@ var import_core = require("@datakable/core");
28
28
  var import_react = require("react");
29
29
 
30
30
  // package.json
31
- var version = "2.0.2";
31
+ var version = "2.0.3";
32
32
 
33
33
  // src/use-data-table.ts
34
34
  var import_codes = require("./codes.cjs");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/use-data-table.ts","../package.json"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n type ApiOf,\n type ColumnDef,\n type CreateTableOptions,\n createDeferred,\n createTable,\n type Diagnostic,\n emitTableDiagnostic,\n type InvalidRowsMode,\n isOptionsDefinition,\n keepDiagnostics,\n type RowModel,\n registerPackage,\n type SchemaRow,\n SERVER_SOURCE,\n startTable,\n type Table,\n type TableSchema,\n type TableState,\n type TableStateFor,\n} from '@datakable/core'\nimport {\n type ReactNode,\n version as reactVersion,\n useCallback,\n useEffect,\n useInsertionEffect,\n useLayoutEffect,\n useReducer,\n useRef,\n useSyncExternalStore,\n} from 'react'\nimport { version } from '../package.json'\nimport { reactDiagnostics } from './codes'\n\n// Registers the (development-only) definitions where they are emitted, so bundlers keep them.\nkeepDiagnostics(reactDiagnostics)\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n/**\n * `useDataTable` options: `createTable`'s (§3.2), with `cell` / `invalidCell` returning a\n * `ReactNode` (§10). Read once, at creation: `features`, `schema`, `invalidRows`, `initialState`,\n * `name`, `timeout`, `strict`, `diagnostics`. Every other option follows the latest render.\n */\nexport type UseDataTableOptions<\n T,\n S extends TableState = TableState,\n Sch = undefined,\n M extends InvalidRowsMode = 'drop',\n> = Omit<CreateTableOptions<T, S, Sch, M>, 'columns'> & {\n /**\n * Compared by reference (§10): a new array tells the table the columns changed. Define them\n * outside the component or memoise them (`DK_UNSTABLE_COLUMNS` in development).\n */\n columns?: readonly ColumnDef<SchemaRow<T, Sch>, ReactNode>[]\n}\n\n/**\n * What `useDataTable` returns: the table (its methods and the installed features' APIs) with the\n * `state` and `rowModel` of this render. A new object whenever the table notifies, so it can be a\n * dependency of `useMemo` / `memo` children; the same object while nothing changed.\n */\nexport type UseDataTableResult<\n T,\n S extends TableState = TableState,\n M extends InvalidRowsMode = 'drop',\n In = T,\n Api = unknown,\n> = Table<T, S, M, In> &\n Api & {\n /** The state snapshot of this render (`getState()`). */\n readonly state: S\n /** The row model of this render (`getRowModel()`, §6.6): rows, counts, status. */\n readonly rowModel: RowModel<T, M>\n }\n\ntype Options = Record<string, unknown> & { features?: readonly AnyFeature[] }\ntype AnyTable = Table<unknown, TableState> & Record<string, unknown>\ntype Callback = (arg: never) => unknown\n\n/** Options forwarded through `setOptions` when they change; the rest are read once (§3.4). */\nconst SYNCED = [\n 'data',\n 'columns',\n 'rowKey',\n 'state',\n 'onStateChange',\n 'interceptors',\n 'onDiagnostic',\n 'fetcher',\n 'rowCount',\n] as const\n\n/** Given to the table as stable wrappers that call the latest prop (latest-ref). */\nconst CALLBACKS = ['onStateChange', 'onDiagnostic', 'fetcher'] as const\ntype CallbackKey = (typeof CALLBACKS)[number]\n\n/** Renders in a row with a new reference before `DK_UNSTABLE_*` is reported. */\nconst UNSTABLE_AFTER = 2\n\ninterface Instance {\n table: AnyTable\n destroyed: boolean\n mounted: boolean\n /** The options of the latest committed render (what the wrappers call). */\n latest: Options\n /** The option values the table has (user values; callbacks count by presence). */\n synced: Options\n readonly wrappers: Record<CallbackKey, Callback>\n /** `onDiagnostic` calls made while rendering, delivered after the commit. */\n queue: Diagnostic[] | undefined\n rendering: number\n /** Inside the hook's own `setOptions` call. */\n syncing: boolean\n /** That call notified: the next commit is the re-render it caused. */\n selfCaused: boolean\n /**\n * `data` was forwarded in a self-caused re-render. Rows that differ on every render (nested\n * objects, computed fields) would otherwise ingest → notify → re-render forever: the next\n * self-caused re-render keeps the data the table has.\n */\n selfData: boolean\n /** Notifications seen; part of the view cache key (a notification is never silent, §6.6). */\n version: number\n view: { table: AnyTable; version: number; value: object } | undefined\n /**\n * SSR (§7.2): the view of `table` at its creation — initial state, controlled state and data /\n * initialData, no async result (the table is created deferred). `getServerSnapshot`.\n */\n server: { table: AnyTable; value: object } | undefined\n /** React read `getServerSnapshot` on the client: this render hydrates server HTML. */\n hydrating: boolean\n // Dev: DK_UNSTABLE_* bookkeeping.\n /** The options of the previous committed render. */\n seen: Options\n /** Development only (`checkUnstable`). */\n unstable?: Map<string, number>\n warned?: Set<string>\n}\n\nlet registered = false\n\n/**\n * Binds a table to a component (§10): the table is created once per component instance and\n * destroyed on unmount; renders read it through `useSyncExternalStore` (with\n * `getServerSnapshot`), and options are synced with `table.setOptions` in a layout effect, never\n * during render.\n *\n * - `features` (and the other read-once options) are read at creation: a new inline `features`\n * array never recreates the table.\n * - `fetcher`, `onStateChange` and `onDiagnostic` may be inline functions: the table always calls\n * the latest one, and a new reference never refetches (call `refetch()` when a value the fetcher\n * reads changes).\n * - `columns`, `data` and a `rowKey` function are compared by reference: memoise them.\n * - Controlled slices (§3.2): pass `state` and `onStateChange`; changes come back through `state`.\n * - SSR (§7.2): rendering starts no async work. The fetcher's first request and a `searchFn` for an\n * initial query start after the commit (`status: 'pending'` until then; `DK_SSR_ASYNC_DEFERRED`\n * on the server), unless `initialData` already holds their result. `initialState` (e.g. parsed\n * from the URL) applies on the server: client-mode features filter / search / sort the HTML.\n * `getServerSnapshot` is the view at creation; a table that changed before the hydration commit\n * reports `DK_HYDRATION_MISMATCH`.\n *\n * `@datakable/react` installs no features by default; `datakable`'s `useDataTable` installs the\n * default preset.\n */\nexport function useDataTable<\n T,\n S extends TableState = never,\n const Fs extends readonly AnyFeature[] = [],\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(\n options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {\n features?: Fs\n },\n): UseDataTableResult<\n SchemaRow<T, Sch>,\n TableStateFor<S, Fs, SchemaRow<T, Sch>>,\n M,\n [Sch] extends [TableSchema] ? unknown : T,\n ApiOf<Fs, SchemaRow<T, Sch>>\n>\nexport function useDataTable(options: Options): unknown {\n const ref = useRef<Instance | null>(null)\n // Created during the first render, deferred: its async work (fetcher, searchFn) starts in the\n // mount effect, never on the server.\n if (ref.current === null) {\n ref.current = createInstance(options)\n // React 18's development StrictMode discards the first mount render, ref included (React 19\n // keeps it): that render's table never mounts, so release it once the render is over. A\n // render that commits after this (one that yielded) gets a new table at mount (`recreate`).\n if (\n process.env.NODE_ENV !== 'production' &&\n typeof window !== 'undefined' &&\n reactVersion.startsWith('18.')\n ) {\n const inst = ref.current\n queueMicrotask(() => release(inst))\n }\n }\n const inst = ref.current\n const table = inst.table\n const [, rerender] = useReducer((n: number) => n + 1, 0)\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n // Replaced or destroyed meanwhile (`<Activity>`): nothing to subscribe to.\n if (inst.table !== table || inst.destroyed) return () => {}\n return table.subscribe(() => {\n inst.version++\n if (inst.syncing) inst.selfCaused = true\n onChange()\n })\n },\n [inst, table],\n )\n const getSnapshot = useCallback(() => snapshot(inst, table), [inst, table])\n const getServerSnapshot = useCallback(() => serverSnapshot(inst, table), [inst, table])\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n\n // Hydration commit (§7.2): before any layout effect can change the table, the snapshot React\n // hydrated with must still be the live one, else React replaces the server HTML at once.\n useInsertionEffect(() => checkHydration(inst), [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.mounted = true\n // Destroyed while hidden (`<Activity>`): a new table, from the latest options.\n if (inst.destroyed) {\n recreate(inst)\n startTable(inst.table)\n rerender()\n } else {\n // The deferred fetch / searchFn starts now; its status shows before paint.\n startTable(inst.table)\n if (snapshot(inst, inst.table) !== view) rerender()\n }\n return () => {\n inst.mounted = false\n // Deferred: the StrictMode effect re-run mounts again synchronously and keeps the table.\n queueMicrotask(() => {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n })\n }\n }, [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.latest = options\n const selfCaused = inst.selfCaused\n inst.selfCaused = false\n if (!inst.destroyed) sync(inst, options, selfCaused)\n deliver(inst)\n })\n\n return view\n}\n\n/** Dev (React 18): destroys a table created in render unless it mounted (or was destroyed). */\nfunction release(inst: Instance) {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n}\n\nfunction createInstance(options: Options): Instance {\n const inst: Instance = {\n table: undefined as unknown as AnyTable,\n destroyed: false,\n mounted: false,\n latest: options,\n synced: options,\n wrappers: {\n onStateChange: (updater) => (inst.latest.onStateChange as Callback)(updater),\n onDiagnostic: (d: Diagnostic) => {\n if (inst.rendering === 0) {\n ;(inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined)?.(d)\n return\n }\n if (inst.queue === undefined) {\n inst.queue = []\n // Delivered by the next layout effect, or here when this render never commits.\n queueMicrotask(() => deliver(inst))\n }\n inst.queue.push(d)\n },\n fetcher: (params) => (inst.latest.fetcher as Callback)(params),\n },\n queue: undefined,\n rendering: 0,\n syncing: false,\n selfCaused: false,\n selfData: false,\n version: 0,\n view: undefined,\n server: undefined,\n hydrating: false,\n seen: options,\n // Development only (`checkUnstable`): no Map / Set per table in production.\n ...(process.env.NODE_ENV !== 'production' ? { unstable: new Map(), warned: new Set() } : {}),\n }\n // The version checks are development-only (§8.5): production bundles no registry.\n if (process.env.NODE_ENV !== 'production' && !registered) {\n registered = true\n registerPackage('@datakable/react', version)\n }\n build(inst, options)\n return inst\n}\n\n/**\n * The stable wrapper of callback `k`. The fetcher's also carries the server source of the user's\n * `withFetcher` fetcher (§7.1), which is what makes the table load through it.\n */\nfunction wrapper(inst: Instance, k: CallbackKey, v: unknown): Callback {\n const w = inst.wrappers[k]\n if (k === 'fetcher') {\n ;(w as unknown as Record<symbol, unknown>)[SERVER_SOURCE] = (v as Record<symbol, unknown>)[\n SERVER_SOURCE\n ]\n }\n return w\n}\n\nfunction build(inst: Instance, options: Options) {\n const init: Options = { ...options }\n for (const k of CALLBACKS) {\n if (typeof options[k] === 'function') init[k] = wrapper(inst, k, options[k])\n }\n inst.rendering++\n try {\n // Deferred (§7.2): rendering starts no fetch / searchFn (none at all on the server, where\n // effects never run); the mount effect starts it.\n inst.table = createDeferred(() => createTable(init as never)) as unknown as AnyTable\n } finally {\n inst.rendering--\n }\n inst.synced = options\n inst.seen = options\n inst.view = undefined\n inst.server = undefined\n}\n\nfunction recreate(inst: Instance) {\n build(inst, inst.latest)\n inst.destroyed = false\n}\n\n/** The view of the table's snapshot, cached on (table, state, row model, notifications). */\nfunction snapshot(inst: Instance, table: AnyTable): object {\n inst.rendering++\n try {\n const state = table.getState()\n const rowModel = table.getRowModel()\n const v = inst.view\n if (v && v.table === table && v.version === inst.version) {\n const value = v.value as { state: unknown; rowModel: unknown }\n if (value.state === state && value.rowModel === rowModel) return value\n }\n const value = Object.create(table, {\n state: { value: state, enumerable: true },\n rowModel: { value: rowModel, enumerable: true },\n }) as object\n inst.view = { table, version: inst.version, value }\n return value\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * `getServerSnapshot` (§7.2): the view of the table at its creation. React reads it on the server\n * and while hydrating, so both render the same snapshot; async work never ran in it.\n */\nfunction serverSnapshot(inst: Instance, table: AnyTable): object {\n if (inst.table !== table) return snapshot(inst, table)\n // On the client React reads it only to hydrate.\n if (typeof window !== 'undefined') inst.hydrating = true\n const s = inst.server\n if (s && s.table === table) return s.value\n const value = snapshot(inst, table)\n inst.server = { table, value }\n return value\n}\n\n/** `DK_HYDRATION_MISMATCH`: what differs between the hydrated (server) view and the live one. */\nfunction checkHydration(inst: Instance) {\n if (!inst.hydrating) return\n inst.hydrating = false\n const server = inst.server\n if (!server || server.table !== inst.table) return\n const live = snapshot(inst, inst.table) as { state: TableState; rowModel: unknown }\n const hydrated = server.value as { state: TableState; rowModel: unknown }\n if (live === hydrated) return\n const slices: string[] = []\n for (const k of new Set([...Object.keys(hydrated.state), ...Object.keys(live.state)])) {\n if (!Object.is(hydrated.state[k], live.state[k])) slices.push(k)\n }\n if (slices.length === 0) {\n if (live.rowModel === hydrated.rowModel) return\n slices.push('rows')\n }\n // Delivered to onDiagnostic by the layout effect (no update during the commit).\n inst.rendering++\n try {\n emitTableDiagnostic(\n inst.table,\n 'DK_HYDRATION_MISMATCH',\n { slices },\n { trigger: 'hydrate', phase: 'hydrate' },\n )\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * Forwards the changed options with one `setOptions` call. In the re-render caused by that call,\n * values recomputed from the same inputs (same-shape `columns`, `data` with equal rows, a `rowKey`\n * function) are not forwarded again: an inline `columns` / `data` would otherwise loop. A `data`\n * that still differs is forwarded at most once per chain of self-caused re-renders, so rows that\n * are new on every render (`data: [{ … }]` with nested objects) re-ingest but never hang.\n */\nfunction sync(inst: Instance, options: Options, selfCaused: boolean) {\n // Written out (not a module-level flag) so bundlers fold it while parsing (§8.2). The re-render\n // a sync causes is not counted: under `<DataTable columns>` it reuses the props (count reset).\n if (process.env.NODE_ENV !== 'production' && !selfCaused) checkUnstable(inst, options)\n const prev = inst.synced\n if (!selfCaused) inst.selfData = false\n let partial: Record<string, unknown> | undefined\n for (const k of SYNCED) {\n const v = options[k]\n const p = prev[k]\n if (Object.is(v, p)) continue\n let forward: unknown = v\n switch (k) {\n case 'onStateChange':\n case 'onDiagnostic':\n case 'fetcher': {\n const on = typeof v === 'function'\n if (on === (typeof p === 'function')) continue\n forward = on ? wrapper(inst, k, v) : undefined\n break\n }\n case 'state':\n if (sameSlices(v, p)) continue\n break\n case 'interceptors':\n if (sameItems(v, p)) continue\n break\n case 'data':\n // Two empty arrays hold nothing to ingest (e.g. an inline `data: []` with a fetcher).\n if (isEmpty(v) && sameItems(v, p)) continue\n if (selfCaused) {\n if (inst.selfData || sameRows(v, p)) continue\n inst.selfData = true\n }\n break\n case 'columns':\n if (selfCaused && sameShape(v, p)) continue\n break\n case 'rowKey':\n if (selfCaused && typeof v === 'function' && typeof p === 'function') continue\n break\n }\n partial ??= {}\n partial[k] = forward\n }\n if (partial === undefined) return\n inst.syncing = true\n try {\n inst.table.setOptions(partial)\n } finally {\n inst.syncing = false\n }\n const synced = { ...prev }\n for (const k of Object.keys(partial)) synced[k] = options[k]\n inst.synced = synced\n}\n\n/** Delivers the `onDiagnostic` calls queued while rendering. */\nfunction deliver(inst: Instance) {\n const queue = inst.queue\n if (queue === undefined) return\n inst.queue = undefined\n const sink = inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined\n for (const d of queue) {\n try {\n sink?.(d)\n } catch (e) {\n // Like a failing sink in the hub: the logger never breaks the table.\n console.error('[DataKable] onDiagnostic threw', e)\n }\n }\n}\n\n// --- comparisons ---------------------------------------------------------------------------------\n\nconst isObject = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === 'object'\n\n/** Controlled slices: the same defined slices, each `Object.is`-equal. */\nfunction sameSlices(a: unknown, b: unknown): boolean {\n if (!isObject(a) || !isObject(b)) return false\n const defined = (o: Record<string, unknown>) => Object.keys(o).filter((k) => o[k] !== undefined)\n const keys = defined(a)\n if (keys.length !== defined(b).length) return false\n for (const k of keys) if (!Object.is(a[k], b[k])) return false\n return true\n}\n\nconst isEmpty = (v: unknown) => Array.isArray(v) && v.length === 0\n\n/** Two arrays with the same items (by reference). */\nfunction sameItems(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false\n return true\n}\n\nconst loose = (v: unknown) => typeof v === 'function' || isObject(v)\n\n/**\n * Two arrays of equal items: each pair the same reference, or objects with the same own keys and\n * `Object.is`-equal values. Rows (`data: rows.map((r) => ({ ...r }))` recomputed in a re-render):\n * exactly that. Columns (`shape`): equal primitive values, while functions and nested objects\n * (`format`, `cell`, `filter`, …) may be new references of the same type.\n */\nfunction sameRows(a: unknown, b: unknown, shape?: boolean): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x: unknown = a[i]\n const y: unknown = b[i]\n if (Object.is(x, y)) continue\n if (!isObject(x) || !isObject(y)) return false\n const keys = Object.keys(x)\n if (keys.length !== Object.keys(y).length) return false\n for (const k of keys) {\n if (!Object.hasOwn(y, k)) return false\n const vx = x[k]\n const vy = y[k]\n if (Object.is(vx, vy)) continue\n if (!(shape && loose(vx) && loose(vy) && typeof vx === typeof vy)) return false\n }\n }\n return true\n}\n\n/** Column arrays of the same shape (see {@link sameRows}). */\nconst sameShape = (a: unknown, b: unknown) => sameRows(a, b, true)\n\n// --- dev: DK_UNSTABLE_COLUMNS / DK_UNSTABLE_OPTION -----------------------------------------------\n\n/** The first function option of a feature that is a new reference: `features[i].<option>`. */\nfunction changedFeatureOption(a: unknown, b: unknown): string | undefined {\n if (!Array.isArray(a) || !Array.isArray(b) || a === b) return undefined\n for (let i = 0; i < a.length; i++) {\n const f = a[i] as AnyFeature | undefined\n const g = b[i] as AnyFeature | undefined\n if (!f || !g || f === g || f.name !== g.name) continue\n if (!isOptionsDefinition(f.options) || !isOptionsDefinition(g.options)) continue\n const fv = f.options.values\n const gv = g.options.values\n if (!fv || !gv) continue\n for (const k of Object.keys(fv)) {\n if (typeof fv[k] === 'function' && fv[k] !== gv[k]) return `features[${i}].${k}`\n }\n }\n return undefined\n}\n\n/** Counts renders in a row that pass a new reference for the same thing; reports each once. */\nfunction checkUnstable(inst: Instance, options: Options) {\n const seen = inst.seen\n inst.seen = options\n const changed = (k: string) => !Object.is(options[k], seen[k])\n const fn = (k: string) =>\n changed(k) && typeof options[k] === 'function' && typeof seen[k] === 'function'\n track(inst, 'columns', changed('columns') && sameShape(options.columns, seen.columns))\n track(inst, 'data', changed('data') && sameRows(options.data, seen.data))\n track(inst, 'fetcher', fn('fetcher'))\n track(inst, 'rowKey', fn('rowKey'))\n const option = changedFeatureOption(options.features, seen.features)\n track(inst, 'features', option !== undefined, option)\n}\n\nfunction track(inst: Instance, key: string, unstable: boolean, option = key) {\n const seen = inst.unstable as Map<string, number>\n const warned = inst.warned as Set<string>\n const n = unstable ? (seen.get(key) ?? 0) + 1 : 0\n seen.set(key, n)\n if (n < UNSTABLE_AFTER || warned.has(key)) return\n warned.add(key)\n if (key === 'columns') emitTableDiagnostic(inst.table, 'DK_UNSTABLE_COLUMNS', { renders: n })\n else emitTableDiagnostic(inst.table, 'DK_UNSTABLE_OPTION', { option, renders: n })\n}\n","{\n \"name\": \"@datakable/react\",\n \"version\": \"2.0.2\",\n \"description\": \"React bindings for DataKable — useDataTable hook and DataTable component.\",\n \"license\": \"MIT\",\n \"author\": \"Supakit Kitjanabumrungsak\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Ink01101011/datakable.git\",\n \"directory\": \"packages/react\"\n },\n \"homepage\": \"https://github.com/Ink01101011/datakable#readme\",\n \"bugs\": \"https://github.com/Ink01101011/datakable/issues\",\n \"keywords\": [\n \"react\",\n \"react-table\",\n \"datatable\",\n \"data-table\",\n \"data-grid\",\n \"datagrid\",\n \"table\",\n \"typescript\",\n \"type-safe\",\n \"headless\",\n \"headless-ui\",\n \"zero-config\",\n \"sorting\",\n \"filtering\",\n \"search\",\n \"pagination\",\n \"react-hooks\",\n \"react-component\",\n \"use-data-table\",\n \"ssr\",\n \"rsc\"\n ],\n \"type\": \"module\",\n \"sideEffects\": [\n \"./dist/messages.js\",\n \"./dist/messages.cjs\",\n \"./dist/styles.css\"\n ],\n \"engines\": {\n \"node\": \">=18.18.0\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"typesVersions\": {\n \"*\": {\n \"messages\": [\n \"./dist/messages.d.ts\"\n ],\n \"styles.css\": [\n \"./dist/styles.css.d.ts\"\n ]\n }\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./messages\": {\n \"import\": {\n \"types\": \"./dist/messages.d.ts\",\n \"default\": \"./dist/messages.js\"\n },\n \"require\": {\n \"types\": \"./dist/messages.d.cts\",\n \"default\": \"./dist/messages.cjs\"\n }\n },\n \"./styles.css\": {\n \"types\": {\n \"import\": \"./dist/styles.css.d.ts\",\n \"require\": \"./dist/styles.css.d.cts\"\n },\n \"default\": \"./dist/styles.css\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup && node ../../scripts/write-styles-dts.mjs\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc -p tsconfig.json\",\n \"check:pkg\": \"publint --strict && attw --pack . && node scripts/check-catalog.mjs\",\n \"check:catalog\": \"node scripts/check-catalog.mjs\"\n },\n \"dependencies\": {\n \"@datakable/core\": \"workspace:^\"\n },\n \"peerDependencies\": {\n \"react\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n }\n }\n}\n"],"mappings":"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","names":["reactVersion","inst","value"]}
1
+ {"version":3,"sources":["../src/use-data-table.ts","../package.json"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n type ApiOf,\n type ColumnDef,\n type CreateTableOptions,\n createDeferred,\n createTable,\n type Diagnostic,\n emitTableDiagnostic,\n type HasSchema,\n type InvalidRowsMode,\n isOptionsDefinition,\n keepDiagnostics,\n type RowModel,\n registerPackage,\n type SchemaRow,\n SERVER_SOURCE,\n startTable,\n type Table,\n type TableSchema,\n type TableState,\n type TableStateFor,\n} from '@datakable/core'\nimport {\n type ReactNode,\n version as reactVersion,\n useCallback,\n useEffect,\n useInsertionEffect,\n useLayoutEffect,\n useReducer,\n useRef,\n useSyncExternalStore,\n} from 'react'\nimport { version } from '../package.json'\nimport { reactDiagnostics } from './codes'\n\n// Registers the (development-only) definitions where they are emitted, so bundlers keep them.\nkeepDiagnostics(reactDiagnostics)\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n/**\n * `useDataTable` options: `createTable`'s (§3.2), with `cell` / `invalidCell` returning a\n * `ReactNode` (§10). Read once, at creation: `features`, `schema`, `invalidRows`, `initialState`,\n * `name`, `timeout`, `strict`, `diagnostics`. Every other option follows the latest render.\n */\nexport type UseDataTableOptions<\n T,\n S extends TableState = TableState,\n Sch = undefined,\n M extends InvalidRowsMode = 'drop',\n> = Omit<CreateTableOptions<T, S, Sch, M>, 'columns'> & {\n /**\n * Compared by reference (§10): a new array tells the table the columns changed. Define them\n * outside the component or memoise them (`DK_UNSTABLE_COLUMNS` in development).\n */\n columns?: readonly ColumnDef<SchemaRow<T, Sch>, ReactNode>[]\n}\n\n/**\n * What `useDataTable` returns: the table (its methods and the installed features' APIs) with the\n * `state` and `rowModel` of this render. A new object whenever the table notifies, so it can be a\n * dependency of `useMemo` / `memo` children; the same object while nothing changed.\n */\nexport type UseDataTableResult<\n T,\n S extends TableState = TableState,\n M extends InvalidRowsMode = 'drop',\n In = T,\n Api = unknown,\n> = Table<T, S, M, In> &\n Api & {\n /** The state snapshot of this render (`getState()`). */\n readonly state: S\n /** The row model of this render (`getRowModel()`, §6.6): rows, counts, status. */\n readonly rowModel: RowModel<T, M>\n }\n\ntype Options = Record<string, unknown> & { features?: readonly AnyFeature[] }\ntype AnyTable = Table<unknown, TableState> & Record<string, unknown>\ntype Callback = (arg: never) => unknown\n\n/** Options forwarded through `setOptions` when they change; the rest are read once (§3.4). */\nconst SYNCED = [\n 'data',\n 'columns',\n 'rowKey',\n 'state',\n 'onStateChange',\n 'interceptors',\n 'onDiagnostic',\n 'fetcher',\n 'rowCount',\n] as const\n\n/** Given to the table as stable wrappers that call the latest prop (latest-ref). */\nconst CALLBACKS = ['onStateChange', 'onDiagnostic', 'fetcher'] as const\ntype CallbackKey = (typeof CALLBACKS)[number]\n\n/** Renders in a row with a new reference before `DK_UNSTABLE_*` is reported. */\nconst UNSTABLE_AFTER = 2\n\ninterface Instance {\n table: AnyTable\n destroyed: boolean\n mounted: boolean\n /** The options of the latest committed render (what the wrappers call). */\n latest: Options\n /** The option values the table has (user values; callbacks count by presence). */\n synced: Options\n readonly wrappers: Record<CallbackKey, Callback>\n /** `onDiagnostic` calls made while rendering, delivered after the commit. */\n queue: Diagnostic[] | undefined\n rendering: number\n /** Inside the hook's own `setOptions` call. */\n syncing: boolean\n /** That call notified: the next commit is the re-render it caused. */\n selfCaused: boolean\n /**\n * `data` was forwarded in a self-caused re-render. Rows that differ on every render (nested\n * objects, computed fields) would otherwise ingest → notify → re-render forever: the next\n * self-caused re-render keeps the data the table has.\n */\n selfData: boolean\n /** Notifications seen; part of the view cache key (a notification is never silent, §6.6). */\n version: number\n view: { table: AnyTable; version: number; value: object } | undefined\n /**\n * SSR (§7.2): the view of `table` at its creation — initial state, controlled state and data /\n * initialData, no async result (the table is created deferred). `getServerSnapshot`.\n */\n server: { table: AnyTable; value: object } | undefined\n /** React read `getServerSnapshot` on the client: this render hydrates server HTML. */\n hydrating: boolean\n // Dev: DK_UNSTABLE_* bookkeeping.\n /** The options of the previous committed render. */\n seen: Options\n /** Development only (`checkUnstable`). */\n unstable?: Map<string, number>\n warned?: Set<string>\n}\n\nlet registered = false\n\n/**\n * Binds a table to a component (§10): the table is created once per component instance and\n * destroyed on unmount; renders read it through `useSyncExternalStore` (with\n * `getServerSnapshot`), and options are synced with `table.setOptions` in a layout effect, never\n * during render.\n *\n * - `features` (and the other read-once options) are read at creation: a new inline `features`\n * array never recreates the table.\n * - `fetcher`, `onStateChange` and `onDiagnostic` may be inline functions: the table always calls\n * the latest one, and a new reference never refetches (call `refetch()` when a value the fetcher\n * reads changes).\n * - `columns`, `data` and a `rowKey` function are compared by reference: memoise them.\n * - Controlled slices (§3.2): pass `state` and `onStateChange`; changes come back through `state`.\n * - SSR (§7.2): rendering starts no async work. The fetcher's first request and a `searchFn` for an\n * initial query start after the commit (`status: 'pending'` until then; `DK_SSR_ASYNC_DEFERRED`\n * on the server), unless `initialData` already holds their result. `initialState` (e.g. parsed\n * from the URL) applies on the server: client-mode features filter / search / sort the HTML.\n * `getServerSnapshot` is the view at creation; a table that changed before the hydration commit\n * reports `DK_HYDRATION_MISMATCH`.\n *\n * `@datakable/react` installs no features by default; `datakable`'s `useDataTable` installs the\n * default preset.\n */\nexport function useDataTable<\n T,\n S extends TableState = never,\n const Fs extends readonly AnyFeature[] = [],\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(\n options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {\n features?: Fs\n },\n): UseDataTableResult<\n SchemaRow<T, Sch>,\n TableStateFor<S, Fs, SchemaRow<T, Sch>>,\n M,\n HasSchema<Sch> extends true ? unknown : T,\n ApiOf<Fs, SchemaRow<T, Sch>>\n>\nexport function useDataTable(options: Options): unknown {\n const ref = useRef<Instance | null>(null)\n // Created during the first render, deferred: its async work (fetcher, searchFn) starts in the\n // mount effect, never on the server.\n if (ref.current === null) {\n ref.current = createInstance(options)\n // React 18's development StrictMode discards the first mount render, ref included (React 19\n // keeps it): that render's table never mounts, so release it once the render is over. A\n // render that commits after this (one that yielded) gets a new table at mount (`recreate`).\n if (\n process.env.NODE_ENV !== 'production' &&\n typeof window !== 'undefined' &&\n reactVersion.startsWith('18.')\n ) {\n const inst = ref.current\n queueMicrotask(() => release(inst))\n }\n }\n const inst = ref.current\n const table = inst.table\n const [, rerender] = useReducer((n: number) => n + 1, 0)\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n // Replaced or destroyed meanwhile (`<Activity>`): nothing to subscribe to.\n if (inst.table !== table || inst.destroyed) return () => {}\n return table.subscribe(() => {\n inst.version++\n if (inst.syncing) inst.selfCaused = true\n onChange()\n })\n },\n [inst, table],\n )\n const getSnapshot = useCallback(() => snapshot(inst, table), [inst, table])\n const getServerSnapshot = useCallback(() => serverSnapshot(inst, table), [inst, table])\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n\n // Hydration commit (§7.2): before any layout effect can change the table, the snapshot React\n // hydrated with must still be the live one, else React replaces the server HTML at once.\n useInsertionEffect(() => checkHydration(inst), [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.mounted = true\n // Destroyed while hidden (`<Activity>`): a new table, from the latest options.\n if (inst.destroyed) {\n recreate(inst)\n startTable(inst.table)\n rerender()\n } else {\n // The deferred fetch / searchFn starts now; its status shows before paint.\n startTable(inst.table)\n if (snapshot(inst, inst.table) !== view) rerender()\n }\n return () => {\n inst.mounted = false\n // Deferred: the StrictMode effect re-run mounts again synchronously and keeps the table.\n queueMicrotask(() => {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n })\n }\n }, [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.latest = options\n const selfCaused = inst.selfCaused\n inst.selfCaused = false\n if (!inst.destroyed) sync(inst, options, selfCaused)\n deliver(inst)\n })\n\n return view\n}\n\n/** Dev (React 18): destroys a table created in render unless it mounted (or was destroyed). */\nfunction release(inst: Instance) {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n}\n\nfunction createInstance(options: Options): Instance {\n const inst: Instance = {\n table: undefined as unknown as AnyTable,\n destroyed: false,\n mounted: false,\n latest: options,\n synced: options,\n wrappers: {\n onStateChange: (updater) => (inst.latest.onStateChange as Callback)(updater),\n onDiagnostic: (d: Diagnostic) => {\n if (inst.rendering === 0) {\n ;(inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined)?.(d)\n return\n }\n if (inst.queue === undefined) {\n inst.queue = []\n // Delivered by the next layout effect, or here when this render never commits.\n queueMicrotask(() => deliver(inst))\n }\n inst.queue.push(d)\n },\n fetcher: (params) => (inst.latest.fetcher as Callback)(params),\n },\n queue: undefined,\n rendering: 0,\n syncing: false,\n selfCaused: false,\n selfData: false,\n version: 0,\n view: undefined,\n server: undefined,\n hydrating: false,\n seen: options,\n // Development only (`checkUnstable`): no Map / Set per table in production.\n ...(process.env.NODE_ENV !== 'production' ? { unstable: new Map(), warned: new Set() } : {}),\n }\n // The version checks are development-only (§8.5): production bundles no registry.\n if (process.env.NODE_ENV !== 'production' && !registered) {\n registered = true\n registerPackage('@datakable/react', version)\n }\n build(inst, options)\n return inst\n}\n\n/**\n * The stable wrapper of callback `k`. The fetcher's also carries the server source of the user's\n * `withFetcher` fetcher (§7.1), which is what makes the table load through it.\n */\nfunction wrapper(inst: Instance, k: CallbackKey, v: unknown): Callback {\n const w = inst.wrappers[k]\n if (k === 'fetcher') {\n ;(w as unknown as Record<symbol, unknown>)[SERVER_SOURCE] = (v as Record<symbol, unknown>)[\n SERVER_SOURCE\n ]\n }\n return w\n}\n\nfunction build(inst: Instance, options: Options) {\n const init: Options = { ...options }\n for (const k of CALLBACKS) {\n if (typeof options[k] === 'function') init[k] = wrapper(inst, k, options[k])\n }\n inst.rendering++\n try {\n // Deferred (§7.2): rendering starts no fetch / searchFn (none at all on the server, where\n // effects never run); the mount effect starts it.\n inst.table = createDeferred(() => createTable(init as never)) as unknown as AnyTable\n } finally {\n inst.rendering--\n }\n inst.synced = options\n inst.seen = options\n inst.view = undefined\n inst.server = undefined\n}\n\nfunction recreate(inst: Instance) {\n build(inst, inst.latest)\n inst.destroyed = false\n}\n\n/** The view of the table's snapshot, cached on (table, state, row model, notifications). */\nfunction snapshot(inst: Instance, table: AnyTable): object {\n inst.rendering++\n try {\n const state = table.getState()\n const rowModel = table.getRowModel()\n const v = inst.view\n if (v && v.table === table && v.version === inst.version) {\n const value = v.value as { state: unknown; rowModel: unknown }\n if (value.state === state && value.rowModel === rowModel) return value\n }\n const value = Object.create(table, {\n state: { value: state, enumerable: true },\n rowModel: { value: rowModel, enumerable: true },\n }) as object\n inst.view = { table, version: inst.version, value }\n return value\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * `getServerSnapshot` (§7.2): the view of the table at its creation. React reads it on the server\n * and while hydrating, so both render the same snapshot; async work never ran in it.\n */\nfunction serverSnapshot(inst: Instance, table: AnyTable): object {\n if (inst.table !== table) return snapshot(inst, table)\n // On the client React reads it only to hydrate.\n if (typeof window !== 'undefined') inst.hydrating = true\n const s = inst.server\n if (s && s.table === table) return s.value\n const value = snapshot(inst, table)\n inst.server = { table, value }\n return value\n}\n\n/** `DK_HYDRATION_MISMATCH`: what differs between the hydrated (server) view and the live one. */\nfunction checkHydration(inst: Instance) {\n if (!inst.hydrating) return\n inst.hydrating = false\n const server = inst.server\n if (!server || server.table !== inst.table) return\n const live = snapshot(inst, inst.table) as { state: TableState; rowModel: unknown }\n const hydrated = server.value as { state: TableState; rowModel: unknown }\n if (live === hydrated) return\n const slices: string[] = []\n for (const k of new Set([...Object.keys(hydrated.state), ...Object.keys(live.state)])) {\n if (!Object.is(hydrated.state[k], live.state[k])) slices.push(k)\n }\n if (slices.length === 0) {\n if (live.rowModel === hydrated.rowModel) return\n slices.push('rows')\n }\n // Delivered to onDiagnostic by the layout effect (no update during the commit).\n inst.rendering++\n try {\n emitTableDiagnostic(\n inst.table,\n 'DK_HYDRATION_MISMATCH',\n { slices },\n { trigger: 'hydrate', phase: 'hydrate' },\n )\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * Forwards the changed options with one `setOptions` call. In the re-render caused by that call,\n * values recomputed from the same inputs (same-shape `columns`, `data` with equal rows, a `rowKey`\n * function) are not forwarded again: an inline `columns` / `data` would otherwise loop. A `data`\n * that still differs is forwarded at most once per chain of self-caused re-renders, so rows that\n * are new on every render (`data: [{ … }]` with nested objects) re-ingest but never hang.\n */\nfunction sync(inst: Instance, options: Options, selfCaused: boolean) {\n // Written out (not a module-level flag) so bundlers fold it while parsing (§8.2). The re-render\n // a sync causes is not counted: under `<DataTable columns>` it reuses the props (count reset).\n if (process.env.NODE_ENV !== 'production' && !selfCaused) checkUnstable(inst, options)\n const prev = inst.synced\n if (!selfCaused) inst.selfData = false\n let partial: Record<string, unknown> | undefined\n for (const k of SYNCED) {\n const v = options[k]\n const p = prev[k]\n if (Object.is(v, p)) continue\n let forward: unknown = v\n switch (k) {\n case 'onStateChange':\n case 'onDiagnostic':\n case 'fetcher': {\n const on = typeof v === 'function'\n if (on === (typeof p === 'function')) continue\n forward = on ? wrapper(inst, k, v) : undefined\n break\n }\n case 'state':\n if (sameSlices(v, p)) continue\n break\n case 'interceptors':\n if (sameItems(v, p)) continue\n break\n case 'data':\n // Two empty arrays hold nothing to ingest (e.g. an inline `data: []` with a fetcher).\n if (isEmpty(v) && sameItems(v, p)) continue\n if (selfCaused) {\n if (inst.selfData || sameRows(v, p)) continue\n inst.selfData = true\n }\n break\n case 'columns':\n if (selfCaused && sameShape(v, p)) continue\n break\n case 'rowKey':\n if (selfCaused && typeof v === 'function' && typeof p === 'function') continue\n break\n }\n partial ??= {}\n partial[k] = forward\n }\n if (partial === undefined) return\n inst.syncing = true\n try {\n inst.table.setOptions(partial)\n } finally {\n inst.syncing = false\n }\n const synced = { ...prev }\n for (const k of Object.keys(partial)) synced[k] = options[k]\n inst.synced = synced\n}\n\n/** Delivers the `onDiagnostic` calls queued while rendering. */\nfunction deliver(inst: Instance) {\n const queue = inst.queue\n if (queue === undefined) return\n inst.queue = undefined\n const sink = inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined\n for (const d of queue) {\n try {\n sink?.(d)\n } catch (e) {\n // Like a failing sink in the hub: the logger never breaks the table.\n console.error('[DataKable] onDiagnostic threw', e)\n }\n }\n}\n\n// --- comparisons ---------------------------------------------------------------------------------\n\nconst isObject = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === 'object'\n\n/** Controlled slices: the same defined slices, each `Object.is`-equal. */\nfunction sameSlices(a: unknown, b: unknown): boolean {\n if (!isObject(a) || !isObject(b)) return false\n const defined = (o: Record<string, unknown>) => Object.keys(o).filter((k) => o[k] !== undefined)\n const keys = defined(a)\n if (keys.length !== defined(b).length) return false\n for (const k of keys) if (!Object.is(a[k], b[k])) return false\n return true\n}\n\nconst isEmpty = (v: unknown) => Array.isArray(v) && v.length === 0\n\n/** Two arrays with the same items (by reference). */\nfunction sameItems(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false\n return true\n}\n\nconst loose = (v: unknown) => typeof v === 'function' || isObject(v)\n\n/**\n * Two arrays of equal items: each pair the same reference, or objects with the same own keys and\n * `Object.is`-equal values. Rows (`data: rows.map((r) => ({ ...r }))` recomputed in a re-render):\n * exactly that. Columns (`shape`): equal primitive values, while functions and nested objects\n * (`format`, `cell`, `filter`, …) may be new references of the same type.\n */\nfunction sameRows(a: unknown, b: unknown, shape?: boolean): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x: unknown = a[i]\n const y: unknown = b[i]\n if (Object.is(x, y)) continue\n if (!isObject(x) || !isObject(y)) return false\n const keys = Object.keys(x)\n if (keys.length !== Object.keys(y).length) return false\n for (const k of keys) {\n if (!Object.hasOwn(y, k)) return false\n const vx = x[k]\n const vy = y[k]\n if (Object.is(vx, vy)) continue\n if (!(shape && loose(vx) && loose(vy) && typeof vx === typeof vy)) return false\n }\n }\n return true\n}\n\n/** Column arrays of the same shape (see {@link sameRows}). */\nconst sameShape = (a: unknown, b: unknown) => sameRows(a, b, true)\n\n// --- dev: DK_UNSTABLE_COLUMNS / DK_UNSTABLE_OPTION -----------------------------------------------\n\n/** The first function option of a feature that is a new reference: `features[i].<option>`. */\nfunction changedFeatureOption(a: unknown, b: unknown): string | undefined {\n if (!Array.isArray(a) || !Array.isArray(b) || a === b) return undefined\n for (let i = 0; i < a.length; i++) {\n const f = a[i] as AnyFeature | undefined\n const g = b[i] as AnyFeature | undefined\n if (!f || !g || f === g || f.name !== g.name) continue\n if (!isOptionsDefinition(f.options) || !isOptionsDefinition(g.options)) continue\n const fv = f.options.values\n const gv = g.options.values\n if (!fv || !gv) continue\n for (const k of Object.keys(fv)) {\n if (typeof fv[k] === 'function' && fv[k] !== gv[k]) return `features[${i}].${k}`\n }\n }\n return undefined\n}\n\n/** Counts renders in a row that pass a new reference for the same thing; reports each once. */\nfunction checkUnstable(inst: Instance, options: Options) {\n const seen = inst.seen\n inst.seen = options\n const changed = (k: string) => !Object.is(options[k], seen[k])\n const fn = (k: string) =>\n changed(k) && typeof options[k] === 'function' && typeof seen[k] === 'function'\n track(inst, 'columns', changed('columns') && sameShape(options.columns, seen.columns))\n track(inst, 'data', changed('data') && sameRows(options.data, seen.data))\n track(inst, 'fetcher', fn('fetcher'))\n track(inst, 'rowKey', fn('rowKey'))\n const option = changedFeatureOption(options.features, seen.features)\n track(inst, 'features', option !== undefined, option)\n}\n\nfunction track(inst: Instance, key: string, unstable: boolean, option = key) {\n const seen = inst.unstable as Map<string, number>\n const warned = inst.warned as Set<string>\n const n = unstable ? (seen.get(key) ?? 0) + 1 : 0\n seen.set(key, n)\n if (n < UNSTABLE_AFTER || warned.has(key)) return\n warned.add(key)\n if (key === 'columns') emitTableDiagnostic(inst.table, 'DK_UNSTABLE_COLUMNS', { renders: n })\n else emitTableDiagnostic(inst.table, 'DK_UNSTABLE_OPTION', { option, renders: n })\n}\n","{\n \"name\": \"@datakable/react\",\n \"version\": \"2.0.3\",\n \"description\": \"React bindings for DataKable — useDataTable hook and DataTable component.\",\n \"license\": \"MIT\",\n \"author\": \"Supakit Kitjanabumrungsak\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Ink01101011/datakable.git\",\n \"directory\": \"packages/react\"\n },\n \"homepage\": \"https://github.com/Ink01101011/datakable#readme\",\n \"bugs\": \"https://github.com/Ink01101011/datakable/issues\",\n \"keywords\": [\n \"react\",\n \"react-table\",\n \"datatable\",\n \"data-table\",\n \"data-grid\",\n \"datagrid\",\n \"table\",\n \"typescript\",\n \"type-safe\",\n \"headless\",\n \"headless-ui\",\n \"zero-config\",\n \"sorting\",\n \"filtering\",\n \"search\",\n \"pagination\",\n \"react-hooks\",\n \"react-component\",\n \"use-data-table\",\n \"ssr\",\n \"rsc\"\n ],\n \"type\": \"module\",\n \"sideEffects\": [\n \"./dist/messages.js\",\n \"./dist/messages.cjs\",\n \"./dist/styles.css\"\n ],\n \"engines\": {\n \"node\": \">=18.18.0\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"typesVersions\": {\n \"*\": {\n \"messages\": [\n \"./dist/messages.d.ts\"\n ],\n \"styles.css\": [\n \"./dist/styles.css.d.ts\"\n ]\n }\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./messages\": {\n \"import\": {\n \"types\": \"./dist/messages.d.ts\",\n \"default\": \"./dist/messages.js\"\n },\n \"require\": {\n \"types\": \"./dist/messages.d.cts\",\n \"default\": \"./dist/messages.cjs\"\n }\n },\n \"./styles.css\": {\n \"types\": {\n \"import\": \"./dist/styles.css.d.ts\",\n \"require\": \"./dist/styles.css.d.cts\"\n },\n \"default\": \"./dist/styles.css\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup && node ../../scripts/write-styles-dts.mjs\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc -p tsconfig.json\",\n \"check:pkg\": \"publint --strict && attw --pack . && node scripts/check-catalog.mjs\",\n \"check:catalog\": \"node scripts/check-catalog.mjs\"\n },\n \"dependencies\": {\n \"@datakable/core\": \"workspace:^\"\n },\n \"peerDependencies\": {\n \"react\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n }\n }\n}\n"],"mappings":"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","names":["reactVersion","inst","value"]}
@@ -23,7 +23,7 @@ import {
23
23
  } from "react";
24
24
 
25
25
  // package.json
26
- var version = "2.0.2";
26
+ var version = "2.0.3";
27
27
 
28
28
  // src/use-data-table.ts
29
29
  import { reactDiagnostics } from "./codes.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/use-data-table.ts","../package.json"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n type ApiOf,\n type ColumnDef,\n type CreateTableOptions,\n createDeferred,\n createTable,\n type Diagnostic,\n emitTableDiagnostic,\n type InvalidRowsMode,\n isOptionsDefinition,\n keepDiagnostics,\n type RowModel,\n registerPackage,\n type SchemaRow,\n SERVER_SOURCE,\n startTable,\n type Table,\n type TableSchema,\n type TableState,\n type TableStateFor,\n} from '@datakable/core'\nimport {\n type ReactNode,\n version as reactVersion,\n useCallback,\n useEffect,\n useInsertionEffect,\n useLayoutEffect,\n useReducer,\n useRef,\n useSyncExternalStore,\n} from 'react'\nimport { version } from '../package.json'\nimport { reactDiagnostics } from './codes'\n\n// Registers the (development-only) definitions where they are emitted, so bundlers keep them.\nkeepDiagnostics(reactDiagnostics)\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n/**\n * `useDataTable` options: `createTable`'s (§3.2), with `cell` / `invalidCell` returning a\n * `ReactNode` (§10). Read once, at creation: `features`, `schema`, `invalidRows`, `initialState`,\n * `name`, `timeout`, `strict`, `diagnostics`. Every other option follows the latest render.\n */\nexport type UseDataTableOptions<\n T,\n S extends TableState = TableState,\n Sch = undefined,\n M extends InvalidRowsMode = 'drop',\n> = Omit<CreateTableOptions<T, S, Sch, M>, 'columns'> & {\n /**\n * Compared by reference (§10): a new array tells the table the columns changed. Define them\n * outside the component or memoise them (`DK_UNSTABLE_COLUMNS` in development).\n */\n columns?: readonly ColumnDef<SchemaRow<T, Sch>, ReactNode>[]\n}\n\n/**\n * What `useDataTable` returns: the table (its methods and the installed features' APIs) with the\n * `state` and `rowModel` of this render. A new object whenever the table notifies, so it can be a\n * dependency of `useMemo` / `memo` children; the same object while nothing changed.\n */\nexport type UseDataTableResult<\n T,\n S extends TableState = TableState,\n M extends InvalidRowsMode = 'drop',\n In = T,\n Api = unknown,\n> = Table<T, S, M, In> &\n Api & {\n /** The state snapshot of this render (`getState()`). */\n readonly state: S\n /** The row model of this render (`getRowModel()`, §6.6): rows, counts, status. */\n readonly rowModel: RowModel<T, M>\n }\n\ntype Options = Record<string, unknown> & { features?: readonly AnyFeature[] }\ntype AnyTable = Table<unknown, TableState> & Record<string, unknown>\ntype Callback = (arg: never) => unknown\n\n/** Options forwarded through `setOptions` when they change; the rest are read once (§3.4). */\nconst SYNCED = [\n 'data',\n 'columns',\n 'rowKey',\n 'state',\n 'onStateChange',\n 'interceptors',\n 'onDiagnostic',\n 'fetcher',\n 'rowCount',\n] as const\n\n/** Given to the table as stable wrappers that call the latest prop (latest-ref). */\nconst CALLBACKS = ['onStateChange', 'onDiagnostic', 'fetcher'] as const\ntype CallbackKey = (typeof CALLBACKS)[number]\n\n/** Renders in a row with a new reference before `DK_UNSTABLE_*` is reported. */\nconst UNSTABLE_AFTER = 2\n\ninterface Instance {\n table: AnyTable\n destroyed: boolean\n mounted: boolean\n /** The options of the latest committed render (what the wrappers call). */\n latest: Options\n /** The option values the table has (user values; callbacks count by presence). */\n synced: Options\n readonly wrappers: Record<CallbackKey, Callback>\n /** `onDiagnostic` calls made while rendering, delivered after the commit. */\n queue: Diagnostic[] | undefined\n rendering: number\n /** Inside the hook's own `setOptions` call. */\n syncing: boolean\n /** That call notified: the next commit is the re-render it caused. */\n selfCaused: boolean\n /**\n * `data` was forwarded in a self-caused re-render. Rows that differ on every render (nested\n * objects, computed fields) would otherwise ingest → notify → re-render forever: the next\n * self-caused re-render keeps the data the table has.\n */\n selfData: boolean\n /** Notifications seen; part of the view cache key (a notification is never silent, §6.6). */\n version: number\n view: { table: AnyTable; version: number; value: object } | undefined\n /**\n * SSR (§7.2): the view of `table` at its creation — initial state, controlled state and data /\n * initialData, no async result (the table is created deferred). `getServerSnapshot`.\n */\n server: { table: AnyTable; value: object } | undefined\n /** React read `getServerSnapshot` on the client: this render hydrates server HTML. */\n hydrating: boolean\n // Dev: DK_UNSTABLE_* bookkeeping.\n /** The options of the previous committed render. */\n seen: Options\n /** Development only (`checkUnstable`). */\n unstable?: Map<string, number>\n warned?: Set<string>\n}\n\nlet registered = false\n\n/**\n * Binds a table to a component (§10): the table is created once per component instance and\n * destroyed on unmount; renders read it through `useSyncExternalStore` (with\n * `getServerSnapshot`), and options are synced with `table.setOptions` in a layout effect, never\n * during render.\n *\n * - `features` (and the other read-once options) are read at creation: a new inline `features`\n * array never recreates the table.\n * - `fetcher`, `onStateChange` and `onDiagnostic` may be inline functions: the table always calls\n * the latest one, and a new reference never refetches (call `refetch()` when a value the fetcher\n * reads changes).\n * - `columns`, `data` and a `rowKey` function are compared by reference: memoise them.\n * - Controlled slices (§3.2): pass `state` and `onStateChange`; changes come back through `state`.\n * - SSR (§7.2): rendering starts no async work. The fetcher's first request and a `searchFn` for an\n * initial query start after the commit (`status: 'pending'` until then; `DK_SSR_ASYNC_DEFERRED`\n * on the server), unless `initialData` already holds their result. `initialState` (e.g. parsed\n * from the URL) applies on the server: client-mode features filter / search / sort the HTML.\n * `getServerSnapshot` is the view at creation; a table that changed before the hydration commit\n * reports `DK_HYDRATION_MISMATCH`.\n *\n * `@datakable/react` installs no features by default; `datakable`'s `useDataTable` installs the\n * default preset.\n */\nexport function useDataTable<\n T,\n S extends TableState = never,\n const Fs extends readonly AnyFeature[] = [],\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(\n options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {\n features?: Fs\n },\n): UseDataTableResult<\n SchemaRow<T, Sch>,\n TableStateFor<S, Fs, SchemaRow<T, Sch>>,\n M,\n [Sch] extends [TableSchema] ? unknown : T,\n ApiOf<Fs, SchemaRow<T, Sch>>\n>\nexport function useDataTable(options: Options): unknown {\n const ref = useRef<Instance | null>(null)\n // Created during the first render, deferred: its async work (fetcher, searchFn) starts in the\n // mount effect, never on the server.\n if (ref.current === null) {\n ref.current = createInstance(options)\n // React 18's development StrictMode discards the first mount render, ref included (React 19\n // keeps it): that render's table never mounts, so release it once the render is over. A\n // render that commits after this (one that yielded) gets a new table at mount (`recreate`).\n if (\n process.env.NODE_ENV !== 'production' &&\n typeof window !== 'undefined' &&\n reactVersion.startsWith('18.')\n ) {\n const inst = ref.current\n queueMicrotask(() => release(inst))\n }\n }\n const inst = ref.current\n const table = inst.table\n const [, rerender] = useReducer((n: number) => n + 1, 0)\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n // Replaced or destroyed meanwhile (`<Activity>`): nothing to subscribe to.\n if (inst.table !== table || inst.destroyed) return () => {}\n return table.subscribe(() => {\n inst.version++\n if (inst.syncing) inst.selfCaused = true\n onChange()\n })\n },\n [inst, table],\n )\n const getSnapshot = useCallback(() => snapshot(inst, table), [inst, table])\n const getServerSnapshot = useCallback(() => serverSnapshot(inst, table), [inst, table])\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n\n // Hydration commit (§7.2): before any layout effect can change the table, the snapshot React\n // hydrated with must still be the live one, else React replaces the server HTML at once.\n useInsertionEffect(() => checkHydration(inst), [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.mounted = true\n // Destroyed while hidden (`<Activity>`): a new table, from the latest options.\n if (inst.destroyed) {\n recreate(inst)\n startTable(inst.table)\n rerender()\n } else {\n // The deferred fetch / searchFn starts now; its status shows before paint.\n startTable(inst.table)\n if (snapshot(inst, inst.table) !== view) rerender()\n }\n return () => {\n inst.mounted = false\n // Deferred: the StrictMode effect re-run mounts again synchronously and keeps the table.\n queueMicrotask(() => {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n })\n }\n }, [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.latest = options\n const selfCaused = inst.selfCaused\n inst.selfCaused = false\n if (!inst.destroyed) sync(inst, options, selfCaused)\n deliver(inst)\n })\n\n return view\n}\n\n/** Dev (React 18): destroys a table created in render unless it mounted (or was destroyed). */\nfunction release(inst: Instance) {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n}\n\nfunction createInstance(options: Options): Instance {\n const inst: Instance = {\n table: undefined as unknown as AnyTable,\n destroyed: false,\n mounted: false,\n latest: options,\n synced: options,\n wrappers: {\n onStateChange: (updater) => (inst.latest.onStateChange as Callback)(updater),\n onDiagnostic: (d: Diagnostic) => {\n if (inst.rendering === 0) {\n ;(inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined)?.(d)\n return\n }\n if (inst.queue === undefined) {\n inst.queue = []\n // Delivered by the next layout effect, or here when this render never commits.\n queueMicrotask(() => deliver(inst))\n }\n inst.queue.push(d)\n },\n fetcher: (params) => (inst.latest.fetcher as Callback)(params),\n },\n queue: undefined,\n rendering: 0,\n syncing: false,\n selfCaused: false,\n selfData: false,\n version: 0,\n view: undefined,\n server: undefined,\n hydrating: false,\n seen: options,\n // Development only (`checkUnstable`): no Map / Set per table in production.\n ...(process.env.NODE_ENV !== 'production' ? { unstable: new Map(), warned: new Set() } : {}),\n }\n // The version checks are development-only (§8.5): production bundles no registry.\n if (process.env.NODE_ENV !== 'production' && !registered) {\n registered = true\n registerPackage('@datakable/react', version)\n }\n build(inst, options)\n return inst\n}\n\n/**\n * The stable wrapper of callback `k`. The fetcher's also carries the server source of the user's\n * `withFetcher` fetcher (§7.1), which is what makes the table load through it.\n */\nfunction wrapper(inst: Instance, k: CallbackKey, v: unknown): Callback {\n const w = inst.wrappers[k]\n if (k === 'fetcher') {\n ;(w as unknown as Record<symbol, unknown>)[SERVER_SOURCE] = (v as Record<symbol, unknown>)[\n SERVER_SOURCE\n ]\n }\n return w\n}\n\nfunction build(inst: Instance, options: Options) {\n const init: Options = { ...options }\n for (const k of CALLBACKS) {\n if (typeof options[k] === 'function') init[k] = wrapper(inst, k, options[k])\n }\n inst.rendering++\n try {\n // Deferred (§7.2): rendering starts no fetch / searchFn (none at all on the server, where\n // effects never run); the mount effect starts it.\n inst.table = createDeferred(() => createTable(init as never)) as unknown as AnyTable\n } finally {\n inst.rendering--\n }\n inst.synced = options\n inst.seen = options\n inst.view = undefined\n inst.server = undefined\n}\n\nfunction recreate(inst: Instance) {\n build(inst, inst.latest)\n inst.destroyed = false\n}\n\n/** The view of the table's snapshot, cached on (table, state, row model, notifications). */\nfunction snapshot(inst: Instance, table: AnyTable): object {\n inst.rendering++\n try {\n const state = table.getState()\n const rowModel = table.getRowModel()\n const v = inst.view\n if (v && v.table === table && v.version === inst.version) {\n const value = v.value as { state: unknown; rowModel: unknown }\n if (value.state === state && value.rowModel === rowModel) return value\n }\n const value = Object.create(table, {\n state: { value: state, enumerable: true },\n rowModel: { value: rowModel, enumerable: true },\n }) as object\n inst.view = { table, version: inst.version, value }\n return value\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * `getServerSnapshot` (§7.2): the view of the table at its creation. React reads it on the server\n * and while hydrating, so both render the same snapshot; async work never ran in it.\n */\nfunction serverSnapshot(inst: Instance, table: AnyTable): object {\n if (inst.table !== table) return snapshot(inst, table)\n // On the client React reads it only to hydrate.\n if (typeof window !== 'undefined') inst.hydrating = true\n const s = inst.server\n if (s && s.table === table) return s.value\n const value = snapshot(inst, table)\n inst.server = { table, value }\n return value\n}\n\n/** `DK_HYDRATION_MISMATCH`: what differs between the hydrated (server) view and the live one. */\nfunction checkHydration(inst: Instance) {\n if (!inst.hydrating) return\n inst.hydrating = false\n const server = inst.server\n if (!server || server.table !== inst.table) return\n const live = snapshot(inst, inst.table) as { state: TableState; rowModel: unknown }\n const hydrated = server.value as { state: TableState; rowModel: unknown }\n if (live === hydrated) return\n const slices: string[] = []\n for (const k of new Set([...Object.keys(hydrated.state), ...Object.keys(live.state)])) {\n if (!Object.is(hydrated.state[k], live.state[k])) slices.push(k)\n }\n if (slices.length === 0) {\n if (live.rowModel === hydrated.rowModel) return\n slices.push('rows')\n }\n // Delivered to onDiagnostic by the layout effect (no update during the commit).\n inst.rendering++\n try {\n emitTableDiagnostic(\n inst.table,\n 'DK_HYDRATION_MISMATCH',\n { slices },\n { trigger: 'hydrate', phase: 'hydrate' },\n )\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * Forwards the changed options with one `setOptions` call. In the re-render caused by that call,\n * values recomputed from the same inputs (same-shape `columns`, `data` with equal rows, a `rowKey`\n * function) are not forwarded again: an inline `columns` / `data` would otherwise loop. A `data`\n * that still differs is forwarded at most once per chain of self-caused re-renders, so rows that\n * are new on every render (`data: [{ … }]` with nested objects) re-ingest but never hang.\n */\nfunction sync(inst: Instance, options: Options, selfCaused: boolean) {\n // Written out (not a module-level flag) so bundlers fold it while parsing (§8.2). The re-render\n // a sync causes is not counted: under `<DataTable columns>` it reuses the props (count reset).\n if (process.env.NODE_ENV !== 'production' && !selfCaused) checkUnstable(inst, options)\n const prev = inst.synced\n if (!selfCaused) inst.selfData = false\n let partial: Record<string, unknown> | undefined\n for (const k of SYNCED) {\n const v = options[k]\n const p = prev[k]\n if (Object.is(v, p)) continue\n let forward: unknown = v\n switch (k) {\n case 'onStateChange':\n case 'onDiagnostic':\n case 'fetcher': {\n const on = typeof v === 'function'\n if (on === (typeof p === 'function')) continue\n forward = on ? wrapper(inst, k, v) : undefined\n break\n }\n case 'state':\n if (sameSlices(v, p)) continue\n break\n case 'interceptors':\n if (sameItems(v, p)) continue\n break\n case 'data':\n // Two empty arrays hold nothing to ingest (e.g. an inline `data: []` with a fetcher).\n if (isEmpty(v) && sameItems(v, p)) continue\n if (selfCaused) {\n if (inst.selfData || sameRows(v, p)) continue\n inst.selfData = true\n }\n break\n case 'columns':\n if (selfCaused && sameShape(v, p)) continue\n break\n case 'rowKey':\n if (selfCaused && typeof v === 'function' && typeof p === 'function') continue\n break\n }\n partial ??= {}\n partial[k] = forward\n }\n if (partial === undefined) return\n inst.syncing = true\n try {\n inst.table.setOptions(partial)\n } finally {\n inst.syncing = false\n }\n const synced = { ...prev }\n for (const k of Object.keys(partial)) synced[k] = options[k]\n inst.synced = synced\n}\n\n/** Delivers the `onDiagnostic` calls queued while rendering. */\nfunction deliver(inst: Instance) {\n const queue = inst.queue\n if (queue === undefined) return\n inst.queue = undefined\n const sink = inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined\n for (const d of queue) {\n try {\n sink?.(d)\n } catch (e) {\n // Like a failing sink in the hub: the logger never breaks the table.\n console.error('[DataKable] onDiagnostic threw', e)\n }\n }\n}\n\n// --- comparisons ---------------------------------------------------------------------------------\n\nconst isObject = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === 'object'\n\n/** Controlled slices: the same defined slices, each `Object.is`-equal. */\nfunction sameSlices(a: unknown, b: unknown): boolean {\n if (!isObject(a) || !isObject(b)) return false\n const defined = (o: Record<string, unknown>) => Object.keys(o).filter((k) => o[k] !== undefined)\n const keys = defined(a)\n if (keys.length !== defined(b).length) return false\n for (const k of keys) if (!Object.is(a[k], b[k])) return false\n return true\n}\n\nconst isEmpty = (v: unknown) => Array.isArray(v) && v.length === 0\n\n/** Two arrays with the same items (by reference). */\nfunction sameItems(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false\n return true\n}\n\nconst loose = (v: unknown) => typeof v === 'function' || isObject(v)\n\n/**\n * Two arrays of equal items: each pair the same reference, or objects with the same own keys and\n * `Object.is`-equal values. Rows (`data: rows.map((r) => ({ ...r }))` recomputed in a re-render):\n * exactly that. Columns (`shape`): equal primitive values, while functions and nested objects\n * (`format`, `cell`, `filter`, …) may be new references of the same type.\n */\nfunction sameRows(a: unknown, b: unknown, shape?: boolean): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x: unknown = a[i]\n const y: unknown = b[i]\n if (Object.is(x, y)) continue\n if (!isObject(x) || !isObject(y)) return false\n const keys = Object.keys(x)\n if (keys.length !== Object.keys(y).length) return false\n for (const k of keys) {\n if (!Object.hasOwn(y, k)) return false\n const vx = x[k]\n const vy = y[k]\n if (Object.is(vx, vy)) continue\n if (!(shape && loose(vx) && loose(vy) && typeof vx === typeof vy)) return false\n }\n }\n return true\n}\n\n/** Column arrays of the same shape (see {@link sameRows}). */\nconst sameShape = (a: unknown, b: unknown) => sameRows(a, b, true)\n\n// --- dev: DK_UNSTABLE_COLUMNS / DK_UNSTABLE_OPTION -----------------------------------------------\n\n/** The first function option of a feature that is a new reference: `features[i].<option>`. */\nfunction changedFeatureOption(a: unknown, b: unknown): string | undefined {\n if (!Array.isArray(a) || !Array.isArray(b) || a === b) return undefined\n for (let i = 0; i < a.length; i++) {\n const f = a[i] as AnyFeature | undefined\n const g = b[i] as AnyFeature | undefined\n if (!f || !g || f === g || f.name !== g.name) continue\n if (!isOptionsDefinition(f.options) || !isOptionsDefinition(g.options)) continue\n const fv = f.options.values\n const gv = g.options.values\n if (!fv || !gv) continue\n for (const k of Object.keys(fv)) {\n if (typeof fv[k] === 'function' && fv[k] !== gv[k]) return `features[${i}].${k}`\n }\n }\n return undefined\n}\n\n/** Counts renders in a row that pass a new reference for the same thing; reports each once. */\nfunction checkUnstable(inst: Instance, options: Options) {\n const seen = inst.seen\n inst.seen = options\n const changed = (k: string) => !Object.is(options[k], seen[k])\n const fn = (k: string) =>\n changed(k) && typeof options[k] === 'function' && typeof seen[k] === 'function'\n track(inst, 'columns', changed('columns') && sameShape(options.columns, seen.columns))\n track(inst, 'data', changed('data') && sameRows(options.data, seen.data))\n track(inst, 'fetcher', fn('fetcher'))\n track(inst, 'rowKey', fn('rowKey'))\n const option = changedFeatureOption(options.features, seen.features)\n track(inst, 'features', option !== undefined, option)\n}\n\nfunction track(inst: Instance, key: string, unstable: boolean, option = key) {\n const seen = inst.unstable as Map<string, number>\n const warned = inst.warned as Set<string>\n const n = unstable ? (seen.get(key) ?? 0) + 1 : 0\n seen.set(key, n)\n if (n < UNSTABLE_AFTER || warned.has(key)) return\n warned.add(key)\n if (key === 'columns') emitTableDiagnostic(inst.table, 'DK_UNSTABLE_COLUMNS', { renders: n })\n else emitTableDiagnostic(inst.table, 'DK_UNSTABLE_OPTION', { option, renders: n })\n}\n","{\n \"name\": \"@datakable/react\",\n \"version\": \"2.0.2\",\n \"description\": \"React bindings for DataKable — useDataTable hook and DataTable component.\",\n \"license\": \"MIT\",\n \"author\": \"Supakit Kitjanabumrungsak\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Ink01101011/datakable.git\",\n \"directory\": \"packages/react\"\n },\n \"homepage\": \"https://github.com/Ink01101011/datakable#readme\",\n \"bugs\": \"https://github.com/Ink01101011/datakable/issues\",\n \"keywords\": [\n \"react\",\n \"react-table\",\n \"datatable\",\n \"data-table\",\n \"data-grid\",\n \"datagrid\",\n \"table\",\n \"typescript\",\n \"type-safe\",\n \"headless\",\n \"headless-ui\",\n \"zero-config\",\n \"sorting\",\n \"filtering\",\n \"search\",\n \"pagination\",\n \"react-hooks\",\n \"react-component\",\n \"use-data-table\",\n \"ssr\",\n \"rsc\"\n ],\n \"type\": \"module\",\n \"sideEffects\": [\n \"./dist/messages.js\",\n \"./dist/messages.cjs\",\n \"./dist/styles.css\"\n ],\n \"engines\": {\n \"node\": \">=18.18.0\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"typesVersions\": {\n \"*\": {\n \"messages\": [\n \"./dist/messages.d.ts\"\n ],\n \"styles.css\": [\n \"./dist/styles.css.d.ts\"\n ]\n }\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./messages\": {\n \"import\": {\n \"types\": \"./dist/messages.d.ts\",\n \"default\": \"./dist/messages.js\"\n },\n \"require\": {\n \"types\": \"./dist/messages.d.cts\",\n \"default\": \"./dist/messages.cjs\"\n }\n },\n \"./styles.css\": {\n \"types\": {\n \"import\": \"./dist/styles.css.d.ts\",\n \"require\": \"./dist/styles.css.d.cts\"\n },\n \"default\": \"./dist/styles.css\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup && node ../../scripts/write-styles-dts.mjs\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc -p tsconfig.json\",\n \"check:pkg\": \"publint --strict && attw --pack . && node scripts/check-catalog.mjs\",\n \"check:catalog\": \"node scripts/check-catalog.mjs\"\n },\n \"dependencies\": {\n \"@datakable/core\": \"workspace:^\"\n },\n \"peerDependencies\": {\n \"react\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n }\n }\n}\n"],"mappings":"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","names":["inst","value"]}
1
+ {"version":3,"sources":["../src/use-data-table.ts","../package.json"],"sourcesContent":["'use client'\n\nimport {\n type AnyFeature,\n type ApiOf,\n type ColumnDef,\n type CreateTableOptions,\n createDeferred,\n createTable,\n type Diagnostic,\n emitTableDiagnostic,\n type HasSchema,\n type InvalidRowsMode,\n isOptionsDefinition,\n keepDiagnostics,\n type RowModel,\n registerPackage,\n type SchemaRow,\n SERVER_SOURCE,\n startTable,\n type Table,\n type TableSchema,\n type TableState,\n type TableStateFor,\n} from '@datakable/core'\nimport {\n type ReactNode,\n version as reactVersion,\n useCallback,\n useEffect,\n useInsertionEffect,\n useLayoutEffect,\n useReducer,\n useRef,\n useSyncExternalStore,\n} from 'react'\nimport { version } from '../package.json'\nimport { reactDiagnostics } from './codes'\n\n// Registers the (development-only) definitions where they are emitted, so bundlers keep them.\nkeepDiagnostics(reactDiagnostics)\n\n// No @types/node here: declare just what is read.\ndeclare const process: { env: { NODE_ENV?: string } }\n\n/** No layout effects on the server (React 18 warns about them there). */\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect\n\n/**\n * `useDataTable` options: `createTable`'s (§3.2), with `cell` / `invalidCell` returning a\n * `ReactNode` (§10). Read once, at creation: `features`, `schema`, `invalidRows`, `initialState`,\n * `name`, `timeout`, `strict`, `diagnostics`. Every other option follows the latest render.\n */\nexport type UseDataTableOptions<\n T,\n S extends TableState = TableState,\n Sch = undefined,\n M extends InvalidRowsMode = 'drop',\n> = Omit<CreateTableOptions<T, S, Sch, M>, 'columns'> & {\n /**\n * Compared by reference (§10): a new array tells the table the columns changed. Define them\n * outside the component or memoise them (`DK_UNSTABLE_COLUMNS` in development).\n */\n columns?: readonly ColumnDef<SchemaRow<T, Sch>, ReactNode>[]\n}\n\n/**\n * What `useDataTable` returns: the table (its methods and the installed features' APIs) with the\n * `state` and `rowModel` of this render. A new object whenever the table notifies, so it can be a\n * dependency of `useMemo` / `memo` children; the same object while nothing changed.\n */\nexport type UseDataTableResult<\n T,\n S extends TableState = TableState,\n M extends InvalidRowsMode = 'drop',\n In = T,\n Api = unknown,\n> = Table<T, S, M, In> &\n Api & {\n /** The state snapshot of this render (`getState()`). */\n readonly state: S\n /** The row model of this render (`getRowModel()`, §6.6): rows, counts, status. */\n readonly rowModel: RowModel<T, M>\n }\n\ntype Options = Record<string, unknown> & { features?: readonly AnyFeature[] }\ntype AnyTable = Table<unknown, TableState> & Record<string, unknown>\ntype Callback = (arg: never) => unknown\n\n/** Options forwarded through `setOptions` when they change; the rest are read once (§3.4). */\nconst SYNCED = [\n 'data',\n 'columns',\n 'rowKey',\n 'state',\n 'onStateChange',\n 'interceptors',\n 'onDiagnostic',\n 'fetcher',\n 'rowCount',\n] as const\n\n/** Given to the table as stable wrappers that call the latest prop (latest-ref). */\nconst CALLBACKS = ['onStateChange', 'onDiagnostic', 'fetcher'] as const\ntype CallbackKey = (typeof CALLBACKS)[number]\n\n/** Renders in a row with a new reference before `DK_UNSTABLE_*` is reported. */\nconst UNSTABLE_AFTER = 2\n\ninterface Instance {\n table: AnyTable\n destroyed: boolean\n mounted: boolean\n /** The options of the latest committed render (what the wrappers call). */\n latest: Options\n /** The option values the table has (user values; callbacks count by presence). */\n synced: Options\n readonly wrappers: Record<CallbackKey, Callback>\n /** `onDiagnostic` calls made while rendering, delivered after the commit. */\n queue: Diagnostic[] | undefined\n rendering: number\n /** Inside the hook's own `setOptions` call. */\n syncing: boolean\n /** That call notified: the next commit is the re-render it caused. */\n selfCaused: boolean\n /**\n * `data` was forwarded in a self-caused re-render. Rows that differ on every render (nested\n * objects, computed fields) would otherwise ingest → notify → re-render forever: the next\n * self-caused re-render keeps the data the table has.\n */\n selfData: boolean\n /** Notifications seen; part of the view cache key (a notification is never silent, §6.6). */\n version: number\n view: { table: AnyTable; version: number; value: object } | undefined\n /**\n * SSR (§7.2): the view of `table` at its creation — initial state, controlled state and data /\n * initialData, no async result (the table is created deferred). `getServerSnapshot`.\n */\n server: { table: AnyTable; value: object } | undefined\n /** React read `getServerSnapshot` on the client: this render hydrates server HTML. */\n hydrating: boolean\n // Dev: DK_UNSTABLE_* bookkeeping.\n /** The options of the previous committed render. */\n seen: Options\n /** Development only (`checkUnstable`). */\n unstable?: Map<string, number>\n warned?: Set<string>\n}\n\nlet registered = false\n\n/**\n * Binds a table to a component (§10): the table is created once per component instance and\n * destroyed on unmount; renders read it through `useSyncExternalStore` (with\n * `getServerSnapshot`), and options are synced with `table.setOptions` in a layout effect, never\n * during render.\n *\n * - `features` (and the other read-once options) are read at creation: a new inline `features`\n * array never recreates the table.\n * - `fetcher`, `onStateChange` and `onDiagnostic` may be inline functions: the table always calls\n * the latest one, and a new reference never refetches (call `refetch()` when a value the fetcher\n * reads changes).\n * - `columns`, `data` and a `rowKey` function are compared by reference: memoise them.\n * - Controlled slices (§3.2): pass `state` and `onStateChange`; changes come back through `state`.\n * - SSR (§7.2): rendering starts no async work. The fetcher's first request and a `searchFn` for an\n * initial query start after the commit (`status: 'pending'` until then; `DK_SSR_ASYNC_DEFERRED`\n * on the server), unless `initialData` already holds their result. `initialState` (e.g. parsed\n * from the URL) applies on the server: client-mode features filter / search / sort the HTML.\n * `getServerSnapshot` is the view at creation; a table that changed before the hydration commit\n * reports `DK_HYDRATION_MISMATCH`.\n *\n * `@datakable/react` installs no features by default; `datakable`'s `useDataTable` installs the\n * default preset.\n */\nexport function useDataTable<\n T,\n S extends TableState = never,\n const Fs extends readonly AnyFeature[] = [],\n const Sch extends TableSchema | undefined = undefined,\n const M extends InvalidRowsMode = 'drop',\n>(\n options: UseDataTableOptions<T, TableStateFor<S, Fs, SchemaRow<T, Sch>>, Sch, M> & {\n features?: Fs\n },\n): UseDataTableResult<\n SchemaRow<T, Sch>,\n TableStateFor<S, Fs, SchemaRow<T, Sch>>,\n M,\n HasSchema<Sch> extends true ? unknown : T,\n ApiOf<Fs, SchemaRow<T, Sch>>\n>\nexport function useDataTable(options: Options): unknown {\n const ref = useRef<Instance | null>(null)\n // Created during the first render, deferred: its async work (fetcher, searchFn) starts in the\n // mount effect, never on the server.\n if (ref.current === null) {\n ref.current = createInstance(options)\n // React 18's development StrictMode discards the first mount render, ref included (React 19\n // keeps it): that render's table never mounts, so release it once the render is over. A\n // render that commits after this (one that yielded) gets a new table at mount (`recreate`).\n if (\n process.env.NODE_ENV !== 'production' &&\n typeof window !== 'undefined' &&\n reactVersion.startsWith('18.')\n ) {\n const inst = ref.current\n queueMicrotask(() => release(inst))\n }\n }\n const inst = ref.current\n const table = inst.table\n const [, rerender] = useReducer((n: number) => n + 1, 0)\n\n const subscribe = useCallback(\n (onChange: () => void) => {\n // Replaced or destroyed meanwhile (`<Activity>`): nothing to subscribe to.\n if (inst.table !== table || inst.destroyed) return () => {}\n return table.subscribe(() => {\n inst.version++\n if (inst.syncing) inst.selfCaused = true\n onChange()\n })\n },\n [inst, table],\n )\n const getSnapshot = useCallback(() => snapshot(inst, table), [inst, table])\n const getServerSnapshot = useCallback(() => serverSnapshot(inst, table), [inst, table])\n const view = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)\n\n // Hydration commit (§7.2): before any layout effect can change the table, the snapshot React\n // hydrated with must still be the live one, else React replaces the server HTML at once.\n useInsertionEffect(() => checkHydration(inst), [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.mounted = true\n // Destroyed while hidden (`<Activity>`): a new table, from the latest options.\n if (inst.destroyed) {\n recreate(inst)\n startTable(inst.table)\n rerender()\n } else {\n // The deferred fetch / searchFn starts now; its status shows before paint.\n startTable(inst.table)\n if (snapshot(inst, inst.table) !== view) rerender()\n }\n return () => {\n inst.mounted = false\n // Deferred: the StrictMode effect re-run mounts again synchronously and keeps the table.\n queueMicrotask(() => {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n })\n }\n }, [inst])\n\n useIsomorphicLayoutEffect(() => {\n inst.latest = options\n const selfCaused = inst.selfCaused\n inst.selfCaused = false\n if (!inst.destroyed) sync(inst, options, selfCaused)\n deliver(inst)\n })\n\n return view\n}\n\n/** Dev (React 18): destroys a table created in render unless it mounted (or was destroyed). */\nfunction release(inst: Instance) {\n if (inst.mounted || inst.destroyed) return\n inst.destroyed = true\n inst.table.destroy()\n}\n\nfunction createInstance(options: Options): Instance {\n const inst: Instance = {\n table: undefined as unknown as AnyTable,\n destroyed: false,\n mounted: false,\n latest: options,\n synced: options,\n wrappers: {\n onStateChange: (updater) => (inst.latest.onStateChange as Callback)(updater),\n onDiagnostic: (d: Diagnostic) => {\n if (inst.rendering === 0) {\n ;(inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined)?.(d)\n return\n }\n if (inst.queue === undefined) {\n inst.queue = []\n // Delivered by the next layout effect, or here when this render never commits.\n queueMicrotask(() => deliver(inst))\n }\n inst.queue.push(d)\n },\n fetcher: (params) => (inst.latest.fetcher as Callback)(params),\n },\n queue: undefined,\n rendering: 0,\n syncing: false,\n selfCaused: false,\n selfData: false,\n version: 0,\n view: undefined,\n server: undefined,\n hydrating: false,\n seen: options,\n // Development only (`checkUnstable`): no Map / Set per table in production.\n ...(process.env.NODE_ENV !== 'production' ? { unstable: new Map(), warned: new Set() } : {}),\n }\n // The version checks are development-only (§8.5): production bundles no registry.\n if (process.env.NODE_ENV !== 'production' && !registered) {\n registered = true\n registerPackage('@datakable/react', version)\n }\n build(inst, options)\n return inst\n}\n\n/**\n * The stable wrapper of callback `k`. The fetcher's also carries the server source of the user's\n * `withFetcher` fetcher (§7.1), which is what makes the table load through it.\n */\nfunction wrapper(inst: Instance, k: CallbackKey, v: unknown): Callback {\n const w = inst.wrappers[k]\n if (k === 'fetcher') {\n ;(w as unknown as Record<symbol, unknown>)[SERVER_SOURCE] = (v as Record<symbol, unknown>)[\n SERVER_SOURCE\n ]\n }\n return w\n}\n\nfunction build(inst: Instance, options: Options) {\n const init: Options = { ...options }\n for (const k of CALLBACKS) {\n if (typeof options[k] === 'function') init[k] = wrapper(inst, k, options[k])\n }\n inst.rendering++\n try {\n // Deferred (§7.2): rendering starts no fetch / searchFn (none at all on the server, where\n // effects never run); the mount effect starts it.\n inst.table = createDeferred(() => createTable(init as never)) as unknown as AnyTable\n } finally {\n inst.rendering--\n }\n inst.synced = options\n inst.seen = options\n inst.view = undefined\n inst.server = undefined\n}\n\nfunction recreate(inst: Instance) {\n build(inst, inst.latest)\n inst.destroyed = false\n}\n\n/** The view of the table's snapshot, cached on (table, state, row model, notifications). */\nfunction snapshot(inst: Instance, table: AnyTable): object {\n inst.rendering++\n try {\n const state = table.getState()\n const rowModel = table.getRowModel()\n const v = inst.view\n if (v && v.table === table && v.version === inst.version) {\n const value = v.value as { state: unknown; rowModel: unknown }\n if (value.state === state && value.rowModel === rowModel) return value\n }\n const value = Object.create(table, {\n state: { value: state, enumerable: true },\n rowModel: { value: rowModel, enumerable: true },\n }) as object\n inst.view = { table, version: inst.version, value }\n return value\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * `getServerSnapshot` (§7.2): the view of the table at its creation. React reads it on the server\n * and while hydrating, so both render the same snapshot; async work never ran in it.\n */\nfunction serverSnapshot(inst: Instance, table: AnyTable): object {\n if (inst.table !== table) return snapshot(inst, table)\n // On the client React reads it only to hydrate.\n if (typeof window !== 'undefined') inst.hydrating = true\n const s = inst.server\n if (s && s.table === table) return s.value\n const value = snapshot(inst, table)\n inst.server = { table, value }\n return value\n}\n\n/** `DK_HYDRATION_MISMATCH`: what differs between the hydrated (server) view and the live one. */\nfunction checkHydration(inst: Instance) {\n if (!inst.hydrating) return\n inst.hydrating = false\n const server = inst.server\n if (!server || server.table !== inst.table) return\n const live = snapshot(inst, inst.table) as { state: TableState; rowModel: unknown }\n const hydrated = server.value as { state: TableState; rowModel: unknown }\n if (live === hydrated) return\n const slices: string[] = []\n for (const k of new Set([...Object.keys(hydrated.state), ...Object.keys(live.state)])) {\n if (!Object.is(hydrated.state[k], live.state[k])) slices.push(k)\n }\n if (slices.length === 0) {\n if (live.rowModel === hydrated.rowModel) return\n slices.push('rows')\n }\n // Delivered to onDiagnostic by the layout effect (no update during the commit).\n inst.rendering++\n try {\n emitTableDiagnostic(\n inst.table,\n 'DK_HYDRATION_MISMATCH',\n { slices },\n { trigger: 'hydrate', phase: 'hydrate' },\n )\n } finally {\n inst.rendering--\n }\n}\n\n/**\n * Forwards the changed options with one `setOptions` call. In the re-render caused by that call,\n * values recomputed from the same inputs (same-shape `columns`, `data` with equal rows, a `rowKey`\n * function) are not forwarded again: an inline `columns` / `data` would otherwise loop. A `data`\n * that still differs is forwarded at most once per chain of self-caused re-renders, so rows that\n * are new on every render (`data: [{ … }]` with nested objects) re-ingest but never hang.\n */\nfunction sync(inst: Instance, options: Options, selfCaused: boolean) {\n // Written out (not a module-level flag) so bundlers fold it while parsing (§8.2). The re-render\n // a sync causes is not counted: under `<DataTable columns>` it reuses the props (count reset).\n if (process.env.NODE_ENV !== 'production' && !selfCaused) checkUnstable(inst, options)\n const prev = inst.synced\n if (!selfCaused) inst.selfData = false\n let partial: Record<string, unknown> | undefined\n for (const k of SYNCED) {\n const v = options[k]\n const p = prev[k]\n if (Object.is(v, p)) continue\n let forward: unknown = v\n switch (k) {\n case 'onStateChange':\n case 'onDiagnostic':\n case 'fetcher': {\n const on = typeof v === 'function'\n if (on === (typeof p === 'function')) continue\n forward = on ? wrapper(inst, k, v) : undefined\n break\n }\n case 'state':\n if (sameSlices(v, p)) continue\n break\n case 'interceptors':\n if (sameItems(v, p)) continue\n break\n case 'data':\n // Two empty arrays hold nothing to ingest (e.g. an inline `data: []` with a fetcher).\n if (isEmpty(v) && sameItems(v, p)) continue\n if (selfCaused) {\n if (inst.selfData || sameRows(v, p)) continue\n inst.selfData = true\n }\n break\n case 'columns':\n if (selfCaused && sameShape(v, p)) continue\n break\n case 'rowKey':\n if (selfCaused && typeof v === 'function' && typeof p === 'function') continue\n break\n }\n partial ??= {}\n partial[k] = forward\n }\n if (partial === undefined) return\n inst.syncing = true\n try {\n inst.table.setOptions(partial)\n } finally {\n inst.syncing = false\n }\n const synced = { ...prev }\n for (const k of Object.keys(partial)) synced[k] = options[k]\n inst.synced = synced\n}\n\n/** Delivers the `onDiagnostic` calls queued while rendering. */\nfunction deliver(inst: Instance) {\n const queue = inst.queue\n if (queue === undefined) return\n inst.queue = undefined\n const sink = inst.latest.onDiagnostic as ((d: Diagnostic) => void) | undefined\n for (const d of queue) {\n try {\n sink?.(d)\n } catch (e) {\n // Like a failing sink in the hub: the logger never breaks the table.\n console.error('[DataKable] onDiagnostic threw', e)\n }\n }\n}\n\n// --- comparisons ---------------------------------------------------------------------------------\n\nconst isObject = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === 'object'\n\n/** Controlled slices: the same defined slices, each `Object.is`-equal. */\nfunction sameSlices(a: unknown, b: unknown): boolean {\n if (!isObject(a) || !isObject(b)) return false\n const defined = (o: Record<string, unknown>) => Object.keys(o).filter((k) => o[k] !== undefined)\n const keys = defined(a)\n if (keys.length !== defined(b).length) return false\n for (const k of keys) if (!Object.is(a[k], b[k])) return false\n return true\n}\n\nconst isEmpty = (v: unknown) => Array.isArray(v) && v.length === 0\n\n/** Two arrays with the same items (by reference). */\nfunction sameItems(a: unknown, b: unknown): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false\n return true\n}\n\nconst loose = (v: unknown) => typeof v === 'function' || isObject(v)\n\n/**\n * Two arrays of equal items: each pair the same reference, or objects with the same own keys and\n * `Object.is`-equal values. Rows (`data: rows.map((r) => ({ ...r }))` recomputed in a re-render):\n * exactly that. Columns (`shape`): equal primitive values, while functions and nested objects\n * (`format`, `cell`, `filter`, …) may be new references of the same type.\n */\nfunction sameRows(a: unknown, b: unknown, shape?: boolean): boolean {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x: unknown = a[i]\n const y: unknown = b[i]\n if (Object.is(x, y)) continue\n if (!isObject(x) || !isObject(y)) return false\n const keys = Object.keys(x)\n if (keys.length !== Object.keys(y).length) return false\n for (const k of keys) {\n if (!Object.hasOwn(y, k)) return false\n const vx = x[k]\n const vy = y[k]\n if (Object.is(vx, vy)) continue\n if (!(shape && loose(vx) && loose(vy) && typeof vx === typeof vy)) return false\n }\n }\n return true\n}\n\n/** Column arrays of the same shape (see {@link sameRows}). */\nconst sameShape = (a: unknown, b: unknown) => sameRows(a, b, true)\n\n// --- dev: DK_UNSTABLE_COLUMNS / DK_UNSTABLE_OPTION -----------------------------------------------\n\n/** The first function option of a feature that is a new reference: `features[i].<option>`. */\nfunction changedFeatureOption(a: unknown, b: unknown): string | undefined {\n if (!Array.isArray(a) || !Array.isArray(b) || a === b) return undefined\n for (let i = 0; i < a.length; i++) {\n const f = a[i] as AnyFeature | undefined\n const g = b[i] as AnyFeature | undefined\n if (!f || !g || f === g || f.name !== g.name) continue\n if (!isOptionsDefinition(f.options) || !isOptionsDefinition(g.options)) continue\n const fv = f.options.values\n const gv = g.options.values\n if (!fv || !gv) continue\n for (const k of Object.keys(fv)) {\n if (typeof fv[k] === 'function' && fv[k] !== gv[k]) return `features[${i}].${k}`\n }\n }\n return undefined\n}\n\n/** Counts renders in a row that pass a new reference for the same thing; reports each once. */\nfunction checkUnstable(inst: Instance, options: Options) {\n const seen = inst.seen\n inst.seen = options\n const changed = (k: string) => !Object.is(options[k], seen[k])\n const fn = (k: string) =>\n changed(k) && typeof options[k] === 'function' && typeof seen[k] === 'function'\n track(inst, 'columns', changed('columns') && sameShape(options.columns, seen.columns))\n track(inst, 'data', changed('data') && sameRows(options.data, seen.data))\n track(inst, 'fetcher', fn('fetcher'))\n track(inst, 'rowKey', fn('rowKey'))\n const option = changedFeatureOption(options.features, seen.features)\n track(inst, 'features', option !== undefined, option)\n}\n\nfunction track(inst: Instance, key: string, unstable: boolean, option = key) {\n const seen = inst.unstable as Map<string, number>\n const warned = inst.warned as Set<string>\n const n = unstable ? (seen.get(key) ?? 0) + 1 : 0\n seen.set(key, n)\n if (n < UNSTABLE_AFTER || warned.has(key)) return\n warned.add(key)\n if (key === 'columns') emitTableDiagnostic(inst.table, 'DK_UNSTABLE_COLUMNS', { renders: n })\n else emitTableDiagnostic(inst.table, 'DK_UNSTABLE_OPTION', { option, renders: n })\n}\n","{\n \"name\": \"@datakable/react\",\n \"version\": \"2.0.3\",\n \"description\": \"React bindings for DataKable — useDataTable hook and DataTable component.\",\n \"license\": \"MIT\",\n \"author\": \"Supakit Kitjanabumrungsak\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Ink01101011/datakable.git\",\n \"directory\": \"packages/react\"\n },\n \"homepage\": \"https://github.com/Ink01101011/datakable#readme\",\n \"bugs\": \"https://github.com/Ink01101011/datakable/issues\",\n \"keywords\": [\n \"react\",\n \"react-table\",\n \"datatable\",\n \"data-table\",\n \"data-grid\",\n \"datagrid\",\n \"table\",\n \"typescript\",\n \"type-safe\",\n \"headless\",\n \"headless-ui\",\n \"zero-config\",\n \"sorting\",\n \"filtering\",\n \"search\",\n \"pagination\",\n \"react-hooks\",\n \"react-component\",\n \"use-data-table\",\n \"ssr\",\n \"rsc\"\n ],\n \"type\": \"module\",\n \"sideEffects\": [\n \"./dist/messages.js\",\n \"./dist/messages.cjs\",\n \"./dist/styles.css\"\n ],\n \"engines\": {\n \"node\": \">=18.18.0\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"typesVersions\": {\n \"*\": {\n \"messages\": [\n \"./dist/messages.d.ts\"\n ],\n \"styles.css\": [\n \"./dist/styles.css.d.ts\"\n ]\n }\n },\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./messages\": {\n \"import\": {\n \"types\": \"./dist/messages.d.ts\",\n \"default\": \"./dist/messages.js\"\n },\n \"require\": {\n \"types\": \"./dist/messages.d.cts\",\n \"default\": \"./dist/messages.cjs\"\n }\n },\n \"./styles.css\": {\n \"types\": {\n \"import\": \"./dist/styles.css.d.ts\",\n \"require\": \"./dist/styles.css.d.cts\"\n },\n \"default\": \"./dist/styles.css\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup && node ../../scripts/write-styles-dts.mjs\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc -p tsconfig.json\",\n \"check:pkg\": \"publint --strict && attw --pack . && node scripts/check-catalog.mjs\",\n \"check:catalog\": \"node scripts/check-catalog.mjs\"\n },\n \"dependencies\": {\n \"@datakable/core\": \"workspace:^\"\n },\n \"peerDependencies\": {\n \"react\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n }\n }\n}\n"],"mappings":"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","names":["inst","value"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datakable/react",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "React bindings for DataKable — useDataTable hook and DataTable component.",
5
5
  "license": "MIT",
6
6
  "author": "Supakit Kitjanabumrungsak",
@@ -90,7 +90,7 @@
90
90
  "dist"
91
91
  ],
92
92
  "dependencies": {
93
- "@datakable/core": "^2.0.2"
93
+ "@datakable/core": "^2.0.3"
94
94
  },
95
95
  "peerDependencies": {
96
96
  "react": ">=18"