ng-hub-ui-spreadsheet 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +571 -0
- package/fesm2022/ng-hub-ui-spreadsheet-signals.mjs +281 -0
- package/fesm2022/ng-hub-ui-spreadsheet-signals.mjs.map +1 -0
- package/fesm2022/ng-hub-ui-spreadsheet.mjs +4598 -0
- package/fesm2022/ng-hub-ui-spreadsheet.mjs.map +1 -0
- package/package.json +67 -0
- package/types/ng-hub-ui-spreadsheet-signals.d.ts +125 -0
- package/types/ng-hub-ui-spreadsheet.d.ts +1958 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-hub-ui-spreadsheet.mjs","sources":["../../../projects/spreadsheet/src/lib/models/spreadsheet-records.ts","../../../projects/spreadsheet/src/lib/exchange/delimited.ts","../../../projects/spreadsheet/src/lib/clipboard/clipboard-table.ts","../../../projects/spreadsheet/src/lib/models/spreadsheet-structure.ts","../../../projects/spreadsheet/src/lib/columns/cell-values.ts","../../../projects/spreadsheet/src/lib/components/spreadsheet/spreadsheet-editor.directive.ts","../../../projects/spreadsheet/src/lib/components/spreadsheet/spreadsheet-cell.directive.ts","../../../projects/spreadsheet/src/lib/columns/column-sizing.ts","../../../projects/spreadsheet/src/lib/fill/fill-series.ts","../../../projects/spreadsheet/src/lib/components/spreadsheet/frozen-panes.ts","../../../projects/spreadsheet/src/lib/components/spreadsheet/reveal-picker.ts","../../../projects/spreadsheet/src/lib/formulas/formula-evaluator.ts","../../../projects/spreadsheet/src/lib/formulas/formula-coordinates.ts","../../../projects/spreadsheet/src/lib/formulas/formula-parser.ts","../../../projects/spreadsheet/src/lib/formulas/formula-sheet.ts","../../../projects/spreadsheet/src/lib/formulas/formula-errors.ts","../../../projects/spreadsheet/src/lib/formulas/formula-suggest.ts","../../../projects/spreadsheet/src/lib/editors/editor-adapter.token.ts","../../../projects/spreadsheet/src/lib/editors/editor-adapter.directive.ts","../../../projects/spreadsheet/src/lib/models/spreadsheet-spans.ts","../../../projects/spreadsheet/src/lib/components/spreadsheet/spreadsheet.component.ts","../../../projects/spreadsheet/src/lib/components/spreadsheet/spreadsheet.component.html","../../../projects/spreadsheet/src/lib/exchange/download.ts","../../../projects/spreadsheet/src/lib/exchange/sheet-values.ts","../../../projects/spreadsheet/src/lib/exchange/table-records.ts","../../../projects/spreadsheet/src/lib/exchange/csv.ts","../../../projects/spreadsheet/src/lib/exchange/zip.ts","../../../projects/spreadsheet/src/lib/exchange/xlsx.ts","../../../projects/spreadsheet/src/lib/exchange/unzip.ts","../../../projects/spreadsheet/src/lib/exchange/xlsx-read.ts","../../../projects/spreadsheet/src/lib/editors/editor-adapter.provider.ts","../../../projects/spreadsheet/src/lib/assets/i18n/en.ts","../../../projects/spreadsheet/src/lib/assets/i18n/es.ts","../../../projects/spreadsheet/src/lib/assets/i18n/fr.ts","../../../projects/spreadsheet/src/lib/assets/i18n/de.ts","../../../projects/spreadsheet/src/lib/assets/i18n/ru.ts","../../../projects/spreadsheet/src/lib/assets/i18n/ja.ts","../../../projects/spreadsheet/src/lib/assets/i18n/zh.ts","../../../projects/spreadsheet/src/lib/assets/i18n/ar.ts","../../../projects/spreadsheet/src/ng-hub-ui-spreadsheet.ts"],"sourcesContent":["import { HubSpreadsheetColumn, HubSpreadsheetRecord } from './spreadsheet.types';\n\n/**\n * Reading a sheet back as plain data, keyed by column alias.\n *\n * The point of the aliases: the owner works with `{ price: 12, units: 3 }` instead of mapping a\n * grid of coordinates back onto its own fields by position, which breaks the moment a column\n * moves.\n *\n * These read the value a column reports, never the text it decides to display, so a cell showing\n * «120 ud.» still yields the number 120.\n */\n\n/** One row as plain data. */\nexport function spreadsheetRecord<TRow>(row: TRow, columns: readonly HubSpreadsheetColumn<TRow>[]): HubSpreadsheetRecord {\n\tconst record: HubSpreadsheetRecord = {};\n\n\tfor (const column of columns) {\n\t\trecord[column.key] = column.cell(row).value;\n\t}\n\n\treturn record;\n}\n\n/** Every row as plain data, in the order the sheet holds them. */\nexport function spreadsheetRecords<TRow>(\n\trows: readonly TRow[],\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[]\n): HubSpreadsheetRecord[] {\n\treturn rows.map((row) => spreadsheetRecord(row, columns));\n}\n\n/**\n * The aliases declared more than once, each named a single time.\n *\n * A repeated alias is not a cosmetic problem: the later column silently overwrites the earlier\n * one in every structured read, and once formulas arrive the reference becomes ambiguous. The\n * sheet reports this rather than guessing which column was meant.\n */\nexport function duplicateColumnKeys<TRow>(columns: readonly HubSpreadsheetColumn<TRow>[]): string[] {\n\tconst seen = new Set<string>();\n\tconst repeated = new Set<string>();\n\n\tfor (const column of columns) {\n\t\tif (seen.has(column.key)) {\n\t\t\trepeated.add(column.key);\n\t\t}\n\n\t\tseen.add(column.key);\n\t}\n\n\treturn [...repeated];\n}\n","/**\n * Delimited text, read and written.\n *\n * The clipboard speaks it with tabs and a CSV file with commas — or with semicolons, wherever the\n * comma is already busy being a decimal mark. Everything else about them is the same, so they\n * share this.\n */\n\n/**\n * Reads a table out of delimited text.\n *\n * One state machine for the clipboard and for CSV, because they are the same format with a\n * different separator and the awkward parts are identical: a quoted cell holding the separator, a\n * doubled quote standing for one, a line ending that may be one character or two, and a stray\n * quote in the middle of a cell that is content rather than punctuation — `12\" de pantalla`.\n *\n * @param input - The text to read.\n * @param delimiter - What separates the cells of a row.\n * @returns The rows, each as a list of cells, exactly as they were written.\n */\nexport function parseDelimited(input: string, delimiter = '\\t'): string[][] {\n\tif (input === '') {\n\t\treturn [];\n\t}\n\n\tconst rows: string[][] = [];\n\tlet row: string[] = [];\n\tlet cell = '';\n\tlet quoted = false;\n\tlet atCellStart = true;\n\n\tfor (let index = 0; index < input.length; index++) {\n\t\tconst char = input[index];\n\n\t\tif (quoted) {\n\t\t\tif (char === '\"') {\n\t\t\t\tif (input[index + 1] === '\"') {\n\t\t\t\t\tcell += '\"';\n\t\t\t\t\tindex++;\n\t\t\t\t} else {\n\t\t\t\t\tquoted = false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcell += char;\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '\"' && atCellStart) {\n\t\t\tquoted = true;\n\t\t\tatCellStart = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tatCellStart = false;\n\n\t\tif (char === delimiter) {\n\t\t\trow.push(cell);\n\t\t\tcell = '';\n\t\t\tatCellStart = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '\\n' || char === '\\r') {\n\t\t\t// Swallow the LF of a CRLF so a Windows paste does not gain a blank row per line.\n\t\t\tif (char === '\\r' && input[index + 1] === '\\n') {\n\t\t\t\tindex++;\n\t\t\t}\n\n\t\t\trow.push(cell);\n\t\t\trows.push(row);\n\t\t\trow = [];\n\t\t\tcell = '';\n\t\t\tatCellStart = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tcell += char;\n\t}\n\n\t// A trailing newline closed the last row already; anything left is a real final row.\n\tif (cell !== '' || row.length) {\n\t\trow.push(cell);\n\t\trows.push(row);\n\t}\n\n\treturn rows;\n}\n\n/**\n * Writes a table as delimited text.\n *\n * A cell is quoted only when it has to be: one that holds the separator, a quote, or a line\n * ending. Quoting everything is also correct and is what many exporters do, but it makes a file\n * that is unpleasant to read and twice the size for nothing.\n *\n * @param rows - The rows to write.\n * @param delimiter - What to put between the cells.\n * @param newline - What ends a line. CRLF is what a spreadsheet on Windows expects.\n */\nexport function serialiseDelimited(\n\trows: readonly (readonly string[])[],\n\tdelimiter = '\\t',\n\tnewline: '\\n' | '\\r\\n' = '\\n'\n): string {\n\tconst needsQuotes = (cell: string) => cell.includes(delimiter) || cell.includes('\"') || /[\\r\\n]/.test(cell);\n\n\treturn rows\n\t\t.map((row) => row.map((cell) => (needsQuotes(cell) ? `\"${cell.replace(/\"/g, '\"\"')}\"` : cell)).join(delimiter))\n\t\t.join(newline);\n}\n","import { HubSpreadsheetValue } from '../models/spreadsheet.types';\nimport { parseDelimited } from '../exchange/delimited';\n\n/**\n * Reading and writing the clipboard the way spreadsheets actually use it.\n *\n * Two flavours travel together. `text/plain` is tab-separated and carries what the source\n * *displayed*, formatted in the source's own locale — so a figure copied from Excel in Spain\n * arrives as `1.234,56 €`. `text/html` is where the raw number travels, in an attribute, and is\n * the only place a value can be read back without guessing which convention wrote it.\n *\n * Reading only the plain text is the bug this module exists to avoid.\n */\n\n/** A cell as it came off the clipboard. */\nexport interface HubClipboardCell {\n\t/** What the source displayed. */\n\treadonly text: string;\n\t/** The underlying number, when the source declared one. */\n\treadonly raw?: number;\n}\n\n/** The two flavours a paste may carry. */\nexport interface HubClipboardPayload {\n\treadonly text?: string;\n\treadonly html?: string;\n}\n\n/** Both flavours of a copy, ready to be put on the clipboard. */\nexport interface HubClipboardWrite {\n\treadonly text: string;\n\treadonly html: string;\n}\n\n/**\n * Reads a number out of text written in the reader's convention.\n *\n * Deliberately three-valued: a number, `null` for an empty cell — which is an absence and not a\n * zero — and `undefined` for text that is not a number at all, so a caller can refuse a paste\n * instead of silently writing NaN.\n *\n * @param text The text as typed or as pasted.\n * @param decimalMark Which character separates the decimals for this reader.\n */\nexport function parseDecimal(text: string, decimalMark: ',' | '.'): number | null | undefined {\n\t// Excel pads figures with non-breaking spaces, which trim() does not touch.\n\tconst trimmed = text.replace(/[\\s ]/g, '');\n\n\tif (trimmed === '') {\n\t\treturn null;\n\t}\n\n\tconst thousands = decimalMark === ',' ? '.' : ',';\n\tconst bare = trimmed.split(thousands).join('').replace(/%$/, '').replace(decimalMark, '.');\n\n\tif (!/^[+-]?(\\d+\\.?\\d*|\\.\\d+)$/.test(bare)) {\n\t\treturn undefined;\n\t}\n\n\tconst value = Number(bare);\n\n\treturn Number.isFinite(value) ? value : undefined;\n}\n\n/**\n * Parses a pasted block into a table of cells.\n *\n * The plain text decides the shape, because it is the only flavour guaranteed to be there and to\n * be complete. The HTML, when present and parseable, is read alongside it purely to recover raw\n * numbers.\n */\nexport function parseClipboardTable(payload: HubClipboardPayload): HubClipboardCell[][] {\n\tconst rows = parseDelimited(payload.text ?? '');\n\n\tif (!rows.length) {\n\t\treturn [];\n\t}\n\n\tconst raw = payload.html ? rawValuesFromHtml(payload.html) : [];\n\n\treturn rows.map((row, rowIndex) =>\n\t\trow.map((text, colIndex) => {\n\t\t\tconst value = raw[rowIndex]?.[colIndex];\n\n\t\t\treturn value === undefined ? { text } : { text, raw: value };\n\t\t})\n\t);\n}\n\n/**\n * Writes a block of values as both flavours.\n *\n * Numbers go into the plain text with a dot and no grouping, which every spreadsheet reads\n * whatever its reader has configured, and into the HTML as `x:num`, which is what lets another\n * instance of this component — or Excel — recover the exact value rather than re-parsing a\n * formatted string.\n */\nexport function serialiseClipboardTable(rows: readonly (readonly HubSpreadsheetValue[])[]): HubClipboardWrite {\n\tconst text = rows.map((row) => row.map(toDelimitedCell).join('\\t')).join('\\n');\n\n\tconst html = '<table>' + rows.map((row) => '<tr>' + row.map(toHtmlCell).join('') + '</tr>').join('') + '</table>';\n\n\treturn { text, html };\n}\n\n/** One cell as tab-separated text, quoted only when it would otherwise break the shape. */\nfunction toDelimitedCell(value: HubSpreadsheetValue): string {\n\tif (value === null) {\n\t\treturn '';\n\t}\n\n\tif (typeof value === 'number') {\n\t\treturn String(value);\n\t}\n\n\treturn /[\\t\\n\\r\"]/.test(value) ? `\"${value.split('\"').join('\"\"')}\"` : value;\n}\n\n/** One cell as HTML, with the raw number attached when there is one. */\nfunction toHtmlCell(value: HubSpreadsheetValue): string {\n\tif (value === null) {\n\t\treturn '<td></td>';\n\t}\n\n\tif (typeof value === 'number') {\n\t\treturn `<td x:num=\"${value}\">${value}</td>`;\n\t}\n\n\treturn `<td>${escapeHtml(value)}</td>`;\n}\n\nfunction escapeHtml(value: string): string {\n\treturn value.split('&').join('&').split('<').join('<').split('>').join('>');\n}\n\n/**\n * Splits tab-separated text into rows and cells, honouring quoting.\n *\n * A hand-rolled state machine rather than a pair of splits, because a cell may legitimately hold\n * a tab or a newline when it is quoted, and splitting first destroys exactly that data. A stray\n * quote in the middle of a cell — `12\" de pantalla` — is content, not a delimiter, so quoting\n * only counts at the start of a cell.\n */\n\n/**\n * Pulls the raw numbers out of the HTML flavour, laid out to match the table.\n *\n * Parsed with `DOMParser` and read through `textContent` and attributes. The clipboard is\n * attacker-controlled input, so nothing here is ever assigned to `innerHTML`: pasting a crafted\n * cell into a page is a direct route to running somebody else's script.\n */\nfunction rawValuesFromHtml(html: string): (number | undefined)[][] {\n\tif (typeof DOMParser === 'undefined') {\n\t\treturn [];\n\t}\n\n\t// Office prefixes the fragment with a byte-offset header that is not markup.\n\tconst markup = html.slice(Math.max(0, html.indexOf('<')));\n\tconst table = new DOMParser().parseFromString(markup, 'text/html').querySelector('table');\n\n\tif (!table) {\n\t\treturn [];\n\t}\n\n\treturn [...table.querySelectorAll('tr')].map((tr) => [...tr.querySelectorAll('td, th')].map((cell) => rawValueOf(cell)));\n}\n\n/** The declared number of one cell, from whichever dialect the source speaks. */\nfunction rawValueOf(cell: Element): number | undefined {\n\tconst excel = cell.getAttribute('x:num');\n\n\tif (excel !== null && excel !== '') {\n\t\tconst value = Number(excel);\n\n\t\treturn Number.isFinite(value) ? value : undefined;\n\t}\n\n\tconst sheets = cell.getAttribute('data-sheets-value');\n\n\tif (sheets) {\n\t\ttry {\n\t\t\t// Google encodes the type in key \"1\" and the number in key \"3\"; 3 means number.\n\t\t\tconst parsed = JSON.parse(sheets) as Record<string, unknown>;\n\n\t\t\tif (parsed['1'] === 3 && typeof parsed['3'] === 'number') {\n\t\t\t\treturn parsed['3'];\n\t\t\t}\n\t\t} catch {\n\t\t\t// A dialect this does not know. The displayed text still carries the cell.\n\t\t}\n\t}\n\n\treturn undefined;\n}\n","import { HubSpreadsheetColumn } from './spreadsheet.types';\n\n/**\n * Adding and removing rows and columns while the sheet is running.\n *\n * The sheet never mutates anything itself. It reports what the reader asked for and the owner\n * decides, because only the owner knows whether a line may be deleted, what a new row should\n * start with, or whether any of it should reach a server. What the sheet does offer is the two\n * pieces that are easy to get wrong: allocating an alias for a new column, and finding out what\n * a deletion would leave pointing at nothing.\n */\n\n/** Which axis a structural change acts on. */\nexport type HubSpreadsheetAxis = 'row' | 'column';\n\n/** Where a new row or column goes, relative to the one the reader pointed at. */\nexport type HubSpreadsheetInsertSide = 'before' | 'after';\n\n/**\n * Whether a structural change is offered at all.\n *\n * A plain boolean covers the usual case. A predicate covers the rest: a tariff sheet that lets\n * you add lines but never delete the first one, a column set where only the ones the reader\n * created may be removed.\n */\nexport type HubSpreadsheetPermission<TSubject> = boolean | ((subject: TSubject, index: number) => boolean);\n\n/** The reader asked to insert. */\nexport interface HubSpreadsheetInsertRequest {\n\treadonly axis: HubSpreadsheetAxis;\n\t/** Where the new one lands, already resolved to an index. */\n\treadonly at: number;\n\t/** How many to insert. */\n\treadonly count: number;\n\t/** For a column, an alias that is free and has never been used in this sheet. */\n\treadonly key?: string;\n}\n\n/** The reader asked to delete. */\nexport interface HubSpreadsheetDeleteRequest {\n\treadonly axis: HubSpreadsheetAxis;\n\t/** The first index to remove. */\n\treadonly at: number;\n\t/** How many to remove. */\n\treadonly count: number;\n\t/**\n\t * For a column, the aliases about to disappear.\n\t *\n\t * Handed over so the owner can check what still points at them before agreeing — see\n\t * {@link danglingColumnKeys}.\n\t */\n\treadonly keys?: readonly string[];\n}\n\n/** How a sheet is allowed to change shape. Everything is refused unless turned on. */\nexport interface HubSpreadsheetStructureOptions<TRow> {\n\treadonly insertRows?: HubSpreadsheetPermission<TRow | null>;\n\treadonly deleteRows?: HubSpreadsheetPermission<TRow>;\n\treadonly insertColumns?: HubSpreadsheetPermission<HubSpreadsheetColumn<TRow> | null>;\n\treadonly deleteColumns?: HubSpreadsheetPermission<HubSpreadsheetColumn<TRow>>;\n}\n\n/** Matches an alias this module allocated, capturing its number. */\nconst GENERATED = /^(.+)-(\\d+)$/;\n\n/**\n * Whether a permission lets this particular subject through.\n *\n * Silence means no. A sheet that gains the ability to delete rows because an option was left out\n * is a worse failure than one that refuses until told otherwise.\n *\n * A predicate that throws is treated as a refusal: the owner's guard is broken, and acting on a\n * broken guard is how data gets deleted that should not have been.\n */\nexport function isStructureAllowed<TSubject>(\n\tpermission: HubSpreadsheetPermission<TSubject> | undefined,\n\tsubject: TSubject,\n\tindex: number\n): boolean {\n\tif (permission === undefined) {\n\t\treturn false;\n\t}\n\n\tif (typeof permission === 'boolean') {\n\t\treturn permission;\n\t}\n\n\ttry {\n\t\treturn permission(subject, index);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Where an insertion actually lands.\n *\n * @param reference The row or column the reader pointed at.\n * @param side Whether the new one goes before it or after it.\n * @param length How many there are now.\n * @returns An index between 0 and `length`, inclusive, since appending at the end is legal.\n */\nexport function resolveInsertIndex(reference: number, side: HubSpreadsheetInsertSide, length: number): number {\n\tconst clamped = Math.max(0, Math.min(length, Math.trunc(reference)));\n\tconst index = side === 'after' ? clamped + 1 : clamped;\n\n\treturn Math.max(0, Math.min(length, index));\n}\n\n/**\n * An alias for a new column that has never belonged to another one.\n *\n * Pass every alias the sheet has ever handed out, the live ones and the retired ones together.\n * That is the whole point: an alias is an identity, so reusing a deleted column's name makes\n * everything that referenced the old column silently resolve to the new one, and the mistake\n * surfaces much later as wrong numbers rather than as an error.\n *\n * The same rule the project already applies to task codes, for the same reason.\n *\n * @param taken Every alias ever used, whether the column still exists or not.\n * @param prefix The family to number within; `col` when not given.\n */\nexport function nextColumnKey(taken: Iterable<string>, prefix = 'col'): string {\n\tlet highest = 0;\n\n\tfor (const key of taken) {\n\t\tconst match = GENERATED.exec(key);\n\n\t\tif (match && match[1] === prefix) {\n\t\t\thighest = Math.max(highest, Number(match[2]));\n\t\t}\n\t}\n\n\treturn `${prefix}-${highest + 1}`;\n}\n\n/**\n * The references that no longer resolve to a column.\n *\n * Give it whatever points at columns — the keys of a saved-state map, the aliases a formula\n * mentions — and it reports which of them have nothing behind them any more. Each one named\n * once, in the order first seen, so a message to the reader lists them the way they were found.\n */\nexport function danglingColumnKeys<TRow>(\n\treferenced: Iterable<string>,\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[]\n): string[] {\n\tconst live = new Set(columns.map((column) => column.key));\n\tconst broken: string[] = [];\n\tconst seen = new Set<string>();\n\n\tfor (const key of referenced) {\n\t\tif (!live.has(key) && !seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tbroken.push(key);\n\t\t}\n\t}\n\n\treturn broken;\n}\n","import { parseDecimal } from '../clipboard/clipboard-table';\nimport { HubSpreadsheetColumn, HubSpreadsheetOption, HubSpreadsheetValue } from '../models/spreadsheet.types';\n\n/**\n * Turning a stored value into what a cell shows, and turning what was typed back into a value.\n *\n * One place for both directions, because they have to agree: a cell that shows `On hold` must\n * accept `On hold` back, or pasting a column onto itself loses data.\n */\n\n/** Written forms of yes and no, in the languages the library ships labels for. */\nconst AFFIRMATIVE = new Set(['1', 'true', 'yes', 'y', 'sí', 'si', 'oui', 'ja', 'да', 'はい', '是', 'نعم']);\nconst NEGATIVE = new Set(['0', 'false', 'no', 'n', 'non', 'nein', 'нет', 'いいえ', '否', 'لا']);\n\n/** The option a stored value belongs to, or undefined when it belongs to none of them. */\nexport function optionFor<TRow>(\n\tvalue: HubSpreadsheetValue,\n\tcolumn: HubSpreadsheetColumn<TRow>\n): HubSpreadsheetOption | undefined {\n\treturn column.options?.find((option) => option.value === value);\n}\n\n/**\n * What the cell shows for a value.\n *\n * A `select` value whose option has been removed is shown as the stored value rather than as\n * nothing: blanking it would read as data loss, and the reader would have no way to tell what the\n * row used to say.\n */\nexport function displayValue<TRow>(value: HubSpreadsheetValue, column: HubSpreadsheetColumn<TRow>): string {\n\tif (value === null || value === '') {\n\t\treturn '';\n\t}\n\n\tswitch (column.kind) {\n\t\tcase 'select':\n\t\t\treturn optionFor(value, column)?.label ?? String(value);\n\t\tcase 'boolean':\n\t\t\t// A mark rather than the word: a column of them reads as a column, and it takes no\n\t\t\t// width worth arguing about.\n\t\t\treturn isTruthy(value) ? '✓' : '';\n\t\tdefault:\n\t\t\treturn String(value);\n\t}\n}\n\n/**\n * What a typed or pasted string is worth in a column.\n *\n * Three answers, as everywhere else here: the value, `null` for an empty cell, and `undefined`\n * for something this column cannot hold — which lets the caller refuse rather than store rubbish.\n */\nexport function parseForColumn<TRow>(\n\ttext: string,\n\tcolumn: HubSpreadsheetColumn<TRow>,\n\tdecimalMark: ',' | '.'\n): HubSpreadsheetValue | undefined {\n\tconst trimmed = text.trim();\n\n\tswitch (column.kind) {\n\t\tcase 'number':\n\t\tcase 'currency':\n\t\t\treturn parseDecimal(text, decimalMark);\n\n\t\tcase 'select': {\n\t\t\tif (trimmed === '') {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// The stored value first, then the label — a paste from a spreadsheet carries what was\n\t\t\t// displayed, and a column pasted onto itself has to survive the round trip.\n\t\t\tconst byValue = column.options?.find((option) => String(option.value) === trimmed);\n\t\t\tconst byLabel = column.options?.find((option) => option.label === trimmed);\n\t\t\tconst match = byValue ?? byLabel;\n\n\t\t\t// Nothing on the list means nothing this column may hold. Refusing is the whole point\n\t\t\t// of declaring a closed list in the first place.\n\t\t\treturn match ? match.value : undefined;\n\t\t}\n\n\t\tcase 'boolean': {\n\t\t\tif (trimmed === '') {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst lowered = trimmed.toLowerCase();\n\n\t\t\tif (AFFIRMATIVE.has(lowered)) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif (NEGATIVE.has(lowered)) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t}\n\n\t\tcase 'date':\n\t\t\t// Kept as the text it was written in. Turning it into a Date and back is what shifts a\n\t\t\t// date by a day for anyone east or west of whoever wrote the code.\n\t\t\treturn trimmed === '' ? null : trimmed;\n\n\t\tdefault:\n\t\t\treturn trimmed === '' ? null : text;\n\t}\n}\n\n/** Whether a stored value counts as yes. */\nexport function isTruthy(value: HubSpreadsheetValue): boolean {\n\tif (typeof value === 'number') {\n\t\treturn value !== 0;\n\t}\n\n\treturn typeof value === 'string' && AFFIRMATIVE.has(value.toLowerCase());\n}\n","import { Directive, TemplateRef, inject, input } from '@angular/core';\nimport { HubSpreadsheetCell, HubSpreadsheetColumn, HubSpreadsheetValue } from '../../models/spreadsheet.types';\n\n/** What an editor template is handed when it opens. */\nexport interface HubSpreadsheetEditorContext<TRow> {\n\t/** The value the cell holds, ready to be edited. */\n\treadonly $implicit: HubSpreadsheetValue;\n\t/** The cell as its column reported it. */\n\treadonly cell: HubSpreadsheetCell;\n\t/**\n\t * The character that opened the cell, when it was opened by typing into it.\n\t *\n\t * That keystroke is the reader's first, and an editor that ignores it makes them type it\n\t * again. A picker should put it in its search box; a field, in its value.\n\t */\n\treadonly seed: string | undefined;\n\t/** The row it belongs to. */\n\treadonly row: TRow;\n\t/** The column it belongs to. */\n\treadonly column: HubSpreadsheetColumn<TRow>;\n\t/** Accepts a new value and closes the editor, moving the cursor down as Enter would. */\n\treadonly commit: (value: HubSpreadsheetValue) => void;\n\t/** Closes the editor and keeps what the cell held. */\n\treadonly cancel: () => void;\n}\n\n/**\n * Replaces the editor of one column with a template of your own.\n *\n * The sheet ships editors for the kinds it knows — a field for text and figures, a list for a\n * column with options, a date field, a checkbox — and this is how a column gets something else:\n * a `hub-select` with a search box, a picker of your own, anything that can report a value.\n *\n * ```html\n * <hub-spreadsheet [rows]=\"rows()\" [columns]=\"columns\" [rowKey]=\"rowKey\">\n * <ng-template hubSpreadsheetEditor=\"supplier\" let-value let-ctx=\"commit\">\n * <hub-select [options]=\"suppliers()\" [ngModel]=\"value\" (ngModelChange)=\"ctx($event)\" />\n * </ng-template>\n * </hub-spreadsheet>\n * ```\n *\n * The template is responsible for calling `commit` or `cancel`. Until it does, the editor stays\n * open — which is what lets a picker take as many clicks as it needs without the sheet deciding\n * the reader has finished.\n */\n@Directive({\n\tselector: '[hubSpreadsheetEditor]',\n\tstandalone: true\n})\nexport class HubSpreadsheetEditorDirective<TRow = unknown> {\n\t/** The alias of the column this editor belongs to. */\n\treadonly column = input.required<string>({ alias: 'hubSpreadsheetEditor' });\n\n\t/**\n\t * The same rows the sheet is given, only so the compiler knows what a row is here.\n\t *\n\t * Nothing reads it. A template is compiled on its own, with no way of knowing which sheet will\n\t * mount it, so `let-row` arrives as `unknown` and every use of it needs a cast. Handing the\n\t * rows over is how Angular's own structural directives solve this, and it costs one binding.\n\t */\n\treadonly rows = input<readonly TRow[]>([], { alias: 'hubSpreadsheetEditorRows' });\n\n\treadonly template = inject<TemplateRef<HubSpreadsheetEditorContext<TRow>>>(TemplateRef);\n\n\t/** Lets Angular narrow `let-` bindings inside the template to the real context type. */\n\tstatic ngTemplateContextGuard<TRow>(\n\t\t_directive: HubSpreadsheetEditorDirective<TRow>,\n\t\t_context: unknown\n\t): _context is HubSpreadsheetEditorContext<TRow> {\n\t\treturn true;\n\t}\n}\n","import { Directive, TemplateRef, inject, input } from '@angular/core';\nimport { HubSpreadsheetCell, HubSpreadsheetColumn, HubSpreadsheetValue } from '../../models/spreadsheet.types';\n\n/** What a cell template is handed while the cell is sitting still. */\nexport interface HubSpreadsheetCellContext<TRow> {\n\t/** What the cell holds. */\n\treadonly $implicit: HubSpreadsheetValue;\n\t/** The cell as its column reported it. */\n\treadonly cell: HubSpreadsheetCell;\n\t/** The row it belongs to. */\n\treadonly row: TRow;\n\t/** The column it belongs to. */\n\treadonly column: HubSpreadsheetColumn<TRow>;\n\t/** Whether this is the cell the reader is on. */\n\treadonly active: boolean;\n}\n\n/**\n * Draws one column's cells yourself: a badge for a state, an avatar beside a name, a row of\n * actions.\n *\n * The sibling of `hubSpreadsheetEditor`, for the other half of a cell's life. That one replaces\n * what appears when the cell is opened; this one replaces what the cell shows while it is not.\n *\n * ```html\n * <hub-spreadsheet [rows]=\"rows()\" [columns]=\"columns\" [rowKey]=\"rowKey\">\n * <ng-template hubSpreadsheetCell=\"status\" let-value>\n * <hub-badge [variant]=\"value === 'done' ? 'success' : 'warning'\">{{ value }}</hub-badge>\n * </ng-template>\n * </hub-spreadsheet>\n * ```\n *\n * Two things stay the sheet's whatever the template draws. The clipboard carries the cell's value,\n * not its decoration, so a copy round-trips as data rather than as a picture of it. And the cell\n * is still the thing the keyboard is on: the template is drawn inside it, not instead of it.\n *\n * A template with something clickable in it joins the tab order of the page, which the grid's own\n * roving tab stop does not manage — put the action behind `hubSpreadsheetEditor` instead when the\n * cell should be entered before it can be used.\n */\n@Directive({\n\tselector: '[hubSpreadsheetCell]',\n\tstandalone: true\n})\nexport class HubSpreadsheetCellDirective<TRow = unknown> {\n\t/** The alias of the column these cells belong to. */\n\treadonly column = input.required<string>({ alias: 'hubSpreadsheetCell' });\n\n\t/**\n\t * The same rows the sheet is given, only so the compiler knows what a row is here.\n\t *\n\t * Nothing reads it. A template is compiled on its own, with no way of knowing which sheet will\n\t * mount it, so `let-row` arrives as `unknown` and every use of it needs a cast. Handing the\n\t * rows over is how Angular's own structural directives solve this, and it costs one binding:\n\t *\n\t * ```html\n\t * <ng-template hubSpreadsheetCell=\"actions\" [hubSpreadsheetCellRows]=\"orders()\" let-row=\"row\">\n\t * ```\n\t */\n\treadonly rows = input<readonly TRow[]>([], { alias: 'hubSpreadsheetCellRows' });\n\n\treadonly template = inject<TemplateRef<HubSpreadsheetCellContext<TRow>>>(TemplateRef);\n\n\t/** Lets Angular narrow `let-` bindings inside the template to the real context type. */\n\tstatic ngTemplateContextGuard<TRow>(\n\t\t_directive: HubSpreadsheetCellDirective<TRow>,\n\t\t_context: unknown\n\t): _context is HubSpreadsheetCellContext<TRow> {\n\t\treturn true;\n\t}\n}\n","/**\n * Resizing and reordering columns, as arithmetic on their own.\n *\n * Kept apart from the component so the fiddly parts — a floor that a drag cannot go under, an\n * index that shifts as a column leaves its old place — are settled by tests rather than by\n * pulling at a header and hoping.\n */\n\n/**\n * The width a drag arrives at, or null when there is no honest answer.\n *\n * Null rather than a guess: if the starting width could not be measured — missing, or zero\n * because nothing had been laid out yet — any number this returns\n * is invented, and an invented width either collapses the column to its floor or makes it jump.\n * Saying so lets the caller leave the column exactly as it is, which is what the reader expects\n * from a drag that could not be interpreted.\n *\n * @param start The width the column had when the drag began.\n * @param delta How far the pointer has travelled since.\n * @param min The narrowest the column may become.\n * @returns A whole number of pixels never below `min`, or null when the drag cannot be read.\n */\nexport function resolveColumnWidth(start: number, delta: number, min: number): number | null {\n\t// Zero counts as unmeasurable, not as a width: no column is nought pixels wide, so a zero\n\t// means the element had not been laid out when the drag began. Accepting it would make the\n\t// column jump to wherever the pointer happened to be.\n\tif (!Number.isFinite(start) || start <= 0) {\n\t\treturn null;\n\t}\n\n\tconst travelled = Number.isFinite(delta) ? delta : 0;\n\n\t// Whole pixels: half a pixel of column leaves a hairline of the one behind showing through.\n\treturn Math.max(min, Math.round(start + travelled));\n}\n\n/**\n * A list with one item moved to another position.\n *\n * `to` is read against the list as it stands before the move, which is what a reader means when\n * they drop a column \"here\". Taking the item out first would shift every later index by one and\n * make a rightward move land one place short — the off-by-one every reorder implementation meets\n * exactly once.\n *\n * @returns A new array; the one passed in is left alone.\n */\nexport function moveColumn<T>(items: readonly T[], from: number, to: number): T[] {\n\tconst next = [...items];\n\n\tif (from < 0 || from >= next.length) {\n\t\treturn next;\n\t}\n\n\tconst target = Math.max(0, Math.min(next.length - 1, to));\n\n\tif (target === from) {\n\t\treturn next;\n\t}\n\n\tconst [moved] = next.splice(from, 1);\n\n\tnext.splice(target, 0, moved);\n\n\treturn next;\n}\n","import { HubSpreadsheetValue } from '../models/spreadsheet.types';\n\n/**\n * Working out what dragging a fill handle should produce.\n *\n * Two rules, in this order. If the source looks like a run — numbers with an even gap, or text\n * ending in a number — it is continued. Otherwise it is repeated. Guessing more than that is how\n * a fill handle becomes something people switch off: a pattern the reader did not intend is\n * worse than a plain repeat they can see coming.\n */\n\n/** What a source run turned out to be. */\nexport type HubFillSeries =\n\t| { kind: 'number'; start: number; step: number }\n\t| { kind: 'text-number'; prefix: string; suffix: string; start: number; step: number; pad: number }\n\t| { kind: 'repeat'; values: readonly HubSpreadsheetValue[] };\n\n/** Text ending in digits: `INV-007`, `Week 3`. The trailing digits are what gets counted. */\nconst TRAILING_NUMBER = /^(.*?)(\\d+)(\\D*)$/;\n\n/**\n * Reads a source run and says how to continue it.\n *\n * A single value still counts as a run: dragging one number down produces 1, 2, 3, which is what\n * every spreadsheet does and what people expect.\n */\nexport function detectSeries(values: readonly HubSpreadsheetValue[]): HubFillSeries {\n\tconst repeat: HubFillSeries = { kind: 'repeat', values };\n\n\tif (!values.length || values.some((value) => value === null || value === '')) {\n\t\treturn repeat;\n\t}\n\n\tif (values.every((value) => typeof value === 'number')) {\n\t\tconst numbers = values as readonly number[];\n\t\tconst step = numbers.length === 1 ? 1 : numbers[1] - numbers[0];\n\n\t\t// Every gap has to match, or it is not a run the reader meant.\n\t\tfor (let index = 2; index < numbers.length; index++) {\n\t\t\tif (round(numbers[index] - numbers[index - 1]) !== round(step)) {\n\t\t\t\treturn repeat;\n\t\t\t}\n\t\t}\n\n\t\treturn { kind: 'number', start: numbers[numbers.length - 1], step: round(step) };\n\t}\n\n\tif (values.every((value) => typeof value === 'string')) {\n\t\treturn textSeries(values as readonly string[]) ?? repeat;\n\t}\n\n\treturn repeat;\n}\n\n/**\n * The values a drag of `count` cells should write.\n *\n * @param source What the reader had selected when they took the handle.\n * @param count How many cells the drag covers.\n */\nexport function fillValues(source: readonly HubSpreadsheetValue[], count: number): HubSpreadsheetValue[] {\n\tif (count <= 0) {\n\t\treturn [];\n\t}\n\n\tif (!source.length) {\n\t\treturn Array.from({ length: count }, () => null);\n\t}\n\n\tconst series = detectSeries(source);\n\tconst out: HubSpreadsheetValue[] = [];\n\n\tfor (let index = 0; index < count; index++) {\n\t\tswitch (series.kind) {\n\t\t\tcase 'number':\n\t\t\t\tout.push(round(series.start + series.step * (index + 1)));\n\t\t\t\tbreak;\n\t\t\tcase 'text-number': {\n\t\t\t\tconst next = series.start + series.step * (index + 1);\n\n\t\t\t\tout.push(`${series.prefix}${String(Math.abs(next)).padStart(series.pad, '0')}${series.suffix}`);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'repeat':\n\t\t\t\tout.push(series.values[index % series.values.length] ?? null);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn out;\n}\n\n/** A run of text ending in numbers, or null when the pieces do not line up. */\nfunction textSeries(values: readonly string[]): HubFillSeries | null {\n\tconst parts = values.map((value) => TRAILING_NUMBER.exec(value));\n\n\tif (parts.some((part) => !part)) {\n\t\treturn null;\n\t}\n\n\tconst matches = parts as RegExpExecArray[];\n\tconst prefix = matches[0][1];\n\tconst suffix = matches[0][3];\n\n\t// Only a run that shares its wording is a run. `INV-1` and `REC-2` are two names, not a series.\n\tif (matches.some((match) => match[1] !== prefix || match[3] !== suffix)) {\n\t\treturn null;\n\t}\n\n\tconst numbers = matches.map((match) => Number(match[2]));\n\tconst step = numbers.length === 1 ? 1 : numbers[1] - numbers[0];\n\n\tfor (let index = 2; index < numbers.length; index++) {\n\t\tif (numbers[index] - numbers[index - 1] !== step) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn {\n\t\tkind: 'text-number',\n\t\tprefix,\n\t\tsuffix,\n\t\tstart: numbers[numbers.length - 1],\n\t\tstep,\n\t\t// The written width is kept, so a run of INV-008 does not become INV-10.\n\t\tpad: matches[0][2].length\n\t};\n}\n\n/**\n * Rounds away the drift of adding decimals repeatedly.\n *\n * `0.1 + 0.1 + 0.1` is not `0.3` in binary floating point, and a column of prices that reads\n * `0.30000000000000004` is a bug report waiting to happen.\n */\nfunction round(value: number): number {\n\treturn Number(value.toFixed(10));\n}\n","/**\n * Working out where frozen rows and columns sit.\n *\n * `position: sticky` pins an element at a distance from the edge, but it cannot work that\n * distance out for itself: the second frozen column has to sit exactly as far in as the first\n * one is wide, and CSS has no way to add up its siblings. So the widths are measured once after\n * a render and turned into offsets here.\n */\n\n/**\n * The distance from the leading edge for each of the first `count` tracks.\n *\n * @param sizes The measured width or height of every track, in order.\n * @param count How many of them are frozen.\n * @returns One offset per frozen track; the first is always zero.\n */\nexport function frozenOffsets(sizes: readonly number[], count: number): number[] {\n\tconst frozen = Math.max(0, Math.min(Math.trunc(count) || 0, sizes.length));\n\tconst offsets: number[] = [];\n\tlet running = 0;\n\n\tfor (let index = 0; index < frozen; index++) {\n\t\toffsets.push(running);\n\n\t\tconst size = sizes[index];\n\n\t\t// A track that could not be measured contributes nothing rather than turning every\n\t\t// offset after it into NaN, which would unpin the whole pane.\n\t\trunning += Number.isFinite(size) ? Math.round(size) : 0;\n\t}\n\n\treturn offsets;\n}\n\n/**\n * Whether a track is the last frozen one.\n *\n * That one carries the divider: a frozen pane needs a visible seam, or content scrolling\n * underneath it reads as content that belongs to it.\n */\nexport function isFrozenEdge(index: number, count: number): boolean {\n\treturn count > 0 && index === count - 1;\n}\n","/**\n * Opens the list of a native select, or the calendar of a date field, as its cell opens.\n *\n * Without it the reader clicks a cell, gets an editor, and has to click a second time to see what\n * the column allows — two gestures for one decision.\n *\n * `showPicker` needs the click that opened the cell still to count as a gesture, and it is recent\n * enough that some browsers do not have it. Either way a refusal leaves the editor focused and the\n * list closed, which is where it stood before, so nothing has to be undone.\n *\n * Only for a list and a date. On a text field the same method opens the browser's own autofill\n * suggestions, which is not what the cell asked for.\n *\n * @returns whether the picker was asked to open.\n */\nexport function revealPicker(element: Element | null | undefined): boolean {\n\tconst picker = element as (Element & { showPicker?: () => void }) | null | undefined;\n\n\tif (typeof picker?.showPicker !== 'function') {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tpicker.showPicker();\n\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n","import {\n\tHubFormula,\n\tHubFormulaContext,\n\tHubFormulaFailure,\n\tHubFormulaNode,\n\tHubFormulaOutcome,\n\tHubFormulaValue\n} from './formula.types';\n\n/**\n * Running a parsed formula against the sheet around it.\n *\n * The rules are a spreadsheet's rather than a programming language's, which is what a reader\n * expects: an empty cell is nought in arithmetic and an empty string in text, `TRUE` is one, and\n * dividing by nought is an error rather than infinity.\n */\n\n/** Whether what came back is a failure. */\nfunction failed(value: unknown): value is HubFormulaFailure {\n\treturn (\n\t\ttypeof value === 'object' && value !== null && 'ok' in (value as object) && (value as HubFormulaFailure).ok === false\n\t);\n}\n\n/**\n * A value as a number.\n *\n * An empty cell counts as nought, as it does in a spreadsheet — a column of figures with gaps adds\n * up rather than refusing. Text that is not a number is an error and not a silent nought: `\"abc\" *\n * 2` is a mistake worth seeing.\n */\nfunction asNumber(value: HubFormulaValue): number | HubFormulaFailure {\n\tif (value === null || value === '') {\n\t\treturn 0;\n\t}\n\n\tif (typeof value === 'number') {\n\t\treturn Number.isFinite(value) ? value : { ok: false, code: 'type' };\n\t}\n\n\tif (typeof value === 'boolean') {\n\t\treturn value ? 1 : 0;\n\t}\n\n\tconst parsed = Number(String(value).replace(',', '.'));\n\n\treturn Number.isFinite(parsed) ? parsed : { ok: false, code: 'type', at: String(value) };\n}\n\n/** A value as text, where an empty cell is an empty string rather than the word \"null\". */\nfunction asText(value: HubFormulaValue): string {\n\tif (value === null) {\n\t\treturn '';\n\t}\n\n\tif (typeof value === 'boolean') {\n\t\treturn value ? 'TRUE' : 'FALSE';\n\t}\n\n\treturn String(value);\n}\n\n/** Whether a value counts as yes. */\nfunction asBoolean(value: HubFormulaValue): boolean {\n\tif (typeof value === 'boolean') {\n\t\treturn value;\n\t}\n\n\tif (typeof value === 'number') {\n\t\treturn value !== 0;\n\t}\n\n\treturn value !== null && value !== '' && value.toUpperCase() !== 'FALSE';\n}\n\n/** Every number in a list of values and lists, with the empties left out. */\nfunction numbersOf(values: readonly (HubFormulaValue | readonly HubFormulaValue[])[]): number[] | HubFormulaFailure {\n\tconst numbers: number[] = [];\n\n\tfor (const value of values) {\n\t\tif (Array.isArray(value)) {\n\t\t\tconst nested = numbersOf(value);\n\n\t\t\tif (failed(nested)) {\n\t\t\t\treturn nested;\n\t\t\t}\n\n\t\t\tnumbers.push(...nested);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst single = value as HubFormulaValue;\n\n\t\t// A gap in a column is not a nought to average against: SUM of three figures and two\n\t\t// blanks is the sum of three figures, and AVERAGE of them divides by three.\n\t\tif (single === null || single === '') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst number = asNumber(single);\n\n\t\tif (failed(number)) {\n\t\t\treturn number;\n\t\t}\n\n\t\tnumbers.push(number);\n\t}\n\n\treturn numbers;\n}\n\n/** What a function is handed: values, and whole columns as lists. */\ntype Argument = HubFormulaValue | readonly HubFormulaValue[];\n\n/**\n * Runs a formula.\n *\n * @param formula - What {@link parseFormula} gave back.\n * @param context - How to reach the sheet: this row's cells, and whole columns.\n * @returns The value, or what went wrong.\n */\nexport function evaluateFormula(formula: HubFormula, context: HubFormulaContext): HubFormulaOutcome {\n\tfunction walk(node: HubFormulaNode): Argument | HubFormulaFailure {\n\t\tswitch (node.kind) {\n\t\t\tcase 'number':\n\t\t\tcase 'text':\n\t\t\tcase 'boolean':\n\t\t\t\treturn node.value;\n\n\t\t\tcase 'cell': {\n\t\t\t\tconst value = context.cell(node.alias);\n\n\t\t\t\t// Undefined is \"no such column\", which is a mistake; null is an empty cell, which\n\t\t\t\t// is not. Collapsing the two is how a typo in an alias comes out as nought.\n\t\t\t\treturn value === undefined ? { ok: false, code: 'name', at: node.alias } : value;\n\t\t\t}\n\n\t\t\tcase 'column': {\n\t\t\t\tconst values = context.column(node.alias);\n\n\t\t\t\treturn values === undefined ? { ok: false, code: 'name', at: node.alias } : values;\n\t\t\t}\n\n\t\t\tcase 'at': {\n\t\t\t\tconst value = context.at?.(node.row, node.col);\n\n\t\t\t\t// A place outside the sheet is a mistake, not an empty cell: a formula that points\n\t\t\t\t// off the edge should say so rather than quietly read nothing.\n\t\t\t\treturn value === undefined ? { ok: false, code: 'name', at: 'ref' } : value;\n\t\t\t}\n\n\t\t\tcase 'area': {\n\t\t\t\tconst values = context.area?.(node.top, node.left, node.bottom, node.right);\n\n\t\t\t\treturn values === undefined ? { ok: false, code: 'name', at: 'ref' } : values;\n\t\t\t}\n\n\t\t\tcase 'unary': {\n\t\t\t\tconst operand = walk(node.operand);\n\n\t\t\t\tif (failed(operand)) {\n\t\t\t\t\treturn operand;\n\t\t\t\t}\n\n\t\t\t\tconst number = asNumber(operand as HubFormulaValue);\n\n\t\t\t\tif (failed(number)) {\n\t\t\t\t\treturn number;\n\t\t\t\t}\n\n\t\t\t\treturn node.operator === '-' ? -number : number;\n\t\t\t}\n\n\t\t\tcase 'binary':\n\t\t\t\treturn binary(node);\n\n\t\t\tcase 'call':\n\t\t\t\treturn call(node);\n\t\t}\n\t}\n\n\tfunction binary(node: Extract<HubFormulaNode, { kind: 'binary' }>): Argument | HubFormulaFailure {\n\t\tconst left = walk(node.left);\n\n\t\tif (failed(left)) {\n\t\t\treturn left;\n\t\t}\n\n\t\tconst right = walk(node.right);\n\n\t\tif (failed(right)) {\n\t\t\treturn right;\n\t\t}\n\n\t\tconst a = left as HubFormulaValue;\n\t\tconst b = right as HubFormulaValue;\n\n\t\tif (node.operator === '&') {\n\t\t\treturn asText(a) + asText(b);\n\t\t}\n\n\t\tif (['=', '<>', '<', '<=', '>', '>='].includes(node.operator)) {\n\t\t\treturn compare(node.operator, a, b);\n\t\t}\n\n\t\tconst x = asNumber(a);\n\n\t\tif (failed(x)) {\n\t\t\treturn x;\n\t\t}\n\n\t\tconst y = asNumber(b);\n\n\t\tif (failed(y)) {\n\t\t\treturn y;\n\t\t}\n\n\t\tswitch (node.operator) {\n\t\t\tcase '+':\n\t\t\t\treturn x + y;\n\t\t\tcase '-':\n\t\t\t\treturn x - y;\n\t\t\tcase '*':\n\t\t\t\treturn x * y;\n\t\t\tcase '/':\n\t\t\t\treturn y === 0 ? { ok: false, code: 'divide-by-zero' } : x / y;\n\t\t\tcase '^':\n\t\t\t\treturn x ** y;\n\t\t}\n\n\t\treturn { ok: false, code: 'syntax', at: node.operator };\n\t}\n\n\t/** Two values compared the way a reader means it: numbers as numbers, text as text. */\n\tfunction compare(operator: string, a: HubFormulaValue, b: HubFormulaValue): boolean {\n\t\tconst bothNumbers = typeof a !== 'string' && typeof b !== 'string';\n\t\tconst x = bothNumbers ? (asNumber(a) as number) : asText(a);\n\t\tconst y = bothNumbers ? (asNumber(b) as number) : asText(b);\n\n\t\tswitch (operator) {\n\t\t\tcase '=':\n\t\t\t\treturn x === y;\n\t\t\tcase '<>':\n\t\t\t\treturn x !== y;\n\t\t\tcase '<':\n\t\t\t\treturn x < y;\n\t\t\tcase '<=':\n\t\t\t\treturn x <= y;\n\t\t\tcase '>':\n\t\t\t\treturn x > y;\n\t\t\tdefault:\n\t\t\t\treturn x >= y;\n\t\t}\n\t}\n\n\tfunction call(node: Extract<HubFormulaNode, { kind: 'call' }>): Argument | HubFormulaFailure {\n\t\tconst args: Argument[] = [];\n\n\t\t// IF decides which branch to run, so its arguments are not all worked out up front: a\n\t\t// division by nought on the branch that is not taken is not an error the reader made.\n\t\tif (node.name === 'IF') {\n\t\t\tif (node.args.length < 2 || node.args.length > 3) {\n\t\t\t\treturn { ok: false, code: 'type', at: 'IF' };\n\t\t\t}\n\n\t\t\tconst condition = walk(node.args[0]);\n\n\t\t\tif (failed(condition)) {\n\t\t\t\treturn condition;\n\t\t\t}\n\n\t\t\tif (asBoolean(condition as HubFormulaValue)) {\n\t\t\t\treturn walk(node.args[1]);\n\t\t\t}\n\n\t\t\treturn node.args[2] ? walk(node.args[2]) : false;\n\t\t}\n\n\t\tfor (const argument of node.args) {\n\t\t\tconst value = walk(argument);\n\n\t\t\tif (failed(value)) {\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\targs.push(value);\n\t\t}\n\n\t\treturn apply(node.name, args);\n\t}\n\n\tfunction apply(name: string, args: readonly Argument[]): Argument | HubFormulaFailure {\n\t\tswitch (name) {\n\t\t\tcase 'SUM':\n\t\t\tcase 'AVERAGE':\n\t\t\tcase 'AVG':\n\t\t\tcase 'MIN':\n\t\t\tcase 'MAX': {\n\t\t\t\tconst numbers = numbersOf(args);\n\n\t\t\t\tif (failed(numbers)) {\n\t\t\t\t\treturn numbers;\n\t\t\t\t}\n\n\t\t\t\tif (name === 'SUM') {\n\t\t\t\t\treturn numbers.reduce((total, value) => total + value, 0);\n\t\t\t\t}\n\n\t\t\t\tif (!numbers.length) {\n\t\t\t\t\t// Nothing to average, and nothing to take the least or the most of.\n\t\t\t\t\treturn name === 'MIN' || name === 'MAX' ? 0 : { ok: false, code: 'divide-by-zero' };\n\t\t\t\t}\n\n\t\t\t\tif (name === 'MIN') {\n\t\t\t\t\treturn Math.min(...numbers);\n\t\t\t\t}\n\n\t\t\t\tif (name === 'MAX') {\n\t\t\t\t\treturn Math.max(...numbers);\n\t\t\t\t}\n\n\t\t\t\treturn numbers.reduce((total, value) => total + value, 0) / numbers.length;\n\t\t\t}\n\n\t\t\tcase 'COUNT': {\n\t\t\t\tconst numbers = numbersOf(args);\n\n\t\t\t\treturn failed(numbers) ? 0 : numbers.length;\n\t\t\t}\n\n\t\t\tcase 'ROUND': {\n\t\t\t\tconst value = asNumber(args[0] as HubFormulaValue);\n\n\t\t\t\tif (failed(value)) {\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\n\t\t\t\tconst places = args.length > 1 ? asNumber(args[1] as HubFormulaValue) : 0;\n\n\t\t\t\tif (failed(places)) {\n\t\t\t\t\treturn places;\n\t\t\t\t}\n\n\t\t\t\tconst factor = 10 ** places;\n\n\t\t\t\treturn Math.round(value * factor) / factor;\n\t\t\t}\n\n\t\t\tcase 'ABS': {\n\t\t\t\tconst value = asNumber(args[0] as HubFormulaValue);\n\n\t\t\t\treturn failed(value) ? value : Math.abs(value);\n\t\t\t}\n\n\t\t\tcase 'AND':\n\t\t\t\treturn args.every((value) => asBoolean(value as HubFormulaValue));\n\n\t\t\tcase 'OR':\n\t\t\t\treturn args.some((value) => asBoolean(value as HubFormulaValue));\n\n\t\t\tcase 'NOT':\n\t\t\t\treturn !asBoolean(args[0] as HubFormulaValue);\n\n\t\t\tcase 'CONCAT':\n\t\t\t\treturn args.map((value) => asText(value as HubFormulaValue)).join('');\n\n\t\t\tcase 'LEN':\n\t\t\t\treturn asText(args[0] as HubFormulaValue).length;\n\n\t\t\tdefault:\n\t\t\t\treturn { ok: false, code: 'name', at: name };\n\t\t}\n\t}\n\n\tconst result = walk(formula.node);\n\n\tif (failed(result)) {\n\t\treturn result;\n\t}\n\n\t// A whole column where a single value was wanted: SUM() takes one, but a cell cannot show one.\n\tif (Array.isArray(result)) {\n\t\treturn { ok: false, code: 'type' };\n\t}\n\n\treturn { ok: true, value: result as HubFormulaValue };\n}\n","/**\n * Coordinates: the other way to point at a cell, and what has to happen to them afterwards.\n *\n * An alias says which column it means and goes on meaning it whatever happens to the sheet. A\n * coordinate says *where* the column was when the formula was written, which is only the same\n * thing until somebody moves it. That is not a reason to refuse coordinates — a spreadsheet\n * without `B2` is not a spreadsheet — it is a reason to move them with the sheet, which is what\n * every spreadsheet does and what these functions are for.\n */\n\n/** The letters a column is known by: A, B … Z, AA, AB … */\nexport function columnLabel(index: number): string {\n\tif (index < 0) {\n\t\treturn '';\n\t}\n\n\tlet label = '';\n\tlet rest = index;\n\n\tfor (;;) {\n\t\tlabel = String.fromCharCode(65 + (rest % 26)) + label;\n\t\trest = Math.floor(rest / 26) - 1;\n\n\t\tif (rest < 0) {\n\t\t\treturn label;\n\t\t}\n\t}\n}\n\n/** Which column a run of letters means, or -1 when it means none. */\nexport function columnIndexOf(label: string): number {\n\tif (!/^[A-Za-z]+$/.test(label)) {\n\t\treturn -1;\n\t}\n\n\tlet index = 0;\n\n\tfor (const character of label.toUpperCase()) {\n\t\tindex = index * 26 + (character.charCodeAt(0) - 64);\n\t}\n\n\treturn index - 1;\n}\n\n/** What a coordinate points at, counting from nought. */\nexport interface HubFormulaCoordinate {\n\treadonly row: number;\n\treadonly col: number;\n}\n\n/** Reads `B3` as a place, or nothing when it is not one. */\nexport function parseCoordinate(text: string): HubFormulaCoordinate | null {\n\tconst match = /^([A-Za-z]+)([0-9]+)$/.exec(text);\n\n\tif (!match) {\n\t\treturn null;\n\t}\n\n\tconst col = columnIndexOf(match[1]);\n\tconst row = Number(match[2]) - 1;\n\n\treturn col < 0 || row < 0 ? null : { row, col };\n}\n\n/** Writes a place back as `B3`, which is what a formula shows. */\nexport function formatCoordinate(coordinate: HubFormulaCoordinate): string {\n\treturn `${columnLabel(coordinate.col)}${coordinate.row + 1}`;\n}\n\n/** What a reference has become after the sheet changed shape. */\ntype Moved = HubFormulaCoordinate | 'gone';\n\n/** What a column moving does to a column index. */\nfunction afterColumnMove(col: number, from: number, to: number): number {\n\tif (col === from) {\n\t\treturn to;\n\t}\n\n\t// Everything between the two places shuffles by one, in whichever direction the column went.\n\tif (from < to) {\n\t\treturn col > from && col <= to ? col - 1 : col;\n\t}\n\n\treturn col >= to && col < from ? col + 1 : col;\n}\n\n/** What inserting or deleting tracks does to an index along that axis. */\nfunction afterInsertOrDelete(index: number, at: number, count: number): number | 'gone' {\n\tif (count > 0) {\n\t\treturn index >= at ? index + count : index;\n\t}\n\n\tconst removed = -count;\n\n\tif (index >= at && index < at + removed) {\n\t\treturn 'gone';\n\t}\n\n\treturn index >= at + removed ? index - removed : index;\n}\n\n/** How the sheet changed shape. */\nexport type HubFormulaShapeChange =\n\t| { readonly kind: 'move-column'; readonly from: number; readonly to: number }\n\t/** A positive count inserts, a negative one deletes. */\n\t| { readonly kind: 'columns'; readonly at: number; readonly count: number }\n\t| { readonly kind: 'rows'; readonly at: number; readonly count: number };\n\n/** Where a coordinate ends up after a change, or that it no longer points at anything. */\nexport function moveCoordinate(coordinate: HubFormulaCoordinate, change: HubFormulaShapeChange): Moved {\n\tif (change.kind === 'move-column') {\n\t\treturn { row: coordinate.row, col: afterColumnMove(coordinate.col, change.from, change.to) };\n\t}\n\n\tif (change.kind === 'columns') {\n\t\tconst col = afterInsertOrDelete(coordinate.col, change.at, change.count);\n\n\t\treturn col === 'gone' ? 'gone' : { row: coordinate.row, col };\n\t}\n\n\tconst row = afterInsertOrDelete(coordinate.row, change.at, change.count);\n\n\treturn row === 'gone' ? 'gone' : { row, col: coordinate.col };\n}\n\n/**\n * Rewrites the coordinates in a formula so they point at the same data as before.\n *\n * Text, not a parsed tree, and deliberately: what a reader typed is what is stored, so what comes\n * back has to be something they would recognise as their own formula with a letter changed. A\n * reference to something that has been deleted becomes `#REF!`, which is what a spreadsheet does\n * and is honest — the alternative is a formula that quietly reads its neighbour.\n *\n * @param formula - The text of the formula, `=` and all.\n * @param change - What happened to the sheet.\n * @returns The formula with its coordinates moved.\n */\nexport function rewriteCoordinates(formula: string, change: HubFormulaShapeChange): string {\n\tif (typeof formula !== 'string' || !formula.trimStart().startsWith('=')) {\n\t\treturn formula;\n\t}\n\n\t// Left alone inside quotes and inside brackets: `\"A1\"` is a word somebody wrote, and `[price]`\n\t// is an alias that happens to look like letters.\n\tlet result = '';\n\tlet index = 0;\n\tlet quoted = false;\n\tlet bracketed = false;\n\n\twhile (index < formula.length) {\n\t\tconst character = formula[index];\n\n\t\tif (quoted) {\n\t\t\tresult += character;\n\t\t\tquoted = character !== '\"' || formula[index + 1] === '\"';\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"') {\n\t\t\tquoted = true;\n\t\t\tresult += character;\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '[') {\n\t\t\tbracketed = true;\n\t\t}\n\n\t\tif (character === ']') {\n\t\t\tbracketed = false;\n\t\t}\n\n\t\tif (!bracketed) {\n\t\t\tconst match = /^[A-Za-z]+[0-9]+/.exec(formula.slice(index));\n\t\t\tconst coordinate = match && parseCoordinate(match[0]);\n\n\t\t\tif (coordinate) {\n\t\t\t\tconst moved = moveCoordinate(coordinate, change);\n\n\t\t\t\tresult += moved === 'gone' ? '#REF!' : formatCoordinate(moved);\n\t\t\t\tindex += match![0].length;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tresult += character;\n\t\tindex++;\n\t}\n\n\treturn result;\n}\n\n/**\n * The rows again, with every formula in them moved to match the sheet's new shape.\n *\n * The sheet reports what the reader asked for and writes nothing, as it does with everything else,\n * so this is the line the host writes in its own handler:\n *\n * ```ts\n * protected onColumnMoved(move: { from: number; to: number; keys: string[] }): void {\n * this.order.set(move.keys);\n * this.rows.update((rows) => rewriteRowFormulas(rows, { kind: 'move-column', from: move.from, to: move.to }));\n * }\n * ```\n *\n * Every own property that holds a formula is rewritten, which covers the usual case of formulas\n * living in the row's own fields. A host that keeps them somewhere else — a map beside the data, a\n * column that declares its own — walks that itself with {@link rewriteCoordinates}.\n *\n * @param rows - The rows as they are.\n * @param change - What happened to the sheet.\n * @returns New rows; the ones with nothing to rewrite are the very same objects, so a sheet that\n * tracks by identity redraws only what moved.\n */\nexport function rewriteRowFormulas<TRow extends object>(rows: readonly TRow[], change: HubFormulaShapeChange): TRow[] {\n\treturn rows.map((row) => {\n\t\tlet changed = false;\n\t\tconst next = { ...row } as Record<string, unknown>;\n\n\t\tfor (const [key, value] of Object.entries(next)) {\n\t\t\tif (typeof value !== 'string') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst rewritten = rewriteCoordinates(value, change);\n\n\t\t\tif (rewritten !== value) {\n\t\t\t\tnext[key] = rewritten;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\treturn (changed ? next : row) as TRow;\n\t});\n}\n","import { parseCoordinate } from './formula-coordinates';\nimport { HubFormula, HubFormulaFailure, HubFormulaNode } from './formula.types';\n\n/**\n * Turning the text of a formula into something that can be run.\n *\n * Hand-written rather than generated, and deliberately: a grammar this small is a page of code,\n * and a parser generator would be a dependency, a build step and a licence to check for the sake\n * of it. What it costs is that the precedence is written out by hand — which is also what makes it\n * readable.\n *\n * Precedence, loosest first, as in a spreadsheet:\n *\n * comparison = <> < <= > >=\n * concatenation &\n * additive + -\n * multiplicative * /\n * power ^\n * unary - +\n * primary number, text, TRUE/FALSE, [alias], [alias:], NAME(…), ( … )\n */\n\n/** Whether a stored value is a formula rather than a value. */\nexport function isFormula(value: unknown): value is string {\n\treturn typeof value === 'string' && value.trimStart().startsWith('=');\n}\n\ntype Token =\n\t| { kind: 'number'; value: number }\n\t| { kind: 'text'; value: string }\n\t| { kind: 'reference'; alias: string; whole: boolean }\n\t| { kind: 'name'; value: string }\n\t| { kind: 'symbol'; value: string };\n\nconst SYMBOLS = ['<>', '<=', '>=', '+', '-', '*', '/', '^', '&', '=', '<', '>', '(', ')', ',', ';', ':'];\n\n/** Splits the text into the pieces the parser walks, or says where it gave up. */\nfunction tokenise(source: string): Token[] | HubFormulaFailure {\n\tconst tokens: Token[] = [];\n\tlet index = 0;\n\n\twhile (index < source.length) {\n\t\tconst char = source[index];\n\n\t\tif (/\\s/.test(char)) {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// A reference: [alias] for this row, [alias:] for the whole column.\n\t\tif (char === '[') {\n\t\t\tconst end = source.indexOf(']', index);\n\n\t\t\tif (end < 0) {\n\t\t\t\treturn { ok: false, code: 'syntax', at: '[' };\n\t\t\t}\n\n\t\t\tconst inside = source.slice(index + 1, end);\n\t\t\tconst whole = inside.endsWith(':');\n\t\t\tconst alias = (whole ? inside.slice(0, -1) : inside).trim();\n\n\t\t\tif (!alias) {\n\t\t\t\treturn { ok: false, code: 'syntax', at: '[]' };\n\t\t\t}\n\n\t\t\ttokens.push({ kind: 'reference', alias, whole });\n\t\t\tindex = end + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// A quoted string. Two quotes in a row are one quote, as in a spreadsheet.\n\t\tif (char === '\"') {\n\t\t\tlet text = '';\n\t\t\tindex++;\n\n\t\t\tfor (;;) {\n\t\t\t\tif (index >= source.length) {\n\t\t\t\t\treturn { ok: false, code: 'syntax', at: '\"' };\n\t\t\t\t}\n\n\t\t\t\tif (source[index] === '\"') {\n\t\t\t\t\tif (source[index + 1] === '\"') {\n\t\t\t\t\t\ttext += '\"';\n\t\t\t\t\t\tindex += 2;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tindex++;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\ttext += source[index];\n\t\t\t\tindex++;\n\t\t\t}\n\n\t\t\ttokens.push({ kind: 'text', value: text });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (/[0-9.]/.test(char)) {\n\t\t\tconst match = /^[0-9]*\\.?[0-9]+(?:[eE][+-]?[0-9]+)?/.exec(source.slice(index));\n\n\t\t\tif (!match) {\n\t\t\t\treturn { ok: false, code: 'syntax', at: char };\n\t\t\t}\n\n\t\t\ttokens.push({ kind: 'number', value: Number(match[0]) });\n\t\t\tindex += match[0].length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (/[A-Za-z_]/.test(char)) {\n\t\t\tconst match = /^[A-Za-z_][A-Za-z0-9_.]*/.exec(source.slice(index))!;\n\n\t\t\ttokens.push({ kind: 'name', value: match[0] });\n\t\t\tindex += match[0].length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst symbol = SYMBOLS.find((candidate) => source.startsWith(candidate, index));\n\n\t\tif (!symbol) {\n\t\t\treturn { ok: false, code: 'syntax', at: char };\n\t\t}\n\n\t\ttokens.push({ kind: 'symbol', value: symbol });\n\t\tindex += symbol.length;\n\t}\n\n\treturn tokens;\n}\n\n/** Whether what came back is a failure rather than what was asked for. */\nfunction failed<T>(value: T | HubFormulaFailure): value is HubFormulaFailure {\n\treturn typeof value === 'object' && value !== null && 'ok' in value && (value as HubFormulaFailure).ok === false;\n}\n\n/**\n * Reads the text of a formula, with or without its leading `=`.\n *\n * @returns The parsed formula, or the first thing that did not make sense.\n */\nexport function parseFormula(source: string): HubFormula | HubFormulaFailure {\n\tconst text = source.trimStart().startsWith('=') ? source.trimStart().slice(1) : source;\n\tconst tokens = tokenise(text);\n\n\tif (failed(tokens)) {\n\t\treturn tokens;\n\t}\n\n\tlet at = 0;\n\n\tconst peek = (): Token | undefined => tokens[at];\n\tconst eat = (value: string): boolean => {\n\t\tconst token = peek();\n\n\t\tif (token?.kind === 'symbol' && token.value === value) {\n\t\t\tat++;\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t};\n\n\tconst cells = new Set<string>();\n\tconst columns = new Set<string>();\n\tlet coordinates = false;\n\n\tfunction parseExpression(): HubFormulaNode | HubFormulaFailure {\n\t\treturn parseComparison();\n\t}\n\n\tfunction parseComparison(): HubFormulaNode | HubFormulaFailure {\n\t\tlet left = parseConcat();\n\n\t\tif (failed(left)) {\n\t\t\treturn left;\n\t\t}\n\n\t\tfor (;;) {\n\t\t\tconst token = peek();\n\t\t\tconst operator = token?.kind === 'symbol' ? token.value : '';\n\n\t\t\tif (!['=', '<>', '<', '<=', '>', '>='].includes(operator)) {\n\t\t\t\treturn left;\n\t\t\t}\n\n\t\t\tat++;\n\n\t\t\tconst right = parseConcat();\n\n\t\t\tif (failed(right)) {\n\t\t\t\treturn right;\n\t\t\t}\n\n\t\t\tleft = { kind: 'binary', operator: operator as '=', left, right };\n\t\t}\n\t}\n\n\tfunction parseConcat(): HubFormulaNode | HubFormulaFailure {\n\t\tlet left = parseAdditive();\n\n\t\tif (failed(left)) {\n\t\t\treturn left;\n\t\t}\n\n\t\twhile (eat('&')) {\n\t\t\tconst right = parseAdditive();\n\n\t\t\tif (failed(right)) {\n\t\t\t\treturn right;\n\t\t\t}\n\n\t\t\tleft = { kind: 'binary', operator: '&', left, right };\n\t\t}\n\n\t\treturn left;\n\t}\n\n\tfunction parseAdditive(): HubFormulaNode | HubFormulaFailure {\n\t\tlet left = parseMultiplicative();\n\n\t\tif (failed(left)) {\n\t\t\treturn left;\n\t\t}\n\n\t\tfor (;;) {\n\t\t\tconst token = peek();\n\t\t\tconst operator = token?.kind === 'symbol' ? token.value : '';\n\n\t\t\tif (operator !== '+' && operator !== '-') {\n\t\t\t\treturn left;\n\t\t\t}\n\n\t\t\tat++;\n\n\t\t\tconst right = parseMultiplicative();\n\n\t\t\tif (failed(right)) {\n\t\t\t\treturn right;\n\t\t\t}\n\n\t\t\tleft = { kind: 'binary', operator, left, right };\n\t\t}\n\t}\n\n\tfunction parseMultiplicative(): HubFormulaNode | HubFormulaFailure {\n\t\tlet left = parsePower();\n\n\t\tif (failed(left)) {\n\t\t\treturn left;\n\t\t}\n\n\t\tfor (;;) {\n\t\t\tconst token = peek();\n\t\t\tconst operator = token?.kind === 'symbol' ? token.value : '';\n\n\t\t\tif (operator !== '*' && operator !== '/') {\n\t\t\t\treturn left;\n\t\t\t}\n\n\t\t\tat++;\n\n\t\t\tconst right = parsePower();\n\n\t\t\tif (failed(right)) {\n\t\t\t\treturn right;\n\t\t\t}\n\n\t\t\tleft = { kind: 'binary', operator, left, right };\n\t\t}\n\t}\n\n\tfunction parsePower(): HubFormulaNode | HubFormulaFailure {\n\t\tconst left = parseUnary();\n\n\t\tif (failed(left)) {\n\t\t\treturn left;\n\t\t}\n\n\t\tif (!eat('^')) {\n\t\t\treturn left;\n\t\t}\n\n\t\t// Right to left, as everywhere else: 2^3^2 is 2^(3^2).\n\t\tconst right = parsePower();\n\n\t\tif (failed(right)) {\n\t\t\treturn right;\n\t\t}\n\n\t\treturn { kind: 'binary', operator: '^', left, right };\n\t}\n\n\tfunction parseUnary(): HubFormulaNode | HubFormulaFailure {\n\t\tconst token = peek();\n\n\t\tif (token?.kind === 'symbol' && (token.value === '-' || token.value === '+')) {\n\t\t\tat++;\n\n\t\t\tconst operand = parseUnary();\n\n\t\t\tif (failed(operand)) {\n\t\t\t\treturn operand;\n\t\t\t}\n\n\t\t\treturn { kind: 'unary', operator: token.value, operand };\n\t\t}\n\n\t\treturn parsePrimary();\n\t}\n\n\tfunction parsePrimary(): HubFormulaNode | HubFormulaFailure {\n\t\tconst token = peek();\n\n\t\tif (!token) {\n\t\t\treturn { ok: false, code: 'syntax', at: 'end' };\n\t\t}\n\n\t\tif (token.kind === 'number') {\n\t\t\tat++;\n\n\t\t\treturn { kind: 'number', value: token.value };\n\t\t}\n\n\t\tif (token.kind === 'text') {\n\t\t\tat++;\n\n\t\t\treturn { kind: 'text', value: token.value };\n\t\t}\n\n\t\tif (token.kind === 'reference') {\n\t\t\tat++;\n\n\t\t\tif (token.whole) {\n\t\t\t\tcolumns.add(token.alias);\n\n\t\t\t\treturn { kind: 'column', alias: token.alias };\n\t\t\t}\n\n\t\t\tcells.add(token.alias);\n\n\t\t\treturn { kind: 'cell', alias: token.alias };\n\t\t}\n\n\t\tif (token.kind === 'name') {\n\t\t\tat++;\n\n\t\t\tconst upper = token.value.toUpperCase();\n\n\t\t\tif (upper === 'TRUE' || upper === 'FALSE') {\n\t\t\t\treturn { kind: 'boolean', value: upper === 'TRUE' };\n\t\t\t}\n\n\t\t\t// A place: `B3`, or `B3:D7` for a rectangle of them. Written the way a spreadsheet\n\t\t\t// writes it, because that is what somebody arriving from one will type.\n\t\t\tconst place = parseCoordinate(token.value);\n\n\t\t\tif (place) {\n\t\t\t\tcoordinates = true;\n\n\t\t\t\tif (!eat(':')) {\n\t\t\t\t\treturn { kind: 'at', row: place.row, col: place.col };\n\t\t\t\t}\n\n\t\t\t\tconst next = peek();\n\t\t\t\tconst far = next?.kind === 'name' ? parseCoordinate(next.value) : null;\n\n\t\t\t\tif (!far) {\n\t\t\t\t\treturn { ok: false, code: 'syntax', at: ':' };\n\t\t\t\t}\n\n\t\t\t\tat++;\n\n\t\t\t\treturn {\n\t\t\t\t\tkind: 'area',\n\t\t\t\t\ttop: Math.min(place.row, far.row),\n\t\t\t\t\tleft: Math.min(place.col, far.col),\n\t\t\t\t\tbottom: Math.max(place.row, far.row),\n\t\t\t\t\tright: Math.max(place.col, far.col)\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (!eat('(')) {\n\t\t\t\t// A bare word is a name nothing answers to — the reader probably meant a column,\n\t\t\t\t// which is written in brackets.\n\t\t\t\treturn { ok: false, code: 'name', at: token.value };\n\t\t\t}\n\n\t\t\tconst args: HubFormulaNode[] = [];\n\n\t\t\tif (!eat(')')) {\n\t\t\t\tfor (;;) {\n\t\t\t\t\tconst argument = parseExpression();\n\n\t\t\t\t\tif (failed(argument)) {\n\t\t\t\t\t\treturn argument;\n\t\t\t\t\t}\n\n\t\t\t\t\targs.push(argument);\n\n\t\t\t\t\t// A comma or a semicolon: the same separator wears both costumes depending on\n\t\t\t\t\t// where the reader learnt to write formulas.\n\t\t\t\t\tif (eat(',') || eat(';')) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (eat(')')) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn { ok: false, code: 'syntax', at: ')' };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { kind: 'call', name: upper, args };\n\t\t}\n\n\t\tif (token.value === '(') {\n\t\t\tat++;\n\n\t\t\tconst inner = parseExpression();\n\n\t\t\tif (failed(inner)) {\n\t\t\t\treturn inner;\n\t\t\t}\n\n\t\t\tif (!eat(')')) {\n\t\t\t\treturn { ok: false, code: 'syntax', at: ')' };\n\t\t\t}\n\n\t\t\treturn inner;\n\t\t}\n\n\t\treturn { ok: false, code: 'syntax', at: token.value };\n\t}\n\n\tconst node = parseExpression();\n\n\tif (failed(node)) {\n\t\treturn node;\n\t}\n\n\tif (at < tokens.length) {\n\t\tconst rest = tokens[at];\n\n\t\treturn { ok: false, code: 'syntax', at: rest.kind === 'symbol' || rest.kind === 'name' ? String(rest.value) : 'end' };\n\t}\n\n\treturn { node, cells: [...cells], columns: [...columns], coordinates };\n}\n","import { HubSpreadsheetColumn, HubSpreadsheetValue } from '../models/spreadsheet.types';\nimport { evaluateFormula } from './formula-evaluator';\nimport { isFormula, parseFormula } from './formula-parser';\nimport { HubFormula, HubFormulaFailure, HubFormulaOutcome, HubFormulaValue } from './formula.types';\n\n/**\n * Working out what every cell of a sheet shows once formulas are in it.\n *\n * A formula reads other cells, and those may be formulas too, so the answer to one can depend on\n * the answer to another. Two things follow, and both are here rather than in the component:\n *\n * - **It has to be worked out in order.** A cell is not ready until everything it reads is ready.\n * - **It has to refuse to go round in circles.** A formula that needs its own result — directly,\n * or through three others — has no answer, and a sheet that tries to find one stops responding.\n *\n * One rule follows from the second and is worth saying out loud: a whole-column reference leaves\n * out the cell that is asking for it. `=SUM([total:])` written in the total row is what everybody\n * writes and what everybody means, and taken literally it is a sum that needs its own answer.\n * Reading a *different* column is untouched — a total row that sums the prices sums every price.\n */\n\n/** What a cell came to, and where it came from. */\nexport interface HubFormulaCellResult {\n\t/** What the cell shows. */\n\treadonly value: HubSpreadsheetValue;\n\t/** Set when the cell holds a formula that could not be run. */\n\treadonly failure?: HubFormulaFailure;\n}\n\n/** Every cell of the sheet, keyed by row index and column alias. */\nexport type HubFormulaSheet = ReadonlyArray<Readonly<Record<string, HubFormulaCellResult>>>;\n\n/** What a sheet of formulas is worked out from. */\nexport interface HubFormulaSheetInput<TRow> {\n\treadonly rows: readonly TRow[];\n\treadonly columns: readonly HubSpreadsheetColumn<TRow>[];\n\t/**\n\t * What a cell holds before any formula is run: a value, or the text of a formula.\n\t *\n\t * By row index rather than by row, because the caller usually has the grid already worked out\n\t * and finding a row's place in a list to read it back is the kind of thing that turns a sheet\n\t * of ten thousand rows into a sheet that takes a second to draw.\n\t */\n\treadonly raw: (rowIndex: number, column: HubSpreadsheetColumn<TRow>) => HubSpreadsheetValue;\n}\n\n/** A cell's place, as the walk names it. */\ntype Where = `${number}\\t${string}`;\n\nconst where = (row: number, alias: string): Where => `${row}\\t${alias}`;\n\n/**\n * Runs every formula in a sheet, in whatever order the dependencies demand.\n *\n * Worked out lazily and remembered: a cell is run the first time something needs it, and a column\n * read by twenty rows is not run twenty times. The walk carries the cells it is in the middle of,\n * which is how a circle is caught the moment it closes rather than by counting to a thousand.\n *\n * @returns Every cell of the sheet, ready to be shown.\n */\nexport function evaluateSheet<TRow>(input: HubFormulaSheetInput<TRow>): HubFormulaSheet {\n\tconst { rows, columns, raw } = input;\n\tconst byAlias = new Map(columns.map((column) => [column.key, column]));\n\tconst done = new Map<Where, HubFormulaCellResult>();\n\tconst parsed = new Map<string, HubFormula | HubFormulaFailure>();\n\tconst running = new Set<Where>();\n\n\t/** The formula of a cell, parsed once however many cells hold the same text. */\n\tfunction formulaOf(text: string): HubFormula | HubFormulaFailure {\n\t\tlet result = parsed.get(text);\n\n\t\tif (!result) {\n\t\t\tresult = parseFormula(text);\n\t\t\tparsed.set(text, result);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tfunction valueOf(rowIndex: number, alias: string): HubFormulaCellResult {\n\t\tconst key = where(rowIndex, alias);\n\t\tconst already = done.get(key);\n\n\t\tif (already) {\n\t\t\treturn already;\n\t\t}\n\n\t\tconst column = byAlias.get(alias);\n\n\t\tif (!column || rowIndex < 0 || rowIndex >= rows.length) {\n\t\t\treturn { value: null, failure: { ok: false, code: 'name', at: alias } };\n\t\t}\n\n\t\t// A column that carries its own formula answers with it, whatever the row happens to hold.\n\t\t// The reader cannot type over one, so what is underneath is not a value that was replaced\n\t\t// — it is a value that was never asked for.\n\t\tconst source = column.formula ?? raw(rowIndex, column);\n\n\t\tif (!isFormula(source)) {\n\t\t\tconst plain: HubFormulaCellResult = { value: source };\n\n\t\t\tdone.set(key, plain);\n\n\t\t\treturn plain;\n\t\t}\n\n\t\t// Already on the stack: the cell needs itself. Remembered as a failure so the other cells\n\t\t// that read it fail the same way instead of starting the walk again.\n\t\tif (running.has(key)) {\n\t\t\tconst circular: HubFormulaCellResult = { value: null, failure: { ok: false, code: 'cycle', at: alias } };\n\n\t\t\tdone.set(key, circular);\n\n\t\t\treturn circular;\n\t\t}\n\n\t\tconst formula = formulaOf(source);\n\n\t\tif ('ok' in formula) {\n\t\t\tconst broken: HubFormulaCellResult = { value: null, failure: formula };\n\n\t\t\tdone.set(key, broken);\n\n\t\t\treturn broken;\n\t\t}\n\n\t\trunning.add(key);\n\n\t\tconst outcome: HubFormulaOutcome = evaluateFormula(formula, {\n\t\t\tcell: (name) => (byAlias.has(name) ? (valueOf(rowIndex, name).value as HubFormulaValue) : undefined),\n\t\t\t// A whole column leaves out the cell that is asking for it, and only when the cell is\n\t\t\t// in that very column. `=SUM([total:])` written in the total row is what everybody\n\t\t\t// writes and what everybody means; taken at its word it is a sum that needs its own\n\t\t\t// answer, and the reader is shown `#CYCLE!` for asking the obvious thing. Reading a\n\t\t\t// different column is untouched: a total row summing the prices sums every price.\n\t\t\tcolumn: (name) =>\n\t\t\t\tbyAlias.has(name)\n\t\t\t\t\t? rows\n\t\t\t\t\t\t\t.map((_, index) =>\n\t\t\t\t\t\t\t\tname === alias && index === rowIndex ? null : (valueOf(index, name).value as HubFormulaValue)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter((_, index) => !(name === alias && index === rowIndex))\n\t\t\t\t\t: undefined,\n\t\t\t// A coordinate is the same walk under another name, so a circle drawn with `B3` is\n\t\t\t// caught exactly as one drawn with an alias.\n\t\t\tat: (row, col) => {\n\t\t\t\tconst target = columns[col];\n\n\t\t\t\treturn target && row >= 0 && row < rows.length\n\t\t\t\t\t? (valueOf(row, target.key).value as HubFormulaValue)\n\t\t\t\t\t: undefined;\n\t\t\t},\n\t\t\tarea: (top, left, bottom, right) => {\n\t\t\t\tif (left < 0 || right >= columns.length || top < 0 || bottom >= rows.length) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst values: HubFormulaValue[] = [];\n\n\t\t\t\tfor (let row = top; row <= bottom; row++) {\n\t\t\t\t\tfor (let col = left; col <= right; col++) {\n\t\t\t\t\t\t// The cell asking is left out of its own rectangle, for the same reason a\n\t\t\t\t\t\t// whole column leaves it out: a total inside the range it totals.\n\t\t\t\t\t\tif (row === rowIndex && columns[col]?.key === alias) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvalues.push(valueOf(row, columns[col].key).value as HubFormulaValue);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t}\n\t\t});\n\n\t\trunning.delete(key);\n\n\t\t// A cell that turned out to be part of a circle answers with the circle, not with the\n\t\t// half-answer the walk happened to reach before it noticed.\n\t\tconst settled = done.get(key);\n\n\t\tif (settled?.failure?.code === 'cycle') {\n\t\t\treturn settled;\n\t\t}\n\n\t\tconst result: HubFormulaCellResult = outcome.ok\n\t\t\t? { value: outcome.value as HubSpreadsheetValue }\n\t\t\t: { value: null, failure: outcome };\n\n\t\tdone.set(key, result);\n\n\t\treturn result;\n\t}\n\n\treturn rows.map((_, rowIndex) => {\n\t\tconst line: Record<string, HubFormulaCellResult> = {};\n\n\t\tfor (const column of columns) {\n\t\t\tline[column.key] = valueOf(rowIndex, column.key);\n\t\t}\n\n\t\treturn line;\n\t});\n}\n","import { HubFormulaFailure } from './formula.types';\n\n/**\n * What a cell shows for a formula that could not be worked out.\n *\n * The spreadsheet spellings rather than sentences: they fit in a cell, they are the same in every\n * language, and anybody who has used a spreadsheet already knows what `#DIV/0!` means. They also\n * travel — a file exported with `#DIV/0!` in a cell says the same thing to whoever opens it in\n * Excel as it did here.\n */\nexport const FORMULA_ERROR_TEXT: Record<HubFormulaFailure['code'], string> = {\n\tsyntax: '#SYNTAX!',\n\tname: '#NAME?',\n\t'divide-by-zero': '#DIV/0!',\n\tcycle: '#CYCLE!',\n\ttype: '#VALUE!'\n};\n\n/** Every spelling, for telling an error apart from something a reader typed. */\nexport const FORMULA_ERRORS = Object.values(FORMULA_ERROR_TEXT);\n\n/** What to show for a failure. */\nexport function formulaErrorText(failure: HubFormulaFailure): string {\n\treturn FORMULA_ERROR_TEXT[failure.code];\n}\n","/**\n * What to offer a reader who is in the middle of writing a formula.\n *\n * A formula names columns by an alias that is nowhere on screen — the header shows a title meant\n * for people, not the key the formula needs — so writing one from memory means knowing something\n * the sheet never showed. That is the actual problem: not that the language is hard, but that the\n * words are hidden.\n *\n * Kept as arithmetic over strings, with no DOM and no component, so the awkward parts — where the\n * word being typed starts, what counts as one — can be held still by a test.\n */\n\n/** One thing the reader can put into the formula. */\nexport interface HubFormulaSuggestion {\n\t/** What to show. */\n\treadonly label: string;\n\t/** What it is, so the list can say so. */\n\treadonly kind: 'column' | 'function';\n\t/** What goes into the draft. */\n\treadonly insert: string;\n\t/** A word on what it does, for a function. */\n\treadonly hint?: string;\n}\n\n/** What the sheet knows that a formula might want. */\nexport interface HubFormulaVocabulary {\n\t/** The column aliases, in the order the columns are in. */\n\treadonly aliases: readonly string[];\n\t/** What each alias is called on screen, so the list can show both. */\n\treadonly titles?: Readonly<Record<string, string>>;\n}\n\n/** The functions the engine knows, with a word on each. */\nexport const HUB_FORMULA_FUNCTIONS: ReadonlyArray<{ name: string; hint: string }> = [\n\t{ name: 'SUM', hint: 'Adds numbers and whole columns' },\n\t{ name: 'AVERAGE', hint: 'The mean of what is there, gaps left out' },\n\t{ name: 'MIN', hint: 'The least of them' },\n\t{ name: 'MAX', hint: 'The most of them' },\n\t{ name: 'COUNT', hint: 'How many are numbers' },\n\t{ name: 'ROUND', hint: 'To a given number of places' },\n\t{ name: 'ABS', hint: 'Without its sign' },\n\t{ name: 'IF', hint: 'One answer or the other' },\n\t{ name: 'AND', hint: 'True when all of them are' },\n\t{ name: 'OR', hint: 'True when any of them is' },\n\t{ name: 'NOT', hint: 'The opposite' },\n\t{ name: 'CONCAT', hint: 'Joins text together' },\n\t{ name: 'LEN', hint: 'How long a piece of text is' }\n];\n\n/** Where the word being typed starts, and what it says so far. */\nexport interface HubFormulaFragment {\n\t/** Where in the draft it begins. */\n\treadonly start: number;\n\t/** What has been typed of it. */\n\treadonly text: string;\n\t/** Whether the reader is inside brackets, which is where a column belongs. */\n\treadonly inBrackets: boolean;\n}\n\n/**\n * The word the caret is in the middle of.\n *\n * Inside brackets it is a column being named — `[pri` — and everywhere else it is a function, or\n * the beginning of one. Everything before the last operator, bracket or space is settled and is\n * left alone.\n */\nexport function formulaFragment(draft: string, caret = draft.length): HubFormulaFragment {\n\tconst upTo = draft.slice(0, caret);\n\tconst opened = upTo.lastIndexOf('[');\n\tconst closed = upTo.lastIndexOf(']');\n\n\tif (opened > closed) {\n\t\treturn { start: opened + 1, text: upTo.slice(opened + 1), inBrackets: true };\n\t}\n\n\tconst match = /[A-Za-z_][A-Za-z0-9_]*$/.exec(upTo);\n\n\treturn match ? { start: match.index, text: match[0], inBrackets: false } : { start: caret, text: '', inBrackets: false };\n}\n\n/**\n * What to offer for a draft, in the order it should be shown.\n *\n * Columns first while inside brackets, functions first outside them, because that is what the\n * reader is asking for by having typed the bracket at all. An empty fragment offers everything:\n * somebody who has just typed `=` is exactly the person who needs the list most.\n *\n * @param draft - The formula as it stands, `=` and all.\n * @param vocabulary - The aliases the sheet has.\n * @param caret - Where the caret is; the end of the draft when not given.\n */\nexport function suggestFormula(\n\tdraft: string,\n\tvocabulary: HubFormulaVocabulary,\n\tcaret = draft.length\n): readonly HubFormulaSuggestion[] {\n\tif (!draft.trimStart().startsWith('=')) {\n\t\treturn [];\n\t}\n\n\tconst fragment = formulaFragment(draft, caret);\n\tconst needle = fragment.text.toLocaleLowerCase();\n\tconst matches = (candidate: string) => !needle || candidate.toLocaleLowerCase().startsWith(needle);\n\n\tconst columns: HubFormulaSuggestion[] = vocabulary.aliases\n\t\t.filter((alias) => matches(alias))\n\t\t.map((alias) => ({\n\t\t\tlabel: alias,\n\t\t\tkind: 'column' as const,\n\t\t\t// Inside brackets the brackets are already there; outside, they come with it.\n\t\t\tinsert: fragment.inBrackets ? alias : `[${alias}]`,\n\t\t\thint: vocabulary.titles?.[alias]\n\t\t}));\n\n\tconst functions: HubFormulaSuggestion[] = fragment.inBrackets\n\t\t? []\n\t\t: HUB_FORMULA_FUNCTIONS.filter((entry) => matches(entry.name)).map((entry) => ({\n\t\t\t\tlabel: entry.name,\n\t\t\t\tkind: 'function' as const,\n\t\t\t\tinsert: `${entry.name}(`,\n\t\t\t\thint: entry.hint\n\t\t\t}));\n\n\treturn fragment.inBrackets ? columns : [...functions, ...columns];\n}\n\n/**\n * The draft with a suggestion put in, and where the caret should end up.\n *\n * The caret matters more than it looks: dropped at the end of `SUM(` it carries straight on into\n * the brackets, and dropped after `[price]` it is ready for the operator. Leaving it where it was\n * makes the reader move it by hand every single time.\n */\nexport function applySuggestion(\n\tdraft: string,\n\tsuggestion: HubFormulaSuggestion,\n\tcaret = draft.length\n): { readonly draft: string; readonly caret: number } {\n\tconst fragment = formulaFragment(draft, caret);\n\tconst before = draft.slice(0, fragment.start);\n\tconst after = draft.slice(caret);\n\n\t// A closing bracket the reader has already typed is not doubled.\n\tconst trailing = fragment.inBrackets && after.startsWith(']') ? after.slice(1) : after;\n\tconst insert = fragment.inBrackets ? `${suggestion.insert}]` : suggestion.insert;\n\n\treturn { draft: before + insert + trailing, caret: before.length + insert.length };\n}\n","import { InjectionToken } from '@angular/core';\nimport { HubSpreadsheetControlsAdapter } from './editor-adapter.types';\n\n/**\n * The optional adapter a sheet renders its list cells through.\n *\n * Injected with `{ optional: true }`: absent means \"draw the native list\", which is what the\n * library does on its own. Register it with {@link provideHubSpreadsheetControls}.\n */\nexport const HUB_SPREADSHEET_CONTROLS = new InjectionToken<HubSpreadsheetControlsAdapter>('HUB_SPREADSHEET_CONTROLS');\n","import { Directive, OnDestroy, ViewContainerRef, afterNextRender, inject, input } from '@angular/core';\nimport { HUB_SPREADSHEET_CONTROLS } from './editor-adapter.token';\nimport { HubSpreadsheetControlConfig, HubSpreadsheetControlHandle } from './editor-adapter.types';\n\n/**\n * Renders a cell's editor through the optional {@link HUB_SPREADSHEET_CONTROLS} adapter.\n *\n * Placed on an `<ng-container>` in the branch that only runs when an adapter is registered; the\n * native list stays in the branch beside it as the answer that needs nothing installed. The\n * control is created as a sibling of the anchor and torn down with it.\n *\n * The config is read once, when the editor opens. A cell editor lives for one decision — it opens,\n * the reader chooses, it closes — so there is nothing to keep in sync afterwards, and the value\n * arriving from elsewhere mid-edit is the case the sheet already refuses.\n */\n@Directive({\n\tselector: '[hubSpreadsheetControl]'\n})\nexport class HubSpreadsheetControlDirective implements OnDestroy {\n\t/** What to build. */\n\treadonly config = input.required<HubSpreadsheetControlConfig>({ alias: 'hubSpreadsheetControl' });\n\n\tprivate readonly vcr = inject(ViewContainerRef);\n\tprivate readonly adapter = inject(HUB_SPREADSHEET_CONTROLS, { optional: true });\n\n\tprivate handle: HubSpreadsheetControlHandle | null = null;\n\n\tconstructor() {\n\t\t// After the cell has been laid out, so a control that measures itself against its host —\n\t\t// a panel deciding whether to open upwards — reads a box that is already the cell's.\n\t\tafterNextRender(() => {\n\t\t\tthis.handle = this.adapter?.create(this.vcr, this.config()) ?? null;\n\t\t});\n\t}\n\n\tngOnDestroy(): void {\n\t\tthis.handle?.destroy();\n\t\tthis.handle = null;\n\t}\n}\n","import { HubGridCoords, HubGridRange, HubGridSpan } from 'ng-hub-ui-utils';\n\n/**\n * Working out what a reader's merge or unmerge does to a list of blocks.\n *\n * The sheet reports what was asked for and writes nothing, as with rows and columns — the list of\n * blocks belongs to whoever declared it, and is usually saved with the document. These are the two\n * lines of arithmetic that would otherwise be rewritten in every host, and the place where the\n * awkward case lives: a merge swallows the blocks already inside it, and a host that merely\n * appends ends up with two blocks claiming the same cell.\n */\n\n/** A merge the reader asked for, and what it absorbs. */\nexport interface HubSpreadsheetMergeRequest {\n\t/** The block to create. */\n\treadonly span: HubGridSpan;\n\t/** The anchors of the blocks it swallows, which have to go. */\n\treadonly replaced: readonly HubGridCoords[];\n}\n\n/** Whether two coordinates are the same cell. */\nfunction sameCell(a: HubGridCoords, b: HubGridCoords): boolean {\n\treturn a.row === b.row && a.col === b.col;\n}\n\n/** The rectangle a block occupies. */\nfunction boundsOf(span: HubGridSpan): HubGridRange {\n\treturn {\n\t\ttop: span.row,\n\t\tleft: span.col,\n\t\tbottom: span.row + span.rowSpan - 1,\n\t\tright: span.col + span.colSpan - 1\n\t};\n}\n\n/** Whether two rectangles share at least one cell. */\nfunction overlaps(a: HubGridRange, b: HubGridRange): boolean {\n\treturn a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;\n}\n\n/** The blocks that share a cell with a rectangle, in the order they were declared. */\nexport function spansWithin(spans: readonly HubGridSpan[], range: HubGridRange): readonly HubGridSpan[] {\n\treturn spans.filter((span) => overlaps(boundsOf(span), range));\n}\n\n/**\n * The block a selection would become, and the blocks it swallows.\n *\n * `null` for a selection of one cell that is not already a block: there is nothing to merge, and\n * an entry that does nothing should not be offered.\n */\nexport function mergeRequestFor(spans: readonly HubGridSpan[], range: HubGridRange): HubSpreadsheetMergeRequest | null {\n\tconst rowSpan = range.bottom - range.top + 1;\n\tconst colSpan = range.right - range.left + 1;\n\n\tif (rowSpan < 1 || colSpan < 1 || (rowSpan === 1 && colSpan === 1)) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tspan: { row: range.top, col: range.left, rowSpan, colSpan },\n\t\treplaced: spansWithin(spans, range).map((span) => ({ row: span.row, col: span.col }))\n\t};\n}\n\n/**\n * The list of blocks after a merge.\n *\n * The swallowed ones are dropped rather than left behind: two blocks claiming the same cell is a\n * sheet that draws one of them and loses the other, and which one depends on the order they happen\n * to be declared in.\n */\nexport function applySpanMerge(spans: readonly HubGridSpan[], request: HubSpreadsheetMergeRequest): HubGridSpan[] {\n\tconst kept = spans.filter((span) => !request.replaced.some((anchor) => sameCell(anchor, span)));\n\n\treturn [...kept, request.span];\n}\n\n/** The list of blocks after the ones anchored at `anchors` are taken apart. */\nexport function applySpanUnmerge(spans: readonly HubGridSpan[], anchors: readonly HubGridCoords[]): HubGridSpan[] {\n\treturn spans.filter((span) => !anchors.some((anchor) => sameCell(anchor, span)));\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n\tChangeDetectionStrategy,\n\tComponent,\n\tElementRef,\n\tInjector,\n\tafterNextRender,\n\tafterRenderEffect,\n\tbooleanAttribute,\n\tcomputed,\n\teffect,\n\tinject,\n\tcontentChildren,\n\tinput,\n\tmodel,\n\toutput,\n\tsignal,\n\tuntracked,\n\tviewChild\n} from '@angular/core';\nimport {\n\tHubGridCoords,\n\tHubGridRange,\n\tHubGridSpan,\n\tHubGridWindow,\n\tanchorOf,\n\tbuildSpanMap,\n\tclampGridRange,\n\tcoversRange,\n\tisCovered,\n\tgridCellTabIndex,\n\tgridRangeBetween,\n\tgridWindow,\n\tgrowWindowToSpans,\n\tgridRangeCells,\n\tisWithinGridRange,\n\tmoveGridFocus,\n\tresolveGridEdge,\n\tresolveGridIntent,\n\tspanAt\n} from 'ng-hub-ui-utils';\nimport { HUB_TRANSLATION_PREFIX, TranslatePipe } from 'ng-hub-ui-utils';\nimport { displayValue, isTruthy, parseForColumn } from '../../columns/cell-values';\nimport { HubSpreadsheetEditorContext, HubSpreadsheetEditorDirective } from './spreadsheet-editor.directive';\nimport { HubSpreadsheetCellContext, HubSpreadsheetCellDirective } from './spreadsheet-cell.directive';\nimport { moveColumn, resolveColumnWidth } from '../../columns/column-sizing';\nimport { fillValues } from '../../fill/fill-series';\nimport { frozenOffsets, isFrozenEdge } from './frozen-panes';\nimport { revealPicker } from './reveal-picker';\nimport { evaluateSheet } from '../../formulas/formula-sheet';\nimport { isFormula } from '../../formulas/formula-parser';\nimport { FORMULA_ERRORS, formulaErrorText } from '../../formulas/formula-errors';\nimport { HubFormulaSuggestion, applySuggestion, formulaFragment, suggestFormula } from '../../formulas/formula-suggest';\nimport { columnLabel } from '../../formulas/formula-coordinates';\nimport { HubSpreadsheetControlDirective } from '../../editors/editor-adapter.directive';\nimport { HUB_SPREADSHEET_CONTROLS } from '../../editors/editor-adapter.token';\nimport { HubSpreadsheetControlConfig } from '../../editors/editor-adapter.types';\nimport { HubClipboardCell, parseClipboardTable, parseDecimal, serialiseClipboardTable } from '../../clipboard/clipboard-table';\nimport { HubSpreadsheetMergeRequest, mergeRequestFor, spansWithin } from '../../models/spreadsheet-spans';\nimport {\n\tHubSpreadsheetDeleteRequest,\n\tHubSpreadsheetInsertRequest,\n\tHubSpreadsheetStructureOptions,\n\tisStructureAllowed,\n\tnextColumnKey,\n\tresolveInsertIndex\n} from '../../models/spreadsheet-structure';\nimport {\n\tHubSpreadsheetCell,\n\tHubSpreadsheetCellRef,\n\tHubSpreadsheetCellState,\n\tHubSpreadsheetColumn,\n\tHubSpreadsheetCommit,\n\tHubSpreadsheetOption,\n\tHubSpreadsheetPaste,\n\tHubSpreadsheetValue,\n\tHubSpreadsheetValueKind\n} from '../../models/spreadsheet.types';\n\n/**\n * The height a row is assumed to have on the very first frame of a virtualised sheet, in pixels.\n *\n * Only ever used once: there is nothing to measure until something is drawn, and what is drawn\n * depends on the height. A rough number breaks that circle, and the measurement that follows\n * replaces it on the next frame. Being wrong costs a few rows too many or too few for one frame;\n * waiting for certainty costs drawing every row there is.\n */\nconst FIRST_PASS_ROW_HEIGHT = 32;\n\n/**\n * An editable sheet of cells: typed into, moved through with the keyboard, and pasted into from\n * a spreadsheet.\n *\n * It knows nothing about what the cells mean. The owner describes each column, keeps the save\n * state it cares about, and does the writing when the sheet reports a change. The sheet never\n * mutates the rows it is given, which is what lets the same component serve an invoice, a price\n * list and a timesheet without learning about any of them.\n *\n * Focus lives on the cells themselves, with one tab stop that travels — the arrangement screen\n * readers expect from a grid. Pasting is the exception: a browser only dispatches `paste` to an\n * editable element, so the paste shortcut hands focus to an off-screen field for the length of\n * the event and takes it straight back.\n */\n@Component({\n\tselector: 'hub-spreadsheet',\n\tstandalone: true,\n\timports: [NgTemplateOutlet, TranslatePipe, HubSpreadsheetControlDirective],\n\tproviders: [{ provide: HUB_TRANSLATION_PREFIX, useValue: 'HUBUI.SPREADSHEET' }],\n\ttemplateUrl: './spreadsheet.component.html',\n\tstyleUrl: './spreadsheet.component.scss',\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\thost: {\n\t\t/*\n\t\t * The sheet draws itself from what it measures, so what a server writes and what a browser\n\t\t * then wants are two different documents — and hydration's job is to insist they are one.\n\t\t *\n\t\t * A virtualised sheet measures a viewport that does not exist on a server and draws every\n\t\t * row; the browser measures a real one and draws fifteen. A column that draws its own cells\n\t\t * needs its template, which a content query has not resolved on the first server pass. Both\n\t\t * come out as NG0500, and neither is a mistake to be fixed — it is what this component is.\n\t\t *\n\t\t * So the markup is re-created rather than adopted. The server's copy still ships in the\n\t\t * page, which is what a crawler reads; the browser simply builds its own.\n\t\t */\n\t\tngSkipHydration: 'true',\n\t\tclass: 'hub-spreadsheet',\n\t\t'[class.hub-spreadsheet--readonly]': 'readonly()',\n\t\t'[class.hub-spreadsheet--editing]': 'editing()',\n\t\t'[class.hub-spreadsheet--virtual]': 'virtual()',\n\t\t'(document:mouseup)': 'endDrag()',\n\t\t'(document:mousemove)': 'onPointerMove($event)',\n\t\t'(document:mousedown)': 'closeMenu()',\n\t\t'(document:keydown.escape)': 'closeMenu()'\n\t}\n})\nexport class HubSpreadsheetComponent<TRow> {\n\treadonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n\treadonly #injector = inject(Injector);\n\n\t/** The rows, as the owner holds them. Never written to. */\n\treadonly rows = input.required<readonly TRow[]>();\n\t/** What each column shows and allows. */\n\treadonly columns = input.required<readonly HubSpreadsheetColumn<TRow>[]>();\n\t/** A stable name per row, so a save state follows its row across a reload. */\n\treadonly rowKey = input.required<(row: TRow) => string>();\n\t/** The save state of each cell, keyed by `rowKey` and column alias joined by a tab. */\n\treadonly states = input<Record<string, HubSpreadsheetCellState>>({});\n\t/**\n\t * A validation message per cell, keyed the same way as {@link states}.\n\t *\n\t * Owned by the host, because validation belongs to whoever knows what the data means. Keeping\n\t * it a plain map rather than tying it to one forms API is what lets the same sheet be driven\n\t * by Signal Forms, by reactive forms, or by nothing at all.\n\t */\n\treadonly errors = input<Record<string, string>>({});\n\t/** The character this reader types decimals with. */\n\treadonly decimalMark = input<',' | '.'>(',');\n\t/** What an empty sheet says. */\n\treadonly emptyText = input('');\n\t/** How many rows Page Up and Page Down travel. */\n\treadonly pageSize = input(10);\n\t/** Turns off every editor, whatever the individual cells say. */\n\treadonly readonly = input(false, { transform: booleanAttribute });\n\t/**\n\t * How many columns stay pinned against the leading edge while the sheet scrolls sideways.\n\t *\n\t * Counted from the start, the way a spreadsheet freezes panes, rather than marked one by one:\n\t * a set of frozen columns with a gap in it cannot be laid out, so the shape of the input rules\n\t * the mistake out instead of validating against it.\n\t */\n\treadonly frozenColumns = input(0);\n\t/** How many rows stay pinned below the header while the sheet scrolls down. */\n\treadonly frozenRows = input(0);\n\t/**\n\t * Cells merged into blocks, each named by its top-left corner.\n\t *\n\t * Owned by the host, which is why they come in as an input and why the reader's merging goes\n\t * back out as a request rather than being done here — see {@link mergeable}. A declared block\n\t * is treated as one cell everywhere it matters: the cursor lands on the block rather than\n\t * inside it, a selection that would clip one grows to contain it, and the covered cells are\n\t * not drawn at all.\n\t */\n\treadonly spans = input<readonly HubGridSpan[]>([]);\n\t/** Which structural changes the reader may ask for. Everything is refused by default. */\n\treadonly structure = input<HubSpreadsheetStructureOptions<TRow>>({});\n\t/** Editors supplied by the host, one per column alias. */\n\tprotected readonly customEditors = contentChildren<HubSpreadsheetEditorDirective<TRow>>(HubSpreadsheetEditorDirective);\n\t/** Cell templates supplied by the host, for what a column shows while it is not being edited. */\n\tprotected readonly customCells = contentChildren<HubSpreadsheetCellDirective<TRow>>(HubSpreadsheetCellDirective);\n\n\t/** Aliases retired by earlier deletions, so a new column never reuses one. */\n\treadonly retiredColumnKeys = input<readonly string[]>([]);\n\t/** Whether the sheet offers the fill handle at the corner of the selection. */\n\treadonly fillHandle = input(false, { transform: booleanAttribute });\n\t/** Whether undo is available; the sheet only asks, the owner keeps the history. */\n\treadonly canUndo = input(false, { transform: booleanAttribute });\n\t/** Whether redo is available. */\n\treadonly canRedo = input(false, { transform: booleanAttribute });\n\t/** Whether a reader may drag a column's trailing edge to widen or narrow it. */\n\treadonly resizableColumns = input(false, { transform: booleanAttribute });\n\t/** Whether a reader may drag a header to put the column somewhere else. */\n\treadonly reorderableColumns = input(false, { transform: booleanAttribute });\n\t/**\n\t * The width of each column in pixels, keyed by alias.\n\t *\n\t * Two-way, and view state rather than data: the sheet writes it as the reader drags, and the\n\t * owner may persist it so a layout survives a reload. A column with no entry keeps whatever\n\t * width its content asks for.\n\t */\n\treadonly columnWidths = model<Record<string, number>>({});\n\t/** The narrowest a column may be dragged. */\n\treadonly minColumnWidth = input(48);\n\t/**\n\t * Whether a right-click offers the menu of structural changes.\n\t *\n\t * Off unless asked for, and each entry still has to pass `structure`. A menu that lists what\n\t * the reader is not allowed to do is worse than no menu.\n\t */\n\treadonly contextMenu = input(false, { transform: booleanAttribute });\n\t/**\n\t * Whether the reader may put cells together and take them apart again.\n\t *\n\t * Off unless asked for, like every other structural change: a sheet whose shape is part of the\n\t * document it belongs to should not be reshaped by a stray right-click. The blocks stay the\n\t * host's — the sheet reports what was asked for through {@link mergeRequested} and\n\t * {@link unmergeRequested} and writes nothing itself. Offered through the context menu, so it\n\t * needs {@link contextMenu} to be reachable with the pointer.\n\t */\n\treadonly mergeable = input(false, { transform: booleanAttribute });\n\t/**\n\t * Whether a cell whose value starts with `=` is a formula.\n\t *\n\t * Off unless asked for, and not as caution for its own sake: a column of text may perfectly\n\t * well hold `=1+1` as the thing somebody wrote, and a sheet that decides to do arithmetic on\n\t * it has lost the reader's data.\n\t *\n\t * Formulas read columns by their alias — `=[price] * [units]`, `=SUM([total:])` — never by a\n\t * coordinate, which is what the aliases were for: move a column, rename its header, and every\n\t * formula still means what it said.\n\t *\n\t * The cell shows the answer; the editor shows the formula, so it can be corrected rather than\n\t * retyped; and the clipboard carries what the cell holds, which is the formula.\n\t */\n\treadonly formulas = input(false, { transform: booleanAttribute });\n\t/**\n\t * Whether to draw only the rows the reader can see.\n\t *\n\t * Off unless asked for. A sheet of a few hundred rows is better off whole — every row is in the\n\t * document, so the browser's own find works, printing works, and nothing depends on a\n\t * measurement. Past a few thousand it stops being a choice: the first paint arrives late and\n\t * every keystroke pays for cells nobody is looking at.\n\t *\n\t * What it costs: the rows out of view are not in the document, so `Ctrl+F` and printing only\n\t * reach what is drawn, and the rows have to be of one height — see {@link rowHeight}.\n\t */\n\treadonly virtual = input(false, { transform: booleanAttribute });\n\t/**\n\t * How tall a row is, in pixels, when {@link virtual} is on.\n\t *\n\t * Nought means \"measure the first one drawn\", which is right whenever the rows are alike. Say\n\t * it outright for a sheet whose first row is not typical, or one that is built while hidden —\n\t * a tab that is not open measures every row as nought, and a window worked out from nought is\n\t * the whole sheet.\n\t */\n\treadonly rowHeight = input(0);\n\t/**\n\t * What opens the editor with the pointer.\n\t *\n\t * `double-click` by default, the spreadsheet convention: a click picks the cell and leaves its\n\t * value where it is. Selecting is the gesture a reader makes most — to copy, to look, to drag\n\t * out a range — and turning every one of them into an open field puts the value at the mercy\n\t * of the next keystroke. Typing is still the short way in: with the cell picked, the first\n\t * character opens the editor and lands in it, so nothing is lost by not opening on the click.\n\t *\n\t * `click` opens on the first one, for a sheet that exists to be typed into and where the two\n\t * gestures per cell are the tax.\n\t *\n\t * Either way the editor opens on release and only when the pointer did not travel, so\n\t * dragging out a range still works — and Shift-clicking still extends rather than edits.\n\t */\n\treadonly editOn = input<'click' | 'double-click'>('double-click');\n\n\t/** A cell took a new value. */\n\treadonly commit = output<HubSpreadsheetCommit<TRow>>();\n\t/** A block was pasted. */\n\treadonly pasted = output<HubSpreadsheetPaste<TRow>>();\n\t/** Delete was pressed over these cells, the editable ones of the selection. */\n\treadonly cleared = output<HubSpreadsheetCellRef<TRow>[]>();\n\t/** The selected rectangle changed; null when nothing is selected. */\n\treadonly selectionChange = output<HubGridRange | null>();\n\t/** The reader asked to add rows or columns. */\n\treadonly insertRequested = output<HubSpreadsheetInsertRequest>();\n\t/** The reader asked to remove rows or columns. */\n\treadonly deleteRequested = output<HubSpreadsheetDeleteRequest>();\n\t/**\n\t * A drag of the fill handle finished.\n\t *\n\t * Reported as one event for the whole gesture, so an owner keeping a history can make it one\n\t * undo step. Filling cell by cell and undoing cell by cell is experienced as a bug.\n\t */\n\treadonly filled = output<HubSpreadsheetPaste<TRow>>();\n\t/** The reader asked to undo. The owner holds the history and decides what that means. */\n\treadonly undoRequested = output<void>();\n\t/** The reader asked to redo. */\n\treadonly redoRequested = output<void>();\n\t/**\n\t * The reader dropped a column somewhere else.\n\t *\n\t * Reported rather than applied: the column list belongs to the owner, as the rows do. The\n\t * payload carries the reordered aliases so acting on it is a single assignment.\n\t */\n\treadonly columnMoved = output<{ from: number; to: number; key: string; keys: string[] }>();\n\t/**\n\t * The reader asked to put a selection together into one block.\n\t *\n\t * The payload carries the block to create and the anchors of the blocks it swallows, because a\n\t * host that merely appends the new one ends up with two claiming the same cell — and which of\n\t * them is drawn depends on the order they were declared in. `applySpanMerge()` does the whole\n\t * thing in a line.\n\t */\n\treadonly mergeRequested = output<HubSpreadsheetMergeRequest>();\n\t/** The reader asked to take apart the blocks their selection touches, named by their anchors. */\n\treadonly unmergeRequested = output<readonly HubGridCoords[]>();\n\n\t/** The cell the cursor is on. */\n\tprotected readonly active = signal<HubGridCoords | null>(null);\n\t/** The other corner of the selection; null when only the active cell is selected. */\n\tprotected readonly anchor = signal<HubGridCoords | null>(null);\n\tprotected readonly editing = signal(false);\n\tprotected readonly draft = signal('');\n\n\t/**\n\t * The control adapter, when the project registered one.\n\t *\n\t * Optional on purpose: without it the sheet draws its own native list, which is what makes the\n\t * library installable on its own.\n\t */\n\treadonly #controls = inject(HUB_SPREADSHEET_CONTROLS, { optional: true });\n\n\t/**\n\t * The character that opened the cell, when typing opened it.\n\t *\n\t * Kept beside the draft rather than inside it because a supplied editor needs it as it was\n\t * typed, while the draft has already been turned into whatever the column stores.\n\t */\n\tprivate readonly seed = signal<string | undefined>(undefined);\n\t/** The editor holds text that does not read as a value, so it stays open and marked. */\n\tprotected readonly invalid = signal(false);\n\tprivate dragging = false;\n\t/** Whether the pointer visited another cell during this press, which makes it a drag. */\n\tprivate dragMoved = false;\n\t/** The selection a fill drag started from; null when no fill is in progress. */\n\tprotected readonly fillSource = signal<HubGridRange | null>(null);\n\t/** What the fill would cover if released now. */\n\tprotected readonly fillTarget = signal<HubGridRange | null>(null);\n\t/** The column being widened, with where the pointer started and how wide it then was. */\n\tprivate resizing: { col: number; startX: number; startWidth: number } | null = null;\n\t/** The column being dragged to another place. */\n\tprotected readonly movingColumn = signal<number | null>(null);\n\t/** Where it would land if dropped now. */\n\tprotected readonly moveTargetColumn = signal<number | null>(null);\n\t/** Where the structural menu sits, in pixels from the sheet's own corner; null when closed. */\n\tprotected readonly menuAt = signal<{ x: number; y: number } | null>(null);\n\n\t/** Where each frozen column sits, in pixels from the leading edge. */\n\tprotected readonly columnOffsets = signal<readonly number[]>([]);\n\t/** Where each frozen row sits, in pixels from the top of the scroll area. */\n\tprotected readonly rowOffsets = signal<readonly number[]>([]);\n\n\t/** The merges, indexed once per change rather than scanned on every keystroke. */\n\tprotected readonly spanMap = computed(() => buildSpanMap(this.spans()));\n\n\tprotected readonly bounds = computed(() => ({\n\t\trows: this.rows().length,\n\t\tcols: this.columns().length\n\t}));\n\n\t/**\n\t * What the viewport has told us about itself: how far it has scrolled and how tall it is.\n\t *\n\t * Nought until the first measurement, which is why {@link gridWindow} draws a first screenful\n\t * from nothing rather than drawing nothing: the rows it puts in are what the measurement then\n\t * measures.\n\t */\n\tprivate readonly viewport = viewChild<ElementRef<HTMLElement>>('viewport');\n\n\tprivate readonly scrollTop = signal(0);\n\tprivate readonly viewportHeight = signal(0);\n\t/** The height of a row, measured off the first one drawn unless the host declared it. */\n\tprivate readonly measuredRowHeight = signal(0);\n\t/** How far the viewport has travelled sideways, and how much of it is on screen. */\n\tprivate readonly scrollLeft = signal(0);\n\tprivate readonly viewportWidth = signal(0);\n\t/** The width of every column, by index, as last measured. */\n\tprivate readonly measuredColumnWidths = signal<number[]>([]);\n\n\t/** The rows to draw: the frozen ones, then the window, or all of them when not virtualising. */\n\tprotected readonly rowWindow = computed<HubGridWindow>(() => {\n\t\tconst total = this.rows().length;\n\t\tconst frozen = Math.min(this.frozenRows(), total);\n\n\t\tif (!this.virtual()) {\n\t\t\treturn { start: frozen, end: total - 1, before: 0, after: 0 };\n\t\t}\n\n\t\t// Nothing measured and nothing declared, which is only ever the first frame: a rough height\n\t\t// rather than the whole sheet. Drawing it whole once is exactly the cost virtualising is\n\t\t// here to avoid — ten thousand rows took a minute and a half of it — and the measurement\n\t\t// that follows lands on the real height before anybody sees the difference.\n\t\tconst size = this.rowHeight() || this.measuredRowHeight() || FIRST_PASS_ROW_HEIGHT;\n\n\t\tconst window = gridWindow({\n\t\t\toffset: this.scrollTop(),\n\t\t\tviewport: this.viewportHeight(),\n\t\t\tsizes: size,\n\t\t\tcount: total,\n\t\t\tpinned: frozen\n\t\t});\n\n\t\treturn growWindowToSpans(window, this.spans(), 'row', size, { count: total, pinned: frozen });\n\t});\n\n\t/**\n\t * The columns to draw, the same way as the rows.\n\t *\n\t * Their widths are measured rather than declared, so the first render draws them all — there\n\t * is nothing to measure otherwise — and every render after that windows them with what the\n\t * first one learnt. A column the sheet has never drawn has no width, and one unknown width is\n\t * enough to fall back to drawing the lot: a window is only as honest as the sizes it is built\n\t * from.\n\t */\n\tprotected readonly columnWindow = computed<HubGridWindow>(() => {\n\t\tconst total = this.columns().length;\n\t\tconst frozen = Math.min(this.frozenColumns(), total);\n\t\tconst everything: HubGridWindow = { start: frozen, end: total - 1, before: 0, after: 0 };\n\n\t\tif (!this.virtual()) {\n\t\t\treturn everything;\n\t\t}\n\n\t\tconst widths = this.measuredColumnWidths();\n\n\t\tif (widths.length !== total || widths.some((width) => !(width > 0))) {\n\t\t\treturn everything;\n\t\t}\n\n\t\tconst window = gridWindow({\n\t\t\toffset: this.scrollLeft(),\n\t\t\tviewport: this.viewportWidth(),\n\t\t\tsizes: widths,\n\t\t\tpinned: frozen\n\t\t});\n\n\t\treturn growWindowToSpans(window, this.spans(), 'col', widths, { pinned: frozen });\n\t});\n\n\t/** The column indices in the document, frozen ones first. */\n\tprotected readonly drawnColumns = computed<number[]>(() => {\n\t\tconst total = this.columns().length;\n\t\tconst frozen = Math.min(this.frozenColumns(), total);\n\t\tconst window = this.columnWindow();\n\t\tconst drawn: number[] = [];\n\n\t\tfor (let index = 0; index < frozen; index++) {\n\t\t\tdrawn.push(index);\n\t\t}\n\n\t\tfor (let index = window.start; index <= window.end; index++) {\n\t\t\tdrawn.push(index);\n\t\t}\n\n\t\treturn drawn;\n\t});\n\n\t/**\n\t * How many cells a row of the sheet actually holds, spacers included.\n\t *\n\t * What a spacer row has to span. `bounds().cols` would be wrong whenever the columns are\n\t * windowed — it counts the columns the sheet has, not the ones in the document — and a colspan\n\t * that overshoots stretches the table wider than its own header.\n\t */\n\tprotected readonly drawnCellCount = computed(() => {\n\t\tconst window = this.columnWindow();\n\n\t\treturn this.drawnColumns().length + (window.before > 0 ? 1 : 0) + (window.after > 0 ? 1 : 0);\n\t});\n\n\t/** The row indices in the document, frozen ones first. */\n\tprotected readonly drawnRows = computed<number[]>(() => {\n\t\tconst total = this.rows().length;\n\t\tconst frozen = Math.min(this.frozenRows(), total);\n\t\tconst window = this.rowWindow();\n\t\tconst drawn: number[] = [];\n\n\t\tfor (let index = 0; index < frozen; index++) {\n\t\t\tdrawn.push(index);\n\t\t}\n\n\t\tfor (let index = window.start; index <= window.end; index++) {\n\t\t\tdrawn.push(index);\n\t\t}\n\n\t\treturn drawn;\n\t});\n\n\t/** Every cell, worked out once per change of rows or columns rather than on every paint. */\n\tprotected readonly grid = computed<HubSpreadsheetCell[][]>(() => {\n\t\tconst columns = this.columns();\n\t\tconst cells = this.rows().map((row) => columns.map((column) => column.cell(row)));\n\n\t\tif (!this.formulas()) {\n\t\t\treturn cells;\n\t\t}\n\n\t\tconst places = new Map(columns.map((column, index) => [column.key, index]));\n\t\tconst sheet = evaluateSheet({\n\t\t\trows: this.rows(),\n\t\t\tcolumns,\n\t\t\traw: (rowIndex, column) => cells[rowIndex]?.[places.get(column.key) ?? -1]?.value ?? null\n\t\t});\n\n\t\treturn cells.map((line, rowIndex) =>\n\t\t\tline.map((cell, colIndex) => {\n\t\t\t\tconst column = columns[colIndex];\n\n\t\t\t\t// Either the row holds a formula, or the column carries one for every row.\n\t\t\t\tif (!isFormula(cell.value) && !column.formula) {\n\t\t\t\t\treturn cell;\n\t\t\t\t}\n\n\t\t\t\tconst result = sheet[rowIndex]?.[column.key];\n\n\t\t\t\t// The value stays the formula: it is what the editor opens on and what the\n\t\t\t\t// clipboard carries. What changes is what the cell shows.\n\t\t\t\treturn {\n\t\t\t\t\t...cell,\n\t\t\t\t\ttext: result?.failure ? formulaErrorText(result.failure) : displayValue(result?.value ?? null, column)\n\t\t\t\t};\n\t\t\t})\n\t\t);\n\t});\n\n\t/** Which suggestion the keyboard is on, or -1 when the reader has not moved into the list. */\n\tprivate readonly suggestionAt = signal(-1);\n\n\t/**\n\t * What to offer while a formula is being written, or nothing when one is not.\n\t *\n\t * A formula names columns by an alias the sheet never shows — the header carries a title meant\n\t * for people — so without this, writing one means knowing something that is not on screen.\n\t */\n\tprotected readonly suggestions = computed<readonly HubFormulaSuggestion[]>(() => {\n\t\tif (!this.formulas() || !this.editing()) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst columns = this.columns();\n\n\t\treturn suggestFormula(this.draft(), {\n\t\t\taliases: columns.map((column) => column.key),\n\t\t\ttitles: Object.fromEntries(columns.map((column) => [column.key, column.header]))\n\t\t});\n\t});\n\n\t/** Whether the sheet is showing the list of what can go into a formula. */\n\tprotected readonly suggesting = computed(() => this.suggestions().length > 0);\n\n\t/**\n\t * The one the keyboard is on, which Enter and Tab put in.\n\t *\n\t * The first is taken as chosen the moment there is a word being typed, so `=SU` and Tab\n\t * finishes it — which is what completing means, and what a reader who has seen a spreadsheet\n\t * expects. Nothing is chosen when there is no word: a bare `=`, or a formula that has just\n\t * closed a bracket, is a list to look at rather than a completion to accept, and Enter there\n\t * means commit.\n\t */\n\tprotected readonly suggestionIndex = computed(() => {\n\t\tconst moved = this.suggestionAt();\n\n\t\tif (moved >= 0 && moved < this.suggestions().length) {\n\t\t\treturn moved;\n\t\t}\n\n\t\treturn formulaFragment(this.draft()).text && this.suggestions().length ? 0 : -1;\n\t});\n\n\t/** Whether a formula is being written, which is when the aliases are worth showing. */\n\tprotected readonly writingFormula = computed(() => this.formulas() && this.editing() && isFormula(this.draft()));\n\n\t/** The letters a column answers to in a formula: A, B … Z, AA. */\n\tprotected columnLetter(index: number): string {\n\t\treturn columnLabel(index);\n\t}\n\n\t/** Puts a suggestion into the draft and leaves the caret where the next thing is typed. */\n\tprotected useSuggestion(suggestion: HubFormulaSuggestion): void {\n\t\tconst editor = this.#host.nativeElement.querySelector<HTMLInputElement>('input.hub-spreadsheet__editor');\n\t\tconst caret = editor?.selectionStart ?? this.draft().length;\n\t\tconst applied = applySuggestion(this.draft(), suggestion, caret);\n\n\t\tthis.draft.set(applied.draft);\n\t\tthis.suggestionAt.set(-1);\n\n\t\tif (editor) {\n\t\t\teditor.value = applied.draft;\n\t\t\teditor.focus();\n\t\t\teditor.setSelectionRange(applied.caret, applied.caret);\n\t\t}\n\t}\n\n\t/** Whether a cell is showing a formula that could not be worked out. */\n\tprotected hasFormulaError(row: number, col: number): boolean {\n\t\tconst cell = this.grid()[row]?.[col];\n\n\t\tconst fromColumn = !!this.columns()[col]?.formula;\n\n\t\treturn !!cell && (isFormula(cell.value) || fromColumn) && FORMULA_ERRORS.includes(cell.text ?? '');\n\t}\n\n\tprotected readonly keys = computed(() => {\n\t\tconst keyOf = this.rowKey();\n\n\t\treturn this.rows().map((row) => keyOf(row));\n\t});\n\n\tprotected readonly range = computed<HubGridRange | null>(() => {\n\t\tconst active = this.active();\n\n\t\tif (!active) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst base = clampGridRange(gridRangeBetween(this.anchor() ?? active, active), this.bounds());\n\n\t\t// A range that clips a merge cannot be copied, filled or cleared coherently, so it grows\n\t\t// until every block it touches is inside it — which is what Excel does too.\n\t\treturn base ? clampGridRange(coversRange(this.spanMap(), base), this.bounds()) : null;\n\t});\n\n\t/**\n\t * Keeps the cursor where it was when the rows are replaced by a reload after a save, and drops\n\t * it only once it points at nothing. Typing a value and pressing Enter has to land on the cell\n\t * below even when the saved figures come back as fresh objects.\n\t */\n\tprivate readonly reconcile = effect(() => {\n\t\tconst { rows, cols } = this.bounds();\n\n\t\tuntracked(() => {\n\t\t\tconst active = this.active();\n\n\t\t\tif (active && (active.row >= rows || active.col >= cols)) {\n\t\t\t\tthis.active.set(null);\n\t\t\t\tthis.anchor.set(null);\n\t\t\t\tthis.editing.set(false);\n\t\t\t}\n\t\t});\n\t});\n\n\t/**\n\t * Keeps the viewport's measurements up to date while virtualising.\n\t *\n\t * In the read phase, like the frozen offsets: reading layout while the browser is writing one\n\t * forces a reflow in the middle of it, which is how a grid loses frames exactly when it is\n\t * being scrolled.\n\t *\n\t * It settles rather than loops. Measuring feeds the window, the window changes what is drawn,\n\t * and the next pass measures the same numbers — a signal set to the value it already holds\n\t * tells nobody, so the third pass does not happen. It reads `drawnRows` so that a sheet whose\n\t * data arrives later is measured when its first row finally exists, which is the common case\n\t * and the one a single measurement at birth gets wrong.\n\t */\n\tprivate readonly measureViewport = afterRenderEffect({\n\t\tread: () => {\n\t\t\tif (!this.virtual()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.drawnRows();\n\t\t\tthis.onViewportScroll();\n\t\t}\n\t});\n\n\t/**\n\t * The width of every column, read off the headers by the index they carry.\n\t *\n\t * By index and not by position, because a windowed header holds the frozen columns and then\n\t * the ones in view — so the third header in the document is rarely the third column. A width\n\t * that is not on screen keeps whatever was measured last, which is what makes windowing the\n\t * columns possible at all: they are measured once, while the sheet is still drawing them all.\n\t */\n\tprivate readColumnWidths(): number[] {\n\t\tconst total = this.columns().length;\n\t\tconst known = [...this.measuredColumnWidths()];\n\n\t\tknown.length = total;\n\n\t\tfor (const header of this.#host.nativeElement.querySelectorAll<HTMLElement>('.hub-spreadsheet__header')) {\n\t\t\tconst index = Number(header.getAttribute('data-header'));\n\t\t\tconst width = header.getBoundingClientRect().width;\n\n\t\t\tif (Number.isInteger(index) && index >= 0 && index < total && width > 0) {\n\t\t\t\tknown[index] = width;\n\t\t\t}\n\t\t}\n\n\t\tconst measured = Array.from(known, (width) => width ?? 0);\n\t\tconst previous = this.measuredColumnWidths();\n\n\t\t// Only when something actually moved. A fresh array is a fresh reference, and a reference\n\t\t// set after every render is a render after every render: the measurement feeds the window,\n\t\t// the window is drawn, and the drawing measures again for ever.\n\t\tif (measured.length !== previous.length || measured.some((width, index) => width !== previous[index])) {\n\t\t\tthis.measuredColumnWidths.set(measured);\n\t\t}\n\n\t\treturn measured;\n\t}\n\n\t/**\n\t * Measures the frozen tracks after every render and turns the sizes into offsets.\n\t *\n\t * Reading layout has to happen in the read phase or it forces a synchronous reflow in the\n\t * middle of writing one, which is the classic way a grid loses frames while scrolling.\n\t */\n\tprivate readonly measureFrozen = afterRenderEffect({\n\t\tread: () => {\n\t\t\tconst columns = this.frozenColumns();\n\t\t\tconst rows = this.frozenRows();\n\t\t\tconst widths = this.readColumnWidths();\n\n\t\t\tif (columns <= 0 && rows <= 0) {\n\t\t\t\tthis.columnOffsets.set([]);\n\t\t\t\tthis.rowOffsets.set([]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst host = this.#host.nativeElement;\n\t\t\tconst bodyRows = [...host.querySelectorAll<HTMLElement>('.hub-spreadsheet__row')];\n\n\t\t\tthis.columnOffsets.set(frozenOffsets(widths, columns));\n\n\t\t\t// Frozen rows start below the header, which is itself pinned at the top.\n\t\t\tconst headerHeight =\n\t\t\t\thost.querySelector<HTMLElement>('.hub-spreadsheet__header')?.getBoundingClientRect().height ?? 0;\n\n\t\t\tthis.rowOffsets.set(\n\t\t\t\tfrozenOffsets(\n\t\t\t\t\tbodyRows.map((row) => row.getBoundingClientRect().height),\n\t\t\t\t\trows\n\t\t\t\t).map((offset) => offset + Math.round(headerHeight))\n\t\t\t);\n\t\t}\n\t});\n\n\t/**\n\t * Whether a column is pinned.\n\t *\n\t * Answered from the input alone, never from the measurement. A cell is taken out of the flow\n\t * because the caller asked for it; the measured offset only decides where it lands. Gating\n\t * the two on the same signal would leave the pane unpinned for the frame before the first\n\t * measurement, and permanently unpinned anywhere the render hooks do not run.\n\t */\n\tprotected isFrozenColumn(col: number): boolean {\n\t\treturn col < Math.min(this.frozenColumns(), this.bounds().cols);\n\t}\n\n\t/** Whether a row is pinned. Same reasoning as {@link isFrozenColumn}. */\n\tprotected isFrozenRow(row: number): boolean {\n\t\treturn row < Math.min(this.frozenRows(), this.bounds().rows);\n\t}\n\n\t/** Where a frozen column sits, once measured; null until then, and the stylesheet pins it at zero. */\n\tprotected columnOffsetOf(col: number): number | null {\n\t\treturn this.isFrozenColumn(col) ? (this.columnOffsets()[col] ?? null) : null;\n\t}\n\n\t/** Where a frozen row sits, once measured. */\n\tprotected rowOffsetOf(row: number): number | null {\n\t\treturn this.isFrozenRow(row) ? (this.rowOffsets()[row] ?? null) : null;\n\t}\n\n\tprotected isColumnEdge(col: number): boolean {\n\t\treturn isFrozenEdge(col, Math.min(this.frozenColumns(), this.bounds().cols));\n\t}\n\n\tprotected isRowEdge(row: number): boolean {\n\t\treturn isFrozenEdge(row, Math.min(this.frozenRows(), this.bounds().rows));\n\t}\n\n\t/** Whether a cell is swallowed by a merge, and therefore not rendered. */\n\tprotected isHidden(row: number, col: number): boolean {\n\t\treturn isCovered(this.spanMap(), { row, col });\n\t}\n\n\t/** How many rows a cell occupies; null leaves the attribute off. */\n\tprotected rowSpanOf(row: number, col: number): number | null {\n\t\tconst span = spanAt(this.spanMap(), { row, col });\n\n\t\treturn span && span.rowSpan > 1 ? span.rowSpan : null;\n\t}\n\n\t/** How many columns a cell occupies; null leaves the attribute off. */\n\tprotected colSpanOf(row: number, col: number): number | null {\n\t\tconst span = spanAt(this.spanMap(), { row, col });\n\n\t\treturn span && span.colSpan > 1 ? span.colSpan : null;\n\t}\n\n\t/**\n\t * Whether a cell reaches the trailing edge of the sheet, counting the columns it spans.\n\t *\n\t * Asked rather than guessed with `:last-child`. Once cells can be swallowed by a merge, the\n\t * last one drawn in a row is not the one in the last column — in a row where the rightmost\n\t * block is covered it is the cell before it, and that is the one that would lose its border.\n\t */\n\tprotected reachesEnd(row: number, col: number): boolean {\n\t\tconst span = spanAt(this.spanMap(), { row, col });\n\n\t\treturn col + (span?.colSpan ?? 1) - 1 >= this.bounds().cols - 1;\n\t}\n\n\tprotected isActive(row: number, col: number): boolean {\n\t\tconst active = this.active();\n\n\t\treturn !!active && active.row === row && active.col === col;\n\t}\n\n\tprotected isSelected(row: number, col: number): boolean {\n\t\treturn isWithinGridRange({ row, col }, this.range());\n\t}\n\n\tprotected tabIndexOf(row: number, col: number): number {\n\t\treturn gridCellTabIndex({ row, col }, this.active(), 'roving');\n\t}\n\n\tprotected stateOf(row: number, col: number): HubSpreadsheetCellState | undefined {\n\t\treturn this.states()[this.cellKey(row, col)];\n\t}\n\n\t/** The validation message the host attached to a cell, if any. */\n\tprotected errorOf(row: number, col: number): string | undefined {\n\t\treturn this.errors()[this.cellKey(row, col)];\n\t}\n\n\t/** How a cell is addressed in the `states` and `errors` maps. */\n\tprivate cellKey(row: number, col: number): string {\n\t\treturn `${this.keys()[row]}\\t${this.columns()[col].key}`;\n\t}\n\n\t/**\n\t * What a cell shows: its own text when it gives one, otherwise whatever its column makes of\n\t * the value — an option's label, a mark for a yes, the value itself for everything else.\n\t */\n\tprotected displayOf(cell: HubSpreadsheetCell, column: HubSpreadsheetColumn<TRow>): string {\n\t\tif (cell.text !== undefined && cell.text !== null) {\n\t\t\treturn cell.text;\n\t\t}\n\n\t\treturn displayValue(cell.value, column);\n\t}\n\n\t/**\n\t * What a hosted control should be for this cell, or null when there is nothing to host.\n\t *\n\t * Null covers three cases and they are all deliberate: no adapter registered, a column that is\n\t * not a list, and a column whose host supplied its own editor — which is read first and wins,\n\t * because a template written for one column is a more specific answer than a rule for all of\n\t * them.\n\t */\n\tprotected hostedControl(row: number, col: number): HubSpreadsheetControlConfig | null {\n\t\tconst column = this.columns()[col];\n\n\t\tif (!this.#controls || this.editorFor(col) || !(column.kind === 'select' || column.options?.length)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tkind: 'select',\n\t\t\tvalue: this.grid()[row][col].value,\n\t\t\toptions: column.options?.map((option) => ({ ...option })),\n\t\t\tlabel: column.header,\n\t\t\tlabelType: 'visually-hidden',\n\t\t\tariaLabel: column.header,\n\t\t\tplaceholder: column.placeholder,\n\t\t\t// A cell is a search box's whole reason for being wired, it empties with `Delete`, and\n\t\t\t// the gesture that opened it has been spent by the time it exists.\n\t\t\tsearchable: true,\n\t\t\tclearable: false,\n\t\t\tautoOpen: true,\n\t\t\tsearchTerm: this.seed(),\n\t\t\tonValueChange: (value) => this.commitFromEditor(value as HubSpreadsheetValue)\n\t\t};\n\t}\n\n\t/**\n\t * Which answer a list shows while it is open.\n\t *\n\t * Read off the draft rather than off the cell, so a list opened by typing shows the answer that\n\t * keystroke reached. The draft holds the stored value until a keystroke moves it, so an\n\t * ordinary open still shows what the cell holds.\n\t */\n\tprotected isChosen(option: HubSpreadsheetOption, column: HubSpreadsheetColumn<TRow>): boolean {\n\t\treturn parseForColumn(this.draft(), column, this.decimalMark()) === option.value;\n\t}\n\n\t/** Whether a boolean cell is on, which is what draws its checkbox. */\n\tprotected isOn(cell: HubSpreadsheetCell): boolean {\n\t\treturn isTruthy(cell.value);\n\t}\n\n\t/**\n\t * What a cell should show to say it opens onto something, or null when it opens onto a field.\n\t *\n\t * Only drawn on the cell the reader is on. A caret down every row of a column would read as\n\t * content and make the sheet look like a form, and it is only ever the current cell that is\n\t * about to be opened.\n\t */\n\tprotected affordanceOf(column: HubSpreadsheetColumn<TRow>, col: number): 'list' | 'date' | null {\n\t\tif (column.kind === 'date') {\n\t\t\treturn 'date';\n\t\t}\n\n\t\t// A column with a supplied editor counts as a list: that hook exists for pickers, and the\n\t\t// sheet cannot see inside the template to know which kind it is.\n\t\treturn column.kind === 'select' || column.options?.length || this.editorFor(col) ? 'list' : null;\n\t}\n\n\t/** The template this column's editor should use, if the host supplied one. */\n\tprotected editorFor(col: number): HubSpreadsheetEditorDirective<TRow> | undefined {\n\t\tconst key = this.columns()[col]?.key;\n\n\t\treturn this.customEditors().find((editor) => editor.column() === key);\n\t}\n\n\t/** The template this column draws its cells with, if the host supplied one. */\n\tprotected cellTemplateFor(col: number): HubSpreadsheetCellDirective<TRow> | undefined {\n\t\tconst key = this.columns()[col]?.key;\n\n\t\treturn this.customCells().find((template) => template.column() === key);\n\t}\n\n\t/** The context a cell template is rendered with. */\n\tprotected cellContext(row: number, col: number): HubSpreadsheetCellContext<TRow> {\n\t\tconst cell = this.grid()[row][col];\n\n\t\treturn {\n\t\t\t$implicit: cell.value,\n\t\t\tcell,\n\t\t\trow: this.rows()[row],\n\t\t\tcolumn: this.columns()[col],\n\t\t\tactive: this.isActive(row, col)\n\t\t};\n\t}\n\n\t/** The context a custom editor template is rendered with. */\n\tprotected editorContext(row: number, col: number): HubSpreadsheetEditorContext<TRow> {\n\t\tconst cell = this.grid()[row][col];\n\n\t\treturn {\n\t\t\t$implicit: cell.value,\n\t\t\tseed: this.seed(),\n\t\t\tcell,\n\t\t\trow: this.rows()[row],\n\t\t\tcolumn: this.columns()[col],\n\t\t\tcommit: (value: HubSpreadsheetValue) => this.commitFromEditor(value),\n\t\t\tcancel: () => this.cancelEdit()\n\t\t};\n\t}\n\n\t/** Accepts a value a custom editor or a built-in list reported, and moves on as Enter would. */\n\tprotected commitFromEditor(value: HubSpreadsheetValue): void {\n\t\tconst active = this.active();\n\n\t\tif (!active) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst column = this.columns()[active.col];\n\t\tconst cell = this.grid()[active.row][active.col];\n\n\t\tthis.editing.set(false);\n\t\tthis.invalid.set(false);\n\n\t\tif (value !== cell.value) {\n\t\t\tthis.commit.emit({ coords: active, row: this.rows()[active.row], column, cell, value });\n\t\t}\n\n\t\tthis.moveTo(moveGridFocus(active, { row: 1, col: 0 }, this.bounds(), { horizontal: 'continuous' }), false);\n\t}\n\n\t/**\n\t * Turns a boolean cell over without opening an editor.\n\t *\n\t * A checkbox that needs opening, ticking and confirming is three gestures for one bit. The\n\t * keyboard reaches it the same way, since a printable character on such a column toggles too.\n\t */\n\tprotected toggleBoolean(row: number, col: number): void {\n\t\tif (!this.canEdit(row, col)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst cell = this.grid()[row][col];\n\t\tconst column = this.columns()[col];\n\n\t\tthis.commit.emit({\n\t\t\tcoords: { row, col },\n\t\t\trow: this.rows()[row],\n\t\t\tcolumn,\n\t\t\tcell,\n\t\t\tvalue: isTruthy(cell.value) ? 0 : 1\n\t\t});\n\t}\n\n\tprotected canEdit(row: number, col: number): boolean {\n\t\t// A column with a formula of its own has nothing to type into: the cell shows what the\n\t\t// column works out, and letting a reader replace it would lose the formula for that row\n\t\t// alone, which is the sort of thing nobody notices until the totals stop adding up.\n\t\tif (this.formulas() && this.columns()[col]?.formula) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn !this.readonly() && !!this.grid()[row]?.[col]?.editable;\n\t}\n\n\tprotected onKeydown(event: KeyboardEvent): void {\n\t\tconst active = this.active();\n\n\t\tif (!active) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editing()) {\n\t\t\tthis.catchUp(event);\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst intent = resolveGridIntent(event, {\n\t\t\tpageSize: this.pageSize(),\n\t\t\teditable: !this.readonly()\n\t\t});\n\n\t\tif (!intent) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Copy and cut ride the browser's own events, which carry the clipboard. Paste needs the\n\t\t// focus moved to something editable first, or the event is never dispatched at all.\n\t\tif (intent.kind === 'copy' || intent.kind === 'cut') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (intent.kind === 'paste') {\n\t\t\tthis.focusSink();\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\n\t\tswitch (intent.kind) {\n\t\t\tcase 'move':\n\t\t\t\tthis.moveTo(moveGridFocus(active, intent.delta, this.bounds(), { horizontal: 'continuous' }), intent.extend);\n\t\t\t\tbreak;\n\t\t\tcase 'edge':\n\t\t\t\tthis.moveTo(resolveGridEdge(active, intent.edge, this.bounds()), intent.extend);\n\t\t\t\tbreak;\n\t\t\tcase 'edit':\n\t\t\t\tthis.startEdit(intent.seed);\n\t\t\t\tbreak;\n\t\t\tcase 'clear':\n\t\t\t\tthis.announceCleared();\n\t\t\t\tbreak;\n\t\t\tcase 'cancel':\n\t\t\t\tthis.anchor.set(null);\n\t\t\t\tthis.announceSelection();\n\t\t\t\tbreak;\n\t\t\tcase 'select-all':\n\t\t\t\tthis.selectRange({ top: 0, bottom: this.bounds().rows - 1, left: 0, right: this.bounds().cols - 1 });\n\t\t\t\tbreak;\n\t\t\tcase 'select-row':\n\t\t\t\tthis.selectRange({ top: active.row, bottom: active.row, left: 0, right: this.bounds().cols - 1 });\n\t\t\t\tbreak;\n\t\t\tcase 'select-col':\n\t\t\t\tthis.selectRange({ top: 0, bottom: this.bounds().rows - 1, left: active.col, right: active.col });\n\t\t\t\tbreak;\n\t\t\tcase 'undo':\n\t\t\t\tif (this.canUndo()) {\n\t\t\t\t\tthis.undoRequested.emit();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tcase 'redo':\n\t\t\t\tif (this.canRedo()) {\n\t\t\t\t\tthis.redoRequested.emit();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprotected onMouseDown(event: MouseEvent, row: number, col: number): void {\n\t\tif (event.button !== 0 || (this.editing() && this.isActive(row, col))) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.editing()) {\n\t\t\tthis.finishEdit(null);\n\t\t}\n\n\t\tthis.dragging = true;\n\t\tthis.dragMoved = false;\n\t\tthis.moveTo({ row, col }, event.shiftKey);\n\t}\n\n\t/**\n\t * Opens the editor on release, not on press.\n\t *\n\t * Pressing would settle the question too early: a press that turns into a drag is a range\n\t * selection, and one that does not is a request to type. Waiting for the release is what lets\n\t * both gestures start the same way.\n\t */\n\tprotected onMouseUp(event: MouseEvent, row: number, col: number): void {\n\t\tif (\n\t\t\tevent.button !== 0 ||\n\t\t\tevent.shiftKey ||\n\t\t\tthis.dragMoved ||\n\t\t\tthis.editing() ||\n\t\t\tthis.editOn() !== 'click' ||\n\t\t\t!this.isActive(row, col)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.startEdit(undefined);\n\t}\n\n\tprotected onMouseEnter(row: number, col: number): void {\n\t\tif (this.dragging && !this.isActive(row, col)) {\n\t\t\tthis.dragMoved = true;\n\t\t}\n\n\t\tif (this.fillSource()) {\n\t\t\tthis.trackFill(row, col);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.dragging && !this.isActive(row, col)) {\n\t\t\tthis.moveTo({ row, col }, true);\n\t\t}\n\t}\n\n\t/** The width a column has been dragged to, or null while it sizes itself to its content. */\n\tprotected widthOf(col: number): number | null {\n\t\treturn this.columnWidths()[this.columns()[col].key] ?? null;\n\t}\n\n\tprotected onResizeStart(event: MouseEvent, col: number): void {\n\t\tif (event.button !== 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The grip lives inside the header; without this the header would also start a reorder.\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tconst header = this.#host.nativeElement.querySelector<HTMLElement>(`[data-header=\"${col}\"]`);\n\n\t\tthis.resizing = {\n\t\t\tcol,\n\t\t\tstartX: event.clientX,\n\t\t\tstartWidth: header?.getBoundingClientRect().width ?? Number.NaN\n\t\t};\n\t}\n\n\tprotected onHeaderMouseDown(event: MouseEvent, col: number): void {\n\t\tif (event.button !== 0 || !this.reorderableColumns()) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tthis.movingColumn.set(col);\n\t\tthis.moveTargetColumn.set(col);\n\t}\n\n\tprotected onHeaderMouseEnter(col: number): void {\n\t\tif (this.movingColumn() !== null) {\n\t\t\tthis.moveTargetColumn.set(col);\n\t\t}\n\t}\n\n\t/** Runs for every pointer move while something is being dragged, and only then. */\n\tprotected onPointerMove(event: MouseEvent): void {\n\t\tconst resizing = this.resizing;\n\n\t\tif (!resizing) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst width = resolveColumnWidth(resizing.startWidth, event.clientX - resizing.startX, this.minColumnWidth());\n\n\t\tif (width === null) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst key = this.columns()[resizing.col]?.key;\n\n\t\tif (key) {\n\t\t\tthis.columnWidths.update((widths) => ({ ...widths, [key]: width }));\n\t\t}\n\t}\n\n\tprotected endDrag(): void {\n\t\tthis.dragging = false;\n\t\tthis.resizing = null;\n\t\tthis.commitColumnMove();\n\n\t\tif (this.fillSource()) {\n\t\t\tthis.commitFill();\n\t\t}\n\t}\n\n\tprotected onContextMenu(event: MouseEvent, row: number, col: number): void {\n\t\tif (!this.contextMenu()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// A right-click on a cell outside the selection moves the cursor there first, as a\n\t\t// spreadsheet does: acting on cells the reader cannot see selected is how rows get\n\t\t// deleted that should not have been.\n\t\tif (!this.isSelected(row, col)) {\n\t\t\tthis.moveTo({ row, col }, false);\n\t\t}\n\n\t\tif (!this.menuEntries().length) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\n\t\tconst host = this.#host.nativeElement.getBoundingClientRect();\n\n\t\tthis.menuAt.set({ x: event.clientX - host.left, y: event.clientY - host.top });\n\t}\n\n\tprotected closeMenu(): void {\n\t\tthis.menuAt.set(null);\n\t}\n\n\t/**\n\t * What the menu offers here, already filtered by what is allowed.\n\t *\n\t * Built rather than rendered-and-hidden so the menu is never opened empty, and so no entry\n\t * appears that would do nothing when clicked.\n\t */\n\tprotected readonly menuEntries = computed<Array<{ id: string; label: string; count: number }>>(() => {\n\t\tconst range = this.range();\n\n\t\tif (!range || this.readonly()) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst rows = this.rows();\n\t\tconst columns = this.columns();\n\t\tconst structure = this.structure();\n\t\tconst entries: Array<{ id: string; label: string; count: number }> = [];\n\t\tconst rowCount = range.bottom - range.top + 1;\n\t\tconst colCount = range.right - range.left + 1;\n\n\t\tif (isStructureAllowed(structure.insertRows, rows[range.top] ?? null, range.top)) {\n\t\t\tentries.push({ id: 'row-before', label: 'INSERT_ROW_ABOVE', count: 1 });\n\t\t\tentries.push({ id: 'row-after', label: 'INSERT_ROW_BELOW', count: 1 });\n\t\t}\n\n\t\tif (this.allRows(range, (row, index) => isStructureAllowed(structure.deleteRows, row, index))) {\n\t\t\tentries.push({ id: 'row-delete', label: 'DELETE_ROWS', count: rowCount });\n\t\t}\n\n\t\tif (isStructureAllowed(structure.insertColumns, columns[range.left] ?? null, range.left)) {\n\t\t\tentries.push({ id: 'col-before', label: 'INSERT_COLUMN_BEFORE', count: 1 });\n\t\t\tentries.push({ id: 'col-after', label: 'INSERT_COLUMN_AFTER', count: 1 });\n\t\t}\n\n\t\tif (this.allColumns(range, (column, index) => isStructureAllowed(structure.deleteColumns, column, index))) {\n\t\t\tentries.push({ id: 'col-delete', label: 'DELETE_COLUMNS', count: colCount });\n\t\t}\n\n\t\tif (this.mergeable()) {\n\t\t\t// The selection has already grown to contain whole blocks, so what it asks for is one\n\t\t\t// rectangle and the arithmetic has nothing left to guess.\n\t\t\tif (mergeRequestFor(this.spans(), range)) {\n\t\t\t\tentries.push({ id: 'merge', label: 'MERGE_CELLS', count: rowCount * colCount });\n\t\t\t}\n\n\t\t\tconst touched = spansWithin(this.spans(), range);\n\n\t\t\tif (touched.length) {\n\t\t\t\tentries.push({ id: 'unmerge', label: 'UNMERGE_CELLS', count: touched.length });\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t});\n\n\tprotected runMenuEntry(id: string): void {\n\t\tthis.closeMenu();\n\n\t\tswitch (id) {\n\t\t\tcase 'row-before':\n\t\t\t\tthis.requestInsertRow('before');\n\t\t\t\tbreak;\n\t\t\tcase 'row-after':\n\t\t\t\tthis.requestInsertRow('after');\n\t\t\t\tbreak;\n\t\t\tcase 'row-delete':\n\t\t\t\tthis.requestDeleteRows();\n\t\t\t\tbreak;\n\t\t\tcase 'col-before':\n\t\t\t\tthis.requestInsertColumn('before');\n\t\t\t\tbreak;\n\t\t\tcase 'col-after':\n\t\t\t\tthis.requestInsertColumn('after');\n\t\t\t\tbreak;\n\t\t\tcase 'col-delete':\n\t\t\t\tthis.requestDeleteColumns();\n\t\t\t\tbreak;\n\t\t\tcase 'merge':\n\t\t\t\tthis.requestMerge();\n\t\t\t\tbreak;\n\t\t\tcase 'unmerge':\n\t\t\t\tthis.requestUnmerge();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/** Reports the block the selection would become, with what it swallows. */\n\tprivate requestMerge(): void {\n\t\tconst range = this.range();\n\t\tconst request = range && mergeRequestFor(this.spans(), range);\n\n\t\tif (request) {\n\t\t\tthis.mergeRequested.emit(request);\n\t\t}\n\t}\n\n\t/** Reports the blocks the selection touches, so the host can take them apart. */\n\tprivate requestUnmerge(): void {\n\t\tconst range = this.range();\n\n\t\tif (!range) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst anchors = spansWithin(this.spans(), range).map((span) => ({ row: span.row, col: span.col }));\n\n\t\tif (anchors.length) {\n\t\t\tthis.unmergeRequested.emit(anchors);\n\t\t}\n\t}\n\n\tprivate allRows(range: HubGridRange, allowed: (row: TRow, index: number) => boolean): boolean {\n\t\tconst rows = this.rows();\n\n\t\tfor (let index = range.top; index <= range.bottom; index++) {\n\t\t\tif (!allowed(rows[index], index)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate allColumns(range: HubGridRange, allowed: (column: HubSpreadsheetColumn<TRow>, index: number) => boolean): boolean {\n\t\tconst columns = this.columns();\n\n\t\tfor (let index = range.left; index <= range.right; index++) {\n\t\t\tif (!allowed(columns[index], index)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Reads the viewport after it has scrolled, or been resized, or drawn its first rows.\n\t *\n\t * Signals rather than a stored geometry, so the window is a computed like everything else and\n\t * nothing has to remember to recompute it. The row height is measured from the first row in\n\t * the document, which is also the only row that is certainly there.\n\t */\n\tprotected onViewportScroll(): void {\n\t\tconst viewport = this.viewport()?.nativeElement;\n\n\t\tif (!viewport) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollTop.set(viewport.scrollTop);\n\t\tthis.viewportHeight.set(viewport.clientHeight);\n\t\tthis.scrollLeft.set(viewport.scrollLeft);\n\t\tthis.viewportWidth.set(viewport.clientWidth);\n\n\t\tif (!this.rowHeight()) {\n\t\t\tconst row = viewport.querySelector<HTMLElement>('.hub-spreadsheet__row');\n\t\t\tconst height = row?.getBoundingClientRect().height ?? 0;\n\n\t\t\t// A row of nought is a sheet that has not been laid out — a closed tab, a hidden\n\t\t\t// panel. Keeping the last good measurement is better than throwing the window away.\n\t\t\tif (height > 0) {\n\t\t\t\tthis.measuredRowHeight.set(height);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Reports where a dragged column was dropped, if it moved at all. */\n\tprivate commitColumnMove(): void {\n\t\tconst from = this.movingColumn();\n\t\tconst to = this.moveTargetColumn();\n\n\t\tthis.movingColumn.set(null);\n\t\tthis.moveTargetColumn.set(null);\n\n\t\tif (from === null || to === null || from === to) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst keys = this.columns().map((column) => column.key);\n\n\t\tthis.columnMoved.emit({ from, to, key: keys[from], keys: moveColumn(keys, from, to) });\n\t}\n\n\t/** Whether a header is the one being dragged, or the place it would land. */\n\tprotected isMovingColumn(col: number): boolean {\n\t\treturn this.movingColumn() === col;\n\t}\n\n\tprotected isMoveTarget(col: number): boolean {\n\t\treturn this.movingColumn() !== null && this.moveTargetColumn() === col && this.movingColumn() !== col;\n\t}\n\n\t/** Whether the fill handle belongs on this cell: the far corner of the selection. */\n\tprotected hasFillHandle(row: number, col: number): boolean {\n\t\tconst range = this.range();\n\n\t\treturn this.fillHandle() && !this.readonly() && !!range && row === range.bottom && col === range.right;\n\t}\n\n\t/** Whether a cell is inside the area a released fill would write to. */\n\tprotected isFillPreview(row: number, col: number): boolean {\n\t\tconst target = this.fillTarget();\n\n\t\treturn !!target && isWithinGridRange({ row, col }, target) && !isWithinGridRange({ row, col }, this.range());\n\t}\n\n\tprotected onFillHandleDown(event: MouseEvent): void {\n\t\tif (event.button !== 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Stops the cell underneath from treating this as the start of a new selection.\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tconst range = this.range();\n\n\t\tif (range) {\n\t\t\tthis.fillSource.set(range);\n\t\t\tthis.fillTarget.set(range);\n\t\t}\n\t}\n\n\t/** Grows the preview towards wherever the pointer went, on one axis only. */\n\tprivate trackFill(row: number, col: number): void {\n\t\tconst source = this.fillSource();\n\n\t\tif (!source) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst down = Math.max(0, row - source.bottom);\n\t\tconst right = Math.max(0, col - source.right);\n\n\t\t// One axis at a time, as a spreadsheet does: a diagonal drag would have to invent a rule\n\t\t// for the corner it opens up, and any rule there surprises somebody.\n\t\tthis.fillTarget.set(\n\t\t\tdown >= right\n\t\t\t\t? { ...source, bottom: Math.max(source.bottom, row) }\n\t\t\t\t: { ...source, right: Math.max(source.right, col) }\n\t\t);\n\t}\n\n\t/** Works out what the finished drag writes, reports it, and leaves the selection covering it. */\n\tprivate commitFill(): void {\n\t\tconst source = this.fillSource();\n\t\tconst target = this.fillTarget();\n\n\t\tthis.fillSource.set(null);\n\t\tthis.fillTarget.set(null);\n\n\t\tif (!source || !target) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst grid = this.grid();\n\t\tconst rows = this.rows();\n\t\tconst columns = this.columns();\n\t\tconst cells: HubSpreadsheetCommit<TRow>[] = [];\n\t\tlet skipped = 0;\n\n\t\tconst down = target.bottom - source.bottom;\n\t\tconst across = target.right - source.right;\n\n\t\tconst write = (row: number, col: number, value: HubSpreadsheetValue) => {\n\t\t\tconst cell = grid[row]?.[col];\n\n\t\t\tif (!cell?.editable) {\n\t\t\t\tskipped++;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (value !== cell.value) {\n\t\t\t\tcells.push({ coords: { row, col }, row: rows[row], column: columns[col], cell, value });\n\t\t\t}\n\t\t};\n\n\t\tif (down > 0) {\n\t\t\tfor (let col = source.left; col <= source.right; col++) {\n\t\t\t\tconst seed: HubSpreadsheetValue[] = [];\n\n\t\t\t\tfor (let row = source.top; row <= source.bottom; row++) {\n\t\t\t\t\tseed.push(grid[row][col].value);\n\t\t\t\t}\n\n\t\t\t\tfillValues(seed, down).forEach((value, offset) => write(source.bottom + 1 + offset, col, value));\n\t\t\t}\n\t\t} else if (across > 0) {\n\t\t\tfor (let row = source.top; row <= source.bottom; row++) {\n\t\t\t\tconst seed: HubSpreadsheetValue[] = [];\n\n\t\t\t\tfor (let col = source.left; col <= source.right; col++) {\n\t\t\t\t\tseed.push(grid[row][col].value);\n\t\t\t\t}\n\n\t\t\t\tfillValues(seed, across).forEach((value, offset) => write(row, source.right + 1 + offset, value));\n\t\t\t}\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.anchor.set({ row: target.top, col: target.left });\n\t\tthis.active.set({ row: target.bottom, col: target.right });\n\t\tthis.filled.emit({ cells, range: target, skipped, rejected: 0 });\n\t\tthis.announceSelection();\n\t}\n\n\t/**\n\t * Opens the cell from its own mark, on the first click.\n\t *\n\t * The mark exists to be pressed, so it does not wait for a second click the way the rest of the\n\t * cell does — which is what a spreadsheet does with the list of a cell that has one. The press\n\t * is swallowed rather than let through: the cell underneath would otherwise start a range drag,\n\t * and the release would land on an editor that was not there when the press began.\n\t */\n\tprotected onAffordanceDown(event: MouseEvent, row: number, col: number): void {\n\t\tif (event.button !== 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tthis.moveTo({ row, col }, false);\n\t\tthis.startEdit(undefined);\n\t}\n\n\tprotected onDoubleClick(): void {\n\t\tthis.startEdit(undefined);\n\t}\n\n\tprotected onCopy(event: ClipboardEvent, cut: boolean): void {\n\t\tconst range = this.range();\n\n\t\tif (!range || this.editing() || !event.clipboardData) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst grid = this.grid();\n\t\tconst values = [];\n\n\t\tfor (let row = range.top; row <= range.bottom; row++) {\n\t\t\tconst line: HubSpreadsheetValue[] = [];\n\n\t\t\tfor (let col = range.left; col <= range.right; col++) {\n\t\t\t\tline.push(grid[row][col].value);\n\t\t\t}\n\n\t\t\tvalues.push(line);\n\t\t}\n\n\t\tconst { text, html } = serialiseClipboardTable(values);\n\n\t\tevent.clipboardData.setData('text/plain', text);\n\t\tevent.clipboardData.setData('text/html', html);\n\t\tevent.preventDefault();\n\n\t\tif (cut) {\n\t\t\tthis.announceCleared();\n\t\t}\n\t}\n\n\tprotected onPaste(event: ClipboardEvent): void {\n\t\tconst active = this.active();\n\n\t\tif (!active || this.editing() || !event.clipboardData) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\n\t\tconst block = parseClipboardTable({\n\t\t\ttext: event.clipboardData.getData('text/plain'),\n\t\t\thtml: event.clipboardData.getData('text/html')\n\t\t});\n\n\t\tthis.focusActive();\n\n\t\tif (!block.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.applyPaste(active, block);\n\t}\n\n\t/** Asks the owner to add a row beside the cursor, if it allows it. */\n\tprotected requestInsertRow(side: 'before' | 'after'): void {\n\t\tconst active = this.active();\n\t\tconst rows = this.rows();\n\t\tconst subject = active ? (rows[active.row] ?? null) : null;\n\n\t\tif (!isStructureAllowed(this.structure().insertRows, subject, active?.row ?? 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.insertRequested.emit({\n\t\t\taxis: 'row',\n\t\t\tat: resolveInsertIndex(active?.row ?? rows.length, side, rows.length),\n\t\t\tcount: 1\n\t\t});\n\t}\n\n\t/** Asks the owner to remove the rows the selection covers, if it allows it. */\n\tprotected requestDeleteRows(): void {\n\t\tconst range = this.range();\n\t\tconst rows = this.rows();\n\n\t\tif (!range) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let row = range.top; row <= range.bottom; row++) {\n\t\t\tif (!isStructureAllowed(this.structure().deleteRows, rows[row], row)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.deleteRequested.emit({ axis: 'row', at: range.top, count: range.bottom - range.top + 1 });\n\t}\n\n\t/** Asks the owner to add a column, handing over an alias that has never been used here. */\n\tprotected requestInsertColumn(side: 'before' | 'after'): void {\n\t\tconst active = this.active();\n\t\tconst columns = this.columns();\n\t\tconst subject = active ? (columns[active.col] ?? null) : null;\n\n\t\tif (!isStructureAllowed(this.structure().insertColumns, subject, active?.col ?? 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.insertRequested.emit({\n\t\t\taxis: 'column',\n\t\t\tat: resolveInsertIndex(active?.col ?? columns.length, side, columns.length),\n\t\t\tcount: 1,\n\t\t\tkey: nextColumnKey([...columns.map((column) => column.key), ...this.retiredColumnKeys()])\n\t\t});\n\t}\n\n\t/** Asks the owner to remove the columns the selection covers, naming the aliases at stake. */\n\tprotected requestDeleteColumns(): void {\n\t\tconst range = this.range();\n\t\tconst columns = this.columns();\n\n\t\tif (!range) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let col = range.left; col <= range.right; col++) {\n\t\t\tif (!isStructureAllowed(this.structure().deleteColumns, columns[col], col)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tthis.deleteRequested.emit({\n\t\t\taxis: 'column',\n\t\t\tat: range.left,\n\t\t\tcount: range.right - range.left + 1,\n\t\t\tkeys: columns.slice(range.left, range.right + 1).map((column) => column.key)\n\t\t});\n\t}\n\n\tprotected onDraftInput(event: Event): void {\n\t\t// A keystroke changes what is being offered, so whatever was highlighted is no longer the\n\t\t// thing the reader was looking at.\n\t\tthis.suggestionAt.set(-1);\n\n\t\tthis.draft.set((event.target as HTMLInputElement).value);\n\t\tthis.invalid.set(false);\n\t}\n\n\tprotected onEditorKeydown(event: KeyboardEvent): void {\n\t\t// A composition is in flight: the Enter that picks a candidate is not the Enter that\n\t\t// commits the cell.\n\t\tif (event.isComposing || event.keyCode === 229) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.onSuggestionKeydown(event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (event.key) {\n\t\t\t// Stopped as well as prevented, all three of them. The editor sits inside the grid, so\n\t\t\t// the same keystroke reaches the grid's own handler a moment later — and there it\n\t\t\t// reads as a fresh Enter on the cell below, which opened an editor the reader never\n\t\t\t// asked for on every single commit.\n\t\t\tcase 'Enter':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tthis.finishEdit({ row: event.shiftKey ? -1 : 1, col: 0 });\n\t\t\t\tbreak;\n\t\t\tcase 'Tab':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tthis.finishEdit({ row: 0, col: event.shiftKey ? -1 : 1 });\n\t\t\t\tbreak;\n\t\t\tcase 'Escape':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tthis.cancelEdit();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * The list of suggestions takes the arrows, and takes Enter only once the reader is in it.\n\t *\n\t * Enter is the awkward one: it both accepts a suggestion and commits a cell, and which of the\n\t * two it means depends on whether the reader has moved into the list. Moving into it is\n\t * deliberate — an arrow key — so somebody who types a whole formula and presses Enter commits\n\t * it, which is what they meant.\n\t *\n\t * @returns Whether the key was the list's, and the editor should leave it alone.\n\t */\n\tprivate onSuggestionKeydown(event: KeyboardEvent): boolean {\n\t\tconst suggestions = this.suggestions();\n\n\t\tif (!suggestions.length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst index = this.suggestionIndex();\n\n\t\tswitch (event.key) {\n\t\t\tcase 'ArrowDown':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tthis.suggestionAt.set((index + 1) % suggestions.length);\n\n\t\t\t\treturn true;\n\n\t\t\tcase 'ArrowUp':\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tthis.suggestionAt.set(index <= 0 ? suggestions.length - 1 : index - 1);\n\n\t\t\t\treturn true;\n\n\t\t\tcase 'Tab':\n\t\t\tcase 'Enter':\n\t\t\t\tif (index < 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tthis.useSuggestion(suggestions[index]);\n\n\t\t\t\treturn true;\n\n\t\t\tcase 'Escape':\n\t\t\t\t// Out of the list, not out of the cell: a reader dismissing a list of suggestions\n\t\t\t\t// has not asked to throw away what they were writing.\n\t\t\t\tif (index >= 0) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tthis.suggestionAt.set(-1);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/** Leaving the editor keeps what was typed, as clicking away does in a spreadsheet. */\n\tprotected onEditorBlur(): void {\n\t\tif (this.editing() && !this.finishEdit(null)) {\n\t\t\tthis.cancelEdit();\n\t\t}\n\t}\n\n\tprotected trackRow = (index: number): string => this.keys()[index] ?? String(index);\n\n\tprotected trackColumn = (_index: number, column: HubSpreadsheetColumn<TRow>): string => column.key;\n\n\t/** Writes a pasted block into the sheet and reports what fitted and what did not. */\n\tprivate applyPaste(at: HubGridCoords, block: HubClipboardCell[][]): void {\n\t\tconst rows = this.rows();\n\t\tconst columns = this.columns();\n\t\tconst grid = this.grid();\n\t\tconst cells: HubSpreadsheetCommit<TRow>[] = [];\n\t\tlet skipped = 0;\n\t\tlet rejected = 0;\n\n\t\tblock.forEach((line, rowOffset) =>\n\t\t\tline.forEach((incoming, colOffset) => {\n\t\t\t\tconst row = at.row + rowOffset;\n\t\t\t\tconst col = at.col + colOffset;\n\t\t\t\tconst cell = grid[row]?.[col];\n\n\t\t\t\tif (!cell?.editable || this.readonly()) {\n\t\t\t\t\tskipped++;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst column = columns[col];\n\t\t\t\tconst value = this.read(incoming, column);\n\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\trejected++;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (value !== cell.value) {\n\t\t\t\t\tcells.push({ coords: { row, col }, row: rows[row], column, cell, value });\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tconst height = block.length;\n\t\tconst width = Math.max(...block.map((line) => line.length));\n\t\tconst range = clampGridRange(\n\t\t\t{ top: at.row, bottom: at.row + height - 1, left: at.col, right: at.col + width - 1 },\n\t\t\tthis.bounds()\n\t\t);\n\n\t\tthis.anchor.set(at);\n\t\tthis.active.set({\n\t\t\trow: Math.min(this.bounds().rows - 1, at.row + height - 1),\n\t\t\tcol: Math.min(this.bounds().cols - 1, at.col + width - 1)\n\t\t});\n\n\t\tthis.pasted.emit({\n\t\t\tcells,\n\t\t\trange: range ?? { top: at.row, bottom: at.row, left: at.col, right: at.col },\n\t\t\tskipped,\n\t\t\trejected\n\t\t});\n\t\tthis.announceSelection();\n\t}\n\n\t/**\n\t * What a pasted cell is worth in this column.\n\t *\n\t * The raw number from the HTML flavour wins where there is one, because it does not depend on\n\t * how the source happened to format it. Only when it is absent is the displayed text parsed,\n\t * and then in this reader's own convention.\n\t */\n\tprivate read(incoming: HubClipboardCell, column: HubSpreadsheetColumn<TRow>): HubSpreadsheetValue | undefined {\n\t\tconst kind = column.kind ?? 'text';\n\n\t\t// A formula is kept as what it is, whatever the column holds. Read as a figure it is not\n\t\t// one — `=2*4` is not a number — and the cell refused the very thing it exists to accept:\n\t\t// a column of currency is exactly where somebody writes a formula.\n\t\tif (this.formulas() && isFormula(incoming.text)) {\n\t\t\treturn incoming.text;\n\t\t}\n\n\t\t// The raw number from the HTML flavour wins for a figure column, because it does not\n\t\t// depend on how the source happened to format it. For every other kind the text is what\n\t\t// carries the meaning.\n\t\tif (incoming.raw !== undefined && (kind === 'number' || kind === 'currency')) {\n\t\t\treturn incoming.raw;\n\t\t}\n\n\t\treturn parseForColumn(incoming.text, column, this.decimalMark());\n\t}\n\n\tprivate startEdit(seed: string | undefined): void {\n\t\tconst active = this.active();\n\n\t\tif (!active || !this.canEdit(active.row, active.col)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// A yes/no column has nothing to type into. Opening a field over it would show the stored\n\t\t// 0 or 1 as text and ask the reader to edit a number that is not what the column means.\n\t\tif (this.columns()[active.col].kind === 'boolean') {\n\t\t\tthis.toggleBoolean(active.row, active.col);\n\t\t\treturn;\n\t\t}\n\n\t\tconst cell = this.grid()[active.row][active.col];\n\t\tconst column = this.columns()[active.col];\n\t\tconst kind = column.kind ?? 'text';\n\t\t// The character that opened the cell is the reader's first keystroke, and it has to land\n\t\t// somewhere. In a list it picks the first answer that starts with it, as a native list\n\t\t// does when you type at it; in a date field it lands nowhere, because a letter is not a\n\t\t// date and keeping it would commit rubbish on the way out.\n\t\tconst opener = kind === 'select' ? this.optionStartingWith(column, seed) : undefined;\n\n\t\tthis.anchor.set(null);\n\t\tthis.seed.set(seed);\n\t\tthis.draft.set(this.openingText(cell, kind, seed, opener));\n\t\tthis.invalid.set(false);\n\t\tthis.editing.set(true);\n\n\t\tafterNextRender(\n\t\t\t() => {\n\t\t\t\tconst editor = this.#host.nativeElement.querySelector<HTMLElement>('.hub-spreadsheet__editor');\n\n\t\t\t\tif (!editor) {\n\t\t\t\t\t// A supplied editor draws whatever it likes, so the most the sheet can do is put\n\t\t\t\t\t// the keyboard inside it and let it take over from there.\n\t\t\t\t\tthis.focusSuppliedEditor();\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\teditor.focus();\n\n\t\t\t\t// Opened with Enter or F2 the value is kept and selected; opened by typing, the caret\n\t\t\t\t// sits after the character that opened it. Only a text field has a selection to\n\t\t\t\t// place — a list has no such method and a date field refuses.\n\t\t\t\tif (seed === undefined && editor instanceof HTMLInputElement && editor.type === 'text') {\n\t\t\t\t\teditor.select();\n\t\t\t\t}\n\n\t\t\t\t// One gesture for one decision: the list and the calendar come up with the cell\n\t\t\t\t// instead of waiting for a second click. Not when the cell was opened by typing\n\t\t\t\t// into it, though — a calendar over a half-written date takes the keystrokes that\n\t\t\t\t// were meant to finish it.\n\t\t\t\tif (seed === undefined && (kind === 'select' || kind === 'date')) {\n\t\t\t\t\trevealPicker(editor);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ injector: this.#injector }\n\t\t);\n\t}\n\n\t/** Puts the keyboard in the first thing a supplied editor offers it. */\n\tprivate focusSuppliedEditor(): void {\n\t\tthis.#host.nativeElement\n\t\t\t.querySelector<HTMLElement>(\n\t\t\t\t'.hub-spreadsheet__custom-editor :is(input, select, textarea, button, [tabindex]:not([tabindex=\"-1\"]))'\n\t\t\t)\n\t\t\t?.focus();\n\t}\n\n\t/**\n\t * Keeps the characters typed between opening a cell and the editor getting the focus.\n\t *\n\t * The field does not exist until the view has been drawn, so the focus can only move to it on\n\t * the render after the keystroke that opened the cell. Anybody typing quickly — `8`, `0`, `0`\n\t * inside one frame — has the first character open the cell and the rest arrive here, at the\n\t * grid, with nowhere to go. They used to be dropped: the cell opened on `8` and committed `8`.\n\t *\n\t * So they are added to the draft, which is what the field shows the moment it appears.\n\t */\n\tprivate catchUp(event: KeyboardEvent): void {\n\t\tif (event.isComposing || event.keyCode === 229 || event.ctrlKey || event.metaKey || event.altKey) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key.length !== 1) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.#host.nativeElement.querySelector<HTMLElement>('.hub-spreadsheet__editor');\n\n\t\t// Only for a key that did not come from the field itself. Once the field has the focus its\n\t\t// keystrokes bubble up here too, and adding those to the draft would type everything\n\t\t// twice. Read off the event rather than off `document.activeElement`, which is the same\n\t\t// question asked of something that lies about it in tests.\n\t\tif (editor && event.target === editor) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tthis.draft.update((draft) => draft + event.key);\n\n\t\tif (editor instanceof HTMLInputElement) {\n\t\t\teditor.value = this.draft();\n\t\t}\n\t}\n\n\t/**\n\t * Reads what was typed, reports it if it changed, then moves by `step`.\n\t *\n\t * @returns false when the text is not a value for this column, leaving the editor open and\n\t * marked rather than throwing away what the reader wrote.\n\t */\n\tprivate finishEdit(step: { row: number; col: number } | null): boolean {\n\t\tconst active = this.active();\n\n\t\tif (!active) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst column = this.columns()[active.col];\n\t\tconst cell = this.grid()[active.row][active.col];\n\t\tconst value = this.read({ text: this.draft() }, column);\n\n\t\tif (value === undefined) {\n\t\t\tthis.invalid.set(true);\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.editing.set(false);\n\t\tthis.invalid.set(false);\n\n\t\tif (value !== cell.value) {\n\t\t\tthis.commit.emit({ coords: active, row: this.rows()[active.row], column, cell, value });\n\t\t}\n\n\t\tif (step) {\n\t\t\tthis.moveTo(moveGridFocus(active, step, this.bounds(), { horizontal: 'continuous' }), false);\n\t\t} else {\n\t\t\tthis.focusActive();\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate cancelEdit(): void {\n\t\tthis.editing.set(false);\n\t\tthis.invalid.set(false);\n\t\tthis.focusActive();\n\t}\n\n\t/**\n\t * The first answer of a list that starts with what was typed, skipping the ones a reader is\n\t * not allowed to choose. Matched on the label, because that is what they were reading.\n\t */\n\tprivate optionStartingWith(column: HubSpreadsheetColumn<TRow>, seed: string | undefined): HubSpreadsheetOption | undefined {\n\t\tif (seed === undefined || seed === '') {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst start = seed.toLocaleLowerCase();\n\n\t\treturn column.options?.find((option) => !option.disabled && option.label.toLocaleLowerCase().startsWith(start));\n\t}\n\n\t/** What the editor starts with, which is not always what was typed. */\n\tprivate openingText(\n\t\tcell: HubSpreadsheetCell,\n\t\tkind: HubSpreadsheetValueKind,\n\t\tseed: string | undefined,\n\t\topener: HubSpreadsheetOption | undefined\n\t): string {\n\t\tif (seed === undefined) {\n\t\t\treturn this.editableTextOf(cell);\n\t\t}\n\n\t\tif (kind === 'select') {\n\t\t\t// The label, which is what a list is read back from; an unmatched character leaves the\n\t\t\t// cell as it was rather than emptying it.\n\t\t\treturn opener ? opener.label : this.editableTextOf(cell);\n\t\t}\n\n\t\t// A date field cannot hold half a date, and a letter left in the draft would be committed\n\t\t// as one the moment the reader clicked away.\n\t\treturn kind === 'date' ? '' : seed;\n\t}\n\n\t/** A value as it goes into the editor: numbers in this reader's own convention. */\n\tprivate editableTextOf(cell: HubSpreadsheetCell): string {\n\t\tif (cell.value === null) {\n\t\t\treturn '';\n\t\t}\n\n\t\treturn typeof cell.value === 'number' ? String(cell.value).replace('.', this.decimalMark()) : String(cell.value);\n\t}\n\n\tprivate moveTo(rawTarget: HubGridCoords, extend: boolean): void {\n\t\t// Arithmetic runs on plain coordinates; landing on a covered cell then resolves to the\n\t\t// block that owns it, so the cursor is never on something that is not drawn.\n\t\tconst target = anchorOf(this.spanMap(), rawTarget);\n\n\t\tif (extend) {\n\t\t\tthis.anchor.set(this.anchor() ?? this.active());\n\t\t} else {\n\t\t\tthis.anchor.set(null);\n\t\t}\n\n\t\tthis.active.set(target);\n\t\tthis.announceSelection();\n\t\tthis.focusActive();\n\t}\n\n\tprivate selectRange(range: HubGridRange): void {\n\t\tthis.anchor.set({ row: range.top, col: range.left });\n\t\tthis.active.set({ row: range.bottom, col: range.right });\n\t\tthis.announceSelection();\n\t\tthis.focusActive();\n\t}\n\n\tprivate focusActive(): void {\n\t\t// While virtualising, the cell the cursor has just moved to may not be in the document at\n\t\t// all — that is the whole point of virtualising — so the scroller is moved first and the\n\t\t// focus follows on the render that puts the row there.\n\t\tthis.scrollRowIntoView();\n\n\t\tafterNextRender(\n\t\t\t() => {\n\t\t\t\tconst active = this.active();\n\n\t\t\t\tif (active) {\n\t\t\t\t\tthis.#host.nativeElement\n\t\t\t\t\t\t.querySelector<HTMLElement>(`[data-cell=\"${active.row}-${active.col}\"]`)\n\t\t\t\t\t\t?.focus({ preventScroll: false });\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ injector: this.#injector }\n\t\t);\n\t}\n\n\t/**\n\t * Brings the row the cursor is on inside the viewport, when the sheet is the thing that\n\t * scrolls and the row might not be drawn.\n\t *\n\t * Only the arithmetic the browser cannot do for us: `scrollIntoView` needs an element, and a\n\t * row that is not in the document has none. The offset is worked out from the row height,\n\t * which virtualising already depends on, and the scroller is nudged by the least that brings\n\t * the row in — jumping it to the middle would move the sheet under a reader who only pressed\n\t * the down arrow.\n\t */\n\tprivate scrollRowIntoView(): void {\n\t\tconst active = this.active();\n\t\tconst viewport = this.viewport()?.nativeElement;\n\t\tconst size = this.rowHeight() || this.measuredRowHeight();\n\n\t\tif (!active || !viewport || !this.virtual() || size <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst frozen = Math.min(this.frozenRows(), this.rows().length);\n\n\t\t// A frozen row is pinned, so it is on screen wherever the reader has got to — but landing\n\t\t// on one means going back to the top of the sheet, and leaving the view where it was makes\n\t\t// the cursor look lost.\n\t\tif (active.row < frozen) {\n\t\t\tviewport.scrollTop = 0;\n\t\t\tthis.scrollColumnIntoView(viewport, active.col);\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst top = (active.row - frozen) * size;\n\t\tconst bottom = top + size;\n\t\tconst visibleTop = viewport.scrollTop;\n\t\tconst visibleBottom = visibleTop + viewport.clientHeight;\n\n\t\tif (top < visibleTop) {\n\t\t\tviewport.scrollTop = top;\n\t\t} else if (bottom > visibleBottom) {\n\t\t\tviewport.scrollTop = bottom - viewport.clientHeight;\n\t\t}\n\n\t\tthis.scrollColumnIntoView(viewport, active.col);\n\t}\n\n\t/**\n\t * The same for the column the cursor is on, which may be out of the document sideways.\n\t *\n\t * Measured widths rather than a single size: columns are rarely alike, and adding up the ones\n\t * before the cursor is the only way to know where it starts. Nothing to do when a width is\n\t * missing, which is also when the sheet is drawing every column anyway.\n\t */\n\tprivate scrollColumnIntoView(viewport: HTMLElement, col: number): void {\n\t\tconst widths = this.measuredColumnWidths();\n\t\tconst frozen = Math.min(this.frozenColumns(), this.columns().length);\n\n\t\tif (widths.length !== this.columns().length || widths.some((width) => !(width > 0))) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Same for a frozen column: pinned, so visible, but `Home` means the beginning of the row\n\t\t// and the sheet has to come back with the cursor.\n\t\tif (col < frozen) {\n\t\t\tviewport.scrollLeft = 0;\n\n\t\t\treturn;\n\t\t}\n\n\t\tlet start = 0;\n\n\t\tfor (let index = frozen; index < col; index++) {\n\t\t\tstart += widths[index];\n\t\t}\n\n\t\tconst end = start + widths[col];\n\t\tconst visibleStart = viewport.scrollLeft;\n\t\tconst visibleEnd = visibleStart + viewport.clientWidth;\n\n\t\tif (start < visibleStart) {\n\t\t\tviewport.scrollLeft = start;\n\t\t} else if (end > visibleEnd) {\n\t\t\tviewport.scrollLeft = end - viewport.clientWidth;\n\t\t}\n\t}\n\n\t/** Hands focus to the off-screen field so the browser will dispatch a paste at all. */\n\tprivate focusSink(): void {\n\t\tthis.#host.nativeElement.querySelector<HTMLTextAreaElement>('.hub-spreadsheet__sink')?.focus({\n\t\t\tpreventScroll: true\n\t\t});\n\t}\n\n\tprivate refAt(coords: HubGridCoords): HubSpreadsheetCellRef<TRow> {\n\t\treturn {\n\t\t\tcoords,\n\t\t\trow: this.rows()[coords.row],\n\t\t\tcolumn: this.columns()[coords.col],\n\t\t\tcell: this.grid()[coords.row][coords.col]\n\t\t};\n\t}\n\n\tprivate announceSelection(): void {\n\t\tthis.selectionChange.emit(this.range());\n\t}\n\n\tprivate announceCleared(): void {\n\t\tconst range = this.range();\n\n\t\tif (!range || this.readonly()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst cells = gridRangeCells(range)\n\t\t\t.filter(({ row, col }) => this.canEdit(row, col) && this.grid()[row][col].value !== null)\n\t\t\t.map((coords) => this.refAt(coords));\n\n\t\tif (cells.length) {\n\t\t\tthis.cleared.emit(cells);\n\t\t}\n\t}\n}\n","<!--\n\tThe off-screen field exists for one reason: a browser only dispatches `paste` to something\n\teditable. The paste shortcut parks the focus here for the length of the event and the cell\n\ttakes it straight back, so the reader never notices and the grid keeps its own focus model.\n-->\n<textarea class=\"hub-spreadsheet__sink\" tabindex=\"-1\" aria-hidden=\"true\" readonly (paste)=\"onPaste($event)\"></textarea>\n\n<div class=\"hub-spreadsheet__viewport\" #viewport (scroll)=\"onViewportScroll()\">\n\t<table\n\t\tclass=\"hub-spreadsheet__table\"\n\t\trole=\"grid\"\n\t\t[attr.aria-rowcount]=\"bounds().rows\"\n\t\t[attr.aria-colcount]=\"bounds().cols\"\n\t\t[attr.aria-readonly]=\"readonly() || null\"\n\t\t(keydown)=\"onKeydown($event)\"\n\t\t(copy)=\"onCopy($event, false)\"\n\t\t(cut)=\"onCopy($event, true)\"\n\t>\n\t\t<thead class=\"hub-spreadsheet__head\">\n\t\t\t<tr role=\"row\">\n\t\t\t\t<!-- Holds the width of the columns that are not drawn, so the sheet is as wide as it\n\t\t\t\tsays it is and the ones that are drawn land where they belong. -->\n\t\t\t\t@if (columnWindow().before > 0) {\n\t\t\t\t\t<!-- A minimum, not a width: in a table that shares its space out, a width is a\n\t\t\t\t\tsuggestion the algorithm is free to ignore, and an empty cell asked for three\n\t\t\t\t\tthousand pixels came out two wide. -->\n\t\t\t\t\t<th\n\t\t\t\t\t\tclass=\"hub-spreadsheet__spacer\"\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\t[style.min-inline-size.px]=\"columnWindow().before\"\n\t\t\t\t\t\t[style.inline-size.px]=\"columnWindow().before\"\n\t\t\t\t\t></th>\n\t\t\t\t}\n\n\t\t\t\t@for (columnIndex of drawnColumns(); track trackColumn(columnIndex, columns()[columnIndex])) {\n\t\t\t\t\t@let column = columns()[columnIndex];\n\t\t\t\t\t<th\n\t\t\t\t\t\tclass=\"hub-spreadsheet__header\"\n\t\t\t\t\t\trole=\"columnheader\"\n\t\t\t\t\t\tscope=\"col\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--frozen]=\"isFrozenColumn(columnIndex)\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--frozen-edge]=\"isColumnEdge(columnIndex)\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--end]=\"column.align === 'end'\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--center]=\"column.align === 'center'\"\n\t\t\t\t\t\t[style.inset-inline-start.px]=\"columnOffsetOf(columnIndex)\"\n\t\t\t\t\t\t[style.min-width]=\"column.minWidth\"\n\t\t\t\t\t\t[style.width.px]=\"widthOf(columnIndex)\"\n\t\t\t\t\t\t[attr.data-header]=\"columnIndex\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--end-of-sheet]=\"columnIndex === bounds().cols - 1\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--moving]=\"isMovingColumn(columnIndex)\"\n\t\t\t\t\t\t[class.hub-spreadsheet__header--move-target]=\"isMoveTarget(columnIndex)\"\n\t\t\t\t\t\t(mousedown)=\"onHeaderMouseDown($event, columnIndex)\"\n\t\t\t\t\t\t(mouseenter)=\"onHeaderMouseEnter(columnIndex)\"\n\t\t\t\t\t\t[attr.aria-colindex]=\"columnIndex + 1\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span [class.hub-spreadsheet__header-text--hidden]=\"column.headerHidden\">\n\t\t\t\t\t\t\t{{ column.header }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<!-- The name a formula calls this column, which is not the name on the header.\n\t\t\t\t\tShown only while one is being written, and clickable, because the alternative is\n\t\t\t\t\tknowing it by heart. -->\n\t\t\t\t\t\t@if (writingFormula()) {\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__alias\"\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\t\t\t(mousedown)=\"\n\t\t\t\t\t\t\t\t\t$event.preventDefault();\n\t\t\t\t\t\t\t\t\tuseSuggestion({ label: column.key, kind: 'column', insert: '[' + column.key + ']' })\n\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span class=\"hub-spreadsheet__alias-letter\">{{ columnLetter(columnIndex) }}</span>\n\t\t\t\t\t\t\t\t{{ column.key }}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@if (column.subheader) {\n\t\t\t\t\t\t\t<small class=\"hub-spreadsheet__subheader\">{{ column.subheader }}</small>\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@if (resizableColumns()) {\n\t\t\t\t\t\t\t<!-- Sits inside the header's trailing edge. Hidden from assistive technology:\n\t\t\t\t\t\t\ta width is a matter of taste, and a screen reader has no use for a drag\n\t\t\t\t\t\t\ttarget it cannot aim at. -->\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__resize-grip\"\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t(mousedown)=\"onResizeStart($event, columnIndex)\"\n\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t}\n\t\t\t\t\t</th>\n\t\t\t\t}\n\n\t\t\t\t@if (columnWindow().after > 0) {\n\t\t\t\t\t<th\n\t\t\t\t\t\tclass=\"hub-spreadsheet__spacer\"\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\t[style.min-inline-size.px]=\"columnWindow().after\"\n\t\t\t\t\t\t[style.inline-size.px]=\"columnWindow().after\"\n\t\t\t\t\t></th>\n\t\t\t\t}\n\t\t\t</tr>\n\t\t</thead>\n\n\t\t<tbody class=\"hub-spreadsheet__body\">\n\t\t\t<!-- The rows above the window are not in the document; this holds their height, so the\n\t\t\tscrollbar still says how long the sheet is and the rows that are drawn land where they\n\t\t\tbelong. Hidden from assistive technology, which reads `aria-rowindex` instead. -->\n\t\t\t@if (rowWindow().before > 0) {\n\t\t\t\t<tr class=\"hub-spreadsheet__spacer\" role=\"presentation\" aria-hidden=\"true\">\n\t\t\t\t\t<td [attr.colspan]=\"drawnCellCount()\" [style.block-size.px]=\"rowWindow().before\"></td>\n\t\t\t\t</tr>\n\t\t\t}\n\n\t\t\t@for (rowIndex of drawnRows(); track trackRow(rowIndex)) {\n\t\t\t\t<tr\n\t\t\t\t\tclass=\"hub-spreadsheet__row\"\n\t\t\t\t\trole=\"row\"\n\t\t\t\t\t[class.hub-spreadsheet__row--frozen]=\"isFrozenRow(rowIndex)\"\n\t\t\t\t\t[class.hub-spreadsheet__row--frozen-edge]=\"isRowEdge(rowIndex)\"\n\t\t\t\t\t[attr.aria-rowindex]=\"rowIndex + 1\"\n\t\t\t\t>\n\t\t\t\t\t@if (columnWindow().before > 0) {\n\t\t\t\t\t\t<td class=\"hub-spreadsheet__spacer\" role=\"presentation\" aria-hidden=\"true\"></td>\n\t\t\t\t\t}\n\n\t\t\t\t\t@for (colIndex of drawnColumns(); track trackColumn(colIndex, columns()[colIndex])) {\n\t\t\t\t\t\t@let column = columns()[colIndex];\n\t\t\t\t\t\t<!-- A cell swallowed by a merge is not rendered at all: the anchor's rowspan and\n\t\t\t\t\t\tcolspan already occupy its place, and drawing it would push the row out of shape. -->\n\t\t\t\t\t\t@if (!isHidden(rowIndex, colIndex)) {\n\t\t\t\t\t\t\t@let cell = grid()[rowIndex][colIndex];\n\t\t\t\t\t\t\t@let state = stateOf(rowIndex, colIndex);\n\t\t\t\t\t\t\t@let error = errorOf(rowIndex, colIndex);\n\t\t\t\t\t\t\t@let editable = canEdit(rowIndex, colIndex);\n\t\t\t\t\t\t\t<!-- Worked out once per cell, and only for the one that is open: the config a\n\t\t\t\t\t\tregistered control adapter is asked for, or null when there is nothing to host. -->\n\t\t\t\t\t\t\t@let hosted = editing() && isActive(rowIndex, colIndex) ? hostedControl(rowIndex, colIndex) : null;\n\n\t\t\t\t\t\t\t<td\n\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__cell\"\n\t\t\t\t\t\t\t\trole=\"gridcell\"\n\t\t\t\t\t\t\t\t[attr.data-cell]=\"rowIndex + '-' + colIndex\"\n\t\t\t\t\t\t\t\t[attr.tabindex]=\"tabIndexOf(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[attr.aria-colindex]=\"colIndex + 1\"\n\t\t\t\t\t\t\t\t[attr.rowspan]=\"rowSpanOf(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[attr.colspan]=\"colSpanOf(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[attr.aria-rowspan]=\"rowSpanOf(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[attr.aria-colspan]=\"colSpanOf(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[attr.aria-selected]=\"isSelected(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[attr.aria-readonly]=\"!editable || null\"\n\t\t\t\t\t\t\t\t[attr.aria-invalid]=\"(isActive(rowIndex, colIndex) && invalid()) || error ? true : null\"\n\t\t\t\t\t\t\t\t[attr.aria-busy]=\"state === 'saving' || null\"\n\t\t\t\t\t\t\t\t[attr.title]=\"error ?? cell.title\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--active]=\"isActive(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--editing]=\"editing() && isActive(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--selected]=\"isSelected(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--end-of-sheet]=\"reachesEnd(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--filling]=\"isFillPreview(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--readonly]=\"!editable\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--muted]=\"cell.muted\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--end]=\"column.align === 'end'\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--center]=\"column.align === 'center'\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--frozen-col]=\"isFrozenColumn(colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--frozen-row]=\"isFrozenRow(rowIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--frozen-col-edge]=\"isColumnEdge(colIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--frozen-row-edge]=\"isRowEdge(rowIndex)\"\n\t\t\t\t\t\t\t\t[style.inset-inline-start.px]=\"columnOffsetOf(colIndex)\"\n\t\t\t\t\t\t\t\t[style.inset-block-start.px]=\"rowOffsetOf(rowIndex)\"\n\t\t\t\t\t\t\t\t[class.hub-spreadsheet__cell--invalid]=\"\n\t\t\t\t\t\t\t\t\t(isActive(rowIndex, colIndex) && invalid()) ||\n\t\t\t\t\t\t\t\t\t!!error ||\n\t\t\t\t\t\t\t\t\thasFormulaError(rowIndex, colIndex)\n\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t[attr.data-state]=\"state\"\n\t\t\t\t\t\t\t\t(mousedown)=\"onMouseDown($event, rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t(mouseenter)=\"onMouseEnter(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t(mouseup)=\"onMouseUp($event, rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t(dblclick)=\"onDoubleClick()\"\n\t\t\t\t\t\t\t\t(contextmenu)=\"onContextMenu($event, rowIndex, colIndex)\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@if (editing() && isActive(rowIndex, colIndex)) {\n\t\t\t\t\t\t\t\t\t@if (editorFor(colIndex); as custom) {\n\t\t\t\t\t\t\t\t\t\t<!-- The host supplied an editor for this column. It reports a value through\n\t\t\t\t\t\t\t\t\t`commit`, or walks away through `cancel`; until it does one of the two the\n\t\t\t\t\t\t\t\t\teditor stays open, so a picker may take as many clicks as it needs. -->\n\t\t\t\t\t\t\t\t\t\t<div class=\"hub-spreadsheet__custom-editor\">\n\t\t\t\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"custom.template\"\n\t\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"editorContext(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t} @else if (hosted) {\n\t\t\t\t\t\t\t\t\t\t<!-- A control adapter is registered and this column is a list, so the cell\n\t\t\t\t\t\t\t\t\topens with whatever the project wired instead of the native list. The\n\t\t\t\t\t\t\t\t\twrapper is the supplied editor's, because from the sheet's side this is\n\t\t\t\t\t\t\t\t\tone: something it did not build, filling the cell. -->\n\t\t\t\t\t\t\t\t\t\t<div class=\"hub-spreadsheet__custom-editor\">\n\t\t\t\t\t\t\t\t\t\t\t<ng-container [hubSpreadsheetControl]=\"hosted\" />\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t} @else if (column.kind === 'select') {\n\t\t\t\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__editor hub-spreadsheet__editor--select\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"column.header\"\n\t\t\t\t\t\t\t\t\t\t\t(change)=\"commitFromEditor($any($event.target).value || null)\"\n\t\t\t\t\t\t\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t\t\t\t\t\t\t\t(blur)=\"onEditorBlur()\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<option value=\"\" [selected]=\"cell.value === null\"></option>\n\t\t\t\t\t\t\t\t\t\t\t@for (option of column.options ?? []; track option.value) {\n\t\t\t\t\t\t\t\t\t\t\t\t<option\n\t\t\t\t\t\t\t\t\t\t\t\t\t[value]=\"option.value\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t[selected]=\"isChosen(option, column)\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t[disabled]=\"option.disabled && option.value !== cell.value\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{{ option.label }}\n\t\t\t\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t@if (suggesting()) {\n\t\t\t\t\t\t\t\t\t\t\t<!-- What can go into the formula, because the aliases it needs are nowhere\n\t\t\t\t\t\t\t\t\t\telse on screen. Hidden from assistive technology: the field owns the\n\t\t\t\t\t\t\t\t\t\tconversation, and a list that announced itself over every keystroke\n\t\t\t\t\t\t\t\t\t\twould talk across it. -->\n\t\t\t\t\t\t\t\t\t\t\t<div class=\"hub-spreadsheet__suggestions\" role=\"presentation\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t@for (suggestion of suggestions(); track suggestion.label; let index = $index) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__suggestion\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t[class.hub-spreadsheet__suggestion--on]=\"index === suggestionIndex()\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(mousedown)=\"$event.preventDefault(); useSuggestion(suggestion)\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"hub-spreadsheet__suggestion-name\">{{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsuggestion.label\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t@if (suggestion.hint) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"hub-spreadsheet__suggestion-hint\">{{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsuggestion.hint\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__editor\"\n\t\t\t\t\t\t\t\t\t\t\t[type]=\"column.kind === 'date' ? 'date' : 'text'\"\n\t\t\t\t\t\t\t\t\t\t\t[value]=\"draft()\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"column.header\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-invalid]=\"invalid() || null\"\n\t\t\t\t\t\t\t\t\t\t\t(input)=\"onDraftInput($event)\"\n\t\t\t\t\t\t\t\t\t\t\t(keydown)=\"onEditorKeydown($event)\"\n\t\t\t\t\t\t\t\t\t\t\t(blur)=\"onEditorBlur()\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@if (column.kind === 'boolean') {\n\t\t\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__check\"\n\t\t\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\t\t\t[checked]=\"isOn(cell)\"\n\t\t\t\t\t\t\t\t\t\t\t[disabled]=\"!editable\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"column.header\"\n\t\t\t\t\t\t\t\t\t\t\t(change)=\"toggleBoolean(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t} @else if (cellTemplateFor(colIndex); as own) {\n\t\t\t\t\t\t\t\t\t\t<!-- The host draws this column's cells. The value still travels to the\n\t\t\t\t\t\t\t\t\tclipboard rather than the drawing, and the cell is still what the\n\t\t\t\t\t\t\t\t\tkeyboard is on: the template is inside it, not instead of it. -->\n\t\t\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"own.template\"\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"cellContext(rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t<!-- The row's number, so a coordinate can be read off the sheet instead of\n\t\t\t\t\t\t\t\t\tcounted. Only while a formula is being written, and only in the first\n\t\t\t\t\t\t\t\t\tcolumn drawn, which is where a spreadsheet puts it. -->\n\t\t\t\t\t\t\t\t\t\t@if (writingFormula() && colIndex === drawnColumns()[0]) {\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"hub-spreadsheet__rownum\" aria-hidden=\"true\">{{ rowIndex + 1 }}</span>\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t<span class=\"hub-spreadsheet__value\">{{ displayOf(cell, column) }}</span>\n\n\t\t\t\t\t\t\t\t\t\t@if (column.placeholder && !displayOf(cell, column)) {\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"hub-spreadsheet__placeholder\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t\t\t\t\t{{ column.placeholder }}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t<!-- Says the cell opens onto a list or a calendar rather than a field, and\n\t\t\t\t\t\t\t\t\topens it on one click — as a spreadsheet drops the list of a cell that\n\t\t\t\t\t\t\t\t\thas one. Shown on the cell the reader is on and on the one under the\n\t\t\t\t\t\t\t\t\tpointer. Hidden from assistive technology: the keyboard opens the same\n\t\t\t\t\t\t\t\t\tcell with Alt and the down arrow, and reads the editor itself. -->\n\t\t\t\t\t\t\t\t\t\t@if (editable && affordanceOf(column, colIndex); as affordance) {\n\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__affordance\"\n\t\t\t\t\t\t\t\t\t\t\t\t[class.hub-spreadsheet__affordance--date]=\"affordance === 'date'\"\n\t\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t\t(mousedown)=\"onAffordanceDown($event, rowIndex, colIndex)\"\n\t\t\t\t\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t@if (cell.secondary) {\n\t\t\t\t\t\t\t\t\t\t<small class=\"hub-spreadsheet__secondary\">{{ cell.secondary }}</small>\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t@if (hasFillHandle(rowIndex, colIndex)) {\n\t\t\t\t\t\t\t\t\t\t<!-- Drawn inside the corner cell so it travels with the selection. Hidden from\n\t\t\t\t\t\t\t\t\tassistive technology: filling is available from the keyboard through the\n\t\t\t\t\t\t\t\t\tclipboard, and a screen reader has no use for a drag target. -->\n\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\tclass=\"hub-spreadsheet__fill-handle\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t\t(mousedown)=\"onFillHandleDown($event)\"\n\t\t\t\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@if (columnWindow().after > 0) {\n\t\t\t\t\t\t<td class=\"hub-spreadsheet__spacer\" role=\"presentation\" aria-hidden=\"true\"></td>\n\t\t\t\t\t}\n\t\t\t\t</tr>\n\t\t\t} @empty {\n\t\t\t\t<tr class=\"hub-spreadsheet__row hub-spreadsheet__row--empty\" role=\"row\">\n\t\t\t\t\t<td class=\"hub-spreadsheet__empty\" role=\"gridcell\" [attr.colspan]=\"bounds().cols || 1\">\n\t\t\t\t\t\t{{ emptyText() }}\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t}\n\t\t\t@if (rowWindow().after > 0) {\n\t\t\t\t<tr class=\"hub-spreadsheet__spacer\" role=\"presentation\" aria-hidden=\"true\">\n\t\t\t\t\t<td [attr.colspan]=\"drawnCellCount()\" [style.block-size.px]=\"rowWindow().after\"></td>\n\t\t\t\t</tr>\n\t\t\t}\n\t\t</tbody>\n\t</table>\n</div>\n\n@if (menuAt(); as at) {\n\t<!-- Positioned against the host, which is the sheet's own corner, so the menu travels with a\n\tscrolled page and never has to be repositioned on scroll. -->\n\t<div\n\t\tclass=\"hub-spreadsheet__menu\"\n\t\trole=\"menu\"\n\t\t[attr.aria-label]=\"'ROW_ACTIONS' | translate\"\n\t\t[style.inset-inline-start.px]=\"at.x\"\n\t\t[style.inset-block-start.px]=\"at.y\"\n\t\t(mousedown)=\"$event.stopPropagation()\"\n\t>\n\t\t@for (entry of menuEntries(); track entry.id) {\n\t\t\t<button class=\"hub-spreadsheet__menu-item\" type=\"button\" role=\"menuitem\" (click)=\"runMenuEntry(entry.id)\">\n\t\t\t\t{{ entry.label | translate: { count: entry.count } }}\n\t\t\t</button>\n\t\t}\n\t</div>\n}\n","/**\n * Handing the reader a file to save.\n *\n * Six lines that every host writes and two things they all get wrong: the object URL nobody\n * releases, and the anchor left in the document.\n *\n * @param filename - What to call it.\n * @param blob - What goes in it.\n */\nexport function downloadBlob(filename: string, blob: Blob): void {\n\tif (typeof document === 'undefined') {\n\t\treturn;\n\t}\n\n\tconst url = URL.createObjectURL(blob);\n\tconst anchor = document.createElement('a');\n\n\tanchor.href = url;\n\tanchor.download = filename;\n\tanchor.rel = 'noopener';\n\tdocument.body.appendChild(anchor);\n\tanchor.click();\n\tanchor.remove();\n\tURL.revokeObjectURL(url);\n}\n","import { formulaErrorText } from '../formulas/formula-errors';\nimport { isFormula } from '../formulas/formula-parser';\nimport { evaluateSheet } from '../formulas/formula-sheet';\nimport { HubSpreadsheetColumn, HubSpreadsheetValue } from '../models/spreadsheet.types';\n\n/** How a sheet's values are read for a file. */\nexport interface HubSheetValuesOptions {\n\t/**\n\t * Whether to work the formulas out first.\n\t *\n\t * On for a file somebody else is going to read: a column of `=SUM([total:])` is of no use to\n\t * them. Off for a round trip that is meant to come back with its formulas intact.\n\t */\n\treadonly formulas?: boolean;\n}\n\n/**\n * What every cell of a sheet holds, with the formulas run if asked.\n *\n * Shared by the exporters because both need the same answer and neither should be the one deciding\n * it: what a cell shows is the sheet's business, and a second copy of that decision inside the CSV\n * writer would drift from the component the first time a formula grows a new case.\n *\n * A formula that cannot be worked out comes out as its spreadsheet spelling — `#DIV/0!` and the\n * rest — which is what Excel writes in the same situation and what the reader of the file expects\n * to see.\n */\nexport function sheetValues<TRow>(\n\trows: readonly TRow[],\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[],\n\toptions: HubSheetValuesOptions = {}\n): HubSpreadsheetValue[][] {\n\tconst cells = rows.map((row) => columns.map((column) => column.cell(row).value));\n\n\tconst anyFormula = columns.some((column) => column.formula) || cells.some((line) => line.some((value) => isFormula(value)));\n\n\tif (!options.formulas || !anyFormula) {\n\t\treturn cells;\n\t}\n\n\tconst places = new Map(columns.map((column, index) => [column.key, index]));\n\tconst sheet = evaluateSheet({\n\t\trows,\n\t\tcolumns,\n\t\traw: (rowIndex, column) => cells[rowIndex]?.[places.get(column.key) ?? -1] ?? null\n\t});\n\n\treturn cells.map((line, rowIndex) =>\n\t\tline.map((value, colIndex) => {\n\t\t\tconst column = columns[colIndex];\n\n\t\t\tif (!isFormula(value) && !column.formula) {\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\tconst result = sheet[rowIndex]?.[column.key];\n\n\t\t\treturn result?.failure ? formulaErrorText(result.failure) : (result?.value ?? null);\n\t\t})\n\t);\n}\n","import { HubSpreadsheetColumn } from '../models/spreadsheet.types';\n\n/** A file read back: its headers, if it had any, and its rows as they were written. */\nexport interface HubSheetTable {\n\treadonly headers: readonly string[] | null;\n\treadonly rows: readonly (readonly string[])[];\n}\n\n/**\n * Turns a file's rows into records keyed by column alias, matching its headers to the sheet.\n *\n * Matched on the header first and the alias second, both ignoring case and surrounding space: a\n * file that came from this sheet carries the headers, and one written by hand often carries the\n * aliases. A column the file has nothing for is left out rather than filled with an empty string,\n * so a partial file updates what it names and leaves the rest alone.\n *\n * Shared by every importer, because the matching is the part that has to behave the same whatever\n * the file was: somebody who fixes a CSV by renaming a heading expects the same file to work when\n * they save it as a workbook instead.\n *\n * @returns One record per row of the file, keyed by column alias.\n */\nexport function tableToRecords<TRow>(\n\ttable: HubSheetTable,\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[]\n): Array<Record<string, string>> {\n\tconst normalise = (value: string) => value.trim().toLocaleLowerCase();\n\tconst places = new Map<number, string>();\n\n\tif (table.headers) {\n\t\ttable.headers.forEach((heading, index) => {\n\t\t\tconst match = columns.find(\n\t\t\t\t(column) => normalise(column.header) === normalise(heading) || normalise(column.key) === normalise(heading)\n\t\t\t);\n\n\t\t\tif (match) {\n\t\t\t\tplaces.set(index, match.key);\n\t\t\t}\n\t\t});\n\t} else {\n\t\tcolumns.forEach((column, index) => places.set(index, column.key));\n\t}\n\n\treturn table.rows.map((row) => {\n\t\tconst record: Record<string, string> = {};\n\n\t\tfor (const [index, alias] of places) {\n\t\t\tif (row[index] !== undefined) {\n\t\t\t\trecord[alias] = row[index];\n\t\t\t}\n\t\t}\n\n\t\treturn record;\n\t});\n}\n","import { displayValue } from '../columns/cell-values';\nimport { HubSpreadsheetColumn, HubSpreadsheetValue } from '../models/spreadsheet.types';\nimport { downloadBlob } from './download';\nimport { parseDelimited, serialiseDelimited } from './delimited';\nimport { sheetValues } from './sheet-values';\nimport { HubSheetTable, tableToRecords } from './table-records';\n\n/**\n * A sheet as a CSV file, and back.\n *\n * Two things decide whether a CSV is any use, and both are here rather than left to the caller.\n *\n * The **separator** is not always a comma: where the comma is the decimal mark — most of Europe —\n * a spreadsheet writes and expects semicolons, and a file written with the wrong one opens as a\n * single column of text. So it is chosen from the decimal mark when nobody says otherwise, and\n * sniffed when reading rather than assumed.\n *\n * The **values** are what the reader sees, not what the row holds: a select column exports the\n * label somebody chose, and a formula exports the number it came to. A CSV is what gets sent to\n * somebody who does not have the application, and a column of `pending` codes is of no use to\n * them. `values: 'stored'` is there for the round trip that is meant to come back.\n */\n\nexport interface HubCsvOptions {\n\t/** What separates the cells. Chosen from the decimal mark when not given. */\n\treadonly delimiter?: ',' | ';' | '\\t';\n\t/** Whether to write the column headers as the first line. On unless turned off. */\n\treadonly headers?: boolean;\n\t/** What to write: what the cell shows, or what the row holds. */\n\treadonly values?: 'shown' | 'stored';\n\t/** How this reader writes decimals, which decides the separator and the figures. */\n\treadonly decimalMark?: ',' | '.';\n\t/** What ends a line. CRLF, because that is what a spreadsheet on Windows expects. */\n\treadonly newline?: '\\n' | '\\r\\n';\n\t/**\n\t * Whether to work the formulas out before writing. On unless turned off, and never done for\n\t * `values: 'stored'`, where the formula itself is the thing worth keeping.\n\t */\n\treadonly formulas?: boolean;\n}\n\n/** The separator to use when nobody said: a comma cannot separate what it also punctuates. */\nfunction delimiterFor(options: HubCsvOptions): ',' | ';' | '\\t' {\n\treturn options.delimiter ?? (options.decimalMark === ',' ? ';' : ',');\n}\n\n/** A value as it goes into the file. */\nfunction textOf<TRow>(value: HubSpreadsheetValue, column: HubSpreadsheetColumn<TRow>, options: HubCsvOptions): string {\n\tif (value === null) {\n\t\treturn '';\n\t}\n\n\tif (options.values === 'stored') {\n\t\treturn String(value);\n\t}\n\n\tconst shown = displayValue(value, column);\n\n\t// A figure is written the way this reader writes figures, or a spreadsheet opening the file\n\t// reads 1.234,56 as text and quietly leaves the column out of every sum.\n\treturn typeof value === 'number' && options.decimalMark === ',' ? shown.replace('.', ',') : shown;\n}\n\n/**\n * Writes a sheet as CSV.\n *\n * @param rows - The rows, as the sheet has them.\n * @param columns - The columns, which decide the order and the headers.\n * @param options - How to write it.\n * @returns The file's contents.\n */\nexport function sheetToCsv<TRow>(\n\trows: readonly TRow[],\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[],\n\toptions: HubCsvOptions = {}\n): string {\n\tconst delimiter = delimiterFor(options);\n\tconst lines: string[][] = [];\n\n\tif (options.headers !== false) {\n\t\tlines.push(columns.map((column) => column.header));\n\t}\n\n\tconst values = sheetValues(rows, columns, { formulas: options.values !== 'stored' && options.formulas !== false });\n\n\tfor (const line of values) {\n\t\tlines.push(line.map((value, index) => textOf(value, columns[index], options)));\n\t}\n\n\treturn serialiseDelimited(lines, delimiter, options.newline ?? '\\r\\n');\n}\n\n/**\n * Which separator a file is written with.\n *\n * Counted on the first line rather than guessed from the file's name: an exporter's idea of CSV\n * and the reader's locale often disagree, and the line that holds the headers is the one that\n * shows it most clearly.\n */\nexport function sniffDelimiter(text: string): ',' | ';' | '\\t' {\n\tconst firstLine = text.split(/\\r?\\n/, 1)[0] ?? '';\n\tconst counts: Array<[',' | ';' | '\\t', number]> = [\n\t\t[',', (firstLine.match(/,/g) ?? []).length],\n\t\t[';', (firstLine.match(/;/g) ?? []).length],\n\t\t['\\t', (firstLine.match(/\\t/g) ?? []).length]\n\t];\n\n\treturn counts.sort((a, b) => b[1] - a[1])[0][1] > 0 ? counts[0][0] : ',';\n}\n\n/**\n * Reads a CSV file.\n *\n * @param text - The file's contents.\n * @param options - How to read it; the separator is sniffed when not given.\n */\nexport function csvToTable(text: string, options: HubCsvOptions = {}): HubSheetTable {\n\tconst rows = parseDelimited(text, options.delimiter ?? sniffDelimiter(text));\n\n\tif (options.headers === false || !rows.length) {\n\t\treturn { headers: null, rows };\n\t}\n\n\treturn { headers: rows[0], rows: rows.slice(1) };\n}\n\n/**\n * Reads a CSV file into rows keyed by column alias, matching its headers to the sheet's columns.\n *\n * @returns One record per row of the file, keyed by column alias.\n */\nexport function csvToRecords<TRow>(\n\ttext: string,\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[],\n\toptions: HubCsvOptions = {}\n): Array<Record<string, string>> {\n\treturn tableToRecords(csvToTable(text, options), columns);\n}\n\n/**\n * Hands the reader a CSV file to save.\n *\n * @param filename - What to call it.\n * @param text - What goes in it.\n * @param type - Its media type.\n */\nexport function downloadText(filename: string, text: string, type = 'text/csv;charset=utf-8'): void {\n\t// The mark is what tells a spreadsheet the file is UTF-8. Without it an accented word opens as\n\t// two characters of nonsense, and the reader blames whoever exported it.\n\tconst contents = type.startsWith('text/csv') ? '\\ufeff' + text : text;\n\n\tdownloadBlob(filename, new Blob([contents], { type }));\n}\n","/**\n * A zip file, written by hand.\n *\n * An xlsx is a zip of XML, and this is the part of that sentence that usually drags a library in.\n * It does not have to: the entries are **stored** rather than deflated, which the format has\n * allowed since the beginning and every reader supports, and what is left is a checksum and three\n * fixed-shape records. A spreadsheet of a few thousand cells makes a file a couple of times bigger\n * than a compressed one would be — against a dependency of some hundreds of kilobytes that every\n * consumer of the library would pay for whether they export anything or not.\n */\n\n/** The table CRC-32 needs, worked out once. */\nconst CRC_TABLE = (() => {\n\tconst table = new Uint32Array(256);\n\n\tfor (let index = 0; index < 256; index++) {\n\t\tlet value = index;\n\n\t\tfor (let bit = 0; bit < 8; bit++) {\n\t\t\tvalue = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;\n\t\t}\n\n\t\ttable[index] = value >>> 0;\n\t}\n\n\treturn table;\n})();\n\n/** The checksum a zip entry carries, which a reader uses to know the bytes arrived whole. */\nexport function crc32(bytes: Uint8Array): number {\n\tlet crc = 0xffffffff;\n\n\tfor (const byte of bytes) {\n\t\tcrc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n\t}\n\n\treturn (crc ^ 0xffffffff) >>> 0;\n}\n\n/** One file inside the archive. */\nexport interface HubZipEntry {\n\t/** Its path inside the zip, with forward slashes. */\n\treadonly path: string;\n\t/** Its contents. */\n\treadonly data: string | Uint8Array;\n}\n\n/** Writes little-endian numbers into a buffer, which is all a zip header is. */\nfunction writer(size: number) {\n\tconst bytes = new Uint8Array(size);\n\tlet at = 0;\n\n\treturn {\n\t\tbytes,\n\t\tu16(value: number) {\n\t\t\tbytes[at++] = value & 0xff;\n\t\t\tbytes[at++] = (value >>> 8) & 0xff;\n\t\t},\n\t\tu32(value: number) {\n\t\t\tbytes[at++] = value & 0xff;\n\t\t\tbytes[at++] = (value >>> 8) & 0xff;\n\t\t\tbytes[at++] = (value >>> 16) & 0xff;\n\t\t\tbytes[at++] = (value >>> 24) & 0xff;\n\t\t},\n\t\traw(source: Uint8Array) {\n\t\t\tbytes.set(source, at);\n\t\t\tat += source.length;\n\t\t}\n\t};\n}\n\n/**\n * Packs a set of files into a zip archive.\n *\n * Everything is stored rather than compressed, and dated to a fixed moment: a file that changes\n * every time it is written for no reason other than the clock is a file that cannot be compared\n * with the one from yesterday.\n *\n * @param entries - What goes in it.\n * @returns The bytes of the archive.\n */\nexport function zip(entries: readonly HubZipEntry[]): Uint8Array {\n\tconst encoder = new TextEncoder();\n\tconst parts: Uint8Array[] = [];\n\tconst directory: Uint8Array[] = [];\n\tlet offset = 0;\n\n\t// 1 January 1980, which is the earliest a zip can say and the only honest answer when the\n\t// contents did not come from a file with a date of its own.\n\tconst time = 0;\n\tconst date = 33;\n\n\tfor (const entry of entries) {\n\t\tconst name = encoder.encode(entry.path);\n\t\tconst data = typeof entry.data === 'string' ? encoder.encode(entry.data) : entry.data;\n\t\tconst checksum = crc32(data);\n\n\t\tconst local = writer(30 + name.length);\n\n\t\tlocal.u32(0x04034b50);\n\t\tlocal.u16(20);\n\t\tlocal.u16(0);\n\t\tlocal.u16(0);\n\t\tlocal.u16(time);\n\t\tlocal.u16(date);\n\t\tlocal.u32(checksum);\n\t\tlocal.u32(data.length);\n\t\tlocal.u32(data.length);\n\t\tlocal.u16(name.length);\n\t\tlocal.u16(0);\n\t\tlocal.raw(name);\n\n\t\tparts.push(local.bytes, data);\n\n\t\tconst central = writer(46 + name.length);\n\n\t\tcentral.u32(0x02014b50);\n\t\tcentral.u16(20);\n\t\tcentral.u16(20);\n\t\tcentral.u16(0);\n\t\tcentral.u16(0);\n\t\tcentral.u16(time);\n\t\tcentral.u16(date);\n\t\tcentral.u32(checksum);\n\t\tcentral.u32(data.length);\n\t\tcentral.u32(data.length);\n\t\tcentral.u16(name.length);\n\t\tcentral.u16(0);\n\t\tcentral.u16(0);\n\t\tcentral.u16(0);\n\t\tcentral.u16(0);\n\t\tcentral.u32(0);\n\t\tcentral.u32(offset);\n\t\tcentral.raw(name);\n\n\t\tdirectory.push(central.bytes);\n\t\toffset += local.bytes.length + data.length;\n\t}\n\n\tconst directorySize = directory.reduce((total, record) => total + record.length, 0);\n\tconst end = writer(22);\n\n\tend.u32(0x06054b50);\n\tend.u16(0);\n\tend.u16(0);\n\tend.u16(entries.length);\n\tend.u16(entries.length);\n\tend.u32(directorySize);\n\tend.u32(offset);\n\tend.u16(0);\n\n\tconst all = [...parts, ...directory, end.bytes];\n\tconst size = all.reduce((total, part) => total + part.length, 0);\n\tconst archive = new Uint8Array(size);\n\tlet at = 0;\n\n\tfor (const part of all) {\n\t\tarchive.set(part, at);\n\t\tat += part.length;\n\t}\n\n\treturn archive;\n}\n","import { displayValue } from '../columns/cell-values';\nimport { HubSpreadsheetColumn, HubSpreadsheetValue } from '../models/spreadsheet.types';\nimport { downloadBlob } from './download';\nimport { sheetValues } from './sheet-values';\nimport { zip } from './zip';\n\n/**\n * A sheet as a real `.xlsx`, written by hand.\n *\n * CSV loses everything except the characters: a figure becomes text the moment a locale disagrees\n * about the decimal mark, a date is whatever the reader's machine decides it is, and nothing knows\n * a column of prices from a column of postcodes. That is why the export people actually ask for is\n * this one.\n *\n * What comes out is a small, honest workbook: one sheet, a header row in bold, numbers as numbers\n * and dates as dates. No charts, no merges, no column widths — anybody who needs those has a\n * workbook of their own to paste into, and every one of them costs another part of a format that\n * is already the largest thing in this library.\n *\n * The one thing worth knowing about the file: its parts are **stored** rather than compressed, so\n * it is a few times larger than what Excel writes. That is the whole price of not depending on a\n * compression library, and no reader can tell the difference.\n */\n\nexport interface HubXlsxOptions {\n\t/** The sheet's name in the workbook. `Sheet1` when not given. */\n\treadonly sheetName?: string;\n\t/** Whether to write the column headers as the first row. On unless turned off. */\n\treadonly headers?: boolean;\n\t/** What to write: what the cell shows, or what the row holds. */\n\treadonly values?: 'shown' | 'stored';\n\t/** Whether to work the formulas out first. On unless turned off. */\n\treadonly formulas?: boolean;\n}\n\n/** The media type a browser and Excel both recognise. */\nexport const XLSX_MEDIA_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';\n\n/** What the day numbers are counted from: 30 December 1899, which is Excel's zero. */\nconst EXCEL_EPOCH = Date.UTC(1899, 11, 30);\n\n/** Style slots, in the order `styles.xml` declares them. */\nconst STYLE_PLAIN = 0;\nconst STYLE_HEADER = 1;\nconst STYLE_DATE = 2;\n\n/** XML has five characters that cannot be written as themselves, and one that must not be written at all. */\nfunction escapeXml(value: string): string {\n\treturn value\n\t\t.replace(/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f]/g, '')\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''');\n}\n\n/** A column's letter, as a spreadsheet names it: A, B, … Z, AA. */\nfunction letter(index: number): string {\n\tlet name = '';\n\tlet rest = index;\n\n\tdo {\n\t\tname = String.fromCharCode(65 + (rest % 26)) + name;\n\t\trest = Math.floor(rest / 26) - 1;\n\t} while (rest >= 0);\n\n\treturn name;\n}\n\n/**\n * A date as the number of days since Excel's zero, or null when the text is not a date.\n *\n * Only whole days and only the ISO shape, which is what a date column of this sheet holds. A\n * string that merely looks date-ish — `2024` — is left as text on purpose: guessing wrong turns a\n * catalogue number into a Tuesday.\n */\nfunction dateSerial(value: string): number | null {\n\tconst match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value.trim());\n\n\tif (!match) {\n\t\treturn null;\n\t}\n\n\tconst stamp = Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n\n\treturn Number.isNaN(stamp) ? null : Math.round((stamp - EXCEL_EPOCH) / 86_400_000);\n}\n\n/** One cell, as the worksheet spells it. */\nfunction cellXml<TRow>(\n\treference: string,\n\tvalue: HubSpreadsheetValue,\n\tcolumn: HubSpreadsheetColumn<TRow> | undefined,\n\toptions: HubXlsxOptions\n): string {\n\tif (value === null || value === '') {\n\t\treturn '';\n\t}\n\n\tif (typeof value === 'number') {\n\t\treturn `<c r=\"${reference}\"><v>${value}</v></c>`;\n\t}\n\n\tif (column?.kind === 'date') {\n\t\tconst serial = dateSerial(value);\n\n\t\tif (serial !== null) {\n\t\t\treturn `<c r=\"${reference}\" s=\"${STYLE_DATE}\"><v>${serial}</v></c>`;\n\t\t}\n\t}\n\n\t// What the reader saw, not the code underneath: a select cell exports the label somebody chose.\n\t// `values: 'stored'` is the round trip, and there the stored value is the point.\n\tconst text = options.values === 'stored' || !column ? value : displayValue(value, column);\n\n\t// Inline rather than through the shared-strings table. A workbook of a few thousand cells does\n\t// not care about the repetition, and the table is a second part to keep in step for nothing.\n\treturn `<c r=\"${reference}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(text)}</t></is></c>`;\n}\n\n/** A sheet name Excel will accept: no more than 31 characters and none of its reserved ones. */\nfunction sheetNameOf(name: string | undefined): string {\n\tconst clean = (name ?? 'Sheet1').replace(/[\\\\/?*[\\]:]/g, ' ').trim();\n\n\treturn clean ? clean.slice(0, 31) : 'Sheet1';\n}\n\n/** The parts of the workbook that never change. */\nconst CONTENT_TYPES = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/><Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/><Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/></Types>`;\n\nconst ROOT_RELS = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/></Relationships>`;\n\nconst WORKBOOK_RELS = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/><Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/></Relationships>`;\n\n/** Three slots: plain, a bold header, and a date. Everything else is Excel's default. */\nconst STYLES = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><numFmts count=\"1\"><numFmt numFmtId=\"164\" formatCode=\"yyyy\\\\-mm\\\\-dd\"/></numFmts><fonts count=\"2\"><font><sz val=\"11\"/><name val=\"Calibri\"/></font><font><b/><sz val=\"11\"/><name val=\"Calibri\"/></font></fonts><fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"gray125\"/></fill></fills><borders count=\"1\"><border/></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs><cellXfs count=\"3\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/><xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/><xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/></cellXfs><cellStyles count=\"1\"><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/></cellStyles></styleSheet>`;\n\n/**\n * Writes a sheet as an xlsx workbook.\n *\n * @param rows - The rows, as the sheet has them.\n * @param columns - The columns, which decide the order and the headers.\n * @param options - How to write it.\n * @returns The bytes of the file.\n */\nexport function sheetToXlsx<TRow>(\n\trows: readonly TRow[],\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[],\n\toptions: HubXlsxOptions = {}\n): Uint8Array {\n\tconst values = sheetValues(rows, columns, { formulas: options.values !== 'stored' && options.formulas !== false });\n\tconst withHeaders = options.headers !== false;\n\tconst lines: string[] = [];\n\n\tif (withHeaders) {\n\t\tconst cells = columns\n\t\t\t.map(\n\t\t\t\t(column, index) =>\n\t\t\t\t\t`<c r=\"${letter(index)}1\" s=\"${STYLE_HEADER}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(column.header)}</t></is></c>`\n\t\t\t)\n\t\t\t.join('');\n\n\t\tlines.push(`<row r=\"1\">${cells}</row>`);\n\t}\n\n\tvalues.forEach((line, rowIndex) => {\n\t\tconst number = rowIndex + (withHeaders ? 2 : 1);\n\t\tconst cells = line.map((value, index) => cellXml(`${letter(index)}${number}`, value, columns[index], options)).join('');\n\n\t\tlines.push(`<row r=\"${number}\">${cells}</row>`);\n\t});\n\n\tconst last = `${letter(Math.max(columns.length - 1, 0))}${Math.max(lines.length, 1)}`;\n\tconst sheet = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><dimension ref=\"A1:${last}\"/><sheetData>${lines.join('')}</sheetData></worksheet>`;\n\n\tconst workbook = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><sheets><sheet name=\"${escapeXml(sheetNameOf(options.sheetName))}\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>`;\n\n\t// `[Content_Types].xml` goes first because that is where a reader looks first, and several\n\t// older ones will not look anywhere else for it.\n\treturn zip([\n\t\t{ path: '[Content_Types].xml', data: CONTENT_TYPES },\n\t\t{ path: '_rels/.rels', data: ROOT_RELS },\n\t\t{ path: 'xl/workbook.xml', data: workbook },\n\t\t{ path: 'xl/_rels/workbook.xml.rels', data: WORKBOOK_RELS },\n\t\t{ path: 'xl/styles.xml', data: STYLES },\n\t\t{ path: 'xl/worksheets/sheet1.xml', data: sheet }\n\t]);\n}\n\n/**\n * Hands the reader an xlsx file to save.\n *\n * @param filename - What to call it; `.xlsx` is added when missing.\n * @param bytes - The workbook, from `sheetToXlsx`.\n */\nexport function downloadXlsx(filename: string, bytes: Uint8Array): void {\n\tconst name = /\\.xlsx$/i.test(filename) ? filename : `${filename}.xlsx`;\n\n\tdownloadBlob(name, new Blob([bytes as BlobPart], { type: XLSX_MEDIA_TYPE }));\n}\n","/**\n * Reading a zip archive, which is what an xlsx is.\n *\n * The writing side got away without compressing anything. Reading cannot: a workbook that came out\n * of Excel has every part deflated, and refusing those would mean refusing every real file. What\n * makes it possible without a dependency is that the platform already has the decompressor —\n * `DecompressionStream`, in every browser since 2023 and in Node since 18 — so all that is left is\n * the bookkeeping: find the directory at the end of the file, and for each entry work out where its\n * bytes start.\n *\n * Only the two storage methods that exist in practice are understood, stored and deflated. An\n * entry compressed any other way is left out rather than guessed at, and the caller sees a part it\n * asked for missing instead of a page of nonsense.\n */\n\n/** Where a reader looks for the directory: the last record in the file. */\nconst END_OF_DIRECTORY = 0x06054b50;\nconst DIRECTORY_ENTRY = 0x02014b50;\n\n/** Reads little-endian numbers, which is the only way a zip states a length. */\nfunction reader(bytes: Uint8Array) {\n\tconst view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n\treturn {\n\t\tu16: (at: number) => view.getUint16(at, true),\n\t\tu32: (at: number) => view.getUint32(at, true)\n\t};\n}\n\n/**\n * Undoes a deflated entry, with the decompressor the platform already has.\n *\n * Written against the stream reader directly rather than through `Blob` or `Response`, which are\n * the shorter spellings and are not there everywhere this runs.\n */\nasync function inflate(bytes: Uint8Array): Promise<Uint8Array> {\n\tconst stream = new DecompressionStream('deflate-raw');\n\tconst writer = stream.writable.getWriter();\n\n\t// The cast is TypeScript's business, not the runtime's: a `Uint8Array` may sit on a shared\n\t// buffer as far as the types are concerned, and a stream writer will not say so.\n\tvoid writer.write(bytes as unknown as BufferSource).then(() => writer.close());\n\n\tconst reader = stream.readable.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet size = 0;\n\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read();\n\n\t\tif (done) {\n\t\t\tbreak;\n\t\t}\n\n\t\tchunks.push(value);\n\t\tsize += value.length;\n\t}\n\n\tconst whole = new Uint8Array(size);\n\tlet at = 0;\n\n\tfor (const chunk of chunks) {\n\t\twhole.set(chunk, at);\n\t\tat += chunk.length;\n\t}\n\n\treturn whole;\n}\n\n/**\n * Takes an archive apart.\n *\n * @param bytes - The whole file.\n * @returns Each entry's contents, by its path inside the archive.\n * @throws When the file is not a zip at all, which for an xlsx means it is not a workbook.\n */\nexport async function unzip(bytes: Uint8Array): Promise<Map<string, Uint8Array>> {\n\tconst { u16, u32 } = reader(bytes);\n\tlet end = -1;\n\n\t// Backwards from the end, because the record that says where everything is may be followed by\n\t// a comment of any length up to 64k.\n\tfor (let at = bytes.length - 22; at >= 0 && at >= bytes.length - 22 - 0xffff; at--) {\n\t\tif (u32(at) === END_OF_DIRECTORY) {\n\t\t\tend = at;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (end < 0) {\n\t\tthrow new Error('Not a zip archive: no end-of-directory record.');\n\t}\n\n\tconst count = u16(end + 10);\n\tconst files = new Map<string, Uint8Array>();\n\tlet at = u32(end + 16);\n\n\tfor (let index = 0; index < count && u32(at) === DIRECTORY_ENTRY; index++) {\n\t\tconst method = u16(at + 10);\n\t\tconst compressed = u32(at + 20);\n\t\tconst nameLength = u16(at + 28);\n\t\tconst extraLength = u16(at + 30);\n\t\tconst commentLength = u16(at + 32);\n\t\tconst localAt = u32(at + 42);\n\t\tconst path = new TextDecoder().decode(bytes.subarray(at + 46, at + 46 + nameLength));\n\n\t\t// The local header repeats the name and carries extra fields of its own length, so where\n\t\t// the data starts can only be read there — not worked out from the directory entry.\n\t\tconst localNameLength = u16(localAt + 26);\n\t\tconst localExtraLength = u16(localAt + 28);\n\t\tconst from = localAt + 30 + localNameLength + localExtraLength;\n\t\tconst raw = bytes.subarray(from, from + compressed);\n\n\t\tif (method === 0) {\n\t\t\tfiles.set(path, raw);\n\t\t} else if (method === 8) {\n\t\t\tfiles.set(path, await inflate(raw));\n\t\t}\n\n\t\tat += 46 + nameLength + extraLength + commentLength;\n\t}\n\n\treturn files;\n}\n","import { HubSpreadsheetColumn } from '../models/spreadsheet.types';\nimport { HubSheetTable, tableToRecords } from './table-records';\nimport { unzip } from './unzip';\n\n/**\n * Reading an xlsx workbook.\n *\n * Only what a sheet of data needs: the first worksheet's cells, as text, with the headers if it has\n * them. Not the charts, not the pictures, not the pivot tables — a file with those in it still\n * reads, they are simply parts nobody opens here.\n *\n * Two things a workbook does that a CSV does not, and both have to be undone or the import is\n * wrong. A **shared string** is written once and pointed at from every cell that holds it, so a\n * column of the same word arrives as a column of numbers unless the table is read. And a **date**\n * is a count of days wearing a number format, so it arrives as `45306` unless the styles are read\n * to know which columns were dates.\n *\n * The XML is read with patterns rather than a parser. It is the part of this file to be suspicious\n * of, and it is a deliberate choice: these parts are machine-written, their shape is fixed by the\n * format, and `DOMParser` does not exist where the tests run. What it means in practice is that\n * anything beyond these few elements is not understood — and a workbook is not a document to be\n * edited here, only a file to be read once.\n */\n\n/** How a workbook is read. */\nexport interface HubXlsxReadOptions {\n\t/** Whether the first row holds the headers. On unless turned off. */\n\treadonly headers?: boolean;\n\t/** Which sheet to read, by name. The first one when not given. */\n\treadonly sheetName?: string;\n}\n\n/** Number formats that mean a date, as the format numbers them. */\nconst DATE_FORMAT_IDS = new Set([\n\t14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 45, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 58\n]);\n\n/** What Excel counts its days from. */\nconst EXCEL_EPOCH = Date.UTC(1899, 11, 30);\n\nconst decoder = new TextDecoder();\n\n/** Undoes the five escapes XML writes, which is all these parts contain. */\nfunction unescapeXml(value: string): string {\n\treturn value\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/"/g, '\"')\n\t\t.replace(/'/g, \"'\")\n\t\t.replace(/&#(\\d+);/g, (_, code) => String.fromCodePoint(Number(code)))\n\t\t.replace(/&/g, '&');\n}\n\n/** A column letter back to its place: A is 0, AA is 26. */\nfunction columnAt(reference: string): number {\n\tconst letters = /^([A-Z]+)/.exec(reference)?.[1] ?? 'A';\n\tlet index = 0;\n\n\tfor (const letter of letters) {\n\t\tindex = index * 26 + (letter.charCodeAt(0) - 64);\n\t}\n\n\treturn index - 1;\n}\n\n/** Every `<si>` of the shared-string table, in order, runs of formatting joined back together. */\nfunction sharedStrings(xml: string | undefined): string[] {\n\tif (!xml) {\n\t\treturn [];\n\t}\n\n\treturn [...xml.matchAll(/<si>([\\s\\S]*?)<\\/si>/g)].map((item) =>\n\t\t[...item[1].matchAll(/<t[^>]*>([\\s\\S]*?)<\\/t>/g)].map((piece) => unescapeXml(piece[1])).join('')\n\t);\n}\n\n/** Which style slots mean a date, worked out from the number format each one points at. */\nfunction dateStyles(xml: string | undefined): Set<number> {\n\tconst dates = new Set<number>();\n\n\tif (!xml) {\n\t\treturn dates;\n\t}\n\n\tconst custom = new Map<number, string>();\n\n\tfor (const format of xml.matchAll(/<numFmt[^>]*numFmtId=\"(\\d+)\"[^>]*formatCode=\"([^\"]*)\"/g)) {\n\t\tcustom.set(Number(format[1]), unescapeXml(format[2]));\n\t}\n\n\tconst cellXfs = /<cellXfs[^>]*>([\\s\\S]*?)<\\/cellXfs>/.exec(xml)?.[1] ?? '';\n\n\t[...cellXfs.matchAll(/<xf[^>]*\\/?>/g)].forEach((slot, index) => {\n\t\tconst id = Number(/numFmtId=\"(\\d+)\"/.exec(slot[0])?.[1] ?? 0);\n\n\t\tif (DATE_FORMAT_IDS.has(id)) {\n\t\t\tdates.add(index);\n\n\t\t\treturn;\n\t\t}\n\n\t\t// A custom format is a date when it says so: day, month or year outside quoted text. The\n\t\t// stripping matters — `\"day \"0` is a label, not a date.\n\t\tconst code = custom.get(id);\n\n\t\tif (code && /[ymd]/i.test(code.replace(/\"[^\"]*\"/g, '').replace(/\\[[^\\]]*\\]/g, ''))) {\n\t\t\tdates.add(index);\n\t\t}\n\t});\n\n\treturn dates;\n}\n\n/** A day count as an ISO date, which is what a date column of this sheet holds. */\nfunction isoDate(serial: number): string {\n\treturn new Date(EXCEL_EPOCH + Math.round(serial) * 86_400_000).toISOString().slice(0, 10);\n}\n\n/** Which worksheet part to read, following the workbook's own list rather than guessing at a name. */\nfunction worksheetPath(files: Map<string, Uint8Array>, sheetName: string | undefined): string | undefined {\n\tconst workbook = files.has('xl/workbook.xml') ? decoder.decode(files.get('xl/workbook.xml')) : '';\n\tconst rels = files.has('xl/_rels/workbook.xml.rels') ? decoder.decode(files.get('xl/_rels/workbook.xml.rels')) : '';\n\tconst sheets = [...workbook.matchAll(/<sheet\\s[^>]*\\/?>/g)].map((sheet) => ({\n\t\tname: unescapeXml(/name=\"([^\"]*)\"/.exec(sheet[0])?.[1] ?? ''),\n\t\trel: /r:id=\"([^\"]*)\"/.exec(sheet[0])?.[1] ?? ''\n\t}));\n\n\tconst wanted = sheetName ? sheets.find((sheet) => sheet.name === sheetName) : sheets[0];\n\tconst target = wanted ? new RegExp(`<Relationship[^>]*Id=\"${wanted.rel}\"[^>]*Target=\"([^\"]*)\"`).exec(rels)?.[1] : undefined;\n\n\tif (target) {\n\t\tconst path = target.replace(/^\\/?xl\\//, '').replace(/^\\//, '');\n\n\t\tif (files.has(`xl/${path}`)) {\n\t\t\treturn `xl/${path}`;\n\t\t}\n\t}\n\n\t// A workbook whose relationships could not be followed still has its sheets where everyone\n\t// puts them. Better to read the file than to refuse it over a part nobody will ever look at.\n\treturn [...files.keys()].find((path) => path.startsWith('xl/worksheets/') && path.endsWith('.xml'));\n}\n\n/**\n * Reads a workbook's first sheet as a table of text.\n *\n * @param bytes - The whole file, as it was read or dropped.\n * @param options - How to read it.\n * @returns The headers, if it has them, and every row.\n * @throws When the file is not a workbook at all.\n */\nexport async function xlsxToTable(bytes: Uint8Array, options: HubXlsxReadOptions = {}): Promise<HubSheetTable> {\n\tconst files = await unzip(bytes);\n\tconst path = worksheetPath(files, options.sheetName);\n\n\tif (!path) {\n\t\tthrow new Error('Not an xlsx workbook: no worksheet inside it.');\n\t}\n\n\tconst strings = sharedStrings(\n\t\tfiles.has('xl/sharedStrings.xml') ? decoder.decode(files.get('xl/sharedStrings.xml')) : undefined\n\t);\n\tconst dates = dateStyles(files.has('xl/styles.xml') ? decoder.decode(files.get('xl/styles.xml')) : undefined);\n\tconst sheet = decoder.decode(files.get(path));\n\tconst rows: string[][] = [];\n\n\tfor (const row of sheet.matchAll(/<row[^>]*>([\\s\\S]*?)<\\/row>/g)) {\n\t\tconst line: string[] = [];\n\n\t\tfor (const cell of row[1].matchAll(/<c(\\s[^>]*)>([\\s\\S]*?)<\\/c>/g)) {\n\t\t\tconst attributes = cell[1];\n\t\t\tconst at = columnAt(/r=\"([A-Z]+)/.exec(attributes)?.[1] ?? '');\n\t\t\tconst type = /t=\"([^\"]*)\"/.exec(attributes)?.[1] ?? 'n';\n\t\t\tconst style = Number(/s=\"(\\d+)\"/.exec(attributes)?.[1] ?? -1);\n\t\t\tconst value = /<v>([\\s\\S]*?)<\\/v>/.exec(cell[2])?.[1];\n\t\t\tlet text = '';\n\n\t\t\tif (type === 's') {\n\t\t\t\ttext = strings[Number(value ?? -1)] ?? '';\n\t\t\t} else if (type === 'inlineStr') {\n\t\t\t\ttext = [...cell[2].matchAll(/<t[^>]*>([\\s\\S]*?)<\\/t>/g)].map((piece) => unescapeXml(piece[1])).join('');\n\t\t\t} else if (type === 'b') {\n\t\t\t\ttext = value === '1' ? 'true' : 'false';\n\t\t\t} else if (value !== undefined) {\n\t\t\t\tconst number = Number(value);\n\n\t\t\t\ttext = dates.has(style) && Number.isFinite(number) ? isoDate(number) : unescapeXml(value);\n\t\t\t}\n\n\t\t\t// Cells are absent where they are empty, so the gaps have to be filled or every value\n\t\t\t// after the first empty cell lands in the wrong column.\n\t\t\twhile (line.length < at) {\n\t\t\t\tline.push('');\n\t\t\t}\n\n\t\t\tline[at] = text;\n\t\t}\n\n\t\trows.push(line);\n\t}\n\n\tif (options.headers === false || !rows.length) {\n\t\treturn { headers: null, rows };\n\t}\n\n\treturn { headers: rows[0], rows: rows.slice(1) };\n}\n\n/**\n * Reads a workbook into rows keyed by column alias, matching its headers to the sheet's columns.\n *\n * @returns One record per row of the file, keyed by column alias.\n */\nexport async function xlsxToRecords<TRow>(\n\tbytes: Uint8Array,\n\tcolumns: readonly HubSpreadsheetColumn<TRow>[],\n\toptions: HubXlsxReadOptions = {}\n): Promise<Array<Record<string, string>>> {\n\treturn tableToRecords(await xlsxToTable(bytes, options), columns);\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { HUB_SPREADSHEET_CONTROLS } from './editor-adapter.token';\nimport { HubSpreadsheetControlsAdapter } from './editor-adapter.types';\n\n/**\n * Registers the control adapter a sheet opens its list cells with.\n *\n * ```ts\n * import { provideHubSpreadsheetControls } from 'ng-hub-ui-spreadsheet';\n * import { hubFormControlAdapter } from 'ng-hub-ui-forms';\n *\n * providers: [provideHubSpreadsheetControls(hubFormControlAdapter)];\n * ```\n *\n * Every list column then opens with that control, with no template written per sheet. A single\n * column that needs something else still overrides it with `hubSpreadsheetEditor`, which wins.\n *\n * @param adapter - The implementation to use, e.g. `hubFormControlAdapter` from `ng-hub-ui-forms`.\n * @returns Providers to add to the application, or to one component.\n */\nexport function provideHubSpreadsheetControls(adapter: HubSpreadsheetControlsAdapter): EnvironmentProviders {\n\treturn makeEnvironmentProviders([\n\t\t{\n\t\t\tprovide: HUB_SPREADSHEET_CONTROLS,\n\t\t\tuseValue: adapter\n\t\t}\n\t]);\n}\n","/** English dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'en',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: 'Insert row above',\n\t\tINSERT_ROW_BELOW: 'Insert row below',\n\t\tDELETE_ROWS: 'Delete {{ count }} row(s)',\n\t\tINSERT_COLUMN_BEFORE: 'Insert column before',\n\t\tINSERT_COLUMN_AFTER: 'Insert column after',\n\t\tDELETE_COLUMNS: 'Delete {{ count }} column(s)',\n\t\tMERGE_CELLS: 'Merge {{ count }} cells',\n\t\tUNMERGE_CELLS: 'Split {{ count }} block(s)',\n\t\tROW_ACTIONS: 'Row and column actions'\n\t}\n};\n","/** Spanish dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'es',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: 'Insertar fila encima',\n\t\tINSERT_ROW_BELOW: 'Insertar fila debajo',\n\t\tDELETE_ROWS: 'Borrar {{ count }} fila(s)',\n\t\tINSERT_COLUMN_BEFORE: 'Insertar columna antes',\n\t\tINSERT_COLUMN_AFTER: 'Insertar columna después',\n\t\tDELETE_COLUMNS: 'Borrar {{ count }} columna(s)',\n\t\tMERGE_CELLS: 'Combinar {{ count }} celdas',\n\t\tUNMERGE_CELLS: 'Separar {{ count }} bloque(s)',\n\t\tROW_ACTIONS: 'Acciones de filas y columnas'\n\t}\n};\n","/** French dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'fr',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: 'Insérer une ligne au-dessus',\n\t\tINSERT_ROW_BELOW: 'Insérer une ligne en dessous',\n\t\tDELETE_ROWS: 'Supprimer {{ count }} ligne(s)',\n\t\tINSERT_COLUMN_BEFORE: 'Insérer une colonne avant',\n\t\tINSERT_COLUMN_AFTER: 'Insérer une colonne après',\n\t\tDELETE_COLUMNS: 'Supprimer {{ count }} colonne(s)',\n\t\tMERGE_CELLS: 'Fusionner {{ count }} cellules',\n\t\tUNMERGE_CELLS: 'Séparer {{ count }} bloc(s)',\n\t\tROW_ACTIONS: 'Actions sur lignes et colonnes'\n\t}\n};\n","/** German dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'de',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: 'Zeile darüber einfügen',\n\t\tINSERT_ROW_BELOW: 'Zeile darunter einfügen',\n\t\tDELETE_ROWS: '{{ count }} Zeile(n) löschen',\n\t\tINSERT_COLUMN_BEFORE: 'Spalte davor einfügen',\n\t\tINSERT_COLUMN_AFTER: 'Spalte danach einfügen',\n\t\tDELETE_COLUMNS: '{{ count }} Spalte(n) löschen',\n\t\tMERGE_CELLS: '{{ count }} Zellen verbinden',\n\t\tUNMERGE_CELLS: '{{ count }} Block/Blöcke trennen',\n\t\tROW_ACTIONS: 'Aktionen für Zeilen und Spalten'\n\t}\n};\n","/** Russian dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'ru',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: 'Вставить строку выше',\n\t\tINSERT_ROW_BELOW: 'Вставить строку ниже',\n\t\tDELETE_ROWS: 'Удалить строк: {{ count }}',\n\t\tINSERT_COLUMN_BEFORE: 'Вставить столбец слева',\n\t\tINSERT_COLUMN_AFTER: 'Вставить столбец справа',\n\t\tDELETE_COLUMNS: 'Удалить столбцов: {{ count }}',\n\t\tMERGE_CELLS: 'Объединить {{ count }} ячеек',\n\t\tUNMERGE_CELLS: 'Разделить {{ count }} блок(ов)',\n\t\tROW_ACTIONS: 'Действия со строками и столбцами'\n\t}\n};\n","/** Japanese dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'ja',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: '上に行を挿入',\n\t\tINSERT_ROW_BELOW: '下に行を挿入',\n\t\tDELETE_ROWS: '{{ count }} 行を削除',\n\t\tINSERT_COLUMN_BEFORE: '左に列を挿入',\n\t\tINSERT_COLUMN_AFTER: '右に列を挿入',\n\t\tDELETE_COLUMNS: '{{ count }} 列を削除',\n\t\tMERGE_CELLS: '{{ count }} 個のセルを結合',\n\t\tUNMERGE_CELLS: '{{ count }} 個の結合を解除',\n\t\tROW_ACTIONS: '行と列の操作'\n\t}\n};\n","/** Chinese dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'zh',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: '在上方插入行',\n\t\tINSERT_ROW_BELOW: '在下方插入行',\n\t\tDELETE_ROWS: '删除 {{ count }} 行',\n\t\tINSERT_COLUMN_BEFORE: '在左侧插入列',\n\t\tINSERT_COLUMN_AFTER: '在右侧插入列',\n\t\tDELETE_COLUMNS: '删除 {{ count }} 列',\n\t\tMERGE_CELLS: '合并 {{ count }} 个单元格',\n\t\tUNMERGE_CELLS: '拆分 {{ count }} 个合并块',\n\t\tROW_ACTIONS: '行与列操作'\n\t}\n};\n","/** Arabic dictionary for the spreadsheet's own labels. */\nexport const locale = {\n\tlang: 'ar',\n\tdata: {\n\t\tINSERT_ROW_ABOVE: 'إدراج صف أعلى',\n\t\tINSERT_ROW_BELOW: 'إدراج صف أسفل',\n\t\tDELETE_ROWS: 'حذف {{ count }} صف',\n\t\tINSERT_COLUMN_BEFORE: 'إدراج عمود قبل',\n\t\tINSERT_COLUMN_AFTER: 'إدراج عمود بعد',\n\t\tDELETE_COLUMNS: 'حذف {{ count }} عمود',\n\t\tMERGE_CELLS: 'دمج {{ count }} خلية',\n\t\tUNMERGE_CELLS: 'فصل {{ count }} كتلة',\n\t\tROW_ACTIONS: 'إجراءات الصفوف والأعمدة'\n\t}\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["failed","EXCEL_EPOCH","locale"],"mappings":"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"}
|