@lilydesignsystem/angular-data-grid 0.9.0 → 0.10.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.
@@ -1 +1 @@
1
- {"version":3,"file":"lilydesignsystem-angular-data-grid.mjs","names":[],"sources":["../../export-data.ts","../../cell-types.ts","../../data-grid.component.ts"],"sourcesContent":["// Table export for DataGrid: CSV, TSV and Excel (.xlsx), as pure functions.\n//\n// Nothing here knows about the grid. A table is a header row plus rows of\n// cell values, and every function turns one into text or bytes, so a consumer\n// who wants their own export button (or a server-side export) can call them\n// directly. DataGrid's own buttons are a thin layer on top.\n//\n// The .xlsx writer has no dependencies: a workbook is a ZIP of a few XML\n// parts, and the ZIP here only *stores* (no compression), which Excel,\n// LibreOffice, Numbers and Google Sheets all read. Entries carry a fixed\n// timestamp, so the same table always produces the same bytes.\n\nexport type ExportFormat = \"csv\" | \"tsv\" | \"xlsx\";\n\n/**\n * A live formula and the result it last computed. In an .xlsx the cell keeps the formula with the result cached\n * (a spreadsheet user keeps the live formula); CSV and TSV carry only the result.\n */\nexport type ExportFormula = { formula: string; result: unknown };\n\n/** Whether a cell value is an {@link ExportFormula}. */\nexport function isExportFormula(value: unknown): value is ExportFormula {\n return !!value && typeof value === \"object\" && !(value instanceof Date) && typeof (value as ExportFormula).formula === \"string\" && \"result\" in (value as object);\n}\n\n/** A header row and rows of cell values. A cell is a string, number, boolean, `Date`, an {@link ExportFormula}, or empty. */\nexport type ExportTable = {\n headers: string[];\n rows: unknown[][];\n};\n\nexport type DelimitedOptions = {\n /** Field separator. Default `\",\"` (use `\"\\t\"` for TSV). */\n delimiter?: string;\n /** Write the header row. Default true. */\n header?: boolean;\n /** Prefix a UTF-8 byte-order mark so Excel opens the file as UTF-8. Default false. */\n bom?: boolean;\n /** Defuse spreadsheet formulas: a string starting with `=`, `+`, `-`, `@`, tab or CR gets a leading `'`. Default true. */\n safe?: boolean;\n /** Line ending. Default `\"\\r\\n\"` (RFC 4180). */\n eol?: string;\n};\n\nexport type XlsxOptions = {\n /** Worksheet name (31 characters at most; `[]:*?/\\` are replaced). Default `\"Sheet1\"`. */\n sheetName?: string;\n /** Write the header row, in bold. Default true. */\n header?: boolean;\n};\n\nexport const MIME_TYPES: Record<ExportFormat, string> = {\n csv: \"text/csv;charset=utf-8\",\n tsv: \"text/tab-separated-values;charset=utf-8\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n};\n\n// ---------------------------------------------------------------------\n// Delimited text (CSV / TSV)\n// ---------------------------------------------------------------------\n\nconst FORMULA_START = /^[=+\\-@\\t\\r]/;\n\n/** One cell as text. Numbers and booleans are never treated as formulas; only strings are defused. */\nexport function cellText(value: unknown, safe = true): string {\n if (value === null || value === undefined) return \"\";\n if (isExportFormula(value)) return cellText(value.result, safe);\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return \"\";\n // A date at exactly UTC midnight is a civil date: write it without a time of day.\n const iso = value.toISOString();\n return iso.endsWith(\"T00:00:00.000Z\") ? iso.slice(0, 10) : iso;\n }\n if (typeof value === \"number\") return Number.isFinite(value) ? String(value) : \"\";\n if (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n const text = String(value);\n return safe && FORMULA_START.test(text) ? `'${text}` : text;\n}\n\nfunction quoteField(text: string, delimiter: string): string {\n return text.includes(delimiter) || /[\"\\r\\n]/.test(text) ? `\"${text.replace(/\"/g, '\"\"')}\"` : text;\n}\n\n/** CSV/TSV text for a table. Fields containing the delimiter, a quote or a line break are quoted. */\nexport function toDelimited(table: ExportTable, options: DelimitedOptions = {}): string {\n const { delimiter = \",\", header = true, bom = false, safe = true, eol = \"\\r\\n\" } = options;\n const lines: string[] = [];\n if (header) lines.push(table.headers.map((h) => quoteField(cellText(h, safe), delimiter)).join(delimiter));\n for (const row of table.rows) {\n lines.push(table.headers.map((_, i) => quoteField(cellText(row[i], safe), delimiter)).join(delimiter));\n }\n return (bom ? \"\" : \"\") + lines.join(eol) + (lines.length > 0 ? eol : \"\");\n}\n\nexport function toCsv(table: ExportTable, options: Omit<DelimitedOptions, \"delimiter\"> = {}): string {\n return toDelimited(table, { ...options, delimiter: \",\" });\n}\n\nexport function toTsv(table: ExportTable, options: Omit<DelimitedOptions, \"delimiter\"> = {}): string {\n return toDelimited(table, { ...options, delimiter: \"\\t\" });\n}\n\n// ---------------------------------------------------------------------\n// Excel (.xlsx)\n// ---------------------------------------------------------------------\n\nconst encoder = new TextEncoder();\n\n/** XML text with the characters XML 1.0 forbids removed. */\nfunction xmlEscape(text: string): string {\n return text\n .replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F￾￿]/g, \"\")\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/** Column index (0-based) to a spreadsheet column name: 0 → A, 25 → Z, 26 → AA. */\nexport function columnName(index: number): string {\n let n = index;\n let name = \"\";\n do {\n name = String.fromCharCode(65 + (n % 26)) + name;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return name;\n}\n\n/** Days since 1899-12-30 (Excel's day 0, with its 1900 leap-year quirk absorbed), with the time of day as a fraction. */\nfunction excelSerial(date: Date): number {\n return date.getTime() / 86_400_000 + 25_569;\n}\n\nfunction sheetNameFor(name: string): string {\n const cleaned = name.replace(/[[\\]:*?/\\\\]/g, \" \").replace(/\\s+/g, \" \").trim().slice(0, 31);\n return cleaned || \"Sheet1\";\n}\n\n// Cell styles: 0 default, 1 date, 2 date and time, 3 bold (headers).\nconst STYLES_XML =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">' +\n '<numFmts count=\"2\"><numFmt numFmtId=\"164\" formatCode=\"yyyy\\\\-mm\\\\-dd\"/><numFmt numFmtId=\"165\" formatCode=\"yyyy\\\\-mm\\\\-dd\\\\ hh:mm:ss\"/></numFmts>' +\n '<fonts count=\"2\"><font><sz val=\"11\"/><name val=\"Calibri\"/></font><font><b/><sz val=\"11\"/><name val=\"Calibri\"/></font></fonts>' +\n '<fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"gray125\"/></fill></fills>' +\n '<borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>' +\n '<cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>' +\n '<cellXfs count=\"4\">' +\n '<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>' +\n '<xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>' +\n '<xf numFmtId=\"165\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>' +\n '<xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>' +\n \"</cellXfs>\" +\n '<cellStyles count=\"1\"><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/></cellStyles>' +\n \"</styleSheet>\";\n\n/** A formula cell: the expression (without its leading `=`) and the result it last computed, cached. */\nfunction formulaXml(ref: string, value: ExportFormula): string {\n const expression = xmlEscape(value.formula.replace(/^=/, \"\"));\n const result = value.result;\n if (typeof result === \"number\" && Number.isFinite(result)) return `<c r=\"${ref}\"><f>${expression}</f><v>${result}</v></c>`;\n if (typeof result === \"boolean\") return `<c r=\"${ref}\" t=\"b\"><f>${expression}</f><v>${result ? 1 : 0}</v></c>`;\n if (result instanceof Date && !Number.isNaN(result.getTime())) {\n const timeOfDay = result.getTime() % 86_400_000 !== 0;\n return `<c r=\"${ref}\" s=\"${timeOfDay ? 2 : 1}\"><f>${expression}</f><v>${excelSerial(result)}</v></c>`;\n }\n if (result === null || result === undefined) return `<c r=\"${ref}\"><f>${expression}</f></c>`;\n return `<c r=\"${ref}\" t=\"str\"><f>${expression}</f><v>${xmlEscape(String(result))}</v></c>`;\n}\n\nfunction cellXml(ref: string, value: unknown, headerStyle = false): string {\n if (value === null || value === undefined) return \"\";\n if (isExportFormula(value)) return formulaXml(ref, value);\n const s = headerStyle ? ' s=\"3\"' : \"\";\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return \"\";\n const timeOfDay = value.getTime() % 86_400_000 !== 0;\n return `<c r=\"${ref}\" s=\"${timeOfDay ? 2 : 1}\"><v>${excelSerial(value)}</v></c>`;\n }\n if (typeof value === \"number\") return Number.isFinite(value) ? `<c r=\"${ref}\"${s}><v>${value}</v></c>` : \"\";\n if (typeof value === \"boolean\") return `<c r=\"${ref}\"${s} t=\"b\"><v>${value ? 1 : 0}</v></c>`;\n // A string is stored as text, so it is never read as a formula.\n return `<c r=\"${ref}\"${s} t=\"inlineStr\"><is><t xml:space=\"preserve\">${xmlEscape(String(value))}</t></is></c>`;\n}\n\nfunction sheetXml(table: ExportTable, header: boolean): string {\n const rows: string[] = [];\n let rowNumber = 0;\n if (header) {\n rowNumber += 1;\n rows.push(\n `<row r=\"${rowNumber}\">${table.headers.map((h, i) => cellXml(`${columnName(i)}${rowNumber}`, h, true)).join(\"\")}</row>`,\n );\n }\n for (const row of table.rows) {\n rowNumber += 1;\n const cells = table.headers.map((_, i) => cellXml(`${columnName(i)}${rowNumber}`, row[i])).join(\"\");\n rows.push(`<row r=\"${rowNumber}\">${cells}</row>`);\n }\n return (\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">' +\n (header && table.headers.length > 0 ? '<sheetViews><sheetView workbookViewId=\"0\"><pane ySplit=\"1\" topLeftCell=\"A2\" activePane=\"bottomLeft\" state=\"frozen\"/></sheetView></sheetViews>' : \"\") +\n `<sheetData>${rows.join(\"\")}</sheetData></worksheet>`\n );\n}\n\n/** An .xlsx workbook with one worksheet, as bytes. */\nexport function toXlsx(table: ExportTable, options: XlsxOptions = {}): Uint8Array {\n const { sheetName = \"Sheet1\", header = true } = options;\n const files: Record<string, string> = {\n \"[Content_Types].xml\":\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">' +\n '<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>' +\n '<Default Extension=\"xml\" ContentType=\"application/xml\"/>' +\n '<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>' +\n '<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>' +\n '<Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>' +\n \"</Types>\",\n \"_rels/.rels\":\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">' +\n '<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>' +\n \"</Relationships>\",\n \"xl/workbook.xml\":\n '<?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\">' +\n `<sheets><sheet name=\"${xmlEscape(sheetNameFor(sheetName))}\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>`,\n \"xl/_rels/workbook.xml.rels\":\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">' +\n '<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>' +\n '<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>' +\n \"</Relationships>\",\n \"xl/styles.xml\": STYLES_XML,\n \"xl/worksheets/sheet1.xml\": sheetXml(table, header),\n };\n return zipStore(Object.entries(files).map(([name, text]) => ({ name, data: encoder.encode(text) })));\n}\n\n// ---------------------------------------------------------------------\n// ZIP (store only)\n// ---------------------------------------------------------------------\n\nlet crcTable: Uint32Array | undefined;\n\nexport function crc32(bytes: Uint8Array): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let crc = 0xffffffff;\n for (let i = 0; i < bytes.length; i++) crc = crcTable[(crc ^ bytes[i]) & 0xff] ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n// 1980-01-01 00:00:00, the ZIP epoch: a fixed stamp keeps the output reproducible.\nconst DOS_TIME = 0x0000;\nconst DOS_DATE = 0x0021;\n\n/** A ZIP archive holding `entries` uncompressed. */\nexport function zipStore(entries: { name: string; data: Uint8Array }[]): Uint8Array {\n const parts: Uint8Array[] = [];\n const central: Uint8Array[] = [];\n let offset = 0;\n for (const { name, data } of entries) {\n const nameBytes = encoder.encode(name);\n const crc = crc32(data);\n const local = new DataView(new ArrayBuffer(30));\n local.setUint32(0, 0x04034b50, true);\n local.setUint16(4, 20, true); // version needed\n local.setUint16(6, 0x0800, true); // flags: UTF-8 names\n local.setUint16(8, 0, true); // method: stored\n local.setUint16(10, DOS_TIME, true);\n local.setUint16(12, DOS_DATE, true);\n local.setUint32(14, crc, true);\n local.setUint32(18, data.length, true);\n local.setUint32(22, data.length, true);\n local.setUint16(26, nameBytes.length, true);\n local.setUint16(28, 0, true);\n parts.push(new Uint8Array(local.buffer), nameBytes, data);\n\n const entry = new DataView(new ArrayBuffer(46));\n entry.setUint32(0, 0x02014b50, true);\n entry.setUint16(4, 20, true); // version made by\n entry.setUint16(6, 20, true); // version needed\n entry.setUint16(8, 0x0800, true);\n entry.setUint16(10, 0, true);\n entry.setUint16(12, DOS_TIME, true);\n entry.setUint16(14, DOS_DATE, true);\n entry.setUint32(16, crc, true);\n entry.setUint32(20, data.length, true);\n entry.setUint32(24, data.length, true);\n entry.setUint16(28, nameBytes.length, true);\n entry.setUint32(42, offset, true);\n central.push(new Uint8Array(entry.buffer), nameBytes);\n\n offset += 30 + nameBytes.length + data.length;\n }\n const centralSize = central.reduce((n, p) => n + p.length, 0);\n const end = new DataView(new ArrayBuffer(22));\n end.setUint32(0, 0x06054b50, true);\n end.setUint16(8, entries.length, true);\n end.setUint16(10, entries.length, true);\n end.setUint32(12, centralSize, true);\n end.setUint32(16, offset, true);\n const all = [...parts, ...central, new Uint8Array(end.buffer)];\n const out = new Uint8Array(all.reduce((n, p) => n + p.length, 0));\n let at = 0;\n for (const p of all) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------\n// Files\n// ---------------------------------------------------------------------\n\n/** The file for `table` in `format`, as a `Blob`. CSV and TSV carry a UTF-8 byte-order mark so Excel reads them as UTF-8. */\nexport function exportBlob(table: ExportTable, format: ExportFormat, options: { sheetName?: string; header?: boolean } = {}): Blob {\n if (format === \"xlsx\") return new Blob([toXlsx(table, options) as BlobPart], { type: MIME_TYPES.xlsx });\n const text = toDelimited(table, { delimiter: format === \"tsv\" ? \"\\t\" : \",\", header: options.header, bom: true });\n return new Blob([text], { type: MIME_TYPES[format] });\n}\n\n/** A filename with the format's extension, without doubling one the name already has. */\nexport function exportFilename(base: string, format: ExportFormat): string {\n const cleaned = base.replace(/[\\\\/:*?\"<>|\\u0000-\\u001F]/g, \"-\").trim() || \"export\";\n return cleaned.toLowerCase().endsWith(`.${format}`) ? cleaned : `${cleaned}.${format}`;\n}\n\n/** Saves a blob through a temporary link. Does nothing outside a browser. */\nexport function downloadBlob(blob: Blob, filename: string): void {\n if (typeof document === \"undefined\" || typeof URL === \"undefined\" || !URL.createObjectURL) return;\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n // Revoking at once can cancel the download in some browsers.\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n","// Cell types for DataGrid: a `column.type` is a named bundle of defaults for the\n// hooks a column already has (`format`, `compare`, `filterText`, `exportValue`,\n// `align`, `editor`). Nothing here is new machinery: `resolveColumn` fills in\n// what the column left out, and a column's own props always win.\n//\n// Values are plain data. Display is derived: no English, no default locale (with\n// no `locale` a value shows as stored), no HTML, no icons. See\n// spec/cell-types/index.md.\n\nexport type DataGridCellType =\n | \"text\"\n | \"number\"\n | \"link\"\n | \"date\"\n | \"time\"\n | \"time-zone\"\n | \"select\"\n | \"radio\"\n | \"person\"\n | \"file\"\n | \"rollup\"\n | \"formula\";\n\n/** A time of day and the zone it is stated in (an IANA zone id, or a bare offset such as `+01:00`). */\nexport type DataGridZonedTime = { time: string; timeZone: string };\n\n/** One person: the name is always shown as text; the avatar is the consumer's. */\nexport type DataGridPerson = { id: string; name?: string; email?: string; avatarUrl?: string };\n\n/** One file's metadata. The bytes live elsewhere; the grid never uploads. */\nexport type DataGridFile = { id: string; name: string; size?: number; type?: string; href?: string };\n\n/** What a rollup reduces its related values with. */\nexport type DataGridAggregate =\n | \"count\"\n | \"countUnique\"\n | \"sum\"\n | \"avg\"\n | \"median\"\n | \"min\"\n | \"max\"\n | \"range\"\n | \"percentTrue\"\n | \"percentEmpty\";\n\n/** What a formula engine hands back: a value, or an error message shown as text. */\nexport type DataGridFormulaResult = { value: unknown } | { error: string };\n\n/** What a formula engine is given. `rows` is every row, for references to other rows. */\nexport type DataGridFormulaContext = { row: Record<string, unknown>; rows: Record<string, unknown>[]; columnId: string };\n\n/** An option of a `select` or `radio` column. The label is displayed; the id is stored. */\nexport type DataGridOption = { id: string; label: string; disabled?: boolean; group?: string; [key: string]: unknown };\n\n/** A link value: an address, or an address with a label. */\nexport type DataGridLink = { href: string; label?: string; external?: boolean };\n\n/** The column facets a type can fill in. Structural so this module does not import the grid. */\nexport type TypedColumn = {\n id: string;\n type?: DataGridCellType;\n locale?: string;\n options?: DataGridOption[];\n sortBy?: \"label\" | \"order\";\n exportAs?: \"label\" | \"id\" | \"email\";\n numberFormat?: Intl.NumberFormatOptions;\n dateFormat?: Intl.DateTimeFormatOptions;\n timeFormat?: Intl.DateTimeFormatOptions;\n accessor?: (row: Record<string, unknown>) => unknown;\n format?: (value: unknown, row: Record<string, unknown>) => string;\n compare?: (a: unknown, b: unknown) => number;\n filterText?: (value: unknown, row: Record<string, unknown>) => string;\n exportValue?: (row: Record<string, unknown>) => unknown;\n align?: \"start\" | \"center\" | \"end\";\n editor?: string;\n parse?: (draft: string, row: Record<string, unknown>) => unknown;\n editable?: boolean;\n /** `time-zone`: the zones the editor offers, as `{ id, label }`. */\n timeZones?: DataGridOption[];\n /** `time-zone`: the date (ISO) used to order zoned times and to name a zone. Never computed here. */\n referenceDate?: string;\n /** `rollup`: how the related values are reduced. */\n aggregate?: DataGridAggregate;\n /** `rollup`: anything the named aggregates do not cover. */\n reduce?: (values: unknown[], row: Record<string, unknown>) => unknown;\n /** `rollup`: reads the related values. Defaults to the row's own array at the column id. */\n relation?: (row: Record<string, unknown>) => unknown[];\n /** `rollup` and `formula`: the type of the result, so it formats and sorts like one. */\n resultType?: \"number\" | \"date\" | \"text\";\n /** `formula`: evaluates an expression. Lily ships no engine and never evaluates a string itself. */\n evaluate?: (expression: string, context: DataGridFormulaContext) => DataGridFormulaResult;\n /** `person`: how many people show before \"+N\". */\n maxPeople?: number;\n /** `file`: formats a size in bytes for display. */\n formatSize?: (bytes: number) => string;\n /** Set by `resolveColumn` for a `formula`: the expression the row holds (the editor shows this, not the result). */\n source?: (row: Record<string, unknown>) => unknown;\n /** Set by `resolveColumn` for a `formula`: the error message for a row, or undefined. */\n errorOf?: (row: Record<string, unknown>) => string | undefined;\n};\n\nconst SAFE_SCHEME = /^(https?:|mailto:|tel:)/i;\nconst RELATIVE = /^(\\/(?!\\/)|\\.\\.?\\/|#|\\?)/;\n\n/** An address safe to put in an `href`: http(s), mailto, tel, or a relative one. Anything else (`javascript:`, `data:`) is null. */\nexport function safeHref(href: unknown): string | null {\n if (typeof href !== \"string\") return null;\n const text = href.trim();\n if (!text) return null;\n // Control characters are stripped by browsers when reading a scheme, so they cannot be allowed to hide one.\n // eslint-disable-next-line no-control-regex\n if (/[\\u0000-\\u001F\\u007F]/.test(text)) return null;\n return SAFE_SCHEME.test(text) || RELATIVE.test(text) ? text : null;\n}\n\n/** A link value as `{ href, label?, external? }`; a plain string is the address. */\nexport function linkParts(value: unknown): DataGridLink | null {\n if (value === null || value === undefined || value === \"\") return null;\n if (typeof value === \"string\") return { href: value };\n if (typeof value === \"object\" && typeof (value as DataGridLink).href === \"string\") return value as DataGridLink;\n return null;\n}\n\nexport function linkLabel(value: unknown): string {\n const link = linkParts(value);\n return link ? (link.label ?? link.href) : \"\";\n}\n\n/** A civil date `YYYY-MM-DD` that exists on the calendar. */\nexport function isCivilDate(text: unknown): text is string {\n if (typeof text !== \"string\" || !/^\\d{4}-\\d{2}-\\d{2}$/.test(text)) return false;\n const [y, m, d] = text.split(\"-\").map(Number);\n const date = new Date(Date.UTC(y, m - 1, d));\n return date.getUTCFullYear() === y && date.getUTCMonth() === m - 1 && date.getUTCDate() === d;\n}\n\n/** A civil time `HH:mm` or `HH:mm:ss`, 24-hour. */\nexport function isCivilTime(text: unknown): text is string {\n if (typeof text !== \"string\") return false;\n const match = /^(\\d{2}):(\\d{2})(?::(\\d{2}))?$/.exec(text);\n return !!match && Number(match[1]) < 24 && Number(match[2]) < 60 && (match[3] === undefined || Number(match[3]) < 60);\n}\n\n/** A civil date as a `Date` at UTC midnight, or null. Typed, so an export writes a real spreadsheet date. */\nexport function civilDateToDate(text: unknown): Date | null {\n if (text instanceof Date) return Number.isNaN(text.getTime()) ? null : text;\n return isCivilDate(text) ? new Date(`${text}T00:00:00Z`) : null;\n}\n\nconst isEmpty = (value: unknown) => value === null || value === undefined || value === \"\";\n\nconst OFFSET = /^([+-])(\\d{2}):?(\\d{2})$/;\n\n/** The zone's offset from UTC, in minutes, at an instant. A bare offset (`+01:00`) is its own answer. Null when the zone is unknown. */\nfunction zoneOffsetMinutes(timeZone: string, instantMs: number): number | null {\n const bare = OFFSET.exec(timeZone);\n if (bare) return (bare[1] === \"-\" ? -1 : 1) * (Number(bare[2]) * 60 + Number(bare[3]));\n try {\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n }).formatToParts(new Date(instantMs));\n const n = (type: string) => Number(parts.find((x) => x.type === type)?.value);\n const local = Date.UTC(n(\"year\"), n(\"month\") - 1, n(\"day\"), n(\"hour\") % 24, n(\"minute\"), n(\"second\"));\n return (local - Math.floor(instantMs / 1000) * 1000) / 60000;\n } catch {\n return null;\n }\n}\n\n/** An IANA zone id the platform knows, or a bare offset such as `+01:00`. */\nexport function isValidTimeZone(timeZone: unknown): timeZone is string {\n return typeof timeZone === \"string\" && timeZone !== \"\" && zoneOffsetMinutes(timeZone, 0) !== null;\n}\n\n/** A zoned time: `{ time: \"HH:mm[:ss]\", timeZone }` with a real time and a known zone. */\nexport function isZonedTime(value: unknown): value is DataGridZonedTime {\n return !!value && typeof value === \"object\" && isCivilTime((value as DataGridZonedTime).time) && isValidTimeZone((value as DataGridZonedTime).timeZone);\n}\n\n/**\n * A zoned time as a number for ordering. With a `referenceDate` (ISO, supplied by the consumer: never computed here)\n * it is the UTC minute of that instant, so equal instants compare equal; without one it is the stated local time and\n * the zone is ignored.\n */\nexport function zonedMinutes(value: unknown, referenceDate?: string): number | null {\n if (!isZonedTime(value)) return null;\n const [h, m, sec] = value.time.split(\":\").map(Number);\n const local = h * 60 + m + (sec || 0) / 60;\n if (!referenceDate || !isCivilDate(referenceDate)) return local;\n const [y, mo, d] = referenceDate.split(\"-\").map(Number);\n const guess = Date.UTC(y, mo - 1, d, h, m, sec || 0);\n const offset = zoneOffsetMinutes(value.timeZone, guess);\n if (offset === null) return local;\n return guess / 60000 - offset;\n}\n\n/** A zoned time as the UTC time of day (`HH:mm`) at a reference date. Null without a valid reference date or value. */\nexport function zonedUtcTime(value: unknown, referenceDate?: string): string | null {\n if (!referenceDate || !isCivilDate(referenceDate)) return null;\n const minutes = zonedMinutes(value, referenceDate);\n if (minutes === null) return null;\n const day = ((Math.round(minutes) % 1440) + 1440) % 1440;\n return `${String(Math.floor(day / 60)).padStart(2, \"0\")}:${String(day % 60).padStart(2, \"0\")}`;\n}\n\n/** The zone as text: its short name (`BST`) when there is a locale and a reference date, else the zone id as given. */\nfunction zoneLabel(timeZone: string, locale: string | undefined, referenceDate: string | undefined): string {\n if (!locale || !referenceDate || !isCivilDate(referenceDate) || OFFSET.test(timeZone)) return timeZone;\n try {\n const parts = new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: \"short\" }).formatToParts(new Date(`${referenceDate}T12:00:00Z`));\n return parts.find((x) => x.type === \"timeZoneName\")?.value ?? timeZone;\n } catch {\n return timeZone;\n }\n}\n\n/** The people in a value: one object or an array, each with an id. */\nexport function peopleOf(value: unknown): DataGridPerson[] {\n const list = Array.isArray(value) ? value : isEmpty(value) ? [] : [value];\n return list.filter((p): p is DataGridPerson => !!p && typeof p === \"object\" && typeof (p as DataGridPerson).id === \"string\");\n}\n\n/** A person's text: the name, or the id when there is none (never blank). */\nexport const personName = (person: DataGridPerson): string => (person.name ? person.name : person.id);\n\n/** The files in a value: an array of `{ id, name, … }`. */\nexport function filesOf(value: unknown): DataGridFile[] {\n return (Array.isArray(value) ? value : []).filter((f): f is DataGridFile => !!f && typeof f === \"object\" && typeof (f as DataGridFile).id === \"string\" && typeof (f as DataGridFile).name === \"string\");\n}\n\n/** Reduces related values to one result. An empty set is empty (null), not 0, except `count`. */\nexport function aggregateValues(kind: DataGridAggregate, values: unknown[]): unknown {\n const present = values.filter((v) => !isEmpty(v));\n const numbers = present.filter((v): v is number => typeof v === \"number\" && Number.isFinite(v));\n switch (kind) {\n case \"count\":\n return values.length;\n case \"countUnique\":\n return present.length === 0 ? null : new Set(present.map((v) => (typeof v === \"object\" ? JSON.stringify(v) : String(v)))).size;\n case \"sum\":\n return numbers.length === 0 ? null : numbers.reduce((a, b) => a + b, 0);\n case \"avg\":\n return numbers.length === 0 ? null : numbers.reduce((a, b) => a + b, 0) / numbers.length;\n case \"median\": {\n if (numbers.length === 0) return null;\n const sorted = numbers.slice().sort((a, b) => a - b);\n const mid = sorted.length >> 1;\n return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;\n }\n case \"min\":\n case \"max\": {\n const pool = numbers.length === present.length ? numbers : present.filter((v): v is string => typeof v === \"string\");\n if (pool.length === 0) return null;\n return (pool as (number | string)[]).reduce((a, b) => ((kind === \"min\" ? b < a : b > a) ? b : a));\n }\n case \"range\":\n return numbers.length === 0 ? null : Math.max(...numbers) - Math.min(...numbers);\n case \"percentTrue\": {\n const booleans = values.filter((v): v is boolean => typeof v === \"boolean\");\n return booleans.length === 0 ? null : (booleans.filter(Boolean).length / booleans.length) * 100;\n }\n case \"percentEmpty\":\n return values.length === 0 ? null : ((values.length - present.length) / values.length) * 100;\n }\n}\n\n/** Whether a (parsed) value is unacceptable for the column's type; the grid refuses the edit. Empty is always acceptable. */\nexport function isInvalidForType(column: TypedColumn, value: unknown): boolean {\n if (isEmpty(value)) return false;\n switch (column.type) {\n case \"number\":\n return typeof value !== \"number\" || !Number.isFinite(value);\n case \"link\":\n return safeHref(linkParts(value)?.href) === null;\n case \"date\":\n return !isCivilDate(value);\n case \"time\":\n return !isCivilTime(value);\n case \"time-zone\":\n return !isZonedTime(value);\n case \"select\":\n case \"radio\":\n return !(column.options ?? []).some((o) => o.id === value);\n case \"person\":\n return peopleOf(value).length === 0;\n default:\n return false;\n }\n}\n\nconst optionLabel = (column: TypedColumn, id: unknown): string => {\n const found = (column.options ?? []).find((o) => o.id === id);\n return found ? found.label : isEmpty(id) ? \"\" : String(id);\n};\n\n/** Formats a result by its declared type, so a rollup or formula of dates reads like a date. */\nfunction resultFormatter(column: TypedColumn, locale: string | undefined): (value: unknown) => string {\n const type = column.resultType ?? \"text\";\n if (type === \"number\") {\n const formatter = locale || column.numberFormat ? new Intl.NumberFormat(locale, column.numberFormat) : null;\n return (v) => (typeof v === \"number\" && Number.isFinite(v) ? (formatter ? formatter.format(v) : String(v)) : isEmpty(v) ? \"\" : String(v));\n }\n if (type === \"date\") {\n const formatter = locale || column.dateFormat ? new Intl.DateTimeFormat(locale, { dateStyle: \"medium\", ...column.dateFormat, timeZone: \"UTC\" }) : null;\n return (v) => {\n if (isEmpty(v)) return \"\";\n const date = civilDateToDate(v);\n return date ? (formatter ? formatter.format(date) : date.toISOString().slice(0, 10)) : String(v);\n };\n }\n return (v) => (isEmpty(v) ? \"\" : String(v));\n}\n\n/** Defaults a `type` gives its column. Anything the column sets itself replaces the matching default. */\nfunction typeDefaults(column: TypedColumn, gridLocale: string | undefined): Partial<TypedColumn> {\n const locale = column.locale ?? gridLocale;\n switch (column.type) {\n case \"text\":\n return {\n align: \"start\",\n editor: \"text\",\n ...(locale ? { compare: (a, b) => new Intl.Collator(locale).compare(String(a), String(b)) } : {}),\n };\n case \"number\": {\n const formatter = locale || column.numberFormat ? new Intl.NumberFormat(locale, column.numberFormat) : null;\n return {\n align: \"end\",\n editor: \"number\",\n ...(formatter ? { format: (v) => (typeof v === \"number\" && Number.isFinite(v) ? formatter.format(v) : \"\") } : {}),\n };\n }\n case \"link\":\n return {\n align: \"start\",\n editor: \"link\",\n format: (v) => linkLabel(v),\n filterText: (v) => {\n const link = linkParts(v);\n return link ? `${link.label ?? \"\"} ${link.href}`.trim() : \"\";\n },\n compare: (a, b) => {\n const x = linkLabel(a);\n const y = linkLabel(b);\n return locale ? new Intl.Collator(locale).compare(x, y) : x < y ? -1 : x > y ? 1 : 0;\n },\n exportValue: (row) => linkLabel(column.accessor ? column.accessor(row) : row[column.id]),\n parse: (draft, row) => {\n const previous = linkParts(column.accessor ? column.accessor(row) : row[column.id]);\n const href = draft.trim();\n if (!href) return null;\n return previous && typeof previous === \"object\" && (previous.label !== undefined || previous.external !== undefined)\n ? { ...previous, href }\n : href;\n },\n };\n case \"date\": {\n const formatter = locale || column.dateFormat\n ? new Intl.DateTimeFormat(locale, { dateStyle: \"medium\", ...column.dateFormat, timeZone: \"UTC\" })\n : null;\n return {\n align: \"start\",\n editor: \"date\",\n format: (v) => {\n if (isEmpty(v)) return \"\";\n const date = civilDateToDate(v);\n if (!date) return String(v);\n return formatter ? formatter.format(date) : date.toISOString().slice(0, 10);\n },\n exportValue: (row) => civilDateToDate(column.accessor ? column.accessor(row) : row[column.id]),\n };\n }\n case \"time\": {\n const formatter = locale || column.timeFormat\n ? new Intl.DateTimeFormat(locale, { timeStyle: \"short\", ...column.timeFormat, timeZone: \"UTC\" })\n : null;\n return {\n align: \"start\",\n editor: \"time\",\n format: (v) => {\n if (isEmpty(v)) return \"\";\n if (!isCivilTime(v)) return String(v);\n return formatter ? formatter.format(new Date(`1970-01-01T${v.length === 5 ? `${v}:00` : v}Z`)) : v;\n },\n };\n }\n case \"time-zone\": {\n const formatter = locale || column.timeFormat\n ? new Intl.DateTimeFormat(locale, { timeStyle: \"short\", ...column.timeFormat, timeZone: \"UTC\" })\n : null;\n const text = (v: unknown) => {\n if (isEmpty(v)) return \"\";\n if (!isZonedTime(v)) return String(v);\n const time = formatter ? formatter.format(new Date(`1970-01-01T${v.time.length === 5 ? `${v.time}:00` : v.time}Z`)) : v.time;\n return `${time} ${zoneLabel(v.timeZone, locale, column.referenceDate)}`;\n };\n return {\n align: \"start\",\n editor: \"time-zone\",\n format: text,\n compare: (a, b) => (zonedMinutes(a, column.referenceDate) ?? 0) - (zonedMinutes(b, column.referenceDate) ?? 0),\n exportValue: (row) => {\n const v = column.accessor ? column.accessor(row) : row[column.id];\n return isZonedTime(v) ? `${v.time} ${v.timeZone}` : null;\n },\n };\n }\n case \"person\": {\n const names = (v: unknown) => peopleOf(v).map(personName);\n const collator = locale ? new Intl.Collator(locale) : null;\n const order = (a: string, b: string) => (collator ? collator.compare(a, b) : a < b ? -1 : a > b ? 1 : 0);\n return {\n align: \"start\",\n editor: \"person\",\n format: (v) => names(v).join(\"; \"),\n filterText: (v) => peopleOf(v).map((p) => `${personName(p)} ${p.email ?? \"\"}`.trim()).join(\" \"),\n compare: (a, b) => {\n const x = names(a);\n const y = names(b);\n return order(x[0] ?? \"\", y[0] ?? \"\") || x.length - y.length;\n },\n exportValue: (row) => {\n const value = column.accessor ? column.accessor(row) : row[column.id];\n const parts = column.exportAs === \"email\" ? peopleOf(value).map((p) => p.email ?? \"\") : names(value);\n const joined = parts.join(\"; \");\n return joined.replace(/[;\\s]/g, \"\") === \"\" ? null : joined;\n },\n };\n }\n case \"file\": {\n const names = (v: unknown) => filesOf(v).map((f) => f.name);\n const collator = locale ? new Intl.Collator(locale) : null;\n const order = (a: string, b: string) => (collator ? collator.compare(a, b) : a < b ? -1 : a > b ? 1 : 0);\n return {\n align: \"start\",\n format: (v) => names(v).join(\"; \"),\n filterText: (v) => names(v).join(\" \"),\n compare: (a, b) => {\n const x = names(a);\n const y = names(b);\n return order(x[0] ?? \"\", y[0] ?? \"\") || x.length - y.length;\n },\n exportValue: (row) => {\n const joined = names(column.accessor ? column.accessor(row) : row[column.id]).join(\"; \");\n return joined === \"\" ? null : joined;\n },\n };\n }\n case \"select\":\n case \"radio\": {\n const order = new Map((column.options ?? []).map((o, i) => [o.id, i]));\n return {\n align: \"start\",\n editor: column.type === \"select\" ? \"select\" : \"radio\",\n format: (v) => optionLabel(column, v),\n filterText: (v) => optionLabel(column, v),\n compare:\n column.type === \"radio\" || column.sortBy === \"order\"\n ? (a, b) => (order.get(a as string) ?? Infinity) - (order.get(b as string) ?? Infinity)\n : (a, b) =>\n locale\n ? new Intl.Collator(locale).compare(optionLabel(column, a), optionLabel(column, b))\n : optionLabel(column, a) < optionLabel(column, b)\n ? -1\n : optionLabel(column, a) > optionLabel(column, b)\n ? 1\n : 0,\n exportValue: (row) => {\n const id = column.accessor ? column.accessor(row) : row[column.id];\n return column.exportAs === \"id\" ? (isEmpty(id) ? null : id) : isEmpty(id) ? null : optionLabel(column, id);\n },\n };\n }\n default:\n return {};\n }\n}\n\n/**\n * The column with its type's defaults filled in under its own props. A column with no `type` is returned as is.\n * `rows` is every row: a `formula` hands it to the consumer's engine for references to other rows. A rollup's and a\n * formula's results are computed once per row each time the columns are resolved (`rows` or `columns` changed),\n * never per comparison or keystroke.\n */\nexport function resolveColumn<T extends TypedColumn>(column: T, gridLocale?: string, rows: Record<string, unknown>[] = []): T {\n if (!column.type) return column;\n const defaults = typeDefaults(column, gridLocale) as Record<string, unknown>;\n const own = Object.fromEntries(Object.entries(column).filter(([, v]) => v !== undefined));\n const resolved = { ...defaults, ...own } as TypedColumn;\n const locale = column.locale ?? gridLocale;\n\n if (column.type === \"rollup\") {\n const relation = column.relation ?? (column.accessor ? (row: Record<string, unknown>) => column.accessor!(row) as unknown[] : (row: Record<string, unknown>) => row[column.id] as unknown[]);\n const cache = new WeakMap<object, unknown>();\n const format = resultFormatter(column, locale);\n resolved.accessor = (row: Record<string, unknown>) => {\n if (cache.has(row)) return cache.get(row);\n const related = relation(row);\n const values = Array.isArray(related) ? related : [];\n const result = column.reduce ? column.reduce(values, row) : aggregateValues(column.aggregate ?? \"count\", values);\n cache.set(row, result);\n return result;\n };\n resolved.editable = false;\n resolved.align = column.align ?? (column.resultType === \"number\" ? \"end\" : \"start\");\n if (column.format === undefined) resolved.format = (v: unknown) => format(v);\n if (column.exportValue === undefined) {\n resolved.exportValue = (row: Record<string, unknown>) => {\n const v = resolved.accessor!(row);\n return column.resultType === \"date\" ? civilDateToDate(v) : isEmpty(v) ? null : v;\n };\n }\n } else if (column.type === \"formula\") {\n const source = column.accessor ?? ((row: Record<string, unknown>) => row[column.id]);\n const cache = new WeakMap<object, DataGridFormulaResult>();\n const format = resultFormatter(column, locale);\n const result = (row: Record<string, unknown>): DataGridFormulaResult => {\n let found = cache.get(row);\n if (!found) {\n const expression = source(row);\n if (isEmpty(expression)) found = { value: null };\n else if (typeof column.evaluate !== \"function\") found = { value: expression };\n else {\n try {\n found = column.evaluate(String(expression), { row, rows, columnId: column.id });\n } catch (error) {\n found = { error: error instanceof Error ? error.message : String(error) };\n }\n }\n cache.set(row, found);\n }\n return found;\n };\n const valueOf = (row: Record<string, unknown>) => {\n const r = result(row);\n return \"error\" in r ? null : r.value;\n };\n resolved.source = source;\n resolved.errorOf = (row: Record<string, unknown>) => {\n const r = result(row);\n return \"error\" in r ? r.error : undefined;\n };\n resolved.accessor = valueOf;\n resolved.align = column.align ?? (column.resultType === \"number\" ? \"end\" : \"start\");\n if (column.format === undefined) {\n resolved.format = (v: unknown, row: Record<string, unknown>) => {\n const message = resolved.errorOf!(row);\n return message !== undefined ? message : format(v);\n };\n }\n if (column.exportValue === undefined) {\n resolved.exportValue = (row: Record<string, unknown>) => {\n const message = resolved.errorOf!(row);\n if (message !== undefined) return message;\n const v = valueOf(row);\n return column.resultType === \"date\" ? civilDateToDate(v) : isEmpty(v) ? null : v;\n };\n }\n if (column.filterText === undefined) {\n resolved.filterText = (v: unknown, row: Record<string, unknown>) =>\n resolved.format!(v, row);\n }\n }\n return resolved as unknown as T;\n}\n","// DataGrid (Angular helper). An Angular port of the canonical Svelte data grid; the contract is that\n// package's spec/index.md. Standalone component, OnPush, signals; it composes the headless\n// DataTable family (`lily-data-table`, `thead[lily-data-table-head]`, …) from\n// @lilydesignsystem/angular-headless.\n//\n// Angular idioms: `selected`, `filter`, `sort`, `columnOrder` and `page` are `model()`s (`[(selected)]`);\n// notifications are outputs; the Svelte snippets (`empty`, `footer`, a column's `cell`, `headerCell`,\n// `avatar`, `personEditor`) are `TemplateRef`s. The headless `lily-data-table` root renders a plain\n// `<table>` with no `role`, so the grid sets `role`, `aria-rowcount` and `aria-busy` on that inner table\n// after each render.\n\nimport {\n ChangeDetectionStrategy,\n Component,\n Directive,\n ElementRef,\n Injector,\n TemplateRef,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n untracked,\n viewChild,\n} from \"@angular/core\";\nimport { NgTemplateOutlet } from \"@angular/common\";\nimport {\n DataTable,\n DataTableBody,\n DataTableFoot,\n DataTableHead,\n DataTableRow,\n DataTableTD,\n DataTableTH,\n} from \"@lilydesignsystem/angular-headless\";\nimport { downloadBlob, exportBlob, exportFilename, type ExportFormat } from \"./export-data\";\nimport {\n filesOf,\n isInvalidForType,\n isZonedTime,\n linkParts,\n peopleOf,\n personName,\n resolveColumn,\n safeHref,\n zonedUtcTime,\n type DataGridCellType,\n type DataGridFile,\n type DataGridLink,\n type DataGridOption,\n type DataGridPerson,\n} from \"./cell-types\";\n\nexport type DataGridSortDirection = \"ascending\" | \"descending\" | \"none\";\n\nexport type DataGridSort = { columnId: string; direction: DataGridSortDirection };\n\nexport type DataGridSelectionMode = \"none\" | \"single\" | \"multiple\";\n\nexport type DataGridRow = Record<string, unknown>;\n\n/** What `exportHandler` and the `exportFile` output receive, before the file is saved. */\nexport type DataGridExport = {\n format: ExportFormat;\n /** The file name, with its extension. */\n filename: string;\n /** How many data rows (the header is not counted). */\n rowCount: number;\n /** The file. */\n blob: Blob;\n};\n\n/** What a column's `cell` template receives (as `$implicit`). */\nexport type DataGridCellContext = {\n value: unknown;\n formatted: string;\n row: DataGridRow;\n column: DataGridColumn;\n};\n\n/** What the `cellEdit` output carries after a cell edit is committed. */\nexport type DataGridCellEdit = {\n rowId: string;\n row: DataGridRow;\n columnId: string;\n /** The parsed new value (a number for the `\"number\"` editor, the text otherwise). */\n value: unknown;\n /** The cell's value before the edit. */\n previous: unknown;\n};\n\n/** What a person editor template receives (as `$implicit`). */\nexport type DataGridPersonEditorContext = { value: unknown; commit: (value: unknown) => void; cancel: () => void };\n\nexport type DataGridColumn = {\n /** Stable column identifier; also the default property read from each row. */\n id: string;\n /** Accessible + visible column header text. */\n header: string;\n /** Reads this column's raw value from a row. Defaults to `row[id]`. */\n accessor?: (row: DataGridRow) => unknown;\n /** Formats a raw value for display. Defaults to `String(value)` (`\"\"` for null/undefined). */\n format?: (value: unknown, row: DataGridRow) => string;\n /** Column participates in sorting. */\n sortable?: boolean;\n /** Orders two raw values when sorting. `null`/`undefined` always sort last, before `compare` is called. */\n compare?: (a: unknown, b: unknown) => number;\n /** Column participates in the text filter. Default true. */\n filterable?: boolean;\n /** Column can be resized (pointer + keyboard). */\n resizable?: boolean;\n /** Column can be reordered: Alt+ArrowLeft/Right on its focused header, or dragging the header onto another. */\n movable?: boolean;\n /** Pins the column: its header and cells get `data-pinned=\"start\"` / `\"end\"` for the consumer's sticky CSS. */\n pinned?: \"start\" | \"end\";\n /** Set `false` to leave the column out of an export. Default true. */\n exportable?: boolean;\n /** The value this column exports for a row. */\n exportValue?: (row: DataGridRow) => unknown;\n /** Column can be hidden via the column-visibility control. */\n hidable?: boolean;\n /** Initial pixel width, meaningful only when `resizable`. */\n width?: number;\n /** Custom cell content: a template receiving the cell context as `$implicit`. */\n cell?: TemplateRef<{ $implicit: DataGridCellContext }>;\n /** The header's content in place of the `header` text. `header` stays the accessible name. */\n headerCell?: TemplateRef<{ $implicit: DataGridColumn }>;\n /** Cells can be edited in place: F2 or Enter on a focused cell, a double click, or the button `labels.editCell` gates. */\n editable?: boolean;\n /** The editor's control. Default `\"text\"`; a `type` sets its own. */\n editor?: \"text\" | \"number\" | \"link\" | \"date\" | \"time\" | \"time-zone\" | \"select\" | \"radio\" | \"person\" | \"formula\";\n /** The kind of value in this column: a bundle of defaults for `format`, `compare`, `filterText`, `exportValue`, `align` and `editor`. */\n type?: DataGridCellType;\n /** BCP 47 locale for this column's formatting and collation. */\n locale?: string;\n /** `select` and `radio`: the choices. */\n options?: DataGridOption[];\n /** `time-zone`: the zones the editor's select offers. */\n timeZones?: DataGridOption[];\n /** `time-zone`: the date (ISO) that orders zoned times and names a zone. Never computed by the grid. */\n referenceDate?: string;\n /** `time-zone`: an export adds a second column holding the UTC time of day at `referenceDate`. */\n exportUtc?: boolean;\n /** `rollup`: how the related values are reduced. */\n aggregate?: \"count\" | \"countUnique\" | \"sum\" | \"avg\" | \"median\" | \"min\" | \"max\" | \"range\" | \"percentTrue\" | \"percentEmpty\";\n /** `rollup`: a reduction the named aggregates do not cover. */\n reduce?: (values: unknown[], row: DataGridRow) => unknown;\n /** `rollup`: reads the related values. */\n relation?: (row: DataGridRow) => unknown[];\n /** `rollup` and `formula`: the result's type. */\n resultType?: \"number\" | \"date\" | \"text\";\n /** `formula`: evaluates an expression. Lily ships no engine and never evaluates a string itself. */\n evaluate?: (expression: string, context: { row: DataGridRow; rows: DataGridRow[]; columnId: string }) => { value: unknown } | { error: string };\n /** `person`: how many people show before \"+N\". */\n maxPeople?: number;\n /** `person`: an avatar beside the name. Decorative. */\n avatar?: TemplateRef<{ $implicit: DataGridPerson }>;\n /** `person`: the editor template (`$implicit`: `{ value, commit, cancel }`). Without it a person cell is read-only. */\n personEditor?: TemplateRef<{ $implicit: DataGridPersonEditorContext }>;\n /** `file`: formats a size in bytes. */\n formatSize?: (bytes: number) => string;\n /** `file`: the `accept` of the file input. */\n accept?: string;\n /** `file`: whether the input takes several files. Default true. */\n multiple?: boolean;\n /** `select`: sort by option label (default) or by option order. */\n sortBy?: \"label\" | \"order\";\n /** `select`/`radio`: export the option's `\"label\"` or `\"id\"`. `person`: `\"email\"`. */\n exportAs?: \"label\" | \"id\" | \"email\";\n /** `number`: options for `Intl.NumberFormat`. */\n numberFormat?: Intl.NumberFormatOptions;\n /** `date`: options for `Intl.DateTimeFormat`. */\n dateFormat?: Intl.DateTimeFormatOptions;\n /** `time`: options for `Intl.DateTimeFormat`. */\n timeFormat?: Intl.DateTimeFormatOptions;\n /** The text the grid's filter matches for a value. */\n filterText?: (value: unknown, row: DataGridRow) => string;\n /** Turns the editor's text into the committed value. */\n parse?: (draft: string, row: DataGridRow) => unknown;\n /** Refuses a value: return a message and the cell stays in edit mode with `aria-invalid`. */\n validate?: (value: unknown, row: DataGridRow) => string | undefined;\n /** Set for a `formula` column: reads the expression a row holds. */\n source?: (row: DataGridRow) => unknown;\n /** Set for a `formula` column: the error message for a row, if any. */\n errorOf?: (row: DataGridRow) => string | undefined;\n /** Body cells of this column are `<th scope=\"row\" role=\"rowheader\">`. */\n rowHeader?: boolean;\n /** Horizontal alignment of the column's cells. */\n align?: \"start\" | \"center\" | \"end\";\n /** Extra class on each body cell of this column. */\n cellClass?: string | ((ctx: DataGridCellContext) => string);\n /** Extra attributes on each body cell of this column. */\n cellAttrs?: (ctx: DataGridCellContext) => Record<string, string>;\n};\n\n/**\n * Every field is optional, but its presence gates the control it names — no baked-in English fallback.\n * See the Svelte canonical's spec/index.md §5.\n */\nexport type DataGridLabels = {\n search?: string;\n columnVisibility?: string;\n columnVisibilityOption?: (header: string) => string;\n resizeHandle?: (header: string) => string;\n selectAll?: string;\n selectionColumn?: string;\n selectRow?: (rowLabel: string) => string;\n previousPage?: string;\n nextPage?: string;\n pageStatus?: (page: number, pageCount: number, rowCount: number) => string;\n pageAnnouncement?: (page: number, pageCount: number) => string;\n sortAnnouncement?: (header: string, direction: DataGridSortDirection) => string;\n filterAnnouncement?: (matchCount: number, totalCount: number) => string;\n selectionAnnouncement?: (selectedCount: number) => string;\n columnMoveAnnouncement?: (header: string, position: number, count: number) => string;\n editCell?: (header: string, rowLabel: string) => string;\n cellEditor?: (header: string) => string;\n editAnnouncement?: (header: string, value: string) => string;\n export?: string;\n exportCsv?: string;\n exportTsv?: string;\n exportExcel?: string;\n exportAnnouncement?: (format: ExportFormat, rowCount: number, filename: string) => string;\n invalidValue?: (header: string, type: string) => string;\n opensInNewTab?: (text: string) => string;\n radioGroup?: (header: string, rowLabel: string) => string;\n timeZone?: (header: string) => string;\n exportUtcHeader?: (header: string) => string;\n morePeople?: (count: number) => string;\n removeFile?: (name: string) => string;\n fileInput?: (header: string, rowLabel: string) => string;\n formulaEditor?: (header: string) => string;\n rollupDescription?: (header: string) => string;\n editCancelAnnouncement?: (header: string) => string;\n editError?: (header: string, message: string) => string;\n};\n\n/** What a footer template receives (as `$implicit`). */\nexport type DataGridFooterContext = { columns: DataGridColumn[]; rows: DataGridRow[] };\n\nexport type DataGridEntry = { row: DataGridRow; id: string };\n\ntype Editing = { rowId: string; columnId: string; draft: string; zone?: string; error?: string; invalid?: boolean };\n\ntype RenderItem = { kind: \"row\"; index: number } | { kind: \"spacer\"; rows: number; key: string };\n\n/** What counts as a widget inside a cell: something a person can operate. */\nconst WIDGET_SELECTOR = 'a[href], button, input, select, textarea, summary, [contenteditable=\"true\"]';\n\nconst MIN_COLUMN_WIDTH = 40;\nconst RESIZE_STEP = 16;\n\nlet uid = 0;\n/** Stable per-instance id prefix; SSR-safe (no Math.random / Date.now). */\nexport function nextDataGridId(): string {\n uid += 1;\n return `data-grid-${uid}`;\n}\n\n/** Default cell value reader: `row[column.id]`. */\nfunction defaultAccessor(column: DataGridColumn, row: DataGridRow): unknown {\n return column.accessor ? column.accessor(row) : row[column.id];\n}\n\n/** Default cell formatter: `String(value)`, `\"\"` for null/undefined. */\nfunction formatCell(column: DataGridColumn, row: DataGridRow): string {\n const value = defaultAccessor(column, row);\n if (column.format) return column.format(value, row);\n return value === null || value === undefined ? \"\" : String(value);\n}\n\n/** Sets a record of attributes on its host element (Angular cannot spread a dictionary in a template). */\n@Directive({ selector: \"[lilyDataGridAttrs]\", standalone: true })\nexport class DataGridAttrs {\n readonly lilyDataGridAttrs = input<Record<string, string> | undefined>(undefined);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private applied: string[] = [];\n\n constructor() {\n effect(() => {\n const next = this.lilyDataGridAttrs() ?? {};\n for (const name of this.applied) if (!(name in next)) this.host.nativeElement.removeAttribute(name);\n for (const [name, value] of Object.entries(next)) this.host.nativeElement.setAttribute(name, value);\n this.applied = Object.keys(next);\n });\n }\n}\n\n@Component({\n selector: \"lily-data-grid\",\n standalone: true,\n imports: [NgTemplateOutlet, DataGridAttrs, DataTable, DataTableBody, DataTableFoot, DataTableHead, DataTableRow, DataTableTD, DataTableTH],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div #rootEl class=\"data-grid {{ className() }}\">\n @if (labels().search || hidableColumns().length > 0 || hasExportButtons()) {\n <div class=\"data-grid-toolbar\">\n @if (labels().search; as searchLabel) {\n <input class=\"data-grid-search\" type=\"search\" [attr.aria-label]=\"searchLabel\" [value]=\"filter()\" (input)=\"onFilterInput($event)\" />\n }\n @if (hasExportButtons()) {\n <div class=\"data-grid-export\" role=\"group\" [attr.aria-label]=\"labels().export ?? null\">\n @if (labels().exportCsv; as csv) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"csv\" [disabled]=\"exportEntries().length === 0\" (click)=\"runExport('csv')\">{{ csv }}</button>\n }\n @if (labels().exportTsv; as tsv) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"tsv\" [disabled]=\"exportEntries().length === 0\" (click)=\"runExport('tsv')\">{{ tsv }}</button>\n }\n @if (labels().exportExcel; as excel) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"xlsx\" [disabled]=\"exportEntries().length === 0\" (click)=\"runExport('xlsx')\">{{ excel }}</button>\n }\n </div>\n }\n @if (hidableColumns().length > 0 && labels().columnVisibility; as visibilityLabel) {\n <fieldset class=\"data-grid-column-visibility\">\n <legend>{{ visibilityLabel }}</legend>\n @for (column of hidableColumns(); track column.id) {\n <label>\n <input type=\"checkbox\" [checked]=\"!hiddenColumnIds().has(column.id)\" (change)=\"toggleColumnVisibility(column.id)\" />\n {{ labels().columnVisibilityOption?.(column.header) ?? column.header }}\n </label>\n }\n </fieldset>\n }\n </div>\n }\n\n @if (scroll()) {\n <!-- A scrollable region must be reachable by keyboard (WCAG 2.1.1); in grid mode a roving cell is already a tab stop. -->\n <div\n #scrollEl\n class=\"data-grid-scroll\"\n role=\"region\"\n [attr.aria-label]=\"label()\"\n [attr.tabindex]=\"isGrid() ? null : 0\"\n [attr.style]=\"scrollStyle()\"\n (scroll)=\"onScroll($event)\"\n >\n <ng-container *ngTemplateOutlet=\"tableTemplate\" />\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"tableTemplate\" />\n }\n\n @if (pageSize()) {\n <div class=\"data-grid-pagination\">\n <button type=\"button\" class=\"data-grid-page-previous\" [disabled]=\"clampedPage() <= 1\" (click)=\"goToPage(clampedPage() - 1)\">{{ labels().previousPage }}</button>\n <span class=\"data-grid-page-status\">{{ labels().pageStatus?.(clampedPage(), pageCount(), sortedEntries().length) }}</span>\n <button type=\"button\" class=\"data-grid-page-next\" [disabled]=\"clampedPage() >= pageCount()\" (click)=\"goToPage(clampedPage() + 1)\">{{ labels().nextPage }}</button>\n </div>\n }\n\n <p class=\"data-grid-status\" aria-live=\"polite\">{{ statusMessage() }}</p>\n </div>\n\n <ng-template #tableTemplate>\n <lily-data-table\n [label]=\"label()\"\n [className]=\"''\"\n (keydown)=\"onGridKeydown($event)\"\n (focusin)=\"onGridFocusin($event)\"\n (focusout)=\"onGridFocusout($event)\"\n (click)=\"onGridClick($event)\"\n (dblclick)=\"onGridDblclick($event)\"\n >\n @if (caption()) {\n <caption>{{ caption() }}</caption>\n }\n <thead lily-data-table-head>\n <tr lily-data-table-row [attr.aria-rowindex]=\"indexed() ? 1 : null\">\n @if (hasSelection()) {\n <th\n lily-data-table-th\n data-row=\"-1\"\n data-col=\"0\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === -1 && activeCol() === 0 ? 0 : -1) : null\"\n >\n @if (selectionMode() === 'multiple') {\n <input\n type=\"checkbox\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"labels().selectAll ?? null\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (click)=\"toggleSelectAll()\"\n />\n } @else {\n <span class=\"data-grid-selection-header-label\">{{ labels().selectionColumn }}</span>\n }\n </th>\n }\n @for (column of visibleColumns(); track column.id; let i = $index) {\n <th\n lily-data-table-th\n data-row=\"-1\"\n [attr.data-col]=\"colOffset() + i\"\n [attr.data-align]=\"column.align ?? null\"\n [attr.data-cell-type]=\"column.type ?? null\"\n [attr.data-pinned]=\"column.pinned ?? null\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === -1 && activeCol() === colOffset() + i ? 0 : -1) : null\"\n [attr.aria-sort]=\"ariaSortFor(column)\"\n [attr.aria-describedby]=\"column.type === 'rollup' && labels().rollupDescription ? gridId + '-' + column.id + '-description' : null\"\n [attr.style]=\"cellStyle(column)\"\n [attr.draggable]=\"column.movable ? 'true' : null\"\n (dragstart)=\"onHeaderDragStart(column, $event)\"\n (dragover)=\"onHeaderDragOver($event)\"\n (drop)=\"onHeaderDrop(column.id, $event)\"\n >\n @if (column.sortable) {\n <button type=\"button\" class=\"data-grid-sort-button\" data-grid-own [attr.tabindex]=\"isGrid() ? -1 : null\" (click)=\"toggleSort(column)\">\n @if (column.headerCell; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: column }\" />\n } @else {<ng-container>{{ column.header }}</ng-container>}\n </button>\n } @else if (column.headerCell; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: column }\" />\n } @else {<ng-container>{{ column.header }}</ng-container>}\n @if (column.type === 'rollup' && labels().rollupDescription; as describe) {\n <span class=\"data-grid-visually-hidden\" [id]=\"gridId + '-' + column.id + '-description'\">{{ describe(column.header) }}</span>\n }\n @if (column.resizable) {\n <!-- WAI-ARIA \"window splitter\" pattern: role=\"separator\" plus tabindex/aria-valuenow is how a resize handle becomes focusable and operable. -->\n <span\n class=\"data-grid-resize-handle\"\n role=\"separator\"\n data-grid-own\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"labels().resizeHandle?.(column.header) ?? null\"\n [attr.aria-valuenow]=\"widthFor(column) ?? 120\"\n [attr.aria-valuemin]=\"minColumnWidth\"\n tabindex=\"0\"\n (keydown)=\"onResizeKeydown(column, $event)\"\n (pointerdown)=\"onResizePointerDown(column, $event)\"\n ></span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody lily-data-table-body>\n @for (item of renderItems(); track item.kind === 'row' ? pageEntries()[item.index].id : item.key) {\n @if (item.kind === 'spacer') {\n <tr class=\"data-grid-spacer\" aria-hidden=\"true\" [attr.style]=\"'height:' + item.rows * (virtualize()?.rowHeight ?? 0) + 'px'\">\n <td [attr.colspan]=\"lastCol() + 1\"></td>\n </tr>\n } @else {\n @let entry = pageEntries()[item.index];\n <tr\n lily-data-table-row\n [className]=\"rowClass()?.(entry.row) ?? ''\"\n [attr.aria-selected]=\"hasSelection() ? isSelected(entry.id) : null\"\n [attr.aria-rowindex]=\"indexed() ? pageStart() + item.index + 2 : null\"\n [lilyDataGridAttrs]=\"rowAttrs()?.(entry.row)\"\n >\n @if (hasSelection()) {\n <td\n lily-data-table-td\n [attr.role]=\"isGrid() ? 'gridcell' : 'cell'\"\n [attr.data-row]=\"item.index\"\n data-col=\"0\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === item.index && activeCol() === 0 ? 0 : -1) : null\"\n >\n <input\n [type]=\"selectionMode() === 'single' ? 'radio' : 'checkbox'\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"labels().selectRow?.(rowLabelOf(entry)) ?? null\"\n [checked]=\"isSelected(entry.id)\"\n (click)=\"onRowSelectClick(pageStart() + item.index, $event)\"\n />\n </td>\n }\n @for (column of visibleColumns(); track column.id; let colIndex = $index) {\n @let ctx = cellFor(column, entry.row);\n @if (column.rowHeader) {\n <th\n lily-data-table-th\n scope=\"row\"\n role=\"rowheader\"\n [className]=\"cellClassOf(column, ctx)\"\n [attr.data-row]=\"item.index\"\n [attr.data-col]=\"colOffset() + colIndex\"\n [attr.data-align]=\"column.align ?? null\"\n [attr.data-cell-type]=\"column.type ?? null\"\n [attr.data-pinned]=\"column.pinned ?? null\"\n [attr.data-error]=\"column.errorOf?.(entry.row) !== undefined ? '' : null\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === item.index && activeCol() === colOffset() + colIndex ? 0 : -1) : null\"\n [attr.style]=\"cellStyle(column)\"\n [lilyDataGridAttrs]=\"column.cellAttrs?.(ctx)\"\n >\n <ng-container *ngTemplateOutlet=\"cellBody; context: { entry: entry, column: column, ctx: ctx }\" />\n </th>\n } @else {\n <td\n lily-data-table-td\n [className]=\"cellClassOf(column, ctx)\"\n [attr.role]=\"isGrid() ? 'gridcell' : 'cell'\"\n [attr.data-row]=\"item.index\"\n [attr.data-col]=\"colOffset() + colIndex\"\n [attr.data-align]=\"column.align ?? null\"\n [attr.data-cell-type]=\"column.type ?? null\"\n [attr.data-pinned]=\"column.pinned ?? null\"\n [attr.data-editable]=\"isEditable(column) ? '' : null\"\n [attr.data-readonly]=\"column.type === 'rollup' ? '' : null\"\n [attr.aria-readonly]=\"column.type === 'rollup' ? 'true' : null\"\n [attr.data-error]=\"column.errorOf?.(entry.row) !== undefined ? '' : null\"\n [attr.data-editing]=\"isEditingCell(entry, column) ? '' : null\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === item.index && activeCol() === colOffset() + colIndex ? 0 : -1) : null\"\n [attr.style]=\"cellStyle(column)\"\n [lilyDataGridAttrs]=\"column.cellAttrs?.(ctx)\"\n (dragover)=\"onFileDragOver(column, $event)\"\n (drop)=\"onFileDrop(entry, column, $event)\"\n >\n <ng-container *ngTemplateOutlet=\"cellBody; context: { entry: entry, column: column, ctx: ctx }\" />\n </td>\n }\n }\n </tr>\n }\n }\n @if (pageEntries().length === 0 && empty(); as emptyTemplate) {\n <tr lily-data-table-row className=\"data-grid-empty-row\">\n <td lily-data-table-td className=\"data-grid-empty\" [attr.colspan]=\"lastCol() + 1\" [attr.role]=\"isGrid() ? 'gridcell' : 'cell'\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </td>\n </tr>\n }\n </tbody>\n @if (footer(); as footerTemplate) {\n <tfoot lily-data-table-foot>\n <ng-container *ngTemplateOutlet=\"footerTemplate; context: { $implicit: footerContext() }\" />\n </tfoot>\n }\n </lily-data-table>\n </ng-template>\n\n <ng-template #cellBody let-entry=\"entry\" let-column=\"column\" let-ctx=\"ctx\">\n @if (isEditingCell(entry, column)) {\n @let editing = editingState()!;\n @if (column.editor === 'person' && column.personEditor) {\n <ng-container *ngTemplateOutlet=\"column.personEditor; context: { $implicit: personEditorContext(entry, column, ctx) }\" />\n } @else if (column.editor === 'time-zone') {\n <span\n class=\"data-grid-zoned-editor\"\n role=\"group\"\n [attr.aria-label]=\"labels().cellEditor?.(column.header) ?? column.header\"\n (focusout)=\"onZonedFocusout($event)\"\n >\n <input\n class=\"data-grid-cell-editor\"\n type=\"time\"\n step=\"1\"\n [attr.aria-label]=\"labels().cellEditor?.(column.header) ?? column.header\"\n [attr.aria-invalid]=\"editing.error || editing.invalid ? 'true' : null\"\n [attr.aria-describedby]=\"editing.error ? entry.id + '-' + column.id + '-error' : null\"\n [value]=\"editing.draft\"\n (input)=\"setDraft($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n />\n <select\n class=\"data-grid-cell-editor data-grid-zone-editor\"\n [attr.aria-label]=\"labels().timeZone?.(column.header) ?? column.header\"\n (change)=\"setZone($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n >\n @for (option of column.timeZones ?? []; track option.id) {\n <option [value]=\"option.id\" [selected]=\"option.id === editing.zone\">{{ option.label }}</option>\n }\n </select>\n </span>\n } @else if (column.editor === 'select') {\n <select\n class=\"data-grid-cell-editor\"\n [attr.aria-label]=\"labels().cellEditor?.(column.header) ?? column.header\"\n [attr.aria-invalid]=\"editing.error || editing.invalid ? 'true' : null\"\n [attr.aria-describedby]=\"editing.error ? entry.id + '-' + column.id + '-error' : null\"\n (change)=\"setDraft($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n (blur)=\"onEditorBlur()\"\n >\n <option value=\"\" [selected]=\"editing.draft === ''\"></option>\n @for (option of ungroupedOptions(column); track option.id) {\n <option [value]=\"option.id\" [disabled]=\"option.disabled ?? false\" [selected]=\"option.id === editing.draft\">{{ option.label }}</option>\n }\n @for (group of groupsOf(column); track group) {\n <optgroup [label]=\"group\">\n @for (option of optionsInGroup(column, group); track option.id) {\n <option [value]=\"option.id\" [disabled]=\"option.disabled ?? false\" [selected]=\"option.id === editing.draft\">{{ option.label }}</option>\n }\n </optgroup>\n }\n </select>\n } @else {\n <input\n class=\"data-grid-cell-editor\"\n [type]=\"column.editor === 'number' ? 'number' : column.editor === 'date' ? 'date' : column.editor === 'time' ? 'time' : 'text'\"\n [attr.step]=\"column.editor === 'time' ? 1 : null\"\n [attr.inputmode]=\"column.editor === 'number' ? 'decimal' : null\"\n [attr.aria-label]=\"(column.type === 'formula' ? labels().formulaEditor?.(column.header) : undefined) ?? labels().cellEditor?.(column.header) ?? column.header\"\n [attr.aria-invalid]=\"editing.error || editing.invalid ? 'true' : null\"\n [attr.aria-describedby]=\"editing.error ? entry.id + '-' + column.id + '-error' : null\"\n [value]=\"editing.draft\"\n (input)=\"setDraft($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n (blur)=\"onEditorBlur()\"\n />\n }\n @if (editing.error) {\n <span class=\"data-grid-cell-error\" [id]=\"entry.id + '-' + column.id + '-error'\">{{ editing.error }}</span>\n }\n } @else if (column.type === 'radio' && column.editable) {\n <fieldset class=\"data-grid-radio-group\" data-grid-own-group>\n <legend class=\"data-grid-radio-legend\">{{ labels().radioGroup?.(column.header, rowLabelOf(entry)) ?? column.header }}</legend>\n @for (option of column.options ?? []; track option.id) {\n <label class=\"data-grid-radio-option\">\n <input\n type=\"radio\"\n [name]=\"gridId + '-' + entry.id + '-' + column.id\"\n [value]=\"option.id\"\n [checked]=\"ctx.value === option.id\"\n [disabled]=\"option.disabled ?? false\"\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n (change)=\"commitValue(entry, column, option.id)\"\n />{{ option.label }}</label>\n }\n </fieldset>\n } @else {\n @if (column.cell; as cellTemplate) {\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: ctx }\" />\n } @else if (column.type === 'person') {\n @let people = peopleIn(ctx.value);\n @if (people.length > 0) {\n @let shown = shownPeople(column, ctx.value);\n <ul class=\"data-grid-people\">\n @for (person of shown; track person.id) {\n <li class=\"data-grid-person\">\n @if (column.avatar; as avatarTemplate) {\n <span class=\"data-grid-avatar\" aria-hidden=\"true\"><ng-container *ngTemplateOutlet=\"avatarTemplate; context: { $implicit: person }\" /></span>\n }\n <span class=\"data-grid-person-name\">{{ nameOf(person) }}</span>\n </li>\n }\n @if (shown.length < people.length && labels().morePeople; as more) {\n <li class=\"data-grid-people-more\">{{ more(people.length - shown.length) }}</li>\n }\n </ul>\n }\n } @else if (column.type === 'file') {\n @let files = filesIn(ctx.value);\n @if (files.length > 0) {\n <ul class=\"data-grid-files\">\n @for (file of files; track file.id) {\n <li class=\"data-grid-file\">\n @if (hrefOf(file.href); as fileHref) {\n <a class=\"data-grid-link\" [href]=\"fileHref\">{{ file.name }}</a>\n } @else {\n <span class=\"data-grid-file-name\">{{ file.name }}</span>\n }\n @if (file.size !== undefined && column.formatSize; as sizeText) {\n {{ ' ' }}<span class=\"data-grid-file-size\">{{ column.formatSize(file.size) }}</span>\n }\n @if (column.editable && labels().removeFile; as removeLabel) {\n <button\n type=\"button\"\n class=\"data-grid-file-remove\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"removeLabel(file.name)\"\n (click)=\"fileRemove.emit({ rowId: entry.id, row: entry.row, columnId: column.id, fileId: file.id })\"\n ></button>\n }\n </li>\n }\n </ul>\n }\n @if (column.editable) {\n <input\n type=\"file\"\n class=\"data-grid-file-input\"\n [attr.aria-label]=\"labels().fileInput?.(column.header, rowLabelOf(entry)) ?? column.header\"\n [multiple]=\"column.multiple !== false\"\n [attr.accept]=\"column.accept ?? null\"\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n (change)=\"onFileInput(entry, column, $event)\"\n />\n }\n } @else if (column.type === 'link') {\n @let link = linkIn(ctx.value);\n @if (link) {\n @if (hrefOf(link.href); as href) {\n <a class=\"data-grid-link\" [href]=\"href\" [attr.target]=\"link.external ? '_blank' : null\" [attr.rel]=\"link.external ? 'noopener noreferrer' : null\">{{ link.label ?? link.href }}@if (link.external && labels().opensInNewTab; as newTab) {{{ ' ' }}<span class=\"data-grid-visually-hidden\">{{ newTab(link.label ?? link.href) }}</span>}</a>\n } @else {\n <!-- An address with an unsafe scheme is shown as text, never as a link. -->\n <span class=\"data-grid-link data-grid-link-unsafe\">{{ link.label ?? link.href }}</span>\n }\n }\n } @else if (column.type === 'date' || column.type === 'time') {\n @if (ctx.formatted !== '') {\n <time [attr.datetime]=\"stringOf(ctx.value)\">{{ ctx.formatted }}</time>\n }\n } @else {<ng-container>{{ ctx.formatted }}</ng-container>}\n @if (isEditable(column) && column.type !== 'radio' && labels().editCell; as editLabel) {\n <button\n type=\"button\"\n class=\"data-grid-edit-button\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"editLabel(column.header, rowLabelOf(entry))\"\n (click)=\"startEdit(entry, column)\"\n ></button>\n }\n }\n </ng-template>\n `,\n})\nexport class DataGrid {\n // ---- Inputs ----\n\n /** Accessible name for the grid, passed through to DataTable. */\n readonly label = input.required<string>();\n /** Optional visible caption. */\n readonly caption = input<string | undefined>(undefined);\n /** Column definitions. */\n readonly columns = input.required<DataGridColumn[]>();\n /** Row data. */\n readonly rows = input.required<DataGridRow[]>();\n /** BCP 47 locale for the typed columns' formatting and collation. Never defaulted: with none, values show as stored. */\n readonly locale = input<string | undefined>(undefined);\n /** Derives a stable id per row. Defaults to the row's index in `rows`. */\n readonly rowId = input<(row: DataGridRow, index: number) => string>((_row, index) => String(index));\n /** Row selection mode. */\n readonly selectionMode = input<DataGridSelectionMode>(\"none\");\n /** Rows per page. Unset disables pagination. */\n readonly pageSize = input<number | undefined>(undefined);\n /** If set, persist column widths / hidden columns / sort to localStorage. */\n readonly storageKey = input<string | undefined>(undefined);\n /** User-facing strings. */\n readonly labels = input<DataGridLabels>({});\n /** `\"grid\"` (default): roving-tabindex grid. `\"table\"`: a plain table with ordinary tab stops. */\n readonly mode = input<\"grid\" | \"table\">(\"grid\");\n /** Extra class on each body row. */\n readonly rowClass = input<((row: DataGridRow) => string) | undefined>(undefined);\n /** Extra attributes on each body row. */\n readonly rowAttrs = input<((row: DataGridRow) => Record<string, string>) | undefined>(undefined);\n /** Enter on a body cell with no widget, and a click outside any widget, emit `rowActivate` — only when this is true (Angular outputs cannot be tested for a listener). */\n readonly activateRows = input<boolean>(false);\n /** Shown in one row spanning every column when no row is to be shown. */\n readonly empty = input<TemplateRef<void> | undefined>(undefined);\n /** Rendered inside a `<tfoot>`: a template receiving `{ columns, rows }` as `$implicit`. */\n readonly footer = input<TemplateRef<{ $implicit: DataGridFooterContext }> | undefined>(undefined);\n /** Sets `aria-busy` on the table. */\n readonly busy = input<boolean>(false);\n /** Wrap the table in a scrollable `data-grid-scroll` region. Default true. */\n readonly scroll = input<boolean>(true);\n /** The file name without its extension. Default `\"data-grid\"`. */\n readonly exportFilename = input<string>(\"data-grid\");\n /** What an export holds: `\"view\"` (default) or `\"selected\"`. */\n readonly exportScope = input<\"view\" | \"selected\">(\"view\");\n /** `.xlsx` only: a `formula` column keeps the live expression with the result cached. */\n readonly exportFormulas = input<boolean>(false);\n /** Called with the file before it is saved. Return `false` to keep the grid from saving it. */\n readonly exportHandler = input<((file: DataGridExport) => boolean | void) | undefined>(undefined);\n /** Renders only the rows in view, in a scroll region of `height` px (needs `scroll`). */\n readonly virtualize = input<{ rowHeight: number; height: number; overscan?: number } | undefined>(undefined);\n /** Extra CSS class on the root. */\n readonly className = input<string>(\"\");\n\n // ---- Two-way models ----\n\n /** Selected row ids. Two-way bindable: `[(selected)]`. */\n readonly selected = model<string[]>([]);\n /** Text filter. Two-way bindable: `[(filter)]`. */\n readonly filter = model<string>(\"\");\n /** Current sort. Two-way bindable: `[(sort)]`. */\n readonly sort = model<DataGridSort>({ columnId: \"\", direction: \"none\" });\n /** Column ids in display order. Two-way bindable: `[(columnOrder)]`; columns it does not name follow in their `columns` order. */\n readonly columnOrder = model<string[]>([]);\n /** Current 1-indexed page. Two-way bindable: `[(page)]`. */\n readonly page = model<number>(1);\n\n // ---- Outputs ----\n\n readonly cellEdit = output<DataGridCellEdit>();\n readonly filesSelected = output<{ rowId: string; row: DataGridRow; columnId: string; files: File[] }>();\n readonly fileRemove = output<{ rowId: string; row: DataGridRow; columnId: string; fileId: string }>();\n readonly rowActivate = output<{ row: DataGridRow; id: string }>();\n readonly exportFile = output<DataGridExport>();\n\n // ---- State ----\n\n protected readonly gridId = nextDataGridId();\n protected readonly minColumnWidth = MIN_COLUMN_WIDTH;\n private readonly rootRef = viewChild.required<ElementRef<HTMLDivElement>>(\"rootEl\");\n private readonly scrollRef = viewChild<ElementRef<HTMLDivElement>>(\"scrollEl\");\n private readonly injector = inject(Injector);\n\n protected readonly statusMessage = signal(\"\");\n protected readonly hiddenColumnIds = signal<ReadonlySet<string>>(new Set());\n private readonly columnWidths = signal<Record<string, number>>({});\n private readonly focusedRow = signal(-1); // -1 = header row\n private readonly focusedCol = signal(0);\n private lastSelectedIndex = -1;\n protected readonly editingState = signal<Editing | null>(null);\n private readonly scrollTop = signal(0);\n private draggingColumnId: string | null = null;\n\n // ---- Derived data ----\n\n /** Each column with its type's defaults filled in under its own props. */\n protected readonly resolvedColumns = computed(() => this.columns().map((c) => resolveColumn(c, this.locale(), this.rows())) as DataGridColumn[]);\n protected readonly isGrid = computed(() => this.mode() === \"grid\");\n protected readonly hasSelection = computed(() => this.selectionMode() !== \"none\");\n protected readonly colOffset = computed(() => (this.hasSelection() ? 1 : 0));\n\n /** Columns in display order: those named in `columnOrder` first, the rest after in their own order. */\n private readonly orderedColumns = computed(() => {\n const order = this.columnOrder();\n const columns = this.resolvedColumns();\n if (order.length === 0) return columns;\n const rank = (id: string) => {\n const i = order.indexOf(id);\n return i === -1 ? order.length : i;\n };\n return columns\n .map((c, i) => ({ c, i }))\n .sort((a, b) => rank(a.c.id) - rank(b.c.id) || a.i - b.i)\n .map((x) => x.c);\n });\n protected readonly visibleColumns = computed(() => this.orderedColumns().filter((c) => !this.hiddenColumnIds().has(c.id)));\n protected readonly hidableColumns = computed(() => this.resolvedColumns().filter((c) => c.hidable));\n\n private readonly entries = computed<DataGridEntry[]>(() => {\n const rowId = this.rowId();\n return this.rows().map((row, index) => ({ row, id: rowId(row, index) }));\n });\n\n /** Each cell's value and formatted text, read once per row object and column (reset when the columns change). */\n private readonly cellCache = computed(() => {\n this.resolvedColumns();\n return new WeakMap<DataGridRow, Map<string, DataGridCellContext>>();\n });\n\n protected cellFor(column: DataGridColumn, row: DataGridRow): DataGridCellContext {\n const cache = this.cellCache();\n let perRow = cache.get(row);\n if (!perRow) {\n perRow = new Map();\n cache.set(row, perRow);\n }\n let ctx = perRow.get(column.id);\n if (!ctx) {\n ctx = { value: defaultAccessor(column, row), formatted: formatCell(column, row), row, column };\n perRow.set(column.id, ctx);\n }\n return ctx;\n }\n\n /** Lowercased search text per row, built once per rows/columns change. */\n private readonly searchIndex = computed(() => {\n const filterable = this.resolvedColumns().filter((c) => c.filterable !== false);\n return this.entries().map((entry) =>\n filterable.map((column) =>\n (column.filterText ? column.filterText(this.cellFor(column, entry.row).value, entry.row) : this.cellFor(column, entry.row).formatted).toLowerCase(),\n ),\n );\n });\n\n private readonly filteredEntries = computed(() => {\n const text = this.filter().trim().toLowerCase();\n if (!text) return this.entries();\n const index = this.searchIndex();\n return this.entries().filter((_entry, i) => index[i].some((value) => value.includes(text)));\n });\n\n protected readonly sortedEntries = computed(() => {\n const sort = this.sort();\n const filtered = this.filteredEntries();\n if (sort.direction === \"none\" || !sort.columnId) return filtered;\n const column = this.resolvedColumns().find((c) => c.id === sort.columnId);\n if (!column) return filtered;\n const dir = sort.direction === \"ascending\" ? 1 : -1;\n const compare = column.compare;\n // Read each sort key once (n accessor calls), not twice per comparison.\n const keyed = filtered.map((entry) => ({ entry, key: this.cellFor(column, entry.row).value }));\n keyed.sort((a, b) => {\n const av = a.key;\n const bv = b.key;\n if (av === bv) return 0;\n // Missing values sort last in both directions.\n if (av === null || av === undefined) return 1;\n if (bv === null || bv === undefined) return -1;\n if (compare) return compare(av, bv) * dir;\n return (av as never) > (bv as never) ? dir : -dir;\n });\n return keyed.map((k) => k.entry);\n });\n\n protected readonly pageCount = computed(() => {\n const size = this.pageSize();\n return size ? Math.max(1, Math.ceil(this.sortedEntries().length / size)) : 1;\n });\n protected readonly clampedPage = computed(() => Math.min(Math.max(this.page(), 1), this.pageCount()));\n protected readonly pageStart = computed(() => {\n const size = this.pageSize();\n return size ? (this.clampedPage() - 1) * size : 0;\n });\n protected readonly pageEntries = computed(() => {\n const size = this.pageSize();\n return size ? this.sortedEntries().slice(this.pageStart(), this.pageStart() + size) : this.sortedEntries();\n });\n protected readonly lastCol = computed(() => this.colOffset() + this.visibleColumns().length - 1);\n\n // The roving position clamped to the cells that exist now.\n protected readonly activeRow = computed(() => Math.max(-1, Math.min(this.focusedRow(), this.pageEntries().length - 1)));\n protected readonly activeCol = computed(() => Math.max(0, Math.min(this.focusedCol(), this.lastCol())));\n\n protected readonly indexed = computed(() => !!this.pageSize() || !!this.virtualize());\n private readonly rowCount = computed(() =>\n this.pageSize() ? this.sortedEntries().length + 1 : this.virtualize() ? this.pageEntries().length + 1 : undefined,\n );\n\n protected readonly renderItems = computed<RenderItem[]>(() => {\n const total = this.pageEntries().length;\n const v = this.virtualize();\n if (!v) return this.pageEntries().map((_, index) => ({ kind: \"row\", index }) as RenderItem);\n const overscan = v.overscan ?? 3;\n const top = this.scrollTop();\n const start = Math.max(0, Math.floor(top / v.rowHeight) - overscan);\n const end = Math.min(total, Math.ceil((top + v.height) / v.rowHeight) + overscan);\n const indices = new Set<number>();\n for (let i = start; i < end; i++) indices.add(i);\n const active = this.activeRow();\n if (active >= 0 && active < total) indices.add(active);\n const items: RenderItem[] = [];\n let previous = -1;\n for (const index of [...indices].sort((a, b) => a - b)) {\n if (index - previous > 1) items.push({ kind: \"spacer\", rows: index - previous - 1, key: `spacer-${previous}` });\n items.push({ kind: \"row\", index });\n previous = index;\n }\n if (total - 1 - previous > 0) items.push({ kind: \"spacer\", rows: total - 1 - previous, key: `spacer-${previous}` });\n return items;\n });\n\n protected readonly scrollStyle = computed(() => {\n const v = this.virtualize();\n return v ? `height:${v.height}px;overflow:auto` : null;\n });\n\n private readonly selectedSet = computed(() => new Set(this.selected()));\n protected readonly allSelected = computed(() => this.sortedEntries().length > 0 && this.sortedEntries().every((e) => this.selectedSet().has(e.id)));\n protected readonly someSelected = computed(() => !this.allSelected() && this.sortedEntries().some((e) => this.selectedSet().has(e.id)));\n\n protected readonly footerContext = computed<DataGridFooterContext>(() => ({\n columns: this.visibleColumns(),\n rows: this.pageEntries().map((e) => e.row),\n }));\n\n protected readonly exportColumns = computed(() => this.visibleColumns().filter((c) => c.exportable !== false));\n protected readonly exportEntries = computed(() =>\n this.exportScope() === \"selected\" ? this.sortedEntries().filter((e) => this.selectedSet().has(e.id)) : this.sortedEntries(),\n );\n protected readonly hasExportButtons = computed(() => {\n const l = this.labels();\n return !!(l.exportCsv || l.exportTsv || l.exportExcel);\n });\n\n constructor() {\n // The headless `lily-data-table` root renders a plain <table>: give it the grid's role and counts.\n effect(() => {\n const root = this.rootRef().nativeElement;\n const grid = this.isGrid();\n const count = this.rowCount();\n const busy = this.busy();\n this.sortedEntries();\n this.pageEntries();\n this.visibleColumns();\n this.scroll();\n afterNextRender(\n () => {\n const table = root.querySelector<HTMLElement>(\"table.data-table\");\n if (!table) return;\n table.setAttribute(\"role\", grid ? \"grid\" : \"table\");\n if (grid && count !== undefined) table.setAttribute(\"aria-rowcount\", String(count));\n else table.removeAttribute(\"aria-rowcount\");\n if (busy) table.setAttribute(\"aria-busy\", \"true\");\n else table.removeAttribute(\"aria-busy\");\n },\n { injector: this.injector },\n );\n });\n\n // Widgets in body cells are not tab stops, so Tab leaves the grid in one step. Re-run whenever what is on screen changes.\n effect(() => {\n this.pageEntries();\n this.visibleColumns();\n this.isGrid();\n this.scrollTop();\n this.editingState();\n afterNextRender(() => this.normaliseWidgets(), { injector: this.injector });\n });\n\n // Persistence (view state only: widths, hidden columns, sort — never rows/selection).\n let restored = false;\n effect(() => {\n const key = this.storageKey();\n if (!key || restored) return;\n restored = true;\n untracked(() => this.restoreView(key));\n });\n effect(() => {\n const key = this.storageKey();\n const snapshot = { columnWidths: this.columnWidths(), hiddenColumnIds: [...this.hiddenColumnIds()], sort: this.sort() };\n if (!key || typeof localStorage === \"undefined\") return;\n try {\n localStorage.setItem(key, JSON.stringify(snapshot));\n } catch {\n // ignore quota / privacy errors\n }\n });\n }\n\n // ---- Announcements ----\n\n private announce(message: string | undefined): void {\n if (message) this.statusMessage.set(message);\n }\n\n // ---- Sorting ----\n\n protected ariaSortFor(column: DataGridColumn): DataGridSortDirection | null {\n if (!column.sortable) return null;\n return this.sort().columnId === column.id ? this.sort().direction : \"none\";\n }\n\n protected toggleSort(column: DataGridColumn): void {\n if (!column.sortable) return;\n const current = this.sort();\n const next: DataGridSort =\n current.columnId !== column.id\n ? { columnId: column.id, direction: \"ascending\" }\n : current.direction === \"ascending\"\n ? { columnId: column.id, direction: \"descending\" }\n : current.direction === \"descending\"\n ? { columnId: \"\", direction: \"none\" }\n : { columnId: column.id, direction: \"ascending\" };\n this.sort.set(next);\n this.announce(this.labels().sortAnnouncement?.(column.header, next.direction));\n }\n\n // ---- Filtering ----\n\n protected onFilterInput(event: Event): void {\n this.filter.set((event.target as HTMLInputElement).value);\n this.page.set(1);\n this.announce(this.labels().filterAnnouncement?.(this.filteredEntries().length, this.rows().length));\n }\n\n // ---- Selection ----\n\n protected isSelected(id: string): boolean {\n return this.selectedSet().has(id);\n }\n\n private setSelected(next: string[]): void {\n this.selected.set(next);\n this.announce(this.labels().selectionAnnouncement?.(next.length));\n }\n\n protected onRowSelectClick(index: number, event: Event): void {\n const e = event as MouseEvent;\n this.toggleRow(index, e);\n }\n\n /** `index` is the row's position in the sorted entries, not on the current page. */\n private toggleRow(index: number, event?: { shiftKey?: boolean; ctrlKey?: boolean; metaKey?: boolean }): void {\n const sorted = this.sortedEntries();\n const id = sorted[index].id;\n const selected = this.selected();\n const mode = this.selectionMode();\n if (mode === \"single\") {\n this.setSelected(this.isSelected(id) ? [] : [id]);\n } else if (mode === \"multiple\") {\n if (event?.shiftKey && this.lastSelectedIndex >= 0) {\n const [start, end] = this.lastSelectedIndex < index ? [this.lastSelectedIndex, index] : [index, this.lastSelectedIndex];\n const range = sorted.slice(start, end + 1).map((e) => e.id);\n this.setSelected([...new Set([...selected, ...range])]);\n } else if (event?.ctrlKey || event?.metaKey) {\n this.setSelected(this.isSelected(id) ? selected.filter((x) => x !== id) : [...selected, id]);\n } else {\n this.setSelected(this.isSelected(id) && selected.length === 1 ? [] : [id]);\n }\n }\n this.lastSelectedIndex = index;\n }\n\n protected toggleSelectAll(): void {\n if (this.allSelected()) this.setSelected([]);\n else this.setSelected(this.sortedEntries().map((e) => e.id));\n }\n\n // ---- Column resize ----\n\n protected widthFor(column: DataGridColumn): number | undefined {\n return this.columnWidths()[column.id] ?? column.width;\n }\n\n /** Inline style of a column's cells: its width, and its alignment where one is set. */\n protected cellStyle(column: DataGridColumn): string | null {\n const parts: string[] = [];\n const width = this.widthFor(column);\n if (width) parts.push(`width:${width}px`);\n if (column.align) parts.push(`text-align:${column.align}`);\n return parts.length > 0 ? parts.join(\";\") : null;\n }\n\n private setWidth(column: DataGridColumn, width: number): void {\n this.columnWidths.update((current) => ({ ...current, [column.id]: Math.max(MIN_COLUMN_WIDTH, width) }));\n }\n\n protected onResizeKeydown(column: DataGridColumn, event: Event): void {\n const e = event as KeyboardEvent;\n // The resize handle is its own tab stop outside the grid's roving-tabindex system — every key here must stop.\n e.stopPropagation();\n const current = this.widthFor(column) ?? 120;\n if (e.key === \"ArrowRight\") {\n e.preventDefault();\n this.setWidth(column, current + RESIZE_STEP);\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n this.setWidth(column, current - RESIZE_STEP);\n }\n }\n\n protected onResizePointerDown(column: DataGridColumn, event: Event): void {\n const e = event as PointerEvent;\n e.preventDefault();\n const startX = e.clientX;\n const target = e.target as HTMLElement;\n const startWidth = this.widthFor(column) ?? target.closest(\"th\")?.getBoundingClientRect().width ?? 120;\n target.setPointerCapture?.(e.pointerId);\n const onMove = (moveEvent: PointerEvent): void => this.setWidth(column, startWidth + (moveEvent.clientX - startX));\n const onUp = (): void => {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n }\n\n // ---- Column visibility, pagination ----\n\n protected toggleColumnVisibility(columnId: string): void {\n this.hiddenColumnIds.update((current) => {\n const next = new Set(current);\n if (next.has(columnId)) next.delete(columnId);\n else next.add(columnId);\n return next;\n });\n }\n\n protected goToPage(next: number): void {\n const target = Math.min(Math.max(next, 1), this.pageCount());\n if (target === this.clampedPage()) return;\n this.page.set(target);\n this.announce(this.labels().pageAnnouncement?.(target, this.pageCount()));\n }\n\n // ---- Column reorder ----\n\n /** Move `columnId` to sit at `toVisibleIndex` among the visible columns. Returns whether it moved. */\n private moveColumn(columnId: string, toVisibleIndex: number): boolean {\n const ids = this.visibleColumns().map((c) => c.id);\n const from = ids.indexOf(columnId);\n const to = Math.min(Math.max(toVisibleIndex, 0), ids.length - 1);\n if (from === -1 || from === to) return false;\n ids.splice(to, 0, ...ids.splice(from, 1));\n // Hidden columns keep their places in the full order; visible ones are re-sequenced around them.\n const visibleSet = new Set(ids);\n let next = 0;\n this.columnOrder.set(this.orderedColumns().map((c) => (visibleSet.has(c.id) ? ids[next++] : c.id)));\n const column = this.resolvedColumns().find((c) => c.id === columnId)!;\n this.announce(this.labels().columnMoveAnnouncement?.(column.header, to + 1, ids.length));\n return true;\n }\n\n protected onHeaderDragStart(column: DataGridColumn, event: Event): void {\n if (!column.movable) return;\n this.draggingColumnId = column.id;\n (event as DragEvent).dataTransfer?.setData(\"text/plain\", column.id);\n }\n\n protected onHeaderDragOver(event: Event): void {\n if (this.draggingColumnId) event.preventDefault();\n }\n\n protected onHeaderDrop(targetId: string, event: Event): void {\n event.preventDefault();\n const id = this.draggingColumnId;\n this.draggingColumnId = null;\n if (!id || id === targetId) return;\n const to = this.visibleColumns().findIndex((c) => c.id === targetId);\n if (to >= 0) this.moveColumn(id, to);\n }\n\n // ---- Windowing ----\n\n protected onScroll(event: Event): void {\n if (this.virtualize()) this.scrollTop.set((event.currentTarget as HTMLElement).scrollTop);\n }\n\n /** Bring a body row into the scroll region. */\n private revealRow(index: number): void {\n const v = this.virtualize();\n if (!v || index < 0) return;\n const top = index * v.rowHeight;\n const current = this.scrollTop();\n let next = current;\n if (top < current) next = top;\n else if (top + v.rowHeight > current + v.height) next = top + v.rowHeight - v.height;\n if (next === current) return;\n this.scrollTop.set(next);\n const el = this.scrollRef()?.nativeElement;\n if (el) el.scrollTop = next;\n }\n\n // ---- Focus ----\n\n private focusActiveCell(): void {\n afterNextRender(\n () => {\n this.rootRef().nativeElement\n .querySelector<HTMLElement>('.data-table-th[tabindex=\"0\"], .data-table-td[tabindex=\"0\"]')\n ?.focus({ preventScroll: true });\n },\n { injector: this.injector },\n );\n }\n\n private moveFocus(row: number, col: number): void {\n const nextRow = Math.min(Math.max(row, -1), this.pageEntries().length - 1);\n this.focusedRow.set(nextRow);\n this.focusedCol.set(Math.min(Math.max(col, 0), this.lastCol()));\n this.revealRow(nextRow);\n this.focusActiveCell();\n }\n\n // ---- Export ----\n\n /** One cell for an export: typed values stay typed, everything else is the text the grid shows. */\n private exportCell(column: DataGridColumn, row: DataGridRow): unknown {\n if (column.exportValue) return column.exportValue(row);\n const ctx = this.cellFor(column, row);\n const value = ctx.value;\n if (value === null || value === undefined) return null;\n if (typeof value === \"number\" || typeof value === \"boolean\" || value instanceof Date) return value;\n return ctx.formatted;\n }\n\n private hasUtcColumn(c: DataGridColumn): boolean {\n return c.type === \"time-zone\" && !!c.exportUtc && !!c.referenceDate && !!this.labels().exportUtcHeader;\n }\n\n protected runExport(format: ExportFormat): void {\n const live = (c: DataGridColumn) => format === \"xlsx\" && this.exportFormulas() && c.type === \"formula\" && !!c.source;\n const headers: string[] = [];\n for (const c of this.exportColumns()) {\n headers.push(c.header);\n if (this.hasUtcColumn(c)) headers.push(this.labels().exportUtcHeader!(c.header));\n }\n const rows = this.exportEntries().map((entry) => {\n const cells: unknown[] = [];\n for (const c of this.exportColumns()) {\n const expression = live(c) ? c.source!(entry.row) : undefined;\n cells.push(\n typeof expression === \"string\" && expression !== \"\" && !c.errorOf?.(entry.row)\n ? { formula: expression, result: this.exportCell(c, entry.row) }\n : this.exportCell(c, entry.row),\n );\n if (this.hasUtcColumn(c)) cells.push(zonedUtcTime(this.cellFor(c, entry.row).value, c.referenceDate));\n }\n return cells;\n });\n const table = { headers, rows };\n const name = this.exportFilename();\n const filename = exportFilename(name, format);\n const blob = exportBlob(table, format, { sheetName: name });\n const file: DataGridExport = { format, filename, rowCount: rows.length, blob };\n this.exportFile.emit(file);\n if (this.exportHandler()?.(file) === false) return;\n downloadBlob(blob, filename);\n this.announce(this.labels().exportAnnouncement?.(format, rows.length, filename));\n }\n\n // ---- Files ----\n\n /** Files dropped on an editable file cell: the same report as the file input. The grid uploads nothing. */\n protected onFileDragOver(column: DataGridColumn, event: Event): void {\n if (column.type !== \"file\" || !column.editable) return;\n if (Array.from((event as DragEvent).dataTransfer?.types ?? []).includes(\"Files\")) event.preventDefault();\n }\n\n protected onFileDrop(entry: DataGridEntry, column: DataGridColumn, event: Event): void {\n if (column.type !== \"file\" || !column.editable) return;\n const dropped = Array.from((event as DragEvent).dataTransfer?.files ?? []);\n if (dropped.length === 0) return;\n event.preventDefault();\n const files = column.multiple === false ? dropped.slice(0, 1) : dropped;\n this.filesSelected.emit({ rowId: entry.id, row: entry.row, columnId: column.id, files });\n }\n\n protected onFileInput(entry: DataGridEntry, column: DataGridColumn, event: Event): void {\n const input = event.target as HTMLInputElement;\n const chosen = Array.from(input.files ?? []);\n if (chosen.length > 0) this.filesSelected.emit({ rowId: entry.id, row: entry.row, columnId: column.id, files: chosen });\n input.value = \"\";\n }\n\n // ---- Cell editing ----\n\n /** A cell the person can edit through the grid's edit model (not a rollup, a file cell with its own widgets, or a person cell with no editor). */\n protected isEditable(column: DataGridColumn): boolean {\n if (!column.editable) return false;\n if (column.type === \"rollup\" || column.type === \"file\") return false;\n if (column.type === \"person\" && !column.personEditor) return false;\n return true;\n }\n\n protected isEditingCell(entry: DataGridEntry, column: DataGridColumn): boolean {\n const e = this.editingState();\n return !!e && e.rowId === entry.id && e.columnId === column.id;\n }\n\n protected startEdit(entry: DataGridEntry, column: DataGridColumn): void {\n if (!this.isEditable(column)) return;\n // A formula's editor shows the expression the row holds, not the result.\n const raw = column.type === \"formula\" && column.source ? column.source(entry.row) : defaultAccessor(column, entry.row);\n if (column.type === \"time-zone\") {\n const zoned = isZonedTime(raw) ? raw : null;\n this.editingState.set({ rowId: entry.id, columnId: column.id, draft: zoned?.time ?? \"\", zone: zoned?.timeZone ?? column.timeZones?.[0]?.id ?? \"\" });\n } else {\n const text = column.type === \"link\" ? (linkParts(raw)?.href ?? \"\") : raw === null || raw === undefined ? \"\" : String(raw);\n this.editingState.set({ rowId: entry.id, columnId: column.id, draft: text });\n }\n afterNextRender(\n () => {\n const editor = this.rootRef().nativeElement.querySelector<HTMLInputElement | HTMLSelectElement>(\".data-grid-cell-editor\");\n editor?.focus();\n if (editor instanceof HTMLInputElement && editor.type === \"text\") editor.select();\n },\n { injector: this.injector },\n );\n }\n\n private parseDraft(column: DataGridColumn, row: DataGridRow, draft: string, zone?: string): unknown {\n if (column.parse) return column.parse(draft, row);\n if (column.type === \"time-zone\") return draft === \"\" ? null : { time: draft, timeZone: zone ?? \"\" };\n if (column.editor === \"number\") return draft.trim() === \"\" ? null : Number(draft);\n if (column.editor === \"date\" || column.editor === \"time\" || column.editor === \"select\") return draft === \"\" ? null : draft;\n return draft;\n }\n\n /** Two link values with the same address and label are the same edit. */\n private isStructurallyEqual(a: unknown, b: unknown): boolean {\n return typeof a === \"object\" && typeof b === \"object\" && a !== null && b !== null && JSON.stringify(a) === JSON.stringify(b);\n }\n\n /** Validate and report one new value for a cell. Returns false (and keeps editing, if the editor is open) when it is refused. */\n protected commitValue(entry: DataGridEntry, column: DataGridColumn, value: unknown): boolean {\n const message = column.validate?.(value, entry.row);\n const invalidType = isInvalidForType(column, value);\n if (message || invalidType) {\n const text = message ?? this.labels().invalidValue?.(column.header, column.type ?? \"\") ?? \"\";\n const current = this.editingState();\n if (current) this.editingState.set({ ...current, error: text || undefined, invalid: true });\n this.announce(this.labels().editError?.(column.header, text));\n return false;\n }\n const previous = column.type === \"formula\" && column.source ? column.source(entry.row) : defaultAccessor(column, entry.row);\n this.editingState.set(null);\n if (value !== previous && !this.isStructurallyEqual(value, previous)) {\n this.cellEdit.emit({ rowId: entry.id, row: entry.row, columnId: column.id, value, previous });\n this.announce(this.labels().editAnnouncement?.(column.header, column.format ? column.format(value, entry.row) : String(value ?? \"\")));\n }\n return true;\n }\n\n private commitEdit(): void {\n const current = this.editingState();\n if (!current) return;\n const entry = this.entries().find((e) => e.id === current.rowId);\n const column = this.resolvedColumns().find((c) => c.id === current.columnId);\n if (!entry || !column) {\n this.editingState.set(null);\n return;\n }\n if (this.commitValue(entry, column, this.parseDraft(column, entry.row, current.draft, current.zone))) this.focusActiveCell();\n }\n\n private cancelEdit(): void {\n const current = this.editingState();\n if (!current) return;\n this.editingState.set(null);\n const column = this.resolvedColumns().find((c) => c.id === current.columnId);\n if (column) this.announce(this.labels().editCancelAnnouncement?.(column.header));\n this.focusActiveCell();\n }\n\n protected onEditorKeydown(event: Event): void {\n const e = event as KeyboardEvent;\n // The editor owns its keys; none may reach the grid's own handler.\n e.stopPropagation();\n // While an input method is composing, Enter picks the candidate and Escape cancels the composition:\n // neither commits nor cancels the edit. Some browsers report the confirming Enter with `isComposing`\n // already false, but keyCode 229.\n if (e.isComposing || e.keyCode === 229) return;\n if (e.key === \"Enter\") {\n e.preventDefault();\n this.commitEdit();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n this.cancelEdit();\n }\n }\n\n protected onEditorBlur(): void {\n if (this.editingState()) this.commitEdit();\n }\n\n /** Focus leaving the time-zone editor's pair (not moving between its two controls) commits. */\n protected onZonedFocusout(event: Event): void {\n const e = event as FocusEvent;\n if (this.editingState() && !(e.currentTarget as HTMLElement).contains(e.relatedTarget as Node | null)) this.commitEdit();\n }\n\n protected setDraft(event: Event): void {\n const current = this.editingState();\n if (current) this.editingState.set({ ...current, draft: (event.target as HTMLInputElement | HTMLSelectElement).value, error: undefined, invalid: false });\n }\n\n protected setZone(event: Event): void {\n const current = this.editingState();\n if (current) this.editingState.set({ ...current, zone: (event.target as HTMLSelectElement).value, error: undefined, invalid: false });\n }\n\n protected personEditorContext(entry: DataGridEntry, column: DataGridColumn, ctx: DataGridCellContext): DataGridPersonEditorContext {\n return { value: ctx.value, commit: (v: unknown) => void this.commitValue(entry, column, v), cancel: () => this.cancelEdit() };\n }\n\n // ---- Keyboard (WAI-ARIA APG Grid pattern) ----\n\n private activateFocusedCell(): void {\n if (this.activeCol() === 0 && this.hasSelection()) {\n if (this.activeRow() === -1) {\n if (this.selectionMode() === \"multiple\") this.toggleSelectAll();\n } else {\n this.toggleRow(this.pageStart() + this.activeRow());\n }\n return;\n }\n const column = this.visibleColumns()[this.activeCol() - this.colOffset()];\n if (!column) return;\n if (this.activeRow() === -1) this.toggleSort(column);\n }\n\n /** The widgets a consumer put in a body cell (never the grid's own controls). */\n private widgetsIn(cell: Element): HTMLElement[] {\n return Array.from(cell.querySelectorAll<HTMLElement>(WIDGET_SELECTOR)).filter((el) => !el.closest(\"[data-grid-own]\"));\n }\n\n private setWidgetTabindex(cell: Element, value: \"0\" | \"-1\"): void {\n for (const widget of this.widgetsIn(cell)) widget.setAttribute(\"tabindex\", value);\n }\n\n private normaliseWidgets(): void {\n if (!this.isGrid()) return;\n for (const cell of this.rootRef().nativeElement.querySelectorAll(\".data-table-body [data-row][data-col]\")) {\n if (cell.getAttribute(\"data-grid-entered\") === \"true\") continue;\n this.setWidgetTabindex(cell, \"-1\");\n }\n }\n\n /** Focus the first widget of a cell; its widgets are tab stops while focus stays inside it. */\n private enterCell(cell: HTMLElement): boolean {\n const first = this.widgetsIn(cell)[0];\n if (!first) return false;\n cell.setAttribute(\"data-grid-entered\", \"true\");\n this.setWidgetTabindex(cell, \"0\");\n first.focus();\n return true;\n }\n\n private leaveCell(cell: Element): void {\n if (cell.getAttribute(\"data-grid-entered\") !== \"true\") return;\n cell.removeAttribute(\"data-grid-entered\");\n this.setWidgetTabindex(cell, \"-1\");\n }\n\n /** Pointer or programmatic focus on a cell moves the roving position to it. */\n protected onGridFocusin(event: Event): void {\n if (!this.isGrid()) return;\n const target = event.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell) return;\n this.focusedRow.set(Number(cell.dataset[\"row\"]));\n this.focusedCol.set(Number(cell.dataset[\"col\"]));\n // Focus arriving on a widget (a click, or Tab inside the cell) makes the cell's widgets tab stops.\n if (target !== cell && !target.closest(\"[data-grid-own]\") && cell.closest(\".data-table-body\")) {\n cell.setAttribute(\"data-grid-entered\", \"true\");\n this.setWidgetTabindex(cell, \"0\");\n }\n }\n\n protected onGridFocusout(event: Event): void {\n if (!this.isGrid()) return;\n const e = event as FocusEvent;\n const cell = (e.target as HTMLElement).closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell) return;\n const next = e.relatedTarget as Node | null;\n if (next && cell.contains(next)) return;\n this.leaveCell(cell);\n }\n\n /** A click on a body cell, outside any widget, activates its row. */\n protected onGridClick(event: Event): void {\n if (!this.activateRows()) return;\n const target = event.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell || cell.closest(\".data-table-head\")) return;\n if (target.closest(WIDGET_SELECTOR) || target.closest(\"[data-grid-own]\")) return;\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n if (entry) this.rowActivate.emit({ row: entry.row, id: entry.id });\n }\n\n /** A double click on an editable body cell starts editing it. */\n protected onGridDblclick(event: Event): void {\n const target = event.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell || cell.closest(\".data-table-head\") || target.closest(\"input, button, select, textarea\")) return;\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n const column = this.visibleColumns()[Number(cell.dataset[\"col\"]) - this.colOffset()];\n if (entry && column && this.isEditable(column)) this.startEdit(entry, column);\n }\n\n protected onGridKeydown(event: Event): void {\n if (!this.isGrid()) return;\n const e = event as KeyboardEvent;\n const target = e.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell) return;\n // A key pressed on a widget inside a cell belongs to the widget: the caret moves in a field, a select\n // opens, a link follows. Only Escape is the grid's, and it hands focus back to the cell.\n if (target !== cell && !target.closest(\"[data-grid-own]\")) {\n if (e.key === \"Escape\") {\n e.preventDefault();\n cell.focus({ preventScroll: true });\n }\n return;\n }\n const activeRow = this.activeRow();\n const activeCol = this.activeCol();\n const colOffset = this.colOffset();\n if (e.altKey && activeRow === -1 && (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\")) {\n const column = this.visibleColumns()[activeCol - colOffset];\n if (column?.movable) {\n e.preventDefault();\n const delta = e.key === \"ArrowRight\" ? 1 : -1;\n if (this.moveColumn(column.id, activeCol - colOffset + delta)) this.moveFocus(-1, activeCol + delta);\n return;\n }\n }\n const size = this.pageSize();\n switch (e.key) {\n case \"ArrowRight\":\n e.preventDefault();\n this.moveFocus(activeRow, activeCol + 1);\n break;\n case \"ArrowLeft\":\n e.preventDefault();\n this.moveFocus(activeRow, activeCol - 1);\n break;\n case \"ArrowDown\":\n e.preventDefault();\n this.moveFocus(activeRow + 1, activeCol);\n break;\n case \"ArrowUp\":\n e.preventDefault();\n this.moveFocus(activeRow - 1, activeCol);\n break;\n case \"Home\":\n e.preventDefault();\n if (e.ctrlKey || e.metaKey) this.moveFocus(-1, 0);\n else this.moveFocus(activeRow, 0);\n break;\n case \"End\":\n e.preventDefault();\n if (e.ctrlKey || e.metaKey) this.moveFocus(this.pageEntries().length - 1, this.lastCol());\n else this.moveFocus(activeRow, this.lastCol());\n break;\n case \"PageDown\":\n e.preventDefault();\n this.moveFocus(activeRow + (size ?? 10), activeCol);\n break;\n case \"PageUp\":\n e.preventDefault();\n this.moveFocus(activeRow - (size ?? 10), activeCol);\n break;\n case \"F2\": {\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n const column = this.visibleColumns()[Number(cell.dataset[\"col\"]) - colOffset];\n if (target === cell && entry && column && this.isEditable(column)) {\n e.preventDefault();\n this.startEdit(entry, column);\n }\n break;\n }\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (e.key === \"Enter\" && target === cell && cell.closest(\".data-table-body\")) {\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n const column = this.visibleColumns()[Number(cell.dataset[\"col\"]) - colOffset];\n if (entry && column && this.isEditable(column)) {\n this.startEdit(entry, column);\n break;\n }\n }\n if (target === cell && cell.closest(\".data-table-body\") && !cell.querySelector(\"[data-grid-own]\")) {\n // A cell with a widget in it is entered; one without activates its row.\n if (this.enterCell(cell)) break;\n if (e.key === \"Enter\" && this.activateRows()) {\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n if (entry) this.rowActivate.emit({ row: entry.row, id: entry.id });\n break;\n }\n }\n this.activateFocusedCell();\n break;\n }\n }\n\n // ---- Persistence ----\n\n private restoreView(key: string): void {\n try {\n const raw = localStorage.getItem(key);\n if (raw) {\n const saved = JSON.parse(raw) as { columnWidths?: Record<string, number>; hiddenColumnIds?: string[]; sort?: DataGridSort };\n if (saved.columnWidths) this.columnWidths.set(saved.columnWidths);\n if (saved.hiddenColumnIds) this.hiddenColumnIds.set(new Set(saved.hiddenColumnIds));\n if (saved.sort) this.sort.set(saved.sort);\n }\n } catch {\n // ignore quota / privacy / parse errors\n }\n }\n\n // ---- Template helpers ----\n\n protected rowLabelOf(entry: DataGridEntry): string {\n const first = this.visibleColumns()[0];\n return first ? this.cellFor(first, entry.row).formatted : entry.id;\n }\n\n protected cellClassOf(column: DataGridColumn, ctx: DataGridCellContext): string {\n const extra = typeof column.cellClass === \"function\" ? column.cellClass(ctx) : column.cellClass;\n return extra ?? \"\";\n }\n\n protected peopleIn(value: unknown): DataGridPerson[] {\n return peopleOf(value);\n }\n\n protected shownPeople(column: DataGridColumn, value: unknown): DataGridPerson[] {\n const people = peopleOf(value);\n return column.maxPeople !== undefined ? people.slice(0, Math.max(0, column.maxPeople)) : people;\n }\n\n protected nameOf(person: DataGridPerson): string {\n return personName(person);\n }\n\n protected filesIn(value: unknown): DataGridFile[] {\n return filesOf(value);\n }\n\n protected linkIn(value: unknown): DataGridLink | null {\n return linkParts(value);\n }\n\n protected hrefOf(href: string | undefined): string | null {\n return href === undefined ? null : safeHref(href);\n }\n\n protected stringOf(value: unknown): string {\n return String(value);\n }\n\n protected ungroupedOptions(column: DataGridColumn): DataGridOption[] {\n return (column.options ?? []).filter((o) => !o.group);\n }\n\n protected groupsOf(column: DataGridColumn): string[] {\n return [...new Set((column.options ?? []).filter((o) => o.group).map((o) => o.group as string))];\n }\n\n protected optionsInGroup(column: DataGridColumn, group: string): DataGridOption[] {\n return (column.options ?? []).filter((o) => o.group === group);\n }\n}\n\nexport default DataGrid;\n"],"mappings":"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"}
1
+ {"version":3,"file":"lilydesignsystem-angular-data-grid.mjs","names":[],"sources":["../../export-data.ts","../../search-text.ts","../../direction.ts","../../grid-navigation.ts","../../label-coverage.ts","../../edit-history.ts","../../typeahead.ts","../../cell-types.ts","../../data-grid.component.ts"],"sourcesContent":["// Table export for DataGrid: CSV, TSV and Excel (.xlsx), as pure functions.\n//\n// Nothing here knows about the grid. A table is a header row plus rows of\n// cell values, and every function turns one into text or bytes, so a consumer\n// who wants their own export button (or a server-side export) can call them\n// directly. DataGrid's own buttons are a thin layer on top.\n//\n// The .xlsx writer has no dependencies: a workbook is a ZIP of a few XML\n// parts, and the ZIP here only *stores* (no compression), which Excel,\n// LibreOffice, Numbers and Google Sheets all read. Entries carry a fixed\n// timestamp, so the same table always produces the same bytes.\n\nexport type ExportFormat = \"csv\" | \"tsv\" | \"xlsx\";\n\n/**\n * A live formula and the result it last computed. In an .xlsx the cell keeps the formula with the result cached\n * (a spreadsheet user keeps the live formula); CSV and TSV carry only the result.\n */\nexport type ExportFormula = { formula: string; result: unknown };\n\n/** Whether a cell value is an {@link ExportFormula}. */\nexport function isExportFormula(value: unknown): value is ExportFormula {\n return !!value && typeof value === \"object\" && !(value instanceof Date) && typeof (value as ExportFormula).formula === \"string\" && \"result\" in (value as object);\n}\n\n/** A header row and rows of cell values. A cell is a string, number, boolean, `Date`, an {@link ExportFormula}, or empty. */\nexport type ExportTable = {\n headers: string[];\n rows: unknown[][];\n};\n\nexport type DelimitedOptions = {\n /** Field separator. Default `\",\"` (use `\"\\t\"` for TSV). */\n delimiter?: string;\n /** Write the header row. Default true. */\n header?: boolean;\n /** Prefix a UTF-8 byte-order mark so Excel opens the file as UTF-8. Default false. */\n bom?: boolean;\n /** Defuse spreadsheet formulas: a string starting with `=`, `+`, `-`, `@`, tab or CR gets a leading `'`. Default true. */\n safe?: boolean;\n /** Line ending. Default `\"\\r\\n\"` (RFC 4180). */\n eol?: string;\n};\n\nexport type XlsxOptions = {\n /** Worksheet name (31 characters at most; `[]:*?/\\` are replaced). Default `\"Sheet1\"`. */\n sheetName?: string;\n /** Write the header row, in bold. Default true. */\n header?: boolean;\n};\n\nexport const MIME_TYPES: Record<ExportFormat, string> = {\n csv: \"text/csv;charset=utf-8\",\n tsv: \"text/tab-separated-values;charset=utf-8\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n};\n\n// ---------------------------------------------------------------------\n// Delimited text (CSV / TSV)\n// ---------------------------------------------------------------------\n\nconst FORMULA_START = /^[=+\\-@\\t\\r]/;\n\n/** One cell as text. Numbers and booleans are never treated as formulas; only strings are defused. */\nexport function cellText(value: unknown, safe = true): string {\n if (value === null || value === undefined) return \"\";\n if (isExportFormula(value)) return cellText(value.result, safe);\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return \"\";\n // A date at exactly UTC midnight is a civil date: write it without a time of day.\n const iso = value.toISOString();\n return iso.endsWith(\"T00:00:00.000Z\") ? iso.slice(0, 10) : iso;\n }\n if (typeof value === \"number\") return Number.isFinite(value) ? String(value) : \"\";\n if (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n const text = String(value);\n return safe && FORMULA_START.test(text) ? `'${text}` : text;\n}\n\nfunction quoteField(text: string, delimiter: string): string {\n return text.includes(delimiter) || /[\"\\r\\n]/.test(text) ? `\"${text.replace(/\"/g, '\"\"')}\"` : text;\n}\n\n/** CSV/TSV text for a table. Fields containing the delimiter, a quote or a line break are quoted. */\nexport function toDelimited(table: ExportTable, options: DelimitedOptions = {}): string {\n const { delimiter = \",\", header = true, bom = false, safe = true, eol = \"\\r\\n\" } = options;\n const lines: string[] = [];\n if (header) lines.push(table.headers.map((h) => quoteField(cellText(h, safe), delimiter)).join(delimiter));\n for (const row of table.rows) {\n lines.push(table.headers.map((_, i) => quoteField(cellText(row[i], safe), delimiter)).join(delimiter));\n }\n return (bom ? \"\" : \"\") + lines.join(eol) + (lines.length > 0 ? eol : \"\");\n}\n\nexport function toCsv(table: ExportTable, options: Omit<DelimitedOptions, \"delimiter\"> = {}): string {\n return toDelimited(table, { ...options, delimiter: \",\" });\n}\n\nexport function toTsv(table: ExportTable, options: Omit<DelimitedOptions, \"delimiter\"> = {}): string {\n return toDelimited(table, { ...options, delimiter: \"\\t\" });\n}\n\n// ---------------------------------------------------------------------\n// Excel (.xlsx)\n// ---------------------------------------------------------------------\n\nconst encoder = new TextEncoder();\n\n/** XML text with the characters XML 1.0 forbids removed. */\nfunction xmlEscape(text: string): string {\n return text\n .replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F￾￿]/g, \"\")\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/** Column index (0-based) to a spreadsheet column name: 0 → A, 25 → Z, 26 → AA. */\nexport function columnName(index: number): string {\n let n = index;\n let name = \"\";\n do {\n name = String.fromCharCode(65 + (n % 26)) + name;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return name;\n}\n\n/** Days since 1899-12-30 (Excel's day 0, with its 1900 leap-year quirk absorbed), with the time of day as a fraction. */\nfunction excelSerial(date: Date): number {\n return date.getTime() / 86_400_000 + 25_569;\n}\n\nfunction sheetNameFor(name: string): string {\n const cleaned = name.replace(/[[\\]:*?/\\\\]/g, \" \").replace(/\\s+/g, \" \").trim().slice(0, 31);\n return cleaned || \"Sheet1\";\n}\n\n// Cell styles: 0 default, 1 date, 2 date and time, 3 bold (headers).\nconst STYLES_XML =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">' +\n '<numFmts count=\"2\"><numFmt numFmtId=\"164\" formatCode=\"yyyy\\\\-mm\\\\-dd\"/><numFmt numFmtId=\"165\" formatCode=\"yyyy\\\\-mm\\\\-dd\\\\ hh:mm:ss\"/></numFmts>' +\n '<fonts count=\"2\"><font><sz val=\"11\"/><name val=\"Calibri\"/></font><font><b/><sz val=\"11\"/><name val=\"Calibri\"/></font></fonts>' +\n '<fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"gray125\"/></fill></fills>' +\n '<borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>' +\n '<cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>' +\n '<cellXfs count=\"4\">' +\n '<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>' +\n '<xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>' +\n '<xf numFmtId=\"165\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>' +\n '<xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>' +\n \"</cellXfs>\" +\n '<cellStyles count=\"1\"><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/></cellStyles>' +\n \"</styleSheet>\";\n\n/** A formula cell: the expression (without its leading `=`) and the result it last computed, cached. */\nfunction formulaXml(ref: string, value: ExportFormula): string {\n const expression = xmlEscape(value.formula.replace(/^=/, \"\"));\n const result = value.result;\n if (typeof result === \"number\" && Number.isFinite(result)) return `<c r=\"${ref}\"><f>${expression}</f><v>${result}</v></c>`;\n if (typeof result === \"boolean\") return `<c r=\"${ref}\" t=\"b\"><f>${expression}</f><v>${result ? 1 : 0}</v></c>`;\n if (result instanceof Date && !Number.isNaN(result.getTime())) {\n const timeOfDay = result.getTime() % 86_400_000 !== 0;\n return `<c r=\"${ref}\" s=\"${timeOfDay ? 2 : 1}\"><f>${expression}</f><v>${excelSerial(result)}</v></c>`;\n }\n if (result === null || result === undefined) return `<c r=\"${ref}\"><f>${expression}</f></c>`;\n return `<c r=\"${ref}\" t=\"str\"><f>${expression}</f><v>${xmlEscape(String(result))}</v></c>`;\n}\n\nfunction cellXml(ref: string, value: unknown, headerStyle = false): string {\n if (value === null || value === undefined) return \"\";\n if (isExportFormula(value)) return formulaXml(ref, value);\n const s = headerStyle ? ' s=\"3\"' : \"\";\n if (value instanceof Date) {\n if (Number.isNaN(value.getTime())) return \"\";\n const timeOfDay = value.getTime() % 86_400_000 !== 0;\n return `<c r=\"${ref}\" s=\"${timeOfDay ? 2 : 1}\"><v>${excelSerial(value)}</v></c>`;\n }\n if (typeof value === \"number\") return Number.isFinite(value) ? `<c r=\"${ref}\"${s}><v>${value}</v></c>` : \"\";\n if (typeof value === \"boolean\") return `<c r=\"${ref}\"${s} t=\"b\"><v>${value ? 1 : 0}</v></c>`;\n // A string is stored as text, so it is never read as a formula.\n return `<c r=\"${ref}\"${s} t=\"inlineStr\"><is><t xml:space=\"preserve\">${xmlEscape(String(value))}</t></is></c>`;\n}\n\nfunction sheetXml(table: ExportTable, header: boolean): string {\n const rows: string[] = [];\n let rowNumber = 0;\n if (header) {\n rowNumber += 1;\n rows.push(\n `<row r=\"${rowNumber}\">${table.headers.map((h, i) => cellXml(`${columnName(i)}${rowNumber}`, h, true)).join(\"\")}</row>`,\n );\n }\n for (const row of table.rows) {\n rowNumber += 1;\n const cells = table.headers.map((_, i) => cellXml(`${columnName(i)}${rowNumber}`, row[i])).join(\"\");\n rows.push(`<row r=\"${rowNumber}\">${cells}</row>`);\n }\n return (\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">' +\n (header && table.headers.length > 0 ? '<sheetViews><sheetView workbookViewId=\"0\"><pane ySplit=\"1\" topLeftCell=\"A2\" activePane=\"bottomLeft\" state=\"frozen\"/></sheetView></sheetViews>' : \"\") +\n `<sheetData>${rows.join(\"\")}</sheetData></worksheet>`\n );\n}\n\n/** An .xlsx workbook with one worksheet, as bytes. */\nexport function toXlsx(table: ExportTable, options: XlsxOptions = {}): Uint8Array {\n const { sheetName = \"Sheet1\", header = true } = options;\n const files: Record<string, string> = {\n \"[Content_Types].xml\":\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">' +\n '<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>' +\n '<Default Extension=\"xml\" ContentType=\"application/xml\"/>' +\n '<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>' +\n '<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>' +\n '<Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>' +\n \"</Types>\",\n \"_rels/.rels\":\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">' +\n '<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>' +\n \"</Relationships>\",\n \"xl/workbook.xml\":\n '<?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\">' +\n `<sheets><sheet name=\"${xmlEscape(sheetNameFor(sheetName))}\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>`,\n \"xl/_rels/workbook.xml.rels\":\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>' +\n '<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">' +\n '<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>' +\n '<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>' +\n \"</Relationships>\",\n \"xl/styles.xml\": STYLES_XML,\n \"xl/worksheets/sheet1.xml\": sheetXml(table, header),\n };\n return zipStore(Object.entries(files).map(([name, text]) => ({ name, data: encoder.encode(text) })));\n}\n\n// ---------------------------------------------------------------------\n// ZIP (store only)\n// ---------------------------------------------------------------------\n\nlet crcTable: Uint32Array | undefined;\n\nexport function crc32(bytes: Uint8Array): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let crc = 0xffffffff;\n for (let i = 0; i < bytes.length; i++) crc = crcTable[(crc ^ bytes[i]) & 0xff] ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n// 1980-01-01 00:00:00, the ZIP epoch: a fixed stamp keeps the output reproducible.\nconst DOS_TIME = 0x0000;\nconst DOS_DATE = 0x0021;\n\n/** A ZIP archive holding `entries` uncompressed. */\nexport function zipStore(entries: { name: string; data: Uint8Array }[]): Uint8Array {\n const parts: Uint8Array[] = [];\n const central: Uint8Array[] = [];\n let offset = 0;\n for (const { name, data } of entries) {\n const nameBytes = encoder.encode(name);\n const crc = crc32(data);\n const local = new DataView(new ArrayBuffer(30));\n local.setUint32(0, 0x04034b50, true);\n local.setUint16(4, 20, true); // version needed\n local.setUint16(6, 0x0800, true); // flags: UTF-8 names\n local.setUint16(8, 0, true); // method: stored\n local.setUint16(10, DOS_TIME, true);\n local.setUint16(12, DOS_DATE, true);\n local.setUint32(14, crc, true);\n local.setUint32(18, data.length, true);\n local.setUint32(22, data.length, true);\n local.setUint16(26, nameBytes.length, true);\n local.setUint16(28, 0, true);\n parts.push(new Uint8Array(local.buffer), nameBytes, data);\n\n const entry = new DataView(new ArrayBuffer(46));\n entry.setUint32(0, 0x02014b50, true);\n entry.setUint16(4, 20, true); // version made by\n entry.setUint16(6, 20, true); // version needed\n entry.setUint16(8, 0x0800, true);\n entry.setUint16(10, 0, true);\n entry.setUint16(12, DOS_TIME, true);\n entry.setUint16(14, DOS_DATE, true);\n entry.setUint32(16, crc, true);\n entry.setUint32(20, data.length, true);\n entry.setUint32(24, data.length, true);\n entry.setUint16(28, nameBytes.length, true);\n entry.setUint32(42, offset, true);\n central.push(new Uint8Array(entry.buffer), nameBytes);\n\n offset += 30 + nameBytes.length + data.length;\n }\n const centralSize = central.reduce((n, p) => n + p.length, 0);\n const end = new DataView(new ArrayBuffer(22));\n end.setUint32(0, 0x06054b50, true);\n end.setUint16(8, entries.length, true);\n end.setUint16(10, entries.length, true);\n end.setUint32(12, centralSize, true);\n end.setUint32(16, offset, true);\n const all = [...parts, ...central, new Uint8Array(end.buffer)];\n const out = new Uint8Array(all.reduce((n, p) => n + p.length, 0));\n let at = 0;\n for (const p of all) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------\n// Files\n// ---------------------------------------------------------------------\n\n/** The file for `table` in `format`, as a `Blob`. CSV and TSV carry a UTF-8 byte-order mark so Excel reads them as UTF-8. */\nexport function exportBlob(table: ExportTable, format: ExportFormat, options: { sheetName?: string; header?: boolean } = {}): Blob {\n if (format === \"xlsx\") return new Blob([toXlsx(table, options) as BlobPart], { type: MIME_TYPES.xlsx });\n const text = toDelimited(table, { delimiter: format === \"tsv\" ? \"\\t\" : \",\", header: options.header, bom: true });\n return new Blob([text], { type: MIME_TYPES[format] });\n}\n\n/** A filename with the format's extension, without doubling one the name already has. */\nexport function exportFilename(base: string, format: ExportFormat): string {\n const cleaned = base.replace(/[\\\\/:*?\"<>|\\u0000-\\u001F]/g, \"-\").trim() || \"export\";\n return cleaned.toLowerCase().endsWith(`.${format}`) ? cleaned : `${cleaned}.${format}`;\n}\n\n/** Saves a blob through a temporary link. Does nothing outside a browser. */\nexport function downloadBlob(blob: Blob, filename: string): void {\n if (typeof document === \"undefined\" || typeof URL === \"undefined\" || !URL.createObjectURL) return;\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n // Revoking at once can cancel the download in some browsers.\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\n// ---------------------------------------------------------------------\n// Clipboard\n// ---------------------------------------------------------------------\n\n/** The table as tab-separated text with its header row, ready to paste into a spreadsheet (no byte-order mark, formula text defused). */\nexport function toClipboardText(table: ExportTable): string {\n return toTsv(table, { bom: false });\n}\n\n/**\n * Write `text` to the clipboard: the async Clipboard API where there is one, otherwise a hidden, selected `<textarea>` and\n * `document.execCommand(\"copy\")`. Resolves true when something was copied, false when neither path worked (no permission, no\n * secure context, no DOM). Never throws.\n */\nexport async function copyToClipboard(text: string): Promise<boolean> {\n try {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return true;\n }\n } catch {\n // fall through to the textarea path\n }\n try {\n if (typeof document === \"undefined\") return false;\n const area = document.createElement(\"textarea\");\n area.value = text;\n area.setAttribute(\"readonly\", \"\");\n area.setAttribute(\"aria-hidden\", \"true\");\n area.style.position = \"fixed\";\n area.style.opacity = \"0\";\n document.body.appendChild(area);\n area.select();\n const ok = typeof document.execCommand === \"function\" && document.execCommand(\"copy\");\n area.remove();\n return !!ok;\n } catch {\n return false;\n }\n}\n","/**\n * Search matching shared by the data grid, kanban board, Gantt chart and calendar: pure, so it is unit-tested without a browser.\n *\n * A query is split on whitespace into terms; every term must appear (AND), in any order, ignoring case and diacritics\n * (\"cafe\" finds \"Café\"). An empty query matches everything.\n */\n\n/** Lower-case and strip combining marks, so matching ignores case and diacritics. */\nexport function foldText(text: string): string {\n return text.normalize(\"NFD\").replace(/\\p{M}+/gu, \"\").toLowerCase();\n}\n\n/** The terms of a query, folded; empty when the query is blank. */\nexport function searchTerms(query: string): string[] {\n return foldText(query).split(/\\s+/).filter(Boolean);\n}\n\n/** True when every term of `query` appears in `text`. */\nexport function matchesSearch(text: string, query: string): boolean {\n const terms = searchTerms(query);\n if (terms.length === 0) return true;\n const folded = foldText(text);\n return terms.every((term) => folded.includes(term));\n}\n\nexport type SearchSegment = { text: string; match: boolean };\n\n/**\n * `text` cut into runs, marking the parts any term matches (for `<mark>`). Folding can change a string's length (a precomposed \"é\"\n * is one character, its folded form too, but a ligature may not be), so matching works on a per-character fold and falls back to\n * one unmarked segment if the two ever disagree.\n */\nexport function highlightSegments(text: string, query: string): SearchSegment[] {\n const terms = searchTerms(query);\n if (terms.length === 0 || text === \"\") return [{ text, match: false }];\n const chars = Array.from(text);\n const folded = chars.map((c) => foldText(c));\n if (folded.some((f) => f.length !== 1)) return [{ text, match: false }];\n const flat = folded.join(\"\");\n const marked = new Array<boolean>(chars.length).fill(false);\n for (const term of terms) {\n for (let at = flat.indexOf(term); at !== -1; at = flat.indexOf(term, at + 1)) {\n for (let i = at; i < at + term.length; i++) marked[i] = true;\n }\n }\n const out: SearchSegment[] = [];\n chars.forEach((c, i) => {\n const last = out[out.length - 1];\n if (last && last.match === marked[i]) last.text += c;\n else out.push({ text: c, match: marked[i] });\n });\n return out;\n}\n","/**\n * Reading direction for keyboard navigation. A grid's left and right arrow keys are *visual*: in a right-to-left layout the next\n * cell is on the left, so ArrowLeft must move forward. Pure apart from reading the DOM, so it is unit-tested with a jsdom element.\n */\n\n/** Whether the text around `element` runs right to left: the nearest `dir` attribute wins, then the computed `direction`. */\nexport function isRtl(element: Element | null | undefined): boolean {\n if (!element) return false;\n const attr = element.closest(\"[dir]\")?.getAttribute(\"dir\")?.toLowerCase();\n if (attr === \"rtl\") return true;\n if (attr === \"ltr\") return false;\n if (typeof getComputedStyle === \"function\") return getComputedStyle(element).direction === \"rtl\";\n return false;\n}\n\n/**\n * The key to act on after reading direction into account: in RTL, ArrowLeft and ArrowRight swap. Everything else is unchanged.\n * Callers pass the result to the same `switch` they always used.\n */\nexport function logicalKey(key: string, rtl: boolean): string {\n if (!rtl) return key;\n if (key === \"ArrowLeft\") return \"ArrowRight\";\n if (key === \"ArrowRight\") return \"ArrowLeft\";\n return key;\n}\n","/**\n * Cursor movement for grid-like helpers (data grid, kanban board, Gantt chart): the arrows, Home / End (with Ctrl or Cmd for the\n * corners), PageUp / PageDown, and the right-to-left swap of ArrowLeft and ArrowRight. Pure, so it is unit-tested without a browser\n * and one place fixes it for every helper. What a helper does on its own keys (Enter, F2, Alt+Arrow, a shortcut letter) stays in the\n * helper: this returns the new position for a movement key and `null` for any other key.\n */\nimport { logicalKey } from \"./direction\";\n\nexport type GridPosition = { row: number; col: number };\n\nexport type GridNavigation = {\n /** The first row the cursor may stand on: -1 where the header row is part of the grid, else 0. */\n firstRow: number;\n /** The last row index (`rowCount - 1`). */\n lastRow: number;\n /** The last column index. */\n lastCol: number;\n /** How many rows PageUp and PageDown move. */\n pageStep: number;\n /** What plain Home and End do: `\"row\"` (default) goes to the first or last column of the row; `\"column\"` to the first or last row of the column. */\n homeEnd?: \"row\" | \"column\";\n /** Right-to-left layout: ArrowLeft goes forward, ArrowRight back. */\n rtl?: boolean;\n};\n\n/** How many rows a page key moves: the rows that fit a virtualized viewport, else `fallback` (10 by default). */\nexport function pageStepFor(virtualize: { height: number; rowHeight: number } | undefined, fallback = 10): number {\n return virtualize ? Math.max(1, Math.floor(virtualize.height / virtualize.rowHeight)) : fallback;\n}\n\nconst clamp = (value: number, low: number, high: number): number => Math.min(Math.max(value, low), high);\n\n/** The position the key moves to, kept inside the grid, or `null` when the key is not a movement key. */\nexport function gridMove(\n event: { key: string; ctrlKey?: boolean; metaKey?: boolean },\n at: GridPosition,\n nav: GridNavigation,\n): GridPosition | null {\n const key = logicalKey(event.key, nav.rtl ?? false);\n const corner = !!(event.ctrlKey || event.metaKey);\n let row = at.row;\n let col = at.col;\n switch (key) {\n case \"ArrowRight\":\n col += 1;\n break;\n case \"ArrowLeft\":\n col -= 1;\n break;\n case \"ArrowDown\":\n row += 1;\n break;\n case \"ArrowUp\":\n row -= 1;\n break;\n case \"PageDown\":\n row += nav.pageStep;\n break;\n case \"PageUp\":\n row -= nav.pageStep;\n break;\n case \"Home\":\n if (corner) [row, col] = [nav.firstRow, 0];\n else if (nav.homeEnd === \"column\") row = nav.firstRow;\n else col = 0;\n break;\n case \"End\":\n if (corner) [row, col] = [nav.lastRow, nav.lastCol];\n else if (nav.homeEnd === \"column\") row = nav.lastRow;\n else col = nav.lastCol;\n break;\n default:\n return null;\n }\n return { row: clamp(row, nav.firstRow, nav.lastRow), col: clamp(col, 0, nav.lastCol) };\n}\n","/**\n * Which `labels` a grid needs, by what it renders — so an app can check that it has supplied every string for its locale, and a\n * grid can say, in development, which control it is about to leave unnamed. Lily ships no English: a missing label is a control with\n * no name, or an announcement that is never made, never English text. Pure, so it is unit-tested on its own.\n */\n\n/** What the grid is showing, as far as labels are concerned. */\nexport type LabelFeatures = {\n /** `selectionMode` is not `none`. */\n selection?: boolean;\n /** `pageSize` is set. */\n pagination?: boolean;\n /** Some column is `hidable`. */\n hidableColumns?: boolean;\n /** Some column is `resizable`. */\n resizableColumns?: boolean;\n /** Some column is editable (`onCellEdit` is set). */\n editing?: boolean;\n /** Some column is `sortable`. */\n sorting?: boolean;\n /** The search field is wanted (the field itself is gated by `labels.search`). */\n search?: boolean;\n /** Export or copy buttons are wanted. */\n exporting?: boolean;\n};\n\n/** Labels that **name a control**: without one the control is unnamed to a screen reader (or not rendered at all). */\nexport const CONTROL_LABELS = {\n selection: [\"selectAll\", \"selectionColumn\", \"selectRow\"],\n pagination: [\"previousPage\", \"nextPage\", \"pageStatus\"],\n hidableColumns: [\"columnVisibility\", \"columnVisibilityOption\"],\n resizableColumns: [\"resizeHandle\"],\n editing: [\"editCell\", \"cellEditor\"],\n search: [\"search\"],\n exporting: [\"export\"],\n} as const;\n\n/** Labels that make an **announcement** through the live region: without one the change is silent. */\nexport const ANNOUNCEMENT_LABELS = {\n sorting: [\"sortAnnouncement\"],\n search: [\"filterAnnouncement\"],\n selection: [\"selectionAnnouncement\"],\n pagination: [\"pageAnnouncement\"],\n editing: [\"editAnnouncement\", \"editCancelAnnouncement\", \"editError\", \"undoAnnouncement\", \"redoAnnouncement\"],\n exporting: [\"exportAnnouncement\", \"copyAnnouncement\", \"copyFailed\"],\n} as const;\n\nexport type LabelKind = \"control\" | \"announcement\";\n\n/** Every label key the features in use call for, with its kind. */\nexport function requiredLabels(features: LabelFeatures): { key: string; kind: LabelKind }[] {\n const out: { key: string; kind: LabelKind }[] = [];\n const add = (table: Record<string, readonly string[]>, kind: LabelKind) => {\n for (const feature of Object.keys(table) as (keyof LabelFeatures)[]) {\n if (!features[feature]) continue;\n for (const key of table[feature]) if (!out.some((o) => o.key === key)) out.push({ key, kind });\n }\n };\n add(CONTROL_LABELS, \"control\");\n add(ANNOUNCEMENT_LABELS, \"announcement\");\n return out;\n}\n\n/** The required labels that are absent (`undefined`, `null` or an empty string) from `labels`. */\nexport function missingLabels(features: LabelFeatures, labels: Record<string, unknown> | undefined): { key: string; kind: LabelKind }[] {\n return requiredLabels(features).filter(({ key }) => {\n const value = labels?.[key];\n return value === undefined || value === null || value === \"\";\n });\n}\n","/**\n * Undo / redo for typed-field edits: pure, so it is unit-tested without a browser. The components own nothing but the stacks:\n * the consumer owns the data, so an undo is reported the same way an edit is — through `onFieldEdit`, with the earlier value.\n */\n\n/** One accepted edit: which record and field, the value it took and the value it replaced. */\nexport type EditRecord = { ownerId: string; fieldId: string; value: unknown; previous: unknown };\n\nexport type EditHistory = { undo: readonly EditRecord[]; redo: readonly EditRecord[] };\n\nexport const EMPTY_HISTORY: EditHistory = { undo: [], redo: [] };\n\n/** Most steps kept; the oldest fall off. */\nexport const HISTORY_LIMIT = 100;\n\n/** A new edit goes on the undo stack and ends any redo chain. */\nexport function recordEdit(history: EditHistory, record: EditRecord, limit: number = HISTORY_LIMIT): EditHistory {\n const undo = [...history.undo, record];\n return { undo: undo.length > limit ? undo.slice(undo.length - limit) : undo, redo: [] };\n}\n\n/** Step back: the record to reverse (apply `previous`), and the history with it moved to the redo stack. */\nexport function undoEdit(history: EditHistory): { history: EditHistory; record: EditRecord | undefined } {\n const record = history.undo[history.undo.length - 1];\n if (!record) return { history, record: undefined };\n return { history: { undo: history.undo.slice(0, -1), redo: [...history.redo, record] }, record };\n}\n\n/** Step forward: the record to re-apply (apply `value`), and the history with it moved back to the undo stack. */\nexport function redoEdit(history: EditHistory): { history: EditHistory; record: EditRecord | undefined } {\n const record = history.redo[history.redo.length - 1];\n if (!record) return { history, record: undefined };\n return { history: { undo: [...history.undo, record], redo: history.redo.slice(0, -1) }, record };\n}\n\n/** Whether a key press is Undo (Ctrl/Cmd+Z) or Redo (Ctrl/Cmd+Shift+Z, or Ctrl+Y), or neither. */\nexport function historyKey(event: { key: string; ctrlKey?: boolean; metaKey?: boolean; shiftKey?: boolean; altKey?: boolean }): \"undo\" | \"redo\" | null {\n if (event.altKey || !(event.ctrlKey || event.metaKey)) return null;\n const key = event.key.toLowerCase();\n if (key === \"z\") return event.shiftKey ? \"redo\" : \"undo\";\n if (key === \"y\" && !event.shiftKey) return \"redo\";\n return null;\n}\n","/**\n * Type-ahead for grids: typing letters moves to the next row whose label starts with them. Pure, so it is unit-tested without a browser.\n * The WAI-ARIA APG listbox / tree model: the letters typed in quick succession form one prefix; the prefix resets after a pause; the same\n * letter pressed again cycles through the rows that start with it.\n */\nimport { foldText } from \"./search-text\";\n\nexport const TYPEAHEAD_RESET_MS = 700;\n\nexport type TypeaheadState = { prefix: string; at: number };\n\n/** Whether a key press is a type-ahead character: one printable character, no Ctrl, Alt or Meta. */\nexport function isTypeaheadKey(event: { key: string; ctrlKey?: boolean; altKey?: boolean; metaKey?: boolean }): boolean {\n return event.key.length === 1 && event.key !== \" \" && !event.ctrlKey && !event.altKey && !event.metaKey;\n}\n\n/** The prefix after `key` is pressed at time `now`: it grows while presses are within `resetMs` of each other, else starts over. */\nexport function nextTypeaheadState(previous: TypeaheadState, key: string, now: number, resetMs: number = TYPEAHEAD_RESET_MS): TypeaheadState {\n const continuing = previous.prefix !== \"\" && now - previous.at <= resetMs;\n return { prefix: (continuing ? previous.prefix : \"\") + key, at: now };\n}\n\n/**\n * The index of the row to move to, or -1. Searches from the row after `from` and wraps. A prefix of one repeated letter (\"ss\") is\n * treated as that single letter, so pressing it again steps through the rows starting with it.\n */\nexport function findTypeaheadMatch(labels: readonly string[], from: number, prefix: string): number {\n const folded = foldText(prefix);\n if (folded === \"\" || labels.length === 0) return -1;\n const repeated = folded.length > 1 && [...folded].every((c) => c === folded[0]);\n const needle = repeated ? folded[0] : folded;\n // A growing prefix (\"de\") may keep the current row; a single letter, or a repeated one, must move on.\n const startOffset = needle.length > 1 ? 0 : 1;\n for (let step = 0; step < labels.length; step++) {\n const index = (from + startOffset + step + labels.length) % labels.length;\n if (foldText(labels[index]).startsWith(needle)) return index;\n }\n return -1;\n}\n","// Cell types for DataGrid: a `column.type` is a named bundle of defaults for the\n// hooks a column already has (`format`, `compare`, `filterText`, `exportValue`,\n// `align`, `editor`). Nothing here is new machinery: `resolveColumn` fills in\n// what the column left out, and a column's own props always win.\n//\n// Values are plain data. Display is derived: no English, no default locale (with\n// no `locale` a value shows as stored), no HTML, no icons. See\n// spec/cell-types/index.md.\n\nexport type DataGridCellType =\n | \"text\"\n | \"number\"\n | \"link\"\n | \"date\"\n | \"time\"\n | \"time-zone\"\n | \"select\"\n | \"radio\"\n | \"person\"\n | \"file\"\n | \"rollup\"\n | \"formula\";\n\n/** A time of day and the zone it is stated in (an IANA zone id, or a bare offset such as `+01:00`). */\nexport type DataGridZonedTime = { time: string; timeZone: string };\n\n/** One person: the name is always shown as text; the avatar is the consumer's. */\nexport type DataGridPerson = { id: string; name?: string; email?: string; avatarUrl?: string };\n\n/** One file's metadata. The bytes live elsewhere; the grid never uploads. */\nexport type DataGridFile = { id: string; name: string; size?: number; type?: string; href?: string };\n\n/** What a rollup reduces its related values with. */\nexport type DataGridAggregate =\n | \"count\"\n | \"countUnique\"\n | \"sum\"\n | \"avg\"\n | \"median\"\n | \"min\"\n | \"max\"\n | \"range\"\n | \"percentTrue\"\n | \"percentEmpty\";\n\n/** What a formula engine hands back: a value, or an error message shown as text. */\nexport type DataGridFormulaResult = { value: unknown } | { error: string };\n\n/** What a formula engine is given. `rows` is every row, for references to other rows. */\nexport type DataGridFormulaContext = { row: Record<string, unknown>; rows: Record<string, unknown>[]; columnId: string };\n\n/** An option of a `select` or `radio` column. The label is displayed; the id is stored. */\nexport type DataGridOption = { id: string; label: string; disabled?: boolean; group?: string; [key: string]: unknown };\n\n/** A link value: an address, or an address with a label. */\nexport type DataGridLink = { href: string; label?: string; external?: boolean };\n\n/** The column facets a type can fill in. Structural so this module does not import the grid. */\nexport type TypedColumn = {\n id: string;\n type?: DataGridCellType;\n locale?: string;\n options?: DataGridOption[];\n sortBy?: \"label\" | \"order\";\n exportAs?: \"label\" | \"id\" | \"email\";\n numberFormat?: Intl.NumberFormatOptions;\n dateFormat?: Intl.DateTimeFormatOptions;\n timeFormat?: Intl.DateTimeFormatOptions;\n accessor?: (row: Record<string, unknown>) => unknown;\n format?: (value: unknown, row: Record<string, unknown>) => string;\n compare?: (a: unknown, b: unknown) => number;\n filterText?: (value: unknown, row: Record<string, unknown>) => string;\n exportValue?: (row: Record<string, unknown>) => unknown;\n align?: \"start\" | \"center\" | \"end\";\n editor?: string;\n parse?: (draft: string, row: Record<string, unknown>) => unknown;\n editable?: boolean;\n /** `time-zone`: the zones the editor offers, as `{ id, label }`. */\n timeZones?: DataGridOption[];\n /** `time-zone`: the date (ISO) used to order zoned times and to name a zone. Never computed here. */\n referenceDate?: string;\n /** `rollup`: how the related values are reduced. */\n aggregate?: DataGridAggregate;\n /** `rollup`: anything the named aggregates do not cover. */\n reduce?: (values: unknown[], row: Record<string, unknown>) => unknown;\n /** `rollup`: reads the related values. Defaults to the row's own array at the column id. */\n relation?: (row: Record<string, unknown>) => unknown[];\n /** `rollup` and `formula`: the type of the result, so it formats and sorts like one. */\n resultType?: \"number\" | \"date\" | \"text\";\n /** `formula`: evaluates an expression. Lily ships no engine and never evaluates a string itself. */\n evaluate?: (expression: string, context: DataGridFormulaContext) => DataGridFormulaResult;\n /** `person`: how many people show before \"+N\". */\n maxPeople?: number;\n /** `file`: formats a size in bytes for display. */\n formatSize?: (bytes: number) => string;\n /** Set by `resolveColumn` for a `formula`: the expression the row holds (the editor shows this, not the result). */\n source?: (row: Record<string, unknown>) => unknown;\n /** Set by `resolveColumn` for a `formula`: the error message for a row, or undefined. */\n errorOf?: (row: Record<string, unknown>) => string | undefined;\n};\n\nconst SAFE_SCHEME = /^(https?:|mailto:|tel:)/i;\nconst RELATIVE = /^(\\/(?!\\/)|\\.\\.?\\/|#|\\?)/;\n\n/** An address safe to put in an `href`: http(s), mailto, tel, or a relative one. Anything else (`javascript:`, `data:`) is null. */\nexport function safeHref(href: unknown): string | null {\n if (typeof href !== \"string\") return null;\n const text = href.trim();\n if (!text) return null;\n // Control characters are stripped by browsers when reading a scheme, so they cannot be allowed to hide one.\n // eslint-disable-next-line no-control-regex\n if (/[\\u0000-\\u001F\\u007F]/.test(text)) return null;\n return SAFE_SCHEME.test(text) || RELATIVE.test(text) ? text : null;\n}\n\n/** A link value as `{ href, label?, external? }`; a plain string is the address. */\nexport function linkParts(value: unknown): DataGridLink | null {\n if (value === null || value === undefined || value === \"\") return null;\n if (typeof value === \"string\") return { href: value };\n if (typeof value === \"object\" && typeof (value as DataGridLink).href === \"string\") return value as DataGridLink;\n return null;\n}\n\nexport function linkLabel(value: unknown): string {\n const link = linkParts(value);\n return link ? (link.label ?? link.href) : \"\";\n}\n\n/** A civil date `YYYY-MM-DD` that exists on the calendar. */\nexport function isCivilDate(text: unknown): text is string {\n if (typeof text !== \"string\" || !/^\\d{4}-\\d{2}-\\d{2}$/.test(text)) return false;\n const [y, m, d] = text.split(\"-\").map(Number);\n const date = new Date(Date.UTC(y, m - 1, d));\n return date.getUTCFullYear() === y && date.getUTCMonth() === m - 1 && date.getUTCDate() === d;\n}\n\n/** A civil time `HH:mm` or `HH:mm:ss`, 24-hour. */\nexport function isCivilTime(text: unknown): text is string {\n if (typeof text !== \"string\") return false;\n const match = /^(\\d{2}):(\\d{2})(?::(\\d{2}))?$/.exec(text);\n return !!match && Number(match[1]) < 24 && Number(match[2]) < 60 && (match[3] === undefined || Number(match[3]) < 60);\n}\n\n/** A civil date as a `Date` at UTC midnight, or null. Typed, so an export writes a real spreadsheet date. */\nexport function civilDateToDate(text: unknown): Date | null {\n if (text instanceof Date) return Number.isNaN(text.getTime()) ? null : text;\n return isCivilDate(text) ? new Date(`${text}T00:00:00Z`) : null;\n}\n\nconst isEmpty = (value: unknown) => value === null || value === undefined || value === \"\";\n\nconst OFFSET = /^([+-])(\\d{2}):?(\\d{2})$/;\n\n/** The zone's offset from UTC, in minutes, at an instant. A bare offset (`+01:00`) is its own answer. Null when the zone is unknown. */\nfunction zoneOffsetMinutes(timeZone: string, instantMs: number): number | null {\n const bare = OFFSET.exec(timeZone);\n if (bare) return (bare[1] === \"-\" ? -1 : 1) * (Number(bare[2]) * 60 + Number(bare[3]));\n try {\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n }).formatToParts(new Date(instantMs));\n const n = (type: string) => Number(parts.find((x) => x.type === type)?.value);\n const local = Date.UTC(n(\"year\"), n(\"month\") - 1, n(\"day\"), n(\"hour\") % 24, n(\"minute\"), n(\"second\"));\n return (local - Math.floor(instantMs / 1000) * 1000) / 60000;\n } catch {\n return null;\n }\n}\n\n/** An IANA zone id the platform knows, or a bare offset such as `+01:00`. */\nexport function isValidTimeZone(timeZone: unknown): timeZone is string {\n return typeof timeZone === \"string\" && timeZone !== \"\" && zoneOffsetMinutes(timeZone, 0) !== null;\n}\n\n/** A zoned time: `{ time: \"HH:mm[:ss]\", timeZone }` with a real time and a known zone. */\nexport function isZonedTime(value: unknown): value is DataGridZonedTime {\n return !!value && typeof value === \"object\" && isCivilTime((value as DataGridZonedTime).time) && isValidTimeZone((value as DataGridZonedTime).timeZone);\n}\n\n/**\n * A zoned time as a number for ordering. With a `referenceDate` (ISO, supplied by the consumer: never computed here)\n * it is the UTC minute of that instant, so equal instants compare equal; without one it is the stated local time and\n * the zone is ignored.\n */\nexport function zonedMinutes(value: unknown, referenceDate?: string): number | null {\n if (!isZonedTime(value)) return null;\n const [h, m, sec] = value.time.split(\":\").map(Number);\n const local = h * 60 + m + (sec || 0) / 60;\n if (!referenceDate || !isCivilDate(referenceDate)) return local;\n const [y, mo, d] = referenceDate.split(\"-\").map(Number);\n const guess = Date.UTC(y, mo - 1, d, h, m, sec || 0);\n const offset = zoneOffsetMinutes(value.timeZone, guess);\n if (offset === null) return local;\n return guess / 60000 - offset;\n}\n\n/** A zoned time as the UTC time of day (`HH:mm`) at a reference date. Null without a valid reference date or value. */\nexport function zonedUtcTime(value: unknown, referenceDate?: string): string | null {\n if (!referenceDate || !isCivilDate(referenceDate)) return null;\n const minutes = zonedMinutes(value, referenceDate);\n if (minutes === null) return null;\n const day = ((Math.round(minutes) % 1440) + 1440) % 1440;\n return `${String(Math.floor(day / 60)).padStart(2, \"0\")}:${String(day % 60).padStart(2, \"0\")}`;\n}\n\n/** The zone as text: its short name (`BST`) when there is a locale and a reference date, else the zone id as given. */\nfunction zoneLabel(timeZone: string, locale: string | undefined, referenceDate: string | undefined): string {\n if (!locale || !referenceDate || !isCivilDate(referenceDate) || OFFSET.test(timeZone)) return timeZone;\n try {\n const parts = new Intl.DateTimeFormat(locale, { timeZone, timeZoneName: \"short\" }).formatToParts(new Date(`${referenceDate}T12:00:00Z`));\n return parts.find((x) => x.type === \"timeZoneName\")?.value ?? timeZone;\n } catch {\n return timeZone;\n }\n}\n\n/** The people in a value: one object or an array, each with an id. */\nexport function peopleOf(value: unknown): DataGridPerson[] {\n const list = Array.isArray(value) ? value : isEmpty(value) ? [] : [value];\n return list.filter((p): p is DataGridPerson => !!p && typeof p === \"object\" && typeof (p as DataGridPerson).id === \"string\");\n}\n\n/** A person's text: the name, or the id when there is none (never blank). */\nexport const personName = (person: DataGridPerson): string => (person.name ? person.name : person.id);\n\n/** The files in a value: an array of `{ id, name, … }`. */\nexport function filesOf(value: unknown): DataGridFile[] {\n return (Array.isArray(value) ? value : []).filter((f): f is DataGridFile => !!f && typeof f === \"object\" && typeof (f as DataGridFile).id === \"string\" && typeof (f as DataGridFile).name === \"string\");\n}\n\n/** Reduces related values to one result. An empty set is empty (null), not 0, except `count`. */\nexport function aggregateValues(kind: DataGridAggregate, values: unknown[]): unknown {\n const present = values.filter((v) => !isEmpty(v));\n const numbers = present.filter((v): v is number => typeof v === \"number\" && Number.isFinite(v));\n switch (kind) {\n case \"count\":\n return values.length;\n case \"countUnique\":\n return present.length === 0 ? null : new Set(present.map((v) => (typeof v === \"object\" ? JSON.stringify(v) : String(v)))).size;\n case \"sum\":\n return numbers.length === 0 ? null : numbers.reduce((a, b) => a + b, 0);\n case \"avg\":\n return numbers.length === 0 ? null : numbers.reduce((a, b) => a + b, 0) / numbers.length;\n case \"median\": {\n if (numbers.length === 0) return null;\n const sorted = numbers.slice().sort((a, b) => a - b);\n const mid = sorted.length >> 1;\n return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;\n }\n case \"min\":\n case \"max\": {\n const pool = numbers.length === present.length ? numbers : present.filter((v): v is string => typeof v === \"string\");\n if (pool.length === 0) return null;\n return (pool as (number | string)[]).reduce((a, b) => ((kind === \"min\" ? b < a : b > a) ? b : a));\n }\n case \"range\":\n return numbers.length === 0 ? null : Math.max(...numbers) - Math.min(...numbers);\n case \"percentTrue\": {\n const booleans = values.filter((v): v is boolean => typeof v === \"boolean\");\n return booleans.length === 0 ? null : (booleans.filter(Boolean).length / booleans.length) * 100;\n }\n case \"percentEmpty\":\n return values.length === 0 ? null : ((values.length - present.length) / values.length) * 100;\n }\n}\n\n/** Whether a (parsed) value is unacceptable for the column's type; the grid refuses the edit. Empty is always acceptable. */\nexport function isInvalidForType(column: TypedColumn, value: unknown): boolean {\n if (isEmpty(value)) return false;\n switch (column.type) {\n case \"number\":\n return typeof value !== \"number\" || !Number.isFinite(value);\n case \"link\":\n return safeHref(linkParts(value)?.href) === null;\n case \"date\":\n return !isCivilDate(value);\n case \"time\":\n return !isCivilTime(value);\n case \"time-zone\":\n return !isZonedTime(value);\n case \"select\":\n case \"radio\":\n return !(column.options ?? []).some((o) => o.id === value);\n case \"person\":\n return peopleOf(value).length === 0;\n default:\n return false;\n }\n}\n\nconst optionLabel = (column: TypedColumn, id: unknown): string => {\n const found = (column.options ?? []).find((o) => o.id === id);\n return found ? found.label : isEmpty(id) ? \"\" : String(id);\n};\n\n/** Formats a result by its declared type, so a rollup or formula of dates reads like a date. */\nfunction resultFormatter(column: TypedColumn, locale: string | undefined): (value: unknown) => string {\n const type = column.resultType ?? \"text\";\n if (type === \"number\") {\n const formatter = locale || column.numberFormat ? new Intl.NumberFormat(locale, column.numberFormat) : null;\n return (v) => (typeof v === \"number\" && Number.isFinite(v) ? (formatter ? formatter.format(v) : String(v)) : isEmpty(v) ? \"\" : String(v));\n }\n if (type === \"date\") {\n const formatter = locale || column.dateFormat ? new Intl.DateTimeFormat(locale, { dateStyle: \"medium\", ...column.dateFormat, timeZone: \"UTC\" }) : null;\n return (v) => {\n if (isEmpty(v)) return \"\";\n const date = civilDateToDate(v);\n return date ? (formatter ? formatter.format(date) : date.toISOString().slice(0, 10)) : String(v);\n };\n }\n return (v) => (isEmpty(v) ? \"\" : String(v));\n}\n\n/** Defaults a `type` gives its column. Anything the column sets itself replaces the matching default. */\nfunction typeDefaults(column: TypedColumn, gridLocale: string | undefined): Partial<TypedColumn> {\n const locale = column.locale ?? gridLocale;\n switch (column.type) {\n case \"text\":\n return {\n align: \"start\",\n editor: \"text\",\n ...(locale ? { compare: (a, b) => new Intl.Collator(locale).compare(String(a), String(b)) } : {}),\n };\n case \"number\": {\n const formatter = locale || column.numberFormat ? new Intl.NumberFormat(locale, column.numberFormat) : null;\n return {\n align: \"end\",\n editor: \"number\",\n ...(formatter ? { format: (v) => (typeof v === \"number\" && Number.isFinite(v) ? formatter.format(v) : \"\") } : {}),\n };\n }\n case \"link\":\n return {\n align: \"start\",\n editor: \"link\",\n format: (v) => linkLabel(v),\n filterText: (v) => {\n const link = linkParts(v);\n return link ? `${link.label ?? \"\"} ${link.href}`.trim() : \"\";\n },\n compare: (a, b) => {\n const x = linkLabel(a);\n const y = linkLabel(b);\n return locale ? new Intl.Collator(locale).compare(x, y) : x < y ? -1 : x > y ? 1 : 0;\n },\n exportValue: (row) => linkLabel(column.accessor ? column.accessor(row) : row[column.id]),\n parse: (draft, row) => {\n const previous = linkParts(column.accessor ? column.accessor(row) : row[column.id]);\n const href = draft.trim();\n if (!href) return null;\n return previous && typeof previous === \"object\" && (previous.label !== undefined || previous.external !== undefined)\n ? { ...previous, href }\n : href;\n },\n };\n case \"date\": {\n const formatter = locale || column.dateFormat\n ? new Intl.DateTimeFormat(locale, { dateStyle: \"medium\", ...column.dateFormat, timeZone: \"UTC\" })\n : null;\n return {\n align: \"start\",\n editor: \"date\",\n format: (v) => {\n if (isEmpty(v)) return \"\";\n const date = civilDateToDate(v);\n if (!date) return String(v);\n return formatter ? formatter.format(date) : date.toISOString().slice(0, 10);\n },\n exportValue: (row) => civilDateToDate(column.accessor ? column.accessor(row) : row[column.id]),\n };\n }\n case \"time\": {\n const formatter = locale || column.timeFormat\n ? new Intl.DateTimeFormat(locale, { timeStyle: \"short\", ...column.timeFormat, timeZone: \"UTC\" })\n : null;\n return {\n align: \"start\",\n editor: \"time\",\n format: (v) => {\n if (isEmpty(v)) return \"\";\n if (!isCivilTime(v)) return String(v);\n return formatter ? formatter.format(new Date(`1970-01-01T${v.length === 5 ? `${v}:00` : v}Z`)) : v;\n },\n };\n }\n case \"time-zone\": {\n const formatter = locale || column.timeFormat\n ? new Intl.DateTimeFormat(locale, { timeStyle: \"short\", ...column.timeFormat, timeZone: \"UTC\" })\n : null;\n const text = (v: unknown) => {\n if (isEmpty(v)) return \"\";\n if (!isZonedTime(v)) return String(v);\n const time = formatter ? formatter.format(new Date(`1970-01-01T${v.time.length === 5 ? `${v.time}:00` : v.time}Z`)) : v.time;\n return `${time} ${zoneLabel(v.timeZone, locale, column.referenceDate)}`;\n };\n return {\n align: \"start\",\n editor: \"time-zone\",\n format: text,\n compare: (a, b) => (zonedMinutes(a, column.referenceDate) ?? 0) - (zonedMinutes(b, column.referenceDate) ?? 0),\n exportValue: (row) => {\n const v = column.accessor ? column.accessor(row) : row[column.id];\n return isZonedTime(v) ? `${v.time} ${v.timeZone}` : null;\n },\n };\n }\n case \"person\": {\n const names = (v: unknown) => peopleOf(v).map(personName);\n const collator = locale ? new Intl.Collator(locale) : null;\n const order = (a: string, b: string) => (collator ? collator.compare(a, b) : a < b ? -1 : a > b ? 1 : 0);\n return {\n align: \"start\",\n editor: \"person\",\n format: (v) => names(v).join(\"; \"),\n filterText: (v) => peopleOf(v).map((p) => `${personName(p)} ${p.email ?? \"\"}`.trim()).join(\" \"),\n compare: (a, b) => {\n const x = names(a);\n const y = names(b);\n return order(x[0] ?? \"\", y[0] ?? \"\") || x.length - y.length;\n },\n exportValue: (row) => {\n const value = column.accessor ? column.accessor(row) : row[column.id];\n const parts = column.exportAs === \"email\" ? peopleOf(value).map((p) => p.email ?? \"\") : names(value);\n const joined = parts.join(\"; \");\n return joined.replace(/[;\\s]/g, \"\") === \"\" ? null : joined;\n },\n };\n }\n case \"file\": {\n const names = (v: unknown) => filesOf(v).map((f) => f.name);\n const collator = locale ? new Intl.Collator(locale) : null;\n const order = (a: string, b: string) => (collator ? collator.compare(a, b) : a < b ? -1 : a > b ? 1 : 0);\n return {\n align: \"start\",\n format: (v) => names(v).join(\"; \"),\n filterText: (v) => names(v).join(\" \"),\n compare: (a, b) => {\n const x = names(a);\n const y = names(b);\n return order(x[0] ?? \"\", y[0] ?? \"\") || x.length - y.length;\n },\n exportValue: (row) => {\n const joined = names(column.accessor ? column.accessor(row) : row[column.id]).join(\"; \");\n return joined === \"\" ? null : joined;\n },\n };\n }\n case \"select\":\n case \"radio\": {\n const order = new Map((column.options ?? []).map((o, i) => [o.id, i]));\n return {\n align: \"start\",\n editor: column.type === \"select\" ? \"select\" : \"radio\",\n format: (v) => optionLabel(column, v),\n filterText: (v) => optionLabel(column, v),\n compare:\n column.type === \"radio\" || column.sortBy === \"order\"\n ? (a, b) => (order.get(a as string) ?? Infinity) - (order.get(b as string) ?? Infinity)\n : (a, b) =>\n locale\n ? new Intl.Collator(locale).compare(optionLabel(column, a), optionLabel(column, b))\n : optionLabel(column, a) < optionLabel(column, b)\n ? -1\n : optionLabel(column, a) > optionLabel(column, b)\n ? 1\n : 0,\n exportValue: (row) => {\n const id = column.accessor ? column.accessor(row) : row[column.id];\n return column.exportAs === \"id\" ? (isEmpty(id) ? null : id) : isEmpty(id) ? null : optionLabel(column, id);\n },\n };\n }\n default:\n return {};\n }\n}\n\n/**\n * The column with its type's defaults filled in under its own props. A column with no `type` is returned as is.\n * `rows` is every row: a `formula` hands it to the consumer's engine for references to other rows. A rollup's and a\n * formula's results are computed once per row each time the columns are resolved (`rows` or `columns` changed),\n * never per comparison or keystroke.\n */\nexport function resolveColumn<T extends TypedColumn>(column: T, gridLocale?: string, rows: Record<string, unknown>[] = []): T {\n if (!column.type) return column;\n const defaults = typeDefaults(column, gridLocale) as Record<string, unknown>;\n const own = Object.fromEntries(Object.entries(column).filter(([, v]) => v !== undefined));\n const resolved = { ...defaults, ...own } as TypedColumn;\n const locale = column.locale ?? gridLocale;\n\n if (column.type === \"rollup\") {\n const relation = column.relation ?? (column.accessor ? (row: Record<string, unknown>) => column.accessor!(row) as unknown[] : (row: Record<string, unknown>) => row[column.id] as unknown[]);\n const cache = new WeakMap<object, unknown>();\n const format = resultFormatter(column, locale);\n resolved.accessor = (row: Record<string, unknown>) => {\n if (cache.has(row)) return cache.get(row);\n const related = relation(row);\n const values = Array.isArray(related) ? related : [];\n const result = column.reduce ? column.reduce(values, row) : aggregateValues(column.aggregate ?? \"count\", values);\n cache.set(row, result);\n return result;\n };\n resolved.editable = false;\n resolved.align = column.align ?? (column.resultType === \"number\" ? \"end\" : \"start\");\n if (column.format === undefined) resolved.format = (v: unknown) => format(v);\n if (column.exportValue === undefined) {\n resolved.exportValue = (row: Record<string, unknown>) => {\n const v = resolved.accessor!(row);\n return column.resultType === \"date\" ? civilDateToDate(v) : isEmpty(v) ? null : v;\n };\n }\n } else if (column.type === \"formula\") {\n const source = column.accessor ?? ((row: Record<string, unknown>) => row[column.id]);\n const cache = new WeakMap<object, DataGridFormulaResult>();\n const format = resultFormatter(column, locale);\n const result = (row: Record<string, unknown>): DataGridFormulaResult => {\n let found = cache.get(row);\n if (!found) {\n const expression = source(row);\n if (isEmpty(expression)) found = { value: null };\n else if (typeof column.evaluate !== \"function\") found = { value: expression };\n else {\n try {\n found = column.evaluate(String(expression), { row, rows, columnId: column.id });\n } catch (error) {\n found = { error: error instanceof Error ? error.message : String(error) };\n }\n }\n cache.set(row, found);\n }\n return found;\n };\n const valueOf = (row: Record<string, unknown>) => {\n const r = result(row);\n return \"error\" in r ? null : r.value;\n };\n resolved.source = source;\n resolved.errorOf = (row: Record<string, unknown>) => {\n const r = result(row);\n return \"error\" in r ? r.error : undefined;\n };\n resolved.accessor = valueOf;\n resolved.align = column.align ?? (column.resultType === \"number\" ? \"end\" : \"start\");\n if (column.format === undefined) {\n resolved.format = (v: unknown, row: Record<string, unknown>) => {\n const message = resolved.errorOf!(row);\n return message !== undefined ? message : format(v);\n };\n }\n if (column.exportValue === undefined) {\n resolved.exportValue = (row: Record<string, unknown>) => {\n const message = resolved.errorOf!(row);\n if (message !== undefined) return message;\n const v = valueOf(row);\n return column.resultType === \"date\" ? civilDateToDate(v) : isEmpty(v) ? null : v;\n };\n }\n if (column.filterText === undefined) {\n resolved.filterText = (v: unknown, row: Record<string, unknown>) =>\n resolved.format!(v, row);\n }\n }\n return resolved as unknown as T;\n}\n","// DataGrid (Angular helper). An Angular port of the canonical Svelte data grid; the contract is that\n// package's spec/index.md. Standalone component, OnPush, signals; it composes the headless\n// DataTable family (`lily-data-table`, `thead[lily-data-table-head]`, …) from\n// @lilydesignsystem/angular-headless.\n//\n// Angular idioms: `selected`, `filter`, `sort`, `columnOrder` and `page` are `model()`s (`[(selected)]`);\n// notifications are outputs; the Svelte snippets (`empty`, `footer`, a column's `cell`, `headerCell`,\n// `avatar`, `personEditor`) are `TemplateRef`s. The headless `lily-data-table` root renders a plain\n// `<table>` with no `role`, so the grid sets `role`, `aria-rowcount` and `aria-busy` on that inner table\n// after each render.\n\nimport {\n ChangeDetectionStrategy,\n Component,\n Directive,\n ElementRef,\n Injector,\n TemplateRef,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n untracked,\n viewChild,\n} from \"@angular/core\";\nimport { NgTemplateOutlet } from \"@angular/common\";\nimport {\n DataTable,\n DataTableBody,\n DataTableFoot,\n DataTableHead,\n DataTableRow,\n DataTableTD,\n DataTableTH,\n PaginationNav,\n SearchInput,\n} from \"@lilydesignsystem/angular-headless\";\nimport { copyToClipboard, downloadBlob, exportBlob, exportFilename, toClipboardText, type ExportFormat } from \"./export-data\";\nimport { foldText, searchTerms } from \"./search-text\";\nimport { isRtl, logicalKey } from \"./direction\";\nimport { gridMove } from \"./grid-navigation\";\nimport { missingLabels, type LabelFeatures } from \"./label-coverage\";\nimport { EMPTY_HISTORY, historyKey, recordEdit, redoEdit, undoEdit, type EditHistory } from \"./edit-history\";\nimport { findTypeaheadMatch, isTypeaheadKey, nextTypeaheadState, type TypeaheadState } from \"./typeahead\";\nimport {\n filesOf,\n isInvalidForType,\n isZonedTime,\n linkParts,\n peopleOf,\n personName,\n resolveColumn,\n safeHref,\n zonedUtcTime,\n type DataGridCellType,\n type DataGridFile,\n type DataGridLink,\n type DataGridOption,\n type DataGridPerson,\n} from \"./cell-types\";\n\n/** A missing value: `null`, `undefined` or an empty string. */\nconst isMissing = (value: unknown): boolean => value === null || value === undefined || value === \"\";\n\nexport type DataGridSortDirection = \"ascending\" | \"descending\" | \"none\";\n\nexport type DataGridSort = { columnId: string; direction: DataGridSortDirection };\n\nexport type DataGridSelectionMode = \"none\" | \"single\" | \"multiple\";\n\nexport type DataGridRow = Record<string, unknown>;\n\n/** What `exportHandler` and the `exportFile` output receive, before the file is saved. */\nexport type DataGridExport = {\n format: ExportFormat;\n /** The file name, with its extension. */\n filename: string;\n /** How many data rows (the header is not counted). */\n rowCount: number;\n /** The file. */\n blob: Blob;\n};\n\n/** What a column's `cell` template receives (as `$implicit`). */\nexport type DataGridCellContext = {\n value: unknown;\n formatted: string;\n row: DataGridRow;\n column: DataGridColumn;\n};\n\n/** What the `cellEdit` output carries after a cell edit is committed. */\nexport type DataGridCellEdit = {\n rowId: string;\n row: DataGridRow;\n columnId: string;\n /** The parsed new value (a number for the `\"number\"` editor, the text otherwise). */\n value: unknown;\n /** The cell's value before the edit. */\n previous: unknown;\n};\n\n/** What a person editor template receives (as `$implicit`). */\nexport type DataGridPersonEditorContext = { value: unknown; commit: (value: unknown) => void; cancel: () => void };\n\nexport type DataGridColumn = {\n /** Stable column identifier; also the default property read from each row. */\n id: string;\n /** Accessible + visible column header text. */\n header: string;\n /** Reads this column's raw value from a row. Defaults to `row[id]`. */\n accessor?: (row: DataGridRow) => unknown;\n /** Formats a raw value for display. Defaults to `String(value)` (`\"\"` for null/undefined). */\n format?: (value: unknown, row: DataGridRow) => string;\n /** Column participates in sorting. */\n sortable?: boolean;\n /** Orders two raw values when sorting. `null`/`undefined` always sort last, before `compare` is called. */\n compare?: (a: unknown, b: unknown) => number;\n /** Column participates in the text filter. Default true. */\n filterable?: boolean;\n /** Column can be resized (pointer + keyboard). */\n resizable?: boolean;\n /** Column can be reordered: Alt+ArrowLeft/Right on its focused header, or dragging the header onto another. */\n movable?: boolean;\n /** Pins the column: its header and cells get `data-pinned=\"start\"` / `\"end\"` for the consumer's sticky CSS. */\n pinned?: \"start\" | \"end\";\n /** Set `false` to leave the column out of an export. Default true. */\n exportable?: boolean;\n /** The value this column exports for a row. */\n exportValue?: (row: DataGridRow) => unknown;\n /** Column can be hidden via the column-visibility control. */\n hidable?: boolean;\n /** Initial pixel width, meaningful only when `resizable`. */\n width?: number;\n /** Custom cell content: a template receiving the cell context as `$implicit`. */\n cell?: TemplateRef<{ $implicit: DataGridCellContext }>;\n /** The header's content in place of the `header` text. `header` stays the accessible name. */\n headerCell?: TemplateRef<{ $implicit: DataGridColumn }>;\n /** Cells can be edited in place: F2 or Enter on a focused cell, a double click, or the button `labels.editCell` gates. */\n editable?: boolean;\n /** The editor's control. Default `\"text\"`; a `type` sets its own. */\n editor?: \"text\" | \"number\" | \"link\" | \"date\" | \"time\" | \"time-zone\" | \"select\" | \"radio\" | \"person\" | \"formula\";\n /** The kind of value in this column: a bundle of defaults for `format`, `compare`, `filterText`, `exportValue`, `align` and `editor`. */\n type?: DataGridCellType;\n /** BCP 47 locale for this column's formatting and collation. */\n /** Shown instead of nothing when this column's value is missing (`null`, `undefined` or `\"\"`). Overrides the grid's `emptyValue`. A missing value always carries `data-empty` on its cell. */\n emptyValue?: string;\n locale?: string;\n /** `select` and `radio`: the choices. */\n options?: DataGridOption[];\n /** `time-zone`: the zones the editor's select offers. */\n timeZones?: DataGridOption[];\n /** `time-zone`: the date (ISO) that orders zoned times and names a zone. Never computed by the grid. */\n referenceDate?: string;\n /** `time-zone`: an export adds a second column holding the UTC time of day at `referenceDate`. */\n exportUtc?: boolean;\n /** `rollup`: how the related values are reduced. */\n aggregate?: \"count\" | \"countUnique\" | \"sum\" | \"avg\" | \"median\" | \"min\" | \"max\" | \"range\" | \"percentTrue\" | \"percentEmpty\";\n /** `rollup`: a reduction the named aggregates do not cover. */\n reduce?: (values: unknown[], row: DataGridRow) => unknown;\n /** `rollup`: reads the related values. */\n relation?: (row: DataGridRow) => unknown[];\n /** `rollup` and `formula`: the result's type. */\n resultType?: \"number\" | \"date\" | \"text\";\n /** `formula`: evaluates an expression. Lily ships no engine and never evaluates a string itself. */\n evaluate?: (expression: string, context: { row: DataGridRow; rows: DataGridRow[]; columnId: string }) => { value: unknown } | { error: string };\n /** `person`: how many people show before \"+N\". */\n maxPeople?: number;\n /** `person`: an avatar beside the name. Decorative. */\n avatar?: TemplateRef<{ $implicit: DataGridPerson }>;\n /** `person`: the editor template (`$implicit`: `{ value, commit, cancel }`). Without it a person cell is read-only. */\n personEditor?: TemplateRef<{ $implicit: DataGridPersonEditorContext }>;\n /** `file`: formats a size in bytes. */\n formatSize?: (bytes: number) => string;\n /** `file`: the `accept` of the file input. */\n accept?: string;\n /** `file`: whether the input takes several files. Default true. */\n multiple?: boolean;\n /** `select`: sort by option label (default) or by option order. */\n sortBy?: \"label\" | \"order\";\n /** `select`/`radio`: export the option's `\"label\"` or `\"id\"`. `person`: `\"email\"`. */\n exportAs?: \"label\" | \"id\" | \"email\";\n /** `number`: options for `Intl.NumberFormat`. */\n numberFormat?: Intl.NumberFormatOptions;\n /** `date`: options for `Intl.DateTimeFormat`. */\n dateFormat?: Intl.DateTimeFormatOptions;\n /** `time`: options for `Intl.DateTimeFormat`. */\n timeFormat?: Intl.DateTimeFormatOptions;\n /** The text the grid's filter matches for a value. */\n filterText?: (value: unknown, row: DataGridRow) => string;\n /** Turns the editor's text into the committed value. */\n parse?: (draft: string, row: DataGridRow) => unknown;\n /** Refuses a value: return a message and the cell stays in edit mode with `aria-invalid`. */\n validate?: (value: unknown, row: DataGridRow) => string | undefined;\n /** Set for a `formula` column: reads the expression a row holds. */\n source?: (row: DataGridRow) => unknown;\n /** Set for a `formula` column: the error message for a row, if any. */\n errorOf?: (row: DataGridRow) => string | undefined;\n /** Body cells of this column are `<th scope=\"row\" role=\"rowheader\">`. */\n rowHeader?: boolean;\n /** Horizontal alignment of the column's cells. */\n align?: \"start\" | \"center\" | \"end\";\n /** Extra class on each body cell of this column. */\n cellClass?: string | ((ctx: DataGridCellContext) => string);\n /** Extra attributes on each body cell of this column. */\n cellAttrs?: (ctx: DataGridCellContext) => Record<string, string>;\n};\n\n/**\n * Every field is optional, but its presence gates the control it names — no baked-in English fallback.\n * See the Svelte canonical's spec/index.md §5.\n */\nexport type DataGridLabels = {\n search?: string;\n /** Accessible name of the select that limits the search to one column. Gates the select (needs `searchAllFields` too). */\n searchField?: string;\n /** The select's first option: search every column. */\n searchAllFields?: string;\n /** Accessible name of the pager. When given, the pager is a labelled `<nav>` landmark (the headless `PaginationNav`); without it the pager is a plain `<div>`. */\n pagination?: string;\n /** Visible text of the copy button, which puts the export (header row first, tab-separated) on the clipboard for pasting into a spreadsheet. Gates the button. */\n copy?: string;\n /** Announced after a copy: (how many rows). */\n copyAnnouncement?: (rowCount: number) => string;\n /** Announced when the clipboard could not be written. */\n copyFailed?: string;\n /** Announced after Ctrl/Cmd+Z puts an earlier value back: (column header, the restored text). */\n undoAnnouncement?: (header: string, text: string) => string;\n /** Announced after Ctrl/Cmd+Shift+Z (or Ctrl+Y) re-applies an edit: (column header, the text). */\n redoAnnouncement?: (header: string, text: string) => string;\n columnVisibility?: string;\n columnVisibilityOption?: (header: string) => string;\n resizeHandle?: (header: string) => string;\n selectAll?: string;\n selectionColumn?: string;\n selectRow?: (rowLabel: string) => string;\n previousPage?: string;\n nextPage?: string;\n pageStatus?: (page: number, pageCount: number, rowCount: number) => string;\n pageAnnouncement?: (page: number, pageCount: number) => string;\n sortAnnouncement?: (header: string, direction: DataGridSortDirection) => string;\n filterAnnouncement?: (matchCount: number, totalCount: number) => string;\n selectionAnnouncement?: (selectedCount: number) => string;\n columnMoveAnnouncement?: (header: string, position: number, count: number) => string;\n editCell?: (header: string, rowLabel: string) => string;\n cellEditor?: (header: string) => string;\n editAnnouncement?: (header: string, value: string) => string;\n export?: string;\n exportCsv?: string;\n exportTsv?: string;\n exportExcel?: string;\n exportAnnouncement?: (format: ExportFormat, rowCount: number, filename: string) => string;\n invalidValue?: (header: string, type: string) => string;\n opensInNewTab?: (text: string) => string;\n radioGroup?: (header: string, rowLabel: string) => string;\n timeZone?: (header: string) => string;\n exportUtcHeader?: (header: string) => string;\n morePeople?: (count: number) => string;\n removeFile?: (name: string) => string;\n fileInput?: (header: string, rowLabel: string) => string;\n formulaEditor?: (header: string) => string;\n rollupDescription?: (header: string) => string;\n editCancelAnnouncement?: (header: string) => string;\n editError?: (header: string, message: string) => string;\n};\n\n/** What a footer template receives (as `$implicit`). */\nexport type DataGridFooterContext = { columns: DataGridColumn[]; rows: DataGridRow[] };\n\nexport type DataGridEntry = { row: DataGridRow; id: string };\n\ntype Editing = { rowId: string; columnId: string; draft: string; zone?: string; error?: string; invalid?: boolean };\n\ntype RenderItem = { kind: \"row\"; index: number } | { kind: \"spacer\"; rows: number; key: string };\n\n/** What counts as a widget inside a cell: something a person can operate. */\nconst WIDGET_SELECTOR = 'a[href], button, input, select, textarea, summary, [contenteditable=\"true\"]';\n\nconst MIN_COLUMN_WIDTH = 40;\nconst RESIZE_STEP = 16;\n\nlet uid = 0;\n/** Stable per-instance id prefix; SSR-safe (no Math.random / Date.now). */\nexport function nextDataGridId(): string {\n uid += 1;\n return `data-grid-${uid}`;\n}\n\n/** Default cell value reader: `row[column.id]`. */\nfunction defaultAccessor(column: DataGridColumn, row: DataGridRow): unknown {\n return column.accessor ? column.accessor(row) : row[column.id];\n}\n\n/** Default cell formatter: `String(value)`, `\"\"` for null/undefined. */\nfunction formatCell(column: DataGridColumn, row: DataGridRow): string {\n const value = defaultAccessor(column, row);\n if (column.format) return column.format(value, row);\n return value === null || value === undefined ? \"\" : String(value);\n}\n\n/** Sets a record of attributes on its host element (Angular cannot spread a dictionary in a template). */\n@Directive({ selector: \"[lilyDataGridAttrs]\", standalone: true })\nexport class DataGridAttrs {\n readonly lilyDataGridAttrs = input<Record<string, string> | undefined>(undefined);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private applied: string[] = [];\n\n constructor() {\n effect(() => {\n const next = this.lilyDataGridAttrs() ?? {};\n for (const name of this.applied) if (!(name in next)) this.host.nativeElement.removeAttribute(name);\n for (const [name, value] of Object.entries(next)) this.host.nativeElement.setAttribute(name, value);\n this.applied = Object.keys(next);\n });\n }\n}\n\n@Component({\n selector: \"lily-data-grid\",\n standalone: true,\n imports: [NgTemplateOutlet, DataGridAttrs, DataTable, DataTableBody, DataTableFoot, DataTableHead, DataTableRow, DataTableTD, DataTableTH, PaginationNav, SearchInput],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div #rootEl class=\"data-grid {{ className() }}\">\n @if (labels().search || hidableColumns().length > 0 || hasExportButtons()) {\n <div class=\"data-grid-toolbar\">\n @if (labels().search && labels().searchField && labels().searchAllFields) {\n <select class=\"data-grid-search-field\" [attr.aria-label]=\"labels().searchField\" [value]=\"filterField()\" (change)=\"onFilterFieldChange($event)\">\n <option value=\"\">{{ labels().searchAllFields }}</option>\n @for (c of filterableColumns(); track c.id) {\n <option [value]=\"c.id\">{{ c.header }}</option>\n }\n </select>\n }\n @if (labels().search; as searchLabel) {\n <lily-search-input className=\"data-grid-search\" [label]=\"searchLabel\" [value]=\"filter()\" (valueChange)=\"setFilter($event)\" (keydown)=\"onFilterKeydown($event)\" />\n }\n @if (hasExportButtons()) {\n <div class=\"data-grid-export\" role=\"group\" [attr.aria-label]=\"labels().export ?? null\">\n @if (labels().copy; as copy) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"copy\" [disabled]=\"exportEntries().length === 0\" (click)=\"runCopy()\">{{ copy }}</button>\n }\n @if (labels().exportCsv; as csv) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"csv\" [disabled]=\"exportEntries().length === 0\" (click)=\"runExport('csv')\">{{ csv }}</button>\n }\n @if (labels().exportTsv; as tsv) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"tsv\" [disabled]=\"exportEntries().length === 0\" (click)=\"runExport('tsv')\">{{ tsv }}</button>\n }\n @if (labels().exportExcel; as excel) {\n <button type=\"button\" class=\"data-grid-export-button\" data-grid-export-format=\"xlsx\" [disabled]=\"exportEntries().length === 0\" (click)=\"runExport('xlsx')\">{{ excel }}</button>\n }\n </div>\n }\n @if (hidableColumns().length > 0 && labels().columnVisibility; as visibilityLabel) {\n <fieldset class=\"data-grid-column-visibility\">\n <legend>{{ visibilityLabel }}</legend>\n @for (column of hidableColumns(); track column.id) {\n <label>\n <input type=\"checkbox\" [checked]=\"!hiddenColumnIds().has(column.id)\" (change)=\"toggleColumnVisibility(column.id)\" />\n {{ labels().columnVisibilityOption?.(column.header) ?? column.header }}\n </label>\n }\n </fieldset>\n }\n </div>\n }\n\n @if (scroll()) {\n <!-- A scrollable region must be reachable by keyboard (WCAG 2.1.1); in grid mode a roving cell is already a tab stop. -->\n <div\n #scrollEl\n class=\"data-grid-scroll\"\n role=\"region\"\n [attr.aria-label]=\"label()\"\n [attr.tabindex]=\"isGrid() ? null : 0\"\n [attr.style]=\"scrollStyle()\"\n (scroll)=\"onScroll($event)\"\n >\n <ng-container *ngTemplateOutlet=\"tableTemplate\" />\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"tableTemplate\" />\n }\n\n @if (pageSize()) {\n @if (labels().pagination; as pagination) {\n <lily-pagination-nav className=\"data-grid-pagination\" [label]=\"pagination\">\n <ng-container *ngTemplateOutlet=\"pager\" />\n </lily-pagination-nav>\n } @else {\n <div class=\"data-grid-pagination\">\n <ng-container *ngTemplateOutlet=\"pager\" />\n </div>\n }\n }\n\n <p class=\"data-grid-status\" aria-live=\"polite\">{{ statusMessage() }}</p>\n </div>\n\n <ng-template #pager>\n <button type=\"button\" class=\"data-grid-page-previous\" [disabled]=\"clampedPage() <= 1\" (click)=\"goToPage(clampedPage() - 1)\">{{ labels().previousPage }}</button>\n <span class=\"data-grid-page-status\">{{ labels().pageStatus?.(clampedPage(), pageCount(), sortedEntries().length) }}</span>\n <button type=\"button\" class=\"data-grid-page-next\" [disabled]=\"clampedPage() >= pageCount()\" (click)=\"goToPage(clampedPage() + 1)\">{{ labels().nextPage }}</button>\n </ng-template>\n\n <ng-template #tableTemplate>\n <lily-data-table\n [label]=\"label()\"\n [className]=\"''\"\n (keydown)=\"onGridKeydown($event)\"\n (focusin)=\"onGridFocusin($event)\"\n (focusout)=\"onGridFocusout($event)\"\n (click)=\"onGridClick($event)\"\n (dblclick)=\"onGridDblclick($event)\"\n >\n @if (caption()) {\n <caption>{{ caption() }}</caption>\n }\n <thead lily-data-table-head>\n <tr lily-data-table-row [attr.aria-rowindex]=\"indexed() ? 1 : null\">\n @if (hasSelection()) {\n <th\n lily-data-table-th\n data-row=\"-1\"\n data-col=\"0\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === -1 && activeCol() === 0 ? 0 : -1) : null\"\n >\n @if (selectionMode() === 'multiple') {\n <input\n type=\"checkbox\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"labels().selectAll ?? null\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (click)=\"toggleSelectAll()\"\n />\n } @else {\n <span class=\"data-grid-selection-header-label\">{{ labels().selectionColumn }}</span>\n }\n </th>\n }\n @for (column of visibleColumns(); track column.id; let i = $index) {\n <th\n lily-data-table-th\n data-row=\"-1\"\n [attr.data-col]=\"colOffset() + i\"\n [attr.data-align]=\"column.align ?? null\"\n [attr.data-cell-type]=\"column.type ?? null\"\n [attr.data-pinned]=\"column.pinned ?? null\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === -1 && activeCol() === colOffset() + i ? 0 : -1) : null\"\n [attr.aria-sort]=\"ariaSortFor(column)\"\n [attr.data-sort-order]=\"sortOrderFor(column)\"\n [attr.aria-describedby]=\"column.type === 'rollup' && labels().rollupDescription ? gridId + '-' + column.id + '-description' : null\"\n [attr.style]=\"cellStyle(column)\"\n [attr.draggable]=\"isMovable(column) ? 'true' : null\"\n (dragstart)=\"onHeaderDragStart(column, $event)\"\n (dragover)=\"onHeaderDragOver($event)\"\n (drop)=\"onHeaderDrop(column.id, $event)\"\n >\n @if (column.sortable) {\n <button type=\"button\" class=\"data-grid-sort-button\" data-grid-own [attr.tabindex]=\"isGrid() ? -1 : null\" (click)=\"toggleSort(column, $any($event).shiftKey)\">\n @if (column.headerCell; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: column }\" />\n } @else {<ng-container>{{ column.header }}</ng-container>}\n </button>\n } @else if (column.headerCell; as headerTemplate) {\n <ng-container *ngTemplateOutlet=\"headerTemplate; context: { $implicit: column }\" />\n } @else {<ng-container>{{ column.header }}</ng-container>}\n @if (column.type === 'rollup' && labels().rollupDescription; as describe) {\n <span class=\"data-grid-visually-hidden\" [id]=\"gridId + '-' + column.id + '-description'\">{{ describe(column.header) }}</span>\n }\n @if (column.resizable) {\n <!-- WAI-ARIA \"window splitter\" pattern: role=\"separator\" plus tabindex/aria-valuenow is how a resize handle becomes focusable and operable. -->\n <span\n class=\"data-grid-resize-handle\"\n role=\"separator\"\n data-grid-own\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"labels().resizeHandle?.(column.header) ?? null\"\n [attr.aria-valuenow]=\"widthFor(column) ?? 120\"\n [attr.aria-valuemin]=\"minColumnWidth\"\n tabindex=\"0\"\n (keydown)=\"onResizeKeydown(column, $event)\"\n (pointerdown)=\"onResizePointerDown(column, $event)\"\n ></span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody lily-data-table-body>\n @for (item of renderItems(); track item.kind === 'row' ? pageEntries()[item.index].id : item.key) {\n @if (item.kind === 'spacer') {\n <tr class=\"data-grid-spacer\" aria-hidden=\"true\" [attr.style]=\"'height:' + item.rows * (virtualize()?.rowHeight ?? 0) + 'px'\">\n <td [attr.colspan]=\"lastCol() + 1\"></td>\n </tr>\n } @else {\n @let entry = pageEntries()[item.index];\n <tr\n lily-data-table-row\n [className]=\"rowClass()?.(entry.row) ?? ''\"\n [attr.aria-selected]=\"hasSelection() ? isSelected(entry.id) : null\"\n [attr.aria-rowindex]=\"indexed() ? pageStart() + item.index + 2 : null\"\n [lilyDataGridAttrs]=\"rowAttrs()?.(entry.row)\"\n >\n @if (hasSelection()) {\n <td\n lily-data-table-td\n [attr.role]=\"isGrid() ? 'gridcell' : 'cell'\"\n [attr.data-row]=\"item.index\"\n data-col=\"0\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === item.index && activeCol() === 0 ? 0 : -1) : null\"\n >\n <input\n [type]=\"selectionMode() === 'single' ? 'radio' : 'checkbox'\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"labels().selectRow?.(rowLabelOf(entry)) ?? null\"\n [checked]=\"isSelected(entry.id)\"\n (click)=\"onRowSelectClick(pageStart() + item.index, $event)\"\n />\n </td>\n }\n @for (column of visibleColumns(); track column.id; let colIndex = $index) {\n @let ctx = cellFor(column, entry.row);\n @if (column.rowHeader) {\n <th\n lily-data-table-th\n scope=\"row\"\n role=\"rowheader\"\n [className]=\"cellClassOf(column, ctx)\"\n [attr.data-row]=\"item.index\"\n [attr.data-col]=\"colOffset() + colIndex\"\n [attr.data-align]=\"column.align ?? null\"\n [attr.data-cell-type]=\"column.type ?? null\"\n [attr.data-pinned]=\"column.pinned ?? null\"\n [attr.data-error]=\"column.errorOf?.(entry.row) !== undefined ? '' : null\"\n [attr.data-empty]=\"isMissing(ctx.value) ? '' : null\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === item.index && activeCol() === colOffset() + colIndex ? 0 : -1) : null\"\n [attr.style]=\"cellStyle(column)\"\n [lilyDataGridAttrs]=\"column.cellAttrs?.(ctx)\"\n >\n <ng-container *ngTemplateOutlet=\"cellBody; context: { entry: entry, column: column, ctx: ctx }\" />\n </th>\n } @else {\n <td\n lily-data-table-td\n [className]=\"cellClassOf(column, ctx)\"\n [attr.role]=\"isGrid() ? 'gridcell' : 'cell'\"\n [attr.data-row]=\"item.index\"\n [attr.data-col]=\"colOffset() + colIndex\"\n [attr.data-align]=\"column.align ?? null\"\n [attr.data-cell-type]=\"column.type ?? null\"\n [attr.data-pinned]=\"column.pinned ?? null\"\n [attr.data-editable]=\"isEditable(column) ? '' : null\"\n [attr.data-readonly]=\"column.type === 'rollup' ? '' : null\"\n [attr.aria-readonly]=\"column.type === 'rollup' ? 'true' : null\"\n [attr.data-error]=\"column.errorOf?.(entry.row) !== undefined ? '' : null\"\n [attr.data-empty]=\"isMissing(ctx.value) ? '' : null\"\n [attr.data-editing]=\"isEditingCell(entry, column) ? '' : null\"\n [attr.tabindex]=\"isGrid() ? (activeRow() === item.index && activeCol() === colOffset() + colIndex ? 0 : -1) : null\"\n [attr.style]=\"cellStyle(column)\"\n [lilyDataGridAttrs]=\"column.cellAttrs?.(ctx)\"\n (dragover)=\"onFileDragOver(column, $event)\"\n (drop)=\"onFileDrop(entry, column, $event)\"\n >\n <ng-container *ngTemplateOutlet=\"cellBody; context: { entry: entry, column: column, ctx: ctx }\" />\n </td>\n }\n }\n </tr>\n }\n }\n @if (pageEntries().length === 0 && empty(); as emptyTemplate) {\n <tr lily-data-table-row className=\"data-grid-empty-row\">\n <td lily-data-table-td className=\"data-grid-empty\" [attr.colspan]=\"lastCol() + 1\" [attr.role]=\"isGrid() ? 'gridcell' : 'cell'\">\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </td>\n </tr>\n }\n </tbody>\n @if (footer(); as footerTemplate) {\n <tfoot lily-data-table-foot>\n <ng-container *ngTemplateOutlet=\"footerTemplate; context: { $implicit: footerContext() }\" />\n </tfoot>\n }\n </lily-data-table>\n </ng-template>\n\n <ng-template #cellBody let-entry=\"entry\" let-column=\"column\" let-ctx=\"ctx\">\n @if (isEditingCell(entry, column)) {\n @let editing = editingState()!;\n @if (column.editor === 'person' && column.personEditor) {\n <ng-container *ngTemplateOutlet=\"column.personEditor; context: { $implicit: personEditorContext(entry, column, ctx) }\" />\n } @else if (column.editor === 'time-zone') {\n <span\n class=\"data-grid-zoned-editor\"\n role=\"group\"\n [attr.aria-label]=\"labels().cellEditor?.(column.header) ?? column.header\"\n (focusout)=\"onZonedFocusout($event)\"\n >\n <input\n class=\"data-grid-cell-editor\"\n type=\"time\"\n step=\"1\"\n [attr.aria-label]=\"labels().cellEditor?.(column.header) ?? column.header\"\n [attr.aria-invalid]=\"editing.error || editing.invalid ? 'true' : null\"\n [attr.aria-describedby]=\"editing.error ? entry.id + '-' + column.id + '-error' : null\"\n [value]=\"editing.draft\"\n (input)=\"setDraft($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n />\n <select\n class=\"data-grid-cell-editor data-grid-zone-editor\"\n [attr.aria-label]=\"labels().timeZone?.(column.header) ?? column.header\"\n (change)=\"setZone($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n >\n @for (option of column.timeZones ?? []; track option.id) {\n <option [value]=\"option.id\" [selected]=\"option.id === editing.zone\">{{ option.label }}</option>\n }\n </select>\n </span>\n } @else if (column.editor === 'select') {\n <select\n class=\"data-grid-cell-editor\"\n [attr.aria-label]=\"labels().cellEditor?.(column.header) ?? column.header\"\n [attr.aria-invalid]=\"editing.error || editing.invalid ? 'true' : null\"\n [attr.aria-describedby]=\"editing.error ? entry.id + '-' + column.id + '-error' : null\"\n (change)=\"setDraft($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n (blur)=\"onEditorBlur()\"\n >\n <option value=\"\" [selected]=\"editing.draft === ''\"></option>\n @for (option of ungroupedOptions(column); track option.id) {\n <option [value]=\"option.id\" [disabled]=\"option.disabled ?? false\" [selected]=\"option.id === editing.draft\">{{ option.label }}</option>\n }\n @for (group of groupsOf(column); track group) {\n <optgroup [label]=\"group\">\n @for (option of optionsInGroup(column, group); track option.id) {\n <option [value]=\"option.id\" [disabled]=\"option.disabled ?? false\" [selected]=\"option.id === editing.draft\">{{ option.label }}</option>\n }\n </optgroup>\n }\n </select>\n } @else {\n <input\n class=\"data-grid-cell-editor\"\n [type]=\"column.editor === 'number' ? 'number' : column.editor === 'date' ? 'date' : column.editor === 'time' ? 'time' : 'text'\"\n [attr.step]=\"column.editor === 'time' ? 1 : null\"\n [attr.inputmode]=\"column.editor === 'number' ? 'decimal' : null\"\n [attr.aria-label]=\"(column.type === 'formula' ? labels().formulaEditor?.(column.header) : undefined) ?? labels().cellEditor?.(column.header) ?? column.header\"\n [attr.aria-invalid]=\"editing.error || editing.invalid ? 'true' : null\"\n [attr.aria-describedby]=\"editing.error ? entry.id + '-' + column.id + '-error' : null\"\n [value]=\"editing.draft\"\n (input)=\"setDraft($event)\"\n (keydown)=\"onEditorKeydown($event)\"\n (blur)=\"onEditorBlur()\"\n />\n }\n @if (editing.error) {\n <span class=\"data-grid-cell-error\" [id]=\"entry.id + '-' + column.id + '-error'\">{{ editing.error }}</span>\n }\n } @else if (column.type === 'radio' && column.editable) {\n <fieldset class=\"data-grid-radio-group\" data-grid-own-group>\n <legend class=\"data-grid-radio-legend\">{{ labels().radioGroup?.(column.header, rowLabelOf(entry)) ?? column.header }}</legend>\n @for (option of column.options ?? []; track option.id) {\n <label class=\"data-grid-radio-option\">\n <input\n type=\"radio\"\n [name]=\"gridId + '-' + entry.id + '-' + column.id\"\n [value]=\"option.id\"\n [checked]=\"ctx.value === option.id\"\n [disabled]=\"option.disabled ?? false\"\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n (change)=\"commitValue(entry, column, option.id)\"\n />{{ option.label }}</label>\n }\n </fieldset>\n } @else {\n @if (column.cell; as cellTemplate) {\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: ctx }\" />\n } @else if (isMissing(ctx.value) && (column.emptyValue ?? emptyValue())) {\n <ng-container>{{ column.emptyValue ?? emptyValue() }}</ng-container>\n } @else if (column.type === 'person') {\n @let people = peopleIn(ctx.value);\n @if (people.length > 0) {\n @let shown = shownPeople(column, ctx.value);\n <ul class=\"data-grid-people\">\n @for (person of shown; track person.id) {\n <li class=\"data-grid-person\">\n @if (column.avatar; as avatarTemplate) {\n <span class=\"data-grid-avatar\" aria-hidden=\"true\"><ng-container *ngTemplateOutlet=\"avatarTemplate; context: { $implicit: person }\" /></span>\n }\n <span class=\"data-grid-person-name\">{{ nameOf(person) }}</span>\n </li>\n }\n @if (shown.length < people.length && labels().morePeople; as more) {\n <li class=\"data-grid-people-more\">{{ more(people.length - shown.length) }}</li>\n }\n </ul>\n }\n } @else if (column.type === 'file') {\n @let files = filesIn(ctx.value);\n @if (files.length > 0) {\n <ul class=\"data-grid-files\">\n @for (file of files; track file.id) {\n <li class=\"data-grid-file\">\n @if (hrefOf(file.href); as fileHref) {\n <a class=\"data-grid-link\" [href]=\"fileHref\">{{ file.name }}</a>\n } @else {\n <span class=\"data-grid-file-name\">{{ file.name }}</span>\n }\n @if (file.size !== undefined && column.formatSize; as sizeText) {\n {{ ' ' }}<span class=\"data-grid-file-size\">{{ column.formatSize(file.size) }}</span>\n }\n @if (column.editable && labels().removeFile; as removeLabel) {\n <button\n type=\"button\"\n class=\"data-grid-file-remove\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"removeLabel(file.name)\"\n (click)=\"fileRemove.emit({ rowId: entry.id, row: entry.row, columnId: column.id, fileId: file.id })\"\n ></button>\n }\n </li>\n }\n </ul>\n }\n @if (column.editable) {\n <input\n type=\"file\"\n class=\"data-grid-file-input\"\n [attr.aria-label]=\"labels().fileInput?.(column.header, rowLabelOf(entry)) ?? column.header\"\n [multiple]=\"column.multiple !== false\"\n [attr.accept]=\"column.accept ?? null\"\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n (change)=\"onFileInput(entry, column, $event)\"\n />\n }\n } @else if (column.type === 'link') {\n @let link = linkIn(ctx.value);\n @if (link) {\n @if (hrefOf(link.href); as href) {\n <a class=\"data-grid-link\" [href]=\"href\" [attr.target]=\"link.external ? '_blank' : null\" [attr.rel]=\"link.external ? 'noopener noreferrer' : null\">{{ link.label ?? link.href }}@if (link.external && labels().opensInNewTab; as newTab) {{{ ' ' }}<span class=\"data-grid-visually-hidden\">{{ newTab(link.label ?? link.href) }}</span>}</a>\n } @else {\n <!-- An address with an unsafe scheme is shown as text, never as a link. -->\n <span class=\"data-grid-link data-grid-link-unsafe\">{{ link.label ?? link.href }}</span>\n }\n }\n } @else if (column.type === 'date' || column.type === 'time') {\n @if (ctx.formatted !== '') {\n <time [attr.datetime]=\"stringOf(ctx.value)\">{{ ctx.formatted }}</time>\n }\n } @else {<ng-container>{{ ctx.formatted }}</ng-container>}\n @if (isEditable(column) && column.type !== 'radio' && labels().editCell; as editLabel) {\n <button\n type=\"button\"\n class=\"data-grid-edit-button\"\n data-grid-own\n [attr.tabindex]=\"isGrid() ? -1 : null\"\n [attr.aria-label]=\"editLabel(column.header, rowLabelOf(entry))\"\n (click)=\"startEdit(entry, column)\"\n ></button>\n }\n }\n </ng-template>\n `,\n})\nexport class DataGrid {\n // ---- Inputs ----\n\n /** Accessible name for the grid, passed through to DataTable. */\n readonly label = input.required<string>();\n /** Optional visible caption. */\n readonly caption = input<string | undefined>(undefined);\n /** Column definitions. */\n readonly columns = input.required<DataGridColumn[]>();\n /** Row data. */\n readonly rows = input.required<DataGridRow[]>();\n /** BCP 47 locale for the typed columns' formatting and collation. Never defaulted: with none, values show as stored. */\n readonly locale = input<string | undefined>(undefined);\n /** What a cell shows when its value is missing (`null`, `undefined` or `\"\"`), for example `\"—\"`. A column's own `emptyValue` wins. No default: Lily ships no text. The cell always carries `data-empty`, and an export is unaffected. */\n readonly emptyValue = input<string | undefined>(undefined);\n /** In development, log (once per grid) the labels the grid's features call for but `labels` leaves out. Default `true`; it never logs in production. */\n readonly warnMissingLabels = input<boolean>(true);\n /** Where missing values sort: `\"last\"` (default, in both directions) or `\"first\"`. */\n readonly nulls = input<\"first\" | \"last\">(\"last\");\n /** Make every column movable (Alt+Arrow on its header, or drag it) unless its own `movable` is `false`. Default `false`. */\n readonly movableColumns = input<boolean>(false);\n /** Hides rows for which it returns false (a status or date-range filter). Combines with the text filter; both must pass. */\n readonly rowFilter = input<((row: DataGridRow) => boolean) | undefined>(undefined);\n /** Derives a stable id per row. Defaults to the row's index in `rows`. */\n readonly rowId = input<(row: DataGridRow, index: number) => string>((_row, index) => String(index));\n /** Row selection mode. */\n readonly selectionMode = input<DataGridSelectionMode>(\"none\");\n /** Rows per page. Unset disables pagination. */\n readonly pageSize = input<number | undefined>(undefined);\n /** If set, persist column widths / hidden columns / sort to localStorage. */\n readonly storageKey = input<string | undefined>(undefined);\n /** User-facing strings. */\n readonly labels = input<DataGridLabels>({});\n /** `\"grid\"` (default): roving-tabindex grid. `\"table\"`: a plain table with ordinary tab stops. */\n readonly mode = input<\"grid\" | \"table\">(\"grid\");\n /** Extra class on each body row. */\n readonly rowClass = input<((row: DataGridRow) => string) | undefined>(undefined);\n /** Extra attributes on each body row. */\n readonly rowAttrs = input<((row: DataGridRow) => Record<string, string>) | undefined>(undefined);\n /** Enter on a body cell with no widget, and a click outside any widget, emit `rowActivate` — only when this is true (Angular outputs cannot be tested for a listener). */\n readonly activateRows = input<boolean>(false);\n /** Shown in one row spanning every column when no row is to be shown. */\n readonly empty = input<TemplateRef<void> | undefined>(undefined);\n /** Rendered inside a `<tfoot>`: a template receiving `{ columns, rows }` as `$implicit`. */\n readonly footer = input<TemplateRef<{ $implicit: DataGridFooterContext }> | undefined>(undefined);\n /** Sets `aria-busy` on the table. */\n readonly busy = input<boolean>(false);\n /** Wrap the table in a scrollable `data-grid-scroll` region. Default true. */\n readonly scroll = input<boolean>(true);\n /** The file name without its extension. Default `\"data-grid\"`. */\n readonly exportFilename = input<string>(\"data-grid\");\n /** What an export holds: `\"view\"` (default) or `\"selected\"`. */\n readonly exportScope = input<\"view\" | \"selected\">(\"view\");\n /** `.xlsx` only: a `formula` column keeps the live expression with the result cached. */\n readonly exportFormulas = input<boolean>(false);\n /** Called with the file before it is saved. Return `false` to keep the grid from saving it. */\n readonly exportHandler = input<((file: DataGridExport) => boolean | void) | undefined>(undefined);\n /** Called before a copy puts text on the clipboard. Return `false` to take over (nothing is copied). The `copy` output fires first. */\n readonly copyHandler = input<((copy: { text: string; rowCount: number }) => boolean | void) | undefined>(undefined);\n /** Renders only the rows in view, in a scroll region of `height` px (needs `scroll`). */\n readonly virtualize = input<{ rowHeight: number; height: number; overscan?: number } | undefined>(undefined);\n /** Extra CSS class on the root. */\n readonly className = input<string>(\"\");\n\n // ---- Two-way models ----\n\n /** Selected row ids. Two-way bindable: `[(selected)]`. */\n readonly selected = model<string[]>([]);\n /** Text filter. Two-way bindable: `[(filter)]`. */\n readonly filter = model<string>(\"\");\n /** Limits the text filter to one column: a column id, or `\"\"` for every filterable column. Two-way bindable: `[(filterField)]`. */\n readonly filterField = model<string>(\"\");\n /** Further sort keys after `sort`, for ties: Shift+click on another sortable header adds it. Two-way bindable: `[(thenBy)]`. */\n readonly thenBy = model<DataGridSort[]>([]);\n /** Current sort. Two-way bindable: `[(sort)]`. */\n readonly sort = model<DataGridSort>({ columnId: \"\", direction: \"none\" });\n /** Column ids in display order. Two-way bindable: `[(columnOrder)]`; columns it does not name follow in their `columns` order. */\n readonly columnOrder = model<string[]>([]);\n /** Current 1-indexed page. Two-way bindable: `[(page)]`. */\n readonly page = model<number>(1);\n\n // ---- Outputs ----\n\n readonly cellEdit = output<DataGridCellEdit>();\n readonly filesSelected = output<{ rowId: string; row: DataGridRow; columnId: string; files: File[] }>();\n readonly fileRemove = output<{ rowId: string; row: DataGridRow; columnId: string; fileId: string }>();\n readonly rowActivate = output<{ row: DataGridRow; id: string }>();\n readonly exportFile = output<DataGridExport>();\n readonly copy = output<{ text: string; rowCount: number }>();\n\n // ---- State ----\n\n protected readonly gridId = nextDataGridId();\n protected readonly minColumnWidth = MIN_COLUMN_WIDTH;\n private readonly rootRef = viewChild.required<ElementRef<HTMLDivElement>>(\"rootEl\");\n private readonly scrollRef = viewChild<ElementRef<HTMLDivElement>>(\"scrollEl\");\n private readonly injector = inject(Injector);\n\n protected readonly statusMessage = signal(\"\");\n protected readonly hiddenColumnIds = signal<ReadonlySet<string>>(new Set());\n private readonly columnWidths = signal<Record<string, number>>({});\n private readonly focusedRow = signal(-1); // -1 = header row\n private readonly focusedCol = signal(0);\n private lastSelectedIndex = -1;\n protected readonly editingState = signal<Editing | null>(null);\n private readonly scrollTop = signal(0);\n private draggingColumnId: string | null = null;\n\n // ---- Derived data ----\n\n /** Each column with its type's defaults filled in under its own props. */\n protected readonly resolvedColumns = computed(() => this.columns().map((c) => resolveColumn(c, this.locale(), this.rows())) as DataGridColumn[]);\n protected readonly isGrid = computed(() => this.mode() === \"grid\");\n protected readonly hasSelection = computed(() => this.selectionMode() !== \"none\");\n protected readonly colOffset = computed(() => (this.hasSelection() ? 1 : 0));\n\n /** Columns in display order: those named in `columnOrder` first, the rest after in their own order. */\n private readonly orderedColumns = computed(() => {\n const order = this.columnOrder();\n const columns = this.resolvedColumns();\n if (order.length === 0) return columns;\n const rank = (id: string) => {\n const i = order.indexOf(id);\n return i === -1 ? order.length : i;\n };\n return columns\n .map((c, i) => ({ c, i }))\n .sort((a, b) => rank(a.c.id) - rank(b.c.id) || a.i - b.i)\n .map((x) => x.c);\n });\n protected readonly visibleColumns = computed(() => this.orderedColumns().filter((c) => !this.hiddenColumnIds().has(c.id)));\n protected readonly hidableColumns = computed(() => this.resolvedColumns().filter((c) => c.hidable));\n\n private readonly entries = computed<DataGridEntry[]>(() => {\n const rowId = this.rowId();\n return this.rows().map((row, index) => ({ row, id: rowId(row, index) }));\n });\n\n /** Each cell's value and formatted text, read once per row object and column (reset when the columns change). */\n private readonly cellCache = computed(() => {\n this.resolvedColumns();\n return new WeakMap<DataGridRow, Map<string, DataGridCellContext>>();\n });\n\n protected cellFor(column: DataGridColumn, row: DataGridRow): DataGridCellContext {\n const cache = this.cellCache();\n let perRow = cache.get(row);\n if (!perRow) {\n perRow = new Map();\n cache.set(row, perRow);\n }\n let ctx = perRow.get(column.id);\n if (!ctx) {\n ctx = { value: defaultAccessor(column, row), formatted: formatCell(column, row), row, column };\n perRow.set(column.id, ctx);\n }\n return ctx;\n }\n\n /** A missing value: `null`, `undefined` or an empty string. */\n protected readonly isMissing = isMissing;\n\n /** A column the user can move: its own `movable`, else the grid's `movableColumns`. */\n protected isMovable(column: DataGridColumn): boolean {\n return column.movable ?? this.movableColumns();\n }\n\n protected readonly filterableColumns = computed(() => this.resolvedColumns().filter((c) => c.filterable !== false));\n\n /** One folded (lower-case, no diacritics) text per filterable cell, built once per rows/columns change. */\n private readonly searchIndex = computed(() =>\n this.entries().map((entry) =>\n this.filterableColumns().map((column) =>\n foldText(column.filterText ? column.filterText(this.cellFor(column, entry.row).value, entry.row) : this.cellFor(column, entry.row).formatted),\n ),\n ),\n );\n\n // Every word of the filter must appear somewhere in the row (any order, any cells), ignoring case and diacritics.\n private readonly filteredEntries = computed(() => {\n const terms = searchTerms(this.filter());\n const rowFilter = this.rowFilter();\n if (terms.length === 0 && !rowFilter) return this.entries();\n const index = terms.length > 0 ? this.searchIndex() : null;\n // With a field chosen, every word must be in that field's cell; otherwise anywhere in the row.\n const field = this.filterField();\n const only = field ? this.filterableColumns().findIndex((c) => c.id === field) : -1;\n const rowText = (i: number): string => (only >= 0 ? index![i][only] : index![i].join(\" \"));\n return this.entries().filter((entry, i) => (!rowFilter || rowFilter(entry.row)) && (!index || terms.every((term) => rowText(i).includes(term))));\n });\n\n /** The sort keys in order: the primary, then `thenBy`, each with a real column and a direction. */\n private readonly sortKeys = computed(() =>\n [this.sort(), ...this.thenBy()]\n .map((k) => ({ column: this.resolvedColumns().find((c) => c.id === k.columnId), dir: k.direction === \"ascending\" ? 1 : k.direction === \"descending\" ? -1 : 0 }))\n .filter((k): k is { column: DataGridColumn; dir: 1 | -1 } => !!k.column && k.dir !== 0),\n );\n\n protected readonly sortedEntries = computed(() => {\n const keys = this.sortKeys();\n const filtered = this.filteredEntries();\n if (keys.length === 0) return filtered;\n const nulls = this.nulls();\n const collators = keys.map((k) => {\n const tag = k.column.locale ?? this.locale();\n return tag ? new Intl.Collator(tag, { numeric: true }) : null;\n });\n // Read each sort key once per column (n accessor calls), not twice per comparison.\n const keyed = filtered.map((entry) => ({ entry, keys: keys.map((k) => this.cellFor(k.column, entry.row).value) }));\n keyed.sort((a, b) => {\n for (let i = 0; i < keys.length; i++) {\n const { column, dir } = keys[i];\n const av = a.keys[i];\n const bv = b.keys[i];\n if (av === bv) continue;\n // Missing values sort together at one end, in both directions (`nulls`).\n const aMissing = av === null || av === undefined;\n const bMissing = bv === null || bv === undefined;\n if (aMissing || bMissing) return aMissing === bMissing ? 0 : (aMissing ? 1 : -1) * (nulls === \"first\" ? -1 : 1);\n const collator = collators[i];\n const result = column.compare\n ? column.compare(av, bv) * dir\n : collator && typeof av === \"string\" && typeof bv === \"string\"\n ? collator.compare(av, bv) * dir\n : (av as never) > (bv as never)\n ? dir\n : -dir;\n if (result !== 0) return result;\n }\n return 0;\n });\n return keyed.map((k) => k.entry);\n });\n\n protected readonly pageCount = computed(() => {\n const size = this.pageSize();\n return size ? Math.max(1, Math.ceil(this.sortedEntries().length / size)) : 1;\n });\n protected readonly clampedPage = computed(() => Math.min(Math.max(this.page(), 1), this.pageCount()));\n protected readonly pageStart = computed(() => {\n const size = this.pageSize();\n return size ? (this.clampedPage() - 1) * size : 0;\n });\n protected readonly pageEntries = computed(() => {\n const size = this.pageSize();\n return size ? this.sortedEntries().slice(this.pageStart(), this.pageStart() + size) : this.sortedEntries();\n });\n protected readonly lastCol = computed(() => this.colOffset() + this.visibleColumns().length - 1);\n\n // The roving position clamped to the cells that exist now.\n protected readonly activeRow = computed(() => Math.max(-1, Math.min(this.focusedRow(), this.pageEntries().length - 1)));\n protected readonly activeCol = computed(() => Math.max(0, Math.min(this.focusedCol(), this.lastCol())));\n\n protected readonly indexed = computed(() => !!this.pageSize() || !!this.virtualize());\n private readonly rowCount = computed(() =>\n this.pageSize() ? this.sortedEntries().length + 1 : this.virtualize() ? this.pageEntries().length + 1 : undefined,\n );\n\n protected readonly renderItems = computed<RenderItem[]>(() => {\n const total = this.pageEntries().length;\n const v = this.virtualize();\n if (!v) return this.pageEntries().map((_, index) => ({ kind: \"row\", index }) as RenderItem);\n const overscan = v.overscan ?? 3;\n const top = this.scrollTop();\n const start = Math.max(0, Math.floor(top / v.rowHeight) - overscan);\n const end = Math.min(total, Math.ceil((top + v.height) / v.rowHeight) + overscan);\n const indices = new Set<number>();\n for (let i = start; i < end; i++) indices.add(i);\n const active = this.activeRow();\n if (active >= 0 && active < total) indices.add(active);\n const items: RenderItem[] = [];\n let previous = -1;\n for (const index of [...indices].sort((a, b) => a - b)) {\n if (index - previous > 1) items.push({ kind: \"spacer\", rows: index - previous - 1, key: `spacer-${previous}` });\n items.push({ kind: \"row\", index });\n previous = index;\n }\n if (total - 1 - previous > 0) items.push({ kind: \"spacer\", rows: total - 1 - previous, key: `spacer-${previous}` });\n return items;\n });\n\n protected readonly scrollStyle = computed(() => {\n const v = this.virtualize();\n return v ? `height:${v.height}px;overflow:auto` : null;\n });\n\n private readonly selectedSet = computed(() => new Set(this.selected()));\n protected readonly allSelected = computed(() => this.sortedEntries().length > 0 && this.sortedEntries().every((e) => this.selectedSet().has(e.id)));\n protected readonly someSelected = computed(() => !this.allSelected() && this.sortedEntries().some((e) => this.selectedSet().has(e.id)));\n\n protected readonly footerContext = computed<DataGridFooterContext>(() => ({\n columns: this.visibleColumns(),\n rows: this.pageEntries().map((e) => e.row),\n }));\n\n protected readonly exportColumns = computed(() => this.visibleColumns().filter((c) => c.exportable !== false));\n protected readonly exportEntries = computed(() =>\n this.exportScope() === \"selected\" ? this.sortedEntries().filter((e) => this.selectedSet().has(e.id)) : this.sortedEntries(),\n );\n protected readonly hasExportButtons = computed(() => {\n const l = this.labels();\n return !!(l.exportCsv || l.exportTsv || l.exportExcel || l.copy);\n });\n\n constructor() {\n // The headless `lily-data-table` root renders a plain <table>: give it the grid's role and counts.\n effect(() => {\n const root = this.rootRef().nativeElement;\n const grid = this.isGrid();\n const count = this.rowCount();\n const busy = this.busy();\n this.sortedEntries();\n this.pageEntries();\n this.visibleColumns();\n this.scroll();\n afterNextRender(\n () => {\n const table = root.querySelector<HTMLElement>(\"table.data-table\");\n if (!table) return;\n table.setAttribute(\"role\", grid ? \"grid\" : \"table\");\n if (grid && count !== undefined) table.setAttribute(\"aria-rowcount\", String(count));\n else table.removeAttribute(\"aria-rowcount\");\n if (busy) table.setAttribute(\"aria-busy\", \"true\");\n else table.removeAttribute(\"aria-busy\");\n },\n { injector: this.injector },\n );\n });\n\n // What the grid renders, as far as labels go, so a missing one can be named in development.\n const reportedLabels = new Set<string>();\n effect(() => {\n const labels = this.labels();\n const columns = this.resolvedColumns();\n const features: LabelFeatures = {\n selection: this.selectionMode() !== \"none\",\n pagination: !!this.pageSize(),\n hidableColumns: columns.some((c) => c.hidable),\n resizableColumns: columns.some((c) => c.resizable),\n editing: columns.some((c) => c.editable),\n sorting: columns.some((c) => c.sortable),\n search: !!labels.search,\n exporting: !!(labels.exportCsv || labels.exportTsv || labels.exportExcel || labels.copy),\n };\n const warn = this.warnMissingLabels();\n const env = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env;\n if (!warn || env?.[\"NODE_ENV\"] === \"production\") return;\n const fresh = missingLabels(features, labels as Record<string, unknown>).filter((m) => !reportedLabels.has(m.key));\n if (fresh.length === 0) return;\n for (const m of fresh) reportedLabels.add(m.key);\n const controls = fresh.filter((m) => m.kind === \"control\").map((m) => m.key);\n const announcements = fresh.filter((m) => m.kind === \"announcement\").map((m) => m.key);\n console.warn(\n `[data-grid] \"${this.label()}\": labels left out — ` +\n [controls.length ? `controls with no name: ${controls.join(\", \")}` : \"\", announcements.length ? `silent announcements: ${announcements.join(\", \")}` : \"\"].filter(Boolean).join(\"; \"),\n );\n });\n\n // Widgets in body cells are not tab stops, so Tab leaves the grid in one step. Re-run whenever what is on screen changes.\n effect(() => {\n this.pageEntries();\n this.visibleColumns();\n this.isGrid();\n this.scrollTop();\n this.editingState();\n afterNextRender(() => this.normaliseWidgets(), { injector: this.injector });\n });\n\n // Persistence (view state only: widths, hidden columns, sort — never rows/selection).\n let restored = false;\n effect(() => {\n const key = this.storageKey();\n if (!key || restored) return;\n restored = true;\n untracked(() => this.restoreView(key));\n });\n effect(() => {\n const key = this.storageKey();\n const snapshot = { columnWidths: this.columnWidths(), hiddenColumnIds: [...this.hiddenColumnIds()], sort: this.sort() };\n if (!key || typeof localStorage === \"undefined\") return;\n try {\n localStorage.setItem(key, JSON.stringify(snapshot));\n } catch {\n // ignore quota / privacy errors\n }\n });\n }\n\n // ---- Announcements ----\n\n private announce(message: string | undefined): void {\n if (message) this.statusMessage.set(message);\n }\n\n // ---- Sorting ----\n\n protected ariaSortFor(column: DataGridColumn): DataGridSortDirection | null {\n if (!column.sortable) return null;\n if (this.sort().columnId === column.id) return this.sort().direction;\n return this.thenBy().find((k) => k.columnId === column.id)?.direction ?? \"none\";\n }\n\n /** 1 for the primary key, 2… for `thenBy`, only while more than one key is in force. */\n protected sortOrderFor(column: DataGridColumn): number | null {\n const keys = this.sortKeys();\n if (keys.length < 2) return null;\n const at = keys.findIndex((k) => k.column.id === column.id);\n return at === -1 ? null : at + 1;\n }\n\n protected toggleSort(column: DataGridColumn, additive = false): void {\n if (!column.sortable) return;\n const current = this.sort();\n if (additive && current.direction !== \"none\" && current.columnId && current.columnId !== column.id) {\n const thenBy = this.thenBy();\n const existing = thenBy.find((k) => k.columnId === column.id);\n const nextThen: DataGridSort[] = !existing\n ? [...thenBy, { columnId: column.id, direction: \"ascending\" }]\n : existing.direction === \"ascending\"\n ? thenBy.map((k) => (k.columnId === column.id ? { columnId: column.id, direction: \"descending\" as const } : k))\n : thenBy.filter((k) => k.columnId !== column.id);\n this.thenBy.set(nextThen);\n this.announce(this.labels().sortAnnouncement?.(column.header, nextThen.find((k) => k.columnId === column.id)?.direction ?? \"none\"));\n return;\n }\n if (this.thenBy().length > 0) this.thenBy.set([]);\n const next: DataGridSort =\n current.columnId !== column.id\n ? { columnId: column.id, direction: \"ascending\" }\n : current.direction === \"ascending\"\n ? { columnId: column.id, direction: \"descending\" }\n : current.direction === \"descending\"\n ? { columnId: \"\", direction: \"none\" }\n : { columnId: column.id, direction: \"ascending\" };\n this.sort.set(next);\n this.announce(this.labels().sortAnnouncement?.(column.header, next.direction));\n }\n\n // ---- Filtering ----\n\n protected setFilter(value: string): void {\n this.filter.set(value);\n this.page.set(1);\n this.announce(this.labels().filterAnnouncement?.(this.filteredEntries().length, this.rows().length));\n }\n\n /** Escape in the search field clears it. */\n protected onFilterKeydown(event: Event): void {\n const e = event as KeyboardEvent;\n if (e.key === \"Escape\" && this.filter() !== \"\") {\n e.preventDefault();\n this.setFilter(\"\");\n }\n }\n\n protected onFilterFieldChange(event: Event): void {\n this.filterField.set((event.target as HTMLSelectElement).value);\n this.page.set(1);\n this.announce(this.labels().filterAnnouncement?.(this.filteredEntries().length, this.rows().length));\n }\n\n // ---- Selection ----\n\n protected isSelected(id: string): boolean {\n return this.selectedSet().has(id);\n }\n\n private setSelected(next: string[]): void {\n this.selected.set(next);\n this.announce(this.labels().selectionAnnouncement?.(next.length));\n }\n\n protected onRowSelectClick(index: number, event: Event): void {\n const e = event as MouseEvent;\n this.toggleRow(index, e);\n }\n\n /** `index` is the row's position in the sorted entries, not on the current page. */\n private toggleRow(index: number, event?: { shiftKey?: boolean; ctrlKey?: boolean; metaKey?: boolean }): void {\n const sorted = this.sortedEntries();\n const id = sorted[index].id;\n const selected = this.selected();\n const mode = this.selectionMode();\n if (mode === \"single\") {\n this.setSelected(this.isSelected(id) ? [] : [id]);\n } else if (mode === \"multiple\") {\n if (event?.shiftKey && this.lastSelectedIndex >= 0) {\n const [start, end] = this.lastSelectedIndex < index ? [this.lastSelectedIndex, index] : [index, this.lastSelectedIndex];\n const range = sorted.slice(start, end + 1).map((e) => e.id);\n this.setSelected([...new Set([...selected, ...range])]);\n } else if (event?.ctrlKey || event?.metaKey) {\n this.setSelected(this.isSelected(id) ? selected.filter((x) => x !== id) : [...selected, id]);\n } else {\n this.setSelected(this.isSelected(id) && selected.length === 1 ? [] : [id]);\n }\n }\n this.lastSelectedIndex = index;\n }\n\n protected toggleSelectAll(): void {\n if (this.allSelected()) this.setSelected([]);\n else this.setSelected(this.sortedEntries().map((e) => e.id));\n }\n\n // ---- Column resize ----\n\n protected widthFor(column: DataGridColumn): number | undefined {\n return this.columnWidths()[column.id] ?? column.width;\n }\n\n /** Inline style of a column's cells: its width, and its alignment where one is set. */\n protected cellStyle(column: DataGridColumn): string | null {\n const parts: string[] = [];\n const width = this.widthFor(column);\n if (width) parts.push(`width:${width}px`);\n if (column.align) parts.push(`text-align:${column.align}`);\n return parts.length > 0 ? parts.join(\";\") : null;\n }\n\n private setWidth(column: DataGridColumn, width: number): void {\n this.columnWidths.update((current) => ({ ...current, [column.id]: Math.max(MIN_COLUMN_WIDTH, width) }));\n }\n\n protected onResizeKeydown(column: DataGridColumn, event: Event): void {\n const e = event as KeyboardEvent;\n // The resize handle is its own tab stop outside the grid's roving-tabindex system — every key here must stop.\n e.stopPropagation();\n const current = this.widthFor(column) ?? 120;\n if (e.key === \"ArrowRight\") {\n e.preventDefault();\n this.setWidth(column, current + RESIZE_STEP);\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n this.setWidth(column, current - RESIZE_STEP);\n }\n }\n\n protected onResizePointerDown(column: DataGridColumn, event: Event): void {\n const e = event as PointerEvent;\n e.preventDefault();\n const startX = e.clientX;\n const target = e.target as HTMLElement;\n const startWidth = this.widthFor(column) ?? target.closest(\"th\")?.getBoundingClientRect().width ?? 120;\n target.setPointerCapture?.(e.pointerId);\n const onMove = (moveEvent: PointerEvent): void => this.setWidth(column, startWidth + (moveEvent.clientX - startX));\n const onUp = (): void => {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n }\n\n // ---- Column visibility, pagination ----\n\n protected toggleColumnVisibility(columnId: string): void {\n this.hiddenColumnIds.update((current) => {\n const next = new Set(current);\n if (next.has(columnId)) next.delete(columnId);\n else next.add(columnId);\n return next;\n });\n }\n\n protected goToPage(next: number): void {\n const target = Math.min(Math.max(next, 1), this.pageCount());\n if (target === this.clampedPage()) return;\n this.page.set(target);\n this.announce(this.labels().pageAnnouncement?.(target, this.pageCount()));\n }\n\n // ---- Column reorder ----\n\n /** Move `columnId` to sit at `toVisibleIndex` among the visible columns. Returns whether it moved. */\n private moveColumn(columnId: string, toVisibleIndex: number): boolean {\n const ids = this.visibleColumns().map((c) => c.id);\n const from = ids.indexOf(columnId);\n const to = Math.min(Math.max(toVisibleIndex, 0), ids.length - 1);\n if (from === -1 || from === to) return false;\n ids.splice(to, 0, ...ids.splice(from, 1));\n // Hidden columns keep their places in the full order; visible ones are re-sequenced around them.\n const visibleSet = new Set(ids);\n let next = 0;\n this.columnOrder.set(this.orderedColumns().map((c) => (visibleSet.has(c.id) ? ids[next++] : c.id)));\n const column = this.resolvedColumns().find((c) => c.id === columnId)!;\n this.announce(this.labels().columnMoveAnnouncement?.(column.header, to + 1, ids.length));\n return true;\n }\n\n protected onHeaderDragStart(column: DataGridColumn, event: Event): void {\n if (!column.movable) return;\n this.draggingColumnId = column.id;\n (event as DragEvent).dataTransfer?.setData(\"text/plain\", column.id);\n }\n\n protected onHeaderDragOver(event: Event): void {\n if (this.draggingColumnId) event.preventDefault();\n }\n\n protected onHeaderDrop(targetId: string, event: Event): void {\n event.preventDefault();\n const id = this.draggingColumnId;\n this.draggingColumnId = null;\n if (!id || id === targetId) return;\n const to = this.visibleColumns().findIndex((c) => c.id === targetId);\n if (to >= 0) this.moveColumn(id, to);\n }\n\n // ---- Windowing ----\n\n protected onScroll(event: Event): void {\n if (this.virtualize()) this.scrollTop.set((event.currentTarget as HTMLElement).scrollTop);\n }\n\n /** Bring a body row into the scroll region. */\n private revealRow(index: number): void {\n const v = this.virtualize();\n if (!v || index < 0) return;\n const top = index * v.rowHeight;\n const current = this.scrollTop();\n let next = current;\n if (top < current) next = top;\n else if (top + v.rowHeight > current + v.height) next = top + v.rowHeight - v.height;\n if (next === current) return;\n this.scrollTop.set(next);\n const el = this.scrollRef()?.nativeElement;\n if (el) el.scrollTop = next;\n }\n\n // ---- Focus ----\n\n private focusActiveCell(): void {\n afterNextRender(\n () => {\n this.rootRef().nativeElement\n .querySelector<HTMLElement>('.data-table-th[tabindex=\"0\"], .data-table-td[tabindex=\"0\"]')\n ?.focus({ preventScroll: true });\n },\n { injector: this.injector },\n );\n }\n\n private moveFocus(row: number, col: number): void {\n const nextRow = Math.min(Math.max(row, -1), this.pageEntries().length - 1);\n this.focusedRow.set(nextRow);\n this.focusedCol.set(Math.min(Math.max(col, 0), this.lastCol()));\n this.revealRow(nextRow);\n this.focusActiveCell();\n }\n\n // ---- Export ----\n\n /** One cell for an export: typed values stay typed, everything else is the text the grid shows. */\n private exportCell(column: DataGridColumn, row: DataGridRow): unknown {\n if (column.exportValue) return column.exportValue(row);\n const ctx = this.cellFor(column, row);\n const value = ctx.value;\n if (value === null || value === undefined) return null;\n if (typeof value === \"number\" || typeof value === \"boolean\" || value instanceof Date) return value;\n return ctx.formatted;\n }\n\n private hasUtcColumn(c: DataGridColumn): boolean {\n return c.type === \"time-zone\" && !!c.exportUtc && !!c.referenceDate && !!this.labels().exportUtcHeader;\n }\n\n private buildExportTable(format: ExportFormat) {\n const live = (c: DataGridColumn) => format === \"xlsx\" && this.exportFormulas() && c.type === \"formula\" && !!c.source;\n const headers: string[] = [];\n for (const c of this.exportColumns()) {\n headers.push(c.header);\n if (this.hasUtcColumn(c)) headers.push(this.labels().exportUtcHeader!(c.header));\n }\n const rows = this.exportEntries().map((entry) => {\n const cells: unknown[] = [];\n for (const c of this.exportColumns()) {\n const expression = live(c) ? c.source!(entry.row) : undefined;\n cells.push(\n typeof expression === \"string\" && expression !== \"\" && !c.errorOf?.(entry.row)\n ? { formula: expression, result: this.exportCell(c, entry.row) }\n : this.exportCell(c, entry.row),\n );\n if (this.hasUtcColumn(c)) cells.push(zonedUtcTime(this.cellFor(c, entry.row).value, c.referenceDate));\n }\n return cells;\n });\n return { headers, rows };\n }\n\n /** Copy the export (what a download would hold) to the clipboard as tab-separated text. `copyHandler` may return false to take over. */\n protected async runCopy(): Promise<void> {\n const table = this.buildExportTable(\"tsv\");\n const text = toClipboardText(table);\n const copied = { text, rowCount: table.rows.length };\n this.copy.emit(copied);\n if (this.copyHandler()?.(copied) === false) return;\n const ok = await copyToClipboard(text);\n this.announce(ok ? this.labels().copyAnnouncement?.(table.rows.length) : this.labels().copyFailed);\n }\n\n protected runExport(format: ExportFormat): void {\n const table = this.buildExportTable(format);\n const rows = table.rows;\n const name = this.exportFilename();\n const filename = exportFilename(name, format);\n const blob = exportBlob(table, format, { sheetName: name });\n const file: DataGridExport = { format, filename, rowCount: rows.length, blob };\n this.exportFile.emit(file);\n if (this.exportHandler()?.(file) === false) return;\n downloadBlob(blob, filename);\n this.announce(this.labels().exportAnnouncement?.(format, rows.length, filename));\n }\n\n // ---- Files ----\n\n /** Files dropped on an editable file cell: the same report as the file input. The grid uploads nothing. */\n protected onFileDragOver(column: DataGridColumn, event: Event): void {\n if (column.type !== \"file\" || !column.editable) return;\n if (Array.from((event as DragEvent).dataTransfer?.types ?? []).includes(\"Files\")) event.preventDefault();\n }\n\n protected onFileDrop(entry: DataGridEntry, column: DataGridColumn, event: Event): void {\n if (column.type !== \"file\" || !column.editable) return;\n const dropped = Array.from((event as DragEvent).dataTransfer?.files ?? []);\n if (dropped.length === 0) return;\n event.preventDefault();\n const files = column.multiple === false ? dropped.slice(0, 1) : dropped;\n this.filesSelected.emit({ rowId: entry.id, row: entry.row, columnId: column.id, files });\n }\n\n protected onFileInput(entry: DataGridEntry, column: DataGridColumn, event: Event): void {\n const input = event.target as HTMLInputElement;\n const chosen = Array.from(input.files ?? []);\n if (chosen.length > 0) this.filesSelected.emit({ rowId: entry.id, row: entry.row, columnId: column.id, files: chosen });\n input.value = \"\";\n }\n\n // ---- Cell editing ----\n\n /** A cell the person can edit through the grid's edit model (not a rollup, a file cell with its own widgets, or a person cell with no editor). */\n protected isEditable(column: DataGridColumn): boolean {\n if (!column.editable) return false;\n if (column.type === \"rollup\" || column.type === \"file\") return false;\n if (column.type === \"person\" && !column.personEditor) return false;\n return true;\n }\n\n protected isEditingCell(entry: DataGridEntry, column: DataGridColumn): boolean {\n const e = this.editingState();\n return !!e && e.rowId === entry.id && e.columnId === column.id;\n }\n\n protected startEdit(entry: DataGridEntry, column: DataGridColumn): void {\n if (!this.isEditable(column)) return;\n // A formula's editor shows the expression the row holds, not the result.\n const raw = column.type === \"formula\" && column.source ? column.source(entry.row) : defaultAccessor(column, entry.row);\n if (column.type === \"time-zone\") {\n const zoned = isZonedTime(raw) ? raw : null;\n this.editingState.set({ rowId: entry.id, columnId: column.id, draft: zoned?.time ?? \"\", zone: zoned?.timeZone ?? column.timeZones?.[0]?.id ?? \"\" });\n } else {\n const text = column.type === \"link\" ? (linkParts(raw)?.href ?? \"\") : raw === null || raw === undefined ? \"\" : String(raw);\n this.editingState.set({ rowId: entry.id, columnId: column.id, draft: text });\n }\n afterNextRender(\n () => {\n const editor = this.rootRef().nativeElement.querySelector<HTMLInputElement | HTMLSelectElement>(\".data-grid-cell-editor\");\n editor?.focus();\n if (editor instanceof HTMLInputElement && editor.type === \"text\") editor.select();\n },\n { injector: this.injector },\n );\n }\n\n private parseDraft(column: DataGridColumn, row: DataGridRow, draft: string, zone?: string): unknown {\n if (column.parse) return column.parse(draft, row);\n if (column.type === \"time-zone\") return draft === \"\" ? null : { time: draft, timeZone: zone ?? \"\" };\n if (column.editor === \"number\") return draft.trim() === \"\" ? null : Number(draft);\n if (column.editor === \"date\" || column.editor === \"time\" || column.editor === \"select\") return draft === \"\" ? null : draft;\n return draft;\n }\n\n /** Two link values with the same address and label are the same edit. */\n /** Accepted cell edits, for Ctrl/Cmd+Z. The consumer owns the data, so an undo is reported through the `cellEdit` output like any edit. */\n private history: EditHistory = EMPTY_HISTORY;\n\n /** Put an earlier cell value back, or re-apply it, through `cellEdit`. */\n private stepHistory(direction: \"undo\" | \"redo\"): void {\n const step = direction === \"undo\" ? undoEdit(this.history) : redoEdit(this.history);\n if (!step.record) return;\n this.history = step.history;\n const { ownerId, fieldId, value, previous } = step.record;\n const entry = this.entries().find((e) => e.id === ownerId);\n const column = this.resolvedColumns().find((c) => c.id === fieldId);\n if (!entry || !column) return;\n const restored = direction === \"undo\" ? previous : value;\n const replaced = direction === \"undo\" ? value : previous;\n this.cellEdit.emit({ rowId: entry.id, row: entry.row, columnId: column.id, value: restored, previous: replaced });\n const text = column.format ? column.format(restored, entry.row) : String(restored ?? \"\");\n this.announce((direction === \"undo\" ? this.labels().undoAnnouncement : this.labels().redoAnnouncement)?.(column.header, text));\n }\n\n private isStructurallyEqual(a: unknown, b: unknown): boolean {\n return typeof a === \"object\" && typeof b === \"object\" && a !== null && b !== null && JSON.stringify(a) === JSON.stringify(b);\n }\n\n /** Validate and report one new value for a cell. Returns false (and keeps editing, if the editor is open) when it is refused. */\n protected commitValue(entry: DataGridEntry, column: DataGridColumn, value: unknown): boolean {\n const message = column.validate?.(value, entry.row);\n const invalidType = isInvalidForType(column, value);\n if (message || invalidType) {\n const text = message ?? this.labels().invalidValue?.(column.header, column.type ?? \"\") ?? \"\";\n const current = this.editingState();\n if (current) this.editingState.set({ ...current, error: text || undefined, invalid: true });\n this.announce(this.labels().editError?.(column.header, text));\n return false;\n }\n const previous = column.type === \"formula\" && column.source ? column.source(entry.row) : defaultAccessor(column, entry.row);\n this.editingState.set(null);\n if (value !== previous && !this.isStructurallyEqual(value, previous)) {\n this.history = recordEdit(this.history, { ownerId: entry.id, fieldId: column.id, value, previous });\n this.cellEdit.emit({ rowId: entry.id, row: entry.row, columnId: column.id, value, previous });\n this.announce(this.labels().editAnnouncement?.(column.header, column.format ? column.format(value, entry.row) : String(value ?? \"\")));\n }\n return true;\n }\n\n private commitEdit(): void {\n const current = this.editingState();\n if (!current) return;\n const entry = this.entries().find((e) => e.id === current.rowId);\n const column = this.resolvedColumns().find((c) => c.id === current.columnId);\n if (!entry || !column) {\n this.editingState.set(null);\n return;\n }\n if (this.commitValue(entry, column, this.parseDraft(column, entry.row, current.draft, current.zone))) this.focusActiveCell();\n }\n\n private cancelEdit(): void {\n const current = this.editingState();\n if (!current) return;\n this.editingState.set(null);\n const column = this.resolvedColumns().find((c) => c.id === current.columnId);\n if (column) this.announce(this.labels().editCancelAnnouncement?.(column.header));\n this.focusActiveCell();\n }\n\n protected onEditorKeydown(event: Event): void {\n const e = event as KeyboardEvent;\n // The editor owns its keys; none may reach the grid's own handler.\n e.stopPropagation();\n // While an input method is composing, Enter picks the candidate and Escape cancels the composition:\n // neither commits nor cancels the edit. Some browsers report the confirming Enter with `isComposing`\n // already false, but keyCode 229.\n if (e.isComposing || e.keyCode === 229) return;\n if (e.key === \"Enter\") {\n e.preventDefault();\n this.commitEdit();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n this.cancelEdit();\n }\n }\n\n protected onEditorBlur(): void {\n if (this.editingState()) this.commitEdit();\n }\n\n /** Focus leaving the time-zone editor's pair (not moving between its two controls) commits. */\n protected onZonedFocusout(event: Event): void {\n const e = event as FocusEvent;\n if (this.editingState() && !(e.currentTarget as HTMLElement).contains(e.relatedTarget as Node | null)) this.commitEdit();\n }\n\n protected setDraft(event: Event): void {\n const current = this.editingState();\n if (current) this.editingState.set({ ...current, draft: (event.target as HTMLInputElement | HTMLSelectElement).value, error: undefined, invalid: false });\n }\n\n protected setZone(event: Event): void {\n const current = this.editingState();\n if (current) this.editingState.set({ ...current, zone: (event.target as HTMLSelectElement).value, error: undefined, invalid: false });\n }\n\n protected personEditorContext(entry: DataGridEntry, column: DataGridColumn, ctx: DataGridCellContext): DataGridPersonEditorContext {\n return { value: ctx.value, commit: (v: unknown) => void this.commitValue(entry, column, v), cancel: () => this.cancelEdit() };\n }\n\n // ---- Keyboard (WAI-ARIA APG Grid pattern) ----\n\n private activateFocusedCell(): void {\n if (this.activeCol() === 0 && this.hasSelection()) {\n if (this.activeRow() === -1) {\n if (this.selectionMode() === \"multiple\") this.toggleSelectAll();\n } else {\n this.toggleRow(this.pageStart() + this.activeRow());\n }\n return;\n }\n const column = this.visibleColumns()[this.activeCol() - this.colOffset()];\n if (!column) return;\n if (this.activeRow() === -1) this.toggleSort(column);\n }\n\n /** The widgets a consumer put in a body cell (never the grid's own controls). */\n private widgetsIn(cell: Element): HTMLElement[] {\n return Array.from(cell.querySelectorAll<HTMLElement>(WIDGET_SELECTOR)).filter((el) => !el.closest(\"[data-grid-own]\"));\n }\n\n private setWidgetTabindex(cell: Element, value: \"0\" | \"-1\"): void {\n for (const widget of this.widgetsIn(cell)) widget.setAttribute(\"tabindex\", value);\n }\n\n private normaliseWidgets(): void {\n if (!this.isGrid()) return;\n for (const cell of this.rootRef().nativeElement.querySelectorAll(\".data-table-body [data-row][data-col]\")) {\n if (cell.getAttribute(\"data-grid-entered\") === \"true\") continue;\n this.setWidgetTabindex(cell, \"-1\");\n }\n }\n\n /** Focus the first widget of a cell; its widgets are tab stops while focus stays inside it. */\n private enterCell(cell: HTMLElement): boolean {\n const first = this.widgetsIn(cell)[0];\n if (!first) return false;\n cell.setAttribute(\"data-grid-entered\", \"true\");\n this.setWidgetTabindex(cell, \"0\");\n first.focus();\n return true;\n }\n\n private leaveCell(cell: Element): void {\n if (cell.getAttribute(\"data-grid-entered\") !== \"true\") return;\n cell.removeAttribute(\"data-grid-entered\");\n this.setWidgetTabindex(cell, \"-1\");\n }\n\n /** Pointer or programmatic focus on a cell moves the roving position to it. */\n protected onGridFocusin(event: Event): void {\n if (!this.isGrid()) return;\n const target = event.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell) return;\n this.focusedRow.set(Number(cell.dataset[\"row\"]));\n this.focusedCol.set(Number(cell.dataset[\"col\"]));\n // Focus arriving on a widget (a click, or Tab inside the cell) makes the cell's widgets tab stops.\n if (target !== cell && !target.closest(\"[data-grid-own]\") && cell.closest(\".data-table-body\")) {\n cell.setAttribute(\"data-grid-entered\", \"true\");\n this.setWidgetTabindex(cell, \"0\");\n }\n }\n\n protected onGridFocusout(event: Event): void {\n if (!this.isGrid()) return;\n const e = event as FocusEvent;\n const cell = (e.target as HTMLElement).closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell) return;\n const next = e.relatedTarget as Node | null;\n if (next && cell.contains(next)) return;\n this.leaveCell(cell);\n }\n\n /** A click on a body cell, outside any widget, activates its row. */\n protected onGridClick(event: Event): void {\n if (!this.activateRows()) return;\n const target = event.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell || cell.closest(\".data-table-head\")) return;\n if (target.closest(WIDGET_SELECTOR) || target.closest(\"[data-grid-own]\")) return;\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n if (entry) this.rowActivate.emit({ row: entry.row, id: entry.id });\n }\n\n /** A double click on an editable body cell starts editing it. */\n protected onGridDblclick(event: Event): void {\n const target = event.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell || cell.closest(\".data-table-head\") || target.closest(\"input, button, select, textarea\")) return;\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n const column = this.visibleColumns()[Number(cell.dataset[\"col\"]) - this.colOffset()];\n if (entry && column && this.isEditable(column)) this.startEdit(entry, column);\n }\n\n private typeahead: TypeaheadState = { prefix: \"\", at: 0 };\n\n protected onGridKeydown(event: Event): void {\n if (!this.isGrid()) return;\n const e = event as KeyboardEvent;\n const target = e.target as HTMLElement;\n const cell = target.closest<HTMLElement>(\"[data-row][data-col]\");\n if (!cell) return;\n // A key pressed on a widget inside a cell belongs to the widget: the caret moves in a field, a select\n // opens, a link follows. Only Escape is the grid's, and it hands focus back to the cell.\n if (target !== cell && !target.closest(\"[data-grid-own]\")) {\n if (e.key === \"Escape\") {\n e.preventDefault();\n cell.focus({ preventScroll: true });\n }\n return;\n }\n const activeRow = this.activeRow();\n const activeCol = this.activeCol();\n const colOffset = this.colOffset();\n // In a right-to-left layout the horizontal arrows swap: ArrowLeft goes to the next cell (`key` is the logical key).\n const key = logicalKey(e.key, isRtl(cell));\n if (e.altKey && activeRow === -1 && (key === \"ArrowRight\" || key === \"ArrowLeft\")) {\n const column = this.visibleColumns()[activeCol - colOffset];\n if (column && this.isMovable(column)) {\n e.preventDefault();\n const delta = key === \"ArrowRight\" ? 1 : -1;\n if (this.moveColumn(column.id, activeCol - colOffset + delta)) this.moveFocus(-1, activeCol + delta);\n return;\n }\n }\n const historyAction = target === cell && this.resolvedColumns().some((c) => c.editable) ? historyKey(e) : null;\n if (historyAction) {\n e.preventDefault();\n this.stepHistory(historyAction);\n return;\n }\n // Type-ahead in the focused column: letters typed in quick succession move to the next row whose cell text starts with them.\n if (isTypeaheadKey(e) && target === cell && activeRow >= 0) {\n const column = this.visibleColumns()[activeCol - colOffset];\n if (column) {\n const state = nextTypeaheadState(this.typeahead, e.key, Date.now(), 700);\n const hit = findTypeaheadMatch(this.pageEntries().map((entry) => this.cellFor(column, entry.row).formatted), activeRow, state.prefix);\n if (hit !== -1) {\n this.typeahead = state;\n e.preventDefault();\n this.moveFocus(hit, activeCol);\n return;\n }\n }\n }\n const move = gridMove(\n e,\n { row: activeRow, col: activeCol },\n { firstRow: -1, lastRow: this.pageEntries().length - 1, lastCol: this.lastCol(), pageStep: this.pageSize() ?? 10, rtl: isRtl(cell) },\n );\n if (move) {\n e.preventDefault();\n this.moveFocus(move.row, move.col);\n return;\n }\n switch (key) {\n case \"F2\": {\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n const column = this.visibleColumns()[Number(cell.dataset[\"col\"]) - colOffset];\n if (target === cell && entry && column && this.isEditable(column)) {\n e.preventDefault();\n this.startEdit(entry, column);\n }\n break;\n }\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (e.key === \"Enter\" && target === cell && cell.closest(\".data-table-body\")) {\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n const column = this.visibleColumns()[Number(cell.dataset[\"col\"]) - colOffset];\n if (entry && column && this.isEditable(column)) {\n this.startEdit(entry, column);\n break;\n }\n }\n if (target === cell && cell.closest(\".data-table-body\") && !cell.querySelector(\"[data-grid-own]\")) {\n // A cell with a widget in it is entered; one without activates its row.\n if (this.enterCell(cell)) break;\n if (e.key === \"Enter\" && this.activateRows()) {\n const entry = this.pageEntries()[Number(cell.dataset[\"row\"])];\n if (entry) this.rowActivate.emit({ row: entry.row, id: entry.id });\n break;\n }\n }\n this.activateFocusedCell();\n break;\n }\n }\n\n // ---- Persistence ----\n\n private restoreView(key: string): void {\n try {\n const raw = localStorage.getItem(key);\n if (raw) {\n const saved = JSON.parse(raw) as { columnWidths?: Record<string, number>; hiddenColumnIds?: string[]; sort?: DataGridSort };\n if (saved.columnWidths) this.columnWidths.set(saved.columnWidths);\n if (saved.hiddenColumnIds) this.hiddenColumnIds.set(new Set(saved.hiddenColumnIds));\n if (saved.sort) this.sort.set(saved.sort);\n }\n } catch {\n // ignore quota / privacy / parse errors\n }\n }\n\n // ---- Template helpers ----\n\n protected rowLabelOf(entry: DataGridEntry): string {\n const first = this.visibleColumns()[0];\n return first ? this.cellFor(first, entry.row).formatted : entry.id;\n }\n\n protected cellClassOf(column: DataGridColumn, ctx: DataGridCellContext): string {\n const extra = typeof column.cellClass === \"function\" ? column.cellClass(ctx) : column.cellClass;\n return extra ?? \"\";\n }\n\n protected peopleIn(value: unknown): DataGridPerson[] {\n return peopleOf(value);\n }\n\n protected shownPeople(column: DataGridColumn, value: unknown): DataGridPerson[] {\n const people = peopleOf(value);\n return column.maxPeople !== undefined ? people.slice(0, Math.max(0, column.maxPeople)) : people;\n }\n\n protected nameOf(person: DataGridPerson): string {\n return personName(person);\n }\n\n protected filesIn(value: unknown): DataGridFile[] {\n return filesOf(value);\n }\n\n protected linkIn(value: unknown): DataGridLink | null {\n return linkParts(value);\n }\n\n protected hrefOf(href: string | undefined): string | null {\n return href === undefined ? null : safeHref(href);\n }\n\n protected stringOf(value: unknown): string {\n return String(value);\n }\n\n protected ungroupedOptions(column: DataGridColumn): DataGridOption[] {\n return (column.options ?? []).filter((o) => !o.group);\n }\n\n protected groupsOf(column: DataGridColumn): string[] {\n return [...new Set((column.options ?? []).filter((o) => o.group).map((o) => o.group as string))];\n }\n\n protected optionsInGroup(column: DataGridColumn, group: string): DataGridOption[] {\n return (column.options ?? []).filter((o) => o.group === group);\n }\n}\n\nexport default DataGrid;\n"],"mappings":"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"}