@squirkle-ui/datagrid 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/GridFilter.vue","../../src/engine.ts","../../src/SqDataGrid.vue","../../src/index.ts"],"sourcesContent":["<template>\n <div class=\"sq-grid-filter\" @click.stop>\n <template v-if=\"kind === 'set'\">\n <SqTextField v-model=\"search\" :placeholder=\"messages.search\" density=\"compact\" prepend-inner-icon=\"search\" hide-details clearable />\n <label class=\"sq-grid-filter__all\">\n <SqCheckbox :model-value=\"allChecked\" :indeterminate=\"someChecked\" :label=\"messages.selectAll\" @update:modelValue=\"toggleAll\" />\n </label>\n <SqVirtualScroll :items=\"shownValues\" :item-height=\"32\" :height=\"Math.min(shownValues.length * 32, 224) || 32\">\n <template #default=\"{ item }\">\n <SqCheckbox :model-value=\"isChecked(item)\" :label=\"label(item)\" @update:modelValue=\"toggleValue(item)\" />\n </template>\n </SqVirtualScroll>\n </template>\n <template v-else>\n <SqSelect :model-value=\"draft.op\" :items=\"ops\" density=\"compact\" hide-details @update:modelValue=\"set('op', $event)\" />\n <SqTextField\n v-if=\"needsValue\"\n :model-value=\"draftValue\"\n :type=\"kind === 'number' ? 'number' : kind === 'date' ? 'date' : 'text'\"\n :placeholder=\"kind === 'text' ? messages.search : 'Value'\"\n density=\"compact\"\n hide-details\n clearable\n @update:modelValue=\"set('value', $event)\"\n />\n <SqTextField\n v-if=\"draft.op === 'between'\"\n :model-value=\"draftValueTo\"\n :type=\"kind === 'number' ? 'number' : 'date'\"\n placeholder=\"To\"\n density=\"compact\"\n hide-details\n @update:modelValue=\"set('valueTo', $event)\"\n />\n </template>\n <div class=\"sq-grid-filter__actions\">\n <SqBtn size=\"small\" variant=\"text\" color=\"surface\" @click=\"$emit('update:modelValue', undefined)\">{{ messages.clear }}</SqBtn>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, ref, type PropType } from 'vue'\nimport { SqBtn, SqCheckbox, SqSelect, SqTextField, SqVirtualScroll, config } from '@squirkle-ui/ui'\nimport type { CellValue, FilterCondition, FilterKind } from './types'\n\nconst TEXT_OPS = [\n { title: 'Contains', value: 'contains' }, { title: 'Does not contain', value: 'notContains' }, { title: 'Equals', value: 'equals' },\n { title: 'Not equal', value: 'notEqual' }, { title: 'Starts with', value: 'startsWith' }, { title: 'Ends with', value: 'endsWith' },\n { title: 'Blank', value: 'blank' }, { title: 'Not blank', value: 'notBlank' },\n]\nconst NUM_OPS = [\n { title: 'Equals', value: 'equals' }, { title: 'Not equal', value: 'notEqual' }, { title: 'Greater than', value: 'gt' }, { title: '≥', value: 'gte' },\n { title: 'Less than', value: 'lt' }, { title: '≤', value: 'lte' }, { title: 'Between', value: 'between' }, { title: 'Blank', value: 'blank' }, { title: 'Not blank', value: 'notBlank' },\n]\n\n/** Filter editor shown in the column menu (internal to SqDataGrid). */\nexport default defineComponent({\n name: 'SqGridFilter',\n components: { SqBtn, SqCheckbox, SqSelect, SqTextField, SqVirtualScroll },\n props: {\n kind: { type: String as PropType<FilterKind>, required: true },\n modelValue: { type: Object as PropType<FilterCondition>, default: undefined },\n /** Distinct values for the set filter. */\n values: { type: Array as PropType<CellValue[]>, default: () => [] },\n formatter: { type: Function as PropType<(v: CellValue) => string>, default: undefined },\n },\n emits: ['update:modelValue'],\n setup(props, { emit }) {\n const search = ref('')\n const ops = computed(() => (props.kind === 'text' ? TEXT_OPS : NUM_OPS))\n const draft = computed<FilterCondition>(() => props.modelValue ?? { kind: props.kind, op: props.kind === 'text' ? 'contains' : 'equals' })\n const draftValue = computed(() => draft.value.value as string | number | undefined)\n const draftValueTo = computed(() => draft.value.valueTo as string | number | undefined)\n const needsValue = computed(() => draft.value.op !== 'blank' && draft.value.op !== 'notBlank')\n const set = (key: 'op' | 'value' | 'valueTo', v: unknown) => emit('update:modelValue', { ...draft.value, kind: props.kind, [key]: v })\n\n const label = (v: CellValue) => (v == null || v === '' ? '(Blanks)' : props.formatter ? props.formatter(v) : String(v))\n const shownValues = computed(() => {\n const q = search.value.trim().toLowerCase()\n return q ? props.values.filter((v) => label(v).toLowerCase().includes(q)) : props.values\n })\n const checkedSet = computed(() => new Set((props.modelValue?.values ?? props.values).map(String)))\n const isChecked = (v: CellValue) => checkedSet.value.has(String(v))\n const allChecked = computed(() => !props.modelValue?.values || props.modelValue.values.length === props.values.length)\n const someChecked = computed(() => !!props.modelValue?.values && props.modelValue.values.length > 0 && !allChecked.value)\n const toggleValue = (v: CellValue) => {\n const cur = props.modelValue?.values ?? props.values\n const next = isChecked(v) ? cur.filter((x) => String(x) !== String(v)) : [...cur, v]\n emit('update:modelValue', next.length === props.values.length ? undefined : { kind: 'set', values: next })\n }\n const toggleAll = () => emit('update:modelValue', allChecked.value ? { kind: 'set', values: [] } : undefined)\n return { search, ops, draft, draftValue, draftValueTo, needsValue, set, label, shownValues, isChecked, allChecked, someChecked, toggleValue, toggleAll, messages: computed(() => config.locale.messages) }\n },\n})\n</script>\n\n<style>\n.sq-grid-filter { display: flex; flex-direction: column; gap: var(--sq-space-2); width: 240px; padding: var(--sq-space-2); }\n.sq-grid-filter__all { border-bottom: 1px solid var(--sq-border); padding-bottom: 2px; }\n.sq-grid-filter__actions { display: flex; justify-content: flex-end; }\n.sq-grid-filter .sq-checkbox { min-height: 32px; font-size: var(--sq-text-sm); width: 100%; }\n</style>\n","/**\n * Pure, framework-free data pipeline for SqDataGrid:\n * rows → quick filter → column filters → sort → group / tree (+ aggregation) → flatten (+ detail rows)\n * Every stage is a separate function so the Vue layer can cache each one in its own computed.\n */\nimport { compareValues, getByPath, toDate } from '@squirkle-ui/core'\nimport type { AggFunc, CellValue, ColumnDef, DisplayRow, FilterCondition, FilterModel, RowData, SortItem } from './types'\n\nexport const colIdOf = <T extends RowData>(c: ColumnDef<T>) => c.colId ?? c.field ?? c.headerName ?? ''\n\nexport function makeGetter<T extends RowData>(col: ColumnDef<T>): (row: T) => CellValue {\n if (col.valueGetter) return col.valueGetter\n const f = col.field\n if (!f) return () => undefined\n if (!f.includes('.')) return (row) => (row as RowData)[f]\n return (row) => getByPath(row, f)\n}\n\nexport function filterKindOf<T extends RowData>(col: ColumnDef<T>): FilterCondition['kind'] {\n if (typeof col.filter === 'string') return col.filter\n return col.type === 'number' ? 'number' : col.type === 'date' ? 'date' : col.type === 'boolean' ? 'set' : 'text'\n}\n\nconst isBlank = (v: CellValue) => v == null || v === ''\n\nexport function matchCondition(value: CellValue, c: FilterCondition): boolean {\n if (c.kind === 'set') {\n if (!c.values) return true\n return c.values.some((x) => x === value || (isBlank(x) && isBlank(value)) || String(x) === String(value))\n }\n const op = c.op ?? (c.kind === 'text' ? 'contains' : 'equals')\n if (op === 'blank') return isBlank(value)\n if (op === 'notBlank') return !isBlank(value)\n if (c.value == null || c.value === '') return true\n if (c.kind === 'text') {\n const v = String(value ?? '').toLowerCase()\n const q = String(c.value).toLowerCase()\n switch (op) {\n case 'contains': return v.includes(q)\n case 'notContains': return !v.includes(q)\n case 'equals': return v === q\n case 'notEqual': return v !== q\n case 'startsWith': return v.startsWith(q)\n case 'endsWith': return v.endsWith(q)\n default: return true\n }\n }\n const toNum = (x: CellValue) => (c.kind === 'date' ? toDate(x as string)?.getTime() ?? NaN : Number(x))\n const v = toNum(value)\n const a = toNum(c.value)\n if (isNaN(v)) return false\n switch (op) {\n case 'equals': return c.kind === 'date' ? Math.floor(v / 864e5) === Math.floor(a / 864e5) : v === a\n case 'notEqual': return v !== a\n case 'gt': return v > a\n case 'gte': return v >= a\n case 'lt': return v < a\n case 'lte': return v <= a\n case 'between': return v >= a && v <= toNum(c.valueTo)\n default: return true\n }\n}\n\nexport function filterRows<T extends RowData>(rows: T[], columns: ColumnDef<T>[], model: FilterModel, quick: string): number[] {\n const active = Object.entries(model).filter(([, c]) => c && (c.kind === 'set' ? !!c.values : c.op === 'blank' || c.op === 'notBlank' || (c.value != null && c.value !== '')))\n const byId = new Map(columns.map((c) => [colIdOf(c), c]))\n const checks = active.map(([id, cond]) => ({ get: makeGetter(byId.get(id) ?? { field: id }), cond }))\n const q = quick.trim().toLowerCase()\n // Quick filter matches raw primitive values (formatting every cell of 100k rows is far too slow).\n const quickGetters = q ? columns.filter((c) => !c.hide).map((c) => makeGetter(c)) : []\n const out: number[] = []\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]\n let ok = true\n for (const { get, cond } of checks) {\n if (!matchCondition(get(row), cond)) { ok = false; break }\n }\n if (ok && q) {\n ok = false\n for (const get of quickGetters) {\n const v = get(row)\n if (v == null || typeof v === 'object') continue\n if (String(v).toLowerCase().includes(q)) { ok = true; break }\n }\n }\n if (ok) out.push(i)\n }\n return out\n}\n\n/** Sorts row indices; keys are extracted once per row (decorate-sort-undecorate). */\nexport function sortIndices<T extends RowData>(rows: T[], indices: number[], columns: ColumnDef<T>[], sort: SortItem[]): number[] {\n if (!sort.length) return indices\n const byId = new Map(columns.map((c) => [colIdOf(c), c]))\n const specs = sort.map((s) => {\n const col = byId.get(s.colId) ?? ({ field: s.colId } as ColumnDef<T>)\n const get = makeGetter(col)\n const keys = new Array<CellValue>(rows.length)\n for (const i of indices) keys[i] = get(rows[i])\n return { keys, dir: s.sort === 'desc' ? -1 : 1, cmp: col.comparator, date: col.type === 'date' }\n })\n for (const s of specs) if (s.date) for (const i of indices) s.keys[i] = toDate(s.keys[i] as string)?.getTime() ?? null\n return indices.slice().sort((a, b) => {\n for (const s of specs) {\n const ka = s.keys[a]\n const kb = s.keys[b]\n // Blanks stay at the bottom in both directions.\n const blankA = ka == null || ka === ''\n const blankB = kb == null || kb === ''\n if (blankA !== blankB) return blankA ? 1 : -1\n const r = s.cmp ? s.cmp(ka, kb, rows[a], rows[b]) : compareValues(ka, kb)\n if (r) return r * s.dir\n }\n return a - b\n })\n}\n\nexport function aggregate(values: CellValue[], fn: AggFunc): CellValue {\n if (typeof fn === 'function') return fn(values)\n const nums = values.filter((v) => v != null && v !== '').map(Number).filter((n) => !isNaN(n))\n switch (fn) {\n case 'sum': return nums.reduce((a, b) => a + b, 0)\n case 'avg': return nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : null\n case 'min': return nums.length ? Math.min(...nums) : null\n case 'max': return nums.length ? Math.max(...nums) : null\n case 'count': return values.length\n case 'first': return values[0]\n case 'last': return values[values.length - 1]\n }\n}\n\nexport interface GroupNode {\n key: CellValue\n colId: string\n id: string\n level: number\n children: GroupNode[]\n /** Leaf source indices (in sorted order). */\n leaves: number[]\n agg: Record<string, CellValue>\n}\n\nfunction computeAgg<T extends RowData>(rows: T[], leaves: number[], aggCols: { id: string; get: (r: T) => CellValue; fn: AggFunc }[]) {\n const agg: Record<string, CellValue> = {}\n for (const a of aggCols) agg[a.id] = aggregate(leaves.map((i) => a.get(rows[i])), a.fn)\n return agg\n}\n\n/** Groups sorted indices by one or more columns. Group order follows the first occurrence in sorted data. */\nexport function groupRows<T extends RowData>(rows: T[], indices: number[], columns: ColumnDef<T>[], groupBy: string[]): GroupNode[] {\n const byId = new Map(columns.map((c) => [colIdOf(c), c]))\n const aggCols = columns.filter((c) => c.aggFunc).map((c) => ({ id: colIdOf(c), get: makeGetter(c), fn: c.aggFunc! }))\n const build = (idx: number[], level: number, parentId: string): GroupNode[] => {\n const colId = groupBy[level]\n const get = makeGetter(byId.get(colId) ?? ({ field: colId } as ColumnDef<T>))\n const buckets = new Map<string, { key: CellValue; leaves: number[] }>()\n for (const i of idx) {\n const key = get(rows[i])\n const k = String(key ?? '')\n let b = buckets.get(k)\n if (!b) buckets.set(k, (b = { key, leaves: [] }))\n b.leaves.push(i)\n }\n return Array.from(buckets.values()).map((b) => {\n const id = `${parentId}/${colId}:${String(b.key ?? '')}`\n return {\n key: b.key,\n colId,\n id,\n level,\n leaves: b.leaves,\n children: level + 1 < groupBy.length ? build(b.leaves, level + 1, id) : [],\n agg: computeAgg(rows, b.leaves, aggCols),\n }\n })\n }\n return groupBy.length ? build(indices, 0, 'g') : []\n}\n\n/** Builds a tree from `getDataPath(row)` (e.g. ['Org', 'Team', 'Alice']); missing parents become filler groups. */\nexport function treeRows<T extends RowData>(rows: T[], indices: number[], columns: ColumnDef<T>[], getDataPath: (row: T) => string[]): GroupNode[] {\n const aggCols = columns.filter((c) => c.aggFunc).map((c) => ({ id: colIdOf(c), get: makeGetter(c), fn: c.aggFunc! }))\n const root: GroupNode = { key: null, colId: '__tree', id: 't', level: -1, children: [], leaves: [], agg: {} }\n const nodes = new Map<string, GroupNode & { self?: number }>()\n for (const i of indices) {\n const path = getDataPath(rows[i])\n let parent = root\n let id = 't'\n path.forEach((part, depth) => {\n id += `/${part}`\n let node = nodes.get(id)\n if (!node) {\n node = { key: part, colId: '__tree', id, level: depth, children: [], leaves: [], agg: {} }\n nodes.set(id, node)\n parent.children.push(node)\n }\n if (depth === path.length - 1) node.self = i\n node.leaves.push(i)\n parent = node\n })\n }\n for (const n of nodes.values()) if (n.children.length) n.agg = computeAgg(rows, n.leaves, aggCols)\n return root.children\n}\n\nexport interface FlattenOptions {\n expanded: Set<string>\n /** Open every group regardless of `expanded` (until the user collapses one). */\n expandAll?: boolean\n collapsed?: Set<string>\n rowId: (row: RowData, index: number) => string\n detailOpen?: Set<string>\n tree?: boolean\n}\n\n/** Turns groups (or plain indices) into the displayed row list. */\nexport function flatten<T extends RowData>(rows: T[], indices: number[], groups: GroupNode[] | null, opts: FlattenOptions): DisplayRow<T>[] {\n const out: DisplayRow<T>[] = []\n const pushData = (i: number, level: number) => {\n const id = opts.rowId(rows[i], i)\n out.push({ kind: 'data', id, data: rows[i], level, sourceIndex: i })\n if (opts.detailOpen?.has(id)) out.push({ kind: 'detail', id: `${id}__detail`, data: rows[i], level, sourceIndex: i })\n }\n if (!groups) {\n for (const i of indices) pushData(i, 0)\n return out\n }\n const isOpen = (id: string) => (opts.expandAll ? !opts.collapsed?.has(id) : opts.expanded.has(id))\n const walk = (nodes: GroupNode[]) => {\n for (const g of nodes) {\n const self = (g as GroupNode & { self?: number }).self\n if (opts.tree && !g.children.length && self != null) {\n pushData(self, g.level)\n continue\n }\n const expanded = isOpen(g.id)\n const leafIds = g.leaves.map((i) => opts.rowId(rows[i], i))\n out.push({\n kind: 'group',\n id: g.id,\n data: opts.tree && self != null ? rows[self] : null,\n level: g.level,\n sourceIndex: self,\n group: { key: g.key, colId: g.colId, count: opts.tree ? g.leaves.length - (self != null ? 1 : 0) : g.leaves.length, expanded, agg: g.agg, leafIds },\n })\n if (!expanded) continue\n if (g.children.length) walk(g.children)\n else for (const i of g.leaves) pushData(i, g.level + 1)\n }\n }\n walk(groups)\n return out\n}\n\nexport function allGroupIds(groups: GroupNode[]): string[] {\n const ids: string[] = []\n const walk = (n: GroupNode[]) => n.forEach((g) => { if (g.children.length || g.colId !== '__tree') ids.push(g.id); walk(g.children) })\n walk(groups)\n return ids\n}\n\n/** Row offsets for virtualization with mixed row heights (data/group vs. detail). */\nexport function rowLayout(rows: DisplayRow[], rowHeight: number, detailHeight: number) {\n const offsets = new Float64Array(rows.length + 1)\n for (let i = 0; i < rows.length; i++) offsets[i + 1] = offsets[i] + (rows[i].kind === 'detail' ? detailHeight : rowHeight)\n const indexAt = (y: number) => {\n let lo = 0\n let hi = rows.length - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1\n if (offsets[mid] <= y) lo = mid\n else hi = mid - 1\n }\n return Math.max(0, lo)\n }\n return { offsets, total: offsets[rows.length], indexAt }\n}\n\n/**\n * Pivot: one output row per combination of `groupBy` values, one column per pivot value × value column.\n * Returns plain rows plus generated column defs, so the result renders like any other data.\n */\nexport function pivotRows<T extends RowData>(rows: T[], indices: number[], columns: ColumnDef<T>[], groupBy: string[], pivotCol: string) {\n const byId = new Map(columns.map((c) => [colIdOf(c), c]))\n const valueCols = columns.filter((c) => c.aggFunc)\n const pGet = makeGetter(byId.get(pivotCol) ?? ({ field: pivotCol } as ColumnDef<T>))\n const gGets = groupBy.map((id) => makeGetter(byId.get(id) ?? ({ field: id } as ColumnDef<T>)))\n const pivotKeys: string[] = []\n const seen = new Set<string>()\n const buckets = new Map<string, { keys: CellValue[]; cells: Map<string, number[]> }>()\n for (const i of indices) {\n const pk = String(pGet(rows[i]) ?? '')\n if (!seen.has(pk)) { seen.add(pk); pivotKeys.push(pk) }\n const keys = gGets.map((g) => g(rows[i]))\n const k = keys.map(String).join('\\u0001')\n let b = buckets.get(k)\n if (!b) buckets.set(k, (b = { keys, cells: new Map() }))\n let cell = b.cells.get(pk)\n if (!cell) b.cells.set(pk, (cell = []))\n cell.push(i)\n }\n pivotKeys.sort((a, b) => compareValues(a, b))\n const outRows: RowData[] = []\n for (const b of buckets.values()) {\n const r: RowData = {}\n groupBy.forEach((id, k) => (r[id] = b.keys[k]))\n for (const pk of pivotKeys)\n for (const vc of valueCols) {\n const leaves = b.cells.get(pk) ?? []\n const get = makeGetter(vc)\n r[`${pk}__${colIdOf(vc)}`] = leaves.length ? aggregate(leaves.map((i) => get(rows[i])), vc.aggFunc!) : null\n }\n outRows.push(r)\n }\n const outCols: ColumnDef[] = [\n ...groupBy.map((id) => ({ ...(byId.get(id) as ColumnDef), colId: id, field: id, pinned: 'left' as const, rowGroup: false, valueGetter: undefined })),\n ...pivotKeys.flatMap((pk) =>\n valueCols.map((vc) => ({\n colId: `${pk}__${colIdOf(vc)}`,\n field: `${pk}__${colIdOf(vc)}`,\n headerName: valueCols.length > 1 ? `${vc.headerName ?? colIdOf(vc)}` : pk,\n group: valueCols.length > 1 ? pk : undefined,\n type: 'number' as const,\n align: 'right' as const,\n aggFunc: vc.aggFunc,\n valueFormatter: vc.valueFormatter as ColumnDef['valueFormatter'],\n width: 120,\n })),\n ),\n ]\n return { rows: outRows, columns: outCols }\n}\n\n/** RFC 4180 CSV. */\nexport function toCsv(header: string[], body: string[][], sep = ','): string {\n const esc = (s: string) => (/[\",\\n\\r]/.test(s) || s.includes(sep) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s)\n return [header, ...body].map((r) => r.map(esc).join(sep)).join('\\r\\n')\n}\n\n/** Parses tab-separated clipboard text into a 2D array. */\nexport const parseTsv = (text: string) => text.replace(/\\r?\\n$/, '').split(/\\r?\\n/).map((l) => l.split('\\t'))\n","<template>\n <div\n class=\"sq-datagrid sq-surface\"\n :class=\"{ 'sq-datagrid--striped': striped, 'sq-datagrid--column-lines': columnLines, 'sq-datagrid--scrolled-x': scrollLeft > 0 }\"\n :style=\"rootStyle\"\n tabindex=\"0\"\n role=\"grid\"\n :aria-rowcount=\"rowCount\"\n :aria-colcount=\"flatCols.length\"\n @keydown=\"onKeydown\"\n @paste=\"onPaste\"\n >\n <SqShape clip />\n\n <div v-if=\"toolbar || has('toolbar')\" class=\"sq-datagrid__toolbar\">\n <slot name=\"toolbar\" :api=\"api\" />\n <SqTextField v-if=\"toolbar\" :model-value=\"quick\" class=\"sq-datagrid__quick\" :placeholder=\"messages.search\" prepend-inner-icon=\"search\" density=\"compact\" hide-details clearable @update:modelValue=\"quick = $event || ''\" />\n <span class=\"sq-spacer\"></span>\n <SqMenu v-if=\"toolbar\" :close-on-content-click=\"false\" location=\"bottom end\">\n <template #activator><SqBtn prepend-icon=\"columns\" variant=\"text\" color=\"surface\" size=\"small\">Columns</SqBtn></template>\n <div class=\"sq-datagrid__chooser\">\n <SqCheckbox v-for=\"c in chooserCols\" :key=\"c.id\" :model-value=\"!c.hidden\" :label=\"c.title\" @update:modelValue=\"setHidden(c.id, !$event)\" />\n </div>\n </SqMenu>\n <SqBtn v-if=\"toolbar\" prepend-icon=\"download\" variant=\"text\" color=\"surface\" size=\"small\" @click=\"exportCsv()\">CSV</SqBtn>\n </div>\n\n <div v-if=\"groupPanel && !treeData && !isServer\" class=\"sq-datagrid__group-panel\" @dragover.prevent @drop=\"onGroupDrop\">\n <SqIcon icon=\"menu\" size=\"16px\" />\n <span v-if=\"!groupBy.length\" class=\"sq-datagrid__group-hint\">Drag a column header here to group rows</span>\n <SqChip v-for=\"id in groupBy\" :key=\"id\" size=\"small\" variant=\"tonal\" color=\"primary\" closable @click:close=\"removeGroup(id)\">{{ titleOf(id) }}</SqChip>\n </div>\n\n <div ref=\"viewport\" class=\"sq-datagrid__viewport\" :style=\"{ height: toUnit(height) }\" @scroll.passive=\"onScroll\">\n <div class=\"sq-datagrid__canvas\" :style=\"{ width: totalWidth + 'px' }\">\n <!-- header (sticky) -->\n <div class=\"sq-datagrid__head\" role=\"rowgroup\">\n <div v-if=\"hasHeaderGroups\" class=\"sq-datagrid__header-row sq-datagrid__header-row--groups\" :style=\"{ height: headerHeight + 'px' }\">\n <div v-for=\"g in headerGroups\" :key=\"g.key\" class=\"sq-datagrid__header-group\" :class=\"g.cls\" :style=\"g.style\">{{ g.label }}</div>\n </div>\n <div class=\"sq-datagrid__header-row\" role=\"row\" :style=\"{ height: headerHeight + 'px' }\">\n <div\n v-for=\"rc in renderCols\"\n :key=\"rc.key\"\n class=\"sq-datagrid__hcell\"\n :class=\"headerCellClass(rc)\"\n :style=\"rc.style\"\n role=\"columnheader\"\n :aria-sort=\"rc.col ? ariaSort(rc.id) : undefined\"\n :draggable=\"!!rc.col && !rc.auto && !rc.col.lockPosition\"\n @click=\"rc.col && onHeaderClick($event, rc)\"\n @dragstart=\"onDragStart($event, rc)\"\n @dragover.prevent=\"onDragOver($event, rc)\"\n @drop.prevent=\"onDrop(rc)\"\n @dragend=\"dragColId = null\"\n >\n <template v-if=\"rc.col\">\n <span v-if=\"rc.id === '__select'\" class=\"sq-datagrid__check\" @click.stop><SqCheckbox :model-value=\"allSelected\" :indeterminate=\"someSelected\" aria-label=\"Select all rows\" @update:modelValue=\"toggleAll\" /></span>\n <template v-else>\n <span class=\"sq-datagrid__htitle\"><slot :name=\"`header-${rc.id}`\" :column=\"rc.col\">{{ rc.title }}</slot></span>\n <span v-if=\"sortIndex(rc.id) >= 0\" class=\"sq-datagrid__sort\">\n <SqIcon :icon=\"sortDir(rc.id) === 'asc' ? 'arrowUp' : 'arrowDown'\" size=\"14px\" />\n <sup v-if=\"sortModelList.length > 1\">{{ sortIndex(rc.id) + 1 }}</sup>\n </span>\n <SqIcon v-if=\"filterModelObj[rc.id]\" icon=\"filter\" size=\"14px\" class=\"sq-datagrid__filtered\" />\n <button v-if=\"!rc.col.suppressMenu && !rc.auto\" type=\"button\" class=\"sq-datagrid__menu-btn\" tabindex=\"-1\" aria-label=\"Column menu\" @click.stop=\"openMenu($event, rc.id)\"><SqIcon icon=\"more\" size=\"16px\" /></button>\n </template>\n <span v-if=\"rc.col.resizable !== false\" class=\"sq-datagrid__resizer\" @pointerdown.stop.prevent=\"startResize($event, rc)\" @dblclick.stop=\"autoSize([rc.id])\" @click.stop></span>\n </template>\n </div>\n </div>\n <div v-if=\"floatingFilters\" class=\"sq-datagrid__header-row sq-datagrid__header-row--filters\" :style=\"{ height: filterRowHeight + 'px' }\">\n <div v-for=\"rc in renderCols\" :key=\"rc.key\" class=\"sq-datagrid__hcell sq-datagrid__fcell\" :class=\"headerCellClass(rc)\" :style=\"rc.style\">\n <input\n v-if=\"rc.col && !rc.auto && rc.col.filter !== false && filterKind(rc.col) !== 'set'\"\n class=\"sq-datagrid__ffilter sq-squircle\"\n :type=\"filterKind(rc.col) === 'number' ? 'number' : filterKind(rc.col) === 'date' ? 'date' : 'text'\"\n :value=\"floatingValue(rc.id)\"\n :placeholder=\"filterKind(rc.col) === 'text' ? '…' : '='\"\n :aria-label=\"`Filter ${rc.title}`\"\n @input=\"onFloatingInput($event, rc)\"\n />\n </div>\n </div>\n <div v-for=\"(pr, pi) in pinnedTopRows\" :key=\"'pt' + pi\" class=\"sq-datagrid__row sq-datagrid__row--pinned\" :style=\"{ height: rowHeight + 'px' }\">\n <div v-for=\"rc in renderCols\" :key=\"rc.key\" class=\"sq-datagrid__cell\" :class=\"cellAlignClass(rc)\" :style=\"rc.style\">\n <template v-if=\"rc.col && !rc.auto\"><slot :name=\"`cell-${rc.id}`\" v-bind=\"cellParams(pr, rc, -1)\">{{ formatCell(rc, pr) }}</slot></template>\n </div>\n </div>\n </div>\n\n <!-- body -->\n <div class=\"sq-datagrid__body\" role=\"rowgroup\" :style=\"{ height: layout.total + 'px' }\">\n <div\n v-for=\"vr in visibleRows\"\n :key=\"vr.row.id\"\n class=\"sq-datagrid__row\"\n :class=\"rowClass(vr)\"\n :style=\"{ transform: `translateY(${vr.top}px)`, height: vr.height + 'px' }\"\n role=\"row\"\n :aria-rowindex=\"vr.index + 1\"\n :aria-selected=\"vr.row.kind === 'data' && rowSelection ? (selectedSet.has(vr.row.id) ? 'true' : 'false') : undefined\"\n @click=\"onRowClick($event, vr)\"\n @dblclick=\"$emit('row-dblclick', { row: vr.row.data, event: $event })\"\n >\n <div v-if=\"vr.row.kind === 'detail'\" class=\"sq-datagrid__detail\" :style=\"{ width: vpWidth + 'px' }\">\n <slot name=\"detail\" :row=\"vr.row.data\" />\n </div>\n <template v-else>\n <div\n v-for=\"rc in renderCols\"\n :key=\"rc.key\"\n class=\"sq-datagrid__cell\"\n :class=\"cellClass(vr, rc)\"\n :style=\"cellStyle(vr, rc)\"\n role=\"gridcell\"\n @mousedown=\"onCellMousedown($event, vr, rc)\"\n @mouseenter=\"onCellEnter(vr, rc)\"\n @dblclick.stop=\"onCellDblclick(vr, rc)\"\n @contextmenu.prevent=\"openContext($event, vr, rc)\"\n >\n <template v-if=\"!rc.col\"></template>\n <span v-else-if=\"vr.row.kind === 'loading'\" class=\"sq-datagrid__skeleton sq-skeleton-shimmer\"></span>\n <span v-else-if=\"rc.id === '__select'\" class=\"sq-datagrid__check\" @click.stop @mousedown.stop><SqCheckbox :model-value=\"isRowChecked(vr.row)\" :indeterminate=\"isRowPartial(vr.row)\" aria-label=\"Select row\" @update:modelValue=\"toggleRowCheck(vr.row)\" /></span>\n <span v-else-if=\"rc.id === '__group'\" class=\"sq-datagrid__group-cell\" :style=\"{ paddingInlineStart: vr.row.level * 18 + 'px' }\">\n <button v-if=\"vr.row.kind === 'group'\" type=\"button\" class=\"sq-datagrid__expander\" :class=\"{ 'sq-datagrid__expander--open': vr.row.group?.expanded }\" tabindex=\"-1\" @click.stop=\"toggleGroup(vr.row)\"><SqIcon icon=\"chevronRight\" size=\"18px\" /></button>\n <button v-else-if=\"masterDetail && !treeData\" type=\"button\" class=\"sq-datagrid__expander\" :class=\"{ 'sq-datagrid__expander--open': detailOpen.has(vr.row.id) }\" tabindex=\"-1\" @click.stop=\"toggleDetail(vr.row.id)\"><SqIcon icon=\"chevronRight\" size=\"18px\" /></button>\n <span v-else class=\"sq-datagrid__expander-spacer\"></span>\n <span class=\"sq-datagrid__group-key\"><slot name=\"group\" :row=\"vr.row\">{{ groupLabel(vr.row) }}</slot></span>\n <span v-if=\"vr.row.kind === 'group' && vr.row.group?.count\" class=\"sq-datagrid__group-count\">{{ vr.row.group?.count }}</span>\n </span>\n <span v-else-if=\"vr.row.kind === 'group'\" class=\"sq-datagrid__agg\">{{ groupAggText(vr.row, rc) }}</span>\n <span v-else-if=\"isEditing(vr, rc)\" class=\"sq-datagrid__editor-wrap\" @mousedown.stop>\n <select v-if=\"editorKind(rc) === 'select'\" class=\"sq-datagrid__editor\" :value=\"String(editing?.value ?? '')\" @change=\"onEditorInput\" @keydown.stop=\"onEditorKey\" @blur=\"commitEdit\">\n <option v-for=\"opt in rc.col.cellEditorParams?.values ?? []\" :key=\"String(opt)\" :value=\"String(opt)\">{{ opt }}</option>\n </select>\n <input v-else class=\"sq-datagrid__editor\" :type=\"editorKind(rc)\" :value=\"editing?.value ?? ''\" @input=\"onEditorInput\" @keydown.stop=\"onEditorKey\" @blur=\"commitEdit\" />\n </span>\n <template v-else>\n <slot :name=\"`cell-${rc.id}`\" v-bind=\"cellParams(vr.row.data, rc, vr.index)\">\n <slot name=\"cell\" v-bind=\"cellParams(vr.row.data, rc, vr.index)\">\n <span v-if=\"rc.col.type === 'boolean'\" class=\"sq-datagrid__bool\" :class=\"{ 'sq-datagrid__bool--on': !!cellValue(rc, vr.row.data) }\"><SqIcon :icon=\"cellValue(rc, vr.row.data) ? 'check' : 'minus'\" size=\"16px\" /></span>\n <span v-else class=\"sq-datagrid__text\">{{ formatCell(rc, vr.row.data) }}</span>\n </slot>\n </slot>\n </template>\n </div>\n </template>\n </div>\n </div>\n\n <!-- pinned bottom / totals (sticky) -->\n <div v-if=\"bottomRows.length\" class=\"sq-datagrid__foot\">\n <div v-for=\"(pr, pi) in bottomRows\" :key=\"'pb' + pi\" class=\"sq-datagrid__row sq-datagrid__row--pinned\" :style=\"{ height: rowHeight + 'px' }\">\n <div v-for=\"rc in renderCols\" :key=\"rc.key\" class=\"sq-datagrid__cell\" :class=\"cellAlignClass(rc)\" :style=\"rc.style\">\n <template v-if=\"rc.id === '__group'\"><strong>Total</strong></template>\n <template v-else-if=\"rc.col && !rc.auto\"><slot :name=\"`cell-${rc.id}`\" v-bind=\"cellParams(pr, rc, -1)\">{{ formatCell(rc, pr) }}</slot></template>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"showLoading\" class=\"sq-datagrid__overlay\"><slot name=\"loading\"><SqProgressCircular indeterminate :size=\"28\" :width=\"3\" /></slot></div>\n <div v-else-if=\"!rowCount\" class=\"sq-datagrid__overlay sq-datagrid__overlay--empty\"><slot name=\"no-rows\"><SqEmptyState :title=\"messages.noData\" icon=\"search\" /></slot></div>\n </div>\n\n <div v-if=\"statusBar || pagination\" class=\"sq-datagrid__footer\">\n <div v-if=\"statusBar\" class=\"sq-datagrid__status\">\n <span>{{ statusText }}</span>\n <span v-if=\"selectedIds.length\">· {{ selectedIds.length }} selected</span>\n <span v-if=\"rangeStats\" class=\"sq-datagrid__range-stats\">Count {{ rangeStats.count }} · Sum {{ fmtNum(rangeStats.sum) }} · Avg {{ fmtNum(rangeStats.avg) }} · Min {{ fmtNum(rangeStats.min) }} · Max {{ fmtNum(rangeStats.max) }}</span>\n </div>\n <span class=\"sq-spacer\"></span>\n <template v-if=\"pagination && !isServer\">\n <span class=\"sq-datagrid__page-size\">{{ messages.rowsPerPage }}\n <select class=\"sq-datagrid__page-select sq-squircle\" :value=\"pageSizeState\" @change=\"onPageSize\"><option v-for=\"s in pageSizes\" :key=\"s\" :value=\"s\">{{ s }}</option></select>\n </span>\n <span class=\"sq-datagrid__page-range\">{{ pageRangeText }}</span>\n <SqPagination v-model=\"page\" :length=\"pageCount\" :total-visible=\"5\" size=\"x-small\" />\n </template>\n </div>\n\n <SqMenu v-model=\"menuOpen\" :activator=\"menuAnchor || undefined\" :close-on-content-click=\"false\" location=\"bottom end\" :max-height=\"480\">\n <div v-if=\"menuCol\" class=\"sq-datagrid__menu\">\n <template v-if=\"menuMode === 'column'\">\n <SqListItem v-if=\"menuCol.col.sortable !== false\" title=\"Sort ascending\" prepend-icon=\"arrowUp\" link @click=\"setSort(menuCol.id, 'asc')\" />\n <SqListItem v-if=\"menuCol.col.sortable !== false\" title=\"Sort descending\" prepend-icon=\"arrowDown\" link @click=\"setSort(menuCol.id, 'desc')\" />\n <SqListItem v-if=\"sortIndex(menuCol.id) >= 0\" title=\"Clear sort\" prepend-icon=\"sort\" link @click=\"setSort(menuCol.id, null)\" />\n <SqDivider />\n <SqListItem :title=\"menuCol.pinned === 'left' ? 'Unpin' : 'Pin left'\" prepend-icon=\"pin\" link @click=\"setPinned(menuCol.id, menuCol.pinned === 'left' ? null : 'left')\" />\n <SqListItem v-if=\"menuCol.pinned !== 'right'\" title=\"Pin right\" prepend-icon=\"pin\" link @click=\"setPinned(menuCol.id, 'right')\" />\n <SqListItem title=\"Autosize column\" prepend-icon=\"columns\" link @click=\"autoSize([menuCol.id])\" />\n <SqListItem title=\"Autosize all columns\" prepend-icon=\"columns\" link @click=\"autoSize()\" />\n <SqListItem v-if=\"!treeData && !isServer\" :title=\"groupBy.includes(menuCol.id) ? `Ungroup by ${menuCol.title}` : `Group by ${menuCol.title}`\" prepend-icon=\"menu\" link @click=\"toggleGroupBy(menuCol.id)\" />\n <SqListItem title=\"Hide column\" prepend-icon=\"eyeOff\" link @click=\"setHidden(menuCol.id, true); menuOpen = false\" />\n <template v-if=\"menuCol.col.filter !== false\">\n <SqDivider>Filter</SqDivider>\n <SqGridFilter :kind=\"filterKind(menuCol.col)\" :model-value=\"filterModelObj[menuCol.id]\" :values=\"distinctValues(menuCol.id)\" :formatter=\"menuFormatter\" @update:modelValue=\"setFilter(menuCol.id, $event)\" />\n </template>\n </template>\n <template v-else>\n <SqListItem title=\"Copy\" prepend-icon=\"copy\" link @click=\"copy(false); menuOpen = false\" />\n <SqListItem title=\"Copy with headers\" prepend-icon=\"copy\" link @click=\"copy(true); menuOpen = false\" />\n <SqListItem v-if=\"canUndo\" title=\"Undo\" prepend-icon=\"refresh\" link @click=\"undo(); menuOpen = false\" />\n <SqDivider />\n <SqListItem title=\"Export CSV\" prepend-icon=\"download\" link @click=\"exportCsv(); menuOpen = false\" />\n <SqListItem v-if=\"selectedIds.length\" title=\"Export selected rows\" prepend-icon=\"download\" link @click=\"exportCsv({ onlySelected: true }); menuOpen = false\" />\n <template v-if=\"hasGroups\">\n <SqDivider />\n <SqListItem title=\"Expand all\" prepend-icon=\"plus\" link @click=\"expandAll(); menuOpen = false\" />\n <SqListItem title=\"Collapse all\" prepend-icon=\"minus\" link @click=\"collapseAll(); menuOpen = false\" />\n </template>\n </template>\n </div>\n </SqMenu>\n <div ref=\"ctxAnchor\" class=\"sq-datagrid__ctx-anchor\" :style=\"{ left: ctxPos.x + 'px', top: ctxPos.y + 'px' }\"></div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, nextTick, onBeforeUnmount, onMounted, ref, toRaw, watch, type PropType } from 'vue'\nimport { clamp, downloadText, formatDate, getByPath, toUnit } from '@squirkle-ui/core'\nimport {\n SqBtn, SqCheckbox, SqChip, SqDivider, SqEmptyState, SqIcon, SqListItem, SqMenu, SqPagination, SqProgressCircular, SqShape, SqTextField,\n config, useProxiedModel,\n} from '@squirkle-ui/ui'\nimport SqGridFilter from './GridFilter.vue'\nimport {\n aggregate, allGroupIds, colIdOf, filterKindOf, filterRows, flatten, groupRows, makeGetter, parseTsv, pivotRows, rowLayout, sortIndices, toCsv, treeRows,\n} from './engine'\nimport type { CellRange, CellValue, ColumnDef, Datasource, DisplayRow, FilterCondition, FilterModel, RowData, SortItem } from './types'\n\ninterface RCol {\n key: string\n id: string\n col: ColumnDef | null\n title: string\n width: number\n pinned: 'left' | 'right' | null\n auto?: boolean\n flatIndex: number\n style: Record<string, string>\n edgeLeft?: boolean\n edgeRight?: boolean\n}\ninterface VRow { index: number; top: number; height: number; row: DisplayRow }\ninterface Change { row: RowData; col: ColumnDef; oldValue: CellValue; newValue: CellValue }\n\nconst SELECT_COL: ColumnDef = { colId: '__select', headerName: '', width: 48, resizable: false, sortable: false, filter: false, suppressMenu: true, lockPosition: true }\n\nfunction setByPath(obj: RowData, path: string, value: CellValue) {\n const keys = path.split('.')\n let cur: RowData = obj\n for (let i = 0; i < keys.length - 1; i++) cur = (cur[keys[i]] ??= {}) as RowData\n cur[keys[keys.length - 1]] = value\n}\n\n/**\n * Enterprise-style data grid: row + column virtualization, multi-sort, column/quick/set filters, row grouping with\n * aggregation, tree data, pivot, master/detail, pinned rows/columns, resizing, drag reorder, cell editing with undo,\n * range selection + clipboard, CSV export, pagination and an infinite server-side row model.\n */\nexport default defineComponent({\n name: 'SqDataGrid',\n components: { SqShape, SqBtn, SqCheckbox, SqChip, SqDivider, SqEmptyState, SqIcon, SqListItem, SqMenu, SqPagination, SqProgressCircular, SqTextField, SqGridFilter },\n props: {\n rows: { type: Array as PropType<RowData[]>, default: () => [] },\n columns: { type: Array as PropType<ColumnDef[]>, default: () => [] },\n defaultColDef: { type: Object as PropType<Partial<ColumnDef>>, default: () => ({}) },\n /** Field name or function producing a stable row id. */\n rowId: { type: [String, Function] as PropType<string | ((row: RowData, index: number) => string | number)>, default: 'id' },\n height: { type: [Number, String], default: 520 },\n rowHeight: { type: Number, default: 40 },\n headerHeight: { type: Number, default: 42 },\n detailHeight: { type: Number, default: 220 },\n rowSelection: { type: String as PropType<'single' | 'multiple' | null>, default: null },\n /** Auto checkbox column when rowSelection = multiple. */\n selectionColumn: { type: Boolean, default: true },\n selected: { type: Array as PropType<string[]>, default: undefined },\n sortModel: { type: Array as PropType<SortItem[]>, default: undefined },\n filterModel: { type: Object as PropType<FilterModel>, default: undefined },\n quickFilter: { type: String, default: undefined },\n groupBy: { type: Array as PropType<string[]>, default: undefined },\n /** Levels expanded by default; -1 = all. */\n groupDefaultExpanded: { type: Number, default: 0 },\n groupColumn: { type: Object as PropType<Partial<ColumnDef>>, default: () => ({}) },\n treeData: Boolean,\n getDataPath: { type: Function as PropType<(row: RowData) => string[]>, default: undefined },\n pivotMode: Boolean,\n pivotColumn: { type: String, default: undefined },\n masterDetail: Boolean,\n pinnedTopRows: { type: Array as PropType<RowData[]>, default: () => [] },\n pinnedBottomRows: { type: Array as PropType<RowData[]>, default: () => [] },\n /** Bottom row with column aggFunc totals over the filtered rows. */\n totalsRow: Boolean,\n pagination: Boolean,\n pageSize: { type: Number, default: 50 },\n pageSizes: { type: Array as PropType<number[]>, default: () => [25, 50, 100, 500] },\n /** Infinite / server-side row model. Sorting & filtering are delegated to getRows. */\n datasource: { type: Object as PropType<Datasource>, default: undefined },\n blockSize: { type: Number, default: 100 },\n loading: Boolean,\n toolbar: Boolean,\n groupPanel: Boolean,\n floatingFilters: Boolean,\n statusBar: { type: Boolean, default: true },\n striped: Boolean,\n columnLines: Boolean,\n rowClassName: { type: Function as PropType<(row: RowData) => string | undefined>, default: undefined },\n locale: { type: String, default: undefined },\n },\n emits: ['update:selected', 'update:sortModel', 'update:filterModel', 'update:quickFilter', 'update:groupBy', 'row-click', 'row-dblclick', 'cell-click', 'cell-value-changed', 'column-state-change', 'selection-change'],\n setup(props, { emit, slots }) {\n const viewport = ref<HTMLElement | null>(null)\n const ctxAnchor = ref<HTMLElement | null>(null)\n const scrollTop = ref(0)\n const scrollLeft = ref(0)\n const vpWidth = ref(800)\n const vpHeight = ref(400)\n const dataVersion = ref(0)\n const loc = computed(() => props.locale ?? config.locale.code)\n const isServer = computed(() => !!props.datasource)\n\n // ---------- models ----------\n const sortModelRef = useProxiedModel<SortItem[]>(props, emit, 'sortModel', () => [])\n const filterModelRef = useProxiedModel<FilterModel>(props, emit, 'filterModel', () => ({}))\n const quick = useProxiedModel<string>(props, emit, 'quickFilter', () => '')\n const groupByRef = useProxiedModel<string[]>(props, emit, 'groupBy', () => props.columns.filter((c) => c.rowGroup).map(colIdOf))\n const selectedRef = useProxiedModel<string[]>(props, emit, 'selected', () => [])\n const sortModelList = computed(() => sortModelRef.value ?? [])\n const filterModelObj = computed(() => filterModelRef.value ?? {})\n const groupBy = computed(() => groupByRef.value ?? [])\n const selectedIds = computed(() => selectedRef.value ?? [])\n const selectedSet = computed(() => new Set(selectedIds.value))\n\n // ---------- columns ----------\n const colOrder = ref<string[]>([])\n const colWidth = ref<Record<string, number>>({})\n const colHidden = ref<Record<string, boolean>>({})\n const colPinned = ref<Record<string, 'left' | 'right' | null>>({})\n const baseCols = computed(() => props.columns.map((c) => ({ ...props.defaultColDef, ...c }) as ColumnDef))\n watch(baseCols, (cols) => {\n const ids = cols.map(colIdOf)\n colOrder.value = [...colOrder.value.filter((id) => ids.includes(id)), ...ids.filter((id) => !colOrder.value.includes(id))]\n }, { immediate: true })\n\n const rowIdOf = (row: RowData, i: number) => String(typeof props.rowId === 'function' ? props.rowId(row, i) : (row?.[props.rowId] ?? i))\n\n // ---------- client pipeline ----------\n const raw = computed(() => {\n void dataVersion.value\n return toRaw(props.rows) as RowData[]\n })\n // Debounced copy of the quick filter so typing stays responsive on large data sets.\n const quickApplied = ref(quick.value ?? '')\n let quickApplyTimer: ReturnType<typeof setTimeout> | undefined\n watch(quick, (q) => { clearTimeout(quickApplyTimer); quickApplyTimer = setTimeout(() => (quickApplied.value = q ?? ''), raw.value.length > 20000 ? 160 : 0) })\n const filteredIdx = computed(() => (isServer.value ? [] : filterRows(raw.value, baseCols.value, filterModelObj.value, quickApplied.value)))\n const sortedIdx = computed(() => sortIndices(raw.value, filteredIdx.value, baseCols.value, sortModelList.value))\n const pivot = computed(() => (props.pivotMode && props.pivotColumn && !isServer.value ? pivotRows(raw.value, sortedIdx.value, baseCols.value, groupBy.value, props.pivotColumn) : null))\n const viewRows = computed(() => (pivot.value ? pivot.value.rows : raw.value))\n const viewIdx = computed(() => (pivot.value ? pivot.value.rows.map((_, i) => i) : sortedIdx.value))\n const viewCols = computed(() => (pivot.value ? pivot.value.columns.map((c) => ({ ...props.defaultColDef, ...c }) as ColumnDef) : baseCols.value))\n const groups = computed(() => {\n if (isServer.value || pivot.value) return null\n if (props.treeData && props.getDataPath) return treeRows(viewRows.value, viewIdx.value, viewCols.value, props.getDataPath)\n return groupBy.value.length ? groupRows(viewRows.value, viewIdx.value, viewCols.value, groupBy.value) : null\n })\n const hasGroups = computed(() => !!groups.value)\n const expanded = ref(new Set<string>())\n const collapsed = ref(new Set<string>())\n const expandAllFlag = ref(props.groupDefaultExpanded === -1)\n const detailOpen = ref(new Set<string>())\n watch(groups, (g) => {\n if (!g || props.groupDefaultExpanded <= 0) return\n const ids = new Set(expanded.value)\n const walk = (nodes: typeof g, lvl: number) => nodes.forEach((n) => { if (lvl < props.groupDefaultExpanded) { ids.add(n.id); walk(n.children, lvl + 1) } })\n walk(g, 0)\n expanded.value = ids\n }, { immediate: true })\n\n const display = computed<DisplayRow[]>(() =>\n flatten(viewRows.value, viewIdx.value, groups.value, {\n expanded: expanded.value,\n expandAll: expandAllFlag.value,\n collapsed: collapsed.value,\n rowId: rowIdOf,\n detailOpen: props.masterDetail ? detailOpen.value : undefined,\n tree: props.treeData,\n }),\n )\n\n // pagination\n const page = ref(1)\n const pageSizeState = ref(props.pageSize)\n const pageCount = computed(() => Math.max(1, Math.ceil(display.value.length / pageSizeState.value)))\n watch([pageCount, filteredIdx], () => (page.value = Math.min(page.value, pageCount.value)))\n const paged = computed(() => (props.pagination ? display.value.slice((page.value - 1) * pageSizeState.value, page.value * pageSizeState.value) : display.value))\n const onPageSize = (e: Event) => { pageSizeState.value = Number((e.target as HTMLSelectElement).value); page.value = 1 }\n const pageRangeText = computed(() => {\n const n = display.value.length\n const a = n ? (page.value - 1) * pageSizeState.value + 1 : 0\n return config.locale.messages.pageRange.replace('{0}', String(a)).replace('{1}', String(Math.min(n, page.value * pageSizeState.value))).replace('{2}', String(n))\n })\n\n // ---------- server (infinite) row model ----------\n const blocks = new Map<number, RowData[] | 'loading'>()\n const blockVersion = ref(0)\n const serverCount = ref(0)\n const serverLoading = ref(false)\n let epoch = 0\n const loadBlock = async (b: number) => {\n if (!props.datasource || blocks.has(b)) return\n blocks.set(b, 'loading')\n const my = epoch\n serverLoading.value = true\n try {\n const res = await props.datasource.getRows({ startRow: b * props.blockSize, endRow: (b + 1) * props.blockSize, sortModel: sortModelList.value, filterModel: filterModelObj.value, quickFilter: quick.value ?? '' })\n if (my !== epoch) return\n blocks.set(b, res.rows)\n if (res.lastRow != null) serverCount.value = res.lastRow\n else if (res.rows.length < props.blockSize) serverCount.value = b * props.blockSize + res.rows.length\n else serverCount.value = Math.max(serverCount.value, (b + 2) * props.blockSize)\n } catch {\n if (my === epoch) blocks.delete(b)\n } finally {\n if (my === epoch) { serverLoading.value = [...blocks.values()].some((v) => v === 'loading'); blockVersion.value++ }\n }\n }\n const purge = () => {\n epoch++\n blocks.clear()\n serverCount.value = 0\n blockVersion.value++\n if (viewport.value) viewport.value.scrollTop = 0\n loadBlock(0)\n }\n let quickTimer: ReturnType<typeof setTimeout> | undefined\n watch([sortModelList, filterModelObj], () => isServer.value && purge(), { deep: true })\n watch(quick, () => { if (!isServer.value) return; clearTimeout(quickTimer); quickTimer = setTimeout(purge, 250) })\n // First block loads on mount (not during server rendering); later datasource swaps purge immediately.\n watch(() => props.datasource, (ds) => ds && purge())\n onMounted(() => props.datasource && purge())\n\n const rowCount = computed(() => (isServer.value ? serverCount.value : paged.value.length))\n const rowAt = (i: number): DisplayRow => {\n if (!isServer.value) return paged.value[i]\n void blockVersion.value\n const b = Math.floor(i / props.blockSize)\n const data = blocks.get(b)\n if (Array.isArray(data)) {\n const row = data[i - b * props.blockSize]\n if (row) return { kind: 'data', id: rowIdOf(row, i), data: row, level: 0, sourceIndex: i }\n }\n return { kind: 'loading', id: `__loading_${i}`, data: null, level: 0 }\n }\n\n // ---------- column layout ----------\n const titleOf = (id: string) => {\n const c = viewCols.value.find((x) => colIdOf(x) === id) ?? baseCols.value.find((x) => colIdOf(x) === id)\n return c?.headerName ?? (c?.field ? c.field.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, (s) => s.toUpperCase()) : id)\n }\n const groupColDef = computed<ColumnDef>(() => ({ colId: '__group', headerName: props.treeData ? 'Name' : 'Group', width: 240, sortable: false, filter: false, suppressMenu: true, lockPosition: true, ...props.groupColumn }))\n const orderedCols = computed(() => {\n const cols = viewCols.value\n const byId = new Map(cols.map((c) => [colIdOf(c), c]))\n const ordered = pivot.value ? cols : [...colOrder.value.map((id) => byId.get(id)).filter(Boolean) as ColumnDef[], ...cols.filter((c) => !colOrder.value.includes(colIdOf(c)))]\n const auto: ColumnDef[] = []\n if (props.rowSelection === 'multiple' && props.selectionColumn) auto.push(SELECT_COL)\n if (groups.value || (props.masterDetail && !props.treeData)) auto.push(groupColDef.value)\n return { auto, ordered }\n })\n const visibleCols = computed(() => {\n const { auto, ordered } = orderedCols.value\n const list = [\n ...auto.map((c) => ({ id: colIdOf(c), col: c, auto: true })),\n ...ordered.filter((c) => !(colHidden.value[colIdOf(c)] ?? c.hide)).map((c) => ({ id: colIdOf(c), col: c, auto: false })),\n ]\n const resolved = list.map((x) => ({\n ...x,\n pinned: x.auto ? ('left' as const) : colPinned.value[x.id] !== undefined ? colPinned.value[x.id] : x.col.pinned ?? null,\n width: colWidth.value[x.id] ?? x.col.width ?? (x.col.flex ? 0 : 150),\n title: x.id === '__group' ? (x.col.headerName as string) : titleOf(x.id),\n }))\n // pinned-left auto columns only when something else is pinned left, else keep them first in the centre\n const anyLeft = resolved.some((r) => !r.auto && r.pinned === 'left')\n if (!anyLeft) resolved.forEach((r) => { if (r.auto) r.pinned = null })\n // flex distribution\n const fixed = resolved.reduce((s, r) => s + (r.col.flex && colWidth.value[r.id] == null ? 0 : r.width), 0)\n const flexCols = resolved.filter((r) => r.col.flex && colWidth.value[r.id] == null)\n const totalFlex = flexCols.reduce((s, r) => s + (r.col.flex ?? 0), 0)\n const avail = Math.max(0, vpWidth.value - fixed - 2)\n for (const r of flexCols) r.width = clamp(Math.floor((avail * (r.col.flex ?? 1)) / totalFlex), r.col.minWidth ?? 80, r.col.maxWidth ?? 4000)\n const left = resolved.filter((r) => r.pinned === 'left')\n const right = resolved.filter((r) => r.pinned === 'right')\n const center = resolved.filter((r) => !r.pinned)\n return { left, center, right }\n })\n const flatCols = computed(() => [...visibleCols.value.left, ...visibleCols.value.center, ...visibleCols.value.right])\n const flatIndex = computed(() => new Map(flatCols.value.map((c, i) => [c.id, i])))\n const leftWidth = computed(() => visibleCols.value.left.reduce((s, c) => s + c.width, 0))\n const rightWidth = computed(() => visibleCols.value.right.reduce((s, c) => s + c.width, 0))\n const centerOffsets = computed(() => {\n const o = [0]\n for (const c of visibleCols.value.center) o.push(o[o.length - 1] + c.width)\n return o\n })\n const totalWidth = computed(() => leftWidth.value + rightWidth.value + centerOffsets.value[centerOffsets.value.length - 1])\n\n const renderCols = computed<RCol[]>(() => {\n const { left, center, right } = visibleCols.value\n const out: RCol[] = []\n let acc = 0\n left.forEach((c, i) => {\n out.push({ key: c.id, id: c.id, col: c.col, title: c.title, width: c.width, pinned: 'left', auto: c.auto, flatIndex: flatIndex.value.get(c.id)!, edgeLeft: i === left.length - 1, style: { width: `${c.width}px`, left: `${acc}px` } })\n acc += c.width\n })\n // centre column virtualization\n const offs = centerOffsets.value\n const viewW = Math.max(0, vpWidth.value - leftWidth.value - rightWidth.value)\n let start = 0\n while (start < center.length && offs[start + 1] < scrollLeft.value) start++\n let end = start\n while (end < center.length && offs[end] < scrollLeft.value + viewW) end++\n start = Math.max(0, start - 2)\n end = Math.min(center.length, end + 2)\n if (offs[start] > 0) out.push({ key: '__padL', id: '__padL', col: null, title: '', width: offs[start], pinned: null, flatIndex: -1, style: { width: `${offs[start]}px` } })\n for (let i = start; i < end; i++) {\n const c = center[i]\n out.push({ key: c.id, id: c.id, col: c.col, title: c.title, width: c.width, pinned: null, auto: c.auto, flatIndex: flatIndex.value.get(c.id)!, style: { width: `${c.width}px` } })\n }\n const padR = offs[center.length] - offs[end]\n if (padR > 0) out.push({ key: '__padR', id: '__padR', col: null, title: '', width: padR, pinned: null, flatIndex: -1, style: { width: `${padR}px` } })\n let racc = 0\n for (let i = right.length - 1; i >= 0; i--) {\n const c = right[i]\n out.push({ key: c.id, id: c.id, col: c.col, title: c.title, width: c.width, pinned: 'right', auto: c.auto, flatIndex: flatIndex.value.get(c.id)!, edgeRight: i === 0, style: { width: `${c.width}px`, right: `${racc}px` } })\n racc += c.width\n }\n // right pinned were pushed in reverse; restore visual order\n const rightPart = out.splice(out.length - right.length, right.length).reverse()\n return [...out, ...rightPart]\n })\n\n const hasHeaderGroups = computed(() => flatCols.value.some((c) => c.col.group))\n const headerGroups = computed(() => {\n type HG = { key: string; label: string; pin: 'left' | 'right' | null; width: number; style: Record<string, string>; cls: Record<string, boolean> }\n const out: HG[] = []\n for (const rc of renderCols.value) {\n const label = rc.col?.group ?? ''\n const last = out[out.length - 1]\n if (last && label && rc.col && last.label === label && last.pin === rc.pinned) {\n last.width += rc.width\n last.style.width = `${last.width}px`\n continue\n }\n const style: Record<string, string> = { width: `${rc.width}px` }\n if (rc.pinned === 'left') style.left = rc.style.left\n if (rc.pinned === 'right') style.right = rc.style.right\n out.push({\n key: `${rc.key}-g`, label: rc.col ? label : '', pin: rc.pinned, width: rc.width, style,\n cls: { 'sq-datagrid__hcell--pinned-left': rc.pinned === 'left', 'sq-datagrid__hcell--pinned-right': rc.pinned === 'right', 'sq-datagrid__header-group--empty': !label },\n })\n }\n // a right-pinned group's sticky offset is its rightmost member's offset\n return out\n })\n\n // ---------- row virtualization ----------\n const filterRowHeight = 38\n const headBlock = computed(() => props.headerHeight * (hasHeaderGroups.value ? 2 : 1) + (props.floatingFilters ? filterRowHeight : 0) + props.pinnedTopRows.length * props.rowHeight)\n const layout = computed(() => {\n if (isServer.value) {\n const n = serverCount.value\n return { offsets: null as Float64Array | null, total: n * props.rowHeight, indexAt: (y: number) => Math.floor(y / props.rowHeight) }\n }\n return rowLayout(paged.value, props.rowHeight, props.detailHeight)\n })\n const range = computed(() => {\n const n = rowCount.value\n if (!n) return { start: 0, end: -1 }\n const top = Math.max(0, scrollTop.value)\n const start = Math.max(0, layout.value.indexAt(top) - 6)\n const end = Math.min(n - 1, layout.value.indexAt(top + vpHeight.value) + 6)\n return { start, end }\n })\n const visibleRows = computed<VRow[]>(() => {\n const out: VRow[] = []\n const { start, end } = range.value\n const offs = layout.value.offsets\n for (let i = start; i <= end; i++) {\n const row = rowAt(i)\n if (!row) continue\n const top = offs ? offs[i] : i * props.rowHeight\n const height = offs ? offs[i + 1] - offs[i] : props.rowHeight\n out.push({ index: i, top, height, row })\n }\n return out\n })\n watch(range, (r) => {\n if (!isServer.value || r.end < 0) return\n for (let b = Math.floor(r.start / props.blockSize); b <= Math.floor(r.end / props.blockSize); b++) loadBlock(b)\n })\n\n // Scroll events already fire at most once per frame and Vue batches the re-render, so no rAF throttle\n // (rAF also stalls in background tabs, which would leave stale rows).\n const onScroll = () => {\n const el = viewport.value\n if (!el) return\n scrollTop.value = el.scrollTop\n scrollLeft.value = el.scrollLeft\n }\n let ro: ResizeObserver | undefined\n onMounted(() => {\n const el = viewport.value!\n const measure = () => { vpWidth.value = el.clientWidth; vpHeight.value = el.clientHeight }\n measure()\n if (typeof ResizeObserver !== 'undefined') { ro = new ResizeObserver(measure); ro.observe(el) }\n })\n onBeforeUnmount(() => { ro?.disconnect(); clearTimeout(quickTimer); clearTimeout(quickApplyTimer); window.removeEventListener('pointermove', onResizeMove); window.removeEventListener('pointerup', onResizeEnd); window.removeEventListener('mouseup', endSelect) })\n\n // ---------- values & formatting ----------\n const getters = new WeakMap<ColumnDef, (row: RowData) => CellValue>()\n const cellValue = (rc: { col: ColumnDef | null }, row: RowData | null) => {\n if (!rc.col || !row) return undefined\n let g = getters.get(rc.col)\n if (!g) getters.set(rc.col, (g = makeGetter(rc.col)))\n return g(row)\n }\n let numFmt: Intl.NumberFormat | null = null\n let numFmtLocale = ''\n const fmtNum = (v: number) => {\n if (numFmtLocale !== loc.value) { numFmt = new Intl.NumberFormat(loc.value, { maximumFractionDigits: 2 }); numFmtLocale = loc.value }\n return numFmt!.format(v)\n }\n const formatValue = (col: ColumnDef, v: CellValue, row: RowData | null) => {\n if (col.valueFormatter) return col.valueFormatter(v, row as RowData)\n if (v == null || v === '') return ''\n if (col.type === 'number' && typeof v === 'number') return fmtNum(v)\n if (col.type === 'date') return formatDate(v as string, loc.value)\n return String(v)\n }\n const formatCell = (rc: RCol, row: RowData | null) => (rc.col ? formatValue(rc.col, cellValue(rc, row), row) : '')\n const cellParams = (row: RowData | null, rc: RCol, rowIndex: number) => ({ value: cellValue(rc, row), formatted: formatCell(rc, row), row, column: rc.col, rowIndex })\n const groupLabel = (row: DisplayRow) => {\n if (row.kind === 'group') {\n const g = row.group!\n if (g.colId === '__tree') return String(g.key ?? '')\n const col = viewCols.value.find((c) => colIdOf(c) === g.colId)\n return col ? formatValue(col, g.key, null) || '(Blank)' : String(g.key ?? '')\n }\n if (props.treeData && props.getDataPath && row.data) {\n const p = props.getDataPath(row.data)\n return p[p.length - 1]\n }\n return ''\n }\n const groupAggText = (row: DisplayRow, rc: RCol) => {\n if (!rc.col) return ''\n const v = row.group?.agg[rc.id]\n if (v === undefined) return row.data && props.treeData ? formatCell(rc, row.data) : ''\n return formatValue(rc.col, v, null)\n }\n const filterKind = (col: ColumnDef) => filterKindOf(col)\n const distinctValues = (id: string) => {\n const col = baseCols.value.find((c) => colIdOf(c) === id)\n if (!col) return []\n const get = makeGetter(col)\n const set = new Set<CellValue>()\n for (const r of raw.value) {\n set.add(get(r))\n if (set.size > 5000) break\n }\n return Array.from(set).sort((a, b) => String(a ?? '').localeCompare(String(b ?? ''), undefined, { numeric: true }))\n }\n\n // ---------- sorting / filtering / grouping ----------\n const sortIndex = (id: string) => sortModelList.value.findIndex((s) => s.colId === id)\n const sortDir = (id: string) => sortModelList.value.find((s) => s.colId === id)?.sort\n const ariaSort = (id: string) => (sortDir(id) === 'asc' ? 'ascending' : sortDir(id) === 'desc' ? 'descending' : 'none')\n const setSort = (id: string, dir: 'asc' | 'desc' | null, multi = false) => {\n const rest = multi ? sortModelList.value.filter((s) => s.colId !== id) : []\n sortModelRef.value = dir ? [...rest, { colId: id, sort: dir }] : rest\n }\n let resized = false\n const onHeaderClick = (e: MouseEvent, rc: RCol) => {\n if (resized) return void (resized = false)\n if (!rc.col || rc.auto || rc.col.sortable === false) return\n const cur = sortDir(rc.id)\n const next = cur === 'asc' ? 'desc' : cur === 'desc' ? null : 'asc'\n if (e.shiftKey) {\n const list = sortModelList.value.slice()\n const i = list.findIndex((s) => s.colId === rc.id)\n if (next && i >= 0) list[i] = { colId: rc.id, sort: next }\n else if (next) list.push({ colId: rc.id, sort: next })\n else list.splice(i, 1)\n sortModelRef.value = list\n } else setSort(rc.id, next)\n }\n const setFilter = (id: string, cond: FilterCondition | undefined) => {\n const next = { ...filterModelObj.value }\n if (cond) next[id] = cond\n else delete next[id]\n filterModelRef.value = next\n }\n const floatingValue = (id: string) => {\n const f = filterModelObj.value[id]\n return f && f.kind !== 'set' ? (f.value as string) ?? '' : ''\n }\n let floatTimer: ReturnType<typeof setTimeout> | undefined\n const onFloatingInput = (e: Event, rc: RCol) => {\n const value = (e.target as HTMLInputElement).value\n const kind = filterKind(rc.col!)\n clearTimeout(floatTimer)\n floatTimer = setTimeout(() => setFilter(rc.id, value === '' ? undefined : { kind, op: kind === 'text' ? 'contains' : 'equals', value: kind === 'number' ? Number(value) : value }), 180)\n }\n const toggleGroupBy = (id: string) => (groupByRef.value = groupBy.value.includes(id) ? groupBy.value.filter((x) => x !== id) : [...groupBy.value, id])\n const removeGroup = (id: string) => (groupByRef.value = groupBy.value.filter((x) => x !== id))\n const toggleGroup = (row: DisplayRow) => {\n if (expandAllFlag.value) {\n const s = new Set(collapsed.value)\n s.has(row.id) ? s.delete(row.id) : s.add(row.id)\n collapsed.value = s\n } else {\n const s = new Set(expanded.value)\n s.has(row.id) ? s.delete(row.id) : s.add(row.id)\n expanded.value = s\n }\n }\n const expandAll = () => { expandAllFlag.value = true; collapsed.value = new Set() }\n const collapseAll = () => { expandAllFlag.value = false; expanded.value = new Set() }\n const toggleDetail = (id: string) => {\n const s = new Set(detailOpen.value)\n s.has(id) ? s.delete(id) : s.add(id)\n detailOpen.value = s\n }\n\n // ---------- column state ops ----------\n const emitColumnState = () => emit('column-state-change', flatCols.value.filter((c) => !c.auto).map((c) => ({ colId: c.id, width: c.width, hide: false, pinned: c.pinned })))\n const setHidden = (id: string, hide: boolean) => { colHidden.value = { ...colHidden.value, [id]: hide }; emitColumnState() }\n const setPinned = (id: string, pin: 'left' | 'right' | null) => { colPinned.value = { ...colPinned.value, [id]: pin }; emitColumnState() }\n const chooserCols = computed(() => orderedCols.value.ordered.map((c) => ({ id: colIdOf(c), title: titleOf(colIdOf(c)), hidden: colHidden.value[colIdOf(c)] ?? !!c.hide })))\n\n let resizeState: { id: string; startX: number; startW: number; min: number; max: number } | null = null\n const onResizeMove = (e: PointerEvent) => {\n if (!resizeState) return\n const w = clamp(resizeState.startW + e.clientX - resizeState.startX, resizeState.min, resizeState.max)\n colWidth.value = { ...colWidth.value, [resizeState.id]: Math.round(w) }\n }\n const onResizeEnd = () => {\n if (resizeState) { resized = true; setTimeout(() => (resized = false), 0); emitColumnState() }\n resizeState = null\n window.removeEventListener('pointermove', onResizeMove)\n window.removeEventListener('pointerup', onResizeEnd)\n }\n const startResize = (e: PointerEvent, rc: RCol) => {\n resizeState = { id: rc.id, startX: e.clientX, startW: rc.width, min: rc.col?.minWidth ?? 48, max: rc.col?.maxWidth ?? 2000 }\n window.addEventListener('pointermove', onResizeMove)\n window.addEventListener('pointerup', onResizeEnd)\n }\n let canvas: HTMLCanvasElement | null = null\n const autoSize = (ids?: string[]) => {\n canvas ??= document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx || !viewport.value) return\n const cs = getComputedStyle(viewport.value)\n ctx.font = `${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`\n const sample = isServer.value ? [] : paged.value.filter((r) => r.kind === 'data').slice(0, 300)\n const next = { ...colWidth.value }\n for (const c of flatCols.value) {\n if (c.auto || (ids && !ids.includes(c.id))) continue\n let w = ctx.measureText(c.title).width + 64\n for (const r of sample) w = Math.max(w, ctx.measureText(formatValue(c.col, cellValue(c, r.data), r.data)).width + 32)\n next[c.id] = Math.ceil(clamp(w, c.col.minWidth ?? 48, c.col.maxWidth ?? 600))\n }\n colWidth.value = next\n emitColumnState()\n }\n const dragColId = ref<string | null>(null)\n const dropTarget = ref<{ id: string; before: boolean } | null>(null)\n const onDragStart = (e: DragEvent, rc: RCol) => {\n if (!rc.col || rc.auto || rc.col.lockPosition) return e.preventDefault()\n dragColId.value = rc.id\n e.dataTransfer?.setData('text/plain', rc.id)\n if (e.dataTransfer) e.dataTransfer.effectAllowed = 'move'\n }\n const onDragOver = (e: DragEvent, rc: RCol) => {\n if (!dragColId.value || !rc.col || rc.auto) return\n dropTarget.value = { id: rc.id, before: e.offsetX < rc.width / 2 }\n }\n const onDrop = (rc: RCol) => {\n const from = dragColId.value\n const target = dropTarget.value\n dragColId.value = null\n dropTarget.value = null\n if (!from || !target || from === target.id || !rc.col || rc.auto) return\n const order = colOrder.value.filter((id) => id !== from)\n const i = order.indexOf(target.id)\n order.splice(target.before ? i : i + 1, 0, from)\n colOrder.value = order\n const pin = visibleCols.value.left.some((c) => c.id === target.id) ? 'left' : visibleCols.value.right.some((c) => c.id === target.id) ? 'right' : null\n colPinned.value = { ...colPinned.value, [from]: pin }\n emitColumnState()\n }\n const onGroupDrop = () => {\n const id = dragColId.value\n dragColId.value = null\n if (id && !groupBy.value.includes(id)) groupByRef.value = [...groupBy.value, id]\n }\n\n // ---------- selection ----------\n const dataIdsInView = () => (isServer.value ? [] : viewIdx.value.map((i) => rowIdOf(viewRows.value[i], i)))\n const setSelected = (ids: string[]) => {\n selectedRef.value = ids\n emit('selection-change', ids)\n }\n const allSelected = computed(() => {\n const ids = filteredIdx.value\n return ids.length > 0 && selectedIds.value.length >= ids.length && ids.every((i) => selectedSet.value.has(rowIdOf(raw.value[i], i)))\n })\n const someSelected = computed(() => !allSelected.value && selectedIds.value.length > 0)\n const toggleAll = () => setSelected(allSelected.value ? [] : dataIdsInView())\n const isRowChecked = (row: DisplayRow) => (row.kind === 'group' ? row.group!.leafIds.every((id) => selectedSet.value.has(id)) : selectedSet.value.has(row.id))\n const isRowPartial = (row: DisplayRow) => row.kind === 'group' && !isRowChecked(row) && row.group!.leafIds.some((id) => selectedSet.value.has(id))\n const toggleRowCheck = (row: DisplayRow) => {\n const ids = row.kind === 'group' ? row.group!.leafIds : [row.id]\n const on = isRowChecked(row)\n const s = new Set(selectedIds.value)\n ids.forEach((id) => (on ? s.delete(id) : s.add(id)))\n setSelected(Array.from(s))\n }\n let lastClicked = -1\n const onRowClick = (e: MouseEvent, vr: VRow) => {\n if (vr.row.kind !== 'data') return\n emit('row-click', { row: vr.row.data, event: e })\n if (!props.rowSelection) return\n if (props.rowSelection === 'single') setSelected(selectedSet.value.has(vr.row.id) && (e.ctrlKey || e.metaKey) ? [] : [vr.row.id])\n else if (e.shiftKey && lastClicked >= 0) {\n const [a, b] = [Math.min(lastClicked, vr.index), Math.max(lastClicked, vr.index)]\n const ids = new Set(selectedIds.value)\n for (let i = a; i <= b; i++) { const r = rowAt(i); if (r?.kind === 'data') ids.add(r.id) }\n setSelected(Array.from(ids))\n } else if (e.ctrlKey || e.metaKey) toggleRowCheck(vr.row)\n else if (!props.selectionColumn) setSelected([vr.row.id])\n lastClicked = vr.index\n }\n\n // ---------- focus, range, editing ----------\n const focus = ref<{ row: number; col: number } | null>(null)\n const cellRange = ref<CellRange | null>(null)\n let anchor: { row: number; col: number } | null = null\n let selecting = false\n const endSelect = () => { selecting = false; window.removeEventListener('mouseup', endSelect) }\n const setRange = (a: { row: number; col: number }, b: { row: number; col: number }) =>\n (cellRange.value = { startRow: Math.min(a.row, b.row), endRow: Math.max(a.row, b.row), startCol: Math.min(a.col, b.col), endCol: Math.max(a.col, b.col) })\n const inRange = (row: number, col: number) => {\n const r = cellRange.value\n return !!r && (r.startRow !== r.endRow || r.startCol !== r.endCol) && row >= r.startRow && row <= r.endRow && col >= r.startCol && col <= r.endCol\n }\n const onCellMousedown = (e: MouseEvent, vr: VRow, rc: RCol) => {\n if (!rc.col || e.button !== 0) return\n const pos = { row: vr.index, col: rc.flatIndex }\n if (editing.value && !isEditing(vr, rc)) commitEdit()\n if (e.shiftKey && focus.value) setRange(focus.value, pos)\n else { focus.value = pos; anchor = pos; setRange(pos, pos) }\n selecting = true\n window.addEventListener('mouseup', endSelect)\n emit('cell-click', { row: vr.row.data, colId: rc.id, value: cellValue(rc, vr.row.data), event: e })\n }\n const onCellEnter = (vr: VRow, rc: RCol) => { if (selecting && anchor && rc.col) setRange(anchor, { row: vr.index, col: rc.flatIndex }) }\n\n const editing = ref<{ row: number; colId: string; value: CellValue } | null>(null)\n const isEditable = (col: ColumnDef, row: RowData | null) => !!row && (typeof col.editable === 'function' ? col.editable(row) : !!col.editable)\n const isEditing = (vr: VRow, rc: RCol) => !!editing.value && editing.value.row === vr.index && editing.value.colId === rc.id\n const editorKind = (rc: RCol) => rc.col?.cellEditor ?? (rc.col?.type === 'number' ? 'number' : rc.col?.type === 'date' ? 'date' : 'text')\n const undoStack: Change[][] = []\n const redoStack: Change[][] = []\n const canUndo = ref(false)\n const applyChanges = (changes: Change[], dir: 'new' | 'old') => {\n for (const c of changes) {\n const v = dir === 'new' ? c.newValue : c.oldValue\n if (c.col.valueSetter) c.col.valueSetter(c.row, v)\n else if (c.col.field) setByPath(c.row, c.col.field, v)\n emit('cell-value-changed', { row: c.row, colId: colIdOf(c.col), oldValue: dir === 'new' ? c.oldValue : c.newValue, newValue: v })\n }\n dataVersion.value++\n }\n const record = (changes: Change[]) => {\n if (!changes.length) return\n applyChanges(changes, 'new')\n undoStack.push(changes)\n if (undoStack.length > 100) undoStack.shift()\n redoStack.length = 0\n canUndo.value = true\n }\n const undo = () => { const c = undoStack.pop(); if (c) { applyChanges(c, 'old'); redoStack.push(c) } canUndo.value = undoStack.length > 0 }\n const redo = () => { const c = redoStack.pop(); if (c) { applyChanges(c, 'new'); undoStack.push(c) } canUndo.value = undoStack.length > 0 }\n const parseFor = (col: ColumnDef, text: string, row: RowData): CellValue => {\n if (col.valueParser) return col.valueParser(text, row)\n if (col.type === 'number') return text === '' ? null : Number(text.replace(/[^\\d.-]/g, ''))\n if (col.type === 'boolean') return /^(true|1|yes|✓)$/i.test(text)\n return text\n }\n const startEdit = (rowIndex: number, flatCol: number, initial?: string) => {\n const c = flatCols.value[flatCol]\n const r = rowAt(rowIndex)\n if (!c || !r || r.kind !== 'data' || !isEditable(c.col, r.data)) return\n if (c.col.type === 'boolean') return record([{ row: r.data!, col: c.col, oldValue: cellValue(c, r.data), newValue: !cellValue(c, r.data) }])\n editing.value = { row: rowIndex, colId: c.id, value: initial ?? (cellValue(c, r.data) as CellValue) }\n nextTick(() => {\n const el = viewport.value?.querySelector<HTMLInputElement>('.sq-datagrid__editor')\n el?.focus()\n if (initial === undefined) el?.select?.()\n })\n }\n const onEditorInput = (e: Event) => editing.value && (editing.value = { ...editing.value, value: (e.target as HTMLInputElement).value })\n const commitEdit = () => {\n const ed = editing.value\n if (!ed) return\n editing.value = null\n const r = rowAt(ed.row)\n const c = flatCols.value.find((x) => x.id === ed.colId)\n if (!r?.data || !c) return\n const newValue = parseFor(c.col, String(ed.value ?? ''), r.data)\n const oldValue = cellValue(c, r.data)\n if (newValue !== oldValue) record([{ row: r.data, col: c.col, oldValue, newValue }])\n }\n const cancelEdit = () => { editing.value = null; rootEl()?.focus() }\n const onEditorKey = (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === 'Tab') { e.preventDefault(); commitEdit(); rootEl()?.focus(); moveFocus(e.key === 'Enter' ? (e.shiftKey ? -1 : 1) : 0, e.key === 'Tab' ? (e.shiftKey ? -1 : 1) : 0, false) }\n else if (e.key === 'Escape') cancelEdit()\n }\n const onCellDblclick = (vr: VRow, rc: RCol) => rc.col && startEdit(vr.index, rc.flatIndex)\n\n const rootEl = () => viewport.value?.parentElement as HTMLElement | null\n const ensureVisible = (row: number, col: number) => {\n const el = viewport.value\n if (!el) return\n const offs = layout.value.offsets\n const top = offs ? offs[row] : row * props.rowHeight\n const h = offs ? offs[row + 1] - offs[row] : props.rowHeight\n const bodyTop = el.scrollTop\n const visibleH = el.clientHeight - headBlock.value\n if (top < bodyTop) el.scrollTop = top\n else if (top + h > bodyTop + visibleH) el.scrollTop = top + h - visibleH\n const c = flatCols.value[col]\n if (c && !c.pinned) {\n const ci = visibleCols.value.center.indexOf(c as (typeof visibleCols.value.center)[number])\n const x = centerOffsets.value[ci]\n const viewW = el.clientWidth - leftWidth.value - rightWidth.value\n if (x < el.scrollLeft) el.scrollLeft = x\n else if (x + c.width > el.scrollLeft + viewW) el.scrollLeft = x + c.width - viewW\n }\n }\n const moveFocus = (dr: number, dc: number, extend: boolean) => {\n const f = focus.value ?? { row: 0, col: 0 }\n const next = { row: clamp(f.row + dr, 0, Math.max(0, rowCount.value - 1)), col: clamp(f.col + dc, 0, Math.max(0, flatCols.value.length - 1)) }\n focus.value = next\n if (extend && anchor) setRange(anchor, next)\n else { anchor = next; setRange(next, next) }\n ensureVisible(next.row, next.col)\n }\n const rangeCells = () => {\n const r = cellRange.value ?? (focus.value ? { startRow: focus.value.row, endRow: focus.value.row, startCol: focus.value.col, endCol: focus.value.col } : null)\n return r\n }\n const copy = async (withHeaders = false) => {\n const r = rangeCells()\n let lines: string[][] = []\n let header: string[] = []\n if (props.rowSelection && selectedIds.value.length && (!r || (r.startRow === r.endRow && r.startCol === r.endCol))) {\n const cols = flatCols.value.filter((c) => !c.auto)\n header = cols.map((c) => c.title)\n const sel = selectedSet.value\n lines = viewIdx.value.filter((i) => sel.has(rowIdOf(viewRows.value[i], i))).map((i) => cols.map((c) => String(cellValue(c, viewRows.value[i]) ?? '')))\n } else if (r) {\n const cols = flatCols.value.slice(r.startCol, r.endCol + 1).filter((c) => !c.auto)\n header = cols.map((c) => c.title)\n for (let i = r.startRow; i <= r.endRow; i++) {\n const row = rowAt(i)\n if (row?.kind === 'data') lines.push(cols.map((c) => String(cellValue(c, row.data) ?? '')))\n }\n }\n const text = [...(withHeaders ? [header] : []), ...lines].map((l) => l.join('\\t')).join('\\n')\n try { await navigator.clipboard.writeText(text) } catch { /* clipboard unavailable (insecure context) */ }\n return text\n }\n const onPaste = (e: ClipboardEvent) => {\n if (editing.value || !focus.value) return\n const text = e.clipboardData?.getData('text/plain')\n if (!text) return\n e.preventDefault()\n const grid = parseTsv(text)\n const changes: Change[] = []\n grid.forEach((line, dr) => line.forEach((cellText, dc) => {\n const row = rowAt(focus.value!.row + dr)\n const c = flatCols.value[focus.value!.col + dc]\n if (row?.kind === 'data' && c && !c.auto && isEditable(c.col, row.data)) changes.push({ row: row.data!, col: c.col, oldValue: cellValue(c, row.data), newValue: parseFor(c.col, cellText, row.data!) })\n }))\n record(changes)\n }\n const clearRange = () => {\n const r = rangeCells()\n if (!r) return\n const changes: Change[] = []\n for (let i = r.startRow; i <= r.endRow; i++)\n for (let j = r.startCol; j <= r.endCol; j++) {\n const row = rowAt(i)\n const c = flatCols.value[j]\n if (row?.kind === 'data' && c && !c.auto && isEditable(c.col, row.data)) changes.push({ row: row.data!, col: c.col, oldValue: cellValue(c, row.data), newValue: c.col.type === 'number' ? null : '' })\n }\n record(changes)\n }\n const onKeydown = (e: KeyboardEvent) => {\n if (editing.value || (e.target as HTMLElement).closest('input, select, textarea, .sq-datagrid__toolbar')) return\n const mod = e.ctrlKey || e.metaKey\n const page = Math.max(1, Math.floor((vpHeight.value - headBlock.value) / props.rowHeight) - 1)\n const map: Record<string, [number, number]> = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1], PageUp: [-page, 0], PageDown: [page, 0] }\n if (map[e.key]) { e.preventDefault(); moveFocus(map[e.key][0], map[e.key][1], e.shiftKey) }\n else if (e.key === 'Home') { e.preventDefault(); moveFocus(mod ? -rowCount.value : 0, -flatCols.value.length, e.shiftKey) }\n else if (e.key === 'End') { e.preventDefault(); moveFocus(mod ? rowCount.value : 0, flatCols.value.length, e.shiftKey) }\n else if (e.key === 'Tab' && focus.value) { e.preventDefault(); moveFocus(0, e.shiftKey ? -1 : 1, false) }\n else if ((e.key === 'Enter' || e.key === 'F2') && focus.value) { e.preventDefault(); const r = rowAt(focus.value.row); r?.kind === 'group' ? toggleGroup(r) : startEdit(focus.value.row, focus.value.col) }\n else if (e.key === ' ' && focus.value && props.rowSelection) { e.preventDefault(); const r = rowAt(focus.value.row); if (r && r.kind !== 'loading' && r.kind !== 'detail') toggleRowCheck(r) }\n else if (mod && e.key.toLowerCase() === 'c') { e.preventDefault(); copy(e.shiftKey) }\n else if (mod && e.key.toLowerCase() === 'a') { e.preventDefault(); if (props.rowSelection === 'multiple') setSelected(dataIdsInView()); else cellRange.value = { startRow: 0, endRow: rowCount.value - 1, startCol: 0, endCol: flatCols.value.length - 1 } }\n else if (mod && e.key.toLowerCase() === 'z') { e.preventDefault(); e.shiftKey ? redo() : undo() }\n else if (mod && e.key.toLowerCase() === 'y') { e.preventDefault(); redo() }\n else if (e.key === 'Delete' || e.key === 'Backspace') { e.preventDefault(); clearRange() }\n else if (e.key.length === 1 && !mod && focus.value) startEdit(focus.value.row, focus.value.col, e.key)\n }\n\n // ---------- menus ----------\n const menuOpen = ref(false)\n const menuAnchor = ref<HTMLElement | null>(null)\n const menuColId = ref<string | null>(null)\n const menuMode = ref<'column' | 'context'>('column')\n const ctxPos = ref({ x: 0, y: 0 })\n const menuCol = computed(() => (menuColId.value ? flatCols.value.find((c) => c.id === menuColId.value) ?? null : null))\n const menuFormatter = (v: CellValue) => (menuCol.value ? formatValue(menuCol.value.col, v, null) : String(v ?? ''))\n const openMenu = (e: MouseEvent, id: string) => {\n menuMode.value = 'column'\n menuColId.value = id\n menuAnchor.value = e.currentTarget as HTMLElement\n menuOpen.value = true\n }\n const openContext = (e: MouseEvent, vr: VRow, rc: RCol) => {\n if (!rc.col) return\n if (!inRange(vr.index, rc.flatIndex)) { const p = { row: vr.index, col: rc.flatIndex }; focus.value = p; anchor = p; setRange(p, p) }\n const rect = rootEl()!.getBoundingClientRect()\n ctxPos.value = { x: e.clientX - rect.left, y: e.clientY - rect.top }\n menuMode.value = 'context'\n menuColId.value = rc.id\n menuAnchor.value = ctxAnchor.value\n menuOpen.value = true\n }\n\n // ---------- export ----------\n const exportCsv = (opts: { fileName?: string; onlySelected?: boolean; separator?: string } = {}) => {\n const cols = flatCols.value.filter((c) => !c.auto)\n const sel = selectedSet.value\n const idx = isServer.value ? [] : viewIdx.value.filter((i) => !opts.onlySelected || sel.has(rowIdOf(viewRows.value[i], i)))\n const body = idx.map((i) => cols.map((c) => formatValue(c.col, cellValue(c, viewRows.value[i]), viewRows.value[i])))\n const csv = toCsv(cols.map((c) => c.title), body, opts.separator)\n downloadText(opts.fileName ?? 'export.csv', '' + csv, 'text/csv;charset=utf-8')\n return csv\n }\n\n // ---------- totals / status ----------\n const bottomRows = computed(() => {\n const extra: RowData[] = []\n if (props.totalsRow && !isServer.value) {\n const r: RowData = {}\n for (const c of viewCols.value) if (c.aggFunc) {\n const get = makeGetter(c)\n const v = aggregate(viewIdx.value.map((i) => get(viewRows.value[i])), c.aggFunc)\n if (c.field) setByPath(r, c.field, v)\n else r[colIdOf(c)] = v\n }\n extra.push(r)\n }\n return [...props.pinnedBottomRows, ...extra]\n })\n const statusText = computed(() => {\n if (isServer.value) return `${serverCount.value.toLocaleString(loc.value)} rows`\n const total = raw.value.length\n const shown = filteredIdx.value.length\n return shown === total ? `${total.toLocaleString(loc.value)} rows` : `${shown.toLocaleString(loc.value)} of ${total.toLocaleString(loc.value)} rows`\n })\n const rangeStats = computed(() => {\n const r = cellRange.value\n if (!r || (r.startRow === r.endRow && r.startCol === r.endCol)) return null\n const nums: number[] = []\n let count = 0\n const maxCells = 200_000\n for (let i = r.startRow; i <= r.endRow && count < maxCells; i++) {\n const row = rowAt(i)\n if (row?.kind !== 'data') continue\n for (let j = r.startCol; j <= r.endCol; j++) {\n const c = flatCols.value[j]\n if (!c || c.auto) continue\n const v = cellValue(c, row.data)\n if (v != null && v !== '') count++\n if (typeof v === 'number') nums.push(v)\n }\n }\n if (!nums.length) return { count, sum: 0, avg: 0, min: 0, max: 0 }\n const sum = nums.reduce((a, b) => a + b, 0)\n return { count, sum, avg: sum / nums.length, min: Math.min(...nums), max: Math.max(...nums) }\n })\n\n // ---------- classes ----------\n const headerCellClass = (rc: RCol) => ({\n 'sq-datagrid__hcell--pinned-left': rc.pinned === 'left',\n 'sq-datagrid__hcell--pinned-right': rc.pinned === 'right',\n 'sq-datagrid__hcell--edge-left': rc.edgeLeft,\n 'sq-datagrid__hcell--edge-right': rc.edgeRight,\n 'sq-datagrid__hcell--sortable': !!rc.col && !rc.auto && rc.col.sortable !== false,\n 'sq-datagrid__hcell--spacer': !rc.col,\n 'sq-datagrid__hcell--drop-before': dropTarget.value?.id === rc.id && dropTarget.value.before,\n 'sq-datagrid__hcell--drop-after': dropTarget.value?.id === rc.id && !dropTarget.value.before,\n [`sq-datagrid__align-${rc.col?.align ?? (rc.col?.type === 'number' ? 'right' : 'left')}`]: true,\n [rc.col?.headerClass ?? '']: !!rc.col?.headerClass,\n })\n const cellAlignClass = (rc: RCol) => ({\n 'sq-datagrid__cell--pinned-left': rc.pinned === 'left',\n 'sq-datagrid__cell--pinned-right': rc.pinned === 'right',\n 'sq-datagrid__cell--edge-left': !!rc.edgeLeft,\n 'sq-datagrid__cell--edge-right': !!rc.edgeRight,\n [`sq-datagrid__align-${rc.col?.align ?? (rc.col?.type === 'number' ? 'right' : rc.col?.type === 'boolean' ? 'center' : 'left')}`]: !!rc.col,\n })\n const cellClass = (vr: VRow, rc: RCol) => {\n const base: Record<string, boolean> = cellAlignClass(rc)\n if (!rc.col) return base\n base['sq-datagrid__cell--focused'] = !!focus.value && focus.value.row === vr.index && focus.value.col === rc.flatIndex\n base['sq-datagrid__cell--range'] = inRange(vr.index, rc.flatIndex)\n base['sq-datagrid__cell--editable'] = vr.row.kind === 'data' && isEditable(rc.col, vr.row.data)\n if (rc.col.cellClass && vr.row.kind === 'data') {\n const extra = typeof rc.col.cellClass === 'function' ? rc.col.cellClass({ value: cellValue(rc, vr.row.data), row: vr.row.data!, column: rc.col, rowIndex: vr.index }) : rc.col.cellClass\n if (extra) base[extra] = true\n }\n return base\n }\n const cellStyle = (vr: VRow, rc: RCol) => {\n if (!rc.col?.cellStyle || vr.row.kind !== 'data') return rc.style\n const extra = typeof rc.col.cellStyle === 'function' ? rc.col.cellStyle({ value: cellValue(rc, vr.row.data), row: vr.row.data!, column: rc.col, rowIndex: vr.index }) : rc.col.cellStyle\n return extra ? { ...rc.style, ...extra } : rc.style\n }\n const rowClass = (vr: VRow) => {\n const c: Record<string, boolean> = {\n 'sq-datagrid__row--group': vr.row.kind === 'group',\n 'sq-datagrid__row--detail': vr.row.kind === 'detail',\n 'sq-datagrid__row--selected': vr.row.kind === 'data' && selectedSet.value.has(vr.row.id),\n 'sq-datagrid__row--odd': vr.index % 2 === 1,\n }\n if (props.rowClassName && vr.row.data && vr.row.kind === 'data') { const x = props.rowClassName(vr.row.data); if (x) c[x] = true }\n return c\n }\n const showLoading = computed(() => props.loading || (isServer.value && serverLoading.value && serverCount.value === 0))\n const rootStyle = { '--sq-r': 'var(--sq-radius-xl)', '--sq-bg': 'var(--sq-surface)', '--sq-bd': 'var(--sq-border)', '--sq-bw': '1px', '--sq-grid-row-h': `${props.rowHeight}px` }\n\n const api = {\n getSelectedRows: () => (isServer.value ? [] : viewIdx.value.map((i) => viewRows.value[i]).filter((r, k) => selectedSet.value.has(rowIdOf(r, viewIdx.value[k])))),\n getDisplayedRows: () => display.value,\n selectAll: () => setSelected(dataIdsInView()),\n deselectAll: () => setSelected([]),\n exportCsv,\n copy,\n undo,\n redo,\n expandAll,\n collapseAll,\n autoSize,\n refresh: () => (isServer.value ? purge() : dataVersion.value++),\n ensureIndexVisible: (i: number) => ensureVisible(i, focus.value?.col ?? 0),\n getColumnState: () => flatCols.value.filter((c) => !c.auto).map((c) => ({ colId: c.id, width: c.width, hide: false, pinned: c.pinned })),\n setColumnState: (state: { colId: string; width?: number; hide?: boolean; pinned?: 'left' | 'right' | null }[]) => {\n colOrder.value = [...state.map((s) => s.colId), ...colOrder.value.filter((id) => !state.some((s) => s.colId === id))]\n colWidth.value = { ...colWidth.value, ...Object.fromEntries(state.filter((s) => s.width).map((s) => [s.colId, s.width!])) }\n colHidden.value = { ...colHidden.value, ...Object.fromEntries(state.filter((s) => s.hide !== undefined).map((s) => [s.colId, s.hide!])) }\n colPinned.value = { ...colPinned.value, ...Object.fromEntries(state.filter((s) => s.pinned !== undefined).map((s) => [s.colId, s.pinned!])) }\n },\n }\n\n return {\n ...api, api, viewport, ctxAnchor, scrollLeft, vpWidth, isServer, quick, groupBy, selectedIds, selectedSet, sortModelList, filterModelObj,\n renderCols, flatCols, totalWidth, hasHeaderGroups, headerGroups, layout, visibleRows, rowCount, filterRowHeight, page, pageSizeState, pageCount, onPageSize, pageRangeText,\n hasGroups, detailOpen, onScroll, cellValue, formatValue, formatCell, cellParams, groupLabel, groupAggText, filterKind, distinctValues, sortIndex, sortDir, ariaSort, setSort,\n onHeaderClick, setFilter, floatingValue, onFloatingInput, toggleGroupBy, removeGroup, toggleGroup, toggleDetail, setHidden, setPinned, chooserCols, startResize,\n dragColId, onDragStart, onDragOver, onDrop, onGroupDrop, allSelected, someSelected, toggleAll, isRowChecked, isRowPartial, toggleRowCheck, onRowClick,\n onCellMousedown, onCellEnter, editing, isEditing, editorKind, onEditorInput, commitEdit, onEditorKey, onCellDblclick, canUndo, onKeydown, onPaste,\n menuOpen, menuAnchor, menuMode, menuCol, menuFormatter, openMenu, openContext, ctxPos, bottomRows, statusText, rangeStats, fmtNum, headerCellClass, cellAlignClass, cellClass, cellStyle,\n rowClass, showLoading, rootStyle, titleOf, toUnit, getByPath, has: (n: string) => !!slots[n], messages: computed(() => config.locale.messages),\n }\n },\n})\n</script>\n\n<style>\n.sq-datagrid { display: flex; flex-direction: column; overflow: hidden; color: var(--sq-on-surface); font-size: var(--sq-text-sm); outline: none; min-width: 0; }\n.sq-datagrid:focus-visible { box-shadow: var(--sq-focus-ring); }\n.sq-datagrid__toolbar { display: flex; align-items: center; gap: var(--sq-space-2); padding: var(--sq-space-2) var(--sq-space-3); border-bottom: 1px solid var(--sq-border); }\n.sq-datagrid__quick { max-width: 280px; }\n.sq-datagrid__chooser { display: flex; flex-direction: column; padding: var(--sq-space-1) var(--sq-space-3); max-height: 340px; overflow: auto; }\n.sq-datagrid__group-panel { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sq-space-2); min-height: 42px; padding: var(--sq-space-1) var(--sq-space-3); border-bottom: 1px dashed var(--sq-border); color: var(--sq-muted); background: color-mix(in srgb, var(--sq-surface-variant) 50%, transparent); }\n.sq-datagrid__group-hint { font-size: var(--sq-text-xs); }\n.sq-datagrid__viewport { position: relative; overflow: auto; overscroll-behavior: contain; flex: 1 1 auto; }\n.sq-datagrid__canvas { position: relative; min-width: 100%; }\n.sq-datagrid__head { position: sticky; top: 0; z-index: 4; background: var(--sq-surface-variant); }\n.sq-datagrid__foot { position: sticky; bottom: 0; z-index: 4; background: var(--sq-surface-variant); border-top: 1px solid var(--sq-border-strong); }\n.sq-datagrid__header-row { display: flex; border-bottom: 1px solid var(--sq-border); }\n.sq-datagrid__hcell, .sq-datagrid__header-group {\n position: relative; display: flex; align-items: center; gap: 4px; flex: none; padding: 0 var(--sq-space-3);\n font-size: var(--sq-text-xs); font-weight: var(--sq-weight-semibold); color: var(--sq-on-surface-variant); user-select: none; background: var(--sq-surface-variant); min-width: 0;\n}\n.sq-datagrid__header-group { justify-content: center; border-inline-end: 1px solid var(--sq-border); letter-spacing: 0.02em; }\n.sq-datagrid__header-group--empty { border-inline-end-color: transparent; }\n.sq-datagrid__hcell--sortable { cursor: pointer; }\n.sq-datagrid__hcell--sortable:hover { color: var(--sq-on-surface); }\n.sq-datagrid__htitle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.sq-datagrid__align-right { justify-content: flex-end; text-align: right; }\n.sq-datagrid__align-center { justify-content: center; text-align: center; }\n.sq-datagrid__hcell.sq-datagrid__align-right { flex-direction: row-reverse; }\n.sq-datagrid__sort { display: inline-flex; align-items: center; color: var(--sq-primary); }\n.sq-datagrid__sort sup { font-size: 9px; }\n.sq-datagrid__filtered { color: var(--sq-primary); }\n.sq-datagrid__menu-btn { display: flex; margin-inline-start: auto; padding: 2px; border: 0; background: none; color: inherit; border-radius: var(--sq-radius-xs); cursor: pointer; opacity: 0; transition: opacity var(--sq-duration-fast); }\n.sq-datagrid__align-right .sq-datagrid__menu-btn { margin-inline-start: 0; margin-inline-end: auto; }\n.sq-datagrid__hcell:hover .sq-datagrid__menu-btn, .sq-datagrid__menu-btn:focus-visible { opacity: 1; }\n.sq-datagrid__menu-btn:hover { background: color-mix(in srgb, var(--sq-on-surface) 10%, transparent); }\n.sq-datagrid__resizer { position: absolute; top: 20%; bottom: 20%; right: 0; width: 7px; cursor: col-resize; border-right: 2px solid transparent; z-index: 1; }\n.sq-datagrid__hcell:hover .sq-datagrid__resizer { border-right-color: var(--sq-border-strong); }\n.sq-datagrid__resizer:hover { border-right-color: var(--sq-primary) !important; }\n.sq-datagrid__hcell--drop-before { box-shadow: inset 3px 0 0 var(--sq-primary); }\n.sq-datagrid__hcell--drop-after { box-shadow: inset -3px 0 0 var(--sq-primary); }\n.sq-datagrid__fcell { padding: 0 6px; }\n.sq-datagrid__ffilter { --sq-r: var(--sq-radius-xs); width: 100%; height: 28px; padding: 0 8px; border: 1px solid var(--sq-border); background: var(--sq-surface); color: var(--sq-on-surface); font: inherit; font-size: var(--sq-text-xs); outline: none; }\n.sq-datagrid__ffilter:focus { border-color: var(--sq-primary); }\n.sq-datagrid__body { position: relative; }\n.sq-datagrid__row { position: absolute; top: 0; left: 0; display: flex; min-width: 100%; border-bottom: 1px solid var(--sq-border); background: var(--sq-surface); contain: layout style; }\n.sq-datagrid__row--pinned { position: relative; background: var(--sq-surface-variant); font-weight: var(--sq-weight-medium); }\n.sq-datagrid--striped .sq-datagrid__row--odd { background: color-mix(in srgb, var(--sq-surface-variant) 45%, var(--sq-surface)); }\n.sq-datagrid__row:hover { --sq-row-hover: color-mix(in srgb, var(--sq-primary) 5%, var(--sq-surface)); background: var(--sq-row-hover); }\n.sq-datagrid__row--selected, .sq-datagrid__row--selected:hover { background: color-mix(in srgb, var(--sq-primary) 11%, var(--sq-surface)) !important; }\n.sq-datagrid__row--group { font-weight: var(--sq-weight-semibold); background: color-mix(in srgb, var(--sq-surface-variant) 60%, var(--sq-surface)); }\n.sq-datagrid__cell { position: relative; display: flex; align-items: center; flex: none; min-width: 0; padding: 0 var(--sq-space-3); white-space: nowrap; overflow: hidden; background: inherit; outline: none; }\n.sq-datagrid--column-lines .sq-datagrid__cell, .sq-datagrid--column-lines .sq-datagrid__hcell { border-inline-end: 1px solid var(--sq-border); }\n.sq-datagrid__cell--pinned-left, .sq-datagrid__hcell--pinned-left { position: sticky; z-index: 2; }\n.sq-datagrid__cell--pinned-right, .sq-datagrid__hcell--pinned-right { position: sticky; z-index: 2; }\n.sq-datagrid--scrolled-x .sq-datagrid__cell--edge-left, .sq-datagrid--scrolled-x .sq-datagrid__hcell--edge-left { box-shadow: 6px 0 8px -6px rgb(16 18 35 / 0.25); }\n.sq-datagrid__cell--edge-right, .sq-datagrid__hcell--edge-right { box-shadow: -6px 0 8px -6px rgb(16 18 35 / 0.25); }\n.sq-datagrid__cell--range { background: color-mix(in srgb, var(--sq-primary) 14%, var(--sq-surface)) !important; }\n.sq-datagrid__cell--focused { box-shadow: inset 0 0 0 2px var(--sq-primary) !important; border-radius: var(--sq-radius-xs); }\n.sq-datagrid__text { overflow: hidden; text-overflow: ellipsis; }\n.sq-datagrid__bool { display: inline-flex; color: var(--sq-border-strong); }\n.sq-datagrid__bool--on { color: var(--sq-success); }\n.sq-datagrid__check { min-height: 0 !important; }\n.sq-datagrid__group-cell { display: flex; align-items: center; gap: 4px; min-width: 0; }\n.sq-datagrid__expander { display: flex; padding: 1px; border: 0; background: none; color: var(--sq-muted); border-radius: var(--sq-radius-xs); cursor: pointer; transition: transform var(--sq-duration) var(--sq-ease); }\n.sq-datagrid__expander:hover { background: color-mix(in srgb, var(--sq-on-surface) 8%, transparent); color: var(--sq-on-surface); }\n.sq-datagrid__expander--open { transform: rotate(90deg); }\n.sq-datagrid__expander-spacer { width: 20px; flex: none; }\n.sq-datagrid__group-key { overflow: hidden; text-overflow: ellipsis; }\n.sq-datagrid__group-count { padding: 0 7px; border-radius: var(--sq-radius-pill); background: color-mix(in srgb, var(--sq-primary) 14%, transparent); color: var(--sq-primary); font-size: var(--sq-text-2xs); font-weight: var(--sq-weight-bold); }\n.sq-datagrid__agg { color: var(--sq-on-surface-variant); font-variant-numeric: tabular-nums; }\n.sq-datagrid__align-right .sq-datagrid__text { font-variant-numeric: tabular-nums; }\n.sq-datagrid__editor-wrap { position: absolute; inset: 2px; display: flex; }\n.sq-datagrid__editor { width: 100%; height: 100%; padding: 0 8px; border: 2px solid var(--sq-primary); border-radius: var(--sq-radius-xs); background: var(--sq-surface); color: var(--sq-on-surface); font: inherit; outline: none; }\n.sq-datagrid__skeleton { position: relative; display: block; width: 70%; height: 10px; border-radius: var(--sq-radius-xs); }\n.sq-datagrid__detail { position: sticky; left: 0; height: 100%; padding: var(--sq-space-3) var(--sq-space-4); overflow: auto; background: color-mix(in srgb, var(--sq-surface-variant) 40%, var(--sq-surface)); }\n.sq-datagrid__overlay { position: absolute; inset: 0; z-index: 5; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--sq-surface) 55%, transparent); pointer-events: none; }\n.sq-datagrid__overlay--empty { background: none; }\n.sq-datagrid__footer { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sq-space-3); min-height: 40px; padding: 4px var(--sq-space-3); border-top: 1px solid var(--sq-border); color: var(--sq-muted); font-size: var(--sq-text-xs); }\n.sq-datagrid__status { display: flex; gap: var(--sq-space-2); flex-wrap: wrap; }\n.sq-datagrid__range-stats { color: var(--sq-on-surface-variant); font-variant-numeric: tabular-nums; }\n.sq-datagrid__page-size { display: inline-flex; align-items: center; gap: 6px; }\n.sq-datagrid__page-select { --sq-r: var(--sq-radius-xs); height: 26px; padding: 0 6px; border: 1px solid var(--sq-border); background: var(--sq-surface); color: var(--sq-on-surface); font: inherit; }\n.sq-datagrid__menu { min-width: 220px; padding: 2px 0; }\n.sq-datagrid__menu .sq-list-item { min-height: 34px; padding-block: 4px; font-size: var(--sq-text-sm); }\n.sq-datagrid__ctx-anchor { position: absolute; width: 1px; height: 1px; pointer-events: none; }\n</style>\n","import SqDataGrid from './SqDataGrid.vue'\n\nexport { SqDataGrid }\nexport const componentNames = ['SqDataGrid'] as const\nexport * from './types'\nexport * from './engine'\nexport default SqDataGrid\n"],"names":["v","_a","_c","_b","page"],"mappings":"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"}