@timlassiter11/yatl 0.3.12 → 0.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/data-table/utils.ts","../src/virtual-scroll/virtual-scroll.ts","../src/data-table/data-table.ts","../src/plugins/local-storage-adapter/local-storage-adapter.ts"],"sourcesContent":["import { TableClasses } from './types';\n\nexport type NestedKeyOf<ObjectType> = ObjectType extends object\n ? {\n [Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends any[]\n ? // If it's an array, STOP and only return the key itself.\n `${Key}`\n : ObjectType[Key] extends object\n ? // If it's a non-array object, recurse as before.\n `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`\n : // Otherwise, it's a primitive, so just output the key.\n `${Key}`;\n }[keyof ObjectType & (string | number)]\n : never;\n\nexport type WithRequiredProp<Type, Key extends keyof Type> = Type &\n Required<Pick<Type, Key>>;\n\nexport const classesToArray = (classes: string[] | string | undefined) => {\n if (typeof classes === 'string' && classes !== '') {\n return classes.split(' ');\n } else if (Array.isArray(classes)) {\n return classes;\n } else if (!classes) {\n return [];\n }\n throw new TypeError('classes must be string or array of strings');\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\nexport 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 function virtualScrollToNumber(virtualScroll: boolean | number) {\n if (typeof virtualScroll === 'boolean') {\n return virtualScroll ? 1 : Number.MAX_SAFE_INTEGER;\n }\n return virtualScroll;\n}\n\nexport function convertClasses(\n defaultClasses: TableClasses,\n userClasses: TableClasses = {},\n) {\n return {\n scroller: [\n ...classesToArray(userClasses.scroller),\n ...classesToArray(defaultClasses.scroller),\n ],\n thead: [\n ...classesToArray(userClasses.thead),\n ...classesToArray(defaultClasses.thead),\n ],\n tbody: [\n ...classesToArray(userClasses.tbody),\n ...classesToArray(defaultClasses.tbody),\n ],\n tr: [\n ...classesToArray(userClasses.tr),\n ...classesToArray(defaultClasses.tr),\n ],\n th: [\n ...classesToArray(userClasses.th),\n ...classesToArray(defaultClasses.th),\n ],\n td: [\n ...classesToArray(userClasses.td),\n ...classesToArray(defaultClasses.td),\n ],\n mark: [\n ...classesToArray(userClasses.mark),\n ...classesToArray(defaultClasses.mark),\n ],\n };\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: any, path: string): any {\n const keys = path.split('.');\n let current = obj;\n\n for (const key of keys) {\n if (current && typeof current === 'object') {\n current = current[key];\n } else {\n return undefined; // Or handle the error as needed\n }\n }\n\n return current;\n}\n","import type {\n VirtualScrollOptions,\n IVirtualScroll,\n IVirtualScrollConstructor,\n} from './types';\n\nconst MAX_ELEMENT_HEIGHT = 33554400;\n\nexport class VirtualScroll implements IVirtualScroll {\n static #warned = false;\n static AVERAGE_RENDER_COUNT = 1000;\n\n #container;\n #element;\n #generator;\n #rowCount = 0;\n #rowHeight = 0;\n #padding = 2;\n #animationFrame = 0;\n #started = false;\n #scrollTop = 0;\n #topPaddingElement: HTMLElement;\n #bottomPaddingElement: HTMLElement;\n #resizeObserver: ResizeObserver;\n\n constructor({\n generator,\n container,\n element = container,\n nodePadding = 10,\n }: VirtualScrollOptions) {\n this.#container = container;\n this.#element = element;\n this.#generator = generator;\n this.#padding = nodePadding;\n this.#topPaddingElement = document.createElement('div');\n this.#topPaddingElement.style.visibility = 'hidden';\n this.#bottomPaddingElement = document.createElement('div');\n this.#bottomPaddingElement.style.visibility = 'hidden';\n this.#resizeObserver = new ResizeObserver(() => this.#scheduleRender());\n }\n\n private get rowHeight() {\n if (!this.#rowHeight) {\n this.#updateRowHeight();\n }\n return this.#rowHeight;\n }\n\n get started() {\n return this.#started;\n }\n\n /*\n * Scroll to a specific index in the virtual scroll.\n * @param index The index to scroll to.\n * @throws RangeError if the index is out of bounds.\n */\n scrollToIndex(index: number) {\n if (index < 0 || index >= this.#rowCount) {\n throw new RangeError('Index out of bounds.');\n }\n this.scrollToPx(this.rowHeight * index);\n }\n\n /**\n * @param px\n */\n scrollToPx(px: number) {\n this.#container.scrollTop = px;\n this.#renderChunk();\n }\n\n #scrollCallback = () => {\n // Only update if we are vertically scrolling.\n // Fixes horizontal scroll bug.\n if (this.#container.scrollTop !== this.#scrollTop) {\n this.#scrollTop = this.#container.scrollTop;\n this.#scheduleRender();\n }\n };\n\n start(rowCount: number) {\n if (!this.#started) {\n this.#container.addEventListener('scroll', this.#scrollCallback);\n this.#resizeObserver.observe(this.#container);\n this.#started = true;\n }\n this.#container.classList.add('dt-virtual-scroll');\n this.#rowCount = rowCount;\n this.#renderChunk();\n }\n\n stop() {\n if (this.#animationFrame) {\n cancelAnimationFrame(this.#animationFrame);\n }\n\n this.#container.classList.remove('dt-virtual-scroll');\n this.#container.removeEventListener('scroll', this.#scrollCallback);\n this.#resizeObserver.disconnect();\n this.#started = false;\n }\n\n #scheduleRender() {\n if (this.#animationFrame) {\n cancelAnimationFrame(this.#animationFrame);\n }\n this.#animationFrame = requestAnimationFrame(() => this.#renderChunk());\n }\n\n #renderChunk() {\n const scrollTop = this.#container.scrollTop;\n const rowCount = this.#rowCount;\n const rowHeight = this.rowHeight;\n const padding = this.#padding;\n\n if (!this.started || !rowCount || !rowHeight) {\n return;\n }\n\n const totalContentHeight = rowHeight * rowCount;\n // Max out the element height so we can get a real height of the container.\n // This fixes an issue when the parent isn't set to grow causing only a\n // small number of rows to render until you scroll.\n const originalHeight = this.#container.style.height;\n this.#container.style.height = '100%';\n const viewHeight = this.#container.offsetHeight;\n this.#container.style.height = originalHeight;\n\n let totalPadding = padding * 2;\n let startNode = Math.floor(scrollTop / rowHeight) - padding;\n\n if (startNode < 0) {\n totalPadding += startNode;\n }\n\n startNode = Math.max(0, startNode);\n\n let visibleNodesCount = Math.ceil(viewHeight / rowHeight) + totalPadding;\n visibleNodesCount = Math.min(rowCount - startNode, visibleNodesCount);\n\n // Always start with an even row.\n // This helps striped tables.\n if (startNode % 2 === 1) {\n startNode--;\n // If we don't add this we might not render the last row\n visibleNodesCount++;\n }\n\n const offsetY = startNode * rowHeight;\n let remainingHeight = totalContentHeight - (offsetY + visibleNodesCount * rowHeight);\n if (remainingHeight < 0) {\n remainingHeight = 0;\n }\n\n // Remove the old visible nodes (all nodes between the padding elements)\n while (this.#topPaddingElement.nextSibling && this.#topPaddingElement.nextSibling !== this.#bottomPaddingElement) {\n this.#element.removeChild(this.#topPaddingElement.nextSibling);\n }\n\n // Generate the new visible nodes\n const visibleChildren = new Array(visibleNodesCount)\n .fill(null)\n .map((_, index) => this.#generator(index + startNode));\n\n // Update padding heights and insert new nodes\n this.#topPaddingElement.style.height = offsetY + 'px';\n this.#bottomPaddingElement.style.height = remainingHeight + 'px';\n\n // If the top element isn't in the DOM, we need to add the initial structure\n if (!this.#topPaddingElement.parentElement) {\n this.#element.append(this.#topPaddingElement, ...visibleChildren, this.#bottomPaddingElement);\n } else {\n // Otherwise, just insert the new children after the top padding element\n this.#topPaddingElement.after(...visibleChildren);\n }\n\n const actualHeight = this.#element.offsetHeight;\n if (\n !VirtualScroll.#warned &&\n actualHeight < Math.round(totalContentHeight - 1)\n ) {\n VirtualScroll.#warned = true;\n console.error(\n 'Max element height exceeded. Virtual scroll may not work.',\n );\n }\n }\n\n #updateRowHeight() {\n if (this.#rowCount === 0) {\n this.#rowHeight = 0;\n return;\n }\n\n const renderSize = Math.min(\n VirtualScroll.AVERAGE_RENDER_COUNT,\n this.#rowCount,\n );\n // Create an average row height by rendering the first N rows.\n const elements = [];\n for (let i = 0; i < renderSize; ++i) {\n elements.push(this.#generator(i));\n }\n\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.visibility = 'hidden';\n container.style.height = 'auto';\n container.style.width = '100%';\n container.style.top = '-9999px';\n container.style.left = '-9999px';\n container.style.maxHeight = 'none';\n container.style.overflow = 'visible';\n container.style.display = 'block';\n\n try {\n container.append(...elements);\n document.body.append(container);\n this.#rowHeight = container.offsetHeight / renderSize;\n } finally {\n container.remove();\n }\n\n if (this.#rowHeight <= 0) {\n throw new VirtualScrollError(\n `First ${renderSize} rows had no rendered height. Virtual scroll can't be used.`,\n );\n } else if (this.#rowHeight * this.#rowCount > MAX_ELEMENT_HEIGHT) {\n // This seems to be Chrome's max height of an element based on some random testing.\n console.warn(\n 'Virtual scroll height exceeded maximum known element height.',\n );\n }\n }\n}\n\nexport class VirtualScrollError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\n// Just to make sure I don't break anything...\nVirtualScroll satisfies IVirtualScrollConstructor;\n","import './data-table.css';\n\nimport type {\n ColumnFilterCallback,\n ColumnInitOptions,\n ColumnOptions,\n ColumnState,\n FilterCallback,\n Filters,\n LoadOptions,\n QueryToken,\n RestorableTableState,\n SortOrder,\n TableClasses,\n TableInitOptions,\n TableOptions,\n TableState,\n} from './types';\n\nimport {\n convertClasses,\n createRegexTokenizer,\n getNestedValue,\n NestedKeyOf,\n toHumanReadable,\n virtualScrollToNumber,\n} from './utils';\nimport {\n VirtualScroll,\n VirtualScrollError,\n} from '../virtual-scroll/virtual-scroll';\nimport type { IVirtualScroll } from '../virtual-scroll/types';\n\n/**\n * Represents a dynamic and interactive table with features like sorting, searching, filtering,\n * column resizing, column rearranging, and virtual scrolling.\n *\n * @example\n * ```ts\n * type DataType = {id: number, name: string, age: number};\n *\n * const dataTable = new DataTable<DataType>('#myTable', [\n * { field: 'id', title: 'ID', sortable: true },\n * { field: 'name', title: 'Name', searchable: true },\n * { field: 'age', title: 'Age', sortable: true, valueFormatter: (value) => `${value} years` }\n * ], {\n * data: [\n * { id: 1, name: 'Alice', age: 30 },\n * { id: 2, name: 'Bob', age: 24 },\n * ],\n * virtualScroll: true,\n * resizable: true,\n * rearrangeable: true,\n * });\n * ```\n */\nexport class DataTable<T> extends EventTarget {\n private static readonly MatchWeights = {\n EXACT: 100,\n PREFIX: 50,\n SUBSTRING: 10,\n };\n\n // Centralized default options for the DataTable.\n // These are the base values used if not overridden by user-provided options.\n private readonly DEFAULT_OPTIONS: ConcreteTableOptions<T> = {\n virtualScroll: 1000,\n highlightSearch: true,\n tokenizeSearch: false,\n enableSearchScoring: false,\n rearrangeable: true,\n extraSearchFields: [],\n emptyValuePlaceholder: '-',\n noDataText: 'No records found',\n noMatchText: 'No matching records found',\n classes: {\n scroller: ['dt-scroller'],\n thead: ['dt-headers'],\n tbody: [],\n tr: [],\n th: [],\n td: [],\n mark: [],\n },\n rowFormatter: null,\n tokenizer: createRegexTokenizer(),\n virtualScrollClass: VirtualScroll,\n };\n\n // Table elements\n #table: HTMLTableElement;\n #thead: HTMLElement;\n #tbody: HTMLElement;\n #scroller: HTMLElement;\n\n // Used to render cells offscreen and calculate their widths\n // for the auto-resize logic used on resize double click.\n #textMeasurementContext: CanvasRenderingContext2D | null = null;\n\n #columnData: Map<NestedKeyOf<T>, ColumnData<T>> = new Map();\n\n // Current data stored by the initial index\n #rows: Map<number, InternalRowData<T>> = new Map();\n #filteredRows: InternalRowData<T>[] = [];\n\n // Search and filter data\n #userQuery: string | RegExp | null = null;\n #query: QueryToken[] | RegExp | null = null;\n #filters: Filters<T> | FilterCallback<T> | null = null;\n\n #virtualScroll: IVirtualScroll | null = null;\n\n #resizingColumn: ColumnData<T> | null = null;\n #tableWidthIsFixed = false;\n\n #options: ConcreteTableOptions<T> = { ...this.DEFAULT_OPTIONS };\n\n #blockUpdates = false;\n #blockedUpdates: Set<TableEffect> = new Set();\n\n /**\n * Initializes a new instance of the DataTable.\n * @param table - The HTMLTableElement or a CSS selector string for the table.\n * @param columns - List of {@link ColumnOptions} for the table.\n * @param options - Optional configuration options for the DataTable.\n * @throws {SyntaxError} If the table selector does not find an element.\n * @throws {TypeError} If the provided table element is not an HTMLTableElement or if columns option is not an array.\n */\n constructor(\n table: string | HTMLTableElement,\n columns: ColumnInitOptions<T>[],\n options: TableInitOptions<T> = {},\n ) {\n super();\n\n const { data, virtualScrollClass, ...restOptions } = options;\n\n if (virtualScrollClass !== undefined) {\n this.#options.virtualScrollClass = virtualScrollClass;\n }\n\n if (typeof table === 'string') {\n const tableElement = document.querySelector(table);\n if (!tableElement)\n throw new SyntaxError(`Failed to find table using selector ${table}`);\n this.#table = tableElement as HTMLTableElement;\n } else {\n this.#table = table;\n }\n\n if (!(this.#table instanceof HTMLTableElement)) {\n throw new TypeError(\n `Invalid table element type. Must be HTMLTableElement`,\n );\n }\n\n const { scroller, thead, headerRow, tbody } = this.#initTableElements();\n\n this.#scroller = scroller;\n this.#thead = thead;\n this.#tbody = tbody;\n\n this.#initColumns(columns, headerRow);\n this.updateTableOptions({ ...this.#options, ...restOptions });\n\n this.loadData(data ?? []);\n }\n\n /**\n * Gets the current options applied to the table.\n */\n get tableOptions() {\n return structuredClone(this.#options);\n }\n\n /**\n * Gets the currently filtered and sorted rows displayed in the table.\n */\n get rows(): T[] {\n return [...this.#filteredRows];\n }\n\n /**\n * Gets the underlying data\n */\n get data(): T[] {\n return [...this.#rows.values()];\n }\n\n /**\n * Gets the underlying HTMLTableElement managed by this DataTable instance.\n */\n get table(): HTMLTableElement {\n return this.#table;\n }\n\n /**\n * Gets the current state of the table.\n */\n getState(): TableState<T> {\n const columns = [...this.#columnData.values()];\n return {\n searchQuery: this.#userQuery,\n filters: this.#filters,\n scrollPosition: {\n top: this.#scroller.scrollTop,\n left: this.#scroller.scrollLeft,\n },\n columnOrder: columns.map(column => column.field),\n columns: columns.map(column => ({\n field: column.field,\n visible: column.state.visible,\n sortState: column.state.sortState,\n width: column.state.width,\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 restoreState(state: RestorableTableState<T>) {\n this.withoutUpdates(() => {\n if ('searchQuery' in state && state.searchQuery !== undefined) {\n this.search(state.searchQuery);\n }\n\n if ('filters' in state && state.filters !== undefined) {\n this.#filters = state.filters;\n this.filter(state.filters);\n }\n\n if ('scrollPosition' in state && state.scrollPosition !== undefined) {\n this.#scroller.scrollTop = state.scrollPosition.top;\n }\n\n if ('columnOrder' in state && state.columnOrder !== undefined) {\n this.setColumnOrder(state.columnOrder);\n }\n\n if ('columns' in state && state.columns !== undefined) {\n for (const columnState of state.columns) {\n const columnData = this.#columnData.get(columnState.field);\n if (!columnData) {\n console.warn(\n `Attempting to restore state for non-existent column ${columnState.field}`,\n );\n continue;\n }\n\n if ('visible' in columnState && columnState.visible !== undefined) {\n columnData.state.visible = columnState.visible;\n }\n\n if (\n 'sortState' in columnState &&\n columnState.sortState !== undefined\n ) {\n columnData.state.sortState = columnState.sortState;\n }\n\n if ('width' in columnState && columnState.width !== undefined) {\n this.#resizeColumn(columnData, columnState.width);\n }\n }\n }\n });\n }\n\n updateTableOptions(options: UpdatableTableOptions<T>) {\n this.withoutUpdates(() => {\n for (const key in options) {\n const optionKey = key as keyof UpdatableTableOptions<T>;\n const value = options[optionKey]!;\n const config = this.TABLE_OPTION_CONFIGS[optionKey];\n\n if (!config) {\n continue;\n }\n\n this.#blockedUpdates.add(config.effect);\n const handler = config.handler as ((v: any) => any) | undefined;\n const finalValue = handler ? handler(value) : value;\n (this.#options as any)[optionKey] = finalValue;\n }\n\n // Search scoring is only useful with tokenization.\n if (this.#options.enableSearchScoring && !this.#options.tokenizeSearch) {\n this.#options.enableSearchScoring = false;\n console.warn(\n 'Search scoring enabled with tokenization disabled... Ignoring',\n );\n }\n });\n }\n\n getColumnOptions(): Required<ColumnOptions<T>>[];\n getColumnOptions(field: NestedKeyOf<T>): Required<ColumnOptions<T>>;\n getColumnOptions(field?: any) {\n if (field) {\n const columnData = this.#columnData.get(field);\n if (!columnData) {\n throw new Error(`Cannot get options for non-existent column \"${field}\"`);\n }\n const options: ColumnOptions<T> = {...columnData.options, field: columnData.field};\n return options;\n }\n\n const options = [...this.#columnData.values()].map((data): ColumnOptions<T> => ({...data.options, field: data.field}));\n return options;\n }\n\n updateColumnOptions(\n column: NestedKeyOf<T>,\n options: ColumnOptionsWithoutField<T>,\n ) {\n const col = this.#columnData.get(column);\n if (!col) {\n throw new Error(\n `Cannot update options for non-existent column \"${column}\"`,\n );\n }\n\n this.withoutUpdates(() => {\n for (const key in options) {\n const optionKey = key as keyof ColumnOptionsWithoutField<T>;\n const value = options[optionKey]!;\n const config = this.COLUMN_OPTION_CONFIGS[optionKey];\n\n if (!config) {\n continue;\n }\n this.#blockedUpdates.add(config.effect);\n const handler = config.handler as ((v: any) => any) | undefined;\n\n const finalValue = handler ? handler(value) : value;\n (col.options as any)[optionKey] = finalValue;\n }\n });\n }\n\n /**\n * Loads data into the table\n * @param rows - An array of data to be loaded\n * @param options - Configuration for the load operation\n */\n loadData(rows: T[], options: LoadOptions = {}) {\n const scrollTop = this.#scroller.scrollTop;\n const scrollLeft = this.#scroller.scrollLeft;\n\n if (!options.append) {\n this.#rows.clear();\n this.#filteredRows = [];\n }\n\n let index = this.#rows.size;\n for (const row of rows as InternalRowData<T>[]) {\n const internal_row = this.#loadRow(row, index);\n this.#rows.set(index, internal_row);\n index++;\n }\n\n this.#updateHeaders();\n this.#filterRows();\n\n if (options.keepScroll) {\n this.#scroller.scrollTop = scrollTop;\n this.#scroller.scrollLeft = scrollLeft;\n }\n }\n\n /**\n * Displays a message in the table body, typically used for \"no data\" or \"no results\" states.\n * The message is shown in a single row spanning all columns.\n * @param text - The text or HTML message to display.\n * @param classes - A string or array of strings for CSS classes to apply to the message row.\n */\n showMessage(text: string, ...classes: string[]) {\n const colSpan = this.#columnData.size;\n this.#tbody.innerHTML = `<tr class=\"${classes.join(' ')}\"><td colSpan=${colSpan}>${text}</td></tr>`;\n }\n\n /**\n * Clears the current message and dispalsy the normal table data.\n */\n clearMessage() {\n this.#renderTable();\n }\n\n /**\n * Filters rows based on a search query.\n * The search is performed on columns marked as `searchable` and `extraSearchFields`.\n * @param query - The search term (string) or a regular expression. An empty string clears the search.\n */\n search(query?: string | RegExp | null) {\n query ??= null;\n\n const searchEvent = new CustomEvent<DataTableEventMap<T>['dt.search']>(\n 'dt.search',\n {\n cancelable: true,\n detail: {\n query: query ?? null,\n },\n },\n );\n\n if (!this.dispatchEvent(searchEvent)) {\n return;\n }\n\n this.#userQuery = query;\n\n // Clear search on empty string\n if (query === '') {\n query = null;\n }\n\n if (typeof query === 'string') {\n if (this.#options.tokenizeSearch) {\n this.#query = this.#options.tokenizer(query);\n } else {\n this.#query = [{ value: query.toLocaleLowerCase(), quoted: true }];\n }\n } else {\n this.#query = query;\n }\n\n this.#filterRows();\n }\n\n /**\n * Applies filters to the table rows.\n * Filters can be an object where keys are field names and values are the criteria to filter by,\n * or a callback function that receives a row and its index and returns `true` if the row should be included.\n * @param filters - An object defining field-based filters or a custom filter callback function.\n * @throws {TypeError} If `filters` is not an object or a function.\n */\n filter(filters?: Filters<T> | FilterCallback<T> | null) {\n this.#filters = filters ?? null;\n this.#filterRows();\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 colName - 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 */\n sort(colName: NestedKeyOf<T>, order: SortOrder | null) {\n const col = this.#columnData.get(colName);\n if (!col) {\n throw new Error(\n `Cannot get options for non-existent column \"${colName}\"`,\n );\n }\n\n if (order === col.state.sortState?.order) {\n return;\n }\n\n const sortEvent = new CustomEvent<DataTableEventMap<T>['dt.col.sort']>(\n 'dt.col.sort',\n {\n cancelable: true,\n detail: {\n column: col.field,\n order: order,\n },\n },\n );\n\n if (!this.dispatchEvent(sortEvent)) {\n return;\n }\n\n // Column was unsorted, give it a new priority\n if (order && !col.state.sortState) {\n // Create a list of current sort priorities\n const priorities = [...this.#columnData.values()]\n .map(col => col.state.sortState?.priority)\n .filter(priority => priority !== undefined);\n\n const maxPriority = this.#columnData.size + 1;\n const priority = Math.min(maxPriority, ...priorities) - 1;\n col.state.sortState = { order, priority };\n } else if (order && col.state.sortState) {\n // Column was sorted, just updated the order\n col.state.sortState.order = order;\n } else {\n col.state.sortState = null;\n }\n\n const scrollTop = this.#scroller.scrollTop;\n const scrollLeft = this.#scroller.scrollLeft;\n\n this.#updateHeaders();\n this.#sortRows();\n\n this.#scroller.scrollTop = scrollTop;\n this.#scroller.scrollLeft = scrollLeft;\n }\n\n /**\n * Sets the visibility of a specified column.\n * @param colName - The field name of the column.\n * @param visisble - `true` to show the column, `false` to hide it.\n */\n setColumnVisibility(colName: NestedKeyOf<T>, visisble: boolean) {\n const col = this.#columnData.get(colName);\n if (!col) {\n throw new Error(\n `Cannot get options for non-existent column \"${colName}\"`,\n );\n }\n\n if (col.state.visible === visisble) {\n return;\n }\n\n const visibilityEvent = new CustomEvent<\n DataTableEventMap<T>['dt.col.visibility']\n >('dt.col.visibility', {\n cancelable: true,\n detail: {\n column: col.field,\n visible: visisble,\n },\n });\n\n if (!this.dispatchEvent(visibilityEvent)) {\n return;\n }\n\n col.state.visible = visisble;\n this.#updateHeaders();\n // If we hide a column that has sorting, we need to resort.\n // This will also handle hiding all of the columns elements.\n this.#sortRows();\n }\n\n /**\n * Shows a previously hidden column.\n * @param field - The field name of the column to show.\n */\n showColumn(field: NestedKeyOf<T>) {\n this.setColumnVisibility(field, true);\n }\n\n /**\n * Hides a visible column.\n * @param field - The field name of the column to hide.\n */\n hideColumn(field: NestedKeyOf<T>) {\n this.setColumnVisibility(field, false);\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 all - If `true`, exports all original data (ignoring filters). If `false` (default), exports only the currently visible (filtered and sorted) rows.\n */\n export(filename: string, all = false) {\n const data = all ? this.#rows : this.#filteredRows;\n const rows = [...data.values()];\n\n const csvHeaders = [...this.#columnData.values()]\n .filter(col => all || col.state.visible)\n .map(col => `\"${col.options.title}\"`)\n .join(',');\n\n const csvRows = rows\n .map(row => {\n const list: string[] = [];\n for (const key of this.#columnData.keys()) {\n const col = this.#columnData.get(key);\n if (!col) {\n continue;\n }\n\n let value = (row as any)[key];\n if (all || !col.headerElement.hidden) {\n if (typeof col.options.valueFormatter === 'function') {\n value = col.options.valueFormatter(value, row);\n }\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 const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8,' });\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 scrollToRow(row: T) {\n const rowData = row as InternalRowData<T>;\n const index = rowData._metadata?.index;\n if (typeof index === 'number') {\n 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 scrollToOriginalIndex(index: number) {\n const rowData = this.#rows.get(index);\n if (rowData) {\n const filteredIndex = this.#filteredRows.indexOf(rowData);\n if (filteredIndex >= 0) {\n this.scrollToFilteredIndex(filteredIndex);\n return;\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 scrollToFilteredIndex(index: number) {\n const rowData = this.#filteredRows[index];\n if (!rowData) {\n throw new RangeError(`Row index ${index} out of range`);\n }\n\n if (this.#virtualScroll) {\n this.#virtualScroll.scrollToIndex(index);\n } else {\n const row = this.#tbody.querySelector(\n `tr[data-dt-index=\"${rowData._metadata.index}\"]`,\n );\n if (row) {\n row.scrollIntoView(true);\n const theadHeight = parseFloat(getComputedStyle(this.#thead).height);\n this.#scroller.scrollTop -= theadHeight;\n }\n }\n }\n\n scrollToPx(px: number) {\n if (this.#virtualScroll) {\n this.#virtualScroll.scrollToPx(px);\n } else {\n const theadHeight = parseFloat(getComputedStyle(this.#thead).height);\n this.#scroller.scrollTop = px - theadHeight;\n }\n }\n\n /**\n * Sets the display order of the columns in the table.\n *\n * @param fields - An array of field names representing the new order of columns. Columns not included in the array will be placed at the end.\n * @throws {TypeError} If `fields` is not an array.\n */\n setColumnOrder(fields: NestedKeyOf<T>[]) {\n if (!Array.isArray(fields)) {\n throw new TypeError('fields must be an array of field names');\n }\n\n const newColumns = new Map<NestedKeyOf<T>, ColumnData<T>>();\n for (const field of fields) {\n const col = this.#columnData.get(field);\n if (col) {\n newColumns.set(field, col);\n }\n }\n\n for (const [field, col] of this.#columnData) {\n if (!newColumns.has(field)) {\n newColumns.set(field, col);\n }\n }\n\n this.#columnData = newColumns;\n this.refresh();\n }\n\n /**\n * Refreshes the table display. This re-applies filters, sorting, and updates headers and rows.\n */\n refresh() {\n this.#updateHeaders();\n this.#filterRows();\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 indexOf(field: string, value: any) {\n const rows = [...this.#rows.values()];\n const found_row = rows.find(row => {\n if (field in row) {\n return (row as any)[field] === value;\n }\n });\n\n if (found_row) {\n return found_row._metadata.index;\n }\n return -1;\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 updateRow(index: number, data: Partial<T>) {\n const current_row = this.#rows.get(index);\n if (current_row) {\n Object.assign(current_row, data);\n this.#loadRow(current_row, index);\n this.#filterRows();\n }\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 deleteRow(index: number) {\n this.#rows.delete(index);\n this.#filterRows();\n }\n\n /**\n * Executes a callback function without triggering table updates (like re-rendering or event dispatches)\n * until the callback has completed. This is useful for batching multiple operations.\n * @param callback - A function to execute. It receives the DataTable instance as its argument.\n * @example dataTable.withoutUpdates(dt => { dt.sort('name', 'asc'); dt.filter({ age: '>30' }); });\n */\n withoutUpdates(callback: (dataTable: DataTable<T>) => void) {\n const prevBlock = this.#blockUpdates;\n this.#blockUpdates = true;\n try {\n callback(this);\n } finally {\n this.#blockUpdates = prevBlock;\n if (!this.#blockUpdates) {\n this.#applyBlockedUpdates();\n }\n }\n }\n\n #initTableElements() {\n this.#table.classList.add('data-table');\n // Inner element that handles the virtual scroll.\n const scroller = document.createElement('div');\n\n // If the user tries to provide a height, we will use that for the scroller.\n if (this.#table.style.height !== '') {\n scroller.style.height = this.#table.style.height;\n this.#table.style.height = '';\n }\n\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n const tbody = document.createElement('tbody');\n\n tbody.addEventListener('click', this.#onTableClicked);\n\n // We currently don't support HTML based columns.\n // Clear the table and start fresh.\n // TODO: Add ability to use HTML headers provided by the user.\n this.#table.innerHTML = '';\n\n thead.append(headerRow);\n this.#table.append(thead);\n this.#table.append(tbody);\n\n // Add the scroller before the table so when we move the\n // table into the scroller it stays in the same place.\n this.#table.parentElement?.insertBefore(scroller, this.#table);\n scroller.append(this.#table);\n\n return {\n scroller,\n thead,\n headerRow,\n tbody,\n };\n }\n\n #initColumns(columns: ColumnOptions<T>[], headerRow: HTMLElement) {\n this.#columnData.clear();\n // We need to make sure at least one column is visible\n let colVisible = false;\n\n for (const colOptions of columns) {\n const header = document.createElement('th');\n const headerContent = document.createElement('div');\n const titleWrapper = document.createElement('div');\n const titleElement = document.createElement('span');\n\n const colData: ColumnData<T> = {\n field: colOptions.field,\n options: {\n title: colOptions.title ?? toHumanReadable(colOptions.field),\n sortable: colOptions.sortable ?? true,\n searchable: colOptions.searchable ?? false,\n tokenize: colOptions.tokenize ?? false,\n resizable: colOptions.resizable ?? true,\n valueFormatter: colOptions.valueFormatter ?? null,\n elementFormatter: colOptions.elementFormatter ?? null,\n sorter: colOptions.sorter ?? null,\n sortValue: colOptions.sortValue ?? null,\n filter: colOptions.filter ?? null,\n },\n state: {\n visible: true,\n sortState: null,\n width: null,\n },\n headerElement: header,\n titleElement: titleElement,\n resizeStartWidth: null,\n resizeStartX: null,\n };\n\n this.#columnData.set(colOptions.field, colData);\n\n header.dataset.dtField = colOptions.field;\n header.hidden = !colData.state.visible;\n header.title = colData.options.title;\n\n headerContent.classList.add('dt-header-content');\n header.append(headerContent);\n\n titleWrapper.classList.add('dt-header-title-wrapper');\n headerContent.append(titleWrapper);\n\n titleElement.classList.add('dt-header-title');\n titleElement.innerHTML = colData.options.title;\n titleWrapper.append(titleElement);\n\n const sorter = document.createElement('div');\n sorter.classList.add('dt-sort-icon');\n titleWrapper.append(sorter);\n\n const resizer = document.createElement('div');\n resizer.classList.add('dt-resizer');\n headerContent.append(resizer);\n\n headerRow.append(header);\n\n if (colData.state.visible) {\n colVisible = true;\n }\n\n this.updateColumnOptions(colOptions.field, colData.options);\n\n if (this.#options.rearrangeable) {\n header.draggable = true;\n }\n\n // Sort event listener\n titleWrapper.addEventListener('click', () => {\n if (!header.classList.contains('dt-sortable')) return;\n\n if (!colData.state.sortState) {\n this.sort(colData.field, 'asc');\n } else if (colData.state.sortState.order === 'asc') {\n this.sort(colData.field, 'desc');\n } else if (colData.state.sortState.order) {\n this.sort(colData.field, null);\n }\n });\n\n // Drag and drop event listeners\n header.addEventListener('dragstart', this.#onDragColumnStart);\n header.addEventListener('dragenter', this.#onDragColumnEnter);\n header.addEventListener('dragover', this.#onDragColumnOver);\n header.addEventListener('dragleave', this.#onDragColumnLeave);\n header.addEventListener('drop', this.#onDragColumnDrop);\n header.addEventListener('dragend', this.#onDragColumnEnd);\n // Resize event listeners\n header.addEventListener('mousedown', this.#onResizeColumnStart);\n header.addEventListener('dblclick', this.#onResizeColumnDoubleClick);\n }\n\n if (this.#columnData.size === 0) {\n console.warn('No columns found. At least one column is required.');\n } else if (!colVisible) {\n console.warn(\n 'At least a single column must be visible. Showing the first column.',\n );\n const col = columns[0].field;\n this.showColumn(col);\n }\n }\n\n #loadRow(row: InternalRowData<T>, index: number) {\n // Add the index\n const metadata: RowMetadata = {\n index: index++,\n tokens: {},\n compareValues: {},\n sortValues: {},\n };\n row._metadata = metadata;\n\n for (const [field, col] of this.#columnData) {\n const value = getNestedValue(row, field);\n\n // Cache precomputed values for sorting\n if (typeof col.options.sortValue === 'function') {\n metadata.sortValues[field] = col.options.sortValue(value);\n } else if (typeof value === 'string') {\n metadata.sortValues[field] = value.toLocaleLowerCase();\n } else {\n metadata.sortValues[field] = value;\n }\n\n // Cache precomputed lower-case values for search\n if (typeof value === 'string') {\n metadata.compareValues[field] = value.toLocaleLowerCase();\n }\n\n // Tokenize any searchable columns\n if (col.options.searchable && col.options.tokenize && value) {\n metadata.tokens[field] = this.#options\n .tokenizer(value)\n .map(token => token.value);\n }\n }\n\n // Add any extra search fields\n for (const field of this.#options.extraSearchFields) {\n const value = getNestedValue(row, field);\n // Cache precomputed lower-case values for search\n if (typeof value === 'string') {\n metadata.compareValues[field] = value.toLocaleLowerCase();\n }\n }\n\n return row;\n }\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 #calculateSearchScore(query: string, target: string): number {\n if (!query || !target) {\n return 0;\n }\n\n let baseScore = 0;\n let matchTypeWeight = 0;\n\n if (target === query) {\n matchTypeWeight = DataTable.MatchWeights.EXACT;\n baseScore = query.length;\n } else if (target.startsWith(query)) {\n matchTypeWeight = DataTable.MatchWeights.PREFIX;\n baseScore = query.length;\n } else if (target.includes(query)) {\n matchTypeWeight = DataTable.MatchWeights.SUBSTRING;\n baseScore = query.length;\n } else {\n return 0;\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 return baseScore * matchTypeWeight * specificityBonus;\n }\n\n #searchField(\n query: QueryToken | RegExp,\n value: string,\n tokens?: string[],\n ): number {\n // RegExp bypasses tokenization and scoring\n if (query instanceof RegExp) {\n return query.test(value) ? 1 : 0;\n }\n\n // Simple search, no scoring\n if (!this.#options.enableSearchScoring) {\n // Quoted tokens bypass tokenization and no tokens means column wasn't tokenized.\n if (query.quoted || !tokens) {\n return value.includes(query.value) ? 1 : 0;\n }\n\n return tokens.some(token => token == query.value) ? 1 : 0;\n }\n\n // Complex scored search\n // Quoted tokens bypass tokenization and no tokens means column wasn't tokenized.\n if (query.quoted || !tokens) {\n return this.#calculateSearchScore(query.value, value);\n }\n\n return tokens\n .map(token => this.#calculateSearchScore(query.value, token))\n .reduce((accumulator, score) => (accumulator += score), 0);\n }\n\n #filterField(\n value: any,\n filter: any,\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 => this.#filterField(value, element));\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 #filterRow(row: InternalRowData<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 = (this.#filters as any)[field];\n const value = getNestedValue(row, field);\n if (typeof filter === 'function') {\n if (!filter(value)) {\n return false;\n }\n } else {\n const col = this.#columnData.get(field as NestedKeyOf<T>);\n const filterCallback = col ? col.options.filter : undefined;\n if (!this.#filterField(value, filter, filterCallback)) {\n return false;\n }\n }\n }\n return true;\n }\n\n #filterRows() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('reApplyFilters');\n return;\n } else {\n this.#blockedUpdates.delete('reApplyFilters');\n }\n\n const searchableFields = [...this.#columnData.values()]\n .filter(col => col.options.searchable)\n .map(c => c.field);\n\n const fields = [...searchableFields, ...this.#options.extraSearchFields];\n\n const rows = [...this.#rows.values()];\n this.#filteredRows = rows.filter((row, index) => {\n row._metadata.searchScore = 0;\n // Filter takes precedence over search.\n if (!this.#filterRow(row, index)) {\n return false;\n }\n\n if (!this.#query) {\n return true;\n }\n\n for (const field of fields) {\n const originalValue = getNestedValue(row, field);\n const compareValue = row._metadata.compareValues[field];\n const columnTokens = row._metadata.tokens[field];\n\n if (\n typeof originalValue !== 'string' ||\n typeof compareValue !== 'string'\n ) {\n continue;\n }\n\n let score: number = 0;\n if (this.#query instanceof RegExp) {\n score = this.#searchField(this.#query, originalValue, columnTokens);\n } else {\n for (const token of this.#query) {\n score += this.#searchField(token, compareValue, columnTokens);\n }\n }\n\n //const score = this.#searchField([...tokens], this.#query);\n row._metadata.searchScore += score;\n }\n\n return row._metadata.searchScore > 0;\n });\n\n this.#sortRows();\n\n const changeEvent = new CustomEvent<\n DataTableEventMap<T>['dt.rows.changed']\n >('dt.rows.changed', {\n cancelable: false,\n detail: {\n dataTable: this,\n },\n });\n\n this.dispatchEvent(changeEvent);\n }\n\n #compareRows(\n a: InternalRowData<T>,\n b: InternalRowData<T>,\n col: ColumnData<T>,\n ): number {\n let aValue, bValue;\n\n if (!col.state.sortState) {\n return 0;\n }\n\n if (col.state.sortState?.order === 'asc') {\n aValue = a._metadata.sortValues[col.field];\n bValue = b._metadata.sortValues[col.field];\n } else if (col.state.sortState?.order === 'desc') {\n aValue = b._metadata.sortValues[col.field];\n bValue = a._metadata.sortValues[col.field];\n }\n\n if (typeof col.options.sorter === 'function') {\n const ret = col.options.sorter(aValue, bValue);\n if (ret !== 0) return ret;\n }\n\n const aIsNull = aValue == null;\n const bIsNull = bValue == null;\n\n if (aIsNull && !bIsNull) return -1;\n if (bIsNull && !aIsNull) return 1;\n\n if (aValue < bValue) return -1;\n if (aValue > bValue) return 1;\n return 0;\n }\n\n #sortRows() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('reSortRows');\n return;\n } else {\n this.#blockedUpdates.delete('reSortRows');\n }\n\n const sortedColumns = [...this.#columnData.values()]\n // Filter to visible columns with active sort states\n .filter(col => !col.headerElement.hidden && col.state.sortState)\n // Sort our columns by their sort priority.\n // This is how sorting by multiple columns is handled.\n .sort(\n (a, b) => b.state.sortState!.priority - a.state.sortState!.priority,\n );\n\n this.#filteredRows.sort((a, b) => {\n // Try to sort by search score if we're using scoring and there is a query.\n if (this.#options.enableSearchScoring && this.#query) {\n const aValue = a._metadata.searchScore || 0;\n const bValue = b._metadata.searchScore || 0;\n if (aValue > bValue) return -1;\n if (aValue < bValue) return 1;\n }\n\n for (const col of sortedColumns) {\n const comp = this.#compareRows(a, b, col);\n if (comp !== 0) {\n return comp;\n }\n }\n\n // Always fall back to the index column\n return a._metadata.index - b._metadata.index;\n });\n this.#renderTable();\n }\n\n #updateHeaders() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('updateHeaders');\n return;\n } else {\n this.#blockedUpdates.delete('updateHeaders');\n }\n\n for (const col of this.#columnData.values()) {\n // Update the order of headers\n col.headerElement.parentElement?.append(col.headerElement);\n col.headerElement.hidden = !col.state.visible;\n col.headerElement.draggable = this.#options.rearrangeable;\n col.titleElement.textContent = col.options.title;\n\n if (col.options.resizable) {\n col.headerElement.classList.add('dt-resizeable');\n } else {\n col.headerElement.classList.remove('dt-resizeable');\n }\n\n if (col.options.sortable) {\n col.headerElement.classList.add('dt-sortable');\n } else {\n col.headerElement.classList.remove('dt-sortable');\n }\n\n if (!col.state.sortState) {\n col.headerElement?.classList.remove('dt-ascending');\n col.headerElement?.classList.remove('dt-descending');\n } else if (col.state.sortState.order === 'asc') {\n col.headerElement?.classList.add('dt-ascending');\n col.headerElement?.classList.remove('dt-descending');\n } else if (col.state.sortState.order === 'desc') {\n col.headerElement?.classList.add('dt-descending');\n col.headerElement?.classList.remove('dt-ascending');\n }\n }\n }\n\n #renderTable() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('reRenderTable');\n return;\n } else {\n this.#blockedUpdates.delete('reRenderTable');\n }\n\n const useVirtualScroll = this.rows.length >= this.#options.virtualScroll;\n\n if (useVirtualScroll && !this.#virtualScroll) {\n this.#virtualScroll = new this.#options.virtualScrollClass({\n container: this.#scroller,\n element: this.#tbody,\n generator: index => this.#createRow(index),\n });\n } else if (!useVirtualScroll && this.#virtualScroll) {\n this.#virtualScroll.stop();\n this.#virtualScroll = null;\n }\n\n this.#tbody.innerHTML = '';\n if (this.#virtualScroll) {\n try {\n this.#virtualScroll.start(this.#filteredRows.length);\n } catch (error) {\n if (error instanceof VirtualScrollError) {\n console.warn(\n 'Failed to start virtual scroll... falling back to standard rendering',\n );\n console.warn(error.stack);\n }\n }\n } else {\n if (this.#filteredRows.length > WARN_ROW_COUNT) {\n const count = WARN_ROW_COUNT.toLocaleString();\n console.warn(\n `Virtual scroll disabled with more than ${count} rows... Good luck with that!`,\n );\n }\n\n const rowElements = this.#filteredRows.map((_, index) =>\n this.#createRow(index),\n );\n this.#tbody.append(...rowElements);\n }\n\n if (this.#rows.size === 0) {\n this.showMessage(this.#options.noDataText, 'dt-empty');\n } else if (this.#filteredRows.length === 0) {\n this.showMessage(this.#options.noMatchText, 'dt-empty');\n }\n }\n\n #markText(element: HTMLElement, query: RegExp) {\n if (element.children.length === 0) {\n let text = element.textContent ?? '';\n const classes = this.#options.classes.mark.join(' ');\n text = text.replace(\n query,\n match => `<mark class=\"${classes}\">${match}</mark>`,\n );\n element.innerHTML = text;\n } else {\n for (const child of element.children) {\n if (child instanceof HTMLElement) {\n this.#markText(child, query);\n }\n }\n }\n }\n\n #updateCell(\n td: HTMLTableCellElement,\n value: any,\n col: ColumnData<T>,\n row: T,\n ) {\n if (typeof col.options.valueFormatter === 'function') {\n value = col.options.valueFormatter(value, row);\n }\n\n if (value != null) {\n td.textContent = value;\n // Full text on hover\n td.title = String(value);\n } else {\n td.textContent = this.#options.emptyValuePlaceholder;\n }\n\n if (typeof col.options.elementFormatter === 'function') {\n col.options.elementFormatter(value, row, td);\n }\n\n if (\n this.#options.highlightSearch &&\n this.#query &&\n col.options.searchable\n ) {\n let regex: RegExp;\n if (this.#query instanceof RegExp) {\n regex = this.#query;\n } else {\n const tokens = this.#query.map(token => token.value).join('|');\n regex = new RegExp(tokens, 'gi');\n }\n\n this.#markText(td, regex);\n }\n\n td.hidden = col.state.visible ? false : true;\n }\n\n #createRow(index: number): HTMLTableRowElement {\n const row = this.#filteredRows[index];\n const tr = document.createElement('tr');\n tr.classList.add(...this.#options.classes.tr);\n tr.dataset.dtIndex = String(row._metadata.index);\n\n for (const [field, col] of this.#columnData) {\n const value = getNestedValue(row, field);\n const td = document.createElement('td');\n td.classList.add(...this.#options.classes.td);\n td.dataset.dtField = field;\n this.#updateCell(td, value, col, row);\n tr.append(td);\n }\n\n if (typeof this.#options.rowFormatter === 'function') {\n try {\n this.#options.rowFormatter(row, tr);\n } catch (error) {\n console.error('Row formatter callback failed with the following error');\n console.error(error);\n }\n }\n\n return tr;\n }\n\n /**\n * Force the table to a fixed layout by setting the width of all columns\n * to their current width in pixels and then setting the table to fit-content.\n */\n #ensureFixedLayout() {\n if (!this.#tableWidthIsFixed) {\n this.#tableWidthIsFixed = true;\n\n for (const column of this.#columnData.values()) {\n const currentWidth = column.headerElement.offsetWidth;\n column.state.width = currentWidth;\n column.headerElement.style.width = `${currentWidth}px`;\n }\n\n this.#table.style.width = 'fit-content';\n }\n }\n\n #resizeColumn(column: ColumnData<T>, width: number | null) {\n this.#ensureFixedLayout();\n\n if (width !== null && width < 0) {\n width = 0;\n }\n\n column.state.width = width;\n\n let headerWidth;\n if (width == null) {\n headerWidth = '';\n } else if (width <= 0) {\n headerWidth = '0px';\n } else {\n headerWidth = `${width}px`;\n }\n column.headerElement.style.width = headerWidth;\n //column.headerElement.style.maxWidth = headerWidth;\n }\n\n #applyBlockedUpdates() {\n while (this.#blockedUpdates.size) {\n if (this.#blockedUpdates.has('reloadData')) {\n this.loadData(this.data);\n this.#blockedUpdates.delete('reloadData');\n } else if (this.#blockedUpdates.has('reApplyFilters')) {\n this.#filterRows();\n this.#blockedUpdates.delete('reApplyFilters');\n } else if (this.#blockedUpdates.has('reSortRows')) {\n this.#sortRows();\n this.#blockedUpdates.delete('reSortRows');\n } else if (this.#blockedUpdates.has('reRenderTable')) {\n this.#renderTable();\n this.#blockedUpdates.delete('reRenderTable');\n }\n\n if (this.#blockedUpdates.has('updateHeaders')) {\n this.#updateHeaders();\n }\n }\n }\n\n /* Event handlers */\n\n #onTableClicked = (event: MouseEvent) => {\n // Ignore events if the user is highlighting text\n if (window.getSelection()?.toString()) return;\n\n let tr, td, field;\n if (event.target instanceof HTMLTableCellElement) {\n td = event.target;\n tr = td.parentElement;\n field = td.dataset.dtField;\n } else if (event.target instanceof HTMLTableRowElement) {\n tr = event.target;\n }\n\n if (tr) {\n const index = parseInt(tr.dataset.dtIndex || '');\n if (!isNaN(index)) {\n const row = this.#filteredRows.find(\n value => value._metadata.index === index,\n );\n if (row) {\n const rowEvent = new CustomEvent<\n DataTableEventMap<T>['dt.row.clicked']\n >('dt.row.clicked', {\n cancelable: false,\n detail: {\n row: row,\n index: index,\n column: field,\n originalEvent: event,\n },\n });\n this.dispatchEvent(rowEvent);\n }\n }\n }\n };\n\n #onResizeColumnStart = (event: MouseEvent) => {\n // If target is not the resizer, we don't care.\n if (!(event.target instanceof HTMLElement)) return;\n if (!event.target.classList.contains('dt-resizer')) return;\n // If the current target isn't the header, we don't care.\n if (!(event.currentTarget instanceof HTMLElement)) return;\n if (!event.currentTarget.dataset.dtField) return;\n\n event.stopImmediatePropagation();\n event.preventDefault();\n\n const field = event.currentTarget.dataset.dtField;\n const col = this.#columnData.get(field as NestedKeyOf<T>);\n if (!col) return;\n this.#resizingColumn = col;\n\n col.resizeStartX = event.clientX;\n col.resizeStartWidth = col.headerElement.offsetWidth;\n\n document.addEventListener('mousemove', this.#onResizeColumnMove);\n document.addEventListener('mouseup', this.#onResizeColumnEnd);\n };\n\n #onResizeColumnMove = (event: MouseEvent) => {\n if (!this.#resizingColumn) return;\n event.stopImmediatePropagation();\n event.preventDefault();\n\n const dx = event.clientX - this.#resizingColumn.resizeStartX!;\n const newWidth = this.#resizingColumn.resizeStartWidth! + dx;\n this.#resizeColumn(this.#resizingColumn, newWidth);\n };\n\n #onResizeColumnEnd = (event: MouseEvent) => {\n if (!this.#resizingColumn) return;\n event.stopImmediatePropagation();\n event.preventDefault();\n\n document.removeEventListener('mousemove', this.#onResizeColumnMove);\n document.removeEventListener('mouseup', this.#onResizeColumnEnd);\n\n const resizeEvent = new CustomEvent<DataTableEventMap<T>['dt.col.resize']>(\n 'dt.col.resize',\n {\n cancelable: false,\n detail: {\n column: this.#resizingColumn.field,\n width: this.#resizingColumn.headerElement.offsetWidth,\n },\n },\n );\n\n this.dispatchEvent(resizeEvent);\n\n this.#resizingColumn = null;\n };\n\n #onResizeColumnDoubleClick = (event: MouseEvent) => {\n // If target is not the resizer, we don't care.\n if (!(event.target instanceof HTMLElement)) return;\n if (!event.target.classList.contains('dt-resizer')) return;\n // If the current target isn't the header, we don't care.\n if (!(event.currentTarget instanceof HTMLElement)) return;\n if (!event.currentTarget.dataset.dtField) return;\n\n const field = event.currentTarget.dataset.dtField;\n const columnData = this.#columnData.get(field as NestedKeyOf<T>);\n if (!columnData) return;\n\n // Calculate the width of the widest cell by rendering\n // offscreen and then resize the column to that value.\n\n let maxWidth = columnData.titleElement.scrollWidth;\n if (this.#filteredRows.length > 0) {\n if (!this.#textMeasurementContext) {\n this.#textMeasurementContext = document\n .createElement('canvas')\n .getContext('2d');\n }\n const context = this.#textMeasurementContext;\n\n // Get the font styles and padding from a sample cell\n const sampleCell = this.#tbody.querySelector('td');\n let cellPadding = 0;\n if (sampleCell && context) {\n const style = window.getComputedStyle(sampleCell);\n context.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n cellPadding =\n parseFloat(style.paddingLeft) + parseFloat(style.paddingRight);\n }\n\n for (const row of this.#filteredRows) {\n let value = getNestedValue(row, field);\n if (typeof columnData.options.valueFormatter === 'function') {\n value = columnData.options.valueFormatter(value, row);\n }\n const text = value == null ? '' : String(value);\n const textWidth = context?.measureText(text).width ?? 0;\n maxWidth = Math.max(maxWidth, textWidth + cellPadding);\n }\n }\n\n this.#resizeColumn(columnData, maxWidth);\n };\n\n #onDragColumnStart = (event: DragEvent) => {\n const target = event.target as HTMLElement;\n const field = target.dataset.dtField;\n\n if (event.dataTransfer && field) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', field);\n }\n };\n\n #onDragColumnOver = (event: DragEvent) => {\n event.preventDefault();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'move';\n }\n return false;\n };\n\n #onDragColumnEnter = (event: DragEvent) => {\n const target = event.target as HTMLElement;\n target.classList.add('dt-drag-over');\n };\n\n #onDragColumnLeave = (event: DragEvent) => {\n const target = event.target as HTMLElement;\n target.classList.remove('dt-drag-over');\n };\n\n #onDragColumnDrop = (event: DragEvent) => {\n const dragField = event.dataTransfer?.getData('text/plain');\n const target = event.currentTarget as HTMLElement;\n const dropField = target.dataset.dtField;\n\n if (!dragField || !dropField) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n const columns = [...this.#columnData.values()];\n const dragIndex = columns.findIndex(col => col.field === dragField);\n const dropIndex = columns.findIndex(col => col.field === dropField);\n\n if (dragIndex > -1 && dropIndex > -1) {\n const [draggedColumn] = columns.splice(dragIndex, 1);\n const droppedColumn = this.#columnData.get(dropField as NestedKeyOf<T>);\n if (!droppedColumn) return;\n\n columns.splice(dropIndex, 0, draggedColumn);\n const newColumnOrder = columns.map(col => col.field);\n const reorderEvent = new CustomEvent<\n DataTableEventMap<T>['dt.col.reorder']\n >('dt.col.reorder', {\n cancelable: true,\n detail: {\n draggedColumn: draggedColumn.field,\n dropColumn: droppedColumn.field,\n order: newColumnOrder,\n },\n });\n if (!this.dispatchEvent(reorderEvent)) {\n return;\n }\n\n this.setColumnOrder(newColumnOrder);\n }\n };\n\n #onDragColumnEnd = () => {\n const elements = document.querySelectorAll('.dt-drag-over');\n for (const element of elements) {\n element.classList.remove('dt-drag-over');\n }\n };\n\n addEventListener<K extends keyof DataTableEventMap<T>>(\n type: K,\n listener: (\n this: DataTable<T>,\n ev: CustomEvent<DataTableEventMap<T>[K]>,\n ) => any,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n // This is the generic fallback for any other string event type (e.g., standard DOM events).\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n // The single implementation for both overloads.\n addEventListener(type: any, listener: any, options?: any) {\n super.addEventListener(type, listener, options);\n }\n\n private readonly TABLE_OPTION_CONFIGS: TableOptionConfigs<T> = {\n virtualScroll: {\n effect: 'reRenderTable',\n handler: value => {\n return virtualScrollToNumber(value);\n },\n },\n highlightSearch: {\n effect: 'reRenderTable',\n },\n tokenizeSearch: {\n effect: 'reloadData',\n handler: value => {\n this.search(this.#userQuery);\n return value;\n },\n },\n enableSearchScoring: {\n effect: 'reApplyFilters',\n },\n rearrangeable: {\n effect: 'updateHeaders',\n },\n extraSearchFields: {\n effect: 'reloadData',\n },\n emptyValuePlaceholder: {\n effect: 'reRenderTable',\n },\n noDataText: {\n effect: 'reRenderTable',\n },\n noMatchText: {\n effect: 'reRenderTable',\n },\n classes: {\n effect: 'reRenderTable',\n handler: value => {\n const classes = convertClasses(this.#options.classes, value);\n this.#scroller.className = classes.scroller.join(' ');\n this.#thead.className = classes.thead.join(' ');\n this.#tbody.className = classes.tbody.join(' ');\n\n for (const col of this.#columnData.values()) {\n col.headerElement.className = classes.th.join(' ');\n }\n return classes;\n },\n },\n rowFormatter: {\n effect: 'reRenderTable',\n },\n tokenizer: {\n effect: 'reloadData',\n },\n virtualScrollClass: {\n effect: 'reRenderTable',\n handler: value => {\n this.#virtualScroll?.stop();\n this.#virtualScroll = null;\n return value;\n },\n },\n };\n\n private readonly COLUMN_OPTION_CONFIGS: ColumnOptionConfigs<T> = {\n title: {\n effect: 'updateHeaders',\n },\n searchable: {\n effect: 'reApplyFilters',\n },\n sortable: {\n effect: 'updateHeaders',\n },\n resizable: {\n effect: 'updateHeaders',\n },\n tokenize: {\n effect: 'reloadData',\n },\n valueFormatter: {\n effect: 'reRenderTable',\n },\n elementFormatter: {\n effect: 'reRenderTable',\n },\n sorter: {\n effect: 'reSortRows',\n },\n sortValue: {\n effect: 'reloadData',\n },\n filter: {\n effect: 'reApplyFilters',\n },\n };\n}\n\n// User can provide either string or list of strings. Internally we enforce a list of strings.\ntype ConcreteTableClasses = Required<{ [K in keyof TableClasses]: string[] }>;\n// Table options without data and with classes and virtual scroll as a single type for internal use\ntype ConcreteTableOptions<T> = Required<\n Omit<TableOptions<T>, 'data' | 'classes' | 'virtualScroll'>\n> & { classes: ConcreteTableClasses; virtualScroll: number };\n\ntype UpdatableTableOptions<T> = TableOptions<T>;\n\n// Type for describing what effect a change has on the table\ntype TableEffect =\n | 'reloadData'\n | 'reApplyFilters'\n | 'reRenderTable'\n | 'reSortRows'\n | 'updateHeaders'\n | null;\n\n// Type for controlling how each table option effects the table\ntype TableOptionConfigs<T> = {\n [K in keyof Required<UpdatableTableOptions<T>>]: {\n // The effect changing the option has on the table.\n effect: TableEffect;\n // A handler to modify the value of the option before it is applied or provide any specialized logic\n handler?: (\n value: Required<UpdatableTableOptions<T>>[K],\n ) => ConcreteTableOptions<T>[K];\n };\n};\n\ntype ColumnOptionConfigs<T> = {\n [K in keyof Required<ColumnOptionsWithoutField<T>>]: {\n effect: TableEffect;\n handler?: (\n value: Required<ColumnOptionsWithoutField<T>>[K],\n ) => Required<ColumnOptionsWithoutField<T>>[K];\n };\n};\n\ntype ColumnOptionsWithoutField<T> = Omit<\n ColumnOptions<T>,\n 'field'\n>;\ntype ColumnStateWithoutField<T> = Omit<ColumnState<T>, 'field'>;\n\ntype ColumnDataOptions<T> = Required<\n ColumnOptionsWithoutField<T>\n>;\ntype ColumnDataState<T> = Required<ColumnStateWithoutField<T>>;\n\ninterface ColumnData<T> {\n field: NestedKeyOf<T>;\n options: ColumnDataOptions<T>;\n state: ColumnDataState<T>;\n\n headerElement: HTMLElement;\n titleElement: HTMLElement;\n\n resizeStartX: number | null;\n resizeStartWidth: number | null;\n}\n\ninterface RowMetadata {\n index: number;\n searchScore?: number;\n tokens: Record<string, string[]>;\n compareValues: Record<string, string>;\n sortValues: Record<string, any>;\n}\n\ntype InternalRowData<T> = T & { _metadata: RowMetadata };\n\nconst WARN_ROW_COUNT = 10_000;\n\n/**\n * Defines the mapping between event names and their detail object types.\n */\nexport interface DataTableEventMap<T> {\n 'dt.row.clicked': {\n row: T;\n index: number;\n column: string | undefined;\n originalEvent: MouseEvent;\n };\n\n 'dt.rows.changed': object;\n\n 'dt.col.sort': {\n column: string;\n order: SortOrder | null;\n };\n\n 'dt.col.visibility': {\n column: string;\n visible: boolean;\n };\n\n 'dt.col.resize': {\n column: string;\n width: number;\n };\n\n 'dt.col.reorder': {\n draggedColumn: string;\n dropColumn: string;\n order: string[];\n };\n\n 'dt.search': {\n query: string | RegExp | null;\n };\n}\n\nexport type * from './types';\nexport { createRegexTokenizer };\n","import {\n RestorableColumnState,\n RestorableTableState,\n} from '../../data-table/types';\nimport { IDataTable, LocalStorageAdapterOptions } from './types';\n/**\n * Monitors a {@link DataTable} instance for changes and saves the state to local storage.\n */\nexport class LocalStorageAdapter<T> {\n #dataTable: IDataTable<T>;\n #storageKey: string;\n #options: Required<LocalStorageAdapterOptions> = {\n saveSearch: true,\n saveColumnSorting: true,\n saveColumnVisibility: true,\n saveColumnWidth: true,\n saveColumnOrder: true,\n };\n\n /**\n * @param dataTable - The DataTable instance to monitor.\n * @param storageKey - The key to use for saving the state in localStorage.\n * @param options - The options for configuring what is stored.\n */\n constructor(\n dataTable: IDataTable<T>,\n storageKey: string,\n options?: LocalStorageAdapterOptions,\n ) {\n this.#dataTable = dataTable;\n this.#storageKey = storageKey;\n this.#options = { ...this.#options, ...options };\n\n // Restore state before adding the listeners.\n this.restoreState();\n\n if (this.#options.saveSearch) {\n dataTable.addEventListener('dt.search', this.#saveStateAfterEvent);\n }\n\n if (this.#options.saveColumnSorting) {\n dataTable.addEventListener('dt.col.sort', this.#saveStateAfterEvent);\n }\n\n if (this.#options.saveColumnVisibility) {\n dataTable.addEventListener(\n 'dt.col.visibility',\n this.#saveStateAfterEvent,\n );\n }\n\n if (this.#options.saveColumnWidth) {\n dataTable.addEventListener('dt.col.resize', this.#saveStateAfterEvent);\n }\n\n if (this.#options.saveColumnOrder) {\n dataTable.addEventListener('dt.col.reorder', this.#saveStateAfterEvent);\n }\n }\n\n /**\n * Saves the current column state to localStorage.\n */\n saveState() {\n const savedTableState: RestorableTableState<T> = {\n columns: [],\n };\n const tableState = this.#dataTable.getState();\n\n if (this.#options.saveSearch) {\n savedTableState.searchQuery = tableState.searchQuery;\n }\n\n if (this.#options.saveColumnOrder) {\n savedTableState.columnOrder = tableState.columnOrder;\n }\n\n for (const columnState of tableState.columns) {\n const savedColumnState: RestorableColumnState<T> = {\n field: columnState.field,\n };\n\n if (this.#options.saveColumnSorting) {\n savedColumnState.sortState = columnState.sortState;\n }\n\n if (this.#options.saveColumnVisibility) {\n savedColumnState.visible = columnState.visible;\n }\n\n if (this.#options.saveColumnWidth) {\n savedColumnState.width = columnState.width;\n }\n\n savedTableState.columns?.push(savedColumnState);\n }\n\n localStorage.setItem(this.#storageKey, JSON.stringify(savedTableState));\n }\n\n /**\n * Restores the column state from localStorage.\n */\n restoreState() {\n const json = localStorage.getItem(this.#storageKey);\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 (this.#options.saveSearch) {\n tableStateToRestore.searchQuery = savedTableState.searchQuery;\n }\n\n if (this.#options.saveColumnOrder) {\n tableStateToRestore.columnOrder = savedTableState.columnOrder;\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 (this.#options.saveColumnVisibility) {\n columnStateToRestore.visible = savedColumnState.visible;\n }\n\n if (this.#options.saveColumnWidth) {\n columnStateToRestore.width = savedColumnState.width;\n }\n\n if (this.#options.saveColumnSorting) {\n columnStateToRestore.sortState = savedColumnState.sortState;\n }\n tableStateToRestore.columns.push(columnStateToRestore);\n }\n }\n\n this.#dataTable.restoreState(tableStateToRestore);\n } catch (error) {\n console.error('Failed to restore DataTable state:', error);\n }\n }\n\n /**\n * Clears the saved state from localStorage.\n */\n clearState() {\n localStorage.removeItem(this.#storageKey);\n }\n\n #saveStateAfterEvent = () => setTimeout(() => this.saveState(), 0);\n}\n"],"mappings":"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","names":["classesToArray","classes","toHumanReadable","str","char","createRegexTokenizer","exp","regex","value","token","virtualScrollToNumber","virtualScroll","convertClasses","defaultClasses","userClasses","getNestedValue","obj","path","keys","current","key","_warned","_container","_element","_generator","_rowCount","_rowHeight","_padding","_animationFrame","_started","_scrollTop","_topPaddingElement","_bottomPaddingElement","_resizeObserver","_scrollCallback","_VirtualScroll_instances","scheduleRender_fn","renderChunk_fn","updateRowHeight_fn","_VirtualScroll","generator","container","element","nodePadding","__privateAdd","__privateGet","__privateSet","__privateMethod","index","px","rowCount","scrollTop","rowHeight","padding","totalContentHeight","originalHeight","viewHeight","totalPadding","startNode","visibleNodesCount","offsetY","remainingHeight","visibleChildren","_","actualHeight","renderSize","elements","VirtualScrollError","VirtualScroll","message","_table","_thead","_tbody","_scroller","_textMeasurementContext","_columnData","_rows","_filteredRows","_userQuery","_query","_filters","_virtualScroll","_resizingColumn","_tableWidthIsFixed","_options","_blockUpdates","_blockedUpdates","_DataTable_instances","initTableElements_fn","initColumns_fn","loadRow_fn","calculateSearchScore_fn","searchField_fn","filterField_fn","filterRow_fn","filterRows_fn","compareRows_fn","sortRows_fn","updateHeaders_fn","renderTable_fn","markText_fn","updateCell_fn","createRow_fn","ensureFixedLayout_fn","resizeColumn_fn","applyBlockedUpdates_fn","_onTableClicked","_onResizeColumnStart","_onResizeColumnMove","_onResizeColumnEnd","_onResizeColumnDoubleClick","_onDragColumnStart","_onDragColumnOver","_onDragColumnEnter","_onDragColumnLeave","_onDragColumnDrop","_onDragColumnEnd","_DataTable","table","columns","options","__privateAdd","createRegexTokenizer","VirtualScroll","__spreadValues","event","_a","tr","td","field","index","row","__privateGet","value","rowEvent","col","__privateSet","dx","newWidth","__privateMethod","resizeEvent","columnData","maxWidth","context","sampleCell","cellPadding","style","getNestedValue","text","textWidth","dragField","dropField","dragIndex","dropIndex","draggedColumn","droppedColumn","newColumnOrder","reorderEvent","elements","element","virtualScrollToNumber","classes","convertClasses","data","virtualScrollClass","restOptions","__objRest","tableElement","scroller","thead","headerRow","tbody","column","state","columnState","key","optionKey","config","handler","finalValue","__spreadProps","rows","scrollTop","scrollLeft","internal_row","colSpan","query","searchEvent","filters","colName","order","sortEvent","priorities","priority","maxPriority","visisble","visibilityEvent","filename","all","csvHeaders","csvRows","list","csvContent","blob","a","rowData","filteredIndex","theadHeight","px","fields","newColumns","found_row","current_row","callback","prevBlock","type","listener","_b","_c","_d","_e","_f","_g","_h","_i","_j","colVisible","colOptions","header","headerContent","titleWrapper","titleElement","colData","toHumanReadable","sorter","resizer","metadata","token","target","baseScore","matchTypeWeight","specificityBonus","tokens","accumulator","score","filter","filterFunction","filterCallback","c","originalValue","compareValue","columnTokens","changeEvent","b","aValue","bValue","ret","aIsNull","bIsNull","sortedColumns","comp","useVirtualScroll","error","VirtualScrollError","WARN_ROW_COUNT","count","rowElements","_","match","child","regex","currentWidth","width","headerWidth","DataTable","_dataTable","_storageKey","_options","_saveStateAfterEvent","LocalStorageAdapter","dataTable","storageKey","options","__privateAdd","__privateSet","__spreadValues","__privateGet","_a","savedTableState","tableState","columnState","savedColumnState","json","tableStateToRestore","columnStateToRestore","error"]}
1
+ {"version":3,"sources":["../src/data-table/utils.ts","../src/virtual-scroll/virtual-scroll.ts","../src/data-table/data-table.ts","../src/plugins/local-storage-adapter/local-storage-adapter.ts"],"sourcesContent":["import { TableClasses } from './types';\n\nexport type NestedKeyOf<ObjectType> = ObjectType extends object\n ? {\n [Key in keyof ObjectType &\n (\n | string\n | number\n )]: // Use NonNullable to include optional properties\n NonNullable<ObjectType[Key]> extends any[]\n ? `${Key}`\n : NonNullable<ObjectType[Key]> extends object\n ? // Recurse with the non-nullable type\n `${Key}` | `${Key}.${NestedKeyOf<NonNullable<ObjectType[Key]>>}`\n : `${Key}`;\n }[keyof ObjectType & (string | number)]\n : never;\n\nexport type WithRequiredProp<Type, Key extends keyof Type> = Type &\n Required<Pick<Type, Key>>;\n\nexport const classesToArray = (classes: string[] | string | undefined) => {\n if (typeof classes === 'string' && classes !== '') {\n return classes.split(' ');\n } else if (Array.isArray(classes)) {\n return classes;\n } else if (!classes) {\n return [];\n }\n throw new TypeError('classes must be string or array of strings');\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\nexport 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 function virtualScrollToNumber(virtualScroll: boolean | number) {\n if (typeof virtualScroll === 'boolean') {\n return virtualScroll ? 1 : Number.MAX_SAFE_INTEGER;\n }\n return virtualScroll;\n}\n\nexport function convertClasses(\n defaultClasses: TableClasses,\n userClasses: TableClasses = {},\n) {\n return {\n scroller: [\n ...classesToArray(userClasses.scroller),\n ...classesToArray(defaultClasses.scroller),\n ],\n thead: [\n ...classesToArray(userClasses.thead),\n ...classesToArray(defaultClasses.thead),\n ],\n tbody: [\n ...classesToArray(userClasses.tbody),\n ...classesToArray(defaultClasses.tbody),\n ],\n tr: [\n ...classesToArray(userClasses.tr),\n ...classesToArray(defaultClasses.tr),\n ],\n th: [\n ...classesToArray(userClasses.th),\n ...classesToArray(defaultClasses.th),\n ],\n td: [\n ...classesToArray(userClasses.td),\n ...classesToArray(defaultClasses.td),\n ],\n mark: [\n ...classesToArray(userClasses.mark),\n ...classesToArray(defaultClasses.mark),\n ],\n };\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: any, path: string): any {\n const keys = path.split('.');\n let current = obj;\n\n for (const key of keys) {\n if (current && typeof current === 'object') {\n current = current[key];\n } else {\n return undefined; // Or handle the error as needed\n }\n }\n\n return current;\n}\n","import type {\n VirtualScrollOptions,\n IVirtualScroll,\n IVirtualScrollConstructor,\n} from './types';\n\nconst MAX_ELEMENT_HEIGHT = 33554400;\n\nexport class VirtualScroll implements IVirtualScroll {\n static #warned = false;\n static AVERAGE_RENDER_COUNT = 1000;\n\n #container;\n #element;\n #generator;\n #rowCount = 0;\n #rowHeight = 0;\n #padding = 2;\n #animationFrame = 0;\n #started = false;\n #scrollTop = 0;\n #topPaddingElement: HTMLElement;\n #bottomPaddingElement: HTMLElement;\n #resizeObserver: ResizeObserver;\n\n constructor({\n generator,\n container,\n element = container,\n nodePadding = 10,\n }: VirtualScrollOptions) {\n this.#container = container;\n this.#element = element;\n this.#generator = generator;\n this.#padding = nodePadding;\n this.#topPaddingElement = document.createElement('div');\n this.#topPaddingElement.style.visibility = 'hidden';\n this.#bottomPaddingElement = document.createElement('div');\n this.#bottomPaddingElement.style.visibility = 'hidden';\n this.#resizeObserver = new ResizeObserver(() => this.#scheduleRender());\n }\n\n private get rowHeight() {\n if (!this.#rowHeight) {\n this.#updateRowHeight();\n }\n return this.#rowHeight;\n }\n\n get started() {\n return this.#started;\n }\n\n /*\n * Scroll to a specific index in the virtual scroll.\n * @param index The index to scroll to.\n * @throws RangeError if the index is out of bounds.\n */\n scrollToIndex(index: number) {\n if (index < 0 || index >= this.#rowCount) {\n throw new RangeError('Index out of bounds.');\n }\n this.scrollToPx(this.rowHeight * index);\n }\n\n /**\n * @param px\n */\n scrollToPx(px: number) {\n this.#container.scrollTop = px;\n this.#renderChunk();\n }\n\n #scrollCallback = () => {\n // Only update if we are vertically scrolling.\n // Fixes horizontal scroll bug.\n if (this.#container.scrollTop !== this.#scrollTop) {\n this.#scrollTop = this.#container.scrollTop;\n this.#scheduleRender();\n }\n };\n\n start(rowCount: number) {\n if (!this.#started) {\n this.#container.addEventListener('scroll', this.#scrollCallback);\n this.#resizeObserver.observe(this.#container);\n this.#started = true;\n }\n this.#container.classList.add('dt-virtual-scroll');\n this.#rowCount = rowCount;\n this.#renderChunk();\n }\n\n stop() {\n if (this.#animationFrame) {\n cancelAnimationFrame(this.#animationFrame);\n }\n\n this.#container.classList.remove('dt-virtual-scroll');\n this.#container.removeEventListener('scroll', this.#scrollCallback);\n this.#resizeObserver.disconnect();\n this.#started = false;\n }\n\n #scheduleRender() {\n if (this.#animationFrame) {\n cancelAnimationFrame(this.#animationFrame);\n }\n this.#animationFrame = requestAnimationFrame(() => this.#renderChunk());\n }\n\n #renderChunk() {\n const scrollTop = this.#container.scrollTop;\n const rowCount = this.#rowCount;\n const rowHeight = this.rowHeight;\n const padding = this.#padding;\n\n if (!this.started || !rowCount || !rowHeight) {\n return;\n }\n\n const totalContentHeight = rowHeight * rowCount;\n // Max out the element height so we can get a real height of the container.\n // This fixes an issue when the parent isn't set to grow causing only a\n // small number of rows to render until you scroll.\n const originalHeight = this.#container.style.height;\n this.#container.style.height = '100%';\n const viewHeight = this.#container.offsetHeight;\n this.#container.style.height = originalHeight;\n\n let totalPadding = padding * 2;\n let startNode = Math.floor(scrollTop / rowHeight) - padding;\n\n if (startNode < 0) {\n totalPadding += startNode;\n }\n\n startNode = Math.max(0, startNode);\n\n let visibleNodesCount = Math.ceil(viewHeight / rowHeight) + totalPadding;\n visibleNodesCount = Math.min(rowCount - startNode, visibleNodesCount);\n\n // Always start with an even row.\n // This helps striped tables.\n if (startNode % 2 === 1) {\n startNode--;\n // If we don't add this we might not render the last row\n visibleNodesCount++;\n }\n\n const offsetY = startNode * rowHeight;\n let remainingHeight =\n totalContentHeight - (offsetY + visibleNodesCount * rowHeight);\n if (remainingHeight < 0) {\n remainingHeight = 0;\n }\n\n // Remove the old visible nodes (all nodes between the padding elements)\n while (\n this.#topPaddingElement.nextSibling &&\n this.#topPaddingElement.nextSibling !== this.#bottomPaddingElement\n ) {\n this.#element.removeChild(this.#topPaddingElement.nextSibling);\n }\n\n // Generate the new visible nodes\n const visibleChildren = new Array(visibleNodesCount)\n .fill(null)\n .map((_, index) => this.#generator(index + startNode));\n\n // Update padding heights and insert new nodes\n this.#topPaddingElement.style.height = offsetY + 'px';\n this.#bottomPaddingElement.style.height = remainingHeight + 'px';\n\n // If the top element isn't in the DOM, we need to add the initial structure\n if (!this.#topPaddingElement.parentElement) {\n this.#element.append(\n this.#topPaddingElement,\n ...visibleChildren,\n this.#bottomPaddingElement,\n );\n } else {\n // Otherwise, just insert the new children after the top padding element\n this.#topPaddingElement.after(...visibleChildren);\n }\n\n const actualHeight = this.#element.offsetHeight;\n if (\n !VirtualScroll.#warned &&\n actualHeight < Math.round(totalContentHeight - 1)\n ) {\n VirtualScroll.#warned = true;\n console.error(\n 'Max element height exceeded. Virtual scroll may not work.',\n );\n }\n }\n\n #updateRowHeight() {\n if (this.#rowCount === 0) {\n this.#rowHeight = 0;\n return;\n }\n\n const renderSize = Math.min(\n VirtualScroll.AVERAGE_RENDER_COUNT,\n this.#rowCount,\n );\n // Create an average row height by rendering the first N rows.\n const elements = [];\n for (let i = 0; i < renderSize; ++i) {\n elements.push(this.#generator(i));\n }\n\n const container = document.createElement('div');\n container.style.position = 'absolute';\n container.style.visibility = 'hidden';\n container.style.height = 'auto';\n container.style.width = '100%';\n container.style.top = '-9999px';\n container.style.left = '-9999px';\n container.style.maxHeight = 'none';\n container.style.overflow = 'visible';\n container.style.display = 'block';\n\n try {\n container.append(...elements);\n document.body.append(container);\n this.#rowHeight = container.offsetHeight / renderSize;\n } finally {\n container.remove();\n }\n\n if (this.#rowHeight <= 0) {\n throw new VirtualScrollError(\n `First ${renderSize} rows had no rendered height. Virtual scroll can't be used.`,\n );\n } else if (this.#rowHeight * this.#rowCount > MAX_ELEMENT_HEIGHT) {\n // This seems to be Chrome's max height of an element based on some random testing.\n console.warn(\n 'Virtual scroll height exceeded maximum known element height.',\n );\n }\n }\n}\n\nexport class VirtualScrollError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\n// Just to make sure I don't break anything...\nVirtualScroll satisfies IVirtualScrollConstructor;\n","import './data-table.css';\n\nimport type {\n ColumnFilterCallback,\n ColumnInitOptions,\n ColumnOptions,\n ColumnState,\n FilterCallback,\n Filters,\n LoadOptions,\n QueryToken,\n RestorableTableState,\n SortOrder,\n TableClasses,\n TableInitOptions,\n TableOptions,\n TableState,\n} from './types';\n\nimport {\n convertClasses,\n createRegexTokenizer,\n getNestedValue,\n NestedKeyOf,\n toHumanReadable,\n virtualScrollToNumber,\n} from './utils';\nimport {\n VirtualScroll,\n VirtualScrollError,\n} from '../virtual-scroll/virtual-scroll';\nimport type { IVirtualScroll } from '../virtual-scroll/types';\n\n/**\n * Represents a dynamic and interactive table with features like sorting, searching, filtering,\n * column resizing, column rearranging, and virtual scrolling.\n *\n * @example\n * ```ts\n * type DataType = {id: number, name: string, age: number};\n *\n * const dataTable = new DataTable<DataType>('#myTable', [\n * { field: 'id', title: 'ID', sortable: true },\n * { field: 'name', title: 'Name', searchable: true },\n * { field: 'age', title: 'Age', sortable: true, valueFormatter: (value) => `${value} years` }\n * ], {\n * data: [\n * { id: 1, name: 'Alice', age: 30 },\n * { id: 2, name: 'Bob', age: 24 },\n * ],\n * virtualScroll: true,\n * resizable: true,\n * rearrangeable: true,\n * });\n * ```\n */\nexport class DataTable<T> extends EventTarget {\n private static readonly MatchWeights = {\n EXACT: 100,\n PREFIX: 50,\n SUBSTRING: 10,\n };\n\n // Centralized default options for the DataTable.\n // These are the base values used if not overridden by user-provided options.\n private readonly DEFAULT_OPTIONS: ConcreteTableOptions<T> = {\n virtualScroll: 1000,\n highlightSearch: true,\n tokenizeSearch: false,\n enableSearchScoring: false,\n rearrangeable: true,\n extraSearchFields: [],\n emptyValuePlaceholder: '-',\n noDataText: 'No records found',\n noMatchText: 'No matching records found',\n classes: {\n scroller: ['dt-scroller'],\n thead: ['dt-headers'],\n tbody: [],\n tr: [],\n th: [],\n td: [],\n mark: [],\n },\n rowFormatter: null,\n tokenizer: createRegexTokenizer(),\n virtualScrollClass: VirtualScroll,\n };\n\n // Table elements\n #table: HTMLTableElement;\n #thead: HTMLElement;\n #tbody: HTMLElement;\n #scroller: HTMLElement;\n\n // Used to render cells offscreen and calculate their widths\n // for the auto-resize logic used on resize double click.\n #textMeasurementContext: CanvasRenderingContext2D | null = null;\n\n #columnData: Map<NestedKeyOf<T>, ColumnData<T>> = new Map();\n\n // Current data stored by the initial index\n #rows: Map<number, InternalRowData<T>> = new Map();\n #filteredRows: InternalRowData<T>[] = [];\n\n // Search and filter data\n #userQuery: string | RegExp | null = null;\n #query: QueryToken[] | RegExp | null = null;\n #filters: Filters<T> | FilterCallback<T> | null = null;\n\n #virtualScroll: IVirtualScroll | null = null;\n\n #resizingColumn: ColumnData<T> | null = null;\n #tableWidthIsFixed = false;\n\n #options: ConcreteTableOptions<T> = { ...this.DEFAULT_OPTIONS };\n\n #blockUpdates = false;\n #blockedUpdates: Set<TableEffect> = new Set();\n\n /**\n * Initializes a new instance of the DataTable.\n * @param table - The HTMLTableElement or a CSS selector string for the table.\n * @param columns - List of {@link ColumnOptions} for the table.\n * @param options - Optional configuration options for the DataTable.\n * @throws {SyntaxError} If the table selector does not find an element.\n * @throws {TypeError} If the provided table element is not an HTMLTableElement or if columns option is not an array.\n */\n constructor(\n table: string | HTMLTableElement,\n columns: ColumnInitOptions<T>[],\n options: TableInitOptions<T> = {},\n ) {\n super();\n\n const { data, virtualScrollClass, ...restOptions } = options;\n\n if (virtualScrollClass !== undefined) {\n this.#options.virtualScrollClass = virtualScrollClass;\n }\n\n if (typeof table === 'string') {\n const tableElement = document.querySelector(table);\n if (!tableElement)\n throw new SyntaxError(`Failed to find table using selector ${table}`);\n this.#table = tableElement as HTMLTableElement;\n } else {\n this.#table = table;\n }\n\n if (!(this.#table instanceof HTMLTableElement)) {\n throw new TypeError(\n `Invalid table element type. Must be HTMLTableElement`,\n );\n }\n\n const { scroller, thead, headerRow, tbody } = this.#initTableElements();\n\n this.#scroller = scroller;\n this.#thead = thead;\n this.#tbody = tbody;\n\n this.#initColumns(columns, headerRow);\n this.updateTableOptions({ ...this.#options, ...restOptions });\n\n this.loadData(data ?? []);\n }\n\n /**\n * Gets the current options applied to the table.\n */\n get tableOptions() {\n return structuredClone(this.#options);\n }\n\n /**\n * Gets the currently filtered and sorted rows displayed in the table.\n */\n get rows(): T[] {\n return [...this.#filteredRows];\n }\n\n /**\n * Gets the underlying data\n */\n get data(): T[] {\n return [...this.#rows.values()];\n }\n\n /**\n * Gets the underlying HTMLTableElement managed by this DataTable instance.\n */\n get table(): HTMLTableElement {\n return this.#table;\n }\n\n /**\n * Gets the current state of the table.\n */\n getState(): TableState<T> {\n const columns = [...this.#columnData.values()];\n return {\n searchQuery: this.#userQuery,\n filters: this.#filters,\n scrollPosition: {\n top: this.#scroller.scrollTop,\n left: this.#scroller.scrollLeft,\n },\n columnOrder: columns.map(column => column.field),\n columns: columns.map(column => ({\n field: column.field,\n visible: column.state.visible,\n sortState: column.state.sortState,\n width: column.state.width,\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 restoreState(state: RestorableTableState<T>) {\n this.withoutUpdates(() => {\n if ('searchQuery' in state && state.searchQuery !== undefined) {\n this.search(state.searchQuery);\n }\n\n if ('filters' in state && state.filters !== undefined) {\n this.#filters = state.filters;\n this.filter(state.filters);\n }\n\n if ('scrollPosition' in state && state.scrollPosition !== undefined) {\n this.#scroller.scrollTop = state.scrollPosition.top;\n }\n\n if ('columnOrder' in state && state.columnOrder !== undefined) {\n this.setColumnOrder(state.columnOrder);\n }\n\n if ('columns' in state && state.columns !== undefined) {\n for (const columnState of state.columns) {\n const columnData = this.#columnData.get(columnState.field);\n if (!columnData) {\n console.warn(\n `Attempting to restore state for non-existent column ${columnState.field}`,\n );\n continue;\n }\n\n if ('visible' in columnState && columnState.visible !== undefined) {\n columnData.state.visible = columnState.visible;\n }\n\n if (\n 'sortState' in columnState &&\n columnState.sortState !== undefined\n ) {\n columnData.state.sortState = columnState.sortState;\n }\n\n if ('width' in columnState && columnState.width !== undefined) {\n this.#resizeColumn(columnData, columnState.width);\n }\n }\n }\n });\n }\n\n updateTableOptions(options: UpdatableTableOptions<T>) {\n this.withoutUpdates(() => {\n for (const key in options) {\n const optionKey = key as keyof UpdatableTableOptions<T>;\n const value = options[optionKey]!;\n const config = this.TABLE_OPTION_CONFIGS[optionKey];\n\n if (!config) {\n continue;\n }\n\n this.#blockedUpdates.add(config.effect);\n const handler = config.handler as ((v: any) => any) | undefined;\n const finalValue = handler ? handler(value) : value;\n (this.#options as any)[optionKey] = finalValue;\n }\n\n // Search scoring is only useful with tokenization.\n if (this.#options.enableSearchScoring && !this.#options.tokenizeSearch) {\n this.#options.enableSearchScoring = false;\n console.warn(\n 'Search scoring enabled with tokenization disabled... Ignoring',\n );\n }\n });\n }\n\n getColumnOptions(): Required<ColumnOptions<T>>[];\n getColumnOptions(field: NestedKeyOf<T>): Required<ColumnOptions<T>>;\n getColumnOptions(field?: any) {\n if (field) {\n const columnData = this.#columnData.get(field);\n if (!columnData) {\n throw new Error(\n `Cannot get options for non-existent column \"${field}\"`,\n );\n }\n const options: ColumnOptions<T> = {\n ...columnData.options,\n field: columnData.field,\n };\n return options;\n }\n\n const options = [...this.#columnData.values()].map(\n (data): ColumnOptions<T> => ({ ...data.options, field: data.field }),\n );\n return options;\n }\n\n updateColumnOptions(\n column: NestedKeyOf<T>,\n options: ColumnOptionsWithoutField<T>,\n ) {\n const col = this.#columnData.get(column);\n if (!col) {\n throw new Error(\n `Cannot update options for non-existent column \"${column}\"`,\n );\n }\n\n this.withoutUpdates(() => {\n for (const key in options) {\n const optionKey = key as keyof ColumnOptionsWithoutField<T>;\n const value = options[optionKey]!;\n const config = this.COLUMN_OPTION_CONFIGS[optionKey];\n\n if (!config) {\n continue;\n }\n this.#blockedUpdates.add(config.effect);\n const handler = config.handler as ((v: any) => any) | undefined;\n\n const finalValue = handler ? handler(value) : value;\n (col.options as any)[optionKey] = finalValue;\n }\n });\n }\n\n /**\n * Loads data into the table\n * @param rows - An array of data to be loaded\n * @param options - Configuration for the load operation\n */\n loadData(rows: T[], options: LoadOptions = {}) {\n const scrollTop = this.#scroller.scrollTop;\n const scrollLeft = this.#scroller.scrollLeft;\n\n if (!options.append) {\n this.#rows.clear();\n this.#filteredRows = [];\n }\n\n let index = this.#rows.size;\n for (const row of rows as InternalRowData<T>[]) {\n const internal_row = this.#loadRow(row, index);\n this.#rows.set(index, internal_row);\n index++;\n }\n\n this.#updateHeaders();\n this.#filterRows();\n\n if (options.keepScroll) {\n this.#scroller.scrollTop = scrollTop;\n this.#scroller.scrollLeft = scrollLeft;\n }\n }\n\n /**\n * Displays a message in the table body, typically used for \"no data\" or \"no results\" states.\n * The message is shown in a single row spanning all columns.\n * @param text - The text or HTML message to display.\n * @param classes - A string or array of strings for CSS classes to apply to the message row.\n */\n showMessage(text: string, ...classes: string[]) {\n const colSpan = this.#columnData.size;\n this.#tbody.innerHTML = `<tr class=\"${classes.join(' ')}\"><td colSpan=${colSpan}>${text}</td></tr>`;\n }\n\n /**\n * Clears the current message and dispalsy the normal table data.\n */\n clearMessage() {\n this.#renderTable();\n }\n\n /**\n * Filters rows based on a search query.\n * The search is performed on columns marked as `searchable` and `extraSearchFields`.\n * @param query - The search term (string) or a regular expression. An empty string clears the search.\n */\n search(query?: string | RegExp | null) {\n query ??= null;\n\n const searchEvent = new CustomEvent<DataTableEventMap<T>['dt.search']>(\n 'dt.search',\n {\n cancelable: true,\n detail: {\n query: query ?? null,\n },\n },\n );\n\n if (!this.dispatchEvent(searchEvent)) {\n return;\n }\n\n this.#userQuery = query;\n\n // Clear search on empty string\n if (query === '') {\n query = null;\n }\n\n if (typeof query === 'string') {\n if (this.#options.tokenizeSearch) {\n this.#query = this.#options.tokenizer(query);\n } else {\n this.#query = [{ value: query.toLocaleLowerCase(), quoted: true }];\n }\n } else {\n this.#query = query;\n }\n\n this.#filterRows();\n }\n\n /**\n * Applies filters to the table rows.\n * Filters can be an object where keys are field names and values are the criteria to filter by,\n * or a callback function that receives a row and its index and returns `true` if the row should be included.\n * @param filters - An object defining field-based filters or a custom filter callback function.\n * @throws {TypeError} If `filters` is not an object or a function.\n */\n filter(filters?: Filters<T> | FilterCallback<T> | null) {\n this.#filters = filters ?? null;\n this.#filterRows();\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 colName - 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 */\n sort(colName: NestedKeyOf<T>, order: SortOrder | null) {\n const col = this.#columnData.get(colName);\n if (!col) {\n throw new Error(\n `Cannot get options for non-existent column \"${colName}\"`,\n );\n }\n\n if (order === col.state.sortState?.order) {\n return;\n }\n\n const sortEvent = new CustomEvent<DataTableEventMap<T>['dt.col.sort']>(\n 'dt.col.sort',\n {\n cancelable: true,\n detail: {\n column: col.field,\n order: order,\n },\n },\n );\n\n if (!this.dispatchEvent(sortEvent)) {\n return;\n }\n\n // Column was unsorted, give it a new priority\n if (order && !col.state.sortState) {\n // Create a list of current sort priorities\n const priorities = [...this.#columnData.values()]\n .map(col => col.state.sortState?.priority)\n .filter(priority => priority !== undefined);\n\n const maxPriority = this.#columnData.size + 1;\n const priority = Math.min(maxPriority, ...priorities) - 1;\n col.state.sortState = { order, priority };\n } else if (order && col.state.sortState) {\n // Column was sorted, just updated the order\n col.state.sortState.order = order;\n } else {\n col.state.sortState = null;\n }\n\n const scrollTop = this.#scroller.scrollTop;\n const scrollLeft = this.#scroller.scrollLeft;\n\n this.#updateHeaders();\n this.#sortRows();\n\n this.#scroller.scrollTop = scrollTop;\n this.#scroller.scrollLeft = scrollLeft;\n }\n\n /**\n * Sets the visibility of a specified column.\n * @param colName - The field name of the column.\n * @param visisble - `true` to show the column, `false` to hide it.\n */\n setColumnVisibility(colName: NestedKeyOf<T>, visisble: boolean) {\n const col = this.#columnData.get(colName);\n if (!col) {\n throw new Error(\n `Cannot get options for non-existent column \"${colName}\"`,\n );\n }\n\n if (col.state.visible === visisble) {\n return;\n }\n\n const visibilityEvent = new CustomEvent<\n DataTableEventMap<T>['dt.col.visibility']\n >('dt.col.visibility', {\n cancelable: true,\n detail: {\n column: col.field,\n visible: visisble,\n },\n });\n\n if (!this.dispatchEvent(visibilityEvent)) {\n return;\n }\n\n col.state.visible = visisble;\n this.#updateHeaders();\n // If we hide a column that has sorting, we need to resort.\n // This will also handle hiding all of the columns elements.\n this.#sortRows();\n }\n\n /**\n * Shows a previously hidden column.\n * @param field - The field name of the column to show.\n */\n showColumn(field: NestedKeyOf<T>) {\n this.setColumnVisibility(field, true);\n }\n\n /**\n * Hides a visible column.\n * @param field - The field name of the column to hide.\n */\n hideColumn(field: NestedKeyOf<T>) {\n this.setColumnVisibility(field, false);\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 all - If `true`, exports all original data (ignoring filters). If `false` (default), exports only the currently visible (filtered and sorted) rows.\n */\n export(filename: string, all = false) {\n const data = all ? this.#rows : this.#filteredRows;\n const rows = [...data.values()];\n\n const csvHeaders = [...this.#columnData.values()]\n .filter(col => all || col.state.visible)\n .map(col => `\"${col.options.title}\"`)\n .join(',');\n\n const csvRows = rows\n .map(row => {\n const list: string[] = [];\n for (const key of this.#columnData.keys()) {\n const col = this.#columnData.get(key);\n if (!col) {\n continue;\n }\n\n let value = (row as any)[key];\n if (all || !col.headerElement.hidden) {\n if (typeof col.options.valueFormatter === 'function') {\n value = col.options.valueFormatter(value, row);\n }\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 const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8,' });\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 scrollToRow(row: T) {\n const rowData = row as InternalRowData<T>;\n const index = rowData._metadata?.index;\n if (typeof index === 'number') {\n 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 scrollToOriginalIndex(index: number) {\n const rowData = this.#rows.get(index);\n if (rowData) {\n const filteredIndex = this.#filteredRows.indexOf(rowData);\n if (filteredIndex >= 0) {\n this.scrollToFilteredIndex(filteredIndex);\n return;\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 scrollToFilteredIndex(index: number) {\n const rowData = this.#filteredRows[index];\n if (!rowData) {\n throw new RangeError(`Row index ${index} out of range`);\n }\n\n if (this.#virtualScroll) {\n this.#virtualScroll.scrollToIndex(index);\n } else {\n const row = this.#tbody.querySelector(\n `tr[data-dt-index=\"${rowData._metadata.index}\"]`,\n );\n if (row) {\n row.scrollIntoView(true);\n const theadHeight = parseFloat(getComputedStyle(this.#thead).height);\n this.#scroller.scrollTop -= theadHeight;\n }\n }\n }\n\n scrollToPx(px: number) {\n if (this.#virtualScroll) {\n this.#virtualScroll.scrollToPx(px);\n } else {\n const theadHeight = parseFloat(getComputedStyle(this.#thead).height);\n this.#scroller.scrollTop = px - theadHeight;\n }\n }\n\n /**\n * Sets the display order of the columns in the table.\n *\n * @param fields - An array of field names representing the new order of columns. Columns not included in the array will be placed at the end.\n * @throws {TypeError} If `fields` is not an array.\n */\n setColumnOrder(fields: NestedKeyOf<T>[]) {\n if (!Array.isArray(fields)) {\n throw new TypeError('fields must be an array of field names');\n }\n\n const newColumns = new Map<NestedKeyOf<T>, ColumnData<T>>();\n for (const field of fields) {\n const col = this.#columnData.get(field);\n if (col) {\n newColumns.set(field, col);\n }\n }\n\n for (const [field, col] of this.#columnData) {\n if (!newColumns.has(field)) {\n newColumns.set(field, col);\n }\n }\n\n this.#columnData = newColumns;\n this.refresh();\n }\n\n /**\n * Refreshes the table display. This re-applies filters, sorting, and updates headers and rows.\n */\n refresh() {\n this.#updateHeaders();\n this.#filterRows();\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 indexOf(field: string, value: any) {\n const rows = [...this.#rows.values()];\n const found_row = rows.find(row => {\n if (field in row) {\n return (row as any)[field] === value;\n }\n });\n\n if (found_row) {\n return found_row._metadata.index;\n }\n return -1;\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 updateRow(index: number, data: Partial<T>) {\n const current_row = this.#rows.get(index);\n if (current_row) {\n Object.assign(current_row, data);\n this.#loadRow(current_row, index);\n this.#filterRows();\n }\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 deleteRow(index: number) {\n this.#rows.delete(index);\n this.#filterRows();\n }\n\n /**\n * Executes a callback function without triggering table updates (like re-rendering or event dispatches)\n * until the callback has completed. This is useful for batching multiple operations.\n * @param callback - A function to execute. It receives the DataTable instance as its argument.\n * @example dataTable.withoutUpdates(dt => { dt.sort('name', 'asc'); dt.filter({ age: '>30' }); });\n */\n withoutUpdates(callback: (dataTable: DataTable<T>) => void) {\n const prevBlock = this.#blockUpdates;\n this.#blockUpdates = true;\n try {\n callback(this);\n } finally {\n this.#blockUpdates = prevBlock;\n if (!this.#blockUpdates) {\n this.#applyBlockedUpdates();\n }\n }\n }\n\n #initTableElements() {\n this.#table.classList.add('data-table');\n // Inner element that handles the virtual scroll.\n const scroller = document.createElement('div');\n\n // If the user tries to provide a height, we will use that for the scroller.\n if (this.#table.style.height !== '') {\n scroller.style.height = this.#table.style.height;\n this.#table.style.height = '';\n }\n\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n const tbody = document.createElement('tbody');\n\n tbody.addEventListener('click', this.#onTableClicked);\n\n // We currently don't support HTML based columns.\n // Clear the table and start fresh.\n // TODO: Add ability to use HTML headers provided by the user.\n this.#table.innerHTML = '';\n\n thead.append(headerRow);\n this.#table.append(thead);\n this.#table.append(tbody);\n\n // Add the scroller before the table so when we move the\n // table into the scroller it stays in the same place.\n this.#table.parentElement?.insertBefore(scroller, this.#table);\n scroller.append(this.#table);\n\n return {\n scroller,\n thead,\n headerRow,\n tbody,\n };\n }\n\n #initColumns(columns: ColumnOptions<T>[], headerRow: HTMLElement) {\n this.#columnData.clear();\n // We need to make sure at least one column is visible\n let colVisible = false;\n\n for (const colOptions of columns) {\n const header = document.createElement('th');\n const headerContent = document.createElement('div');\n const titleWrapper = document.createElement('div');\n const titleElement = document.createElement('span');\n\n const colData: ColumnData<T> = {\n field: colOptions.field,\n options: {\n title: colOptions.title ?? toHumanReadable(colOptions.field),\n sortable: colOptions.sortable ?? true,\n searchable: colOptions.searchable ?? false,\n tokenize: colOptions.tokenize ?? false,\n resizable: colOptions.resizable ?? true,\n valueFormatter: colOptions.valueFormatter ?? null,\n elementFormatter: colOptions.elementFormatter ?? null,\n sorter: colOptions.sorter ?? null,\n sortValue: colOptions.sortValue ?? null,\n filter: colOptions.filter ?? null,\n },\n state: {\n visible: true,\n sortState: null,\n width: null,\n },\n headerElement: header,\n titleElement: titleElement,\n resizeStartWidth: null,\n resizeStartX: null,\n };\n\n this.#columnData.set(colOptions.field, colData);\n\n header.dataset.dtField = colOptions.field;\n header.hidden = !colData.state.visible;\n header.title = colData.options.title;\n\n headerContent.classList.add('dt-header-content');\n header.append(headerContent);\n\n titleWrapper.classList.add('dt-header-title-wrapper');\n headerContent.append(titleWrapper);\n\n titleElement.classList.add('dt-header-title');\n titleElement.innerHTML = colData.options.title;\n titleWrapper.append(titleElement);\n\n const sorter = document.createElement('div');\n sorter.classList.add('dt-sort-icon');\n titleWrapper.append(sorter);\n\n const resizer = document.createElement('div');\n resizer.classList.add('dt-resizer');\n headerContent.append(resizer);\n\n headerRow.append(header);\n\n if (colData.state.visible) {\n colVisible = true;\n }\n\n this.updateColumnOptions(colOptions.field, colData.options);\n\n if (this.#options.rearrangeable) {\n header.draggable = true;\n }\n\n // Sort event listener\n titleWrapper.addEventListener('click', () => {\n if (!header.classList.contains('dt-sortable')) return;\n\n if (!colData.state.sortState) {\n this.sort(colData.field, 'asc');\n } else if (colData.state.sortState.order === 'asc') {\n this.sort(colData.field, 'desc');\n } else if (colData.state.sortState.order) {\n this.sort(colData.field, null);\n }\n });\n\n // Drag and drop event listeners\n header.addEventListener('dragstart', this.#onDragColumnStart);\n header.addEventListener('dragenter', this.#onDragColumnEnter);\n header.addEventListener('dragover', this.#onDragColumnOver);\n header.addEventListener('dragleave', this.#onDragColumnLeave);\n header.addEventListener('drop', this.#onDragColumnDrop);\n header.addEventListener('dragend', this.#onDragColumnEnd);\n // Resize event listeners\n header.addEventListener('mousedown', this.#onResizeColumnStart);\n header.addEventListener('dblclick', this.#onResizeColumnDoubleClick);\n }\n\n if (this.#columnData.size === 0) {\n console.warn('No columns found. At least one column is required.');\n } else if (!colVisible) {\n console.warn(\n 'At least a single column must be visible. Showing the first column.',\n );\n const col = columns[0].field;\n this.showColumn(col);\n }\n }\n\n #loadRow(row: InternalRowData<T>, index: number) {\n // Add the index\n const metadata: RowMetadata = {\n index: index++,\n tokens: {},\n compareValues: {},\n sortValues: {},\n };\n row._metadata = metadata;\n\n for (const [field, col] of this.#columnData) {\n const value = getNestedValue(row, field);\n\n // Cache precomputed values for sorting\n if (typeof col.options.sortValue === 'function') {\n metadata.sortValues[field] = col.options.sortValue(value);\n } else if (typeof value === 'string') {\n metadata.sortValues[field] = value.toLocaleLowerCase();\n } else {\n metadata.sortValues[field] = value;\n }\n\n // Cache precomputed lower-case values for search\n if (typeof value === 'string') {\n metadata.compareValues[field] = value.toLocaleLowerCase();\n }\n\n // Tokenize any searchable columns\n if (col.options.searchable && col.options.tokenize && value) {\n metadata.tokens[field] = this.#options\n .tokenizer(value)\n .map(token => token.value);\n }\n }\n\n // Add any extra search fields\n for (const field of this.#options.extraSearchFields) {\n const value = getNestedValue(row, field);\n // Cache precomputed lower-case values for search\n if (typeof value === 'string') {\n metadata.compareValues[field] = value.toLocaleLowerCase();\n }\n }\n\n return row;\n }\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 #calculateSearchScore(query: string, target: string): number {\n if (!query || !target) {\n return 0;\n }\n\n let baseScore = 0;\n let matchTypeWeight = 0;\n\n if (target === query) {\n matchTypeWeight = DataTable.MatchWeights.EXACT;\n baseScore = query.length;\n } else if (target.startsWith(query)) {\n matchTypeWeight = DataTable.MatchWeights.PREFIX;\n baseScore = query.length;\n } else if (target.includes(query)) {\n matchTypeWeight = DataTable.MatchWeights.SUBSTRING;\n baseScore = query.length;\n } else {\n return 0;\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 return baseScore * matchTypeWeight * specificityBonus;\n }\n\n #searchField(\n query: QueryToken | RegExp,\n value: string,\n tokens?: string[],\n ): number {\n // RegExp bypasses tokenization and scoring\n if (query instanceof RegExp) {\n return query.test(value) ? 1 : 0;\n }\n\n // Simple search, no scoring\n if (!this.#options.enableSearchScoring) {\n // Quoted tokens bypass tokenization and no tokens means column wasn't tokenized.\n if (query.quoted || !tokens) {\n return value.includes(query.value) ? 1 : 0;\n }\n\n return tokens.some(token => token == query.value) ? 1 : 0;\n }\n\n // Complex scored search\n // Quoted tokens bypass tokenization and no tokens means column wasn't tokenized.\n if (query.quoted || !tokens) {\n return this.#calculateSearchScore(query.value, value);\n }\n\n return tokens\n .map(token => this.#calculateSearchScore(query.value, token))\n .reduce((accumulator, score) => (accumulator += score), 0);\n }\n\n #filterField(\n value: any,\n filter: any,\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 => this.#filterField(value, element));\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 #filterRow(row: InternalRowData<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 = (this.#filters as any)[field];\n const value = getNestedValue(row, field);\n if (typeof filter === 'function') {\n if (!filter(value)) {\n return false;\n }\n } else {\n const col = this.#columnData.get(field as NestedKeyOf<T>);\n const filterCallback = col ? col.options.filter : undefined;\n if (!this.#filterField(value, filter, filterCallback)) {\n return false;\n }\n }\n }\n return true;\n }\n\n #filterRows() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('reApplyFilters');\n return;\n } else {\n this.#blockedUpdates.delete('reApplyFilters');\n }\n\n const searchableFields = [...this.#columnData.values()]\n .filter(col => col.options.searchable)\n .map(c => c.field);\n\n const fields = [...searchableFields, ...this.#options.extraSearchFields];\n\n const rows = [...this.#rows.values()];\n this.#filteredRows = rows.filter((row, index) => {\n row._metadata.searchScore = 0;\n // Filter takes precedence over search.\n if (!this.#filterRow(row, index)) {\n return false;\n }\n\n if (!this.#query) {\n return true;\n }\n\n for (const field of fields) {\n const originalValue = getNestedValue(row, field);\n const compareValue = row._metadata.compareValues[field];\n const columnTokens = row._metadata.tokens[field];\n\n if (\n typeof originalValue !== 'string' ||\n typeof compareValue !== 'string'\n ) {\n continue;\n }\n\n let score: number = 0;\n if (this.#query instanceof RegExp) {\n score = this.#searchField(this.#query, originalValue, columnTokens);\n } else {\n for (const token of this.#query) {\n score += this.#searchField(token, compareValue, columnTokens);\n }\n }\n\n //const score = this.#searchField([...tokens], this.#query);\n row._metadata.searchScore += score;\n }\n\n return row._metadata.searchScore > 0;\n });\n\n this.#sortRows();\n\n const changeEvent = new CustomEvent<\n DataTableEventMap<T>['dt.rows.changed']\n >('dt.rows.changed', {\n cancelable: false,\n detail: {\n dataTable: this,\n },\n });\n\n this.dispatchEvent(changeEvent);\n }\n\n #compareRows(\n a: InternalRowData<T>,\n b: InternalRowData<T>,\n col: ColumnData<T>,\n ): number {\n let aValue, bValue;\n\n if (!col.state.sortState) {\n return 0;\n }\n\n if (col.state.sortState?.order === 'asc') {\n aValue = a._metadata.sortValues[col.field];\n bValue = b._metadata.sortValues[col.field];\n } else if (col.state.sortState?.order === 'desc') {\n aValue = b._metadata.sortValues[col.field];\n bValue = a._metadata.sortValues[col.field];\n }\n\n if (typeof col.options.sorter === 'function') {\n const ret = col.options.sorter(aValue, bValue);\n if (ret !== 0) return ret;\n }\n\n const aIsNull = aValue == null;\n const bIsNull = bValue == null;\n\n if (aIsNull && !bIsNull) return -1;\n if (bIsNull && !aIsNull) return 1;\n\n if (aValue < bValue) return -1;\n if (aValue > bValue) return 1;\n return 0;\n }\n\n #sortRows() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('reSortRows');\n return;\n } else {\n this.#blockedUpdates.delete('reSortRows');\n }\n\n const sortedColumns = [...this.#columnData.values()]\n // Filter to visible columns with active sort states\n .filter(col => !col.headerElement.hidden && col.state.sortState)\n // Sort our columns by their sort priority.\n // This is how sorting by multiple columns is handled.\n .sort(\n (a, b) => b.state.sortState!.priority - a.state.sortState!.priority,\n );\n\n this.#filteredRows.sort((a, b) => {\n // Try to sort by search score if we're using scoring and there is a query.\n if (this.#options.enableSearchScoring && this.#query) {\n const aValue = a._metadata.searchScore || 0;\n const bValue = b._metadata.searchScore || 0;\n if (aValue > bValue) return -1;\n if (aValue < bValue) return 1;\n }\n\n for (const col of sortedColumns) {\n const comp = this.#compareRows(a, b, col);\n if (comp !== 0) {\n return comp;\n }\n }\n\n // Always fall back to the index column\n return a._metadata.index - b._metadata.index;\n });\n this.#renderTable();\n }\n\n #updateHeaders() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('updateHeaders');\n return;\n } else {\n this.#blockedUpdates.delete('updateHeaders');\n }\n\n for (const col of this.#columnData.values()) {\n // Update the order of headers\n col.headerElement.parentElement?.append(col.headerElement);\n col.headerElement.hidden = !col.state.visible;\n col.headerElement.draggable = this.#options.rearrangeable;\n col.titleElement.textContent = col.options.title;\n\n if (col.options.resizable) {\n col.headerElement.classList.add('dt-resizeable');\n } else {\n col.headerElement.classList.remove('dt-resizeable');\n }\n\n if (col.options.sortable) {\n col.headerElement.classList.add('dt-sortable');\n } else {\n col.headerElement.classList.remove('dt-sortable');\n }\n\n if (!col.state.sortState) {\n col.headerElement?.classList.remove('dt-ascending');\n col.headerElement?.classList.remove('dt-descending');\n } else if (col.state.sortState.order === 'asc') {\n col.headerElement?.classList.add('dt-ascending');\n col.headerElement?.classList.remove('dt-descending');\n } else if (col.state.sortState.order === 'desc') {\n col.headerElement?.classList.add('dt-descending');\n col.headerElement?.classList.remove('dt-ascending');\n }\n }\n }\n\n #renderTable() {\n if (this.#blockUpdates) {\n this.#blockedUpdates.add('reRenderTable');\n return;\n } else {\n this.#blockedUpdates.delete('reRenderTable');\n }\n\n const useVirtualScroll = this.rows.length >= this.#options.virtualScroll;\n\n if (useVirtualScroll && !this.#virtualScroll) {\n this.#virtualScroll = new this.#options.virtualScrollClass({\n container: this.#scroller,\n element: this.#tbody,\n generator: index => this.#createRow(index),\n });\n } else if (!useVirtualScroll && this.#virtualScroll) {\n this.#virtualScroll.stop();\n this.#virtualScroll = null;\n }\n\n this.#tbody.innerHTML = '';\n if (this.#virtualScroll) {\n try {\n this.#virtualScroll.start(this.#filteredRows.length);\n } catch (error) {\n if (error instanceof VirtualScrollError) {\n console.warn(\n 'Failed to start virtual scroll... falling back to standard rendering',\n );\n console.warn(error.stack);\n }\n }\n } else {\n if (this.#filteredRows.length > WARN_ROW_COUNT) {\n const count = WARN_ROW_COUNT.toLocaleString();\n console.warn(\n `Virtual scroll disabled with more than ${count} rows... Good luck with that!`,\n );\n }\n\n const rowElements = this.#filteredRows.map((_, index) =>\n this.#createRow(index),\n );\n this.#tbody.append(...rowElements);\n }\n\n if (this.#rows.size === 0) {\n this.showMessage(this.#options.noDataText, 'dt-empty');\n } else if (this.#filteredRows.length === 0) {\n this.showMessage(this.#options.noMatchText, 'dt-empty');\n }\n }\n\n #markText(element: HTMLElement, query: RegExp) {\n if (element.children.length === 0) {\n let text = element.textContent ?? '';\n const classes = this.#options.classes.mark.join(' ');\n text = text.replace(\n query,\n match => `<mark class=\"${classes}\">${match}</mark>`,\n );\n element.innerHTML = text;\n } else {\n for (const child of element.children) {\n if (child instanceof HTMLElement) {\n this.#markText(child, query);\n }\n }\n }\n }\n\n #updateCell(\n td: HTMLTableCellElement,\n value: any,\n col: ColumnData<T>,\n row: T,\n ) {\n if (typeof col.options.valueFormatter === 'function') {\n value = col.options.valueFormatter(value, row);\n }\n\n if (value != null) {\n td.textContent = value;\n // Full text on hover\n td.title = String(value);\n } else {\n td.textContent = this.#options.emptyValuePlaceholder;\n }\n\n if (typeof col.options.elementFormatter === 'function') {\n col.options.elementFormatter(value, row, td);\n }\n\n if (\n this.#options.highlightSearch &&\n this.#query &&\n col.options.searchable\n ) {\n let regex: RegExp;\n if (this.#query instanceof RegExp) {\n regex = this.#query;\n } else {\n const tokens = this.#query.map(token => token.value).join('|');\n regex = new RegExp(tokens, 'gi');\n }\n\n this.#markText(td, regex);\n }\n\n td.hidden = col.state.visible ? false : true;\n }\n\n #createRow(index: number): HTMLTableRowElement {\n const row = this.#filteredRows[index];\n const tr = document.createElement('tr');\n tr.classList.add(...this.#options.classes.tr);\n tr.dataset.dtIndex = String(row._metadata.index);\n\n for (const [field, col] of this.#columnData) {\n const value = getNestedValue(row, field);\n const td = document.createElement('td');\n td.classList.add(...this.#options.classes.td);\n td.dataset.dtField = field;\n this.#updateCell(td, value, col, row);\n tr.append(td);\n }\n\n if (typeof this.#options.rowFormatter === 'function') {\n try {\n this.#options.rowFormatter(row, tr);\n } catch (error) {\n console.error('Row formatter callback failed with the following error');\n console.error(error);\n }\n }\n\n return tr;\n }\n\n /**\n * Force the table to a fixed layout by setting the width of all columns\n * to their current width in pixels and then setting the table to fit-content.\n */\n #ensureFixedLayout() {\n if (!this.#tableWidthIsFixed) {\n this.#tableWidthIsFixed = true;\n\n for (const column of this.#columnData.values()) {\n const currentWidth = column.headerElement.offsetWidth;\n column.state.width = currentWidth;\n column.headerElement.style.width = `${currentWidth}px`;\n }\n\n this.#table.style.width = 'fit-content';\n }\n }\n\n #resizeColumn(column: ColumnData<T>, width: number | null) {\n this.#ensureFixedLayout();\n\n if (width !== null && width < 0) {\n width = 0;\n }\n\n column.state.width = width;\n\n let headerWidth;\n if (width == null) {\n headerWidth = '';\n } else if (width <= 0) {\n headerWidth = '0px';\n } else {\n headerWidth = `${width}px`;\n }\n column.headerElement.style.width = headerWidth;\n //column.headerElement.style.maxWidth = headerWidth;\n }\n\n #applyBlockedUpdates() {\n while (this.#blockedUpdates.size) {\n if (this.#blockedUpdates.has('reloadData')) {\n this.loadData(this.data);\n this.#blockedUpdates.delete('reloadData');\n } else if (this.#blockedUpdates.has('reApplyFilters')) {\n this.#filterRows();\n this.#blockedUpdates.delete('reApplyFilters');\n } else if (this.#blockedUpdates.has('reSortRows')) {\n this.#sortRows();\n this.#blockedUpdates.delete('reSortRows');\n } else if (this.#blockedUpdates.has('reRenderTable')) {\n this.#renderTable();\n this.#blockedUpdates.delete('reRenderTable');\n }\n\n if (this.#blockedUpdates.has('updateHeaders')) {\n this.#updateHeaders();\n }\n }\n }\n\n /* Event handlers */\n\n #onTableClicked = (event: MouseEvent) => {\n // Ignore events if the user is highlighting text\n if (window.getSelection()?.toString()) return;\n\n let tr, td, field;\n if (event.target instanceof HTMLTableCellElement) {\n td = event.target;\n tr = td.parentElement;\n field = td.dataset.dtField;\n } else if (event.target instanceof HTMLTableRowElement) {\n tr = event.target;\n }\n\n if (tr) {\n const index = parseInt(tr.dataset.dtIndex || '');\n if (!isNaN(index)) {\n const row = this.#filteredRows.find(\n value => value._metadata.index === index,\n );\n if (row) {\n const rowEvent = new CustomEvent<\n DataTableEventMap<T>['dt.row.clicked']\n >('dt.row.clicked', {\n cancelable: false,\n detail: {\n row: row,\n index: index,\n column: field,\n originalEvent: event,\n },\n });\n this.dispatchEvent(rowEvent);\n }\n }\n }\n };\n\n #onResizeColumnStart = (event: MouseEvent) => {\n // If target is not the resizer, we don't care.\n if (!(event.target instanceof HTMLElement)) return;\n if (!event.target.classList.contains('dt-resizer')) return;\n // If the current target isn't the header, we don't care.\n if (!(event.currentTarget instanceof HTMLElement)) return;\n if (!event.currentTarget.dataset.dtField) return;\n\n event.stopImmediatePropagation();\n event.preventDefault();\n\n const field = event.currentTarget.dataset.dtField;\n const col = this.#columnData.get(field as NestedKeyOf<T>);\n if (!col) return;\n this.#resizingColumn = col;\n\n col.resizeStartX = event.clientX;\n col.resizeStartWidth = col.headerElement.offsetWidth;\n\n document.addEventListener('mousemove', this.#onResizeColumnMove);\n document.addEventListener('mouseup', this.#onResizeColumnEnd);\n };\n\n #onResizeColumnMove = (event: MouseEvent) => {\n if (!this.#resizingColumn) return;\n event.stopImmediatePropagation();\n event.preventDefault();\n\n const dx = event.clientX - this.#resizingColumn.resizeStartX!;\n const newWidth = this.#resizingColumn.resizeStartWidth! + dx;\n this.#resizeColumn(this.#resizingColumn, newWidth);\n };\n\n #onResizeColumnEnd = (event: MouseEvent) => {\n if (!this.#resizingColumn) return;\n event.stopImmediatePropagation();\n event.preventDefault();\n\n document.removeEventListener('mousemove', this.#onResizeColumnMove);\n document.removeEventListener('mouseup', this.#onResizeColumnEnd);\n\n const resizeEvent = new CustomEvent<DataTableEventMap<T>['dt.col.resize']>(\n 'dt.col.resize',\n {\n cancelable: false,\n detail: {\n column: this.#resizingColumn.field,\n width: this.#resizingColumn.headerElement.offsetWidth,\n },\n },\n );\n\n this.dispatchEvent(resizeEvent);\n\n this.#resizingColumn = null;\n };\n\n #onResizeColumnDoubleClick = (event: MouseEvent) => {\n // If target is not the resizer, we don't care.\n if (!(event.target instanceof HTMLElement)) return;\n if (!event.target.classList.contains('dt-resizer')) return;\n // If the current target isn't the header, we don't care.\n if (!(event.currentTarget instanceof HTMLElement)) return;\n if (!event.currentTarget.dataset.dtField) return;\n\n const field = event.currentTarget.dataset.dtField;\n const columnData = this.#columnData.get(field as NestedKeyOf<T>);\n if (!columnData) return;\n\n // Calculate the width of the widest cell by rendering\n // offscreen and then resize the column to that value.\n\n let maxWidth = columnData.titleElement.scrollWidth;\n if (this.#filteredRows.length > 0) {\n if (!this.#textMeasurementContext) {\n this.#textMeasurementContext = document\n .createElement('canvas')\n .getContext('2d');\n }\n const context = this.#textMeasurementContext;\n\n // Get the font styles and padding from a sample cell\n const sampleCell = this.#tbody.querySelector('td');\n let cellPadding = 0;\n if (sampleCell && context) {\n const style = window.getComputedStyle(sampleCell);\n context.font = `${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;\n cellPadding =\n parseFloat(style.paddingLeft) + parseFloat(style.paddingRight);\n }\n\n for (const row of this.#filteredRows) {\n let value = getNestedValue(row, field);\n if (typeof columnData.options.valueFormatter === 'function') {\n value = columnData.options.valueFormatter(value, row);\n }\n const text = value == null ? '' : String(value);\n const textWidth = context?.measureText(text).width ?? 0;\n maxWidth = Math.max(maxWidth, textWidth + cellPadding);\n }\n }\n\n this.#resizeColumn(columnData, maxWidth);\n };\n\n #onDragColumnStart = (event: DragEvent) => {\n const target = event.target as HTMLElement;\n const field = target.dataset.dtField;\n\n if (event.dataTransfer && field) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', field);\n }\n };\n\n #onDragColumnOver = (event: DragEvent) => {\n event.preventDefault();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'move';\n }\n return false;\n };\n\n #onDragColumnEnter = (event: DragEvent) => {\n const target = event.target as HTMLElement;\n target.classList.add('dt-drag-over');\n };\n\n #onDragColumnLeave = (event: DragEvent) => {\n const target = event.target as HTMLElement;\n target.classList.remove('dt-drag-over');\n };\n\n #onDragColumnDrop = (event: DragEvent) => {\n const dragField = event.dataTransfer?.getData('text/plain');\n const target = event.currentTarget as HTMLElement;\n const dropField = target.dataset.dtField;\n\n if (!dragField || !dropField) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n const columns = [...this.#columnData.values()];\n const dragIndex = columns.findIndex(col => col.field === dragField);\n const dropIndex = columns.findIndex(col => col.field === dropField);\n\n if (dragIndex > -1 && dropIndex > -1) {\n const [draggedColumn] = columns.splice(dragIndex, 1);\n const droppedColumn = this.#columnData.get(dropField as NestedKeyOf<T>);\n if (!droppedColumn) return;\n\n columns.splice(dropIndex, 0, draggedColumn);\n const newColumnOrder = columns.map(col => col.field);\n const reorderEvent = new CustomEvent<\n DataTableEventMap<T>['dt.col.reorder']\n >('dt.col.reorder', {\n cancelable: true,\n detail: {\n draggedColumn: draggedColumn.field,\n dropColumn: droppedColumn.field,\n order: newColumnOrder,\n },\n });\n if (!this.dispatchEvent(reorderEvent)) {\n return;\n }\n\n this.setColumnOrder(newColumnOrder);\n }\n };\n\n #onDragColumnEnd = () => {\n const elements = document.querySelectorAll('.dt-drag-over');\n for (const element of elements) {\n element.classList.remove('dt-drag-over');\n }\n };\n\n addEventListener<K extends keyof DataTableEventMap<T>>(\n type: K,\n listener: (\n this: DataTable<T>,\n ev: CustomEvent<DataTableEventMap<T>[K]>,\n ) => any,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n // This is the generic fallback for any other string event type (e.g., standard DOM events).\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n\n // The single implementation for both overloads.\n addEventListener(type: any, listener: any, options?: any) {\n super.addEventListener(type, listener, options);\n }\n\n private readonly TABLE_OPTION_CONFIGS: TableOptionConfigs<T> = {\n virtualScroll: {\n effect: 'reRenderTable',\n handler: value => {\n return virtualScrollToNumber(value);\n },\n },\n highlightSearch: {\n effect: 'reRenderTable',\n },\n tokenizeSearch: {\n effect: 'reloadData',\n handler: value => {\n this.search(this.#userQuery);\n return value;\n },\n },\n enableSearchScoring: {\n effect: 'reApplyFilters',\n },\n rearrangeable: {\n effect: 'updateHeaders',\n },\n extraSearchFields: {\n effect: 'reloadData',\n },\n emptyValuePlaceholder: {\n effect: 'reRenderTable',\n },\n noDataText: {\n effect: 'reRenderTable',\n },\n noMatchText: {\n effect: 'reRenderTable',\n },\n classes: {\n effect: 'reRenderTable',\n handler: value => {\n const classes = convertClasses(this.#options.classes, value);\n this.#scroller.className = classes.scroller.join(' ');\n this.#thead.className = classes.thead.join(' ');\n this.#tbody.className = classes.tbody.join(' ');\n\n for (const col of this.#columnData.values()) {\n col.headerElement.className = classes.th.join(' ');\n }\n return classes;\n },\n },\n rowFormatter: {\n effect: 'reRenderTable',\n },\n tokenizer: {\n effect: 'reloadData',\n },\n virtualScrollClass: {\n effect: 'reRenderTable',\n handler: value => {\n this.#virtualScroll?.stop();\n this.#virtualScroll = null;\n return value;\n },\n },\n };\n\n private readonly COLUMN_OPTION_CONFIGS: ColumnOptionConfigs<T> = {\n title: {\n effect: 'updateHeaders',\n },\n searchable: {\n effect: 'reApplyFilters',\n },\n sortable: {\n effect: 'updateHeaders',\n },\n resizable: {\n effect: 'updateHeaders',\n },\n tokenize: {\n effect: 'reloadData',\n },\n valueFormatter: {\n effect: 'reRenderTable',\n },\n elementFormatter: {\n effect: 'reRenderTable',\n },\n sorter: {\n effect: 'reSortRows',\n },\n sortValue: {\n effect: 'reloadData',\n },\n filter: {\n effect: 'reApplyFilters',\n },\n };\n}\n\n// User can provide either string or list of strings. Internally we enforce a list of strings.\ntype ConcreteTableClasses = Required<{ [K in keyof TableClasses]: string[] }>;\n// Table options without data and with classes and virtual scroll as a single type for internal use\ntype ConcreteTableOptions<T> = Required<\n Omit<TableOptions<T>, 'data' | 'classes' | 'virtualScroll'>\n> & { classes: ConcreteTableClasses; virtualScroll: number };\n\ntype UpdatableTableOptions<T> = TableOptions<T>;\n\n// Type for describing what effect a change has on the table\ntype TableEffect =\n | 'reloadData'\n | 'reApplyFilters'\n | 'reRenderTable'\n | 'reSortRows'\n | 'updateHeaders'\n | null;\n\n// Type for controlling how each table option effects the table\ntype TableOptionConfigs<T> = {\n [K in keyof Required<UpdatableTableOptions<T>>]: {\n // The effect changing the option has on the table.\n effect: TableEffect;\n // A handler to modify the value of the option before it is applied or provide any specialized logic\n handler?: (\n value: Required<UpdatableTableOptions<T>>[K],\n ) => ConcreteTableOptions<T>[K];\n };\n};\n\ntype ColumnOptionConfigs<T> = {\n [K in keyof Required<ColumnOptionsWithoutField<T>>]: {\n effect: TableEffect;\n handler?: (\n value: Required<ColumnOptionsWithoutField<T>>[K],\n ) => Required<ColumnOptionsWithoutField<T>>[K];\n };\n};\n\ntype ColumnOptionsWithoutField<T> = Omit<ColumnOptions<T>, 'field'>;\ntype ColumnStateWithoutField<T> = Omit<ColumnState<T>, 'field'>;\n\ntype ColumnDataOptions<T> = Required<ColumnOptionsWithoutField<T>>;\ntype ColumnDataState<T> = Required<ColumnStateWithoutField<T>>;\n\ninterface ColumnData<T> {\n field: NestedKeyOf<T>;\n options: ColumnDataOptions<T>;\n state: ColumnDataState<T>;\n\n headerElement: HTMLElement;\n titleElement: HTMLElement;\n\n resizeStartX: number | null;\n resizeStartWidth: number | null;\n}\n\ninterface RowMetadata {\n index: number;\n searchScore?: number;\n tokens: Record<string, string[]>;\n compareValues: Record<string, string>;\n sortValues: Record<string, any>;\n}\n\ntype InternalRowData<T> = T & { _metadata: RowMetadata };\n\nconst WARN_ROW_COUNT = 10_000;\n\n/**\n * Defines the mapping between event names and their detail object types.\n */\nexport interface DataTableEventMap<T> {\n 'dt.row.clicked': {\n row: T;\n index: number;\n column: string | undefined;\n originalEvent: MouseEvent;\n };\n\n 'dt.rows.changed': object;\n\n 'dt.col.sort': {\n column: string;\n order: SortOrder | null;\n };\n\n 'dt.col.visibility': {\n column: string;\n visible: boolean;\n };\n\n 'dt.col.resize': {\n column: string;\n width: number;\n };\n\n 'dt.col.reorder': {\n draggedColumn: string;\n dropColumn: string;\n order: string[];\n };\n\n 'dt.search': {\n query: string | RegExp | null;\n };\n}\n\nexport type * from './types';\nexport { createRegexTokenizer };\n","import {\n RestorableColumnState,\n RestorableTableState,\n} from '../../data-table/types';\nimport { IDataTable, LocalStorageAdapterOptions } from './types';\n/**\n * Monitors a {@link DataTable} instance for changes and saves the state to local storage.\n */\nexport class LocalStorageAdapter<T> {\n #dataTable: IDataTable<T>;\n #storageKey: string;\n #options: Required<LocalStorageAdapterOptions> = {\n saveSearch: true,\n saveColumnSorting: true,\n saveColumnVisibility: true,\n saveColumnWidth: true,\n saveColumnOrder: true,\n };\n\n /**\n * @param dataTable - The DataTable instance to monitor.\n * @param storageKey - The key to use for saving the state in localStorage.\n * @param options - The options for configuring what is stored.\n */\n constructor(\n dataTable: IDataTable<T>,\n storageKey: string,\n options?: LocalStorageAdapterOptions,\n ) {\n this.#dataTable = dataTable;\n this.#storageKey = storageKey;\n this.#options = { ...this.#options, ...options };\n\n // Restore state before adding the listeners.\n this.restoreState();\n\n if (this.#options.saveSearch) {\n dataTable.addEventListener('dt.search', this.#saveStateAfterEvent);\n }\n\n if (this.#options.saveColumnSorting) {\n dataTable.addEventListener('dt.col.sort', this.#saveStateAfterEvent);\n }\n\n if (this.#options.saveColumnVisibility) {\n dataTable.addEventListener(\n 'dt.col.visibility',\n this.#saveStateAfterEvent,\n );\n }\n\n if (this.#options.saveColumnWidth) {\n dataTable.addEventListener('dt.col.resize', this.#saveStateAfterEvent);\n }\n\n if (this.#options.saveColumnOrder) {\n dataTable.addEventListener('dt.col.reorder', this.#saveStateAfterEvent);\n }\n }\n\n /**\n * Saves the current column state to localStorage.\n */\n saveState() {\n const savedTableState: RestorableTableState<T> = {\n columns: [],\n };\n const tableState = this.#dataTable.getState();\n\n if (this.#options.saveSearch) {\n savedTableState.searchQuery = tableState.searchQuery;\n }\n\n if (this.#options.saveColumnOrder) {\n savedTableState.columnOrder = tableState.columnOrder;\n }\n\n for (const columnState of tableState.columns) {\n const savedColumnState: RestorableColumnState<T> = {\n field: columnState.field,\n };\n\n if (this.#options.saveColumnSorting) {\n savedColumnState.sortState = columnState.sortState;\n }\n\n if (this.#options.saveColumnVisibility) {\n savedColumnState.visible = columnState.visible;\n }\n\n if (this.#options.saveColumnWidth) {\n savedColumnState.width = columnState.width;\n }\n\n savedTableState.columns?.push(savedColumnState);\n }\n\n localStorage.setItem(this.#storageKey, JSON.stringify(savedTableState));\n }\n\n /**\n * Restores the column state from localStorage.\n */\n restoreState() {\n const json = localStorage.getItem(this.#storageKey);\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 (this.#options.saveSearch) {\n tableStateToRestore.searchQuery = savedTableState.searchQuery;\n }\n\n if (this.#options.saveColumnOrder) {\n tableStateToRestore.columnOrder = savedTableState.columnOrder;\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 (this.#options.saveColumnVisibility) {\n columnStateToRestore.visible = savedColumnState.visible;\n }\n\n if (this.#options.saveColumnWidth) {\n columnStateToRestore.width = savedColumnState.width;\n }\n\n if (this.#options.saveColumnSorting) {\n columnStateToRestore.sortState = savedColumnState.sortState;\n }\n tableStateToRestore.columns.push(columnStateToRestore);\n }\n }\n\n this.#dataTable.restoreState(tableStateToRestore);\n } catch (error) {\n console.error('Failed to restore DataTable state:', error);\n }\n }\n\n /**\n * Clears the saved state from localStorage.\n */\n clearState() {\n localStorage.removeItem(this.#storageKey);\n }\n\n #saveStateAfterEvent = () => setTimeout(() => this.saveState(), 0);\n}\n"],"mappings":"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","names":["classesToArray","classes","toHumanReadable","str","char","createRegexTokenizer","exp","regex","value","token","virtualScrollToNumber","virtualScroll","convertClasses","defaultClasses","userClasses","getNestedValue","obj","path","keys","current","key","_warned","_container","_element","_generator","_rowCount","_rowHeight","_padding","_animationFrame","_started","_scrollTop","_topPaddingElement","_bottomPaddingElement","_resizeObserver","_scrollCallback","_VirtualScroll_instances","scheduleRender_fn","renderChunk_fn","updateRowHeight_fn","_VirtualScroll","generator","container","element","nodePadding","__privateAdd","__privateGet","__privateSet","__privateMethod","index","px","rowCount","scrollTop","rowHeight","padding","totalContentHeight","originalHeight","viewHeight","totalPadding","startNode","visibleNodesCount","offsetY","remainingHeight","visibleChildren","_","actualHeight","renderSize","elements","VirtualScrollError","VirtualScroll","message","_table","_thead","_tbody","_scroller","_textMeasurementContext","_columnData","_rows","_filteredRows","_userQuery","_query","_filters","_virtualScroll","_resizingColumn","_tableWidthIsFixed","_options","_blockUpdates","_blockedUpdates","_DataTable_instances","initTableElements_fn","initColumns_fn","loadRow_fn","calculateSearchScore_fn","searchField_fn","filterField_fn","filterRow_fn","filterRows_fn","compareRows_fn","sortRows_fn","updateHeaders_fn","renderTable_fn","markText_fn","updateCell_fn","createRow_fn","ensureFixedLayout_fn","resizeColumn_fn","applyBlockedUpdates_fn","_onTableClicked","_onResizeColumnStart","_onResizeColumnMove","_onResizeColumnEnd","_onResizeColumnDoubleClick","_onDragColumnStart","_onDragColumnOver","_onDragColumnEnter","_onDragColumnLeave","_onDragColumnDrop","_onDragColumnEnd","_DataTable","table","columns","options","__privateAdd","createRegexTokenizer","VirtualScroll","__spreadValues","event","_a","tr","td","field","index","row","__privateGet","value","rowEvent","col","__privateSet","dx","newWidth","__privateMethod","resizeEvent","columnData","maxWidth","context","sampleCell","cellPadding","style","getNestedValue","text","textWidth","dragField","dropField","dragIndex","dropIndex","draggedColumn","droppedColumn","newColumnOrder","reorderEvent","elements","element","virtualScrollToNumber","classes","convertClasses","data","virtualScrollClass","restOptions","__objRest","tableElement","scroller","thead","headerRow","tbody","column","state","columnState","key","optionKey","config","handler","finalValue","__spreadProps","rows","scrollTop","scrollLeft","internal_row","colSpan","query","searchEvent","filters","colName","order","sortEvent","priorities","priority","maxPriority","visisble","visibilityEvent","filename","all","csvHeaders","csvRows","list","csvContent","blob","a","rowData","filteredIndex","theadHeight","px","fields","newColumns","found_row","current_row","callback","prevBlock","type","listener","_b","_c","_d","_e","_f","_g","_h","_i","_j","colVisible","colOptions","header","headerContent","titleWrapper","titleElement","colData","toHumanReadable","sorter","resizer","metadata","token","target","baseScore","matchTypeWeight","specificityBonus","tokens","accumulator","score","filter","filterFunction","filterCallback","c","originalValue","compareValue","columnTokens","changeEvent","b","aValue","bValue","ret","aIsNull","bIsNull","sortedColumns","comp","useVirtualScroll","error","VirtualScrollError","WARN_ROW_COUNT","count","rowElements","_","match","child","regex","currentWidth","width","headerWidth","DataTable","_dataTable","_storageKey","_options","_saveStateAfterEvent","LocalStorageAdapter","dataTable","storageKey","options","__privateAdd","__privateSet","__spreadValues","__privateGet","_a","savedTableState","tableState","columnState","savedColumnState","json","tableStateToRestore","columnStateToRestore","error"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timlassiter11/yatl",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
4
4
  "description": "Yet another table library with all of the standard bells and whistles.",
5
5
  "main": "dist/data-table.js",
6
6
  "module": "dist/data-table.mjs",