@orkestrel/table 0.0.8 → 0.0.9

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/browser/errors.ts","../../../src/core/errors.ts","../../../src/core/cloners.ts","../../../src/core/constants.ts","../../../src/core/helpers.ts","../../../src/core/validators.ts","../../../src/core/parsers.ts","../../../src/browser/helpers.ts","../../../src/browser/TableBinding.ts","../../../src/browser/factories.ts"],"sourcesContent":["import type { TableBindingErrorCode } from './types.js'\nimport { isInstance } from '@orkestrel/contract'\n\n/** Represents a native table binding failure with a machine-readable code. */\nexport class TableBindingError extends Error {\n\treadonly code: TableBindingErrorCode\n\n\t/** Creates a binding failure.\n\t * @param code - The failed boundary.\n\t * @param message - The explanation.\n\t */\n\tconstructor(code: TableBindingErrorCode, message: string) {\n\t\tsuper(message)\n\t\tthis.name = 'TableBindingError'\n\t\tthis.code = code\n\t}\n}\n\n/** Checks whether a caught value is a native table binding error.\n * @param value - The caught value.\n * @returns Whether the value is a binding error.\n */\nexport function isTableBindingError(value: unknown): value is TableBindingError {\n\treturn isInstance(value, TableBindingError)\n}\n","import type { JSONRecord } from '@orkestrel/contract'\nimport { isInstance } from '@orkestrel/contract'\nimport type { TableErrorCode } from './types.js'\n\n/**\n * Represents an error raised by the table domain — a machine-readable `code` and optional\n * structured `context`.\n */\nexport class TableError extends Error {\n\t/** Holds the machine-readable reason for this failure. */\n\treadonly code: TableErrorCode\n\n\t/** Holds structured values that locate or explain this failure. */\n\treadonly context?: JSONRecord\n\n\t/**\n\t * Creates a table error.\n\t *\n\t * @param code - The machine-readable reason.\n\t * @param message - The human-readable failure text.\n\t * @param context - Optional structured failure details.\n\t */\n\tconstructor(code: TableErrorCode, message: string, context?: JSONRecord) {\n\t\tsuper(message)\n\t\tthis.name = 'TableError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Determines whether a caught value is a table error, so a `catch` branches on `code` without an\n * assertion.\n *\n * @param input - The value to inspect.\n * @returns True if the value is a {@link TableError} instance; false otherwise.\n */\nexport function isTableError(input: unknown): input is TableError {\n\treturn isInstance(input, TableError)\n}\n","import type { JSONRecord } from '@orkestrel/contract'\nimport type { TableRow, TableSchema } from './types.js'\nimport { cloneJSONRecord, isContractError } from '@orkestrel/contract'\nimport { TableError } from './errors.js'\n\n/**\n * Clones one row into an owned frozen snapshot.\n *\n * @param row - The row to own.\n * @returns A frozen copy of the row's cells.\n */\nexport function cloneRow(row: TableRow): TableRow {\n\treturn Object.freeze({ ...row })\n}\n\n/**\n * Clones a whole schema into an owned frozen snapshot, freezing every nested column, choice list,\n * choice, and `meta`; raises `SCHEMA` for a `meta` it cannot own.\n *\n * @param schema - The schema to own.\n * @returns A frozen schema with every nested column, choice, list, and metadata record owned.\n */\nexport function cloneSchema(schema: TableSchema): TableSchema {\n\treturn Object.freeze({\n\t\t...schema,\n\t\tcolumns: Object.freeze(\n\t\t\tschema.columns.map((column) => {\n\t\t\t\tlet meta: { meta?: JSONRecord } = {}\n\n\t\t\t\tif (column.meta !== undefined) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmeta = { meta: cloneJSONRecord(column.meta) }\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (!isContractError(error)) throw error\n\t\t\t\t\t\tthrow new TableError(\n\t\t\t\t\t\t\t'SCHEMA',\n\t\t\t\t\t\t\t`column \"${column.key}\" has metadata that cannot be owned`,\n\t\t\t\t\t\t\t{ column: column.key },\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (column.cell === 'choice') {\n\t\t\t\t\treturn Object.freeze({\n\t\t\t\t\t\t...column,\n\t\t\t\t\t\t...meta,\n\t\t\t\t\t\tchoices: Object.freeze(column.choices.map((choice) => Object.freeze({ ...choice }))),\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\treturn Object.freeze({ ...column, ...meta })\n\t\t\t}),\n\t\t),\n\t})\n}\n","import type { ColumnCell } from './types.js'\n\n/** Lists every column cell, in the order declared by the public contract. */\nexport const COLUMN_CELLS: readonly ColumnCell[] = Object.freeze([\n\t'text',\n\t'number',\n\t'flag',\n\t'choice',\n])\n\n/** Names the maximum number of columns one schema may declare: 256. */\nexport const COLUMN_LIMIT = 256\n\n/** Names the maximum number of choices one `choice` column may offer: 1024. */\nexport const CHOICE_LIMIT = 1024\n\n/** Names the maximum length of a schema name or column key: 128 UTF-16 code units. */\nexport const NAME_LIMIT = 128\n\n/** Names the maximum length of any single retained string: 65536 UTF-16 code units. */\nexport const STRING_LIMIT = 65536\n\n/**\n * Names the maximum total length of every string one schema retains: 1048576 UTF-16 code units.\n */\nexport const TEXT_LIMIT = 1048576\n\n/** Names the maximum total number of records, arrays, and leaves one schema retains: 16384. */\nexport const NODE_LIMIT = 16384\n","import type { JSONPrimitive, JSONRecord, JSONValue } from '@orkestrel/contract'\nimport type {\n\tCellComparator,\n\tCellMatcher,\n\tTableCell,\n\tTableColumn,\n\tTableFilter,\n\tTableKey,\n\tTableOrder,\n\tTableRow,\n\tTableSchema,\n\tTableTerm,\n} from './types.js'\nimport {\n\tattempt,\n\tcloneJSONRecord,\n\tisArray,\n\tisBoolean,\n\tisContractError,\n\tisFiniteNumber,\n\tisRecord,\n\tisString,\n\treadArrayEntries,\n} from '@orkestrel/contract'\nimport {\n\tCHOICE_LIMIT,\n\tCOLUMN_LIMIT,\n\tNAME_LIMIT,\n\tNODE_LIMIT,\n\tSTRING_LIMIT,\n\tTEXT_LIMIT,\n} from './constants.js'\nimport { TableError } from './errors.js'\n\n/**\n * Finds one column by key; `undefined` when the schema declares no such column.\n *\n * @param schema - The schema whose columns to search.\n * @param key - The column key to find.\n * @returns The declared column, or `undefined` when no column has that key.\n */\nexport function extractColumn(schema: TableSchema, key: string): TableColumn | undefined {\n\treturn schema.columns.find((column) => column.key === key)\n}\n\n/**\n * Reads one row's declared identity; `undefined` when its key cell is missing, empty, or not a\n * string.\n *\n * @param schema - The schema that names the identity column.\n * @param row - The row whose identity to read.\n * @returns The non-empty string identity, or `undefined` when it is unusable.\n */\nexport function extractKey(schema: TableSchema, row: TableRow): TableKey | undefined {\n\tif (!Object.hasOwn(row, schema.key)) return undefined\n\tconst key = row[schema.key]\n\treturn isString(key) && key.length > 0 ? key : undefined\n}\n\n/**\n * Computes one atomic 0/1/N membership change over the keys a caller may address — the engine\n * selection and expansion share.\n *\n * @param known - Every key the caller may change.\n * @param current - The current key set.\n * @param input - Every known key, one key, or a key list.\n * @param include - Decide the next membership from each key's membership at that step.\n * @returns `undefined` when any requested key is unknown, the current set for a no-op, or the next\n * set when membership changes.\n */\nexport function computeKeys(\n\tknown: readonly TableKey[],\n\tcurrent: ReadonlySet<TableKey>,\n\tinput: TableKey | readonly TableKey[] | undefined,\n\tinclude: (included: boolean) => boolean,\n): ReadonlySet<TableKey> | undefined {\n\tconst requested = input === undefined ? known : isArray(input) ? input : [input]\n\tconst population = new Set(known)\n\tif (requested.some((key) => !population.has(key))) return undefined\n\n\tconst next = new Set(current)\n\tfor (const key of requested) {\n\t\tif (include(next.has(key))) next.add(key)\n\t\telse next.delete(key)\n\t}\n\n\tconst changed = next.size !== current.size || [...next].some((key) => !current.has(key))\n\treturn changed ? next : current\n}\n\n/**\n * Merges lens terms into a column-keyed list, replacing the entry that names the same column —\n * the `set` write.\n *\n * @param current - The list as it stands.\n * @param requested - The terms to write, in the order they are written.\n * @returns A frozen list holding one owned entry per column, in the order the columns first\n * appeared.\n */\nexport function mergeTerms<Term extends TableTerm>(\n\tcurrent: readonly Term[],\n\trequested: readonly Term[],\n): readonly Term[] {\n\tconst next = [...current]\n\tfor (const term of requested) {\n\t\tconst owned = Object.freeze({ ...term })\n\t\tconst index = next.findIndex((candidate) => candidate.column === term.column)\n\t\tif (index === -1) next.push(owned)\n\t\telse next[index] = owned\n\t}\n\n\treturn Object.freeze(next)\n}\n\n/**\n * Removes every lens term naming one of the given columns — the drop `sort.remove` and\n * `filter.remove` share.\n *\n * @param current - The list as it stands.\n * @param columns - The column keys to drop.\n * @returns A frozen list holding the entries no named column matched, in their original order.\n */\nexport function removeTerms<Term extends TableTerm>(\n\tcurrent: readonly Term[],\n\tcolumns: readonly string[],\n): readonly Term[] {\n\tconst removed = new Set(columns)\n\treturn Object.freeze(current.filter((term) => !removed.has(term.column)))\n}\n\n/**\n * Checks whether two lens lists hold the same terms in the same order, with the supplied test\n * deciding the operands.\n *\n * @param left - The first list.\n * @param right - The second list.\n * @param equal - Decide whether two terms naming one column carry the same operands.\n * @returns True if the lists are the same length and every position names the same column and\n * carries the same operands; false otherwise.\n */\nexport function matchesTerms<Term extends TableTerm>(\n\tleft: readonly Term[],\n\tright: readonly Term[],\n\tequal: (left: Term, right: Term) => boolean,\n): boolean {\n\treturn (\n\t\tleft.length === right.length &&\n\t\tleft.every((term, index) => {\n\t\t\tconst other = right[index]\n\t\t\treturn other !== undefined && term.column === other.column && equal(term, other)\n\t\t})\n\t)\n}\n\n/**\n * Checks whether one column can hold a value — the shape gate every write and every seed passes\n * through.\n *\n * @param column - The column that owns the cell.\n * @param value - The unknown value to inspect.\n * @returns True if the column can hold the value; false otherwise.\n */\nexport function matchesCell(column: TableColumn, value: unknown): value is TableCell {\n\tif (isString(value) && value.length > STRING_LIMIT) return false\n\n\tswitch (column.cell) {\n\t\tcase 'text':\n\t\t\treturn isString(value)\n\t\tcase 'number':\n\t\t\treturn isFiniteNumber(value)\n\t\tcase 'flag':\n\t\t\treturn isBoolean(value)\n\t\tcase 'choice':\n\t\t\treturn isString(value) && column.choices.some((choice) => choice.value === value)\n\t}\n}\n\n/**\n * Compares two of one column's cells the way its `cell` fixes, describing ascending order.\n *\n * @param column - The column that fixes the comparison.\n * @param left - The first cell, or absence.\n * @param right - The second cell, or absence.\n * @returns A negative number, positive number, or zero in sort-comparator form.\n */\nexport function compareCells(\n\tcolumn: TableColumn,\n\tleft: TableCell | undefined,\n\tright: TableCell | undefined,\n): number {\n\tif (left === undefined) return right === undefined ? 0 : -1\n\tif (right === undefined) return 1\n\n\tswitch (column.cell) {\n\t\tcase 'text':\n\t\t\tif (!isString(left) || !isString(right)) return 0\n\t\t\treturn left < right ? -1 : left > right ? 1 : 0\n\t\tcase 'number':\n\t\t\tif (!isFiniteNumber(left) || !isFiniteNumber(right)) return 0\n\t\t\treturn left - right\n\t\tcase 'flag':\n\t\t\tif (!isBoolean(left) || !isBoolean(right)) return 0\n\t\t\treturn left === right ? 0 : left ? 1 : -1\n\t\tcase 'choice': {\n\t\t\tif (!isString(left) || !isString(right)) return 0\n\t\t\tconst leftIndex = column.choices.findIndex((choice) => choice.value === left)\n\t\t\tconst rightIndex = column.choices.findIndex((choice) => choice.value === right)\n\t\t\treturn leftIndex - rightIndex\n\t\t}\n\t}\n}\n\n/**\n * Checks whether one column admits a filter and every operand it carries — the gate `filter.set`\n * and {@link matchesFilter} share.\n *\n * @param column - The column that fixes the accepted operators and cell shapes.\n * @param filter - The filter to inspect.\n * @returns True if the filter belongs to the column and the column can apply it; false otherwise.\n */\nexport function admitsFilter(column: TableColumn, filter: TableFilter): boolean {\n\tif (filter.column !== column.key) return false\n\n\tswitch (filter.operator) {\n\t\tcase 'contains':\n\t\t\treturn (\n\t\t\t\t(column.cell === 'text' || column.cell === 'choice') && filter.text.length <= STRING_LIMIT\n\t\t\t)\n\t\tcase 'between':\n\t\t\treturn (\n\t\t\t\t(column.cell === 'text' || column.cell === 'number') &&\n\t\t\t\tmatchesCell(column, filter.minimum) &&\n\t\t\t\tmatchesCell(column, filter.maximum)\n\t\t\t)\n\t\tcase 'equals':\n\t\t\treturn matchesCell(column, filter.value)\n\t}\n}\n\n/**\n * Tests one of a column's cells against one filter the way its `cell` fixes.\n *\n * @param column - The column that fixes the accepted operators.\n * @param cell - The cell to test, or absence.\n * @param filter - The filter to apply.\n * @returns True if the filter accepts the cell; false otherwise.\n */\nexport function matchesFilter(\n\tcolumn: TableColumn,\n\tcell: TableCell | undefined,\n\tfilter: TableFilter,\n): boolean {\n\tif (cell === undefined || !admitsFilter(column, filter) || !matchesCell(column, cell))\n\t\treturn false\n\n\tswitch (filter.operator) {\n\t\tcase 'contains':\n\t\t\treturn isString(cell) && cell.includes(filter.text)\n\t\tcase 'between':\n\t\t\treturn (\n\t\t\t\tcompareCells(column, cell, filter.minimum) >= 0 &&\n\t\t\t\tcompareCells(column, cell, filter.maximum) <= 0\n\t\t\t)\n\t\tcase 'equals':\n\t\t\treturn cell === filter.value\n\t}\n}\n\n/**\n * Keeps the rows every filter accepts, in the order given; a supplied {@link CellMatcher}\n * replaces the default per column.\n *\n * @param schema - The schema that declares the filtered columns.\n * @param rows - The rows to filter.\n * @param filters - The filters to apply with and-only composition.\n * @param matchers - Optional per-column replacements for the default matcher.\n * @returns A frozen copy of the accepted rows in their original order.\n */\nexport function filterRows(\n\tschema: TableSchema,\n\trows: readonly TableRow[],\n\tfilters: readonly TableFilter[],\n\tmatchers?: Readonly<Record<string, CellMatcher>>,\n): readonly TableRow[] {\n\treturn Object.freeze(\n\t\trows.filter((row) =>\n\t\t\tfilters.every((filter) => {\n\t\t\t\tconst column = extractColumn(schema, filter.column)\n\t\t\t\tif (column === undefined) return false\n\t\t\t\tconst matcher =\n\t\t\t\t\tmatchers !== undefined && Object.hasOwn(matchers, column.key)\n\t\t\t\t\t\t? matchers[column.key]\n\t\t\t\t\t\t: undefined\n\t\t\t\tconst cell = Object.hasOwn(row, column.key) ? row[column.key] : undefined\n\t\t\t\treturn matcher === undefined ? matchesFilter(column, cell, filter) : matcher(cell, filter)\n\t\t\t}),\n\t\t),\n\t)\n}\n\n/**\n * Orders rows by the terms given, stably; a supplied {@link CellComparator} replaces the default\n * per column.\n *\n * @param schema - The schema that declares the sorted columns.\n * @param rows - The rows to order.\n * @param orders - The ordered sort terms.\n * @param comparators - Optional per-column replacements for the default comparator.\n * @returns A frozen sorted copy that leaves the input untouched.\n */\nexport function sortRows(\n\tschema: TableSchema,\n\trows: readonly TableRow[],\n\torders: readonly TableOrder[],\n\tcomparators?: Readonly<Record<string, CellComparator>>,\n): readonly TableRow[] {\n\tconst indexed = rows.map((row, index) => ({ row, index }))\n\n\tindexed.sort((left, right) => {\n\t\tfor (const order of orders) {\n\t\t\tconst column = extractColumn(schema, order.column)\n\t\t\tif (column === undefined) continue\n\t\t\tconst comparator =\n\t\t\t\tcomparators !== undefined && Object.hasOwn(comparators, column.key)\n\t\t\t\t\t? comparators[column.key]\n\t\t\t\t\t: undefined\n\t\t\tconst leftCell = Object.hasOwn(left.row, column.key) ? left.row[column.key] : undefined\n\t\t\tconst rightCell = Object.hasOwn(right.row, column.key) ? right.row[column.key] : undefined\n\t\t\tconst compared =\n\t\t\t\tcomparator === undefined\n\t\t\t\t\t? compareCells(column, leftCell, rightCell)\n\t\t\t\t\t: comparator(leftCell, rightCell)\n\t\t\tif (compared !== 0 && !Number.isNaN(compared)) {\n\t\t\t\treturn order.direction === 'ascending' ? compared : -compared\n\t\t\t}\n\t\t}\n\n\t\treturn left.index - right.index\n\t})\n\n\treturn Object.freeze(indexed.map((entry) => entry.row))\n}\n\n/**\n * Audits a structurally valid schema for domain faults and budget breaches, returning human\n * diagnostics.\n *\n * @param schema - The table schema to audit.\n * @returns Frozen human-readable diagnostics, or an empty list when the schema is sound.\n */\nexport function auditTable(schema: TableSchema): readonly string[] {\n\tconst faults: string[] = []\n\tconst columns = new Set<string>()\n\tlet choiceExceeded: string | undefined\n\tlet nameExceeded = schema.name !== undefined && schema.name.length > NAME_LIMIT\n\n\tif (schema.columns.length > COLUMN_LIMIT) {\n\t\tfaults.push(`schema declares more than ${COLUMN_LIMIT} columns`)\n\t}\n\n\tconst columnCount = Math.min(schema.columns.length, COLUMN_LIMIT + 1)\n\tfor (let index = 0; index < columnCount; index += 1) {\n\t\tconst column = schema.columns[index]\n\t\tif (column === undefined) continue\n\t\tif (column.key.length > NAME_LIMIT) nameExceeded = true\n\t\tif (\n\t\t\tchoiceExceeded === undefined &&\n\t\t\tcolumn.cell === 'choice' &&\n\t\t\tcolumn.choices.length > CHOICE_LIMIT\n\t\t) {\n\t\t\tchoiceExceeded = column.key\n\t\t}\n\t}\n\n\tif (choiceExceeded !== undefined) {\n\t\tfaults.push(`column \"${choiceExceeded}\" offers more than ${CHOICE_LIMIT} choices`)\n\t}\n\tif (nameExceeded) faults.push(`schema contains a name longer than ${NAME_LIMIT}`)\n\n\tconst pending: unknown[] = [schema]\n\tconst metadata: boolean[] = [false]\n\tlet position = 0\n\tlet stringExceeded = false\n\tlet textExceeded = false\n\tlet nodeExceeded = false\n\tlet text = 0\n\n\twhile (position < pending.length) {\n\t\tconst node = pending[position]\n\t\tconst inMeta = metadata[position] === true\n\t\tposition += 1\n\n\t\tif (isString(node)) {\n\t\t\tif (node.length > STRING_LIMIT) stringExceeded = true\n\t\t\ttext = Math.min(TEXT_LIMIT + 1, text + node.length)\n\t\t\tif (text > TEXT_LIMIT) textExceeded = true\n\t\t\tcontinue\n\t\t}\n\n\t\tif (isArray(node)) {\n\t\t\tconst read = readArrayEntries(node)\n\t\t\tif (!read.success || !read.value.dense) continue\n\t\t\tfor (const entry of read.value.entries) {\n\t\t\t\tif (pending.length >= NODE_LIMIT) {\n\t\t\t\t\tnodeExceeded = true\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tpending.push(entry)\n\t\t\t\tmetadata.push(inMeta)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif (!isRecord(node)) continue\n\t\tconst keys = attempt(() => Object.keys(node))\n\t\tif (!keys.success) continue\n\n\t\tfor (const key of keys.value) {\n\t\t\tif (inMeta) {\n\t\t\t\tif (key.length > STRING_LIMIT) stringExceeded = true\n\t\t\t\ttext = Math.min(TEXT_LIMIT + 1, text + key.length)\n\t\t\t\tif (text > TEXT_LIMIT) textExceeded = true\n\t\t\t}\n\n\t\t\tconst value = attempt(() => node[key])\n\t\t\tif (!value.success || value.value === undefined) continue\n\t\t\tif (pending.length >= NODE_LIMIT) {\n\t\t\t\tnodeExceeded = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpending.push(value.value)\n\t\t\tmetadata.push(inMeta || key === 'meta')\n\t\t}\n\t}\n\n\tif (stringExceeded) faults.push(`schema contains a string longer than ${STRING_LIMIT}`)\n\tif (textExceeded) faults.push(`schema retains more than ${TEXT_LIMIT} string code units`)\n\tif (nodeExceeded) faults.push(`schema retains more than ${NODE_LIMIT} nodes`)\n\n\tfor (let index = 0; index < columnCount; index += 1) {\n\t\tconst column = schema.columns[index]\n\t\tif (column === undefined) continue\n\t\tif (!nodeExceeded && column.meta !== undefined) {\n\t\t\tconst owned = attempt(() => cloneJSONRecord(column.meta))\n\t\t\tif (!owned.success) {\n\t\t\t\tfaults.push(`column \"${column.key}\" has metadata that cannot be owned`)\n\t\t\t}\n\t\t}\n\t\tif (column.key.length === 0) faults.push('column \"\" has an empty key')\n\t\tif (columns.has(column.key)) {\n\t\t\tfaults.push(`column \"${column.key}\" is declared more than once`)\n\t\t}\n\t\tcolumns.add(column.key)\n\n\t\tif (column.cell === 'choice') {\n\t\t\tconst choices = new Set<string>()\n\t\t\tconst choiceCount = Math.min(column.choices.length, CHOICE_LIMIT + 1)\n\t\t\tfor (let choiceIndex = 0; choiceIndex < choiceCount; choiceIndex += 1) {\n\t\t\t\tconst choice = column.choices[choiceIndex]\n\t\t\t\tif (choice === undefined) continue\n\t\t\t\tif (choices.has(choice.value)) {\n\t\t\t\t\tfaults.push(`column \"${column.key}\" offers choice \"${choice.value}\" more than once`)\n\t\t\t\t}\n\t\t\t\tchoices.add(choice.value)\n\t\t\t}\n\t\t\tif (column.choices.length === 0) {\n\t\t\t\tfaults.push(`column \"${column.key}\" offers no choices`)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst key = extractColumn(schema, schema.key)\n\tif (key === undefined) {\n\t\tfaults.push(`schema key \"${schema.key}\" names no declared column`)\n\t} else if (key.cell === 'number' || key.cell === 'flag') {\n\t\tfaults.push(`schema key \"${schema.key}\" names a ${key.cell} column, which holds no identity`)\n\t}\n\n\treturn Object.freeze(faults)\n}\n\n/**\n * Projects a schema into JSON in declaration order, dropping every absent member; raises `SCHEMA`\n * for a `meta` it cannot own.\n *\n * @param schema - The schema to project.\n * @returns A deeply owned JSON record with absent members omitted.\n * @throws A {@link TableError} coded `SCHEMA` when metadata cannot be owned.\n */\nexport function serializeTable(schema: TableSchema): JSONRecord {\n\tconst output: Record<string, JSONValue> = {}\n\tif (schema.name !== undefined) output.name = schema.name\n\tif (schema.label !== undefined) output.label = schema.label\n\tif (schema.help !== undefined) output.help = schema.help\n\toutput.key = schema.key\n\toutput.columns = schema.columns.map((column): JSONRecord => {\n\t\tconst entry: Record<string, JSONValue> = { cell: column.cell, key: column.key }\n\t\tif (column.label !== undefined) entry.label = column.label\n\t\tif (column.help !== undefined) entry.help = column.help\n\t\tif (column.hidden !== undefined) entry.hidden = column.hidden\n\t\tif (column.meta !== undefined) entry.meta = column.meta\n\t\tif (column.cell === 'choice') {\n\t\t\tentry.choices = column.choices.map((choice): JSONRecord => {\n\t\t\t\tconst option: Record<string, JSONValue> = {\n\t\t\t\t\tvalue: choice.value,\n\t\t\t\t\tlabel: choice.label,\n\t\t\t\t}\n\t\t\t\tif (choice.help !== undefined) option.help = choice.help\n\t\t\t\treturn option\n\t\t\t})\n\t\t}\n\t\treturn entry\n\t})\n\n\ttry {\n\t\treturn cloneJSONRecord(output)\n\t} catch (error) {\n\t\tif (!isContractError(error)) throw error\n\t\tthrow new TableError('SCHEMA', 'schema contains metadata that cannot be owned')\n\t}\n}\n\n/**\n * Projects rows into JSON with each row's cells in the schema's column order, dropping every\n * absent cell.\n *\n * @param schema - The schema that fixes cell order.\n * @param rows - The rows to project.\n * @returns A frozen list of owned JSON records with absent cells omitted.\n */\nexport function serializeRows(\n\tschema: TableSchema,\n\trows: readonly TableRow[],\n): readonly JSONRecord[] {\n\tconst output: JSONRecord[] = []\n\n\tfor (const row of rows) {\n\t\tconst entry: Record<string, JSONPrimitive> = {}\n\t\tfor (const column of schema.columns) {\n\t\t\tif (!Object.hasOwn(row, column.key)) continue\n\t\t\tconst value = row[column.key]\n\t\t\tif (value === undefined) continue\n\t\t\tObject.defineProperty(entry, column.key, {\n\t\t\t\tvalue,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t\twritable: true,\n\t\t\t})\n\t\t}\n\t\toutput.push(cloneJSONRecord(entry))\n\t}\n\n\treturn Object.freeze(output)\n}\n\n/** Compares complete row values independently of their snapshot identities.\n * @param left - The previous row, if present.\n * @param right - The next row.\n * @returns Whether both rows carry exactly the same cells.\n */\nexport function matchesTableRow(left: TableRow | undefined, right: TableRow): boolean {\n\treturn (\n\t\tleft !== undefined &&\n\t\tObject.keys(left).length === Object.keys(right).length &&\n\t\tObject.keys(right).every((key) => Object.hasOwn(left, key) && left[key] === right[key])\n\t)\n}\n","import type {\n\tColumnCell,\n\tColumnChoice,\n\tTableCell,\n\tTableColumn,\n\tTableRow,\n\tTableSchema,\n} from './types.js'\nimport {\n\tarrayOf,\n\tattempt,\n\tcloneJSONRecord,\n\tisBoolean,\n\tisBoundedJSONRecord,\n\tisFiniteNumber,\n\tisRecord,\n\tisString,\n\trecordOf,\n\tunionOf,\n} from '@orkestrel/contract'\nimport { COLUMN_CELLS } from './constants.js'\nimport { auditTable } from './helpers.js'\n\n/**\n * Determines whether an unknown value has a table cell shape — a string, a finite number, or a\n * boolean.\n *\n * @param input - The value to inspect.\n * @returns True if the value is a string, finite number, or boolean; false otherwise.\n */\nexport function isTableCell(input: unknown): input is TableCell {\n\treturn unionOf(isString, isFiniteNumber, isBoolean)(input)\n}\n\n/**\n * Determines whether an unknown value is a record whose every own key is a string and every value\n * a {@link TableCell}.\n *\n * @param input - The value to inspect.\n * @returns True if every own key is a string and every value is a table cell; false otherwise.\n */\nexport function isTableRow(input: unknown): input is TableRow {\n\tconst outcome = attempt(() => {\n\t\tif (!isRecord(input)) return false\n\t\treturn Reflect.ownKeys(input).every(\n\t\t\t(key) => isString(key) && Object.hasOwn(input, key) && isTableCell(input[key]),\n\t\t)\n\t})\n\n\treturn outcome.success && outcome.value\n}\n\n/**\n * Determines whether an unknown value is a declared column cell.\n *\n * @param input - The value to inspect.\n * @returns True if the value is a declared column cell; false otherwise.\n */\nexport function isColumnCell(input: unknown): input is ColumnCell {\n\treturn COLUMN_CELLS.some((cell) => cell === input)\n}\n\n/**\n * Determines whether an unknown value is one exact {@link ColumnChoice} record; an unknown member\n * refuses it.\n *\n * @param input - The value to inspect.\n * @returns True if the value is a column choice; false otherwise.\n */\nexport function isColumnChoice(input: unknown): input is ColumnChoice {\n\tconst outcome = attempt(() => {\n\t\tif (!isRecord(input) || !Reflect.ownKeys(input).every((key) => isString(key))) return false\n\t\treturn recordOf({ value: isString, label: isString, help: isString }, ['help'])(input)\n\t})\n\n\treturn outcome.success && outcome.value\n}\n\n/**\n * Determines whether an unknown value is one exact discriminated {@link TableColumn}, checked\n * against its cell's own options.\n *\n * @param input - The value to inspect.\n * @returns True if the value is a structurally valid table column; false otherwise.\n */\nexport function isTableColumn(input: unknown): input is TableColumn {\n\tconst outcome = attempt(() => {\n\t\tif (!isRecord(input) || !Object.hasOwn(input, 'cell') || !Object.hasOwn(input, 'key')) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst cell = input.cell\n\t\tif (!isColumnCell(cell)) return false\n\n\t\tconst exact = Reflect.ownKeys(input).every((key) => {\n\t\t\tif (!isString(key)) return false\n\t\t\tif (['cell', 'key', 'label', 'help', 'hidden', 'meta'].includes(key)) return true\n\t\t\treturn cell === 'choice' && key === 'choices'\n\t\t})\n\t\tif (!exact) return false\n\n\t\tconst key = input.key\n\t\tconst hasLabel = Object.hasOwn(input, 'label')\n\t\tconst label = hasLabel ? input.label : undefined\n\t\tconst hasHelp = Object.hasOwn(input, 'help')\n\t\tconst help = hasHelp ? input.help : undefined\n\t\tconst hasHidden = Object.hasOwn(input, 'hidden')\n\t\tconst hidden = hasHidden ? input.hidden : undefined\n\t\tconst hasMeta = Object.hasOwn(input, 'meta')\n\t\tconst meta = hasMeta ? input.meta : undefined\n\t\tif (hasMeta) {\n\t\t\tif (!isBoundedJSONRecord(meta)) return false\n\t\t\tconst owned = attempt(() => cloneJSONRecord(meta))\n\t\t\tif (!owned.success) return false\n\t\t}\n\n\t\tif (\n\t\t\t!isString(key) ||\n\t\t\t(hasLabel && !isString(label)) ||\n\t\t\t(hasHelp && !isString(help)) ||\n\t\t\t(hasHidden && !isBoolean(hidden))\n\t\t) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (cell !== 'choice') return !Object.hasOwn(input, 'choices')\n\t\treturn Object.hasOwn(input, 'choices') && arrayOf(isColumnChoice)(input.choices)\n\t})\n\n\treturn outcome.success && outcome.value\n}\n\n/**\n * Determines whether an unknown value has the exact shape of a {@link TableSchema} — the shape\n * alone, with no domain check.\n *\n * @param input - The value to inspect.\n * @returns True if the value has the exact structure of a table schema; false otherwise.\n */\nexport function isStructuralTableSchema(input: unknown): input is TableSchema {\n\tconst outcome = attempt(() => {\n\t\tif (!isRecord(input) || !Reflect.ownKeys(input).every((key) => isString(key))) return false\n\t\treturn recordOf(\n\t\t\t{\n\t\t\t\tname: isString,\n\t\t\t\tlabel: isString,\n\t\t\t\thelp: isString,\n\t\t\t\tkey: isString,\n\t\t\t\tcolumns: arrayOf(isTableColumn),\n\t\t\t},\n\t\t\t['name', 'label', 'help'],\n\t\t)(input)\n\t})\n\n\treturn outcome.success && outcome.value\n}\n\n/**\n * Determines whether an unknown value is a {@link TableSchema} a table can be opened against —\n * the exact shape, and an audit that finds nothing.\n *\n * @param input - The value to inspect.\n * @returns True if the value has valid structure, domain relationships, and\n * budgets; false otherwise.\n */\nexport function isTableSchema(input: unknown): input is TableSchema {\n\tconst outcome = attempt(() => isStructuralTableSchema(input) && auditTable(input).length === 0)\n\treturn outcome.success && outcome.value\n}\n","import type { TableCell, TableRow, TableSchema } from './types.js'\nimport {\n\tattempt,\n\tisArray,\n\tisRecord,\n\tisString,\n\tparseNumber,\n\treadArrayEntries,\n} from '@orkestrel/contract'\nimport { cloneRow } from './cloners.js'\nimport { STRING_LIMIT } from './constants.js'\nimport { extractColumn, extractKey, matchesCell, serializeTable } from './helpers.js'\nimport { isTableSchema } from './validators.js'\n\n/**\n * Parses unknown wire data into an owned, structurally valid, semantically sound table schema.\n *\n * @param input - The unknown schema value to parse.\n * @returns An owned table schema, or `undefined` on refusal.\n */\nexport function parseTable(input: unknown): TableSchema | undefined {\n\tconst outcome = attempt(() => {\n\t\tif (!isTableSchema(input)) return undefined\n\t\tconst projected = serializeTable(input)\n\t\treturn isTableSchema(projected) ? projected : undefined\n\t})\n\n\treturn outcome.success ? outcome.value : undefined\n}\n\n/**\n * Parses unknown wire data into owned rows against one table schema, coercing a numeric string\n * and `'true'` / `'false'`.\n *\n * @param schema - The schema that declares the accepted keys and cell shapes.\n * @param input - The unknown row-list value to parse.\n * @returns Frozen owned rows, or `undefined` when any row is refused.\n */\nexport function parseRows(schema: TableSchema, input: unknown): readonly TableRow[] | undefined {\n\tconst outcome = attempt(() => {\n\t\tif (!isTableSchema(schema) || !isArray(input)) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst read = readArrayEntries(input)\n\t\tif (!read.success || !read.value.dense) return undefined\n\n\t\tconst keys = new Set<string>()\n\t\tconst rows: TableRow[] = []\n\n\t\tfor (const candidate of read.value.entries) {\n\t\t\tif (!isRecord(candidate)) return undefined\n\t\t\tconst row: Record<string, TableCell> = {}\n\n\t\t\tfor (const key of Reflect.ownKeys(candidate)) {\n\t\t\t\tif (!isString(key) || !Object.hasOwn(candidate, key)) return undefined\n\t\t\t\tconst column = extractColumn(schema, key)\n\t\t\t\tif (column === undefined) return undefined\n\t\t\t\tconst inputCell = candidate[key]\n\t\t\t\tlet cell: unknown = inputCell\n\n\t\t\t\tif (column.cell === 'number' && isString(inputCell)) {\n\t\t\t\t\tif (inputCell.length > STRING_LIMIT) return undefined\n\t\t\t\t\tcell = parseNumber(inputCell)\n\t\t\t\t} else if (column.cell === 'flag' && inputCell === 'true') {\n\t\t\t\t\tcell = true\n\t\t\t\t} else if (column.cell === 'flag' && inputCell === 'false') {\n\t\t\t\t\tcell = false\n\t\t\t\t}\n\n\t\t\t\tif (!matchesCell(column, cell)) return undefined\n\t\t\t\tObject.defineProperty(row, key, {\n\t\t\t\t\tvalue: cell,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tconst owned = cloneRow(row)\n\t\t\tconst key = extractKey(schema, owned)\n\t\t\tif (key === undefined || keys.has(key)) return undefined\n\t\t\tkeys.add(key)\n\t\t\trows.push(owned)\n\t\t}\n\n\t\treturn Object.freeze(rows)\n\t})\n\n\treturn outcome.success ? outcome.value : undefined\n}\n","import type { TableProjection } from './types.js'\nimport type { TableRow, TableSchema } from '../core/types.js'\nimport { parseJSON } from '@orkestrel/contract'\nimport { parseRows, parseTable } from '../core/parsers.js'\nimport { TableBindingError } from './errors.js'\n\n/** Reads declared header metadata and explicit row keys into a validated core projection.\n * @param element - A native table with data-table-key naming its identity column.\n * @returns The schema and rows, validated together before any mutation.\n * @throws A binding error when metadata, identities, or cells are malformed.\n * @example\n * ```ts\n * import { createTable } from '@orkestrel/table'\n * import { readTable } from '@orkestrel/table/browser'\n * const element = document.createElement('table')\n * element.setAttribute('data-table-key', 'id')\n * element.innerHTML = '<thead><tr><th data-table-column=\"id\" data-table-cell=\"text\">Reference</th></tr></thead><tbody></tbody>'\n * const projection = readTable(element)\n * const table = createTable(projection.schema, { rows: projection.rows })\n * ```\n */\nexport function readTable(element: HTMLTableElement): TableProjection {\n\tconst schema = readTableSchema(element)\n\treturn { schema, rows: readTableRows(schema, Array.from(element.tBodies[0]?.rows ?? [])) }\n}\n\n/** Reads and validates explicit native header metadata.\n * @param element - The table declaring its identity column and cell kinds.\n * @returns The core schema described by the native headers.\n */\nexport function readTableSchema(element: HTMLTableElement): TableSchema {\n\tconst columns = Array.from(element.tHead?.querySelectorAll('th[data-table-column]') ?? [])\n\t\t.filter((header) => header.closest('table') === element)\n\t\t.map((header) => ({\n\t\t\tkey: header.getAttribute('data-table-column'),\n\t\t\tcell: header.getAttribute('data-table-cell'),\n\t\t\tlabel: header.textContent?.trim() ?? '',\n\t\t\t...(header.hasAttribute('data-table-choices')\n\t\t\t\t? { choices: parseJSON(header.getAttribute('data-table-choices') ?? '') }\n\t\t\t\t: {}),\n\t\t}))\n\tconst schema = parseTable({ key: element.getAttribute('data-table-key'), columns })\n\tif (schema === undefined || element.tBodies.length !== 1)\n\t\tthrow new TableBindingError(\n\t\t\t'STRUCTURE',\n\t\t\t'Declare one body, an identity column, and valid header metadata',\n\t\t)\n\treturn schema\n}\n\n/** Reads explicit keys and declared direct cells against a core schema.\n * @param schema - The declared columns and identity column.\n * @param elements - Data rows belonging to one table, including retained detached rows.\n * @returns Validated rows in the supplied order.\n * @throws A binding error for duplicate keys, undeclared cells, or malformed values.\n */\nexport function readTableRows(\n\tschema: TableSchema,\n\telements: readonly HTMLTableRowElement[],\n): readonly TableRow[] {\n\tconst candidates = elements.map((element) => {\n\t\tconst cells: Record<string, unknown> = { [schema.key]: element.getAttribute('data-table-key') }\n\t\tconst seen = new Set<string>()\n\t\tfor (const cell of element.cells) {\n\t\t\tconst column = cell.getAttribute('data-table-column')\n\t\t\tif (column === null) continue\n\t\t\tif (seen.has(column))\n\t\t\t\tthrow new TableBindingError('STRUCTURE', 'A row repeats a declared cell')\n\t\t\tseen.add(column)\n\t\t\tconst value = cell.querySelector('data[value], time[datetime]')\n\t\t\tconst text =\n\t\t\t\tvalue?.closest('table') === element.closest('table')\n\t\t\t\t\t? (value?.getAttribute('value') ?? value?.getAttribute('datetime') ?? '')\n\t\t\t\t\t: (cell.textContent ?? '')\n\t\t\tif (column === schema.key && text !== cells[schema.key])\n\t\t\t\tthrow new TableBindingError('STRUCTURE', 'The identity cell disagrees with its row key')\n\t\t\tObject.defineProperty(cells, column, { value: text, enumerable: true, configurable: true })\n\t\t}\n\t\treturn cells\n\t})\n\tconst rows = parseRows(schema, candidates)\n\tif (rows === undefined)\n\t\tthrow new TableBindingError('STRUCTURE', 'Native row keys or cells are invalid')\n\treturn rows\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type { TableInterface, TableRow } from '../core/types.js'\nimport type { TableBindingEventMap, TableBindingInterface, TableBindingOptions } from './types.js'\nimport { attempt } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { extractKey, matchesTableRow } from '../core/helpers.js'\nimport { TableBindingError } from './errors.js'\nimport { readTableRows, readTableSchema } from './helpers.js'\n\n/** Retains keyed native rows while projecting every core table manager. */\nexport class TableBinding implements TableBindingInterface {\n\treadonly #element: HTMLTableElement\n\treadonly #document: TableInterface\n\treadonly #options: TableBindingOptions\n\treadonly #body: HTMLTableSectionElement\n\treadonly #scope: HTMLElement\n\treadonly #emitter: Emitter<TableBindingEventMap>\n\treadonly #lifetime = new AbortController()\n\treadonly #observer: MutationObserver\n\treadonly #rows = new Map<string, HTMLTableRowElement>()\n\treadonly #values = new Map<string, TableRow>()\n\treadonly #details = new Map<string, HTMLTableRowElement>()\n\treadonly #detailValues = new Map<string, TableRow>()\n\treadonly #visible = new Set<HTMLTableRowElement>()\n\treadonly #attributes = new Map<\n\t\tElement,\n\t\tMap<string, { readonly original: string | null; value: string | null }>\n\t>()\n\treadonly #checks = new Map<\n\t\tHTMLInputElement,\n\t\t{ readonly checked: boolean; readonly indeterminate: boolean; value: boolean; mixed: boolean }\n\t>()\n\treadonly #schedule = this.#enqueue.bind(this)\n\treadonly #subscriptions: Array<() => void> = []\n\t#pending: ReturnType<typeof setTimeout> | undefined\n\t#rendering = false\n\t#requesting = false\n\t#records: MutationRecord[] = []\n\n\t/** Creates a native binding over a borrowed document.\n\t * @param element - The table whose body the binding owns.\n\t * @param document - The core document retained by the caller.\n\t * @param options - Row ownership, detail renderer, controls, and listeners.\n\t */\n\tconstructor(\n\t\telement: HTMLTableElement,\n\t\tdocument: TableInterface,\n\t\toptions: TableBindingOptions = {},\n\t) {\n\t\tif (element.tBodies.length !== 1 || document.destroyed)\n\t\t\tthrow new TableBindingError('STRUCTURE', 'Bind one table body to a live document')\n\t\tconst body = element.tBodies[0]\n\t\tif (body === undefined) throw new TableBindingError('STRUCTURE', 'The table has no body')\n\t\tthis.#element = element\n\t\tthis.#document = document\n\t\tthis.#options = { ...options }\n\t\tthis.#body = body\n\t\tthis.#scope = options.scope ?? element\n\t\tif (!this.#scope.contains(element))\n\t\t\tthrow new TableBindingError('STRUCTURE', 'The scope must contain the table')\n\t\tthis.#emitter = new Emitter<TableBindingEventMap>({\n\t\t\t...(options.on === undefined ? {} : { on: options.on }),\n\t\t\t...(options.error === undefined ? {} : { error: options.error }),\n\t\t})\n\t\tthis.#observer = new MutationObserver((records) => {\n\t\t\tthis.#records.push(...records)\n\t\t\tthis.#enqueue()\n\t\t})\n\t\tif (options.row === undefined) {\n\t\t\tthis.#validateSchema()\n\t\t\tconst elements = Array.from(body.rows)\n\t\t\tconst rows = readTableRows(document.schema, elements)\n\t\t\tif (\n\t\t\t\trows.length !== document.rows.rows().length ||\n\t\t\t\trows.some((row) => {\n\t\t\t\t\tconst key = extractKey(document.schema, row)\n\t\t\t\t\treturn key === undefined || !matchesTableRow(document.rows.row(key), row)\n\t\t\t\t})\n\t\t\t)\n\t\t\t\tthrow new TableBindingError('STRUCTURE', 'Authored rows must match the supplied document')\n\t\t\tfor (const [index, row] of rows.entries()) {\n\t\t\t\tconst key = extractKey(document.schema, row)\n\t\t\t\tconst node = elements[index]\n\t\t\t\tif (key !== undefined && node !== undefined) this.#rows.set(key, node)\n\t\t\t}\n\t\t} else if (body.rows.length > 0) {\n\t\t\tthrow new TableBindingError('STRUCTURE', 'Model rendering requires an empty body')\n\t\t}\n\t\tfor (const event of [\n\t\t\t'write',\n\t\t\t'remove',\n\t\t\t'sort',\n\t\t\t'filter',\n\t\t\t'select',\n\t\t\t'expand',\n\t\t\t'paginate',\n\t\t\t'clear',\n\t\t] as const) {\n\t\t\tdocument.emitter.on(event, this.#schedule)\n\t\t\tthis.#subscriptions.push(() => document.emitter.off(event, this.#schedule))\n\t\t}\n\t\telement.addEventListener('click', (event) => this.#click(event), {\n\t\t\tsignal: this.#lifetime.signal,\n\t\t})\n\t\tthis.#scope.addEventListener('change', (event) => this.#change(event), {\n\t\t\tsignal: this.#lifetime.signal,\n\t\t})\n\t\tthis.#observe()\n\t\tthis.refresh()\n\t}\n\n\tget element(): HTMLTableElement {\n\t\treturn this.#element\n\t}\n\tget document(): TableInterface {\n\t\treturn this.#document\n\t}\n\tget destroyed(): boolean {\n\t\treturn this.#lifetime.signal.aborted\n\t}\n\tget emitter(): EmitterInterface<TableBindingEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Reconciles native input and retries rendering against the current document. */\n\trefresh(): void {\n\t\tif (this.destroyed) return\n\t\tif (this.#rendering) {\n\t\t\tthis.#enqueue()\n\t\t\treturn\n\t\t}\n\t\tif (this.#pending !== undefined) clearTimeout(this.#pending)\n\t\tthis.#pending = undefined\n\t\tthis.#rendering = true\n\t\tconst outcome = attempt(() => {\n\t\t\tthis.#records.push(...this.#observer.takeRecords())\n\t\t\tif (this.#options.row === undefined && this.#records.length > 0) this.#reconcile()\n\t\t\tif (!this.destroyed) this.#render()\n\t\t})\n\t\tif (!outcome.success && !this.destroyed) this.#emitter.emit('error', outcome.error)\n\t\telse if (!this.destroyed) this.#emitter.emit('render')\n\t\tthis.#rendering = false\n\t}\n\n\t/** Releases native resources and restores authored state while retaining the core document. */\n\tdestroy(): void {\n\t\tif (this.destroyed) return\n\t\tconst active = this.#element.ownerDocument.activeElement\n\t\tconst focused =\n\t\t\tactive instanceof HTMLElement && [...this.#rows.values()].some((row) => row.contains(active))\n\t\t\t\t? active\n\t\t\t\t: undefined\n\t\tthis.#lifetime.abort()\n\t\tif (this.#pending !== undefined) clearTimeout(this.#pending)\n\t\tthis.#pending = undefined\n\t\tthis.#observer.disconnect()\n\t\tfor (const unsubscribe of this.#subscriptions) unsubscribe()\n\t\tthis.#subscriptions.length = 0\n\t\tfor (const detail of this.#details.values()) detail.remove()\n\t\tif (this.#options.row === undefined) {\n\t\t\tfor (const row of this.#document.rows.rows()) {\n\t\t\t\tconst key = extractKey(this.#document.schema, row)\n\t\t\t\tconst node = key === undefined ? undefined : this.#rows.get(key)\n\t\t\t\tif (node !== undefined) this.#place(node, null)\n\t\t\t}\n\t\t}\n\t\tfor (const element of this.#attributes.keys()) this.#release(element)\n\t\tfor (const input of this.#checks.keys()) this.#release(input)\n\t\tthis.#restoreFocus(focused)\n\t\tthis.#rows.clear()\n\t\tthis.#values.clear()\n\t\tthis.#details.clear()\n\t\tthis.#detailValues.clear()\n\t\tthis.#attributes.clear()\n\t\tthis.#checks.clear()\n\t\tthis.#visible.clear()\n\t\tthis.#records = []\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#enqueue(): void {\n\t\tif (this.destroyed || this.#pending !== undefined) return\n\t\tthis.#pending = setTimeout(() => {\n\t\t\tthis.#pending = undefined\n\t\t\tthis.refresh()\n\t\t}, 0)\n\t}\n\n\t#observe(): void {\n\t\tif (this.destroyed || this.#options.row !== undefined) return\n\t\tthis.#records.push(...this.#observer.takeRecords())\n\t\tthis.#observer.disconnect()\n\t\tthis.#observer.observe(this.#element, {\n\t\t\tchildList: true,\n\t\t\tcharacterData: true,\n\t\t\tsubtree: true,\n\t\t\tattributes: true,\n\t\t\tattributeFilter: [\n\t\t\t\t'data-table-key',\n\t\t\t\t'data-table-column',\n\t\t\t\t'data-table-cell',\n\t\t\t\t'data-table-choices',\n\t\t\t\t'value',\n\t\t\t\t'datetime',\n\t\t\t],\n\t\t})\n\t\tfor (const node of this.#rows.values())\n\t\t\tif (node.parentElement !== this.#body)\n\t\t\t\tthis.#observer.observe(node, {\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tcharacterData: true,\n\t\t\t\t\tsubtree: true,\n\t\t\t\t\tattributes: true,\n\t\t\t\t\tattributeFilter: ['data-table-key', 'data-table-column', 'value', 'datetime'],\n\t\t\t\t})\n\t}\n\n\t#validateSchema(): void {\n\t\tconst schema = readTableSchema(this.#element)\n\t\tif (\n\t\t\tschema.key !== this.#document.schema.key ||\n\t\t\tschema.columns.length !== this.#document.schema.columns.length ||\n\t\t\tschema.columns.some((column, index) => {\n\t\t\t\tconst declared = this.#document.schema.columns[index]\n\t\t\t\treturn (\n\t\t\t\t\tdeclared?.key !== column.key ||\n\t\t\t\t\tdeclared.cell !== column.cell ||\n\t\t\t\t\t(column.cell === 'choice' &&\n\t\t\t\t\t\tdeclared.cell === 'choice' &&\n\t\t\t\t\t\tJSON.stringify(column.choices) !== JSON.stringify(declared.choices))\n\t\t\t\t)\n\t\t\t})\n\t\t)\n\t\t\tthrow new TableBindingError('STRUCTURE', 'Header metadata must match the supplied schema')\n\t}\n\n\t#reconcile(): void {\n\t\tthis.#validateSchema()\n\t\tconst retained = Array.from(this.#rows).filter(\n\t\t\t([, node]) => !this.#visible.has(node) || node.parentElement === this.#body,\n\t\t)\n\t\tconst elements = retained.map(([, node]) => node)\n\t\tfor (const node of this.#body.rows)\n\t\t\tif (!elements.includes(node) && !Array.from(this.#details.values()).includes(node))\n\t\t\t\telements.push(node)\n\t\tconst rows = readTableRows(this.#document.schema, elements)\n\t\tthis.#records = []\n\t\tconst keys = new Set(this.#keys(rows))\n\t\tconst additions: TableRow[] = []\n\t\tconst replacements: TableRow[] = []\n\t\tfor (const row of rows) {\n\t\t\tconst key = extractKey(this.#document.schema, row)\n\t\t\tif (key !== undefined && this.#document.rows.row(key) === undefined) additions.push(row)\n\t\t\telse replacements.push(row)\n\t\t}\n\t\tthis.#document.rows.replace(replacements)\n\t\tif (this.destroyed) return\n\t\tthis.#document.rows.add(additions)\n\t\tif (this.destroyed) return\n\t\tfor (const key of this.#rows.keys())\n\t\t\tif (!keys.has(key)) {\n\t\t\t\tthis.#document.rows.remove(key)\n\t\t\t\tif (this.destroyed) return\n\t\t\t}\n\t\tfor (const [index, row] of rows.entries()) {\n\t\t\tconst key = extractKey(this.#document.schema, row)\n\t\t\tconst node = elements[index]\n\t\t\tif (key !== undefined && node !== undefined) this.#rows.set(key, node)\n\t\t}\n\t}\n\n\t#render(): void {\n\t\tconst active = this.#element.ownerDocument.activeElement\n\t\tconst focused =\n\t\t\tactive instanceof HTMLElement &&\n\t\t\t[...this.#rows.values(), ...this.#details.values()].some((row) => row.contains(active))\n\t\t\t\t? active\n\t\t\t\t: undefined\n\t\tconst stored = this.#document.rows.rows()\n\t\tconst keys = new Set(this.#keys(stored))\n\t\tfor (const [key, node] of this.#rows)\n\t\t\tif (!keys.has(key)) {\n\t\t\t\tthis.#place(node)\n\t\t\t\tthis.#release(node)\n\t\t\t\tconst detail = this.#details.get(key)\n\t\t\t\tif (detail !== undefined) this.#place(detail)\n\t\t\t\tthis.#rows.delete(key)\n\t\t\t\tthis.#values.delete(key)\n\t\t\t\tthis.#details.delete(key)\n\t\t\t\tthis.#detailValues.delete(key)\n\t\t\t}\n\t\tconst view = this.#document.view\n\t\tconst ordered: HTMLTableRowElement[] = []\n\t\tfor (const row of view) {\n\t\t\tconst key = extractKey(this.#document.schema, row)\n\t\t\tif (key === undefined) continue\n\t\t\tlet node = this.#rows.get(key)\n\t\t\tif (node === undefined) {\n\t\t\t\tif (this.#options.row === undefined)\n\t\t\t\t\tthrow new TableBindingError('STRUCTURE', 'An authored document row has no native row')\n\t\t\t\tnode = this.#element.ownerDocument.createElement('tr')\n\t\t\t\tnode.setAttribute('data-table-key', key)\n\t\t\t\tthis.#rows.set(key, node)\n\t\t\t}\n\t\t\tif (this.#options.row !== undefined && !matchesTableRow(this.#values.get(key), row)) {\n\t\t\t\tthis.#options.row(node, row)\n\t\t\t\tif (this.destroyed) return\n\t\t\t\tthis.#values.set(key, row)\n\t\t\t}\n\t\t\tordered.push(node)\n\t\t\tconst detail = this.#detail(key, row)\n\t\t\tif (this.destroyed) return\n\t\t\tif (detail !== undefined) ordered.push(detail)\n\t\t\tthis.#controls(node, key, detail)\n\t\t}\n\t\tfor (const node of [...this.#rows.values(), ...this.#details.values()])\n\t\t\tif (!ordered.includes(node) && node.parentElement === this.#body) this.#place(node)\n\t\tfor (const [index, node] of ordered.entries())\n\t\t\tif (this.#body.rows[index] !== node) this.#place(node, this.#body.rows[index] ?? null)\n\t\tthis.#visible.clear()\n\t\tfor (const node of this.#rows.values())\n\t\t\tif (node.parentElement === this.#body) this.#visible.add(node)\n\t\tthis.#headers()\n\t\tthis.#pages(view)\n\t\tthis.#restoreFocus(focused, true)\n\t\tthis.#observe()\n\t\tif (this.#records.length > 0) this.#enqueue()\n\t}\n\n\t#restoreFocus(focused: HTMLElement | undefined, hidden = false): void {\n\t\tif (\n\t\t\tfocused !== undefined &&\n\t\t\tthis.#element.ownerDocument.activeElement !== focused &&\n\t\t\t(this.#element.ownerDocument.activeElement === this.#element.ownerDocument.body ||\n\t\t\t\tthis.#element.ownerDocument.activeElement === null)\n\t\t) {\n\t\t\tif (focused.isConnected) focused.focus({ preventScroll: true })\n\t\t\telse if (hidden) {\n\t\t\t\tthis.#attribute(this.#element, 'tabindex', '-1')\n\t\t\t\tif (\n\t\t\t\t\t!this.#element.hasAttribute('aria-label') &&\n\t\t\t\t\t!this.#element.hasAttribute('aria-labelledby') &&\n\t\t\t\t\tthis.#element.caption === null\n\t\t\t\t)\n\t\t\t\t\tthis.#attribute(this.#element, 'aria-label', this.#document.schema.label ?? 'Table')\n\t\t\t\tthis.#element.focus({ preventScroll: true })\n\t\t\t}\n\t\t}\n\t}\n\n\t#detail(key: string, row: TableRow): HTMLTableRowElement | undefined {\n\t\tif (this.#options.detail === undefined || !this.#document.expansion.keys.has(key))\n\t\t\treturn undefined\n\t\tlet detail = this.#details.get(key)\n\t\tif (detail === undefined) {\n\t\t\tdetail = this.#element.ownerDocument.createElement('tr')\n\t\t\tdetail.id = `table-detail-${crypto.randomUUID()}`\n\t\t\tdetail.insertCell().colSpan = Math.max(\n\t\t\t\t1,\n\t\t\t\tthis.#rows.get(key)?.cells.length ?? this.#document.schema.columns.length,\n\t\t\t)\n\t\t\tthis.#details.set(key, detail)\n\t\t}\n\t\tif (!matchesTableRow(this.#detailValues.get(key), row)) {\n\t\t\tthis.#options.detail(detail, row)\n\t\t\tif (!this.destroyed) this.#detailValues.set(key, row)\n\t\t}\n\t\treturn detail\n\t}\n\n\t#place(node: HTMLTableRowElement, before?: HTMLTableRowElement | null): void {\n\t\tthis.#records.push(...this.#observer.takeRecords())\n\t\tthis.#observer.disconnect()\n\t\tif (before === undefined) node.remove()\n\t\telse if (\n\t\t\ttypeof this.#body.moveBefore === 'function' &&\n\t\t\tnode.isConnected &&\n\t\t\tthis.#body.isConnected\n\t\t)\n\t\t\tthis.#body.moveBefore(node, before)\n\t\telse this.#body.insertBefore(node, before)\n\t\tthis.#observe()\n\t}\n\n\t#attribute(element: Element, name: string, value: string | null): void {\n\t\tlet attributes = this.#attributes.get(element)\n\t\tif (attributes === undefined) {\n\t\t\tattributes = new Map()\n\t\t\tthis.#attributes.set(element, attributes)\n\t\t}\n\t\tconst entry = attributes.get(name)\n\t\tif (entry === undefined) attributes.set(name, { original: element.getAttribute(name), value })\n\t\telse entry.value = value\n\t\tif (value === null) element.removeAttribute(name)\n\t\telse if (element.getAttribute(name) !== value) element.setAttribute(name, value)\n\t}\n\n\t#release(root: Element): void {\n\t\tfor (const [element, attributes] of this.#attributes)\n\t\t\tif (root.contains(element)) {\n\t\t\t\tfor (const [name, entry] of attributes)\n\t\t\t\t\tif (element.getAttribute(name) === entry.value) {\n\t\t\t\t\t\tif (entry.original === null) element.removeAttribute(name)\n\t\t\t\t\t\telse element.setAttribute(name, entry.original)\n\t\t\t\t\t}\n\t\t\t\tthis.#attributes.delete(element)\n\t\t\t}\n\t\tfor (const [input, state] of this.#checks)\n\t\t\tif (root.contains(input)) {\n\t\t\t\tif (input.checked === state.value) input.checked = state.checked\n\t\t\t\tif (input.indeterminate === state.mixed) input.indeterminate = state.indeterminate\n\t\t\t\tthis.#checks.delete(input)\n\t\t\t}\n\t}\n\n\t#check(input: HTMLInputElement, value: boolean, mixed: boolean): void {\n\t\tconst state = this.#checks.get(input)\n\t\tif (state === undefined)\n\t\t\tthis.#checks.set(input, {\n\t\t\t\tchecked: input.checked,\n\t\t\t\tindeterminate: input.indeterminate,\n\t\t\t\tvalue,\n\t\t\t\tmixed,\n\t\t\t})\n\t\telse {\n\t\t\tstate.value = value\n\t\t\tstate.mixed = mixed\n\t\t}\n\t\tinput.checked = value\n\t\tinput.indeterminate = mixed\n\t}\n\n\t#controls(node: HTMLTableRowElement, key: string, detail: HTMLTableRowElement | undefined): void {\n\t\tconst table = node.closest('table')\n\t\tfor (const input of node.querySelectorAll('input[type=\"checkbox\"][data-table-select]'))\n\t\t\tif (input instanceof HTMLInputElement && input.closest('table') === table)\n\t\t\t\tthis.#check(input, this.#document.selection.keys.has(key), false)\n\t\tfor (const button of node.querySelectorAll('button[data-table-expand]'))\n\t\t\tif (button.closest('table') === table) {\n\t\t\t\tthis.#attribute(button, 'aria-expanded', String(this.#document.expansion.keys.has(key)))\n\t\t\t\tthis.#attribute(button, 'aria-controls', detail?.id ?? null)\n\t\t\t}\n\t}\n\n\t#headers(): void {\n\t\tconst orders = this.#document.sort.orders()\n\t\tfor (const button of this.#element.tHead?.querySelectorAll('button[data-table-sort]') ?? []) {\n\t\t\tif (button.closest('table') !== this.#element) continue\n\t\t\tconst header = button.closest('th')\n\t\t\tif (header === null) continue\n\t\t\tconst column = button.getAttribute('data-table-sort')\n\t\t\tconst index = orders.findIndex((order) => order.column === column)\n\t\t\tconst order = orders[index]\n\t\t\tthis.#attribute(\n\t\t\t\theader,\n\t\t\t\t'aria-sort',\n\t\t\t\tindex === 0 && order !== undefined ? order.direction : null,\n\t\t\t)\n\t\t\tthis.#attribute(\n\t\t\t\tbutton,\n\t\t\t\t'aria-description',\n\t\t\t\torder === undefined\n\t\t\t\t\t? null\n\t\t\t\t\t: `Sort priority ${index + 1} of ${orders.length}, ${order.direction}`,\n\t\t\t)\n\t\t}\n\t}\n\n\t#pages(view: readonly TableRow[]): void {\n\t\tconst selected = view.filter((row) => {\n\t\t\tconst key = extractKey(this.#document.schema, row)\n\t\t\treturn key !== undefined && this.#document.selection.keys.has(key)\n\t\t}).length\n\t\tfor (const input of this.#scope.querySelectorAll('input[type=\"checkbox\"][data-table-page]'))\n\t\t\tif (\n\t\t\t\tinput instanceof HTMLInputElement &&\n\t\t\t\t(input.closest('table') === null || input.closest('table') === this.#element)\n\t\t\t)\n\t\t\t\tthis.#check(\n\t\t\t\t\tinput,\n\t\t\t\t\tview.length > 0 && selected === view.length,\n\t\t\t\t\tselected > 0 && selected < view.length,\n\t\t\t\t)\n\t}\n\n\t#click(event: MouseEvent): void {\n\t\tif (!(event.target instanceof Element) || this.destroyed || this.#requesting) return\n\t\tconst button = event.target.closest('button')\n\t\tif (\n\t\t\t!(button instanceof HTMLButtonElement) ||\n\t\t\tbutton.disabled ||\n\t\t\tbutton.closest('table') !== this.#element\n\t\t)\n\t\t\treturn\n\t\tconst outcome = attempt(() => {\n\t\t\tif (button.hasAttribute('data-table-sort') && this.#element.tHead?.contains(button)) {\n\t\t\t\tconst column = button.getAttribute('data-table-sort')\n\t\t\t\tif (column === null || !this.#document.schema.columns.some((entry) => entry.key === column))\n\t\t\t\t\tthrow new TableBindingError('STRUCTURE', 'The sort button names no column')\n\t\t\t\tconst direction = this.#document.sort.order(column)?.direction\n\t\t\t\tconst orders =\n\t\t\t\t\tdirection === 'descending'\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcolumn,\n\t\t\t\t\t\t\t\t\tdirection:\n\t\t\t\t\t\t\t\t\t\tdirection === undefined ? ('ascending' as const) : ('descending' as const),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\tconst request = new CustomEvent('table-sort', { cancelable: true, detail: orders })\n\t\t\t\tthis.#requesting = true\n\t\t\t\tthis.#emitter.emit('sort', request)\n\t\t\t\tthis.#requesting = false\n\t\t\t\tif (request.defaultPrevented || this.destroyed) return\n\t\t\t\tthis.#document.sort.remove()\n\t\t\t\tif (!this.destroyed) this.#document.sort.set(orders)\n\t\t\t} else if (button.hasAttribute('data-table-expand')) {\n\t\t\t\tconst row = button.closest('tr')\n\t\t\t\tconst key = Array.from(this.#rows).find(([, node]) => node === row)?.[0]\n\t\t\t\tif (key !== undefined) this.#document.expansion.toggle(key)\n\t\t\t}\n\t\t})\n\t\tif (!outcome.success) this.#emitter.emit('error', outcome.error)\n\t}\n\n\t#change(event: Event): void {\n\t\tconst input = event.target\n\t\tif (\n\t\t\t!(input instanceof HTMLInputElement) ||\n\t\t\tinput.type !== 'checkbox' ||\n\t\t\tinput.disabled ||\n\t\t\tthis.destroyed\n\t\t)\n\t\t\treturn\n\t\tconst table = input.closest('table')\n\t\tif (table !== null && table !== this.#element) return\n\t\tconst outcome = attempt(() => {\n\t\t\tif (input.hasAttribute('data-table-page')) {\n\t\t\t\tconst keys = this.#keys(this.#document.view)\n\t\t\t\tif (input.checked) this.#document.selection.select(keys)\n\t\t\t\telse this.#document.selection.clear(keys)\n\t\t\t} else if (input.hasAttribute('data-table-select') && table === this.#element) {\n\t\t\t\tconst key = Array.from(this.#rows).find(([, node]) => node === input.closest('tr'))?.[0]\n\t\t\t\tif (key !== undefined) {\n\t\t\t\t\tif (input.checked) this.#document.selection.select(key)\n\t\t\t\t\telse this.#document.selection.clear(key)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\tif (!outcome.success) this.#emitter.emit('error', outcome.error)\n\t}\n\n\t#keys(rows: readonly TableRow[]): readonly string[] {\n\t\treturn rows.flatMap((row) => {\n\t\t\tconst key = extractKey(this.#document.schema, row)\n\t\t\treturn key === undefined ? [] : [key]\n\t\t})\n\t}\n}\n","import type { TableInterface } from '../core/types.js'\nimport type { TableBindingInterface, TableBindingOptions } from './types.js'\nimport { TableBinding } from './TableBinding.js'\n\n/** Creates a native table binding with one retained row owner.\n * @param element - The native table to bind.\n * @param document - The borrowed core document.\n * @param options - Renderers, scoped controls, and listeners.\n * @returns The native binding.\n */\nexport function createTableBinding(\n\telement: HTMLTableElement,\n\tdocument: TableInterface,\n\toptions?: TableBindingOptions,\n): TableBindingInterface {\n\treturn new TableBinding(element, document, options)\n}\n"],"mappings":"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"}
@@ -440,6 +440,14 @@ function serializeRows(schema, rows) {
440
440
  }
441
441
  return Object.freeze(output);
442
442
  }
443
+ /** Compares complete row values independently of their snapshot identities.
444
+ * @param left - The previous row, if present.
445
+ * @param right - The next row.
446
+ * @returns Whether both rows carry exactly the same cells.
447
+ */
448
+ function matchesTableRow(left, right) {
449
+ return left !== void 0 && Object.keys(left).length === Object.keys(right).length && Object.keys(right).every((key) => Object.hasOwn(left, key) && left[key] === right[key]);
450
+ }
443
451
  //#endregion
444
452
  //#region src/core/validators.ts
445
453
  /**
@@ -997,7 +1005,7 @@ var RowManager = class {
997
1005
  ...previous,
998
1006
  ...update
999
1007
  });
1000
- if (!this.#same(previous, merged)) {
1008
+ if (!matchesTableRow(previous, merged)) {
1001
1009
  next[location] = merged;
1002
1010
  const key = extractKey(this.#schema, merged);
1003
1011
  if (key !== void 0) moved.push(key);
@@ -1010,6 +1018,39 @@ var RowManager = class {
1010
1018
  });
1011
1019
  return true;
1012
1020
  }
1021
+ /** Replaces complete rows atomically without removing their identities. */
1022
+ replace(input) {
1023
+ this.#gate();
1024
+ const replacements = ((0, _orkestrel_contract.isArray)(input) ? input : [input]).map((row) => cloneRow(row));
1025
+ const current = this.#read();
1026
+ const locations = [];
1027
+ for (const row of replacements) {
1028
+ this.#validate(row);
1029
+ const location = current.findIndex((candidate) => extractKey(this.#schema, candidate) === extractKey(this.#schema, row));
1030
+ if (location === -1) return false;
1031
+ locations.push(location);
1032
+ }
1033
+ const next = [...current];
1034
+ const changed = /* @__PURE__ */ new Set();
1035
+ for (const [index, row] of replacements.entries()) {
1036
+ const location = locations[index];
1037
+ if (location === void 0) continue;
1038
+ next[location] = row;
1039
+ }
1040
+ for (const location of locations) {
1041
+ const previous = current[location];
1042
+ const row = next[location];
1043
+ if (previous === void 0 || row === void 0) continue;
1044
+ const key = extractKey(this.#schema, row);
1045
+ if (key !== void 0 && !matchesTableRow(previous, row)) changed.add(key);
1046
+ }
1047
+ if (changed.size === 0) return true;
1048
+ this.#write(Object.freeze(next));
1049
+ this.#settle([], () => {
1050
+ for (const key of changed) this.#emitter.emit("write", key);
1051
+ });
1052
+ return true;
1053
+ }
1013
1054
  /** Moves one row to a clamped index in table order. */
1014
1055
  move(key, index) {
1015
1056
  this.#gate();
@@ -1080,11 +1121,6 @@ var RowManager = class {
1080
1121
  if (key === void 0) throw new TableError("KEY", message);
1081
1122
  throw new TableError("KEY", message, { key });
1082
1123
  }
1083
- #same(left, right) {
1084
- const leftKeys = Object.keys(left);
1085
- const rightKeys = Object.keys(right);
1086
- return leftKeys.length === rightKeys.length && leftKeys.every((key) => Object.hasOwn(right, key) && left[key] === right[key]);
1087
- }
1088
1124
  };
1089
1125
  //#endregion
1090
1126
  //#region src/core/tables/SelectionManager.ts
@@ -1425,6 +1461,7 @@ exports.isTableRow = isTableRow;
1425
1461
  exports.isTableSchema = isTableSchema;
1426
1462
  exports.matchesCell = matchesCell;
1427
1463
  exports.matchesFilter = matchesFilter;
1464
+ exports.matchesTableRow = matchesTableRow;
1428
1465
  exports.matchesTerms = matchesTerms;
1429
1466
  exports.mergeTerms = mergeTerms;
1430
1467
  exports.parseRows = parseRows;