@timlassiter11/yatl 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/theme.css +7 -0
- package/dist/yatl.min.global.js.map +1 -1
- package/package.json +1 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/events.ts","../src/utils/columns.ts","../src/utils/common.ts","../src/utils/tokenizer.ts","../src/utils/typed-event-target.ts","../src/table/utils.ts","../src/table/table.ts","../src/table-controller/utils.ts","../src/table-controller/table-controller.ts","../src/table/table.styles.ts"],"sourcesContent":["export * from './events';\nexport * from './table/table';\nexport * from './table-controller/table-controller';\nexport * from './types';\nexport * from './utils';\n","import {\n NestedKeyOf,\n RowId,\n SortOrder,\n TableState,\n UnspecifiedRecord,\n} from './types';\n\n/**\n * Base event class that bubbles and is composed.\n */\nexport abstract class YatlEvent extends Event {\n constructor(name: string, options: EventInit = {}) {\n super(name, {\n bubbles: true,\n composed: true,\n cancelable: false,\n ...options,\n });\n }\n\n public abstract clone(): YatlEvent;\n}\n\nexport class YatlRowClickEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-row-click';\n\n constructor(\n public readonly row: T,\n public readonly rowId: RowId,\n public readonly index: number,\n public readonly field: NestedKeyOf<T>,\n public readonly originalEvent: MouseEvent,\n ) {\n super(YatlRowClickEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlRowClickEvent<T>(\n this.row,\n this.rowId,\n this.index,\n this.field,\n this.originalEvent,\n );\n }\n}\n\nexport class YatlRowSelectRequest extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-row-select-request';\n\n constructor(\n public readonly rowId: RowId,\n public readonly selected: boolean,\n public readonly currentlySelectedRows: RowId[],\n ) {\n super(YatlRowSelectRequest.EVENT_NAME, { cancelable: true });\n }\n\n public override clone() {\n return new YatlRowSelectRequest(\n this.rowId,\n this.selected,\n this.currentlySelectedRows,\n );\n }\n}\n\nexport class YatlRowSelectEvent extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-row-select';\n\n constructor(\n public readonly selectedIds: RowId[],\n public readonly previouslySelectedRows: RowId[],\n ) {\n super(YatlRowSelectEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlRowSelectEvent(\n this.selectedIds,\n this.previouslySelectedRows,\n );\n }\n}\n\nexport class YatlColumnSortRequest<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-sort-request';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly order: SortOrder | null,\n public readonly multisort: boolean,\n ) {\n super(YatlColumnSortRequest.EVENT_NAME, { cancelable: true });\n }\n\n public override clone() {\n return new YatlColumnSortRequest<T>(this.field, this.order, this.multisort);\n }\n}\n\nexport class YatlColumnSortEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-sort';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly order: SortOrder | null,\n public readonly multisort: boolean,\n ) {\n super(YatlColumnSortEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnSortEvent<T>(this.field, this.order, this.multisort);\n }\n}\n\nexport class YatlColumnToggleEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-toggle';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly visible: boolean,\n ) {\n super(YatlColumnToggleEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnToggleEvent<T>(this.field, this.visible);\n }\n}\n\nexport class YatlColumnResizeEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-resize';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly width: number | null,\n ) {\n super(YatlColumnResizeEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnResizeEvent<T>(this.field, this.width);\n }\n}\n\nexport class YatlColumnReorderRequest<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-reorder-request';\n\n constructor(\n public readonly movedColumn: NestedKeyOf<T>,\n public readonly originalIndex: number,\n public readonly newIndex: number,\n ) {\n super(YatlColumnReorderRequest.EVENT_NAME, { cancelable: true });\n }\n\n public override clone() {\n return new YatlColumnReorderRequest<T>(\n this.movedColumn,\n this.originalIndex,\n this.newIndex,\n );\n }\n}\n\nexport class YatlColumnReorderEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-reorder';\n\n constructor(public readonly order: NestedKeyOf<T>[]) {\n super(YatlColumnReorderEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnReorderEvent<T>(this.order);\n }\n}\n\nexport class YatlTableSearchEvent extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-table-search';\n\n constructor(public readonly query: string) {\n super(YatlTableSearchEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlTableSearchEvent(this.query);\n }\n}\n\nexport class YatlTableViewChangeEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-table-view-change';\n\n constructor(public readonly data: T[]) {\n super(YatlTableViewChangeEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlTableViewChangeEvent<T>(this.data);\n }\n}\n\nexport class YatlTableStateChangeEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-table-state-change';\n\n constructor(\n public readonly state: TableState<T>,\n public readonly triggers: string[],\n ) {\n super(YatlTableStateChangeEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlTableStateChangeEvent<T>(this.state, this.triggers);\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [YatlRowClickEvent.EVENT_NAME]: YatlRowClickEvent;\n\n [YatlRowSelectRequest.EVENT_NAME]: YatlRowSelectRequest;\n [YatlRowSelectEvent.EVENT_NAME]: YatlRowSelectEvent;\n\n [YatlColumnSortRequest.EVENT_NAME]: YatlColumnSortRequest;\n [YatlColumnSortEvent.EVENT_NAME]: YatlColumnSortEvent;\n\n [YatlColumnToggleEvent.EVENT_NAME]: YatlColumnToggleEvent;\n\n [YatlColumnResizeEvent.EVENT_NAME]: YatlColumnResizeEvent;\n\n [YatlColumnReorderRequest.EVENT_NAME]: YatlColumnReorderRequest;\n [YatlColumnReorderEvent.EVENT_NAME]: YatlColumnReorderEvent;\n\n [YatlTableSearchEvent.EVENT_NAME]: YatlTableSearchEvent;\n [YatlTableViewChangeEvent.EVENT_NAME]: YatlTableViewChangeEvent;\n [YatlTableStateChangeEvent.EVENT_NAME]: YatlTableStateChangeEvent;\n }\n}\n","import {\n ColumnOptions,\n ColumnState,\n DisplayColumnOptions,\n InternalColumnOptions,\n NestedKeyOf,\n} from '../types';\n\nexport function findColumn<\n TData extends Record<string, unknown>,\n TCol extends { field: NestedKeyOf<TData> },\n>(columns: TCol[], field: NestedKeyOf<TData>) {\n return columns.find(c => c.field === field);\n}\n\nexport function isInternalColumn<T>(\n col: ColumnOptions<T> | undefined | null,\n): col is InternalColumnOptions<T> {\n return col?.role === 'internal';\n}\n\nexport function isDisplayColumn<T>(\n col: ColumnOptions<T> | undefined | null,\n): col is DisplayColumnOptions<T> {\n return col?.role !== 'internal';\n}\n\nexport function createState<T>(\n field: NestedKeyOf<T>,\n defaults?: Partial<ColumnState<T>>,\n): ColumnState<T> {\n return {\n field,\n visible: defaults?.visible ?? true,\n width: defaults?.width ?? null,\n sort: defaults?.sort ? { ...defaults.sort } : null,\n };\n}\n\nexport function getColumnStateChanges<T>(\n oldState: ColumnState<T> | undefined,\n newState: ColumnState<T>,\n): (keyof ColumnState<T>)[] {\n if (oldState && oldState.field !== newState.field) {\n throw Error(\n `attempting to compare states for different fields: ${oldState.field}, ${newState.field}`,\n );\n }\n\n const changes: (keyof ColumnState<T>)[] = [];\n if (oldState?.visible !== newState.visible) {\n changes.push('visible');\n }\n\n if (oldState?.width !== newState.width) {\n changes.push('width');\n }\n\n if (\n oldState?.sort !== newState.sort ||\n oldState.sort?.order !== newState.sort?.order ||\n oldState.sort?.priority !== newState.sort?.priority\n ) {\n changes.push('sort');\n }\n\n return changes;\n}\n","import { RowId, RowSelectionMethod } from '../types';\n\nexport function isRowIdType(value: unknown): value is RowId {\n return typeof value === 'string' || typeof value === 'number';\n}\n\nexport function isRowSelectionMethod(\n value: string | null,\n): value is RowSelectionMethod {\n return value === null || value === 'multi' || value === 'single';\n}\n\nfunction isValidKey<K extends string>(\n key: string,\n obj: Record<K, unknown>,\n): key is K {\n return key in obj;\n}\n\n/**\n * Get a value from an object based on a path.\n * @param obj - The object to get the value from\n * @param path - The path of the value\n * @returns The value found at the given path\n */\nexport function getNestedValue(obj: object, path: string): unknown {\n const keys = path.split('.');\n\n let current = obj;\n\n for (const key of keys) {\n if (current && isValidKey(key, current)) {\n current = current[key];\n } else {\n return undefined;\n }\n }\n\n return current;\n}\n\nexport function setNestedValue(obj: object, path: string, value: unknown) {\n const keys = path.split('.');\n const finalProp = keys.at(-1);\n if (!finalProp) {\n throw new Error('Cannot set nested value with empty path');\n }\n\n let current = obj;\n for (const key of keys.slice(0, -1)) {\n if (!isValidKey(key, current)) {\n const newObj = {};\n Object.assign(current, { [key]: newObj });\n current = newObj;\n } else {\n current = current[key];\n }\n }\n\n Object.assign(current, { [finalProp]: value });\n}\n","export const createRegexTokenizer = (exp: string = '\\\\S+') => {\n const regex = new RegExp(`\"[^\"]*\"|${exp}`, 'g');\n\n return (value: string) => {\n // Find all matches, which will include the quotes\n const matches = value.match(regex) || [];\n\n // Clean up the results by removing the surrounding quotes\n return matches.map(token => {\n token = token.toLocaleLowerCase().trim();\n if (token.startsWith('\"') && token.endsWith('\"')) {\n return { value: token.slice(1, -1), quoted: true };\n }\n return { value: token, quoted: false };\n });\n };\n};\n\nexport const whitespaceTokenizer = createRegexTokenizer();\n","export class TypedEventTarget<\n TEventMap extends Record<string, Event>,\n> extends EventTarget {\n public override addEventListener<K extends keyof TEventMap>(\n type: K,\n listener: (this: TEventMap, ev: TEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n public override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n public override addEventListener(\n type: string,\n listener: unknown,\n options?: boolean | AddEventListenerOptions,\n ) {\n super.addEventListener(\n type,\n listener as EventListenerOrEventListenerObject,\n options,\n );\n }\n\n public override removeEventListener<K extends keyof TEventMap>(\n type: K,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ): void;\n\n public override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ): void {\n super.removeEventListener(type, listener, options);\n }\n\n public override dispatchEvent<K extends keyof TEventMap>(\n event: TEventMap[K],\n ): boolean {\n return super.dispatchEvent(event);\n }\n}\n","import { html, TemplateResult } from 'lit';\n\n/**\n * Highlights sections of a string based on index ranges.\n * @param text - The original string to render.\n * @param ranges - An array of [start, end] tuples representing matches.\n * @returns A Lit TemplateResult with <mark> tags, or the original string if no ranges exist.\n */\nexport function highlightText(\n text: string,\n ranges: [number, number][],\n): TemplateResult | string {\n if (!text || !ranges || ranges.length === 0) {\n return text;\n }\n\n // 1. Sort ranges by start position to process linearly\n const sortedRanges = [...ranges].sort((a, b) => a[0] - b[0]);\n\n // 2. Merge overlapping ranges\n // Example: [[0, 5], [2, 6]] becomes [[0, 6]]\n const mergedRanges: [number, number][] = [];\n let currentRange = sortedRanges[0];\n\n for (let i = 1; i < sortedRanges.length; i++) {\n const nextRange = sortedRanges[i];\n\n if (nextRange[0] < currentRange[1]) {\n // Overlap detected: Extend the current end if needed\n currentRange[1] = Math.max(currentRange[1], nextRange[1]);\n } else {\n // No overlap: Push current and start a new one\n mergedRanges.push(currentRange);\n currentRange = nextRange;\n }\n }\n mergedRanges.push(currentRange);\n\n // 3. Slice the string\n const result: (string | TemplateResult)[] = [];\n let lastIndex = 0;\n\n for (const [start, end] of mergedRanges) {\n // Clamp values to prevent out-of-bounds errors\n const safeStart = Math.max(0, Math.min(start, text.length));\n const safeEnd = Math.max(0, Math.min(end, text.length));\n\n // Append non-highlighted text before the match\n if (safeStart > lastIndex) {\n result.push(text.slice(lastIndex, safeStart));\n }\n\n // Append highlighted text\n // We use the 'mark' tag, but you can change this to a span with a class\n result.push(\n html`<mark class=\"highlight\">${text.slice(safeStart, safeEnd)}</mark>`,\n );\n\n lastIndex = safeEnd;\n }\n\n // 4. Append any remaining text after the last match\n if (lastIndex < text.length) {\n result.push(text.slice(lastIndex));\n }\n\n return html`${result}`;\n}\n\n/*\n * Converts a string to a human-readable format.\n * - Replaces underscores with spaces\n * - Inserts spaces before uppercase letters (for camelCase)\n * - Capitalizes the first letter of each word\n *\n * @param {string} str - The input string to convert.\n * @returns {string} - The converted human-readable string.\n */\nexport const toHumanReadable = (str: string) => {\n return (\n str\n // Replace underscores with spaces\n .replace(/_/g, ' ')\n // Insert spaces before uppercase letters (for camelCase)\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Capitalize the first letter of each word\n .replace(/\\b\\w/g, char => char.toUpperCase())\n );\n};\n","import type {\n ColumnOptions,\n ColumnState,\n DisplayColumnOptions,\n ExportOptions,\n NestedKeyOf,\n RestorableColumnState,\n RestorableTableState,\n RowId,\n RowPartsCallback,\n SortOrder,\n TableState,\n UnspecifiedRecord,\n} from '../types';\n\nimport {\n getColumnStateChanges,\n getNestedValue,\n isDisplayColumn,\n} from '../utils';\n\nimport { highlightText, toHumanReadable } from './utils';\n\nimport {\n YatlColumnReorderRequest,\n YatlColumnSortRequest,\n YatlRowClickEvent,\n YatlRowSelectRequest,\n} from '../events';\n\nimport { html, LitElement, nothing, TemplateResult } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport '@lit-labs/virtualizer';\nimport { LitVirtualizer } from '@lit-labs/virtualizer';\nimport { YatlEvent } from '../events';\nimport {\n ControllerEventMap,\n YatlTableController,\n} from '../table-controller/table-controller';\nimport styles from './table.styles';\n\n// #region --- Constants ---\n\n// #endregion\n\n/**\n * A virtualized data table capable of handling complex sorting, filtering, and tokenized searching.\n *\n * @element yatl-table\n * @summary A high-performance grid engine for rugged environments.\n *\n * @fires yatl-row-click - Fired when a user clicks a row.\n * @fires yatl-row-select-request - Fired before the row selection changes. Cancellable\n * @fires yatl-row-select - Fired when the row selection changes.\n * @fires yatl-column-sort-request - Fired before a column sort order changes. Cancellable.\n * @fires yatl-column-sort - Fired when a column sort order changes.\n * @fires yatl-column-toggle - Fired when a column's visibility changes.\n * @fires yatl-column-resize - Fired after a column has been resized by the user.\n * @fires yatl-column-reorder-request - Fired when the user drops a column into a new position. Cancellable.\n * @fires yatl-column-reorder - Fired after the column order changes.\n * @fires yatl-table-search - Fired when the search query is updated.\n * @fires yatl-table-view-change - Fired when the visible slice of data changes due to sorting, filtering, or data updates. Payload contains the processed rows.\n * @fires yatl-table-state-change - Fired when any persistable state (width, order, sort, query) changes. Used for syncing with local storage.\n */\n@customElement('yatl-table')\nexport class YatlTable<\n T extends object = UnspecifiedRecord,\n> extends LitElement {\n public static override styles = [styles];\n\n @query('.table')\n private tableElement!: HTMLElement;\n @query('lit-virtualizer')\n private virtualizer?: LitVirtualizer;\n\n // #region --- State Data ---\n\n // Property data\n\n private resizeState: {\n active: boolean;\n startX: number;\n startWidth: number;\n columnIndex: number;\n columnField: NestedKeyOf<T>;\n currentWidths: string[];\n } | null = null;\n\n // Column drag & drop state\n private dragColumn: NestedKeyOf<T> | null = null;\n\n @state() private useYatlUi = false;\n\n // #endregion\n\n // #region --- Properties ---\n\n private _controller = new YatlTableController<T>(this);\n @property({ attribute: false })\n public get controller() {\n return this._controller;\n }\n\n public set controller(controller) {\n if (this._controller === controller) {\n return;\n }\n\n const oldController = this._controller;\n if (this.isConnected) {\n this.removeControllerListeners(oldController);\n this.addControllerListeners(controller);\n }\n\n oldController.detach(this);\n controller.attach(this);\n\n this._controller = controller;\n this.requestUpdate('controller', oldController);\n }\n\n @property({ type: Boolean, reflect: true })\n public striped = true;\n\n /**\n * Default sortability for all columns.\n * Can be overridden by setting `sortable` on the specific column definition.\n * * **NOTE:** Changing this will not clear sorted column states.\n * @default false\n */\n @property({ type: Boolean, attribute: 'sortable' })\n public sortable = true;\n\n /**\n * Default resizability for all columns.\n * Can be overridden by setting `resizable` on the specific column definition.\n * * **NOTE:** Changing this will not clear current column widths.\n * @default false\n */\n @property({ type: Boolean, attribute: 'resizable' })\n public resizable = true;\n\n /**\n * Enables virtual scrolling for the table.\n * When enabled, only the visible rows are rendered to the DOM, significantly improving\n * performance for large datasets (1000+ rows).\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-virtual-scroll' })\n public enableVirtualScroll = false;\n\n /**\n * When enabled, text matching the current search query will be wrapped in `<mark>` tags.\n * This applies to all visible cells that contain the search term.\n * This does NOT apply to content rendered by the user such as the ColumnOptions.render callback.\n * @default true\n */\n @property({ type: Boolean, attribute: 'enable-search-highlight' })\n public enableSearchHighlight = true;\n\n /**\n * Enables tokenized search behavior.\n * When enabled, the search query is split into individual tokens using the\n * `searchTokenizer` function (defaults to splitting on whitespace).\n * A row is considered a match if **ANY** of the tokens appear in the searchable fields.\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-search-tokenization' })\n public get enableSearchTokenization() {\n return this.controller.enableSearchTokenization;\n }\n\n public set enableSearchTokenization(enable) {\n const oldValue = this.enableSearchTokenization;\n if (oldValue === enable) {\n return;\n }\n\n this.controller.enableSearchTokenization = enable;\n this.requestUpdate('enableSearchTokenization', oldValue);\n }\n\n /**\n * Enables weighted relevance scoring for search results.\n * When enabled, exact matches and prefix matches are ranked higher than substring matches.\n * Rows are sorted by their relevance score descending.\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-search-scoring' })\n public get enableSearchScoring() {\n return this.controller.enableSearchScoring;\n }\n\n public set enableSearchScoring(enable) {\n const oldValue = this.enableSearchScoring;\n if (oldValue === enable) {\n return;\n }\n\n this.controller.enableSearchScoring = enable;\n this.requestUpdate('enableSearchScoring', oldValue);\n }\n\n /**\n * Allows users to reorder columns by dragging and dropping headers.\n * @default true\n */\n @property({ type: Boolean, attribute: 'enable-column-reorder' })\n public enableColumnReorder = true;\n\n /**\n * Shows a column to the left of each row with its row number.\n */\n @property({ type: Boolean })\n public enableRowNumberColumn = true;\n\n /**\n * Shows the built-in footer row which displays the current record count.\n * The footer content can be customized using the `slot=\"footer\"` element.\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-footer' })\n public enableFooter = true;\n\n /**\n * The string to display in a cell when the data value is `null` or `undefined`.\n * @default \"-\"\n */\n @property({ type: String, attribute: 'null-value-placeholder' })\n public nullValuePlaceholder = '-';\n\n /**\n * The message displayed when the `data` array is empty.\n * @default \"No records to display\"\n */\n @property({ type: String, attribute: 'empty-message' })\n public emptyMessage = 'No records to display';\n\n /**\n * The message displayed when `data` exists but the current search/filter\n * results in zero visible rows.\n * @default \"No matching records found\"\n */\n @property({ type: String, attribute: 'no-results-message' })\n public noResultsMessage = 'No matching records found';\n\n /**\n * The definitions for the columns to be rendered.\n * This defines the field mapping, titles, sortability, and other static options.\n */\n @property({ attribute: false })\n public get columns() {\n return this.controller.columns;\n }\n\n public set columns(columns) {\n const oldValue = this.columns;\n if (oldValue === columns) {\n return;\n }\n\n for (const column of columns) {\n if (isDisplayColumn(column) && column.title === undefined) {\n column.title = toHumanReadable(column.field);\n }\n }\n\n this.controller.columns = columns;\n this.requestUpdate('columns', oldValue);\n }\n\n /**\n * Gets a list of columns with the display role\n * **This will always be ordered the same as the visual column order**\n */\n public get displayColumns() {\n return this.controller.displayColumns;\n }\n\n @property({ attribute: false })\n public get columnStates() {\n return this.controller.columnStates;\n }\n\n public set columnStates(states) {\n const oldValue = this.columnStates;\n\n let changed = false;\n for (const state of states) {\n const oldState = this.getColumnState(state.field);\n const stateChanges = getColumnStateChanges(oldState, state);\n if (stateChanges.length) {\n changed = true;\n break;\n }\n }\n\n if (!changed) {\n return;\n }\n\n this.controller.columnStates = states;\n this.requestUpdate('columnStates', oldValue);\n }\n\n /**\n * The current text string used to filter the table data.\n * Setting this property triggers a new search and render cycle.\n */\n @property({ type: String, attribute: 'search-query' })\n public get searchQuery() {\n return this.controller.searchQuery;\n }\n\n public set searchQuery(query) {\n const oldValue = this.searchQuery;\n if (oldValue === query) {\n return;\n }\n\n this.controller.searchQuery = query;\n this.requestUpdate('searchQuery', oldValue);\n }\n\n /**\n * A function that splits the search query into tokens.\n * Only used if `enableSearchTokenization` is true.\n * @default whitespaceTokenizer\n */\n @property({ attribute: false })\n public get searchTokenizer() {\n return this.controller.searchTokenizer;\n }\n\n public set searchTokenizer(tokenizer) {\n const oldValue = this.searchTokenizer;\n if (oldValue === tokenizer) {\n return;\n }\n\n this.controller.searchTokenizer = tokenizer;\n this.requestUpdate('searchTokenizer', oldValue);\n }\n\n /**\n * An optional set of criteria to filter the visible rows.\n * This runs **before** the global search query is applied.\n * * You can provide:\n * 1. A **Partial Object**: matches rows where specific keys equal specific values (AND logic).\n * 2. A **Callback Function**: returns `true` to keep the row, `false` to hide it.\n * * @example\n * // 1. Object Syntax (Simple Exact Match)\n * // Shows rows where status is 'active' AND role is 'admin'\n * table.filters = { status: 'active', role: 'admin' };\n * * @example\n * // 2. Callback Syntax (Complex Logic)\n * // Shows rows where age is over 21 OR they are a VIP\n * table.filters = (row) => row.age > 21 || row.isVip;\n */\n @property({ attribute: false })\n public get filters() {\n return this.controller.filters;\n }\n\n public set filters(filters) {\n const oldValue = this.filters;\n if (oldValue === filters) {\n return;\n }\n\n this.controller.filters = filters;\n this.requestUpdate('filters', oldValue);\n }\n\n /**\n * A callback function to conditionally apply CSS parts to table rows.\n */\n @property({ attribute: false })\n public rowParts: RowPartsCallback<T> | null = null;\n\n /**\n * The row selection method to use.\n * * single - Only a single row can be selected at a time\n * * multi - Multiple rows can be selected at a time\n * * null - Disable row selection\n */\n @property({ type: String })\n public get rowSelectionMethod() {\n return this.controller.rowSelectionMethod;\n }\n\n public set rowSelectionMethod(selection) {\n const oldValue = this.rowSelectionMethod;\n if (oldValue === selection) {\n return;\n }\n\n this.controller.rowSelectionMethod = selection;\n this.requestUpdate('rowSelectionMethod', oldValue);\n }\n\n /**\n * List of currently selected row indexes.\n * * **NOTE**: These indexes are based off the of\n * the original data array index, *not* the filtered data.\n */\n @property({ attribute: false })\n public get selectedRowIds() {\n return this.controller.selectedRowIds;\n }\n\n public set selectedRowIds(rows) {\n const oldValue = new Set(this.selectedRowIds);\n if (oldValue.size === rows.length && rows.every(r => oldValue.has(r))) {\n return;\n }\n\n this.controller.selectedRowIds = rows;\n this.requestUpdate('selectedRows', [...oldValue]);\n }\n\n /**\n * Configuration options for automatically saving and restoring table state\n * (column width, order, visibility, etc.) to browser storage.\n */\n @property({ type: Object, attribute: 'storage-options' })\n public get storageOptions() {\n return this.controller.storageOptions;\n }\n\n public set storageOptions(options) {\n const oldValue = this.storageOptions;\n // TODO: Check if anything changed\n this.controller.storageOptions = options;\n this.requestUpdate('storageOptions', oldValue);\n }\n\n @property({ attribute: false })\n public get rowIdCallback() {\n return this.controller.rowIdCallback;\n }\n\n public set rowIdCallback(callback) {\n const oldValue = this.rowIdCallback;\n if (oldValue === callback) {\n return;\n }\n\n this.controller.rowIdCallback = callback;\n this.requestUpdate('rowIdCallback', oldValue);\n }\n\n /**\n * The array of data objects to be displayed.\n * Objects must satisfy the `WeakKey` constraint (objects only, no primitives).\n */\n @property({ attribute: false })\n public get data() {\n return this.controller.data;\n }\n\n public set data(value: T[]) {\n const oldValue = this.data;\n this.controller.data = value;\n this.requestUpdate('data', oldValue);\n }\n\n public get filteredData() {\n return this.controller.filteredData;\n }\n\n public get dataUpdateTimestamp() {\n return this.controller.dataUpdateTimestamp;\n }\n\n // #endregion\n\n // #region --- Public Methods ---\n\n public getColumn(field: NestedKeyOf<T>) {\n return this.controller.getColumn(field);\n }\n\n public getDisplayColumn(field: NestedKeyOf<T>) {\n const column = this.getColumn(field);\n if (column && isDisplayColumn(column)) {\n return column;\n }\n }\n\n /**\n * Gets a copy of the current state of the table.\n */\n public getTableState(): TableState<T> {\n return this.controller.getTableState();\n }\n\n /**\n * Restores the table to the provided state.\n * @param state - The state to restore the table to.\n */\n public updateTableState(state: RestorableTableState<T>) {\n return this.controller.updateTableState(state);\n }\n\n public getColumnState(field: NestedKeyOf<T>) {\n return this.controller.getColumnState(field);\n }\n\n public updateColumnState(\n field: NestedKeyOf<T>,\n state: RestorableColumnState<T>,\n ) {\n return this.controller.updateColumnState(field, state);\n }\n\n /**\n * Sorts the table by a specified column and order.\n * If `order` is `null`, the sort on this column is removed.\n * @param field - The field name of the column to sort by.\n * @param order - The sort order: 'asc', 'desc', or `null` to remove sorting for this column.\n * @param clear - Clear all other sorting\n */\n public sort(\n field: NestedKeyOf<T>,\n order: SortOrder | null,\n clear: boolean = true,\n ) {\n return this.controller.sort(field, order, clear);\n }\n\n /**\n * Toggles the visibility of hte specified column\n * @param field - The field name of the column to toggle.\n * @param visible - Optionally force the visibility state.\n */\n public toggleColumnVisibility(field: NestedKeyOf<T>, visible?: boolean) {\n return this.controller.toggleColumnVisibility(field, visible);\n }\n\n /**\n * Shows the specified column\n * @param field - The field name of the column to show.\n */\n public showColumn(field: NestedKeyOf<T>) {\n return this.controller.showColumn(field);\n }\n\n /**\n * Hides the specified column\n * @param field - The field name of the column to hide.\n */\n public hideColumn(field: NestedKeyOf<T>) {\n return this.controller.hideColumn(field);\n }\n\n /**\n * Moves a column to a new position\n * @param field - The column to move\n * @param newPosition The index or field of the column to move it to.\n * @returns\n */\n public moveColumn(\n field: NestedKeyOf<T>,\n newPosition: number | NestedKeyOf<T>,\n ) {\n return this.controller.moveColumn(field, newPosition);\n }\n\n public resizeColumn(field: NestedKeyOf<T>, width: number | null) {\n return this.controller.resizeColumn(field, width);\n }\n\n public isRowSelected(row: T) {\n return this.controller.isRowSelected(row);\n }\n\n /**\n * Toggles the selection state of a specific row.\n */\n public toggleRowSelection(row: T, state?: boolean) {\n return this.controller.toggleRowSelection(row, state);\n }\n\n /**\n * Selects a specific row.\n */\n public selectRow(row: T) {\n return this.controller.selectRow(row);\n }\n\n /**\n * Deselects a specific row.\n */\n public deselectRow(row: T) {\n return this.controller.deselectRow(row);\n }\n\n /**\n * Selects all currently visible rows (for \"Select All\" checkbox).\n */\n public selectAll() {\n return this.controller.selectAll();\n }\n\n /**\n * Clears all selection.\n */\n public deselectAll() {\n return this.controller.deselectAll();\n }\n\n /**\n * Export the current visible table data to a CSV file.\n * @param filename - The name of the file to save.\n * @param options - Options for configuring what should be exported.\n */\n public export(\n filename: string,\n options: ExportOptions = {\n includeAllRows: false,\n includeHiddenColumns: false,\n includeInternalColumns: false,\n },\n ) {\n const blob = this.controller.export(options);\n const a = document.createElement('a');\n a.style.display = 'none';\n a.href = URL.createObjectURL(blob);\n a.download = `${filename}.csv`;\n document.body.append(a);\n a.click();\n a.remove();\n }\n\n public scrollToRow(row: T) {\n const index = this.data.findIndex(v => v === row);\n if (typeof index === 'number') {\n return this.scrollToOriginalIndex(index);\n } else {\n throw new Error('Row not in table');\n }\n }\n\n /**\n * Scrolls the table to bring the row at the specified original index into view.\n * @param index - The original index of the row (from the initial dataset).\n */\n public scrollToOriginalIndex(index: number) {\n const rowData = this.data[index];\n if (rowData) {\n const filteredIndex = this.filteredData.indexOf(rowData);\n if (filteredIndex >= 0) {\n return this.scrollToFilteredIndex(filteredIndex);\n } else {\n throw new Error('Cannot scroll to filtered out row');\n }\n } else {\n throw new RangeError(`Row index ${index} out of range`);\n }\n }\n\n public async scrollToFilteredIndex(index: number) {\n // FIXME: Scrolling to an index using lit-virtualizer is buggy.\n // It usually stops short of the requested index.\n // The amount it stops short seems to be proportinal to how far away the index is.\n // Scrolling without VS works but since I use sticky headers, it seems to be one row off.\n\n const rowData = this.filteredData[index];\n if (!rowData) {\n throw new RangeError(`Row index ${index} out of range`);\n }\n\n await this.updateComplete;\n\n // TODO: Should I check if virtual scroll is enabled\n // or just rely on the appropriate elements existing?\n if (this.virtualizer) {\n this.virtualizer.element(index)?.scrollIntoView({\n block: 'start',\n behavior: 'instant',\n });\n } else {\n const row = this.tableElement.querySelector(\n `.row[data-filtered-index=\"${index}\"]`,\n );\n row?.scrollIntoView({\n block: 'start',\n behavior: 'smooth',\n });\n }\n }\n\n public async scrollToPx(px: number) {\n // FIXME: This doesn't work with lit-virtualizer at all.\n\n await this.updateComplete;\n\n if (this.virtualizer) {\n this.virtualizer.scrollTop = px;\n } else {\n this.tableElement.scrollTop = px;\n }\n }\n\n /**\n * Gets the row associated with the provided ID.\n * @param id - The ID of the row to get\n * @returns\n */\n public getRow(id: RowId) {\n return this.controller.getRow(id);\n }\n\n /**\n * Finds the first row where {@link field} matches {@link value}\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The found row, or undefined if no match is found.\n */\n public findRow(field: NestedKeyOf<T>, value: unknown) {\n return this.controller.findRow(field, value);\n }\n\n /**\n * Finds the original index of the first row where the specified field matches the given value.\n * This searches through the original, unfiltered dataset.\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The original index of the found row, or -1 if no match is found.\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow({description: \"Updated description\"}, index);\n * }\n * ```\n */\n public findRowIndex(field: NestedKeyOf<T>, value: unknown) {\n return this.controller.findRowIndex(field, value);\n }\n\n public updateRow(rowId: RowId, data: Partial<T>) {\n return this.controller.updateRow(rowId, data);\n }\n\n /**\n * Updates the data of a row at a specific original index.\n * @param index - The original index of the row to update.\n * @param data - An object containing the new data to assign to the row. Existing fields will be updated, and new fields will be added.\n *\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow(index, {description: \"Updated description\"});\n * }\n * ```\n */\n public updateRowAtIndex(index: number, data: Partial<T>) {\n return this.controller.updateRowAtIndex(index, data);\n }\n\n /**\n * Deletes the row with the matching ID.\n * @param rowIds - The IDs rows to delete\n */\n public deleteRow(...rowIds: RowId[]) {\n return this.controller.deleteRow(...rowIds);\n }\n\n /**\n * Deletes a row at a specific original index from the table.\n * @param index - The original index of the row to delete.\n */\n public deleteRowAtIndex(index: number) {\n return this.controller.deleteRowAtIndex(index);\n }\n\n // #endregion\n\n // #region Render Methods\n\n protected renderColumnSortIcon(\n column: DisplayColumnOptions<T>,\n state: ColumnState<T>,\n ) {\n return (column.sortable ?? this.sortable)\n ? html`<div\n part=\"header-sort-icon\"\n class=${classMap({\n 'sort-icon': true,\n ascending: state.sort?.order === 'asc',\n descending: state.sort?.order === 'desc',\n })}\n ></div>`\n : nothing;\n }\n\n protected renderColumnResizer(\n column: DisplayColumnOptions<T>,\n _state: ColumnState<T>,\n ) {\n return (column.resizable ?? this.resizable)\n ? html`\n <div\n part=\"header-resizer\"\n class=\"resizer\"\n @click=${(event: MouseEvent) => event.stopPropagation()}\n @mousedown=${(event: MouseEvent) =>\n this.handleResizeMouseDown(event, column.field)}\n ></div>\n `\n : nothing;\n }\n\n protected renderHeaderCell(column: DisplayColumnOptions<T>) {\n if (!column) {\n return nothing;\n }\n\n const state = this.getColumnState(column.field);\n const title = column.title ?? column.field;\n\n let ariaSort: 'none' | 'ascending' | 'descending' = 'none';\n if (state.sort?.order === 'asc') ariaSort = 'ascending';\n if (state.sort?.order === 'desc') ariaSort = 'descending';\n\n const role = state.visible ? 'columnheader' : undefined;\n const hidden = state.visible ? false : undefined;\n\n const classes = {\n cell: true,\n sortable: column.sortable ?? this.sortable,\n };\n\n return this.renderCellWrapper(html`\n <div\n role=${ifDefined(role)}\n aria-hidden=${ifDefined(hidden)}\n aria-sort=${ariaSort}\n aria-label=${title}\n part=\"cell header-cell\"\n class=${classMap(classes)}\n draggable=${ifDefined(this.enableColumnReorder ? true : undefined)}\n data-field=${column.field}\n @dragstart=${(event: DragEvent) =>\n this.handleDragColumnStart(event, column.field)}\n @dragenter=${this.handleDragColumnEnter}\n @dragleave=${this.handleDragColumnLeave}\n @dragover=${this.handleDragColumnOver}\n @drop=${(event: DragEvent) =>\n this.handleDragColumnDrop(event, column.field)}\n @dragend=${this.handleDragColumnEnd}\n @click=${(event: MouseEvent) => this.handleHeaderClicked(event, column)}\n >\n <div class=\"header-content\">\n <span class=\"header-title truncate\" part=\"header-title\">\n ${title}\n </span>\n ${this.renderColumnSortIcon(column, state)}\n </div>\n ${this.renderColumnResizer(column, state)}\n <div part=\"drop-indicator\" class=\"drop-indicator\"></div>\n </div>\n `);\n }\n\n protected renderRowNumberHeader() {\n return this.renderCellWrapper(\n html`<div part=\"cell-index\" class=\"cell-index\"></div>`,\n );\n }\n\n protected renderSelectionHeader() {\n return this.renderCellWrapper(\n html`<div part=\"cell-selector\" class=\"cell-selector\"></div>`,\n );\n }\n\n protected renderHeader() {\n const classes = {\n header: true,\n reorderable: this.enableColumnReorder,\n };\n return html`\n <div role=\"rowgroup\" part=\"header\" class=${classMap(classes)}>\n <div role=\"row\" class=\"row header-row\" part=\"row header-row\">\n ${this.renderRowNumberHeader()} ${this.renderSelectionHeader()}\n ${this.displayColumns.map(column => this.renderHeaderCell(column))}\n </div>\n </div>\n `;\n }\n\n protected renderCellContents(\n value: unknown,\n column: DisplayColumnOptions<T>,\n row: T,\n ) {\n if (column.cellRenderer) {\n return column.cellRenderer(value, column.field, row);\n }\n\n if (value == null) {\n return this.nullValuePlaceholder;\n }\n\n const indices = this.controller.getRowHighlightIndicies(row);\n\n return this.enableSearchHighlight && indices\n ? highlightText(String(value), indices[column.field])\n : value;\n }\n\n protected renderCell(column: DisplayColumnOptions<T>, row: T) {\n let value = getNestedValue(row, column.field);\n // Get the user parts from the raw value\n // before we call the value formatter.\n let userParts = column.cellParts?.call(this, value, column.field, row);\n if (Array.isArray(userParts)) {\n userParts = userParts.join(' ');\n }\n\n if (typeof column.valueFormatter === 'function') {\n value = column.valueFormatter(value, row);\n }\n\n return this.renderCellWrapper(html`\n <div\n role=\"cell\"\n part=\"cell body-cell cell-${column.field} ${userParts}\"\n data-field=${column.field}\n class=\"cell\"\n title=${ifDefined(value ? String(value) : undefined)}\n @click=${(event: MouseEvent) =>\n this.handleCellClick(event, row, column.field)}\n >\n <span class=\"truncate\">\n ${this.renderCellContents(value, column, row)}\n </span>\n </div>\n `);\n }\n\n protected renderCheckbox(row: T, selected: boolean) {\n return this.useYatlUi\n ? html`<yatl-checkbox\n part=\"row-checkbox\"\n class=\"row-checkbox\"\n .checked=${selected}\n @change=${(event: Event) =>\n this.handleRowSelectionClicked(event, row)}\n ></yatl-checkbox>`\n : html`<input\n part=\"row-checkbox\"\n class=\"row-checkbox\"\n type=\"checkbox\"\n .checked=${selected}\n @change=${(event: Event) =>\n this.handleRowSelectionClicked(event, row)}\n />`;\n }\n\n protected renderRowSelectorCell(row: T, selected: boolean) {\n return this.renderCellWrapper(html`\n <div part=\"cell body-cell\" class=\"cell body-cell\">\n <div part=\"row-selector-cell\" class=\"row-selector-cell\">\n <label> ${this.renderCheckbox(row, selected)} </label>\n </div>\n </div>\n `);\n }\n\n protected renderRowNumberCell(rowNumber: number) {\n return this.renderCellWrapper(html`\n <div part=\"cell body-cell\" class=\"cell body-cell\">\n <div part=\"row-number-cell\" class=\"row-number-cell\">${rowNumber}</div>\n </div>\n `);\n }\n\n protected renderRow(row: T, renderIndex: number) {\n const selected = this.isRowSelected(row);\n let userParts = this.rowParts?.(row) ?? '';\n if (Array.isArray(userParts)) {\n userParts = userParts.join(' ');\n }\n\n const classes = { row: true, selected };\n const rowIndex = renderIndex + 1;\n\n return html`\n <div\n role=\"row\"\n aria-rowindex=${rowIndex}\n aria-selected=${selected ? 'true' : 'false'}\n part=${'row ' + userParts}\n class=${classMap(classes)}\n >\n ${this.renderRowNumberCell(rowIndex)}\n ${this.renderRowSelectorCell(row, selected)}\n ${this.displayColumns.map(column => this.renderCell(column, row))}\n </div>\n `;\n }\n\n protected renderBodyContents() {\n if (!this.hasVisibleColumn()) {\n return html`\n <div part=\"message\" class=\"message\">No visible columns.</div>\n `;\n }\n\n if (this.data.length === 0) {\n return html`\n <div part=\"message\" class=\"message\">${this.emptyMessage}</div>\n `;\n }\n if (this.filteredData.length === 0) {\n return html`\n <div part=\"message\" class=\"message\">${this.noResultsMessage}</div>\n `;\n }\n\n if (this.enableVirtualScroll) {\n return html`\n <lit-virtualizer\n .items=${this.filteredData}\n .renderItem=${(item: T, index: number) =>\n this.renderRow(item, index) as TemplateResult}\n >\n </lit-virtualizer>\n `;\n }\n\n return html`\n ${repeat(\n this.filteredData,\n item => this.controller.getRowId(item),\n (item, index) => this.renderRow(item, index),\n )}\n `;\n }\n\n protected renderFooter() {\n if (!this.enableFooter) {\n return nothing;\n }\n\n const total = this.data.length;\n const filtered = this.filteredData.length;\n\n const fmt = new Intl.NumberFormat(undefined);\n const totalStr = fmt.format(total);\n const filteredStr = fmt.format(filtered);\n\n const rowCountText =\n total !== filtered\n ? `Showing ${filteredStr} of ${totalStr} records`\n : `Total records: ${totalStr}`;\n\n const formatter = Intl.DateTimeFormat(undefined, {\n dateStyle: 'short',\n timeStyle: 'short',\n });\n\n const lastUpdateText = this.dataUpdateTimestamp\n ? formatter.format(this.dataUpdateTimestamp)\n : 'Never';\n\n return html`\n <div part=\"footer\" class=\"footer\">\n <slot name=\"footer\">\n <span part=\"row-count\">${rowCountText}</span>\n <span part=\"timestamp\">${lastUpdateText}</span>\n </slot>\n </div>\n `;\n }\n\n protected override render() {\n const gridTemplate = this.getGridWidths().join(' ');\n const style = {\n '--grid-template': gridTemplate,\n };\n\n /*\n * DO NOT USE THE DEFAULT SLOT!\n * It causes whitespace like new lines in the HTML to override the body.\n */\n return html`\n <div\n role=\"table\"\n aria-label=\"Data Table\"\n aria-rowcount=${this.filteredData.length}\n part=\"table\"\n class=\"table\"\n style=${styleMap(style)}\n >\n <div class=\"scroller\">\n ${this.renderHeader()}\n <div class=\"body\" role=\"rowgroup\">\n <slot name=\"body\">${this.renderBodyContents()}</slot>\n </div>\n </div>\n ${this.renderFooter()}\n </div>\n `;\n }\n\n private renderCellWrapper(content: TemplateResult | typeof nothing) {\n return html` <div class=\"cell-wrapper\">${content}</div> `;\n }\n\n // #endregion\n // #region --- Lifecycle Methods ---\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.addControllerListeners(this.controller);\n\n // We want to use the checkbox from yatl-ui if it is available.\n // If it gets defined, rerender with it.\n if (!this.useYatlUi) {\n customElements.whenDefined('yatl-checkbox').then(() => {\n this.useYatlUi = true;\n });\n }\n }\n\n public override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeControllerListeners(this.controller);\n\n // Clean up just in case\n window.addEventListener('mousemove', this.handleResizeMouseMove);\n window.addEventListener('mouseup', this.handleResizeMouseUp);\n }\n\n // #endregion\n // #region Utilities\n\n private readonly eventNames: (keyof ControllerEventMap)[] = [\n 'yatl-column-reorder',\n 'yatl-column-resize',\n 'yatl-column-sort',\n 'yatl-column-toggle',\n 'yatl-row-select',\n 'yatl-table-search',\n 'yatl-table-state-change',\n 'yatl-table-view-change',\n ];\n\n private addControllerListeners(controller: YatlTableController<T>) {\n for (const name of this.eventNames) {\n controller.addEventListener(name, this.redispatchControllerEvent);\n }\n }\n\n private removeControllerListeners(controller: YatlTableController<T>) {\n for (const name of this.eventNames) {\n controller.removeEventListener(name, this.redispatchControllerEvent);\n }\n }\n\n private redispatchControllerEvent = (event: Event) => {\n if (event instanceof YatlEvent) {\n this.dispatchEvent(event.clone());\n }\n };\n\n private hasVisibleColumn() {\n return (\n this.displayColumns\n .map(column => this.getColumnState(column.field))\n .filter(state => state.visible).length > 0\n );\n }\n\n /**\n * Gets the width of each column in the\n * order they will appear in the grid.\n */\n private getGridWidths() {\n const widths: string[] = [];\n\n if (this.enableRowNumberColumn) {\n widths.push('var(--yatl-row-number-column-width, 48px)');\n } else {\n widths.push('0');\n }\n\n if (this.rowSelectionMethod) {\n widths.push('var(--yatl-row-selector-column-width, 48px)');\n } else {\n widths.push('0');\n }\n\n for (const column of this.displayColumns) {\n const state = this.getColumnState(column.field);\n\n // Check if we have a fixed pixel width (User resized it)\n const hasPixelWidth = state.width != null;\n\n if (state.visible) {\n if (hasPixelWidth) {\n widths.push(`${state.width}px`);\n } else {\n widths.push('minmax(0, 1fr)');\n }\n } else {\n if (hasPixelWidth) {\n widths.push('0px');\n } else {\n widths.push('minmax(0, 0fr)');\n }\n }\n }\n\n return widths;\n }\n\n // #endregion\n\n // #region --- Event Handlers ---\n\n private handleHeaderClicked = (\n event: MouseEvent,\n column: ColumnOptions<T>,\n ) => {\n const cell = event.currentTarget as HTMLElement;\n // Ignore header click events while resizing\n if (!cell.classList.contains('sortable') || this.resizeState) {\n return;\n }\n\n const multiSort = event.shiftKey;\n const state = this.getColumnState(column.field);\n let sortOrder: SortOrder | null = null;\n if (!state?.sort) {\n sortOrder = 'asc';\n } else if (state.sort.order === 'asc') {\n sortOrder = 'desc';\n }\n\n const requestEvent = new YatlColumnSortRequest(\n column.field,\n sortOrder,\n multiSort,\n );\n if (!this.dispatchEvent(requestEvent)) {\n return;\n }\n\n this.sort(column.field, sortOrder, !multiSort);\n };\n\n private handleCellClick = (\n event: MouseEvent,\n row: T,\n field: NestedKeyOf<T>,\n ) => {\n // Ignore events if the user is highlighting text\n if (window.getSelection()?.toString()) return;\n\n const rowId = this.controller.getRowId(row);\n const rowIndex = this.controller.getRowIndex(row);\n this.dispatchEvent(\n new YatlRowClickEvent(row, rowId, rowIndex, field, event),\n );\n };\n\n private handleResizeMouseDown(event: MouseEvent, field: NestedKeyOf<T>) {\n event.preventDefault();\n event.stopPropagation();\n\n const target = event.target as HTMLElement;\n const header = target.closest('.cell');\n if (!header) {\n return;\n }\n\n const columnIndex = this.displayColumns.findIndex(\n column => column.field === field,\n );\n if (columnIndex < 0) {\n return;\n }\n\n this.tableElement.classList.add('resizing');\n\n // Freeze the current widths as soon as the users starts resizing\n this.tableElement\n .querySelectorAll<HTMLElement>('.header .cell')\n .forEach(element => {\n const field = element.dataset.field as NestedKeyOf<T> | undefined;\n if (field) {\n const state = this.getColumnState(field);\n state.width = element.getBoundingClientRect().width;\n this.updateColumnState(field, state);\n }\n });\n\n const gridWidths = this.getGridWidths();\n this.resizeState = {\n active: true,\n startX: event.pageX,\n startWidth: header.getBoundingClientRect().width,\n columnIndex: columnIndex + 2, // row number column + selector column\n columnField: field,\n currentWidths: gridWidths,\n };\n\n this.tableElement.style.setProperty(\n '--grid-template',\n gridWidths.join(' '),\n );\n\n window.addEventListener('mousemove', this.handleResizeMouseMove);\n window.addEventListener('mouseup', this.handleResizeMouseUp);\n }\n\n private handleResizeMouseMove = (event: MouseEvent) => {\n if (!this.resizeState?.active) return;\n\n requestAnimationFrame(() => {\n if (!this.resizeState?.active) return;\n\n const deltaX = event.pageX - this.resizeState.startX;\n const newWidth = Math.max(50, this.resizeState.startWidth + deltaX);\n this.resizeState.currentWidths[this.resizeState.columnIndex] =\n `${newWidth}px`;\n this.tableElement.style.setProperty(\n '--grid-template',\n this.resizeState.currentWidths.join(' '),\n );\n });\n };\n\n private handleResizeMouseUp = (event: MouseEvent) => {\n window.removeEventListener('mousemove', this.handleResizeMouseMove);\n window.removeEventListener('mouseup', this.handleResizeMouseUp);\n\n this.tableElement.classList.remove('resizing');\n\n if (this.resizeState?.active) {\n event.preventDefault();\n event.stopPropagation();\n\n // Calculate the final width based on the DOM's current style\n const finalWidth = parseFloat(\n this.resizeState.currentWidths[this.resizeState.columnIndex],\n );\n\n this.resizeColumn(this.resizeState.columnField, finalWidth);\n }\n\n // This is a hacky workaround to prevent the header click event from firing\n // if the user releases their mouse click outside of the resizer handle.\n setTimeout(() => {\n this.resizeState = null;\n });\n };\n\n private handleDragColumnStart = (event: DragEvent, field: NestedKeyOf<T>) => {\n const target = event.target as HTMLElement;\n\n if (target?.classList.contains('resizer')) {\n event.preventDefault();\n return;\n }\n\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', field);\n this.dragColumn = field;\n }\n };\n\n private handleDragColumnEnter = (event: DragEvent) => {\n const cell = event.currentTarget as HTMLElement;\n cell.querySelector('.drop-indicator')?.classList.add('active');\n };\n\n private handleDragColumnLeave = (event: DragEvent) => {\n const cell = event.currentTarget as HTMLElement;\n const enteringElement = event.relatedTarget as Node;\n\n if (cell.contains(enteringElement)) {\n return;\n }\n\n cell.querySelector('.drop-indicator')?.classList.remove('active');\n };\n\n private handleDragColumnOver = (event: DragEvent) => {\n event.preventDefault();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'move';\n }\n };\n\n private handleDragColumnDrop = (event: DragEvent, field: NestedKeyOf<T>) => {\n if (!this.dragColumn || this.dragColumn === field) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n const newColumns = this.displayColumns;\n const originalIndex = newColumns.findIndex(\n col => col.field === this.dragColumn,\n );\n const newIndex = newColumns.findIndex(col => col.field === field);\n\n const requestEvent = new YatlColumnReorderRequest(\n this.dragColumn,\n originalIndex,\n newIndex,\n );\n if (!this.dispatchEvent(requestEvent)) {\n return;\n }\n\n this.moveColumn(this.dragColumn, field);\n };\n\n private handleDragColumnEnd = () => {\n this.dragColumn = null;\n // Clean up just in case\n this.tableElement\n .querySelectorAll('.drop-indicator.active')\n .forEach(element => element.classList.remove('active'));\n };\n\n private handleRowSelectionClicked = (event: Event, row: T) => {\n event.stopPropagation();\n const inputElement = event.currentTarget as HTMLInputElement;\n const selected = inputElement.checked;\n\n const rowId = this.controller.getRowId(row);\n const selectedRows = this.selectedRowIds;\n const requestEvent = new YatlRowSelectRequest(\n rowId,\n selected,\n selectedRows,\n );\n if (!this.dispatchEvent(requestEvent)) {\n inputElement.checked = !selected;\n return;\n }\n\n this.toggleRowSelection(row, selected);\n };\n\n // #endregion\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'yatl-table': YatlTable;\n }\n}\n","export function getCompareableValue(value: unknown) {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'bigint'\n ) {\n return value;\n } else if (typeof value === 'boolean') {\n return Number(value);\n } else if (value instanceof Date) {\n return value.getTime();\n } else {\n return String(value);\n }\n}\n\n/**\n * Creates a mapping of values to their sorted rank (0-based index).\n * Handles locale comparison correctly during the setup phase.\n */\nexport function createRankMap(\n values: [unknown, unknown][],\n locale?: string,\n): Map<unknown, number> {\n const unique = Array.from(new Set(values));\n // Use Intl.Collator for high-performance, correct locale sorting\n const collator = new Intl.Collator(locale, {\n numeric: true,\n sensitivity: 'base',\n });\n\n unique.sort(([_aOrig, aMod], [_bOrig, bMod]) => {\n if (aMod == null && bMod == null) return 0;\n if (aMod == null) return -1;\n if (aMod == null) return 1;\n const aValue = getCompareableValue(aMod);\n const bValue = getCompareableValue(bMod);\n if (typeof aValue === 'string' && typeof bValue === 'string') {\n return collator.compare(String(aValue), String(bValue));\n }\n\n if (aValue < bValue) return -1;\n if (bValue < aValue) return 1;\n return 0;\n });\n\n const rankMap = new Map<unknown, number>();\n unique.forEach(([orig, _mod], index) => rankMap.set(orig, index));\n return rankMap;\n}\n","import type {\n ColumnFilterCallback,\n ColumnOptions,\n ColumnState,\n ExportOptions,\n FilterCallback,\n Filters,\n NestedKeyOf,\n QueryToken,\n RestorableColumnState,\n RestorableTableState,\n RowId,\n RowIdCallback,\n RowSelectionMethod,\n SortOrder,\n StorageOptions,\n TableControllerOptions,\n TableState,\n TokenizerCallback,\n UnspecifiedRecord,\n} from '../types';\n\nimport {\n createState,\n getNestedValue,\n isDisplayColumn,\n isRowIdType,\n isRowSelectionMethod,\n whitespaceTokenizer,\n getColumnStateChanges,\n} from '../utils';\n\nimport { createRankMap } from './utils';\n\nimport { ReactiveController, ReactiveControllerHost } from 'lit';\n\nimport {\n YatlColumnReorderEvent,\n YatlColumnResizeEvent,\n YatlColumnSortEvent,\n YatlColumnToggleEvent,\n YatlRowSelectEvent,\n YatlTableSearchEvent,\n YatlTableStateChangeEvent,\n YatlTableViewChangeEvent,\n} from '../events';\nimport { TypedEventTarget } from '../utils/typed-event-target';\n\n// #region Constants\n\n// Debounce between state saves\nconst STATE_SAVE_DEBOUNCE = 1000;\n\nconst DEFAULT_STORAGE_OPTIONS: Partial<StorageOptions> = {\n storage: 'local',\n saveColumnSortOrders: true,\n saveColumnVisibility: true,\n saveColumnWidths: true,\n saveColumnOrder: true,\n saveSelectedRows: true,\n};\n\nconst MATCH_WEIGHTS = {\n EXACT: 100,\n PREFIX: 50,\n SUBSTRING: 10,\n};\n\n// #endregion\n\nexport class YatlTableController<T extends object = UnspecifiedRecord>\n extends TypedEventTarget<ControllerEventMap>\n implements ReactiveController\n{\n // #region State Data\n\n // Property data\n private hosts = new Set<ReactiveControllerHost>();\n private _enableSearchTokenization = false;\n private _enableSearchScoring = false;\n // Original options passed by the user\n private _columns: ColumnOptions<T>[] = [];\n // Options mapped by field for faster lookup\n private _columnDefinitionMap = new Map<NestedKeyOf<T>, ColumnOptions<T>>();\n private _columnStateMap = new Map<NestedKeyOf<T>, Readonly<ColumnState<T>>>();\n private _rowSelectionMethod: RowSelectionMethod | null = null;\n private _selectedRowIds = new Set<RowId>();\n private _storageOptions: StorageOptions | null = null;\n private _rowIdCallback: RowIdCallback<T> = (row, index) => {\n if ('id' in row && isRowIdType(row.id)) return row.id;\n if ('key' in row && isRowIdType(row.key)) return row.key;\n if ('_id' in row && isRowIdType(row._id)) return row._id;\n warnMissingId();\n return index;\n };\n private _data: T[] = [];\n private _filteredData: T[] = [];\n // The last time the data was updated.\n // This is just provided as a convience so the\n // table element can display it in the footer.\n // The controller needs to own it so it is always accurate.\n private _dataUpdateTimestamp: Date | null = null;\n\n private _searchQuery = '';\n private _searchTokenizer: TokenizerCallback = whitespaceTokenizer;\n private _filters: Filters<T> | FilterCallback<T> | null = null;\n\n // Flag if we have already restored the state or not.\n private hasRestoredState = false;\n\n // save state debounce timer\n private saveTimer = 0;\n\n // Flags set when something changes that\n // requires the filter or sort logic to re-run.\n private filterDirty = false;\n private sortDirty = false;\n\n // Maps rows to their metadata\n private rowMetadata = new WeakMap<T, RowMetadata>();\n // Map row ids to their rows for faster lookup\n private idToRowMap = new Map<RowId, T>();\n // List of tokens created from the current query\n private queryTokens: QueryToken[] | null = null;\n\n // #endregion\n\n // #region Properties\n\n /**\n * Enables tokenized search behavior.\n * When enabled, the search query is split into individual tokens using the\n * `searchTokenizer` function (defaults to splitting on whitespace).\n * A row is considered a match if **ANY** of the tokens appear in the searchable fields.\n * @default false\n */\n public get enableSearchTokenization() {\n return this._enableSearchTokenization;\n }\n\n public set enableSearchTokenization(enable) {\n if (this._enableSearchTokenization === enable) {\n return;\n }\n\n this._enableSearchTokenization = enable;\n this.updateInternalQuery();\n this.filterDirty = true;\n this.requestUpdate('enableSearchTokenization');\n }\n\n /**\n * Enables weighted relevance scoring for search results.\n * When enabled, exact matches and prefix matches are ranked higher than substring matches.\n * Rows are sorted by their relevance score descending.\n * @default false\n */\n public get enableSearchScoring() {\n return this._enableSearchScoring;\n }\n\n public set enableSearchScoring(enable) {\n if (this._enableSearchScoring === enable) {\n return;\n }\n\n this._enableSearchScoring = enable;\n this.filterDirty = true;\n this.requestUpdate('enableSearchScoring');\n }\n\n /**\n * The definitions for the columns to be rendered.\n * This defines the field mapping, titles, sortability, and other static options.\n */\n public get columns() {\n return [...this._columns];\n }\n\n public set columns(columns) {\n this._columns = [...columns];\n this.filterDirty = true;\n // Cache these in a map for faster lookups\n this._columnDefinitionMap = new Map();\n for (const column of columns) {\n this._columnDefinitionMap.set(column.field, column);\n }\n this.requestUpdate('columns');\n }\n\n public get displayColumns() {\n return this.columns.filter(isDisplayColumn);\n }\n\n public get columnStates() {\n return this.columns.map(column => {\n const state = this.getColumnState(column.field);\n // Always return a copy so the user can't modify it.\n return createState(column.field, state);\n });\n }\n\n public set columnStates(states) {\n let changed = false;\n for (const state of states) {\n const oldState = this.getColumnState(state.field);\n const stateChanges = getColumnStateChanges(oldState, state);\n if (stateChanges.length) {\n changed = true;\n if (stateChanges.includes('sort')) {\n this.sortDirty = true;\n }\n\n const newState = createState(state.field, state);\n this._columnStateMap.set(state.field, newState);\n }\n }\n\n if (!changed) {\n return;\n }\n\n this.requestUpdate('columnStates');\n }\n\n /**\n * The current text string used to filter the table data.\n * Setting this property triggers a new search and render cycle.\n */\n public get searchQuery() {\n return this._searchQuery;\n }\n\n public set searchQuery(query) {\n if (this._searchQuery === query) {\n return;\n }\n\n this._searchQuery = query;\n this.updateInternalQuery();\n this.filterDirty = true;\n this.requestUpdate('searchQuery');\n }\n\n /**\n * A function that splits the search query into tokens.\n * Only used if `enableSearchTokenization` is true.\n * @default whitespaceTokenizer\n */\n public get searchTokenizer() {\n return this._searchTokenizer;\n }\n\n public set searchTokenizer(tokenizer) {\n if (this._searchTokenizer === tokenizer) {\n return;\n }\n\n this._searchTokenizer = tokenizer;\n this.filterDirty = true;\n this.requestUpdate('searchTokenizer');\n }\n\n /**\n * An optional set of criteria to filter the visible rows.\n * This runs **before** the global search query is applied.\n * * You can provide:\n * 1. A **Partial Object**: matches rows where specific keys equal specific values (AND logic).\n * 2. A **Callback Function**: returns `true` to keep the row, `false` to hide it.\n * * @example\n * // 1. Object Syntax (Simple Exact Match)\n * // Shows rows where status is 'active' AND role is 'admin'\n * table.filters = { status: 'active', role: 'admin' };\n * * @example\n * // 2. Callback Syntax (Complex Logic)\n * // Shows rows where age is over 21 OR they are a VIP\n * table.filters = (row) => row.age > 21 || row.isVip;\n */\n public get filters() {\n return this._filters;\n }\n\n public set filters(filters) {\n if (this._filters === filters) {\n return;\n }\n\n this._filters = filters;\n this.filterDirty = true;\n this.requestUpdate('filters');\n }\n\n /**\n * The row selection method to use.\n * * single - Only a single row can be selected at a time\n * * multi - Multiple rows can be selected at a time\n * * null - Disable row selection\n */\n public get rowSelectionMethod() {\n return this._rowSelectionMethod;\n }\n\n public set rowSelectionMethod(selection) {\n if (\n this._rowSelectionMethod === selection ||\n !isRowSelectionMethod(selection)\n ) {\n return;\n }\n\n this._rowSelectionMethod = selection;\n this.requestUpdate('rowSelectionMethod');\n }\n\n /**\n * List of currently selected row indexes.\n * * **NOTE**: These indexes are based off the of\n * the original data array index, *not* the filtered data.\n */\n public get selectedRowIds() {\n let selectedRows = [...this._selectedRowIds];\n\n if (this.rowSelectionMethod === 'single') {\n selectedRows = selectedRows.slice(0, 1);\n } else if (!this.rowSelectionMethod) {\n selectedRows = [];\n }\n return selectedRows;\n }\n\n public set selectedRowIds(rows) {\n if (\n rows.length === this._selectedRowIds.size &&\n rows.every(a => this._selectedRowIds.has(a))\n ) {\n return;\n }\n\n this._selectedRowIds = new Set(rows);\n this.requestUpdate('selectedRowIds');\n }\n\n /**\n * Configuration options for automatically saving and restoring table state\n * (column width, order, visibility, etc.) to browser storage.\n */\n public get storageOptions() {\n return this._storageOptions ? { ...this._storageOptions } : null;\n }\n\n public set storageOptions(options) {\n if (this._storageOptions === options) {\n return;\n }\n\n this._storageOptions = options ? { ...options } : null;\n if (!this.hasRestoredState) {\n this.loadStateFromStorage();\n this.requestUpdate('storageOptions');\n }\n }\n\n public get rowIdCallback() {\n return this._rowIdCallback;\n }\n\n public set rowIdCallback(callback) {\n if (this._rowIdCallback === callback) {\n return;\n }\n\n this._rowIdCallback = callback;\n // Update IDs in metadata for existing data.\n for (let i = 0; i < this.data.length; ++i) {\n const row = this.data[i];\n this.rowMetadata.get(row)!.id = this._rowIdCallback(row, i);\n }\n this.requestUpdate('rowIdCallback');\n }\n\n /**\n * The array of data objects to be displayed.\n * Objects must satisfy the `WeakKey` constraint (objects only, no primitives).\n */\n public get data() {\n return [...this._data];\n }\n\n public set data(data: T[]) {\n this._data = [...data];\n this.createMetadata();\n this._dataUpdateTimestamp = new Date();\n this.filterDirty = true;\n this.requestUpdate('data');\n }\n\n public get filteredData() {\n if (this.filterDirty) {\n this.filterRows();\n } else if (this.sortDirty) {\n this.sortRows();\n }\n\n this.filterDirty = false;\n this.sortDirty = false;\n\n return [...this._filteredData];\n }\n\n public get dataUpdateTimestamp() {\n return this._dataUpdateTimestamp;\n }\n\n // #endregion\n\n // #region Public Methods\n\n constructor(\n host?: ReactiveControllerHost,\n options?: TableControllerOptions<T>,\n ) {\n super();\n\n if (host) {\n this.attach(host);\n }\n\n if (options) {\n if (options.enableSearchScoring !== undefined)\n this.enableSearchScoring = options.enableSearchScoring;\n if (options.enableSearchTokenization !== undefined)\n this.enableSearchTokenization = options.enableSearchTokenization;\n if (options.searchTokenizer !== undefined)\n this.searchTokenizer = options.searchTokenizer;\n if (options.rowIdCallback !== undefined)\n this.rowIdCallback = options.rowIdCallback;\n if (options.rowSelectionMethod !== undefined)\n this.rowSelectionMethod = options.rowSelectionMethod;\n if (options.storageOptions !== undefined)\n this.storageOptions = options.storageOptions;\n if (options.columns !== undefined) this.columns = options.columns;\n if (options.data !== undefined) this.data = options.data;\n }\n }\n\n public attach(host: ReactiveControllerHost) {\n this.hosts.add(host);\n host.addController(this);\n host.requestUpdate();\n }\n\n public detach(host: ReactiveControllerHost) {\n host.removeController(this);\n this.hosts.delete(host);\n }\n\n public getColumn(field: NestedKeyOf<T>) {\n return this._columnDefinitionMap.get(field);\n }\n\n public getDisplayColumn(field: NestedKeyOf<T>) {\n const column = this._columnDefinitionMap.get(field);\n if (isDisplayColumn(column)) {\n return column;\n }\n }\n\n /**\n * Gets a copy of the current state of the table.\n */\n public getTableState(): TableState<T> {\n return {\n searchQuery: this.searchQuery,\n selectedRows: this.selectedRowIds,\n columns: this.columnStates.map(column => {\n const state = this.getColumnState(column.field);\n // Always return a copy so the user can't modify it\n return createState(column.field, state);\n }),\n };\n }\n\n /**\n * Restores the table to the provided state.\n * @param state - The state to restore the table to.\n */\n public updateTableState(state: RestorableTableState<T>) {\n if ('searchQuery' in state && state.searchQuery !== undefined) {\n this.searchQuery = state.searchQuery;\n }\n\n if ('selectedRows' in state && state.selectedRows) {\n this.selectedRowIds = state.selectedRows;\n }\n\n if ('columns' in state && state.columns !== undefined) {\n for (const newState of state.columns) {\n this.updateColumnState(newState.field, newState);\n }\n }\n\n this.requestUpdate();\n }\n\n public getColumnState(field: NestedKeyOf<T>) {\n const currentState = this._columnStateMap.get(field);\n if (!currentState) {\n const createdState = createState(field);\n this._columnStateMap.set(field, createdState);\n return createdState;\n }\n return createState(field, currentState);\n }\n\n public updateColumnState(\n field: NestedKeyOf<T>,\n state: RestorableColumnState<T>,\n ) {\n const currentState = this._columnStateMap.get(field);\n const newState = createState(field, { ...currentState, ...state });\n this.columnStates = [newState];\n }\n\n public search(query: string) {\n this.searchQuery = query;\n this.dispatchEvent(new YatlTableSearchEvent(query));\n }\n\n public getColumnFilterValues(field: NestedKeyOf<T>, includeNull = false) {\n const column = this.getDisplayColumn(field);\n const values = new Map<unknown, number>();\n for (const row of this.filteredData) {\n let value = getNestedValue(row, field);\n if (column?.valueFormatter) {\n value = column.valueFormatter(value, row);\n }\n if (value != null || includeNull) {\n const valueCount = values.get(value) ?? 0;\n values.set(value, valueCount + 1);\n }\n }\n return values;\n }\n\n /**\n * Sorts the table by a specified column and order.\n * If `order` is `null`, the sort on this column is removed.\n * @param field - The field name of the column to sort by.\n * @param order - The sort order: 'asc', 'desc', or `null` to remove sorting for this column.\n * @param clear - Clear all other sorting\n */\n public sort(\n field: NestedKeyOf<T>,\n order: SortOrder | null,\n clear: boolean = true,\n ) {\n const state = this.getColumnState(field);\n if (state === undefined) {\n throw new Error(`Cannot get options for non-existent column \"${field}\"`);\n }\n\n if (order === state?.sort?.order) {\n return;\n }\n\n // Column was unsorted, give it a new priority\n if (order && !state.sort) {\n // Create a list of current sort priorities\n const priorities = [...this._columnStateMap.values()]\n .map(state => state.sort?.priority)\n .filter(priority => priority !== undefined);\n\n const maxPriority = this.columns.length + 1;\n const priority = Math.min(maxPriority, ...priorities) - 1;\n state.sort = { order, priority };\n } else if (order && state.sort) {\n // Column was sorted, just updated the order\n state.sort.order = order;\n } else {\n state.sort = null;\n }\n\n const newStates = [state];\n // Clear all other sorting\n if (clear) {\n for (const otherColumn of this.columns) {\n if (otherColumn.field !== field) {\n const otherState = this.getColumnState(otherColumn.field);\n otherState.sort = null;\n newStates.push(otherState);\n }\n }\n }\n\n this.columnStates = newStates;\n\n const event = new YatlColumnSortEvent(field, order, !clear);\n this.dispatchEvent(event);\n }\n\n /**\n * Toggles the visibility of hte specified column\n * @param field - The field name of the column to toggle.\n * @param visible - Optionally force the visibility state.\n */\n public toggleColumnVisibility(field: NestedKeyOf<T>, visible?: boolean) {\n const state = this.getColumnState(field);\n const newVisibility = visible !== undefined ? visible : !state.visible;\n\n if (newVisibility === state.visible) {\n return;\n }\n\n state.visible = newVisibility;\n this.columnStates = [state];\n\n const event = new YatlColumnToggleEvent(field, newVisibility);\n this.dispatchEvent(event);\n }\n\n /**\n * Shows the specified column\n * @param field - The field name of the column to show.\n */\n public showColumn(field: NestedKeyOf<T>) {\n this.toggleColumnVisibility(field, true);\n }\n\n /**\n * Hides the specified column\n * @param field - The field name of the column to hide.\n */\n public hideColumn(field: NestedKeyOf<T>) {\n this.toggleColumnVisibility(field, false);\n }\n\n /**\n * Moves a column to a new position\n * @param field - The column to move\n * @param newPosition The index or field of the column to move it to.\n * @returns\n */\n public moveColumn(\n field: NestedKeyOf<T>,\n newPosition: number | NestedKeyOf<T>,\n ) {\n const newColumns = this.displayColumns;\n const originalIndex = newColumns.findIndex(col => col.field === field);\n const newIndex =\n typeof newPosition === 'number'\n ? newPosition\n : newColumns.findIndex(col => col.field === newPosition);\n\n if (originalIndex > -1 && newIndex > -1) {\n const [movedColumn] = newColumns.splice(originalIndex, 1);\n newColumns.splice(newIndex, 0, movedColumn);\n this.columns = newColumns;\n const event = new YatlColumnReorderEvent(newColumns.map(c => c.field));\n this.dispatchEvent(event);\n }\n }\n\n public resizeColumn(field: NestedKeyOf<T>, width: number | null) {\n const state = this.getColumnState(field);\n state.width = width;\n this.updateColumnState(field, state);\n this.dispatchEvent(new YatlColumnResizeEvent(field, width));\n }\n\n public isRowSelected(row: T) {\n const rowId = this.getRowId(row);\n return this.selectedRowIds.includes(rowId);\n }\n\n /**\n * Toggles the selection state of a specific row.\n */\n public toggleRowSelection(row: T, state?: boolean) {\n const rowId = this.getRowId(row);\n\n const isSelected = this.isRowSelected(row);\n const newSelectionState = state !== undefined ? state : isSelected;\n\n if (newSelectionState === isSelected) {\n return;\n }\n\n let newSelection: RowId[];\n if (newSelectionState) {\n newSelection =\n this.rowSelectionMethod === 'single'\n ? [rowId]\n : [...this.selectedRowIds, rowId];\n } else {\n newSelection = this.selectedRowIds.filter(\n existingId => existingId !== rowId,\n );\n }\n\n const previousSelection = this.selectedRowIds;\n this.selectedRowIds = newSelection;\n\n const event = new YatlRowSelectEvent(newSelection, previousSelection);\n this.dispatchEvent(event);\n }\n\n /**\n * Selects a specific row.\n */\n public selectRow(row: T) {\n this.toggleRowSelection(row, true);\n }\n\n /**\n * Deselects a specific row.\n */\n public deselectRow(row: T) {\n this.toggleRowSelection(row, false);\n }\n\n /**\n * Selects all currently visible rows (for \"Select All\" checkbox).\n */\n public selectAll() {\n if (this.rowSelectionMethod === 'single') return;\n\n // Use visible rows (filtered) or all rows depending on your UX preference\n const allIds = this.filteredData.map(row => this.getRowId(row));\n this.selectedRowIds = allIds;\n }\n\n /**\n * Clears all selection.\n */\n public deselectAll() {\n this.selectedRowIds = [];\n }\n\n /**\n * Export the current visible table data to a CSV file.\n * @param options - Options for configuring what should be exported.\n */\n public export(\n options: ExportOptions = {\n includeAllRows: false,\n includeHiddenColumns: false,\n includeInternalColumns: false,\n },\n ) {\n const data = options.includeAllRows ? this.data : this.filteredData;\n\n const columnData = options.includeInternalColumns\n ? this.columns\n : this.displayColumns;\n\n const csvHeaders = columnData\n .filter(column => {\n if (options.includeHiddenColumns) {\n return true;\n }\n return this.getColumnState(column.field).visible;\n })\n .map(column => {\n if (isDisplayColumn(column)) {\n return column.title;\n }\n return column.field;\n })\n .join(',');\n\n const csvRows = data\n .map(row => {\n const list: string[] = [];\n for (const column of columnData) {\n const state = this.getColumnState(column.field);\n let value = getNestedValue(row, column.field);\n if (options.includeHiddenColumns || state.visible) {\n if (\n isDisplayColumn(column) &&\n typeof column.valueFormatter === 'function'\n ) {\n value = column.valueFormatter(value, row);\n }\n value = String(value).replace('\"', '\"\"');\n list.push(`\"${value}\"`);\n }\n }\n return list.join(',');\n })\n .join('\\n');\n\n const csvContent = csvHeaders + '\\n' + csvRows;\n return new Blob([csvContent], { type: 'text/csv;charset=utf-8,' });\n }\n\n /**\n * Gets the row associated with the provided ID.\n * @param id - The ID of the row to get\n * @returns\n */\n public getRow(id: RowId) {\n return this.idToRowMap.get(id);\n }\n\n /**\n * Finds the first row where {@link field} matches {@link value}\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The found row, or undefined if no match is found.\n */\n public findRow(field: NestedKeyOf<T>, value: unknown) {\n return this.data.find(row => {\n const rowValue = getNestedValue(row, field);\n return rowValue === value;\n });\n }\n\n /**\n * Finds the original index of the first row where the specified field matches the given value.\n * This searches through the original, unfiltered dataset.\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The original index of the found row, or -1 if no match is found.\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow({description: \"Updated description\"}, index);\n * }\n * ```\n */\n public findRowIndex(field: NestedKeyOf<T>, value: unknown) {\n const row = this.findRow(field, value);\n if (row) {\n return this.rowMetadata.get(row)!.index;\n }\n return -1;\n }\n\n public updateRow(rowId: RowId, data: Partial<T>) {\n const row = this.idToRowMap.get(rowId);\n if (row) {\n Object.assign(row, data);\n this.requestUpdate('data');\n }\n }\n\n /**\n * Updates the data of a row at a specific original index.\n * @param index - The original index of the row to update.\n * @param data - An object containing the new data to assign to the row. Existing fields will be updated, and new fields will be added.\n *\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow(index, {description: \"Updated description\"});\n * }\n * ```\n */\n public updateRowAtIndex(index: number, data: Partial<T>) {\n const row = this.data[index];\n if (row) {\n Object.assign(row, data);\n this.requestUpdate('data');\n }\n }\n\n /**\n * Deletes the row with the matching ID.\n * @param rowIds - The IDs rows to delete\n */\n public deleteRow(...rowIds: RowId[]) {\n for (const rowId of rowIds) {\n const row = this.idToRowMap.get(rowId);\n if (row) {\n const metadata = this.rowMetadata.get(row)!;\n this.deleteRowAtIndex(metadata.index);\n }\n }\n }\n\n /**\n * Deletes a row at a specific original index from the table.\n * @param indexes - The original indexes of rows to delete.\n */\n public deleteRowAtIndex(...indexes: number[]) {\n const newSelectedRows = new Set(this.selectedRowIds);\n for (const index of indexes) {\n const row = this.data[index];\n if (row) {\n const metadata = this.rowMetadata.get(row)!;\n this.idToRowMap.delete(metadata.id);\n this.rowMetadata.delete(row);\n newSelectedRows.delete(metadata.id);\n this.data = this.data.toSpliced(index, 1);\n }\n }\n this.selectedRowIds = [...newSelectedRows];\n }\n\n public getRowId(row: T) {\n const metadata = this.rowMetadata.get(row);\n if (!metadata) {\n throw new Error('The provided row does not exist in the current dataset');\n }\n return metadata.id;\n }\n\n public getRowIndex(row: T) {\n const metadata = this.rowMetadata.get(row);\n if (!metadata) {\n throw new Error('The provided row does not exist in the current dataset');\n }\n return metadata.index;\n }\n\n public getRowHighlightIndicies(row: T) {\n const metadata = this.rowMetadata.get(row);\n if (!metadata) {\n throw new Error('The provided row does not exist in the current dataset');\n }\n return metadata.highlightIndices;\n }\n\n // #endregion\n\n // #region Lifecycle Methods\n public hostConnected(): void {}\n\n public hostDisconnected(): void {}\n\n public hostUpdate(): void {}\n\n public hostUpdated(): void {}\n\n public requestUpdate(...props: (keyof YatlTableController)[]) {\n const SAVE_TRIGGERS: (keyof YatlTableController)[] = [\n 'columns',\n 'columnStates',\n 'searchQuery',\n 'selectedRowIds',\n ];\n const triggers = props.filter(p => SAVE_TRIGGERS.includes(p));\n if (triggers.length) {\n this.scheduleSave();\n this.dispatchEvent(\n new YatlTableStateChangeEvent(this.getTableState(), triggers),\n );\n }\n\n for (const host of this.hosts) {\n host.requestUpdate();\n }\n }\n\n // #endregion\n\n // #region Filter Methods\n\n /**\n * Calculates a relevance score for a given query against a target string.\n *\n * This function implements a tiered matching strategy:\n * 1. **Exact Match**: The query exactly matches the target. This yields the highest score.\n * 2. **Prefix Match**: The target starts with the query. This is the next most relevant.\n * 3. **Substring Match**: The target contains the query somewhere. This is the least relevant.\n *\n * The final score is weighted and adjusted by the length difference between the query and the target\n * to ensure that more specific matches (e.g., \"apple\" vs \"application\" for the query \"apple\") rank higher.\n *\n * @param query The search term (e.g., \"app\").\n * @param target The string to be searched (e.g., \"Apple\" or \"Application\").\n * @returns A numerical score representing the relevance of the match. Higher is better. Returns 0 if no match is found.\n */\n private calculateSearchScore(query: string, target: string): SearchResult {\n const results: SearchResult = { score: 0, ranges: [] };\n\n if (!query || !target) {\n return results;\n }\n\n let baseScore = 0;\n let matchTypeWeight = 0;\n\n if (target === query) {\n matchTypeWeight = MATCH_WEIGHTS.EXACT;\n baseScore = query.length;\n results.ranges.push([0, target.length]);\n } else if (target.startsWith(query)) {\n matchTypeWeight = MATCH_WEIGHTS.PREFIX;\n baseScore = query.length;\n results.ranges.push([0, query.length]);\n } else {\n const index = target.indexOf(query);\n if (index !== -1) {\n matchTypeWeight = MATCH_WEIGHTS.SUBSTRING;\n baseScore = query.length;\n\n let cursor = index;\n while (cursor !== -1) {\n results.ranges.push([cursor, cursor + query.length]);\n cursor = target.indexOf(query, cursor + 1);\n }\n } else {\n return results;\n }\n }\n\n // Reward matches where the query length is close to the target length.\n const lengthDifference = target.length - query.length;\n const specificityBonus = 1 / (1 + lengthDifference);\n\n // The final score is a combination of the match type's importance,\n // the base score from the query length, and the specificity bonus.\n results.score = baseScore * matchTypeWeight * specificityBonus;\n return results;\n }\n\n private searchField(\n query: QueryToken,\n value: string,\n tokens?: string[],\n ): SearchResult {\n const result: SearchResult = { score: 0, ranges: [] };\n\n const addRangesFromValue = (searchTerm: string) => {\n let idx = value.indexOf(searchTerm);\n while (idx !== -1) {\n result.ranges.push([idx, idx + searchTerm.length]);\n idx = value.indexOf(searchTerm, idx + 1);\n }\n };\n\n // Handle Quoted/Untokenized (Direct Search)\n if (query.quoted || !tokens) {\n if (!this.enableSearchScoring) {\n // Simple boolean match\n if (value.includes(query.value)) {\n result.score = 1;\n addRangesFromValue(query.value);\n }\n } else {\n // Scored match\n const calculation = this.calculateSearchScore(query.value, value);\n result.score = calculation.score;\n result.ranges = calculation.ranges;\n }\n return result;\n }\n\n // Handle Tokenized Search\n // We search the tokens to check for validity/scoring,\n // but we map back to the 'value' for highlighting.\n if (!this.enableSearchScoring) {\n const isMatch = tokens.some(token => token.includes(query.value));\n if (isMatch) {\n result.score = 1;\n addRangesFromValue(query.value);\n }\n return result;\n }\n\n // Complex Scored Token Search\n // We sum the scores of all matching tokens\n for (const token of tokens) {\n const calculation = this.calculateSearchScore(query.value, token);\n if (calculation.score > 0) {\n result.score += calculation.score;\n // If a token matched, find that query in the main string\n addRangesFromValue(query.value);\n }\n }\n\n return result;\n }\n\n private filterField(\n value: unknown,\n filter: unknown,\n filterFunction: ColumnFilterCallback | null = null,\n ): boolean {\n if (Array.isArray(filter)) {\n if (filter.length === 0) {\n return true;\n }\n // If it's an array, we will use an OR filter.\n // If any filters in the array match, keep it.\n return filter.some(element =>\n this.filterField(value, element, filterFunction),\n );\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return false;\n }\n return value.some(element =>\n this.filterField(element, filter, filterFunction),\n );\n }\n\n if (typeof filterFunction === 'function') {\n return filterFunction(value, filter);\n }\n\n if (filter instanceof RegExp) {\n return filter.test(String(value));\n }\n\n return filter === value;\n }\n\n private filterRow(row: T, index: number): boolean {\n if (!this.filters) {\n return true;\n }\n\n if (typeof this.filters === 'function') {\n return this.filters(row, index);\n }\n\n for (const field in this.filters) {\n const filter = getNestedValue(this.filters, field);\n const value = getNestedValue(row, field);\n if (typeof filter === 'function') {\n if (!filter(value)) {\n return false;\n }\n } else if (filter !== undefined) {\n const column = this.getColumn(field as NestedKeyOf<T>);\n const filterCallback = column ? column.filter : undefined;\n if (!this.filterField(value, filter, filterCallback)) {\n return false;\n }\n }\n }\n return true;\n }\n\n private filterRows() {\n const columnData = [...this.columns];\n const fields = columnData\n .filter(column => column.searchable)\n .map(column => column.field);\n\n this._filteredData = this.data.filter((row, index) => {\n const metadata = this.rowMetadata.get(row)!;\n metadata.searchScore = 0;\n metadata.highlightIndices = {};\n // Filter takes precedence over search.\n if (!this.filterRow(row, index)) {\n return false;\n }\n\n if (!this.queryTokens) {\n return true;\n }\n\n for (const field of fields) {\n const originalValue = getNestedValue(row, field);\n const compareValue = metadata.searchValues[field];\n const columnTokens = metadata.searchTokens[field];\n\n if (\n typeof originalValue !== 'string' ||\n typeof compareValue !== 'string'\n ) {\n continue;\n }\n\n const fieldResults: SearchResult = { score: 0, ranges: [] };\n for (const token of this.queryTokens) {\n const results = this.searchField(token, compareValue, columnTokens);\n fieldResults.score += results.score;\n fieldResults.ranges.push(...results.ranges);\n }\n\n if (fieldResults.score > 0) {\n metadata.searchScore += fieldResults.score;\n metadata.highlightIndices[field] = fieldResults.ranges;\n }\n }\n\n return metadata.searchScore > 0;\n });\n\n this.filterDirty = false;\n\n this.sortRows();\n this.dispatchEvent(new YatlTableViewChangeEvent(this.data));\n }\n\n // #endregion\n\n // #region Sort Methods\n\n private compareRows(a: T, b: T, field: NestedKeyOf<T>): number {\n let aValue, bValue;\n\n const state = this.getColumnState(field);\n if (!state.sort) {\n return 0;\n }\n\n const aMetadata = this.rowMetadata.get(a)!;\n const bMetadata = this.rowMetadata.get(b)!;\n\n if (state.sort?.order === 'asc') {\n aValue = aMetadata.sortValues[field];\n bValue = bMetadata.sortValues[field];\n } else {\n aValue = bMetadata.sortValues[field];\n bValue = aMetadata.sortValues[field];\n }\n\n aValue ??= Number.MIN_SAFE_INTEGER;\n bValue ??= Number.MIN_SAFE_INTEGER;\n\n if (aValue < bValue) return -1;\n if (aValue > bValue) return 1;\n return 0;\n }\n\n private sortRows() {\n if (this.filterDirty) {\n this.filterRows();\n return;\n }\n\n const sortedStates = [...this._columnStateMap.values()]\n // Filter to visible columns with active sort states\n .filter(state => state.visible && state.sort)\n // Sort our columns by their sort priority.\n // This is how sorting by multiple columns is handled.\n .sort((a, b) => b.sort!.priority - a.sort!.priority);\n\n this._filteredData = this._filteredData.toSorted((a, b) => {\n const aMetadata = this.rowMetadata.get(a)!;\n const bMetadata = this.rowMetadata.get(b)!;\n\n // Try to sort by search score if we're using scoring and there is a query.\n if (this.enableSearchScoring && this.queryTokens) {\n const aValue = aMetadata.searchScore || 0;\n const bValue = bMetadata.searchScore || 0;\n if (aValue > bValue) return -1;\n if (aValue < bValue) return 1;\n }\n\n for (const state of sortedStates) {\n const comp = this.compareRows(a, b, state.field);\n if (comp !== 0) {\n return comp;\n }\n }\n\n // Always fall back to the index column\n return aMetadata.index - bMetadata.index;\n });\n this.sortDirty = false;\n }\n\n // #endregion\n\n // #region Utilities\n\n private createMetadata() {\n this.idToRowMap = new Map();\n this.rowMetadata = new WeakMap();\n\n const rankMaps = new Map<string, Map<unknown, number>>();\n // TODO: We only need rank maps for sortable columns\n // but the user could enable sorting later. It's easiest\n // to just compute them all know regardless.\n for (const column of this.columns) {\n // Collect all raw values for this column\n const rawValues = this.data.map(row => {\n const originalValue = getNestedValue(row, column.field);\n const modifiedValue = column.sorter?.(originalValue) ?? originalValue;\n return [originalValue, modifiedValue] as [unknown, unknown];\n });\n rankMaps.set(column.field, createRankMap(rawValues));\n }\n\n let index = 0;\n for (const row of this.data) {\n let rowId = this._rowIdCallback(row, index);\n // If the user screws\n if (rowId == null || this.idToRowMap.has(rowId)) {\n warnInvalidIdFunction(index, rowId, row);\n rowId = `__yatl_fallback_id_${index}`;\n }\n\n this.idToRowMap.set(rowId, row);\n // Add the index\n const metadata: RowMetadata = {\n id: rowId,\n index: index++,\n searchTokens: {},\n searchValues: {},\n sortValues: {},\n selected: false,\n };\n this.rowMetadata.set(row, metadata);\n\n for (const column of this.columns) {\n const value = getNestedValue(row, column.field);\n const rankMap = rankMaps.get(column.field)!;\n metadata.sortValues[column.field] = rankMap.get(value) ?? null;\n\n // Cache precomputed lower-case values for search\n if (typeof value === 'string') {\n metadata.searchValues[column.field] = value.toLocaleLowerCase();\n }\n\n // Tokenize any searchable columns\n if (column.searchable && column.tokenize && value) {\n const tokenizer = column.searchTokenizer ?? this.searchTokenizer;\n metadata.searchTokens[column.field] = tokenizer(String(value)).map(\n token => token.value,\n );\n }\n }\n }\n }\n\n private updateInternalQuery() {\n if (this.searchQuery.length === 0) {\n this.queryTokens = null;\n return;\n }\n\n this.queryTokens = [\n { value: this.searchQuery.toLocaleLowerCase(), quoted: true },\n ];\n\n if (this.enableSearchTokenization) {\n this.queryTokens.push(...this.searchTokenizer(this.searchQuery));\n }\n }\n\n private scheduleSave() {\n window.clearTimeout(this.saveTimer);\n\n this.saveTimer = window.setTimeout(() => {\n this.saveStateToStorage();\n }, STATE_SAVE_DEBOUNCE);\n }\n\n // #endregion\n\n // #region Storage Methods\n\n private saveStateToStorage() {\n if (!this.storageOptions) {\n return;\n }\n\n const options = { ...DEFAULT_STORAGE_OPTIONS, ...this.storageOptions };\n const savedTableState: RestorableTableState<T> = {\n columns: [],\n };\n const tableState = this.getTableState();\n\n if (options.saveSearchQuery) {\n savedTableState.searchQuery = tableState.searchQuery;\n }\n\n if (options.saveSelectedRows) {\n savedTableState.selectedRows = tableState.selectedRows;\n }\n\n for (const columnState of tableState.columns) {\n const savedColumnState: RestorableColumnState<T> = {\n field: columnState.field,\n };\n\n if (options.saveColumnSortOrders) {\n savedColumnState.sort = columnState.sort;\n }\n\n if (options.saveColumnVisibility) {\n savedColumnState.visible = columnState.visible;\n }\n\n if (options.saveColumnWidths) {\n savedColumnState.width = columnState.width;\n }\n\n savedTableState.columns?.push(savedColumnState);\n }\n\n const storage =\n options.storage === 'session' ? sessionStorage : localStorage;\n try {\n storage.setItem(options.key, JSON.stringify(savedTableState));\n } catch (error) {\n console.warn('Failed to save table state', error);\n }\n }\n\n private loadStateFromStorage() {\n if (!this.storageOptions) {\n return;\n }\n\n const options = { ...DEFAULT_STORAGE_OPTIONS, ...this.storageOptions };\n const json = localStorage.getItem(options.key);\n if (!json) {\n return;\n }\n\n try {\n const savedTableState = JSON.parse(json) as RestorableTableState<T>;\n const tableStateToRestore: RestorableTableState<T> = {};\n\n if (options.saveSearchQuery) {\n tableStateToRestore.searchQuery = savedTableState.searchQuery;\n }\n\n if (options.saveSelectedRows) {\n tableStateToRestore.selectedRows = savedTableState.selectedRows;\n }\n\n if (savedTableState.columns) {\n tableStateToRestore.columns = [];\n for (const savedColumnState of savedTableState.columns) {\n const columnStateToRestore: RestorableColumnState<T> = {\n field: savedColumnState.field,\n };\n\n if (options.saveColumnVisibility) {\n columnStateToRestore.visible = savedColumnState.visible;\n }\n\n if (options.saveColumnWidths) {\n columnStateToRestore.width = savedColumnState.width;\n }\n\n if (options.saveColumnSortOrders) {\n columnStateToRestore.sort = savedColumnState.sort;\n }\n tableStateToRestore.columns.push(columnStateToRestore);\n }\n }\n\n this.updateTableState(tableStateToRestore);\n this.hasRestoredState = true;\n } catch (error) {\n console.error('Failed to restore DataTable state:', error);\n }\n }\n\n // #endregion\n}\n\nexport type ControllerEventMap = {\n [YatlColumnReorderEvent.EVENT_NAME]: YatlColumnReorderEvent;\n [YatlColumnResizeEvent.EVENT_NAME]: YatlColumnResizeEvent;\n [YatlColumnSortEvent.EVENT_NAME]: YatlColumnSortEvent;\n [YatlColumnToggleEvent.EVENT_NAME]: YatlColumnToggleEvent;\n [YatlRowSelectEvent.EVENT_NAME]: YatlRowSelectEvent;\n [YatlTableSearchEvent.EVENT_NAME]: YatlTableSearchEvent;\n [YatlTableStateChangeEvent.EVENT_NAME]: YatlTableStateChangeEvent;\n [YatlTableViewChangeEvent.EVENT_NAME]: YatlTableViewChangeEvent;\n};\n\ninterface RowMetadata {\n id: RowId;\n index: number;\n searchScore?: number;\n /** Precomputed search tokens */\n searchTokens: Record<string, string[]>;\n /** Precomputed search values */\n searchValues: Record<string, string>;\n /** Precomputed sort values */\n sortValues: Record<string, number | null>;\n highlightIndices?: Record<string, [number, number][]>;\n selected: boolean;\n}\n\ninterface SearchResult {\n score: number;\n ranges: [number, number][]; // Array of [start, end] tuples\n}\n\nlet _hasWarnedMissingId = false;\nfunction warnMissingId() {\n if (_hasWarnedMissingId) return;\n _hasWarnedMissingId = true;\n\n console.warn(\n `[yatl-table] Data rows are missing a unique 'id' or 'key' property.\n Falling back to array index.\n Selection and sorting may behave unexpectedly.\n Please provide a unique ID via the 'rowIdCallback' property.\n `,\n );\n}\n\nlet _hasWarnedInvalidIdFunction = false;\nfunction warnInvalidIdFunction<T>(index: number, rowId: RowId, row: T) {\n if (_hasWarnedInvalidIdFunction) return;\n _hasWarnedInvalidIdFunction = true;\n console.warn(\n `[yatl-table] rowIdCallback returned non-unique id (${rowId}) for data at index ${index}.\n Falling back to array index.\n Selection and sorting may behave unexpectedly.\n `,\n );\n console.debug(row);\n}\n","import { css } from 'lit';\n\n/**\n * we separate the CSS variable names between internal '--yatl' and external '--yatl-table'\n * so that way users can more easily customize the table. Instead of having to apply the\n * overrides to the element itself, they can apply them to the root. So DON'T think this\n * is overly complicated and should be cleaned up by combining the --yatl-* and --yatl-table-* variables.\n */\nexport default css`\n @layer base, striped, hover, selected;\n\n :host {\n --table-cell-padding: var(\n --yatl-table-cell-padding,\n var(--yatl-spacing-m) var(--yatl-spacing-m)\n );\n --table-header-padding: var(\n --yatl-table-header-padding,\n var(--yatl-spacing-m) var(--yatl-spacing-l)\n );\n\n --table-text: var(--yatl-table-text, var(--yatl-text-1));\n --table-bg: var(--yatl-table-bg, var(--yatl-surface-1));\n --table-radius: var(--yatl-table-radius, var(--yatl-radius-m));\n --table-border-width: var(--yatl-table-border-width, 1px);\n --table-border-color: var(\n --yatl-table-border-color,\n var(--yatl-border-color)\n );\n\n --table-header-text: var(--yatl-table-header-text, var(--yatl-text-1));\n --table-header-bg: var(\n --yatl-table-header-bg,\n color-mix(in srgb, var(--yatl-color-mix) 4%, var(--table-bg))\n );\n --table-header-hover-bg: var(\n --yatl-table-header-hover-bg,\n color-mix(in srgb, var(--yatl-color-mix) 4%, var(--table-header-bg))\n );\n --table-header-drop-bg: var(\n --yatl-table-header-drop-bg,\n color-mix(in srgb, var(--yatl-color-mix) 4%, var(--table-header-bg))\n );\n\n --table-row-text: var(--yatl-table-row-text, var(--yatl-text-1));\n --table-row-bg: var(\n --yatl-table-row-bg,\n color-mix(in srgb, var(--yatl-color-mix) 2%, var(--table-bg))\n );\n --table-row-hover-bg: var(\n --yatl-table-row-hover-bg,\n var(--table-header-bg)\n );\n --table-row-stripe-bg: var(\n --yatl-table-row-stripe-bg,\n color-mix(in srbg, var(--yatl-color-mix) 3%, var(--table-bg))\n var(--table-header-bg)\n );\n --table-row-selected-bg: var(\n --yatl-table-row-selected-bg,\n color-mix(in srgb, var(--yatl-color-brand) 20%, transparent)\n );\n --table-footer-text: var(--yatl-table-footer-text, var(--yatl-text-3));\n --table-selector-color: var(\n --yatl-table-selector-color,\n color-mix(in srgb, var(--table-row-bg), var(--yatl-color-brand, black) 5%)\n );\n\n --table-row-number-column-width: var(\n --yatl-table-row-number-column-width,\n 48px\n );\n --table-row-selector-column-width: var(\n --yatl-table-row-selector-column-width,\n 48px\n );\n --table-column-visibility-transition: var(\n --yatl-table-column-visibility-transition,\n 100ms\n );\n\n /* Resize grab handle width */\n --resizer-width: var(--yatl-table-column-resizer-width, 10px);\n\n /* z-index for the header */\n --header-z-index: 2;\n }\n\n @layer base {\n .table {\n border-radius: var(--table-radius);\n background-color: var(--table-bg);\n border: var(--table-border-width) solid var(--table-border-color);\n }\n\n .row {\n position: relative;\n background-color: var(--table-row-bg);\n border-bottom: 1px solid var(--table-border-color);\n transition: background-color 50ms;\n }\n\n .row.header-row {\n background-color: var(--table-header-bg);\n border-bottom: 1px solid var(--table-border-color);\n font-weight: 600;\n color: var(--table-header-text);\n }\n\n .body .row {\n background-color: var(--table-row-bg);\n }\n\n .row:last-child {\n border-bottom: none;\n }\n\n .table:not(.resizing) .row {\n transition: grid-template-columns\n var(--table-column-visibility-transition);\n }\n\n .cell {\n align-items: center;\n padding: var(--table-cell-padding);\n }\n\n .table.resizing * {\n cursor: col-resize !important;\n }\n\n .header .cell {\n padding: var(--table-header-padding);\n }\n\n .footer {\n padding: 8px 12px;\n background-color: var(--table-header-bg);\n border-top: 1px solid var(--table-border-color);\n color: var(--table-footer-text);\n font-size: 0.8em;\n }\n\n .resizer::after {\n height: 60%;\n width: 1px;\n background-color: color-mix(in srgb, currentcolor 30%, transparent);\n transition: background-color 0.2s;\n }\n\n .row-number-cell {\n background-color: var(--table-header-bg);\n }\n\n .message {\n font-size: large;\n }\n }\n\n @layer striped {\n :host([striped]) .body .row:nth-child(even) {\n background-color: var(--table-row-stripe-bg);\n }\n }\n\n @layer hover {\n .table:not(.resizing) .header .cell:hover {\n background-color: var(--table-header-hover-bg);\n }\n\n .body .row:hover {\n background-color: var(--table-row-hover-bg);\n }\n\n .resizer:hover::after {\n background-color: currentcolor;\n width: 2px;\n }\n\n .drop-indicator {\n background: var(--table-header-drop-bg);\n }\n }\n\n @layer selected {\n /* Use after element to blend selection color */\n .body .row.selected::after {\n content: '';\n position: absolute;\n inset: 0;\n pointer-events: none;\n transition: background-color 50ms;\n z-index: 1;\n background-color: var(--table-row-selected-bg);\n }\n }\n\n /* Layout stuff\n * Most of this is functional and needed\n * for the table to work properly. \n * Modify with caution!\n */\n /* stylelint-disable-next-line no-duplicate-selectors */\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .table {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .scroller {\n box-sizing: border-box;\n overflow: auto;\n width: 100%;\n height: 100%;\n }\n\n .body {\n min-width: 100%;\n width: fit-content;\n height: fit-content;\n }\n\n .header {\n z-index: var(--header-z-index);\n flex-shrink: 0;\n position: sticky;\n top: 0;\n }\n\n .header-content {\n position: relative;\n width: 100%;\n display: flex;\n flex-direction: row;\n align-items: baseline;\n gap: 0.5rem;\n }\n\n .sort-icon {\n display: none;\n position: relative;\n width: 1ch;\n align-self: stretch;\n padding: 0;\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .sort-icon.ascending,\n .sort-icon.descending {\n display: block;\n }\n\n .sort-icon::after {\n content: '';\n position: absolute;\n }\n\n .sort-icon.ascending::after {\n content: '\\\\2191';\n }\n\n .sort-icon.descending::after {\n content: '\\\\2193';\n }\n\n .resizer {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n width: var(--resizer-width);\n cursor: col-resize;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n .resizer::after {\n content: '';\n display: block;\n }\n\n .drop-indicator {\n display: none;\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: calc(var(--header-z-index) + 1);\n }\n\n .drop-indicator.active {\n display: block;\n }\n\n .sortable {\n cursor: pointer;\n }\n\n /* Footer */\n .footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n position: sticky;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: var(--header-z-index);\n }\n\n /* Generic table parts */\n .row {\n display: grid;\n grid-template-columns: var(--grid-template);\n\n /* This is required! Don't remove it. */\n min-width: 100%;\n width: fit-content;\n }\n\n .cell-wrapper {\n padding: 0;\n overflow: hidden;\n min-width: 0;\n }\n\n .cell {\n white-space: nowrap;\n overflow: hidden;\n position: relative;\n display: flex;\n align-items: center;\n height: 100%;\n box-sizing: border-box;\n min-width: 0;\n }\n\n /* Add the padding to the child */\n .cell:has(.row-number-cell),\n .cell:has(.row-selector-cell),\n .row-selector-cell {\n padding: 0;\n }\n\n .row-number-cell,\n .row-selector-cell > label {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n padding: var(--table-cell-padding);\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n }\n\n .message {\n position: absolute;\n inset: 0;\n text-align: center;\n pointer-events: none;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .truncate {\n display: block;\n white-space: nowrap;\n overflow: hidden;\n }\n`;\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["query","state","import_lit","state","query","priority","import_lit","state","query","field"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/events.ts","../src/utils/columns.ts","../src/utils/common.ts","../src/utils/tokenizer.ts","../src/utils/typed-event-target.ts","../src/table/utils.ts","../src/table/table.ts","../src/table-controller/utils.ts","../src/table-controller/table-controller.ts","../src/table/table.styles.ts"],"sourcesContent":["export * from './events';\nexport * from './table/table';\nexport * from './table-controller/table-controller';\nexport * from './types';\nexport * from './utils';\n","import {\n NestedKeyOf,\n RowId,\n SortOrder,\n TableState,\n UnspecifiedRecord,\n} from './types';\n\n/**\n * Base event class that bubbles and is composed.\n */\nexport abstract class YatlEvent extends Event {\n constructor(name: string, options: EventInit = {}) {\n super(name, {\n bubbles: true,\n composed: true,\n cancelable: false,\n ...options,\n });\n }\n\n public abstract clone(): YatlEvent;\n}\n\nexport class YatlRowClickEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-row-click';\n\n constructor(\n public readonly row: T,\n public readonly rowId: RowId,\n public readonly index: number,\n public readonly field: NestedKeyOf<T>,\n public readonly originalEvent: MouseEvent,\n ) {\n super(YatlRowClickEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlRowClickEvent<T>(\n this.row,\n this.rowId,\n this.index,\n this.field,\n this.originalEvent,\n );\n }\n}\n\nexport class YatlRowSelectRequest extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-row-select-request';\n\n constructor(\n public readonly rowId: RowId,\n public readonly selected: boolean,\n public readonly currentlySelectedRows: RowId[],\n ) {\n super(YatlRowSelectRequest.EVENT_NAME, { cancelable: true });\n }\n\n public override clone() {\n return new YatlRowSelectRequest(\n this.rowId,\n this.selected,\n this.currentlySelectedRows,\n );\n }\n}\n\nexport class YatlRowSelectEvent extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-row-select';\n\n constructor(\n public readonly selectedIds: RowId[],\n public readonly previouslySelectedRows: RowId[],\n ) {\n super(YatlRowSelectEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlRowSelectEvent(\n this.selectedIds,\n this.previouslySelectedRows,\n );\n }\n}\n\nexport class YatlColumnSortRequest<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-sort-request';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly order: SortOrder | null,\n public readonly multisort: boolean,\n ) {\n super(YatlColumnSortRequest.EVENT_NAME, { cancelable: true });\n }\n\n public override clone() {\n return new YatlColumnSortRequest<T>(this.field, this.order, this.multisort);\n }\n}\n\nexport class YatlColumnSortEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-sort';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly order: SortOrder | null,\n public readonly multisort: boolean,\n ) {\n super(YatlColumnSortEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnSortEvent<T>(this.field, this.order, this.multisort);\n }\n}\n\nexport class YatlColumnToggleEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-toggle';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly visible: boolean,\n ) {\n super(YatlColumnToggleEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnToggleEvent<T>(this.field, this.visible);\n }\n}\n\nexport class YatlColumnResizeEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-resize';\n\n constructor(\n public readonly field: NestedKeyOf<T>,\n public readonly width: number | null,\n ) {\n super(YatlColumnResizeEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnResizeEvent<T>(this.field, this.width);\n }\n}\n\nexport class YatlColumnReorderRequest<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-reorder-request';\n\n constructor(\n public readonly movedColumn: NestedKeyOf<T>,\n public readonly originalIndex: number,\n public readonly newIndex: number,\n ) {\n super(YatlColumnReorderRequest.EVENT_NAME, { cancelable: true });\n }\n\n public override clone() {\n return new YatlColumnReorderRequest<T>(\n this.movedColumn,\n this.originalIndex,\n this.newIndex,\n );\n }\n}\n\nexport class YatlColumnReorderEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-column-reorder';\n\n constructor(public readonly order: NestedKeyOf<T>[]) {\n super(YatlColumnReorderEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlColumnReorderEvent<T>(this.order);\n }\n}\n\nexport class YatlTableSearchEvent extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-table-search';\n\n constructor(public readonly query: string) {\n super(YatlTableSearchEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlTableSearchEvent(this.query);\n }\n}\n\nexport class YatlTableViewChangeEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-table-view-change';\n\n constructor(public readonly data: T[]) {\n super(YatlTableViewChangeEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlTableViewChangeEvent<T>(this.data);\n }\n}\n\nexport class YatlTableStateChangeEvent<\n T extends object = UnspecifiedRecord,\n> extends YatlEvent {\n public static readonly EVENT_NAME = 'yatl-table-state-change';\n\n constructor(\n public readonly state: TableState<T>,\n public readonly triggers: string[],\n ) {\n super(YatlTableStateChangeEvent.EVENT_NAME);\n }\n\n public override clone() {\n return new YatlTableStateChangeEvent<T>(this.state, this.triggers);\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [YatlRowClickEvent.EVENT_NAME]: YatlRowClickEvent;\n\n [YatlRowSelectRequest.EVENT_NAME]: YatlRowSelectRequest;\n [YatlRowSelectEvent.EVENT_NAME]: YatlRowSelectEvent;\n\n [YatlColumnSortRequest.EVENT_NAME]: YatlColumnSortRequest;\n [YatlColumnSortEvent.EVENT_NAME]: YatlColumnSortEvent;\n\n [YatlColumnToggleEvent.EVENT_NAME]: YatlColumnToggleEvent;\n\n [YatlColumnResizeEvent.EVENT_NAME]: YatlColumnResizeEvent;\n\n [YatlColumnReorderRequest.EVENT_NAME]: YatlColumnReorderRequest;\n [YatlColumnReorderEvent.EVENT_NAME]: YatlColumnReorderEvent;\n\n [YatlTableSearchEvent.EVENT_NAME]: YatlTableSearchEvent;\n [YatlTableViewChangeEvent.EVENT_NAME]: YatlTableViewChangeEvent;\n [YatlTableStateChangeEvent.EVENT_NAME]: YatlTableStateChangeEvent;\n }\n}\n","import {\n ColumnOptions,\n ColumnState,\n DisplayColumnOptions,\n InternalColumnOptions,\n NestedKeyOf,\n} from '../types';\n\nexport function findColumn<\n TData extends Record<string, unknown>,\n TCol extends { field: NestedKeyOf<TData> },\n>(columns: TCol[], field: NestedKeyOf<TData>) {\n return columns.find(c => c.field === field);\n}\n\nexport function isInternalColumn<T>(\n col: ColumnOptions<T> | undefined | null,\n): col is InternalColumnOptions<T> {\n return col?.role === 'internal';\n}\n\nexport function isDisplayColumn<T>(\n col: ColumnOptions<T> | undefined | null,\n): col is DisplayColumnOptions<T> {\n return col?.role !== 'internal';\n}\n\nexport function createState<T>(\n field: NestedKeyOf<T>,\n defaults?: Partial<ColumnState<T>>,\n): ColumnState<T> {\n return {\n field,\n visible: defaults?.visible ?? true,\n width: defaults?.width ?? null,\n sort: defaults?.sort ? { ...defaults.sort } : null,\n };\n}\n\nexport function getColumnStateChanges<T>(\n oldState: ColumnState<T> | undefined,\n newState: ColumnState<T>,\n): (keyof ColumnState<T>)[] {\n if (oldState && oldState.field !== newState.field) {\n throw Error(\n `attempting to compare states for different fields: ${oldState.field}, ${newState.field}`,\n );\n }\n\n const changes: (keyof ColumnState<T>)[] = [];\n if (oldState?.visible !== newState.visible) {\n changes.push('visible');\n }\n\n if (oldState?.width !== newState.width) {\n changes.push('width');\n }\n\n if (\n oldState?.sort !== newState.sort ||\n oldState.sort?.order !== newState.sort?.order ||\n oldState.sort?.priority !== newState.sort?.priority\n ) {\n changes.push('sort');\n }\n\n return changes;\n}\n","import { RowId, RowSelectionMethod } from '../types';\n\nexport function isRowIdType(value: unknown): value is RowId {\n return typeof value === 'string' || typeof value === 'number';\n}\n\nexport function isRowSelectionMethod(\n value: string | null,\n): value is RowSelectionMethod {\n return value === null || value === 'multi' || value === 'single';\n}\n\nfunction isValidKey<K extends string>(\n key: string,\n obj: Record<K, unknown>,\n): key is K {\n return key in obj;\n}\n\n/**\n * Get a value from an object based on a path.\n * @param obj - The object to get the value from\n * @param path - The path of the value\n * @returns The value found at the given path\n */\nexport function getNestedValue(obj: object, path: string): unknown {\n const keys = path.split('.');\n\n let current = obj;\n\n for (const key of keys) {\n if (current && isValidKey(key, current)) {\n current = current[key];\n } else {\n return undefined;\n }\n }\n\n return current;\n}\n\nexport function setNestedValue(obj: object, path: string, value: unknown) {\n const keys = path.split('.');\n const finalProp = keys.at(-1);\n if (!finalProp) {\n throw new Error('Cannot set nested value with empty path');\n }\n\n let current = obj;\n for (const key of keys.slice(0, -1)) {\n if (!isValidKey(key, current)) {\n const newObj = {};\n Object.assign(current, { [key]: newObj });\n current = newObj;\n } else {\n current = current[key];\n }\n }\n\n Object.assign(current, { [finalProp]: value });\n}\n","export const createRegexTokenizer = (exp: string = '\\\\S+') => {\n const regex = new RegExp(`\"[^\"]*\"|${exp}`, 'g');\n\n return (value: string) => {\n // Find all matches, which will include the quotes\n const matches = value.match(regex) || [];\n\n // Clean up the results by removing the surrounding quotes\n return matches.map(token => {\n token = token.toLocaleLowerCase().trim();\n if (token.startsWith('\"') && token.endsWith('\"')) {\n return { value: token.slice(1, -1), quoted: true };\n }\n return { value: token, quoted: false };\n });\n };\n};\n\nexport const whitespaceTokenizer = createRegexTokenizer();\n","export class TypedEventTarget<\n TEventMap extends Record<string, Event>,\n> extends EventTarget {\n public override addEventListener<K extends keyof TEventMap>(\n type: K,\n listener: (this: TEventMap, ev: TEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n public override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n public override addEventListener(\n type: string,\n listener: unknown,\n options?: boolean | AddEventListenerOptions,\n ) {\n super.addEventListener(\n type,\n listener as EventListenerOrEventListenerObject,\n options,\n );\n }\n\n public override removeEventListener<K extends keyof TEventMap>(\n type: K,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ): void;\n\n public override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ): void {\n super.removeEventListener(type, listener, options);\n }\n\n public override dispatchEvent<K extends keyof TEventMap>(\n event: TEventMap[K],\n ): boolean {\n return super.dispatchEvent(event);\n }\n}\n","import { html, TemplateResult } from 'lit';\n\n/**\n * Highlights sections of a string based on index ranges.\n * @param text - The original string to render.\n * @param ranges - An array of [start, end] tuples representing matches.\n * @returns A Lit TemplateResult with <mark> tags, or the original string if no ranges exist.\n */\nexport function highlightText(\n text: string,\n ranges: [number, number][],\n): TemplateResult | string {\n if (!text || !ranges || ranges.length === 0) {\n return text;\n }\n\n // 1. Sort ranges by start position to process linearly\n const sortedRanges = [...ranges].sort((a, b) => a[0] - b[0]);\n\n // 2. Merge overlapping ranges\n // Example: [[0, 5], [2, 6]] becomes [[0, 6]]\n const mergedRanges: [number, number][] = [];\n let currentRange = sortedRanges[0];\n\n for (let i = 1; i < sortedRanges.length; i++) {\n const nextRange = sortedRanges[i];\n\n if (nextRange[0] < currentRange[1]) {\n // Overlap detected: Extend the current end if needed\n currentRange[1] = Math.max(currentRange[1], nextRange[1]);\n } else {\n // No overlap: Push current and start a new one\n mergedRanges.push(currentRange);\n currentRange = nextRange;\n }\n }\n mergedRanges.push(currentRange);\n\n // 3. Slice the string\n const result: (string | TemplateResult)[] = [];\n let lastIndex = 0;\n\n for (const [start, end] of mergedRanges) {\n // Clamp values to prevent out-of-bounds errors\n const safeStart = Math.max(0, Math.min(start, text.length));\n const safeEnd = Math.max(0, Math.min(end, text.length));\n\n // Append non-highlighted text before the match\n if (safeStart > lastIndex) {\n result.push(text.slice(lastIndex, safeStart));\n }\n\n // Append highlighted text\n // We use the 'mark' tag, but you can change this to a span with a class\n result.push(\n html`<mark class=\"highlight\">${text.slice(safeStart, safeEnd)}</mark>`,\n );\n\n lastIndex = safeEnd;\n }\n\n // 4. Append any remaining text after the last match\n if (lastIndex < text.length) {\n result.push(text.slice(lastIndex));\n }\n\n return html`${result}`;\n}\n\n/*\n * Converts a string to a human-readable format.\n * - Replaces underscores with spaces\n * - Inserts spaces before uppercase letters (for camelCase)\n * - Capitalizes the first letter of each word\n *\n * @param {string} str - The input string to convert.\n * @returns {string} - The converted human-readable string.\n */\nexport const toHumanReadable = (str: string) => {\n return (\n str\n // Replace underscores with spaces\n .replace(/_/g, ' ')\n // Insert spaces before uppercase letters (for camelCase)\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Capitalize the first letter of each word\n .replace(/\\b\\w/g, char => char.toUpperCase())\n );\n};\n","import type {\n ColumnOptions,\n ColumnState,\n DisplayColumnOptions,\n ExportOptions,\n NestedKeyOf,\n RestorableColumnState,\n RestorableTableState,\n RowId,\n RowPartsCallback,\n SortOrder,\n TableState,\n UnspecifiedRecord,\n} from '../types';\n\nimport {\n getColumnStateChanges,\n getNestedValue,\n isDisplayColumn,\n} from '../utils';\n\nimport { highlightText, toHumanReadable } from './utils';\n\nimport {\n YatlColumnReorderRequest,\n YatlColumnSortRequest,\n YatlRowClickEvent,\n YatlRowSelectRequest,\n} from '../events';\n\nimport { html, LitElement, nothing, TemplateResult } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { styleMap } from 'lit/directives/style-map.js';\n\nimport '@lit-labs/virtualizer';\nimport { LitVirtualizer } from '@lit-labs/virtualizer';\nimport { YatlEvent } from '../events';\nimport {\n ControllerEventMap,\n YatlTableController,\n} from '../table-controller/table-controller';\nimport styles from './table.styles';\n\n// #region --- Constants ---\n\n// #endregion\n\n/**\n * A virtualized data table capable of handling complex sorting, filtering, and tokenized searching.\n *\n * @element yatl-table\n * @summary A high-performance grid engine for rugged environments.\n *\n * @fires yatl-row-click - Fired when a user clicks a row.\n * @fires yatl-row-select-request - Fired before the row selection changes. Cancellable\n * @fires yatl-row-select - Fired when the row selection changes.\n * @fires yatl-column-sort-request - Fired before a column sort order changes. Cancellable.\n * @fires yatl-column-sort - Fired when a column sort order changes.\n * @fires yatl-column-toggle - Fired when a column's visibility changes.\n * @fires yatl-column-resize - Fired after a column has been resized by the user.\n * @fires yatl-column-reorder-request - Fired when the user drops a column into a new position. Cancellable.\n * @fires yatl-column-reorder - Fired after the column order changes.\n * @fires yatl-table-search - Fired when the search query is updated.\n * @fires yatl-table-view-change - Fired when the visible slice of data changes due to sorting, filtering, or data updates. Payload contains the processed rows.\n * @fires yatl-table-state-change - Fired when any persistable state (width, order, sort, query) changes. Used for syncing with local storage.\n */\n@customElement('yatl-table')\nexport class YatlTable<\n T extends object = UnspecifiedRecord,\n> extends LitElement {\n public static override styles = [styles];\n\n @query('.table')\n private tableElement!: HTMLElement;\n @query('lit-virtualizer')\n private virtualizer?: LitVirtualizer;\n\n // #region --- State Data ---\n\n // Property data\n\n private resizeState: {\n active: boolean;\n startX: number;\n startWidth: number;\n columnIndex: number;\n columnField: NestedKeyOf<T>;\n currentWidths: string[];\n } | null = null;\n\n // Column drag & drop state\n private dragColumn: NestedKeyOf<T> | null = null;\n\n @state() private useYatlUi = false;\n\n // #endregion\n\n // #region --- Properties ---\n\n private _controller = new YatlTableController<T>(this);\n @property({ attribute: false })\n public get controller() {\n return this._controller;\n }\n\n public set controller(controller) {\n if (this._controller === controller) {\n return;\n }\n\n const oldController = this._controller;\n if (this.isConnected) {\n this.removeControllerListeners(oldController);\n this.addControllerListeners(controller);\n }\n\n oldController.detach(this);\n controller.attach(this);\n\n this._controller = controller;\n this.requestUpdate('controller', oldController);\n }\n\n @property({ type: Boolean, reflect: true })\n public striped = true;\n\n /**\n * Default sortability for all columns.\n * Can be overridden by setting `sortable` on the specific column definition.\n * * **NOTE:** Changing this will not clear sorted column states.\n * @default false\n */\n @property({ type: Boolean, attribute: 'sortable' })\n public sortable = true;\n\n /**\n * Default resizability for all columns.\n * Can be overridden by setting `resizable` on the specific column definition.\n * * **NOTE:** Changing this will not clear current column widths.\n * @default false\n */\n @property({ type: Boolean, attribute: 'resizable' })\n public resizable = true;\n\n /**\n * Enables virtual scrolling for the table.\n * When enabled, only the visible rows are rendered to the DOM, significantly improving\n * performance for large datasets (1000+ rows).\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-virtual-scroll' })\n public enableVirtualScroll = false;\n\n /**\n * When enabled, text matching the current search query will be wrapped in `<mark>` tags.\n * This applies to all visible cells that contain the search term.\n * This does NOT apply to content rendered by the user such as the ColumnOptions.render callback.\n * @default true\n */\n @property({ type: Boolean, attribute: 'enable-search-highlight' })\n public enableSearchHighlight = true;\n\n /**\n * Enables tokenized search behavior.\n * When enabled, the search query is split into individual tokens using the\n * `searchTokenizer` function (defaults to splitting on whitespace).\n * A row is considered a match if **ANY** of the tokens appear in the searchable fields.\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-search-tokenization' })\n public get enableSearchTokenization() {\n return this.controller.enableSearchTokenization;\n }\n\n public set enableSearchTokenization(enable) {\n const oldValue = this.enableSearchTokenization;\n if (oldValue === enable) {\n return;\n }\n\n this.controller.enableSearchTokenization = enable;\n this.requestUpdate('enableSearchTokenization', oldValue);\n }\n\n /**\n * Enables weighted relevance scoring for search results.\n * When enabled, exact matches and prefix matches are ranked higher than substring matches.\n * Rows are sorted by their relevance score descending.\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-search-scoring' })\n public get enableSearchScoring() {\n return this.controller.enableSearchScoring;\n }\n\n public set enableSearchScoring(enable) {\n const oldValue = this.enableSearchScoring;\n if (oldValue === enable) {\n return;\n }\n\n this.controller.enableSearchScoring = enable;\n this.requestUpdate('enableSearchScoring', oldValue);\n }\n\n /**\n * Allows users to reorder columns by dragging and dropping headers.\n * @default true\n */\n @property({ type: Boolean, attribute: 'enable-column-reorder' })\n public enableColumnReorder = true;\n\n /**\n * Shows a column to the left of each row with its row number.\n */\n @property({ type: Boolean })\n public enableRowNumberColumn = true;\n\n /**\n * Shows the built-in footer row which displays the current record count.\n * The footer content can be customized using the `slot=\"footer\"` element.\n * @default false\n */\n @property({ type: Boolean, attribute: 'enable-footer' })\n public enableFooter = true;\n\n /**\n * The string to display in a cell when the data value is `null` or `undefined`.\n * @default \"-\"\n */\n @property({ type: String, attribute: 'null-value-placeholder' })\n public nullValuePlaceholder = '-';\n\n /**\n * The message displayed when the `data` array is empty.\n * @default \"No records to display\"\n */\n @property({ type: String, attribute: 'empty-message' })\n public emptyMessage = 'No records to display';\n\n /**\n * The message displayed when `data` exists but the current search/filter\n * results in zero visible rows.\n * @default \"No matching records found\"\n */\n @property({ type: String, attribute: 'no-results-message' })\n public noResultsMessage = 'No matching records found';\n\n /**\n * The definitions for the columns to be rendered.\n * This defines the field mapping, titles, sortability, and other static options.\n */\n @property({ attribute: false })\n public get columns() {\n return this.controller.columns;\n }\n\n public set columns(columns) {\n const oldValue = this.columns;\n if (oldValue === columns) {\n return;\n }\n\n for (const column of columns) {\n if (isDisplayColumn(column) && column.title === undefined) {\n column.title = toHumanReadable(column.field);\n }\n }\n\n this.controller.columns = columns;\n this.requestUpdate('columns', oldValue);\n }\n\n /**\n * Gets a list of columns with the display role\n * **This will always be ordered the same as the visual column order**\n */\n public get displayColumns() {\n return this.controller.displayColumns;\n }\n\n @property({ attribute: false })\n public get columnStates() {\n return this.controller.columnStates;\n }\n\n public set columnStates(states) {\n const oldValue = this.columnStates;\n\n let changed = false;\n for (const state of states) {\n const oldState = this.getColumnState(state.field);\n const stateChanges = getColumnStateChanges(oldState, state);\n if (stateChanges.length) {\n changed = true;\n break;\n }\n }\n\n if (!changed) {\n return;\n }\n\n this.controller.columnStates = states;\n this.requestUpdate('columnStates', oldValue);\n }\n\n /**\n * The current text string used to filter the table data.\n * Setting this property triggers a new search and render cycle.\n */\n @property({ type: String, attribute: 'search-query' })\n public get searchQuery() {\n return this.controller.searchQuery;\n }\n\n public set searchQuery(query) {\n const oldValue = this.searchQuery;\n if (oldValue === query) {\n return;\n }\n\n this.controller.searchQuery = query;\n this.requestUpdate('searchQuery', oldValue);\n }\n\n /**\n * A function that splits the search query into tokens.\n * Only used if `enableSearchTokenization` is true.\n * @default whitespaceTokenizer\n */\n @property({ attribute: false })\n public get searchTokenizer() {\n return this.controller.searchTokenizer;\n }\n\n public set searchTokenizer(tokenizer) {\n const oldValue = this.searchTokenizer;\n if (oldValue === tokenizer) {\n return;\n }\n\n this.controller.searchTokenizer = tokenizer;\n this.requestUpdate('searchTokenizer', oldValue);\n }\n\n /**\n * An optional set of criteria to filter the visible rows.\n * This runs **before** the global search query is applied.\n * * You can provide:\n * 1. A **Partial Object**: matches rows where specific keys equal specific values (AND logic).\n * 2. A **Callback Function**: returns `true` to keep the row, `false` to hide it.\n * * @example\n * // 1. Object Syntax (Simple Exact Match)\n * // Shows rows where status is 'active' AND role is 'admin'\n * table.filters = { status: 'active', role: 'admin' };\n * * @example\n * // 2. Callback Syntax (Complex Logic)\n * // Shows rows where age is over 21 OR they are a VIP\n * table.filters = (row) => row.age > 21 || row.isVip;\n */\n @property({ attribute: false })\n public get filters() {\n return this.controller.filters;\n }\n\n public set filters(filters) {\n const oldValue = this.filters;\n if (oldValue === filters) {\n return;\n }\n\n this.controller.filters = filters;\n this.requestUpdate('filters', oldValue);\n }\n\n /**\n * A callback function to conditionally apply CSS parts to table rows.\n */\n @property({ attribute: false })\n public rowParts: RowPartsCallback<T> | null = null;\n\n /**\n * The row selection method to use.\n * * single - Only a single row can be selected at a time\n * * multi - Multiple rows can be selected at a time\n * * null - Disable row selection\n */\n @property({ type: String })\n public get rowSelectionMethod() {\n return this.controller.rowSelectionMethod;\n }\n\n public set rowSelectionMethod(selection) {\n const oldValue = this.rowSelectionMethod;\n if (oldValue === selection) {\n return;\n }\n\n this.controller.rowSelectionMethod = selection;\n this.requestUpdate('rowSelectionMethod', oldValue);\n }\n\n /**\n * List of currently selected row indexes.\n * * **NOTE**: These indexes are based off the of\n * the original data array index, *not* the filtered data.\n */\n @property({ attribute: false })\n public get selectedRowIds() {\n return this.controller.selectedRowIds;\n }\n\n public set selectedRowIds(rows) {\n const oldValue = new Set(this.selectedRowIds);\n if (oldValue.size === rows.length && rows.every(r => oldValue.has(r))) {\n return;\n }\n\n this.controller.selectedRowIds = rows;\n this.requestUpdate('selectedRows', [...oldValue]);\n }\n\n /**\n * Configuration options for automatically saving and restoring table state\n * (column width, order, visibility, etc.) to browser storage.\n */\n @property({ type: Object, attribute: 'storage-options' })\n public get storageOptions() {\n return this.controller.storageOptions;\n }\n\n public set storageOptions(options) {\n const oldValue = this.storageOptions;\n // TODO: Check if anything changed\n this.controller.storageOptions = options;\n this.requestUpdate('storageOptions', oldValue);\n }\n\n @property({ attribute: false })\n public get rowIdCallback() {\n return this.controller.rowIdCallback;\n }\n\n public set rowIdCallback(callback) {\n const oldValue = this.rowIdCallback;\n if (oldValue === callback) {\n return;\n }\n\n this.controller.rowIdCallback = callback;\n this.requestUpdate('rowIdCallback', oldValue);\n }\n\n /**\n * The array of data objects to be displayed.\n * Objects must satisfy the `WeakKey` constraint (objects only, no primitives).\n */\n @property({ attribute: false })\n public get data() {\n return this.controller.data;\n }\n\n public set data(value: T[]) {\n const oldValue = this.data;\n this.controller.data = value;\n this.requestUpdate('data', oldValue);\n }\n\n public get filteredData() {\n return this.controller.filteredData;\n }\n\n public get dataUpdateTimestamp() {\n return this.controller.dataUpdateTimestamp;\n }\n\n // #endregion\n\n // #region --- Public Methods ---\n\n public getColumn(field: NestedKeyOf<T>) {\n return this.controller.getColumn(field);\n }\n\n public getDisplayColumn(field: NestedKeyOf<T>) {\n const column = this.getColumn(field);\n if (column && isDisplayColumn(column)) {\n return column;\n }\n }\n\n /**\n * Gets a copy of the current state of the table.\n */\n public getTableState(): TableState<T> {\n return this.controller.getTableState();\n }\n\n /**\n * Restores the table to the provided state.\n * @param state - The state to restore the table to.\n */\n public updateTableState(state: RestorableTableState<T>) {\n return this.controller.updateTableState(state);\n }\n\n public getColumnState(field: NestedKeyOf<T>) {\n return this.controller.getColumnState(field);\n }\n\n public updateColumnState(\n field: NestedKeyOf<T>,\n state: RestorableColumnState<T>,\n ) {\n return this.controller.updateColumnState(field, state);\n }\n\n /**\n * Sorts the table by a specified column and order.\n * If `order` is `null`, the sort on this column is removed.\n * @param field - The field name of the column to sort by.\n * @param order - The sort order: 'asc', 'desc', or `null` to remove sorting for this column.\n * @param clear - Clear all other sorting\n */\n public sort(\n field: NestedKeyOf<T>,\n order: SortOrder | null,\n clear: boolean = true,\n ) {\n return this.controller.sort(field, order, clear);\n }\n\n /**\n * Toggles the visibility of hte specified column\n * @param field - The field name of the column to toggle.\n * @param visible - Optionally force the visibility state.\n */\n public toggleColumnVisibility(field: NestedKeyOf<T>, visible?: boolean) {\n return this.controller.toggleColumnVisibility(field, visible);\n }\n\n /**\n * Shows the specified column\n * @param field - The field name of the column to show.\n */\n public showColumn(field: NestedKeyOf<T>) {\n return this.controller.showColumn(field);\n }\n\n /**\n * Hides the specified column\n * @param field - The field name of the column to hide.\n */\n public hideColumn(field: NestedKeyOf<T>) {\n return this.controller.hideColumn(field);\n }\n\n /**\n * Moves a column to a new position\n * @param field - The column to move\n * @param newPosition The index or field of the column to move it to.\n * @returns\n */\n public moveColumn(\n field: NestedKeyOf<T>,\n newPosition: number | NestedKeyOf<T>,\n ) {\n return this.controller.moveColumn(field, newPosition);\n }\n\n public resizeColumn(field: NestedKeyOf<T>, width: number | null) {\n return this.controller.resizeColumn(field, width);\n }\n\n public isRowSelected(row: T) {\n return this.controller.isRowSelected(row);\n }\n\n /**\n * Toggles the selection state of a specific row.\n */\n public toggleRowSelection(row: T, state?: boolean) {\n return this.controller.toggleRowSelection(row, state);\n }\n\n /**\n * Selects a specific row.\n */\n public selectRow(row: T) {\n return this.controller.selectRow(row);\n }\n\n /**\n * Deselects a specific row.\n */\n public deselectRow(row: T) {\n return this.controller.deselectRow(row);\n }\n\n /**\n * Selects all currently visible rows (for \"Select All\" checkbox).\n */\n public selectAll() {\n return this.controller.selectAll();\n }\n\n /**\n * Clears all selection.\n */\n public deselectAll() {\n return this.controller.deselectAll();\n }\n\n /**\n * Export the current visible table data to a CSV file.\n * @param filename - The name of the file to save.\n * @param options - Options for configuring what should be exported.\n */\n public export(\n filename: string,\n options: ExportOptions = {\n includeAllRows: false,\n includeHiddenColumns: false,\n includeInternalColumns: false,\n },\n ) {\n const blob = this.controller.export(options);\n const a = document.createElement('a');\n a.style.display = 'none';\n a.href = URL.createObjectURL(blob);\n a.download = `${filename}.csv`;\n document.body.append(a);\n a.click();\n a.remove();\n }\n\n public scrollToRow(row: T) {\n const index = this.data.findIndex(v => v === row);\n if (typeof index === 'number') {\n return this.scrollToOriginalIndex(index);\n } else {\n throw new Error('Row not in table');\n }\n }\n\n /**\n * Scrolls the table to bring the row at the specified original index into view.\n * @param index - The original index of the row (from the initial dataset).\n */\n public scrollToOriginalIndex(index: number) {\n const rowData = this.data[index];\n if (rowData) {\n const filteredIndex = this.filteredData.indexOf(rowData);\n if (filteredIndex >= 0) {\n return this.scrollToFilteredIndex(filteredIndex);\n } else {\n throw new Error('Cannot scroll to filtered out row');\n }\n } else {\n throw new RangeError(`Row index ${index} out of range`);\n }\n }\n\n public async scrollToFilteredIndex(index: number) {\n // FIXME: Scrolling to an index using lit-virtualizer is buggy.\n // It usually stops short of the requested index.\n // The amount it stops short seems to be proportinal to how far away the index is.\n // Scrolling without VS works but since I use sticky headers, it seems to be one row off.\n\n const rowData = this.filteredData[index];\n if (!rowData) {\n throw new RangeError(`Row index ${index} out of range`);\n }\n\n await this.updateComplete;\n\n // TODO: Should I check if virtual scroll is enabled\n // or just rely on the appropriate elements existing?\n if (this.virtualizer) {\n this.virtualizer.element(index)?.scrollIntoView({\n block: 'start',\n behavior: 'instant',\n });\n } else {\n const row = this.tableElement.querySelector(\n `.row[data-filtered-index=\"${index}\"]`,\n );\n row?.scrollIntoView({\n block: 'start',\n behavior: 'smooth',\n });\n }\n }\n\n public async scrollToPx(px: number) {\n // FIXME: This doesn't work with lit-virtualizer at all.\n\n await this.updateComplete;\n\n if (this.virtualizer) {\n this.virtualizer.scrollTop = px;\n } else {\n this.tableElement.scrollTop = px;\n }\n }\n\n /**\n * Gets the row associated with the provided ID.\n * @param id - The ID of the row to get\n * @returns\n */\n public getRow(id: RowId) {\n return this.controller.getRow(id);\n }\n\n /**\n * Finds the first row where {@link field} matches {@link value}\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The found row, or undefined if no match is found.\n */\n public findRow(field: NestedKeyOf<T>, value: unknown) {\n return this.controller.findRow(field, value);\n }\n\n /**\n * Finds the original index of the first row where the specified field matches the given value.\n * This searches through the original, unfiltered dataset.\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The original index of the found row, or -1 if no match is found.\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow({description: \"Updated description\"}, index);\n * }\n * ```\n */\n public findRowIndex(field: NestedKeyOf<T>, value: unknown) {\n return this.controller.findRowIndex(field, value);\n }\n\n public updateRow(rowId: RowId, data: Partial<T>) {\n return this.controller.updateRow(rowId, data);\n }\n\n /**\n * Updates the data of a row at a specific original index.\n * @param index - The original index of the row to update.\n * @param data - An object containing the new data to assign to the row. Existing fields will be updated, and new fields will be added.\n *\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow(index, {description: \"Updated description\"});\n * }\n * ```\n */\n public updateRowAtIndex(index: number, data: Partial<T>) {\n return this.controller.updateRowAtIndex(index, data);\n }\n\n /**\n * Deletes the row with the matching ID.\n * @param rowIds - The IDs rows to delete\n */\n public deleteRow(...rowIds: RowId[]) {\n return this.controller.deleteRow(...rowIds);\n }\n\n /**\n * Deletes a row at a specific original index from the table.\n * @param index - The original index of the row to delete.\n */\n public deleteRowAtIndex(index: number) {\n return this.controller.deleteRowAtIndex(index);\n }\n\n // #endregion\n\n // #region Render Methods\n\n protected renderColumnSortIcon(\n column: DisplayColumnOptions<T>,\n state: ColumnState<T>,\n ) {\n return column.sortable ?? this.sortable\n ? html`<div\n part=\"header-sort-icon\"\n class=${classMap({\n 'sort-icon': true,\n ascending: state.sort?.order === 'asc',\n descending: state.sort?.order === 'desc',\n })}\n ></div>`\n : nothing;\n }\n\n protected renderColumnResizer(\n column: DisplayColumnOptions<T>,\n _state: ColumnState<T>,\n ) {\n return column.resizable ?? this.resizable\n ? html`\n <div\n part=\"header-resizer\"\n class=\"resizer\"\n @click=${(event: MouseEvent) => event.stopPropagation()}\n @mousedown=${(event: MouseEvent) =>\n this.handleResizeMouseDown(event, column.field)}\n ></div>\n `\n : nothing;\n }\n\n protected renderHeaderCell(column: DisplayColumnOptions<T>) {\n if (!column) {\n return nothing;\n }\n\n const state = this.getColumnState(column.field);\n const title = column.title ?? column.field;\n\n let ariaSort: 'none' | 'ascending' | 'descending' = 'none';\n if (state.sort?.order === 'asc') ariaSort = 'ascending';\n if (state.sort?.order === 'desc') ariaSort = 'descending';\n\n const role = state.visible ? 'columnheader' : undefined;\n const hidden = state.visible ? false : undefined;\n\n const classes = {\n cell: true,\n sortable: column.sortable ?? this.sortable,\n };\n\n return this.renderCellWrapper(html`\n <div\n role=${ifDefined(role)}\n aria-hidden=${ifDefined(hidden)}\n aria-sort=${ariaSort}\n aria-label=${title}\n part=\"cell header-cell\"\n class=${classMap(classes)}\n draggable=${ifDefined(this.enableColumnReorder ? true : undefined)}\n data-field=${column.field}\n @dragstart=${(event: DragEvent) =>\n this.handleDragColumnStart(event, column.field)}\n @dragenter=${this.handleDragColumnEnter}\n @dragleave=${this.handleDragColumnLeave}\n @dragover=${this.handleDragColumnOver}\n @drop=${(event: DragEvent) =>\n this.handleDragColumnDrop(event, column.field)}\n @dragend=${this.handleDragColumnEnd}\n @click=${(event: MouseEvent) => this.handleHeaderClicked(event, column)}\n >\n <div class=\"header-content\">\n <span class=\"header-title truncate\" part=\"header-title\">\n ${title}\n </span>\n ${this.renderColumnSortIcon(column, state)}\n </div>\n ${this.renderColumnResizer(column, state)}\n <div part=\"drop-indicator\" class=\"drop-indicator\"></div>\n </div>\n `);\n }\n\n protected renderRowNumberHeader() {\n return this.renderCellWrapper(\n html`<div part=\"cell-index\" class=\"cell-index\"></div>`,\n );\n }\n\n protected renderSelectionHeader() {\n return this.renderCellWrapper(\n html`<div part=\"cell-selector\" class=\"cell-selector\"></div>`,\n );\n }\n\n protected renderHeader() {\n const classes = {\n header: true,\n reorderable: this.enableColumnReorder,\n };\n return html`\n <div role=\"rowgroup\" part=\"header\" class=${classMap(classes)}>\n <div role=\"row\" class=\"row header-row\" part=\"row header-row\">\n ${this.renderRowNumberHeader()} ${this.renderSelectionHeader()}\n ${this.displayColumns.map(column => this.renderHeaderCell(column))}\n </div>\n </div>\n `;\n }\n\n protected renderCellContents(\n value: unknown,\n column: DisplayColumnOptions<T>,\n row: T,\n ) {\n if (column.cellRenderer) {\n return column.cellRenderer(value, column.field, row);\n }\n\n if (value == null) {\n return this.nullValuePlaceholder;\n }\n\n const indices = this.controller.getRowHighlightIndicies(row);\n\n return this.enableSearchHighlight && indices\n ? highlightText(String(value), indices[column.field])\n : value;\n }\n\n protected renderCell(column: DisplayColumnOptions<T>, row: T) {\n let value = getNestedValue(row, column.field);\n // Get the user parts from the raw value\n // before we call the value formatter.\n let userParts = column.cellParts?.call(this, value, column.field, row);\n if (Array.isArray(userParts)) {\n userParts = userParts.join(' ');\n }\n\n if (typeof column.valueFormatter === 'function') {\n value = column.valueFormatter(value, row);\n }\n\n return this.renderCellWrapper(html`\n <div\n role=\"cell\"\n part=\"cell body-cell cell-${column.field} ${userParts}\"\n data-field=${column.field}\n class=\"cell\"\n title=${ifDefined(value ? String(value) : undefined)}\n @click=${(event: MouseEvent) =>\n this.handleCellClick(event, row, column.field)}\n >\n <span class=\"truncate\">\n ${this.renderCellContents(value, column, row)}\n </span>\n </div>\n `);\n }\n\n protected renderCheckbox(row: T, selected: boolean) {\n return this.useYatlUi\n ? html`<yatl-checkbox\n part=\"row-checkbox\"\n class=\"row-checkbox\"\n .checked=${selected}\n @change=${(event: Event) =>\n this.handleRowSelectionClicked(event, row)}\n ></yatl-checkbox>`\n : html`<input\n part=\"row-checkbox\"\n class=\"row-checkbox\"\n type=\"checkbox\"\n .checked=${selected}\n @change=${(event: Event) =>\n this.handleRowSelectionClicked(event, row)}\n />`;\n }\n\n protected renderRowSelectorCell(row: T, selected: boolean) {\n return this.renderCellWrapper(html`\n <div part=\"cell body-cell\" class=\"cell body-cell\">\n <div part=\"row-selector-cell\" class=\"row-selector-cell\">\n <label> ${this.renderCheckbox(row, selected)} </label>\n </div>\n </div>\n `);\n }\n\n protected renderRowNumberCell(rowNumber: number) {\n return this.renderCellWrapper(html`\n <div part=\"cell body-cell\" class=\"cell body-cell\">\n <div part=\"row-number-cell\" class=\"row-number-cell\">${rowNumber}</div>\n </div>\n `);\n }\n\n protected renderRow(row: T, renderIndex: number) {\n const selected = this.isRowSelected(row);\n let userParts = this.rowParts?.(row) ?? '';\n if (Array.isArray(userParts)) {\n userParts = userParts.join(' ');\n }\n\n const classes = { row: true, selected };\n const rowIndex = renderIndex + 1;\n\n return html`\n <div\n role=\"row\"\n aria-rowindex=${rowIndex}\n aria-selected=${selected ? 'true' : 'false'}\n part=${'row ' + userParts}\n class=${classMap(classes)}\n >\n ${this.renderRowNumberCell(rowIndex)}\n ${this.renderRowSelectorCell(row, selected)}\n ${this.displayColumns.map(column => this.renderCell(column, row))}\n </div>\n `;\n }\n\n protected renderBodyContents() {\n if (!this.hasVisibleColumn()) {\n return html`\n <div part=\"message\" class=\"message\">No visible columns.</div>\n `;\n }\n\n if (this.data.length === 0) {\n return html`\n <div part=\"message\" class=\"message\">${this.emptyMessage}</div>\n `;\n }\n if (this.filteredData.length === 0) {\n return html`\n <div part=\"message\" class=\"message\">${this.noResultsMessage}</div>\n `;\n }\n\n if (this.enableVirtualScroll) {\n return html`\n <lit-virtualizer\n .items=${this.filteredData}\n .renderItem=${(item: T, index: number) =>\n this.renderRow(item, index) as TemplateResult}\n >\n </lit-virtualizer>\n `;\n }\n\n return html`\n ${repeat(\n this.filteredData,\n item => this.controller.getRowId(item),\n (item, index) => this.renderRow(item, index),\n )}\n `;\n }\n\n protected renderFooter() {\n if (!this.enableFooter) {\n return nothing;\n }\n\n const total = this.data.length;\n const filtered = this.filteredData.length;\n\n const fmt = new Intl.NumberFormat(undefined);\n const totalStr = fmt.format(total);\n const filteredStr = fmt.format(filtered);\n\n const rowCountText =\n total !== filtered\n ? `Showing ${filteredStr} of ${totalStr} records`\n : `Total records: ${totalStr}`;\n\n const formatter = Intl.DateTimeFormat(undefined, {\n dateStyle: 'short',\n timeStyle: 'short',\n });\n\n const lastUpdateText = this.dataUpdateTimestamp\n ? formatter.format(this.dataUpdateTimestamp)\n : 'Never';\n\n return html`\n <div part=\"footer\" class=\"footer\">\n <slot name=\"footer\">\n <span part=\"row-count\">${rowCountText}</span>\n <span part=\"timestamp\">${lastUpdateText}</span>\n </slot>\n </div>\n `;\n }\n\n protected override render() {\n const gridTemplate = this.getGridWidths().join(' ');\n const style = {\n '--grid-template': gridTemplate,\n };\n\n /*\n * DO NOT USE THE DEFAULT SLOT!\n * It causes whitespace like new lines in the HTML to override the body.\n */\n return html`\n <div\n role=\"table\"\n aria-label=\"Data Table\"\n aria-rowcount=${this.filteredData.length}\n part=\"table\"\n class=\"table\"\n style=${styleMap(style)}\n >\n <div class=\"scroller\">\n ${this.renderHeader()}\n <div class=\"body\" role=\"rowgroup\">\n <slot name=\"body\">${this.renderBodyContents()}</slot>\n </div>\n </div>\n ${this.renderFooter()}\n </div>\n `;\n }\n\n private renderCellWrapper(content: TemplateResult | typeof nothing) {\n return html` <div class=\"cell-wrapper\">${content}</div> `;\n }\n\n // #endregion\n // #region --- Lifecycle Methods ---\n\n public override connectedCallback(): void {\n super.connectedCallback();\n this.addControllerListeners(this.controller);\n\n // We want to use the checkbox from yatl-ui if it is available.\n // If it gets defined, rerender with it.\n if (!this.useYatlUi) {\n customElements.whenDefined('yatl-checkbox').then(() => {\n this.useYatlUi = true;\n });\n }\n }\n\n public override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeControllerListeners(this.controller);\n\n // Clean up just in case\n window.addEventListener('mousemove', this.handleResizeMouseMove);\n window.addEventListener('mouseup', this.handleResizeMouseUp);\n }\n\n // #endregion\n // #region Utilities\n\n private readonly eventNames: (keyof ControllerEventMap)[] = [\n 'yatl-column-reorder',\n 'yatl-column-resize',\n 'yatl-column-sort',\n 'yatl-column-toggle',\n 'yatl-row-select',\n 'yatl-table-search',\n 'yatl-table-state-change',\n 'yatl-table-view-change',\n ];\n\n private addControllerListeners(controller: YatlTableController<T>) {\n for (const name of this.eventNames) {\n controller.addEventListener(name, this.redispatchControllerEvent);\n }\n }\n\n private removeControllerListeners(controller: YatlTableController<T>) {\n for (const name of this.eventNames) {\n controller.removeEventListener(name, this.redispatchControllerEvent);\n }\n }\n\n private redispatchControllerEvent = (event: Event) => {\n if (event instanceof YatlEvent) {\n this.dispatchEvent(event.clone());\n }\n };\n\n private hasVisibleColumn() {\n return (\n this.displayColumns\n .map(column => this.getColumnState(column.field))\n .filter(state => state.visible).length > 0\n );\n }\n\n /**\n * Gets the width of each column in the\n * order they will appear in the grid.\n */\n private getGridWidths() {\n const widths: string[] = [];\n\n if (this.enableRowNumberColumn) {\n widths.push('var(--yatl-row-number-column-width, 48px)');\n } else {\n widths.push('0');\n }\n\n if (this.rowSelectionMethod) {\n widths.push('var(--yatl-row-selector-column-width, 48px)');\n } else {\n widths.push('0');\n }\n\n for (const column of this.displayColumns) {\n const state = this.getColumnState(column.field);\n\n // Check if we have a fixed pixel width (User resized it)\n const hasPixelWidth = state.width != null;\n\n if (state.visible) {\n if (hasPixelWidth) {\n widths.push(`${state.width}px`);\n } else {\n widths.push('minmax(0, 1fr)');\n }\n } else {\n if (hasPixelWidth) {\n widths.push('0px');\n } else {\n widths.push('minmax(0, 0fr)');\n }\n }\n }\n\n return widths;\n }\n\n // #endregion\n\n // #region --- Event Handlers ---\n\n private handleHeaderClicked = (\n event: MouseEvent,\n column: ColumnOptions<T>,\n ) => {\n const cell = event.currentTarget as HTMLElement;\n // Ignore header click events while resizing\n if (!cell.classList.contains('sortable') || this.resizeState) {\n return;\n }\n\n const multiSort = event.shiftKey;\n const state = this.getColumnState(column.field);\n let sortOrder: SortOrder | null = null;\n if (!state?.sort) {\n sortOrder = 'asc';\n } else if (state.sort.order === 'asc') {\n sortOrder = 'desc';\n }\n\n const requestEvent = new YatlColumnSortRequest(\n column.field,\n sortOrder,\n multiSort,\n );\n if (!this.dispatchEvent(requestEvent)) {\n return;\n }\n\n this.sort(column.field, sortOrder, !multiSort);\n };\n\n private handleCellClick = (\n event: MouseEvent,\n row: T,\n field: NestedKeyOf<T>,\n ) => {\n // Ignore events if the user is highlighting text\n if (window.getSelection()?.toString()) return;\n\n const rowId = this.controller.getRowId(row);\n const rowIndex = this.controller.getRowIndex(row);\n this.dispatchEvent(\n new YatlRowClickEvent(row, rowId, rowIndex, field, event),\n );\n };\n\n private handleResizeMouseDown(event: MouseEvent, field: NestedKeyOf<T>) {\n event.preventDefault();\n event.stopPropagation();\n\n const target = event.target as HTMLElement;\n const header = target.closest('.cell');\n if (!header) {\n return;\n }\n\n const columnIndex = this.displayColumns.findIndex(\n column => column.field === field,\n );\n if (columnIndex < 0) {\n return;\n }\n\n this.tableElement.classList.add('resizing');\n\n // Freeze the current widths as soon as the users starts resizing\n this.tableElement\n .querySelectorAll<HTMLElement>('.header .cell')\n .forEach(element => {\n const field = element.dataset.field as NestedKeyOf<T> | undefined;\n if (field) {\n const state = this.getColumnState(field);\n state.width = element.getBoundingClientRect().width;\n this.updateColumnState(field, state);\n }\n });\n\n const gridWidths = this.getGridWidths();\n this.resizeState = {\n active: true,\n startX: event.pageX,\n startWidth: header.getBoundingClientRect().width,\n columnIndex: columnIndex + 2, // row number column + selector column\n columnField: field,\n currentWidths: gridWidths,\n };\n\n this.tableElement.style.setProperty(\n '--grid-template',\n gridWidths.join(' '),\n );\n\n window.addEventListener('mousemove', this.handleResizeMouseMove);\n window.addEventListener('mouseup', this.handleResizeMouseUp);\n }\n\n private handleResizeMouseMove = (event: MouseEvent) => {\n if (!this.resizeState?.active) return;\n\n requestAnimationFrame(() => {\n if (!this.resizeState?.active) return;\n\n const deltaX = event.pageX - this.resizeState.startX;\n const newWidth = Math.max(50, this.resizeState.startWidth + deltaX);\n this.resizeState.currentWidths[\n this.resizeState.columnIndex\n ] = `${newWidth}px`;\n this.tableElement.style.setProperty(\n '--grid-template',\n this.resizeState.currentWidths.join(' '),\n );\n });\n };\n\n private handleResizeMouseUp = (event: MouseEvent) => {\n window.removeEventListener('mousemove', this.handleResizeMouseMove);\n window.removeEventListener('mouseup', this.handleResizeMouseUp);\n\n this.tableElement.classList.remove('resizing');\n\n if (this.resizeState?.active) {\n event.preventDefault();\n event.stopPropagation();\n\n // Calculate the final width based on the DOM's current style\n const finalWidth = parseFloat(\n this.resizeState.currentWidths[this.resizeState.columnIndex],\n );\n\n this.resizeColumn(this.resizeState.columnField, finalWidth);\n }\n\n // This is a hacky workaround to prevent the header click event from firing\n // if the user releases their mouse click outside of the resizer handle.\n setTimeout(() => {\n this.resizeState = null;\n });\n };\n\n private handleDragColumnStart = (event: DragEvent, field: NestedKeyOf<T>) => {\n const target = event.target as HTMLElement;\n\n if (target?.classList.contains('resizer')) {\n event.preventDefault();\n return;\n }\n\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', field);\n this.dragColumn = field;\n }\n };\n\n private handleDragColumnEnter = (event: DragEvent) => {\n const cell = event.currentTarget as HTMLElement;\n cell.querySelector('.drop-indicator')?.classList.add('active');\n };\n\n private handleDragColumnLeave = (event: DragEvent) => {\n const cell = event.currentTarget as HTMLElement;\n const enteringElement = event.relatedTarget as Node;\n\n if (cell.contains(enteringElement)) {\n return;\n }\n\n cell.querySelector('.drop-indicator')?.classList.remove('active');\n };\n\n private handleDragColumnOver = (event: DragEvent) => {\n event.preventDefault();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'move';\n }\n };\n\n private handleDragColumnDrop = (event: DragEvent, field: NestedKeyOf<T>) => {\n if (!this.dragColumn || this.dragColumn === field) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n const newColumns = this.displayColumns;\n const originalIndex = newColumns.findIndex(\n col => col.field === this.dragColumn,\n );\n const newIndex = newColumns.findIndex(col => col.field === field);\n\n const requestEvent = new YatlColumnReorderRequest(\n this.dragColumn,\n originalIndex,\n newIndex,\n );\n if (!this.dispatchEvent(requestEvent)) {\n return;\n }\n\n this.moveColumn(this.dragColumn, field);\n };\n\n private handleDragColumnEnd = () => {\n this.dragColumn = null;\n // Clean up just in case\n this.tableElement\n .querySelectorAll('.drop-indicator.active')\n .forEach(element => element.classList.remove('active'));\n };\n\n private handleRowSelectionClicked = (event: Event, row: T) => {\n event.stopPropagation();\n const inputElement = event.currentTarget as HTMLInputElement;\n const selected = inputElement.checked;\n\n const rowId = this.controller.getRowId(row);\n const selectedRows = this.selectedRowIds;\n const requestEvent = new YatlRowSelectRequest(\n rowId,\n selected,\n selectedRows,\n );\n if (!this.dispatchEvent(requestEvent)) {\n inputElement.checked = !selected;\n return;\n }\n\n this.toggleRowSelection(row, selected);\n };\n\n // #endregion\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'yatl-table': YatlTable;\n }\n}\n","export function getCompareableValue(value: unknown) {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'bigint'\n ) {\n return value;\n } else if (typeof value === 'boolean') {\n return Number(value);\n } else if (value instanceof Date) {\n return value.getTime();\n } else {\n return String(value);\n }\n}\n\n/**\n * Creates a mapping of values to their sorted rank (0-based index).\n * Handles locale comparison correctly during the setup phase.\n */\nexport function createRankMap(\n values: [unknown, unknown][],\n locale?: string,\n): Map<unknown, number> {\n const unique = Array.from(new Set(values));\n // Use Intl.Collator for high-performance, correct locale sorting\n const collator = new Intl.Collator(locale, {\n numeric: true,\n sensitivity: 'base',\n });\n\n unique.sort(([_aOrig, aMod], [_bOrig, bMod]) => {\n if (aMod == null && bMod == null) return 0;\n if (aMod == null) return -1;\n if (aMod == null) return 1;\n const aValue = getCompareableValue(aMod);\n const bValue = getCompareableValue(bMod);\n if (typeof aValue === 'string' && typeof bValue === 'string') {\n return collator.compare(String(aValue), String(bValue));\n }\n\n if (aValue < bValue) return -1;\n if (bValue < aValue) return 1;\n return 0;\n });\n\n const rankMap = new Map<unknown, number>();\n unique.forEach(([orig, _mod], index) => rankMap.set(orig, index));\n return rankMap;\n}\n","import type {\n ColumnFilterCallback,\n ColumnOptions,\n ColumnState,\n ExportOptions,\n FilterCallback,\n Filters,\n NestedKeyOf,\n QueryToken,\n RestorableColumnState,\n RestorableTableState,\n RowId,\n RowIdCallback,\n RowSelectionMethod,\n SortOrder,\n StorageOptions,\n TableControllerOptions,\n TableState,\n TokenizerCallback,\n UnspecifiedRecord,\n} from '../types';\n\nimport {\n createState,\n getNestedValue,\n isDisplayColumn,\n isRowIdType,\n isRowSelectionMethod,\n whitespaceTokenizer,\n getColumnStateChanges,\n} from '../utils';\n\nimport { createRankMap } from './utils';\n\nimport { ReactiveController, ReactiveControllerHost } from 'lit';\n\nimport {\n YatlColumnReorderEvent,\n YatlColumnResizeEvent,\n YatlColumnSortEvent,\n YatlColumnToggleEvent,\n YatlRowSelectEvent,\n YatlTableSearchEvent,\n YatlTableStateChangeEvent,\n YatlTableViewChangeEvent,\n} from '../events';\nimport { TypedEventTarget } from '../utils/typed-event-target';\n\n// #region Constants\n\n// Debounce between state saves\nconst STATE_SAVE_DEBOUNCE = 1000;\n\nconst DEFAULT_STORAGE_OPTIONS: Partial<StorageOptions> = {\n storage: 'local',\n saveColumnSortOrders: true,\n saveColumnVisibility: true,\n saveColumnWidths: true,\n saveColumnOrder: true,\n saveSelectedRows: true,\n};\n\nconst MATCH_WEIGHTS = {\n EXACT: 100,\n PREFIX: 50,\n SUBSTRING: 10,\n};\n\n// #endregion\n\nexport class YatlTableController<T extends object = UnspecifiedRecord>\n extends TypedEventTarget<ControllerEventMap>\n implements ReactiveController\n{\n // #region State Data\n\n // Property data\n private hosts = new Set<ReactiveControllerHost>();\n private _enableSearchTokenization = false;\n private _enableSearchScoring = false;\n // Original options passed by the user\n private _columns: ColumnOptions<T>[] = [];\n // Options mapped by field for faster lookup\n private _columnDefinitionMap = new Map<NestedKeyOf<T>, ColumnOptions<T>>();\n private _columnStateMap = new Map<NestedKeyOf<T>, Readonly<ColumnState<T>>>();\n private _rowSelectionMethod: RowSelectionMethod | null = null;\n private _selectedRowIds = new Set<RowId>();\n private _storageOptions: StorageOptions | null = null;\n private _rowIdCallback: RowIdCallback<T> = (row, index) => {\n if ('id' in row && isRowIdType(row.id)) return row.id;\n if ('key' in row && isRowIdType(row.key)) return row.key;\n if ('_id' in row && isRowIdType(row._id)) return row._id;\n warnMissingId();\n return index;\n };\n private _data: T[] = [];\n private _filteredData: T[] = [];\n // The last time the data was updated.\n // This is just provided as a convience so the\n // table element can display it in the footer.\n // The controller needs to own it so it is always accurate.\n private _dataUpdateTimestamp: Date | null = null;\n\n private _searchQuery = '';\n private _searchTokenizer: TokenizerCallback = whitespaceTokenizer;\n private _filters: Filters<T> | FilterCallback<T> | null = null;\n\n // Flag if we have already restored the state or not.\n private hasRestoredState = false;\n\n // save state debounce timer\n private saveTimer = 0;\n\n // Flags set when something changes that\n // requires the filter or sort logic to re-run.\n private filterDirty = false;\n private sortDirty = false;\n\n // Maps rows to their metadata\n private rowMetadata = new WeakMap<T, RowMetadata>();\n // Map row ids to their rows for faster lookup\n private idToRowMap = new Map<RowId, T>();\n // List of tokens created from the current query\n private queryTokens: QueryToken[] | null = null;\n\n // #endregion\n\n // #region Properties\n\n /**\n * Enables tokenized search behavior.\n * When enabled, the search query is split into individual tokens using the\n * `searchTokenizer` function (defaults to splitting on whitespace).\n * A row is considered a match if **ANY** of the tokens appear in the searchable fields.\n * @default false\n */\n public get enableSearchTokenization() {\n return this._enableSearchTokenization;\n }\n\n public set enableSearchTokenization(enable) {\n if (this._enableSearchTokenization === enable) {\n return;\n }\n\n this._enableSearchTokenization = enable;\n this.updateInternalQuery();\n this.filterDirty = true;\n this.requestUpdate('enableSearchTokenization');\n }\n\n /**\n * Enables weighted relevance scoring for search results.\n * When enabled, exact matches and prefix matches are ranked higher than substring matches.\n * Rows are sorted by their relevance score descending.\n * @default false\n */\n public get enableSearchScoring() {\n return this._enableSearchScoring;\n }\n\n public set enableSearchScoring(enable) {\n if (this._enableSearchScoring === enable) {\n return;\n }\n\n this._enableSearchScoring = enable;\n this.filterDirty = true;\n this.requestUpdate('enableSearchScoring');\n }\n\n /**\n * The definitions for the columns to be rendered.\n * This defines the field mapping, titles, sortability, and other static options.\n */\n public get columns() {\n return [...this._columns];\n }\n\n public set columns(columns) {\n this._columns = [...columns];\n this.filterDirty = true;\n // Cache these in a map for faster lookups\n this._columnDefinitionMap = new Map();\n for (const column of columns) {\n this._columnDefinitionMap.set(column.field, column);\n }\n this.requestUpdate('columns');\n }\n\n public get displayColumns() {\n return this.columns.filter(isDisplayColumn);\n }\n\n public get columnStates() {\n return this.columns.map(column => {\n const state = this.getColumnState(column.field);\n // Always return a copy so the user can't modify it.\n return createState(column.field, state);\n });\n }\n\n public set columnStates(states) {\n let changed = false;\n for (const state of states) {\n const oldState = this.getColumnState(state.field);\n const stateChanges = getColumnStateChanges(oldState, state);\n if (stateChanges.length) {\n changed = true;\n if (stateChanges.includes('sort')) {\n this.sortDirty = true;\n }\n\n const newState = createState(state.field, state);\n this._columnStateMap.set(state.field, newState);\n }\n }\n\n if (!changed) {\n return;\n }\n\n this.requestUpdate('columnStates');\n }\n\n /**\n * The current text string used to filter the table data.\n * Setting this property triggers a new search and render cycle.\n */\n public get searchQuery() {\n return this._searchQuery;\n }\n\n public set searchQuery(query) {\n if (this._searchQuery === query) {\n return;\n }\n\n this._searchQuery = query;\n this.updateInternalQuery();\n this.filterDirty = true;\n this.requestUpdate('searchQuery');\n }\n\n /**\n * A function that splits the search query into tokens.\n * Only used if `enableSearchTokenization` is true.\n * @default whitespaceTokenizer\n */\n public get searchTokenizer() {\n return this._searchTokenizer;\n }\n\n public set searchTokenizer(tokenizer) {\n if (this._searchTokenizer === tokenizer) {\n return;\n }\n\n this._searchTokenizer = tokenizer;\n this.filterDirty = true;\n this.requestUpdate('searchTokenizer');\n }\n\n /**\n * An optional set of criteria to filter the visible rows.\n * This runs **before** the global search query is applied.\n * * You can provide:\n * 1. A **Partial Object**: matches rows where specific keys equal specific values (AND logic).\n * 2. A **Callback Function**: returns `true` to keep the row, `false` to hide it.\n * * @example\n * // 1. Object Syntax (Simple Exact Match)\n * // Shows rows where status is 'active' AND role is 'admin'\n * table.filters = { status: 'active', role: 'admin' };\n * * @example\n * // 2. Callback Syntax (Complex Logic)\n * // Shows rows where age is over 21 OR they are a VIP\n * table.filters = (row) => row.age > 21 || row.isVip;\n */\n public get filters() {\n return this._filters;\n }\n\n public set filters(filters) {\n if (this._filters === filters) {\n return;\n }\n\n this._filters = filters;\n this.filterDirty = true;\n this.requestUpdate('filters');\n }\n\n /**\n * The row selection method to use.\n * * single - Only a single row can be selected at a time\n * * multi - Multiple rows can be selected at a time\n * * null - Disable row selection\n */\n public get rowSelectionMethod() {\n return this._rowSelectionMethod;\n }\n\n public set rowSelectionMethod(selection) {\n if (\n this._rowSelectionMethod === selection ||\n !isRowSelectionMethod(selection)\n ) {\n return;\n }\n\n this._rowSelectionMethod = selection;\n this.requestUpdate('rowSelectionMethod');\n }\n\n /**\n * List of currently selected row indexes.\n * * **NOTE**: These indexes are based off the of\n * the original data array index, *not* the filtered data.\n */\n public get selectedRowIds() {\n let selectedRows = [...this._selectedRowIds];\n\n if (this.rowSelectionMethod === 'single') {\n selectedRows = selectedRows.slice(0, 1);\n } else if (!this.rowSelectionMethod) {\n selectedRows = [];\n }\n return selectedRows;\n }\n\n public set selectedRowIds(rows) {\n if (\n rows.length === this._selectedRowIds.size &&\n rows.every(a => this._selectedRowIds.has(a))\n ) {\n return;\n }\n\n this._selectedRowIds = new Set(rows);\n this.requestUpdate('selectedRowIds');\n }\n\n /**\n * Configuration options for automatically saving and restoring table state\n * (column width, order, visibility, etc.) to browser storage.\n */\n public get storageOptions() {\n return this._storageOptions ? { ...this._storageOptions } : null;\n }\n\n public set storageOptions(options) {\n if (this._storageOptions === options) {\n return;\n }\n\n this._storageOptions = options ? { ...options } : null;\n if (!this.hasRestoredState) {\n this.loadStateFromStorage();\n this.requestUpdate('storageOptions');\n }\n }\n\n public get rowIdCallback() {\n return this._rowIdCallback;\n }\n\n public set rowIdCallback(callback) {\n if (this._rowIdCallback === callback) {\n return;\n }\n\n this._rowIdCallback = callback;\n // Update IDs in metadata for existing data.\n for (let i = 0; i < this.data.length; ++i) {\n const row = this.data[i];\n this.rowMetadata.get(row)!.id = this._rowIdCallback(row, i);\n }\n this.requestUpdate('rowIdCallback');\n }\n\n /**\n * The array of data objects to be displayed.\n * Objects must satisfy the `WeakKey` constraint (objects only, no primitives).\n */\n public get data() {\n return [...this._data];\n }\n\n public set data(data: T[]) {\n this._data = [...data];\n this.createMetadata();\n this._dataUpdateTimestamp = new Date();\n this.filterDirty = true;\n this.requestUpdate('data');\n }\n\n public get filteredData() {\n if (this.filterDirty) {\n this.filterRows();\n } else if (this.sortDirty) {\n this.sortRows();\n }\n\n this.filterDirty = false;\n this.sortDirty = false;\n\n return [...this._filteredData];\n }\n\n public get dataUpdateTimestamp() {\n return this._dataUpdateTimestamp;\n }\n\n // #endregion\n\n // #region Public Methods\n\n constructor(\n host?: ReactiveControllerHost,\n options?: TableControllerOptions<T>,\n ) {\n super();\n\n if (host) {\n this.attach(host);\n }\n\n if (options) {\n if (options.enableSearchScoring !== undefined)\n this.enableSearchScoring = options.enableSearchScoring;\n if (options.enableSearchTokenization !== undefined)\n this.enableSearchTokenization = options.enableSearchTokenization;\n if (options.searchTokenizer !== undefined)\n this.searchTokenizer = options.searchTokenizer;\n if (options.rowIdCallback !== undefined)\n this.rowIdCallback = options.rowIdCallback;\n if (options.rowSelectionMethod !== undefined)\n this.rowSelectionMethod = options.rowSelectionMethod;\n if (options.storageOptions !== undefined)\n this.storageOptions = options.storageOptions;\n if (options.columns !== undefined) this.columns = options.columns;\n if (options.data !== undefined) this.data = options.data;\n }\n }\n\n public attach(host: ReactiveControllerHost) {\n this.hosts.add(host);\n host.addController(this);\n host.requestUpdate();\n }\n\n public detach(host: ReactiveControllerHost) {\n host.removeController(this);\n this.hosts.delete(host);\n }\n\n public getColumn(field: NestedKeyOf<T>) {\n return this._columnDefinitionMap.get(field);\n }\n\n public getDisplayColumn(field: NestedKeyOf<T>) {\n const column = this._columnDefinitionMap.get(field);\n if (isDisplayColumn(column)) {\n return column;\n }\n }\n\n /**\n * Gets a copy of the current state of the table.\n */\n public getTableState(): TableState<T> {\n return {\n searchQuery: this.searchQuery,\n selectedRows: this.selectedRowIds,\n columns: this.columnStates.map(column => {\n const state = this.getColumnState(column.field);\n // Always return a copy so the user can't modify it\n return createState(column.field, state);\n }),\n };\n }\n\n /**\n * Restores the table to the provided state.\n * @param state - The state to restore the table to.\n */\n public updateTableState(state: RestorableTableState<T>) {\n if ('searchQuery' in state && state.searchQuery !== undefined) {\n this.searchQuery = state.searchQuery;\n }\n\n if ('selectedRows' in state && state.selectedRows) {\n this.selectedRowIds = state.selectedRows;\n }\n\n if ('columns' in state && state.columns !== undefined) {\n for (const newState of state.columns) {\n this.updateColumnState(newState.field, newState);\n }\n }\n\n this.requestUpdate();\n }\n\n public getColumnState(field: NestedKeyOf<T>) {\n const currentState = this._columnStateMap.get(field);\n if (!currentState) {\n const createdState = createState(field);\n this._columnStateMap.set(field, createdState);\n return createdState;\n }\n return createState(field, currentState);\n }\n\n public updateColumnState(\n field: NestedKeyOf<T>,\n state: RestorableColumnState<T>,\n ) {\n const currentState = this._columnStateMap.get(field);\n const newState = createState(field, { ...currentState, ...state });\n this.columnStates = [newState];\n }\n\n public search(query: string) {\n this.searchQuery = query;\n this.dispatchEvent(new YatlTableSearchEvent(query));\n }\n\n public getColumnFilterValues(field: NestedKeyOf<T>, includeNull = false) {\n const column = this.getDisplayColumn(field);\n const values = new Map<unknown, number>();\n for (const row of this.filteredData) {\n let value = getNestedValue(row, field);\n if (column?.valueFormatter) {\n value = column.valueFormatter(value, row);\n }\n if (value != null || includeNull) {\n const valueCount = values.get(value) ?? 0;\n values.set(value, valueCount + 1);\n }\n }\n return values;\n }\n\n /**\n * Sorts the table by a specified column and order.\n * If `order` is `null`, the sort on this column is removed.\n * @param field - The field name of the column to sort by.\n * @param order - The sort order: 'asc', 'desc', or `null` to remove sorting for this column.\n * @param clear - Clear all other sorting\n */\n public sort(\n field: NestedKeyOf<T>,\n order: SortOrder | null,\n clear: boolean = true,\n ) {\n const state = this.getColumnState(field);\n if (state === undefined) {\n throw new Error(`Cannot get options for non-existent column \"${field}\"`);\n }\n\n if (order === state?.sort?.order) {\n return;\n }\n\n // Column was unsorted, give it a new priority\n if (order && !state.sort) {\n // Create a list of current sort priorities\n const priorities = [...this._columnStateMap.values()]\n .map(state => state.sort?.priority)\n .filter(priority => priority !== undefined);\n\n const maxPriority = this.columns.length + 1;\n const priority = Math.min(maxPriority, ...priorities) - 1;\n state.sort = { order, priority };\n } else if (order && state.sort) {\n // Column was sorted, just updated the order\n state.sort.order = order;\n } else {\n state.sort = null;\n }\n\n const newStates = [state];\n // Clear all other sorting\n if (clear) {\n for (const otherColumn of this.columns) {\n if (otherColumn.field !== field) {\n const otherState = this.getColumnState(otherColumn.field);\n otherState.sort = null;\n newStates.push(otherState);\n }\n }\n }\n\n this.columnStates = newStates;\n\n const event = new YatlColumnSortEvent(field, order, !clear);\n this.dispatchEvent(event);\n }\n\n /**\n * Toggles the visibility of hte specified column\n * @param field - The field name of the column to toggle.\n * @param visible - Optionally force the visibility state.\n */\n public toggleColumnVisibility(field: NestedKeyOf<T>, visible?: boolean) {\n const state = this.getColumnState(field);\n const newVisibility = visible !== undefined ? visible : !state.visible;\n\n if (newVisibility === state.visible) {\n return;\n }\n\n state.visible = newVisibility;\n this.columnStates = [state];\n\n const event = new YatlColumnToggleEvent(field, newVisibility);\n this.dispatchEvent(event);\n }\n\n /**\n * Shows the specified column\n * @param field - The field name of the column to show.\n */\n public showColumn(field: NestedKeyOf<T>) {\n this.toggleColumnVisibility(field, true);\n }\n\n /**\n * Hides the specified column\n * @param field - The field name of the column to hide.\n */\n public hideColumn(field: NestedKeyOf<T>) {\n this.toggleColumnVisibility(field, false);\n }\n\n /**\n * Moves a column to a new position\n * @param field - The column to move\n * @param newPosition The index or field of the column to move it to.\n * @returns\n */\n public moveColumn(\n field: NestedKeyOf<T>,\n newPosition: number | NestedKeyOf<T>,\n ) {\n const newColumns = this.displayColumns;\n const originalIndex = newColumns.findIndex(col => col.field === field);\n const newIndex =\n typeof newPosition === 'number'\n ? newPosition\n : newColumns.findIndex(col => col.field === newPosition);\n\n if (originalIndex > -1 && newIndex > -1) {\n const [movedColumn] = newColumns.splice(originalIndex, 1);\n newColumns.splice(newIndex, 0, movedColumn);\n this.columns = newColumns;\n const event = new YatlColumnReorderEvent(newColumns.map(c => c.field));\n this.dispatchEvent(event);\n }\n }\n\n public resizeColumn(field: NestedKeyOf<T>, width: number | null) {\n const state = this.getColumnState(field);\n state.width = width;\n this.updateColumnState(field, state);\n this.dispatchEvent(new YatlColumnResizeEvent(field, width));\n }\n\n public isRowSelected(row: T) {\n const rowId = this.getRowId(row);\n return this.selectedRowIds.includes(rowId);\n }\n\n /**\n * Toggles the selection state of a specific row.\n */\n public toggleRowSelection(row: T, state?: boolean) {\n const rowId = this.getRowId(row);\n\n const isSelected = this.isRowSelected(row);\n const newSelectionState = state !== undefined ? state : isSelected;\n\n if (newSelectionState === isSelected) {\n return;\n }\n\n let newSelection: RowId[];\n if (newSelectionState) {\n newSelection =\n this.rowSelectionMethod === 'single'\n ? [rowId]\n : [...this.selectedRowIds, rowId];\n } else {\n newSelection = this.selectedRowIds.filter(\n existingId => existingId !== rowId,\n );\n }\n\n const previousSelection = this.selectedRowIds;\n this.selectedRowIds = newSelection;\n\n const event = new YatlRowSelectEvent(newSelection, previousSelection);\n this.dispatchEvent(event);\n }\n\n /**\n * Selects a specific row.\n */\n public selectRow(row: T) {\n this.toggleRowSelection(row, true);\n }\n\n /**\n * Deselects a specific row.\n */\n public deselectRow(row: T) {\n this.toggleRowSelection(row, false);\n }\n\n /**\n * Selects all currently visible rows (for \"Select All\" checkbox).\n */\n public selectAll() {\n if (this.rowSelectionMethod === 'single') return;\n\n // Use visible rows (filtered) or all rows depending on your UX preference\n const allIds = this.filteredData.map(row => this.getRowId(row));\n this.selectedRowIds = allIds;\n }\n\n /**\n * Clears all selection.\n */\n public deselectAll() {\n this.selectedRowIds = [];\n }\n\n /**\n * Export the current visible table data to a CSV file.\n * @param options - Options for configuring what should be exported.\n */\n public export(\n options: ExportOptions = {\n includeAllRows: false,\n includeHiddenColumns: false,\n includeInternalColumns: false,\n },\n ) {\n const data = options.includeAllRows ? this.data : this.filteredData;\n\n const columnData = options.includeInternalColumns\n ? this.columns\n : this.displayColumns;\n\n const csvHeaders = columnData\n .filter(column => {\n if (options.includeHiddenColumns) {\n return true;\n }\n return this.getColumnState(column.field).visible;\n })\n .map(column => {\n if (isDisplayColumn(column)) {\n return column.title;\n }\n return column.field;\n })\n .join(',');\n\n const csvRows = data\n .map(row => {\n const list: string[] = [];\n for (const column of columnData) {\n const state = this.getColumnState(column.field);\n let value = getNestedValue(row, column.field);\n if (options.includeHiddenColumns || state.visible) {\n if (\n isDisplayColumn(column) &&\n typeof column.valueFormatter === 'function'\n ) {\n value = column.valueFormatter(value, row);\n }\n value = String(value).replace('\"', '\"\"');\n list.push(`\"${value}\"`);\n }\n }\n return list.join(',');\n })\n .join('\\n');\n\n const csvContent = csvHeaders + '\\n' + csvRows;\n return new Blob([csvContent], { type: 'text/csv;charset=utf-8,' });\n }\n\n /**\n * Gets the row associated with the provided ID.\n * @param id - The ID of the row to get\n * @returns\n */\n public getRow(id: RowId) {\n return this.idToRowMap.get(id);\n }\n\n /**\n * Finds the first row where {@link field} matches {@link value}\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The found row, or undefined if no match is found.\n */\n public findRow(field: NestedKeyOf<T>, value: unknown) {\n return this.data.find(row => {\n const rowValue = getNestedValue(row, field);\n return rowValue === value;\n });\n }\n\n /**\n * Finds the original index of the first row where the specified field matches the given value.\n * This searches through the original, unfiltered dataset.\n * @param field - The field name within the row data to search.\n * @param value - The value to match against the field's content.\n * @returns The original index of the found row, or -1 if no match is found.\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow({description: \"Updated description\"}, index);\n * }\n * ```\n */\n public findRowIndex(field: NestedKeyOf<T>, value: unknown) {\n const row = this.findRow(field, value);\n if (row) {\n return this.rowMetadata.get(row)!.index;\n }\n return -1;\n }\n\n public updateRow(rowId: RowId, data: Partial<T>) {\n const row = this.idToRowMap.get(rowId);\n if (row) {\n Object.assign(row, data);\n this.requestUpdate('data');\n }\n }\n\n /**\n * Updates the data of a row at a specific original index.\n * @param index - The original index of the row to update.\n * @param data - An object containing the new data to assign to the row. Existing fields will be updated, and new fields will be added.\n *\n * @example\n * ```ts\n * const index = dataTable.indexOf('id', 12345);\n * if (index >= 0) {\n * dataTable.updateRow(index, {description: \"Updated description\"});\n * }\n * ```\n */\n public updateRowAtIndex(index: number, data: Partial<T>) {\n const row = this.data[index];\n if (row) {\n Object.assign(row, data);\n this.requestUpdate('data');\n }\n }\n\n /**\n * Deletes the row with the matching ID.\n * @param rowIds - The IDs rows to delete\n */\n public deleteRow(...rowIds: RowId[]) {\n for (const rowId of rowIds) {\n const row = this.idToRowMap.get(rowId);\n if (row) {\n const metadata = this.rowMetadata.get(row)!;\n this.deleteRowAtIndex(metadata.index);\n }\n }\n }\n\n /**\n * Deletes a row at a specific original index from the table.\n * @param indexes - The original indexes of rows to delete.\n */\n public deleteRowAtIndex(...indexes: number[]) {\n const newSelectedRows = new Set(this.selectedRowIds);\n for (const index of indexes) {\n const row = this.data[index];\n if (row) {\n const metadata = this.rowMetadata.get(row)!;\n this.idToRowMap.delete(metadata.id);\n this.rowMetadata.delete(row);\n newSelectedRows.delete(metadata.id);\n this.data = this.data.toSpliced(index, 1);\n }\n }\n this.selectedRowIds = [...newSelectedRows];\n }\n\n public getRowId(row: T) {\n const metadata = this.rowMetadata.get(row);\n if (!metadata) {\n throw new Error('The provided row does not exist in the current dataset');\n }\n return metadata.id;\n }\n\n public getRowIndex(row: T) {\n const metadata = this.rowMetadata.get(row);\n if (!metadata) {\n throw new Error('The provided row does not exist in the current dataset');\n }\n return metadata.index;\n }\n\n public getRowHighlightIndicies(row: T) {\n const metadata = this.rowMetadata.get(row);\n if (!metadata) {\n throw new Error('The provided row does not exist in the current dataset');\n }\n return metadata.highlightIndices;\n }\n\n // #endregion\n\n // #region Lifecycle Methods\n public hostConnected(): void {}\n\n public hostDisconnected(): void {}\n\n public hostUpdate(): void {}\n\n public hostUpdated(): void {}\n\n public requestUpdate(...props: (keyof YatlTableController)[]) {\n const SAVE_TRIGGERS: (keyof YatlTableController)[] = [\n 'columns',\n 'columnStates',\n 'searchQuery',\n 'selectedRowIds',\n ];\n const triggers = props.filter(p => SAVE_TRIGGERS.includes(p));\n if (triggers.length) {\n this.scheduleSave();\n this.dispatchEvent(\n new YatlTableStateChangeEvent(this.getTableState(), triggers),\n );\n }\n\n for (const host of this.hosts) {\n host.requestUpdate();\n }\n }\n\n // #endregion\n\n // #region Filter Methods\n\n /**\n * Calculates a relevance score for a given query against a target string.\n *\n * This function implements a tiered matching strategy:\n * 1. **Exact Match**: The query exactly matches the target. This yields the highest score.\n * 2. **Prefix Match**: The target starts with the query. This is the next most relevant.\n * 3. **Substring Match**: The target contains the query somewhere. This is the least relevant.\n *\n * The final score is weighted and adjusted by the length difference between the query and the target\n * to ensure that more specific matches (e.g., \"apple\" vs \"application\" for the query \"apple\") rank higher.\n *\n * @param query The search term (e.g., \"app\").\n * @param target The string to be searched (e.g., \"Apple\" or \"Application\").\n * @returns A numerical score representing the relevance of the match. Higher is better. Returns 0 if no match is found.\n */\n private calculateSearchScore(query: string, target: string): SearchResult {\n const results: SearchResult = { score: 0, ranges: [] };\n\n if (!query || !target) {\n return results;\n }\n\n let baseScore = 0;\n let matchTypeWeight = 0;\n\n if (target === query) {\n matchTypeWeight = MATCH_WEIGHTS.EXACT;\n baseScore = query.length;\n results.ranges.push([0, target.length]);\n } else if (target.startsWith(query)) {\n matchTypeWeight = MATCH_WEIGHTS.PREFIX;\n baseScore = query.length;\n results.ranges.push([0, query.length]);\n } else {\n const index = target.indexOf(query);\n if (index !== -1) {\n matchTypeWeight = MATCH_WEIGHTS.SUBSTRING;\n baseScore = query.length;\n\n let cursor = index;\n while (cursor !== -1) {\n results.ranges.push([cursor, cursor + query.length]);\n cursor = target.indexOf(query, cursor + 1);\n }\n } else {\n return results;\n }\n }\n\n // Reward matches where the query length is close to the target length.\n const lengthDifference = target.length - query.length;\n const specificityBonus = 1 / (1 + lengthDifference);\n\n // The final score is a combination of the match type's importance,\n // the base score from the query length, and the specificity bonus.\n results.score = baseScore * matchTypeWeight * specificityBonus;\n return results;\n }\n\n private searchField(\n query: QueryToken,\n value: string,\n tokens?: string[],\n ): SearchResult {\n const result: SearchResult = { score: 0, ranges: [] };\n\n const addRangesFromValue = (searchTerm: string) => {\n let idx = value.indexOf(searchTerm);\n while (idx !== -1) {\n result.ranges.push([idx, idx + searchTerm.length]);\n idx = value.indexOf(searchTerm, idx + 1);\n }\n };\n\n // Handle Quoted/Untokenized (Direct Search)\n if (query.quoted || !tokens) {\n if (!this.enableSearchScoring) {\n // Simple boolean match\n if (value.includes(query.value)) {\n result.score = 1;\n addRangesFromValue(query.value);\n }\n } else {\n // Scored match\n const calculation = this.calculateSearchScore(query.value, value);\n result.score = calculation.score;\n result.ranges = calculation.ranges;\n }\n return result;\n }\n\n // Handle Tokenized Search\n // We search the tokens to check for validity/scoring,\n // but we map back to the 'value' for highlighting.\n if (!this.enableSearchScoring) {\n const isMatch = tokens.some(token => token.includes(query.value));\n if (isMatch) {\n result.score = 1;\n addRangesFromValue(query.value);\n }\n return result;\n }\n\n // Complex Scored Token Search\n // We sum the scores of all matching tokens\n for (const token of tokens) {\n const calculation = this.calculateSearchScore(query.value, token);\n if (calculation.score > 0) {\n result.score += calculation.score;\n // If a token matched, find that query in the main string\n addRangesFromValue(query.value);\n }\n }\n\n return result;\n }\n\n private filterField(\n value: unknown,\n filter: unknown,\n filterFunction: ColumnFilterCallback | null = null,\n ): boolean {\n if (Array.isArray(filter)) {\n if (filter.length === 0) {\n return true;\n }\n // If it's an array, we will use an OR filter.\n // If any filters in the array match, keep it.\n return filter.some(element =>\n this.filterField(value, element, filterFunction),\n );\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return false;\n }\n return value.some(element =>\n this.filterField(element, filter, filterFunction),\n );\n }\n\n if (typeof filterFunction === 'function') {\n return filterFunction(value, filter);\n }\n\n if (filter instanceof RegExp) {\n return filter.test(String(value));\n }\n\n return filter === value;\n }\n\n private filterRow(row: T, index: number): boolean {\n if (!this.filters) {\n return true;\n }\n\n if (typeof this.filters === 'function') {\n return this.filters(row, index);\n }\n\n for (const field in this.filters) {\n const filter = getNestedValue(this.filters, field);\n const value = getNestedValue(row, field);\n if (typeof filter === 'function') {\n if (!filter(value)) {\n return false;\n }\n } else if (filter !== undefined) {\n const column = this.getColumn(field as NestedKeyOf<T>);\n const filterCallback = column ? column.filter : undefined;\n if (!this.filterField(value, filter, filterCallback)) {\n return false;\n }\n }\n }\n return true;\n }\n\n private filterRows() {\n const columnData = [...this.columns];\n const fields = columnData\n .filter(column => column.searchable)\n .map(column => column.field);\n\n this._filteredData = this.data.filter((row, index) => {\n const metadata = this.rowMetadata.get(row)!;\n metadata.searchScore = 0;\n metadata.highlightIndices = {};\n // Filter takes precedence over search.\n if (!this.filterRow(row, index)) {\n return false;\n }\n\n if (!this.queryTokens) {\n return true;\n }\n\n for (const field of fields) {\n const originalValue = getNestedValue(row, field);\n const compareValue = metadata.searchValues[field];\n const columnTokens = metadata.searchTokens[field];\n\n if (\n typeof originalValue !== 'string' ||\n typeof compareValue !== 'string'\n ) {\n continue;\n }\n\n const fieldResults: SearchResult = { score: 0, ranges: [] };\n for (const token of this.queryTokens) {\n const results = this.searchField(token, compareValue, columnTokens);\n fieldResults.score += results.score;\n fieldResults.ranges.push(...results.ranges);\n }\n\n if (fieldResults.score > 0) {\n metadata.searchScore += fieldResults.score;\n metadata.highlightIndices[field] = fieldResults.ranges;\n }\n }\n\n return metadata.searchScore > 0;\n });\n\n this.filterDirty = false;\n\n this.sortRows();\n this.dispatchEvent(new YatlTableViewChangeEvent(this.data));\n }\n\n // #endregion\n\n // #region Sort Methods\n\n private compareRows(a: T, b: T, field: NestedKeyOf<T>): number {\n let aValue, bValue;\n\n const state = this.getColumnState(field);\n if (!state.sort) {\n return 0;\n }\n\n const aMetadata = this.rowMetadata.get(a)!;\n const bMetadata = this.rowMetadata.get(b)!;\n\n if (state.sort?.order === 'asc') {\n aValue = aMetadata.sortValues[field];\n bValue = bMetadata.sortValues[field];\n } else {\n aValue = bMetadata.sortValues[field];\n bValue = aMetadata.sortValues[field];\n }\n\n aValue ??= Number.MIN_SAFE_INTEGER;\n bValue ??= Number.MIN_SAFE_INTEGER;\n\n if (aValue < bValue) return -1;\n if (aValue > bValue) return 1;\n return 0;\n }\n\n private sortRows() {\n if (this.filterDirty) {\n this.filterRows();\n return;\n }\n\n const sortedStates = [...this._columnStateMap.values()]\n // Filter to visible columns with active sort states\n .filter(state => state.visible && state.sort)\n // Sort our columns by their sort priority.\n // This is how sorting by multiple columns is handled.\n .sort((a, b) => b.sort!.priority - a.sort!.priority);\n\n this._filteredData = this._filteredData.toSorted((a, b) => {\n const aMetadata = this.rowMetadata.get(a)!;\n const bMetadata = this.rowMetadata.get(b)!;\n\n // Try to sort by search score if we're using scoring and there is a query.\n if (this.enableSearchScoring && this.queryTokens) {\n const aValue = aMetadata.searchScore || 0;\n const bValue = bMetadata.searchScore || 0;\n if (aValue > bValue) return -1;\n if (aValue < bValue) return 1;\n }\n\n for (const state of sortedStates) {\n const comp = this.compareRows(a, b, state.field);\n if (comp !== 0) {\n return comp;\n }\n }\n\n // Always fall back to the index column\n return aMetadata.index - bMetadata.index;\n });\n this.sortDirty = false;\n }\n\n // #endregion\n\n // #region Utilities\n\n private createMetadata() {\n this.idToRowMap = new Map();\n this.rowMetadata = new WeakMap();\n\n const rankMaps = new Map<string, Map<unknown, number>>();\n // TODO: We only need rank maps for sortable columns\n // but the user could enable sorting later. It's easiest\n // to just compute them all know regardless.\n for (const column of this.columns) {\n // Collect all raw values for this column\n const rawValues = this.data.map(row => {\n const originalValue = getNestedValue(row, column.field);\n const modifiedValue = column.sorter?.(originalValue) ?? originalValue;\n return [originalValue, modifiedValue] as [unknown, unknown];\n });\n rankMaps.set(column.field, createRankMap(rawValues));\n }\n\n let index = 0;\n for (const row of this.data) {\n let rowId = this._rowIdCallback(row, index);\n // If the user screws\n if (rowId == null || this.idToRowMap.has(rowId)) {\n warnInvalidIdFunction(index, rowId, row);\n rowId = `__yatl_fallback_id_${index}`;\n }\n\n this.idToRowMap.set(rowId, row);\n // Add the index\n const metadata: RowMetadata = {\n id: rowId,\n index: index++,\n searchTokens: {},\n searchValues: {},\n sortValues: {},\n selected: false,\n };\n this.rowMetadata.set(row, metadata);\n\n for (const column of this.columns) {\n const value = getNestedValue(row, column.field);\n const rankMap = rankMaps.get(column.field)!;\n metadata.sortValues[column.field] = rankMap.get(value) ?? null;\n\n // Cache precomputed lower-case values for search\n if (typeof value === 'string') {\n metadata.searchValues[column.field] = value.toLocaleLowerCase();\n }\n\n // Tokenize any searchable columns\n if (column.searchable && column.tokenize && value) {\n const tokenizer = column.searchTokenizer ?? this.searchTokenizer;\n metadata.searchTokens[column.field] = tokenizer(String(value)).map(\n token => token.value,\n );\n }\n }\n }\n }\n\n private updateInternalQuery() {\n if (this.searchQuery.length === 0) {\n this.queryTokens = null;\n return;\n }\n\n this.queryTokens = [\n { value: this.searchQuery.toLocaleLowerCase(), quoted: true },\n ];\n\n if (this.enableSearchTokenization) {\n this.queryTokens.push(...this.searchTokenizer(this.searchQuery));\n }\n }\n\n private scheduleSave() {\n window.clearTimeout(this.saveTimer);\n\n this.saveTimer = window.setTimeout(() => {\n this.saveStateToStorage();\n }, STATE_SAVE_DEBOUNCE);\n }\n\n // #endregion\n\n // #region Storage Methods\n\n private saveStateToStorage() {\n if (!this.storageOptions) {\n return;\n }\n\n const options = { ...DEFAULT_STORAGE_OPTIONS, ...this.storageOptions };\n const savedTableState: RestorableTableState<T> = {\n columns: [],\n };\n const tableState = this.getTableState();\n\n if (options.saveSearchQuery) {\n savedTableState.searchQuery = tableState.searchQuery;\n }\n\n if (options.saveSelectedRows) {\n savedTableState.selectedRows = tableState.selectedRows;\n }\n\n for (const columnState of tableState.columns) {\n const savedColumnState: RestorableColumnState<T> = {\n field: columnState.field,\n };\n\n if (options.saveColumnSortOrders) {\n savedColumnState.sort = columnState.sort;\n }\n\n if (options.saveColumnVisibility) {\n savedColumnState.visible = columnState.visible;\n }\n\n if (options.saveColumnWidths) {\n savedColumnState.width = columnState.width;\n }\n\n savedTableState.columns?.push(savedColumnState);\n }\n\n const storage =\n options.storage === 'session' ? sessionStorage : localStorage;\n try {\n storage.setItem(options.key, JSON.stringify(savedTableState));\n } catch (error) {\n console.warn('Failed to save table state', error);\n }\n }\n\n private loadStateFromStorage() {\n if (!this.storageOptions) {\n return;\n }\n\n const options = { ...DEFAULT_STORAGE_OPTIONS, ...this.storageOptions };\n const json = localStorage.getItem(options.key);\n if (!json) {\n return;\n }\n\n try {\n const savedTableState = JSON.parse(json) as RestorableTableState<T>;\n const tableStateToRestore: RestorableTableState<T> = {};\n\n if (options.saveSearchQuery) {\n tableStateToRestore.searchQuery = savedTableState.searchQuery;\n }\n\n if (options.saveSelectedRows) {\n tableStateToRestore.selectedRows = savedTableState.selectedRows;\n }\n\n if (savedTableState.columns) {\n tableStateToRestore.columns = [];\n for (const savedColumnState of savedTableState.columns) {\n const columnStateToRestore: RestorableColumnState<T> = {\n field: savedColumnState.field,\n };\n\n if (options.saveColumnVisibility) {\n columnStateToRestore.visible = savedColumnState.visible;\n }\n\n if (options.saveColumnWidths) {\n columnStateToRestore.width = savedColumnState.width;\n }\n\n if (options.saveColumnSortOrders) {\n columnStateToRestore.sort = savedColumnState.sort;\n }\n tableStateToRestore.columns.push(columnStateToRestore);\n }\n }\n\n this.updateTableState(tableStateToRestore);\n this.hasRestoredState = true;\n } catch (error) {\n console.error('Failed to restore DataTable state:', error);\n }\n }\n\n // #endregion\n}\n\nexport type ControllerEventMap = {\n [YatlColumnReorderEvent.EVENT_NAME]: YatlColumnReorderEvent;\n [YatlColumnResizeEvent.EVENT_NAME]: YatlColumnResizeEvent;\n [YatlColumnSortEvent.EVENT_NAME]: YatlColumnSortEvent;\n [YatlColumnToggleEvent.EVENT_NAME]: YatlColumnToggleEvent;\n [YatlRowSelectEvent.EVENT_NAME]: YatlRowSelectEvent;\n [YatlTableSearchEvent.EVENT_NAME]: YatlTableSearchEvent;\n [YatlTableStateChangeEvent.EVENT_NAME]: YatlTableStateChangeEvent;\n [YatlTableViewChangeEvent.EVENT_NAME]: YatlTableViewChangeEvent;\n};\n\ninterface RowMetadata {\n id: RowId;\n index: number;\n searchScore?: number;\n /** Precomputed search tokens */\n searchTokens: Record<string, string[]>;\n /** Precomputed search values */\n searchValues: Record<string, string>;\n /** Precomputed sort values */\n sortValues: Record<string, number | null>;\n highlightIndices?: Record<string, [number, number][]>;\n selected: boolean;\n}\n\ninterface SearchResult {\n score: number;\n ranges: [number, number][]; // Array of [start, end] tuples\n}\n\nlet _hasWarnedMissingId = false;\nfunction warnMissingId() {\n if (_hasWarnedMissingId) return;\n _hasWarnedMissingId = true;\n\n console.warn(\n `[yatl-table] Data rows are missing a unique 'id' or 'key' property.\n Falling back to array index.\n Selection and sorting may behave unexpectedly.\n Please provide a unique ID via the 'rowIdCallback' property.\n `,\n );\n}\n\nlet _hasWarnedInvalidIdFunction = false;\nfunction warnInvalidIdFunction<T>(index: number, rowId: RowId, row: T) {\n if (_hasWarnedInvalidIdFunction) return;\n _hasWarnedInvalidIdFunction = true;\n console.warn(\n `[yatl-table] rowIdCallback returned non-unique id (${rowId}) for data at index ${index}.\n Falling back to array index.\n Selection and sorting may behave unexpectedly.\n `,\n );\n console.debug(row);\n}\n","import { css } from 'lit';\n\n/**\n * we separate the CSS variable names between internal '--yatl' and external '--yatl-table'\n * so that way users can more easily customize the table. Instead of having to apply the\n * overrides to the element itself, they can apply them to the root. So DON'T think this\n * is overly complicated and should be cleaned up by combining the --yatl-* and --yatl-table-* variables.\n */\nexport default css`\n @layer base, striped, hover, selected;\n\n :host {\n --table-cell-padding: var(\n --yatl-table-cell-padding,\n var(--yatl-spacing-m) var(--yatl-spacing-m)\n );\n --table-header-padding: var(\n --yatl-table-header-padding,\n var(--yatl-spacing-m) var(--yatl-spacing-l)\n );\n\n --table-text: var(--yatl-table-text, var(--yatl-text-1));\n --table-bg: var(--yatl-table-bg, var(--yatl-surface-1));\n --table-radius: var(--yatl-table-radius, var(--yatl-radius-m));\n --table-border-width: var(--yatl-table-border-width, 1px);\n --table-border-color: var(\n --yatl-table-border-color,\n var(--yatl-border-color)\n );\n\n --table-header-text: var(--yatl-table-header-text, var(--yatl-text-1));\n --table-header-bg: var(\n --yatl-table-header-bg,\n color-mix(in srgb, var(--yatl-color-mix) 4%, var(--table-bg))\n );\n --table-header-hover-bg: var(\n --yatl-table-header-hover-bg,\n color-mix(in srgb, var(--yatl-color-mix) 4%, var(--table-header-bg))\n );\n --table-header-drop-bg: var(\n --yatl-table-header-drop-bg,\n color-mix(in srgb, var(--yatl-color-mix) 4%, var(--table-header-bg))\n );\n\n --table-row-text: var(--yatl-table-row-text, var(--yatl-text-1));\n --table-row-bg: var(\n --yatl-table-row-bg,\n color-mix(in srgb, var(--yatl-color-mix) 2%, var(--table-bg))\n );\n --table-row-hover-bg: var(\n --yatl-table-row-hover-bg,\n var(--table-header-bg)\n );\n --table-row-stripe-bg: var(\n --yatl-table-row-stripe-bg,\n color-mix(in srbg, var(--yatl-color-mix) 3%, var(--table-bg))\n var(--table-header-bg)\n );\n --table-row-selected-bg: var(\n --yatl-table-row-selected-bg,\n color-mix(in srgb, var(--yatl-color-brand) 20%, transparent)\n );\n --table-footer-text: var(--yatl-table-footer-text, var(--yatl-text-3));\n --table-selector-color: var(\n --yatl-table-selector-color,\n color-mix(in srgb, var(--table-row-bg), var(--yatl-color-brand, black) 5%)\n );\n\n --table-row-number-column-width: var(\n --yatl-table-row-number-column-width,\n 48px\n );\n --table-row-selector-column-width: var(\n --yatl-table-row-selector-column-width,\n 48px\n );\n --table-column-visibility-transition: var(\n --yatl-table-column-visibility-transition,\n 100ms\n );\n\n /* Resize grab handle width */\n --resizer-width: var(--yatl-table-column-resizer-width, 10px);\n\n /* z-index for the header */\n --header-z-index: 2;\n }\n\n @layer base {\n .table {\n border-radius: var(--table-radius);\n background-color: var(--table-bg);\n border: var(--table-border-width) solid var(--table-border-color);\n }\n\n .row {\n position: relative;\n background-color: var(--table-row-bg);\n border-bottom: 1px solid var(--table-border-color);\n transition: background-color 50ms;\n }\n\n .row.header-row {\n background-color: var(--table-header-bg);\n border-bottom: 1px solid var(--table-border-color);\n font-weight: 600;\n color: var(--table-header-text);\n }\n\n .body .row {\n background-color: var(--table-row-bg);\n }\n\n .row:last-child {\n border-bottom: none;\n }\n\n .table:not(.resizing) .row {\n transition: grid-template-columns\n var(--table-column-visibility-transition);\n }\n\n .cell {\n align-items: center;\n padding: var(--table-cell-padding);\n }\n\n .table.resizing * {\n cursor: col-resize !important;\n }\n\n .header .cell {\n padding: var(--table-header-padding);\n }\n\n .footer {\n padding: 8px 12px;\n background-color: var(--table-header-bg);\n border-top: 1px solid var(--table-border-color);\n color: var(--table-footer-text);\n font-size: 0.8em;\n }\n\n .resizer::after {\n height: 60%;\n width: 1px;\n background-color: color-mix(in srgb, currentcolor 30%, transparent);\n transition: background-color 0.2s;\n }\n\n .row-number-cell {\n background-color: var(--table-header-bg);\n }\n\n .message {\n font-size: large;\n }\n }\n\n @layer striped {\n :host([striped]) .body .row:nth-child(even) {\n background-color: var(--table-row-stripe-bg);\n }\n }\n\n @layer hover {\n .table:not(.resizing) .header .cell:hover {\n background-color: var(--table-header-hover-bg);\n }\n\n .body .row:hover {\n background-color: var(--table-row-hover-bg);\n }\n\n .resizer:hover::after {\n background-color: currentcolor;\n width: 2px;\n }\n\n .drop-indicator {\n background: var(--table-header-drop-bg);\n }\n }\n\n @layer selected {\n /* Use after element to blend selection color */\n .body .row.selected::after {\n content: '';\n position: absolute;\n inset: 0;\n pointer-events: none;\n transition: background-color 50ms;\n z-index: 1;\n background-color: var(--table-row-selected-bg);\n }\n }\n\n /* Layout stuff\n * Most of this is functional and needed\n * for the table to work properly. \n * Modify with caution!\n */\n /* stylelint-disable-next-line no-duplicate-selectors */\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n .table {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n position: relative;\n overflow: hidden;\n box-sizing: border-box;\n }\n\n .scroller {\n box-sizing: border-box;\n overflow: auto;\n width: 100%;\n height: 100%;\n }\n\n .body {\n min-width: 100%;\n width: fit-content;\n height: fit-content;\n }\n\n .header {\n z-index: var(--header-z-index);\n flex-shrink: 0;\n position: sticky;\n top: 0;\n }\n\n .header-content {\n position: relative;\n width: 100%;\n display: flex;\n flex-direction: row;\n align-items: baseline;\n gap: 0.5rem;\n }\n\n .sort-icon {\n display: none;\n position: relative;\n width: 1ch;\n align-self: stretch;\n padding: 0;\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .sort-icon.ascending,\n .sort-icon.descending {\n display: block;\n }\n\n .sort-icon::after {\n content: '';\n position: absolute;\n }\n\n .sort-icon.ascending::after {\n content: '\\\\2191';\n }\n\n .sort-icon.descending::after {\n content: '\\\\2193';\n }\n\n .resizer {\n position: absolute;\n top: 0;\n bottom: 0;\n right: 0;\n width: var(--resizer-width);\n cursor: col-resize;\n display: flex;\n justify-content: center;\n align-items: center;\n }\n\n .resizer::after {\n content: '';\n display: block;\n }\n\n .drop-indicator {\n display: none;\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: calc(var(--header-z-index) + 1);\n }\n\n .drop-indicator.active {\n display: block;\n }\n\n .sortable {\n cursor: pointer;\n }\n\n /* Footer */\n .footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n position: sticky;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: var(--header-z-index);\n }\n\n /* Generic table parts */\n .row {\n display: grid;\n grid-template-columns: var(--grid-template);\n\n /* This is required! Don't remove it. */\n min-width: 100%;\n width: fit-content;\n }\n\n .cell-wrapper {\n padding: 0;\n overflow: hidden;\n min-width: 0;\n }\n\n .cell {\n white-space: nowrap;\n overflow: hidden;\n position: relative;\n display: flex;\n align-items: center;\n height: 100%;\n box-sizing: border-box;\n min-width: 0;\n }\n\n /* Add the padding to the child */\n .cell:has(.row-number-cell),\n .cell:has(.row-selector-cell),\n .row-selector-cell {\n padding: 0;\n }\n\n .row-number-cell,\n .row-selector-cell > label {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n padding: var(--table-cell-padding);\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n }\n\n .message {\n position: absolute;\n inset: 0;\n text-align: center;\n pointer-events: none;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .truncate {\n display: block;\n white-space: nowrap;\n overflow: hidden;\n }\n`;\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["query","state","import_lit","state","query","priority","import_lit","state","query","field"]}
|