@squirkle-ui/datagrid 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1842 @@
1
+ import { defineComponent, ref, computed, watch, toRaw, onMounted, onBeforeUnmount, nextTick } from "vue";
2
+ import { getByPath, compareValues, toDate, clamp, toUnit, formatDate, downloadText } from "@squirkle-ui/core";
3
+ import { SqVirtualScroll, SqTextField, SqSelect, SqCheckbox, SqBtn, config, SqProgressCircular, SqPagination, SqMenu, SqListItem, SqIcon, SqEmptyState, SqDivider, SqChip, SqShape, useProxiedModel } from "@squirkle-ui/ui/vue2";
4
+ const TEXT_OPS = [
5
+ { title: "Contains", value: "contains" },
6
+ { title: "Does not contain", value: "notContains" },
7
+ { title: "Equals", value: "equals" },
8
+ { title: "Not equal", value: "notEqual" },
9
+ { title: "Starts with", value: "startsWith" },
10
+ { title: "Ends with", value: "endsWith" },
11
+ { title: "Blank", value: "blank" },
12
+ { title: "Not blank", value: "notBlank" }
13
+ ];
14
+ const NUM_OPS = [
15
+ { title: "Equals", value: "equals" },
16
+ { title: "Not equal", value: "notEqual" },
17
+ { title: "Greater than", value: "gt" },
18
+ { title: "≥", value: "gte" },
19
+ { title: "Less than", value: "lt" },
20
+ { title: "≤", value: "lte" },
21
+ { title: "Between", value: "between" },
22
+ { title: "Blank", value: "blank" },
23
+ { title: "Not blank", value: "notBlank" }
24
+ ];
25
+ const _sfc_main$1 = defineComponent({
26
+ name: "SqGridFilter",
27
+ components: { SqBtn, SqCheckbox, SqSelect, SqTextField, SqVirtualScroll },
28
+ props: {
29
+ kind: { type: String, required: true },
30
+ modelValue: { type: Object, default: void 0 },
31
+ /** Distinct values for the set filter. */
32
+ values: { type: Array, default: () => [] },
33
+ formatter: { type: Function, default: void 0 }
34
+ },
35
+ emits: ["update:modelValue"],
36
+ setup(props, { emit }) {
37
+ const search = ref("");
38
+ const ops = computed(() => props.kind === "text" ? TEXT_OPS : NUM_OPS);
39
+ const draft = computed(() => {
40
+ var _a;
41
+ return (_a = props.modelValue) != null ? _a : { kind: props.kind, op: props.kind === "text" ? "contains" : "equals" };
42
+ });
43
+ const draftValue = computed(() => draft.value.value);
44
+ const draftValueTo = computed(() => draft.value.valueTo);
45
+ const needsValue = computed(() => draft.value.op !== "blank" && draft.value.op !== "notBlank");
46
+ const set = (key, v) => emit("update:modelValue", { ...draft.value, kind: props.kind, [key]: v });
47
+ const label = (v) => v == null || v === "" ? "(Blanks)" : props.formatter ? props.formatter(v) : String(v);
48
+ const shownValues = computed(() => {
49
+ const q = search.value.trim().toLowerCase();
50
+ return q ? props.values.filter((v) => label(v).toLowerCase().includes(q)) : props.values;
51
+ });
52
+ const checkedSet = computed(() => {
53
+ var _a, _b;
54
+ return new Set(((_b = (_a = props.modelValue) == null ? void 0 : _a.values) != null ? _b : props.values).map(String));
55
+ });
56
+ const isChecked = (v) => checkedSet.value.has(String(v));
57
+ const allChecked = computed(() => {
58
+ var _a;
59
+ return !((_a = props.modelValue) == null ? void 0 : _a.values) || props.modelValue.values.length === props.values.length;
60
+ });
61
+ const someChecked = computed(() => {
62
+ var _a;
63
+ return !!((_a = props.modelValue) == null ? void 0 : _a.values) && props.modelValue.values.length > 0 && !allChecked.value;
64
+ });
65
+ const toggleValue = (v) => {
66
+ var _a, _b;
67
+ const cur = (_b = (_a = props.modelValue) == null ? void 0 : _a.values) != null ? _b : props.values;
68
+ const next = isChecked(v) ? cur.filter((x) => String(x) !== String(v)) : [...cur, v];
69
+ emit("update:modelValue", next.length === props.values.length ? void 0 : { kind: "set", values: next });
70
+ };
71
+ const toggleAll = () => emit("update:modelValue", allChecked.value ? { kind: "set", values: [] } : void 0);
72
+ return { search, ops, draft, draftValue, draftValueTo, needsValue, set, label, shownValues, isChecked, allChecked, someChecked, toggleValue, toggleAll, messages: computed(() => config.locale.messages) };
73
+ }
74
+ });
75
+ function normalizeComponent(scriptExports, render3, staticRenderFns, functionalTemplate, injectStyles, scopeId, moduleIdentifier, shadowMode) {
76
+ var options = typeof scriptExports === "function" ? scriptExports.options : scriptExports;
77
+ if (render3) {
78
+ options.render = render3;
79
+ options.staticRenderFns = staticRenderFns;
80
+ options._compiled = true;
81
+ }
82
+ return {
83
+ exports: scriptExports,
84
+ options
85
+ };
86
+ }
87
+ var _sfc_render$1 = function render() {
88
+ var _vm = this, _c = _vm._self._c;
89
+ _vm._self._setupProxy;
90
+ return _c("div", { staticClass: "sq-grid-filter", on: { "click": function($event) {
91
+ $event.stopPropagation();
92
+ } } }, [_vm.kind === "set" ? [_c("SqTextField", { attrs: { "placeholder": _vm.messages.search, "density": "compact", "prepend-inner-icon": "search", "hide-details": "", "clearable": "" }, model: { value: _vm.search, callback: function($$v) {
93
+ _vm.search = $$v;
94
+ }, expression: "search" } }), _c("label", { staticClass: "sq-grid-filter__all" }, [_c("SqCheckbox", { attrs: { "model-value": _vm.allChecked, "indeterminate": _vm.someChecked, "label": _vm.messages.selectAll }, on: { "update:modelValue": _vm.toggleAll } })], 1), _c("SqVirtualScroll", { attrs: { "items": _vm.shownValues, "item-height": 32, "height": Math.min(_vm.shownValues.length * 32, 224) || 32 }, scopedSlots: _vm._u([{ key: "default", fn: function({ item }) {
95
+ return [_c("SqCheckbox", { attrs: { "model-value": _vm.isChecked(item), "label": _vm.label(item) }, on: { "update:modelValue": function($event) {
96
+ return _vm.toggleValue(item);
97
+ } } })];
98
+ } }], null, false, 1269732013) })] : [_c("SqSelect", { attrs: { "model-value": _vm.draft.op, "items": _vm.ops, "density": "compact", "hide-details": "" }, on: { "update:modelValue": function($event) {
99
+ return _vm.set("op", $event);
100
+ } } }), _vm.needsValue ? _c("SqTextField", { attrs: { "model-value": _vm.draftValue, "type": _vm.kind === "number" ? "number" : _vm.kind === "date" ? "date" : "text", "placeholder": _vm.kind === "text" ? _vm.messages.search : "Value", "density": "compact", "hide-details": "", "clearable": "" }, on: { "update:modelValue": function($event) {
101
+ return _vm.set("value", $event);
102
+ } } }) : _vm._e(), _vm.draft.op === "between" ? _c("SqTextField", { attrs: { "model-value": _vm.draftValueTo, "type": _vm.kind === "number" ? "number" : "date", "placeholder": "To", "density": "compact", "hide-details": "" }, on: { "update:modelValue": function($event) {
103
+ return _vm.set("valueTo", $event);
104
+ } } }) : _vm._e()], _c("div", { staticClass: "sq-grid-filter__actions" }, [_c("SqBtn", { attrs: { "size": "small", "variant": "text", "color": "surface" }, on: { "click": function($event) {
105
+ return _vm.$emit("update:modelValue", void 0);
106
+ } } }, [_vm._v(_vm._s(_vm.messages.clear))])], 1)], 2);
107
+ };
108
+ var _sfc_staticRenderFns$1 = [];
109
+ var __component__$1 = /* @__PURE__ */ normalizeComponent(
110
+ _sfc_main$1,
111
+ _sfc_render$1,
112
+ _sfc_staticRenderFns$1
113
+ );
114
+ const SqGridFilter = __component__$1.exports;
115
+ const colIdOf = (c) => {
116
+ var _a, _b, _c;
117
+ return (_c = (_b = (_a = c.colId) != null ? _a : c.field) != null ? _b : c.headerName) != null ? _c : "";
118
+ };
119
+ function makeGetter(col) {
120
+ if (col.valueGetter) return col.valueGetter;
121
+ const f = col.field;
122
+ if (!f) return () => void 0;
123
+ if (!f.includes(".")) return (row) => row[f];
124
+ return (row) => getByPath(row, f);
125
+ }
126
+ function filterKindOf(col) {
127
+ if (typeof col.filter === "string") return col.filter;
128
+ return col.type === "number" ? "number" : col.type === "date" ? "date" : col.type === "boolean" ? "set" : "text";
129
+ }
130
+ const isBlank = (v) => v == null || v === "";
131
+ function matchCondition(value, c) {
132
+ var _a;
133
+ if (c.kind === "set") {
134
+ if (!c.values) return true;
135
+ return c.values.some((x) => x === value || isBlank(x) && isBlank(value) || String(x) === String(value));
136
+ }
137
+ const op = (_a = c.op) != null ? _a : c.kind === "text" ? "contains" : "equals";
138
+ if (op === "blank") return isBlank(value);
139
+ if (op === "notBlank") return !isBlank(value);
140
+ if (c.value == null || c.value === "") return true;
141
+ if (c.kind === "text") {
142
+ const v2 = String(value != null ? value : "").toLowerCase();
143
+ const q = String(c.value).toLowerCase();
144
+ switch (op) {
145
+ case "contains":
146
+ return v2.includes(q);
147
+ case "notContains":
148
+ return !v2.includes(q);
149
+ case "equals":
150
+ return v2 === q;
151
+ case "notEqual":
152
+ return v2 !== q;
153
+ case "startsWith":
154
+ return v2.startsWith(q);
155
+ case "endsWith":
156
+ return v2.endsWith(q);
157
+ default:
158
+ return true;
159
+ }
160
+ }
161
+ const toNum = (x) => {
162
+ var _a2, _b;
163
+ return c.kind === "date" ? (_b = (_a2 = toDate(x)) == null ? void 0 : _a2.getTime()) != null ? _b : NaN : Number(x);
164
+ };
165
+ const v = toNum(value);
166
+ const a = toNum(c.value);
167
+ if (isNaN(v)) return false;
168
+ switch (op) {
169
+ case "equals":
170
+ return c.kind === "date" ? Math.floor(v / 864e5) === Math.floor(a / 864e5) : v === a;
171
+ case "notEqual":
172
+ return v !== a;
173
+ case "gt":
174
+ return v > a;
175
+ case "gte":
176
+ return v >= a;
177
+ case "lt":
178
+ return v < a;
179
+ case "lte":
180
+ return v <= a;
181
+ case "between":
182
+ return v >= a && v <= toNum(c.valueTo);
183
+ default:
184
+ return true;
185
+ }
186
+ }
187
+ function filterRows(rows, columns, model, quick) {
188
+ const active = Object.entries(model).filter(([, c]) => c && (c.kind === "set" ? !!c.values : c.op === "blank" || c.op === "notBlank" || c.value != null && c.value !== ""));
189
+ const byId = new Map(columns.map((c) => [colIdOf(c), c]));
190
+ const checks = active.map(([id, cond]) => {
191
+ var _a;
192
+ return { get: makeGetter((_a = byId.get(id)) != null ? _a : { field: id }), cond };
193
+ });
194
+ const q = quick.trim().toLowerCase();
195
+ const quickGetters = q ? columns.filter((c) => !c.hide).map((c) => makeGetter(c)) : [];
196
+ const out = [];
197
+ for (let i = 0; i < rows.length; i++) {
198
+ const row = rows[i];
199
+ let ok = true;
200
+ for (const { get, cond } of checks) {
201
+ if (!matchCondition(get(row), cond)) {
202
+ ok = false;
203
+ break;
204
+ }
205
+ }
206
+ if (ok && q) {
207
+ ok = false;
208
+ for (const get of quickGetters) {
209
+ const v = get(row);
210
+ if (v == null || typeof v === "object") continue;
211
+ if (String(v).toLowerCase().includes(q)) {
212
+ ok = true;
213
+ break;
214
+ }
215
+ }
216
+ }
217
+ if (ok) out.push(i);
218
+ }
219
+ return out;
220
+ }
221
+ function sortIndices(rows, indices, columns, sort) {
222
+ var _a, _b;
223
+ if (!sort.length) return indices;
224
+ const byId = new Map(columns.map((c) => [colIdOf(c), c]));
225
+ const specs = sort.map((s) => {
226
+ var _a2;
227
+ const col = (_a2 = byId.get(s.colId)) != null ? _a2 : { field: s.colId };
228
+ const get = makeGetter(col);
229
+ const keys = new Array(rows.length);
230
+ for (const i of indices) keys[i] = get(rows[i]);
231
+ return { keys, dir: s.sort === "desc" ? -1 : 1, cmp: col.comparator, date: col.type === "date" };
232
+ });
233
+ for (const s of specs) if (s.date) for (const i of indices) s.keys[i] = (_b = (_a = toDate(s.keys[i])) == null ? void 0 : _a.getTime()) != null ? _b : null;
234
+ return indices.slice().sort((a, b) => {
235
+ for (const s of specs) {
236
+ const ka = s.keys[a];
237
+ const kb = s.keys[b];
238
+ const blankA = ka == null || ka === "";
239
+ const blankB = kb == null || kb === "";
240
+ if (blankA !== blankB) return blankA ? 1 : -1;
241
+ const r = s.cmp ? s.cmp(ka, kb, rows[a], rows[b]) : compareValues(ka, kb);
242
+ if (r) return r * s.dir;
243
+ }
244
+ return a - b;
245
+ });
246
+ }
247
+ function aggregate(values, fn) {
248
+ if (typeof fn === "function") return fn(values);
249
+ const nums = values.filter((v) => v != null && v !== "").map(Number).filter((n) => !isNaN(n));
250
+ switch (fn) {
251
+ case "sum":
252
+ return nums.reduce((a, b) => a + b, 0);
253
+ case "avg":
254
+ return nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : null;
255
+ case "min":
256
+ return nums.length ? Math.min(...nums) : null;
257
+ case "max":
258
+ return nums.length ? Math.max(...nums) : null;
259
+ case "count":
260
+ return values.length;
261
+ case "first":
262
+ return values[0];
263
+ case "last":
264
+ return values[values.length - 1];
265
+ }
266
+ }
267
+ function computeAgg(rows, leaves, aggCols) {
268
+ const agg = {};
269
+ for (const a of aggCols) agg[a.id] = aggregate(leaves.map((i) => a.get(rows[i])), a.fn);
270
+ return agg;
271
+ }
272
+ function groupRows(rows, indices, columns, groupBy) {
273
+ const byId = new Map(columns.map((c) => [colIdOf(c), c]));
274
+ const aggCols = columns.filter((c) => c.aggFunc).map((c) => ({ id: colIdOf(c), get: makeGetter(c), fn: c.aggFunc }));
275
+ const build = (idx, level, parentId) => {
276
+ var _a;
277
+ const colId = groupBy[level];
278
+ const get = makeGetter((_a = byId.get(colId)) != null ? _a : { field: colId });
279
+ const buckets = /* @__PURE__ */ new Map();
280
+ for (const i of idx) {
281
+ const key = get(rows[i]);
282
+ const k = String(key != null ? key : "");
283
+ let b = buckets.get(k);
284
+ if (!b) buckets.set(k, b = { key, leaves: [] });
285
+ b.leaves.push(i);
286
+ }
287
+ return Array.from(buckets.values()).map((b) => {
288
+ var _a2;
289
+ const id = `${parentId}/${colId}:${String((_a2 = b.key) != null ? _a2 : "")}`;
290
+ return {
291
+ key: b.key,
292
+ colId,
293
+ id,
294
+ level,
295
+ leaves: b.leaves,
296
+ children: level + 1 < groupBy.length ? build(b.leaves, level + 1, id) : [],
297
+ agg: computeAgg(rows, b.leaves, aggCols)
298
+ };
299
+ });
300
+ };
301
+ return groupBy.length ? build(indices, 0, "g") : [];
302
+ }
303
+ function treeRows(rows, indices, columns, getDataPath) {
304
+ const aggCols = columns.filter((c) => c.aggFunc).map((c) => ({ id: colIdOf(c), get: makeGetter(c), fn: c.aggFunc }));
305
+ const root = { children: [] };
306
+ const nodes = /* @__PURE__ */ new Map();
307
+ for (const i of indices) {
308
+ const path = getDataPath(rows[i]);
309
+ let parent = root;
310
+ let id = "t";
311
+ path.forEach((part, depth) => {
312
+ id += `/${part}`;
313
+ let node = nodes.get(id);
314
+ if (!node) {
315
+ node = { key: part, colId: "__tree", id, level: depth, children: [], leaves: [], agg: {} };
316
+ nodes.set(id, node);
317
+ parent.children.push(node);
318
+ }
319
+ if (depth === path.length - 1) node.self = i;
320
+ node.leaves.push(i);
321
+ parent = node;
322
+ });
323
+ }
324
+ for (const n of nodes.values()) if (n.children.length) n.agg = computeAgg(rows, n.leaves, aggCols);
325
+ return root.children;
326
+ }
327
+ function flatten(rows, indices, groups, opts) {
328
+ const out = [];
329
+ const pushData = (i, level) => {
330
+ var _a;
331
+ const id = opts.rowId(rows[i], i);
332
+ out.push({ kind: "data", id, data: rows[i], level, sourceIndex: i });
333
+ if ((_a = opts.detailOpen) == null ? void 0 : _a.has(id)) out.push({ kind: "detail", id: `${id}__detail`, data: rows[i], level, sourceIndex: i });
334
+ };
335
+ if (!groups) {
336
+ for (const i of indices) pushData(i, 0);
337
+ return out;
338
+ }
339
+ const isOpen = (id) => {
340
+ var _a;
341
+ return opts.expandAll ? !((_a = opts.collapsed) == null ? void 0 : _a.has(id)) : opts.expanded.has(id);
342
+ };
343
+ const walk = (nodes) => {
344
+ for (const g of nodes) {
345
+ const self = g.self;
346
+ if (opts.tree && !g.children.length && self != null) {
347
+ pushData(self, g.level);
348
+ continue;
349
+ }
350
+ const expanded = isOpen(g.id);
351
+ const leafIds = g.leaves.map((i) => opts.rowId(rows[i], i));
352
+ out.push({
353
+ kind: "group",
354
+ id: g.id,
355
+ data: opts.tree && self != null ? rows[self] : null,
356
+ level: g.level,
357
+ sourceIndex: self,
358
+ 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 }
359
+ });
360
+ if (!expanded) continue;
361
+ if (g.children.length) walk(g.children);
362
+ else for (const i of g.leaves) pushData(i, g.level + 1);
363
+ }
364
+ };
365
+ walk(groups);
366
+ return out;
367
+ }
368
+ function allGroupIds(groups) {
369
+ const ids = [];
370
+ const walk = (n) => n.forEach((g) => {
371
+ if (g.children.length || g.colId !== "__tree") ids.push(g.id);
372
+ walk(g.children);
373
+ });
374
+ walk(groups);
375
+ return ids;
376
+ }
377
+ function rowLayout(rows, rowHeight, detailHeight) {
378
+ const offsets = new Float64Array(rows.length + 1);
379
+ for (let i = 0; i < rows.length; i++) offsets[i + 1] = offsets[i] + (rows[i].kind === "detail" ? detailHeight : rowHeight);
380
+ const indexAt = (y) => {
381
+ let lo = 0;
382
+ let hi = rows.length - 1;
383
+ while (lo < hi) {
384
+ const mid = lo + hi + 1 >> 1;
385
+ if (offsets[mid] <= y) lo = mid;
386
+ else hi = mid - 1;
387
+ }
388
+ return Math.max(0, lo);
389
+ };
390
+ return { offsets, total: offsets[rows.length], indexAt };
391
+ }
392
+ function pivotRows(rows, indices, columns, groupBy, pivotCol) {
393
+ var _a, _b, _c;
394
+ const byId = new Map(columns.map((c) => [colIdOf(c), c]));
395
+ const valueCols = columns.filter((c) => c.aggFunc);
396
+ const pGet = makeGetter((_a = byId.get(pivotCol)) != null ? _a : { field: pivotCol });
397
+ const gGets = groupBy.map((id) => {
398
+ var _a2;
399
+ return makeGetter((_a2 = byId.get(id)) != null ? _a2 : { field: id });
400
+ });
401
+ const pivotKeys = [];
402
+ const seen = /* @__PURE__ */ new Set();
403
+ const buckets = /* @__PURE__ */ new Map();
404
+ for (const i of indices) {
405
+ const pk = String((_b = pGet(rows[i])) != null ? _b : "");
406
+ if (!seen.has(pk)) {
407
+ seen.add(pk);
408
+ pivotKeys.push(pk);
409
+ }
410
+ const keys = gGets.map((g) => g(rows[i]));
411
+ const k = keys.map(String).join("");
412
+ let b = buckets.get(k);
413
+ if (!b) buckets.set(k, b = { keys, cells: /* @__PURE__ */ new Map() });
414
+ let cell = b.cells.get(pk);
415
+ if (!cell) b.cells.set(pk, cell = []);
416
+ cell.push(i);
417
+ }
418
+ pivotKeys.sort((a, b) => compareValues(a, b));
419
+ const outRows = [];
420
+ for (const b of buckets.values()) {
421
+ const r = {};
422
+ groupBy.forEach((id, k) => r[id] = b.keys[k]);
423
+ for (const pk of pivotKeys)
424
+ for (const vc of valueCols) {
425
+ const leaves = (_c = b.cells.get(pk)) != null ? _c : [];
426
+ const get = makeGetter(vc);
427
+ r[`${pk}__${colIdOf(vc)}`] = leaves.length ? aggregate(leaves.map((i) => get(rows[i])), vc.aggFunc) : null;
428
+ }
429
+ outRows.push(r);
430
+ }
431
+ const outCols = [
432
+ ...groupBy.map((id) => ({ ...byId.get(id), colId: id, field: id, pinned: "left", rowGroup: false, valueGetter: void 0 })),
433
+ ...pivotKeys.flatMap(
434
+ (pk) => valueCols.map((vc) => {
435
+ var _a2;
436
+ return {
437
+ colId: `${pk}__${colIdOf(vc)}`,
438
+ field: `${pk}__${colIdOf(vc)}`,
439
+ headerName: valueCols.length > 1 ? `${(_a2 = vc.headerName) != null ? _a2 : colIdOf(vc)}` : pk,
440
+ group: valueCols.length > 1 ? pk : void 0,
441
+ type: "number",
442
+ align: "right",
443
+ aggFunc: vc.aggFunc,
444
+ valueFormatter: vc.valueFormatter,
445
+ width: 120
446
+ };
447
+ })
448
+ )
449
+ ];
450
+ return { rows: outRows, columns: outCols };
451
+ }
452
+ function toCsv(header, body, sep = ",") {
453
+ const esc = (s) => /[",\n\r]/.test(s) || s.includes(sep) ? `"${s.replace(/"/g, '""')}"` : s;
454
+ return [header, ...body].map((r) => r.map(esc).join(sep)).join("\r\n");
455
+ }
456
+ const parseTsv = (text) => text.replace(/\r?\n$/, "").split(/\r?\n/).map((l) => l.split(" "));
457
+ const SELECT_COL = { colId: "__select", headerName: "", width: 48, resizable: false, sortable: false, filter: false, suppressMenu: true, lockPosition: true };
458
+ function setByPath(obj, path, value) {
459
+ var _a, _b;
460
+ const keys = path.split(".");
461
+ let cur = obj;
462
+ for (let i = 0; i < keys.length - 1; i++) cur = (_b = cur[_a = keys[i]]) != null ? _b : cur[_a] = {};
463
+ cur[keys[keys.length - 1]] = value;
464
+ }
465
+ const _sfc_main = defineComponent({
466
+ name: "SqDataGrid",
467
+ components: { SqShape, SqBtn, SqCheckbox, SqChip, SqDivider, SqEmptyState, SqIcon, SqListItem, SqMenu, SqPagination, SqProgressCircular, SqTextField, SqGridFilter },
468
+ props: {
469
+ rows: { type: Array, default: () => [] },
470
+ columns: { type: Array, default: () => [] },
471
+ defaultColDef: { type: Object, default: () => ({}) },
472
+ /** Field name or function producing a stable row id. */
473
+ rowId: { type: [String, Function], default: "id" },
474
+ height: { type: [Number, String], default: 520 },
475
+ rowHeight: { type: Number, default: 40 },
476
+ headerHeight: { type: Number, default: 42 },
477
+ detailHeight: { type: Number, default: 220 },
478
+ rowSelection: { type: String, default: null },
479
+ /** Auto checkbox column when rowSelection = multiple. */
480
+ selectionColumn: { type: Boolean, default: true },
481
+ selected: { type: Array, default: void 0 },
482
+ sortModel: { type: Array, default: void 0 },
483
+ filterModel: { type: Object, default: void 0 },
484
+ quickFilter: { type: String, default: void 0 },
485
+ groupBy: { type: Array, default: void 0 },
486
+ /** Levels expanded by default; -1 = all. */
487
+ groupDefaultExpanded: { type: Number, default: 0 },
488
+ groupColumn: { type: Object, default: () => ({}) },
489
+ treeData: Boolean,
490
+ getDataPath: { type: Function, default: void 0 },
491
+ pivotMode: Boolean,
492
+ pivotColumn: { type: String, default: void 0 },
493
+ masterDetail: Boolean,
494
+ pinnedTopRows: { type: Array, default: () => [] },
495
+ pinnedBottomRows: { type: Array, default: () => [] },
496
+ /** Bottom row with column aggFunc totals over the filtered rows. */
497
+ totalsRow: Boolean,
498
+ pagination: Boolean,
499
+ pageSize: { type: Number, default: 50 },
500
+ pageSizes: { type: Array, default: () => [25, 50, 100, 500] },
501
+ /** Infinite / server-side row model. Sorting & filtering are delegated to getRows. */
502
+ datasource: { type: Object, default: void 0 },
503
+ blockSize: { type: Number, default: 100 },
504
+ loading: Boolean,
505
+ toolbar: Boolean,
506
+ groupPanel: Boolean,
507
+ floatingFilters: Boolean,
508
+ statusBar: { type: Boolean, default: true },
509
+ striped: Boolean,
510
+ columnLines: Boolean,
511
+ rowClassName: { type: Function, default: void 0 },
512
+ locale: { type: String, default: void 0 }
513
+ },
514
+ 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"],
515
+ setup(props, { emit, slots }) {
516
+ var _a;
517
+ const viewport = ref(null);
518
+ const ctxAnchor = ref(null);
519
+ const scrollTop = ref(0);
520
+ const scrollLeft = ref(0);
521
+ const vpWidth = ref(800);
522
+ const vpHeight = ref(400);
523
+ const dataVersion = ref(0);
524
+ const loc = computed(() => {
525
+ var _a2;
526
+ return (_a2 = props.locale) != null ? _a2 : config.locale.code;
527
+ });
528
+ const isServer = computed(() => !!props.datasource);
529
+ const sortModelRef = useProxiedModel(props, emit, "sortModel", () => []);
530
+ const filterModelRef = useProxiedModel(props, emit, "filterModel", () => ({}));
531
+ const quick = useProxiedModel(props, emit, "quickFilter", () => "");
532
+ const groupByRef = useProxiedModel(props, emit, "groupBy", () => props.columns.filter((c) => c.rowGroup).map(colIdOf));
533
+ const selectedRef = useProxiedModel(props, emit, "selected", () => []);
534
+ const sortModelList = computed(() => {
535
+ var _a2;
536
+ return (_a2 = sortModelRef.value) != null ? _a2 : [];
537
+ });
538
+ const filterModelObj = computed(() => {
539
+ var _a2;
540
+ return (_a2 = filterModelRef.value) != null ? _a2 : {};
541
+ });
542
+ const groupBy = computed(() => {
543
+ var _a2;
544
+ return (_a2 = groupByRef.value) != null ? _a2 : [];
545
+ });
546
+ const selectedIds = computed(() => {
547
+ var _a2;
548
+ return (_a2 = selectedRef.value) != null ? _a2 : [];
549
+ });
550
+ const selectedSet = computed(() => new Set(selectedIds.value));
551
+ const colOrder = ref([]);
552
+ const colWidth = ref({});
553
+ const colHidden = ref({});
554
+ const colPinned = ref({});
555
+ const baseCols = computed(() => props.columns.map((c) => ({ ...props.defaultColDef, ...c })));
556
+ watch(baseCols, (cols) => {
557
+ const ids = cols.map(colIdOf);
558
+ colOrder.value = [...colOrder.value.filter((id) => ids.includes(id)), ...ids.filter((id) => !colOrder.value.includes(id))];
559
+ }, { immediate: true });
560
+ const rowIdOf = (row, i) => {
561
+ var _a2;
562
+ return String(typeof props.rowId === "function" ? props.rowId(row, i) : (_a2 = row == null ? void 0 : row[props.rowId]) != null ? _a2 : i);
563
+ };
564
+ const raw = computed(() => {
565
+ void dataVersion.value;
566
+ return toRaw(props.rows);
567
+ });
568
+ const quickApplied = ref((_a = quick.value) != null ? _a : "");
569
+ let quickApplyTimer;
570
+ watch(quick, (q) => {
571
+ clearTimeout(quickApplyTimer);
572
+ quickApplyTimer = setTimeout(() => quickApplied.value = q != null ? q : "", raw.value.length > 2e4 ? 160 : 0);
573
+ });
574
+ const filteredIdx = computed(() => isServer.value ? [] : filterRows(raw.value, baseCols.value, filterModelObj.value, quickApplied.value));
575
+ const sortedIdx = computed(() => sortIndices(raw.value, filteredIdx.value, baseCols.value, sortModelList.value));
576
+ const pivot = computed(() => props.pivotMode && props.pivotColumn && !isServer.value ? pivotRows(raw.value, sortedIdx.value, baseCols.value, groupBy.value, props.pivotColumn) : null);
577
+ const viewRows = computed(() => pivot.value ? pivot.value.rows : raw.value);
578
+ const viewIdx = computed(() => pivot.value ? pivot.value.rows.map((_, i) => i) : sortedIdx.value);
579
+ const viewCols = computed(() => pivot.value ? pivot.value.columns.map((c) => ({ ...props.defaultColDef, ...c })) : baseCols.value);
580
+ const groups = computed(() => {
581
+ if (isServer.value || pivot.value) return null;
582
+ if (props.treeData && props.getDataPath) return treeRows(viewRows.value, viewIdx.value, viewCols.value, props.getDataPath);
583
+ return groupBy.value.length ? groupRows(viewRows.value, viewIdx.value, viewCols.value, groupBy.value) : null;
584
+ });
585
+ const hasGroups = computed(() => !!groups.value);
586
+ const expanded = ref(/* @__PURE__ */ new Set());
587
+ const collapsed = ref(/* @__PURE__ */ new Set());
588
+ const expandAllFlag = ref(props.groupDefaultExpanded === -1);
589
+ const detailOpen = ref(/* @__PURE__ */ new Set());
590
+ watch(groups, (g) => {
591
+ if (!g || props.groupDefaultExpanded <= 0) return;
592
+ const ids = new Set(expanded.value);
593
+ const walk = (nodes, lvl) => nodes.forEach((n) => {
594
+ if (lvl < props.groupDefaultExpanded) {
595
+ ids.add(n.id);
596
+ walk(n.children, lvl + 1);
597
+ }
598
+ });
599
+ walk(g, 0);
600
+ expanded.value = ids;
601
+ }, { immediate: true });
602
+ const display = computed(
603
+ () => flatten(viewRows.value, viewIdx.value, groups.value, {
604
+ expanded: expanded.value,
605
+ expandAll: expandAllFlag.value,
606
+ collapsed: collapsed.value,
607
+ rowId: rowIdOf,
608
+ detailOpen: props.masterDetail ? detailOpen.value : void 0,
609
+ tree: props.treeData
610
+ })
611
+ );
612
+ const page = ref(1);
613
+ const pageSizeState = ref(props.pageSize);
614
+ const pageCount = computed(() => Math.max(1, Math.ceil(display.value.length / pageSizeState.value)));
615
+ watch([pageCount, filteredIdx], () => page.value = Math.min(page.value, pageCount.value));
616
+ const paged = computed(() => props.pagination ? display.value.slice((page.value - 1) * pageSizeState.value, page.value * pageSizeState.value) : display.value);
617
+ const onPageSize = (e) => {
618
+ pageSizeState.value = Number(e.target.value);
619
+ page.value = 1;
620
+ };
621
+ const pageRangeText = computed(() => {
622
+ const n = display.value.length;
623
+ const a = n ? (page.value - 1) * pageSizeState.value + 1 : 0;
624
+ return config.locale.messages.pageRange.replace("{0}", String(a)).replace("{1}", String(Math.min(n, page.value * pageSizeState.value))).replace("{2}", String(n));
625
+ });
626
+ const blocks = /* @__PURE__ */ new Map();
627
+ const blockVersion = ref(0);
628
+ const serverCount = ref(0);
629
+ const serverLoading = ref(false);
630
+ let epoch = 0;
631
+ const loadBlock = async (b) => {
632
+ var _a2;
633
+ if (!props.datasource || blocks.has(b)) return;
634
+ blocks.set(b, "loading");
635
+ const my = epoch;
636
+ serverLoading.value = true;
637
+ try {
638
+ const res = await props.datasource.getRows({ startRow: b * props.blockSize, endRow: (b + 1) * props.blockSize, sortModel: sortModelList.value, filterModel: filterModelObj.value, quickFilter: (_a2 = quick.value) != null ? _a2 : "" });
639
+ if (my !== epoch) return;
640
+ blocks.set(b, res.rows);
641
+ if (res.lastRow != null) serverCount.value = res.lastRow;
642
+ else if (res.rows.length < props.blockSize) serverCount.value = b * props.blockSize + res.rows.length;
643
+ else serverCount.value = Math.max(serverCount.value, (b + 2) * props.blockSize);
644
+ } catch {
645
+ if (my === epoch) blocks.delete(b);
646
+ } finally {
647
+ if (my === epoch) {
648
+ serverLoading.value = [...blocks.values()].some((v) => v === "loading");
649
+ blockVersion.value++;
650
+ }
651
+ }
652
+ };
653
+ const purge = () => {
654
+ epoch++;
655
+ blocks.clear();
656
+ serverCount.value = 0;
657
+ blockVersion.value++;
658
+ if (viewport.value) viewport.value.scrollTop = 0;
659
+ loadBlock(0);
660
+ };
661
+ let quickTimer;
662
+ watch([sortModelList, filterModelObj], () => isServer.value && purge(), { deep: true });
663
+ watch(quick, () => {
664
+ if (!isServer.value) return;
665
+ clearTimeout(quickTimer);
666
+ quickTimer = setTimeout(purge, 250);
667
+ });
668
+ watch(() => props.datasource, (ds) => ds && purge());
669
+ onMounted(() => props.datasource && purge());
670
+ const rowCount = computed(() => isServer.value ? serverCount.value : paged.value.length);
671
+ const rowAt = (i) => {
672
+ if (!isServer.value) return paged.value[i];
673
+ void blockVersion.value;
674
+ const b = Math.floor(i / props.blockSize);
675
+ const data = blocks.get(b);
676
+ if (Array.isArray(data)) {
677
+ const row = data[i - b * props.blockSize];
678
+ if (row) return { kind: "data", id: rowIdOf(row, i), data: row, level: 0, sourceIndex: i };
679
+ }
680
+ return { kind: "loading", id: `__loading_${i}`, data: null, level: 0 };
681
+ };
682
+ const titleOf = (id) => {
683
+ var _a2, _b;
684
+ const c = (_a2 = viewCols.value.find((x) => colIdOf(x) === id)) != null ? _a2 : baseCols.value.find((x) => colIdOf(x) === id);
685
+ return (_b = c == null ? void 0 : c.headerName) != null ? _b : (c == null ? void 0 : c.field) ? c.field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (s) => s.toUpperCase()) : id;
686
+ };
687
+ const groupColDef = computed(() => ({ colId: "__group", headerName: props.treeData ? "Name" : "Group", width: 240, sortable: false, filter: false, suppressMenu: true, lockPosition: true, ...props.groupColumn }));
688
+ const orderedCols = computed(() => {
689
+ const cols = viewCols.value;
690
+ const byId = new Map(cols.map((c) => [colIdOf(c), c]));
691
+ const ordered = pivot.value ? cols : [...colOrder.value.map((id) => byId.get(id)).filter(Boolean), ...cols.filter((c) => !colOrder.value.includes(colIdOf(c)))];
692
+ const auto = [];
693
+ if (props.rowSelection === "multiple" && props.selectionColumn) auto.push(SELECT_COL);
694
+ if (groups.value || props.masterDetail && !props.treeData) auto.push(groupColDef.value);
695
+ return { auto, ordered };
696
+ });
697
+ const visibleCols = computed(() => {
698
+ var _a2, _b, _c;
699
+ const { auto, ordered } = orderedCols.value;
700
+ const list = [
701
+ ...auto.map((c) => ({ id: colIdOf(c), col: c, auto: true })),
702
+ ...ordered.filter((c) => {
703
+ var _a3;
704
+ return !((_a3 = colHidden.value[colIdOf(c)]) != null ? _a3 : c.hide);
705
+ }).map((c) => ({ id: colIdOf(c), col: c, auto: false }))
706
+ ];
707
+ const resolved = list.map((x) => {
708
+ var _a3, _b2, _c2;
709
+ return {
710
+ ...x,
711
+ pinned: x.auto ? "left" : colPinned.value[x.id] !== void 0 ? colPinned.value[x.id] : (_a3 = x.col.pinned) != null ? _a3 : null,
712
+ width: (_c2 = (_b2 = colWidth.value[x.id]) != null ? _b2 : x.col.width) != null ? _c2 : x.col.flex ? 0 : 150,
713
+ title: x.id === "__group" ? x.col.headerName : titleOf(x.id)
714
+ };
715
+ });
716
+ const anyLeft = resolved.some((r) => !r.auto && r.pinned === "left");
717
+ if (!anyLeft) resolved.forEach((r) => {
718
+ if (r.auto) r.pinned = null;
719
+ });
720
+ const fixed = resolved.reduce((s, r) => s + (r.col.flex && colWidth.value[r.id] == null ? 0 : r.width), 0);
721
+ const flexCols = resolved.filter((r) => r.col.flex && colWidth.value[r.id] == null);
722
+ const totalFlex = flexCols.reduce((s, r) => {
723
+ var _a3;
724
+ return s + ((_a3 = r.col.flex) != null ? _a3 : 0);
725
+ }, 0);
726
+ const avail = Math.max(0, vpWidth.value - fixed - 2);
727
+ for (const r of flexCols) r.width = clamp(Math.floor(avail * ((_a2 = r.col.flex) != null ? _a2 : 1) / totalFlex), (_b = r.col.minWidth) != null ? _b : 80, (_c = r.col.maxWidth) != null ? _c : 4e3);
728
+ const left = resolved.filter((r) => r.pinned === "left");
729
+ const right = resolved.filter((r) => r.pinned === "right");
730
+ const center = resolved.filter((r) => !r.pinned);
731
+ return { left, center, right };
732
+ });
733
+ const flatCols = computed(() => [...visibleCols.value.left, ...visibleCols.value.center, ...visibleCols.value.right]);
734
+ const flatIndex = computed(() => new Map(flatCols.value.map((c, i) => [c.id, i])));
735
+ const leftWidth = computed(() => visibleCols.value.left.reduce((s, c) => s + c.width, 0));
736
+ const rightWidth = computed(() => visibleCols.value.right.reduce((s, c) => s + c.width, 0));
737
+ const centerOffsets = computed(() => {
738
+ const o = [0];
739
+ for (const c of visibleCols.value.center) o.push(o[o.length - 1] + c.width);
740
+ return o;
741
+ });
742
+ const totalWidth = computed(() => leftWidth.value + rightWidth.value + centerOffsets.value[centerOffsets.value.length - 1]);
743
+ const renderCols = computed(() => {
744
+ const { left, center, right } = visibleCols.value;
745
+ const out = [];
746
+ let acc = 0;
747
+ left.forEach((c, i) => {
748
+ 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` } });
749
+ acc += c.width;
750
+ });
751
+ const offs = centerOffsets.value;
752
+ const viewW = Math.max(0, vpWidth.value - leftWidth.value - rightWidth.value);
753
+ let start = 0;
754
+ while (start < center.length && offs[start + 1] < scrollLeft.value) start++;
755
+ let end = start;
756
+ while (end < center.length && offs[end] < scrollLeft.value + viewW) end++;
757
+ start = Math.max(0, start - 2);
758
+ end = Math.min(center.length, end + 2);
759
+ 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` } });
760
+ for (let i = start; i < end; i++) {
761
+ const c = center[i];
762
+ 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` } });
763
+ }
764
+ const padR = offs[center.length] - offs[end];
765
+ if (padR > 0) out.push({ key: "__padR", id: "__padR", col: null, title: "", width: padR, pinned: null, flatIndex: -1, style: { width: `${padR}px` } });
766
+ let racc = 0;
767
+ for (let i = right.length - 1; i >= 0; i--) {
768
+ const c = right[i];
769
+ 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` } });
770
+ racc += c.width;
771
+ }
772
+ const rightPart = out.splice(out.length - right.length, right.length).reverse();
773
+ return [...out, ...rightPart];
774
+ });
775
+ const hasHeaderGroups = computed(() => flatCols.value.some((c) => c.col.group));
776
+ const headerGroups = computed(() => {
777
+ var _a2, _b;
778
+ const out = [];
779
+ for (const rc of renderCols.value) {
780
+ const label = (_b = (_a2 = rc.col) == null ? void 0 : _a2.group) != null ? _b : "";
781
+ const last = out[out.length - 1];
782
+ if (last && label && rc.col && last.label === label && last.pin === rc.pinned) {
783
+ last.width += rc.width;
784
+ last.style.width = `${last.width}px`;
785
+ continue;
786
+ }
787
+ const style = { width: `${rc.width}px` };
788
+ if (rc.pinned === "left") style.left = rc.style.left;
789
+ if (rc.pinned === "right") style.right = rc.style.right;
790
+ out.push({
791
+ key: `${rc.key}-g`,
792
+ label: rc.col ? label : "",
793
+ pin: rc.pinned,
794
+ width: rc.width,
795
+ style,
796
+ cls: { "sq-datagrid__hcell--pinned-left": rc.pinned === "left", "sq-datagrid__hcell--pinned-right": rc.pinned === "right", "sq-datagrid__header-group--empty": !label }
797
+ });
798
+ }
799
+ return out;
800
+ });
801
+ const filterRowHeight = 38;
802
+ const headBlock = computed(() => props.headerHeight * (hasHeaderGroups.value ? 2 : 1) + (props.floatingFilters ? filterRowHeight : 0) + props.pinnedTopRows.length * props.rowHeight);
803
+ const layout = computed(() => {
804
+ if (isServer.value) {
805
+ const n = serverCount.value;
806
+ return { offsets: null, total: n * props.rowHeight, indexAt: (y) => Math.floor(y / props.rowHeight) };
807
+ }
808
+ return rowLayout(paged.value, props.rowHeight, props.detailHeight);
809
+ });
810
+ const range = computed(() => {
811
+ const n = rowCount.value;
812
+ if (!n) return { start: 0, end: -1 };
813
+ const top = Math.max(0, scrollTop.value);
814
+ const start = Math.max(0, layout.value.indexAt(top) - 6);
815
+ const end = Math.min(n - 1, layout.value.indexAt(top + vpHeight.value) + 6);
816
+ return { start, end };
817
+ });
818
+ const visibleRows = computed(() => {
819
+ const out = [];
820
+ const { start, end } = range.value;
821
+ const offs = layout.value.offsets;
822
+ for (let i = start; i <= end; i++) {
823
+ const row = rowAt(i);
824
+ if (!row) continue;
825
+ const top = offs ? offs[i] : i * props.rowHeight;
826
+ const height = offs ? offs[i + 1] - offs[i] : props.rowHeight;
827
+ out.push({ index: i, top, height, row });
828
+ }
829
+ return out;
830
+ });
831
+ watch(range, (r) => {
832
+ if (!isServer.value || r.end < 0) return;
833
+ for (let b = Math.floor(r.start / props.blockSize); b <= Math.floor(r.end / props.blockSize); b++) loadBlock(b);
834
+ });
835
+ const onScroll = () => {
836
+ const el = viewport.value;
837
+ if (!el) return;
838
+ scrollTop.value = el.scrollTop;
839
+ scrollLeft.value = el.scrollLeft;
840
+ };
841
+ let ro;
842
+ onMounted(() => {
843
+ const el = viewport.value;
844
+ const measure = () => {
845
+ vpWidth.value = el.clientWidth;
846
+ vpHeight.value = el.clientHeight;
847
+ };
848
+ measure();
849
+ if (typeof ResizeObserver !== "undefined") {
850
+ ro = new ResizeObserver(measure);
851
+ ro.observe(el);
852
+ }
853
+ });
854
+ onBeforeUnmount(() => {
855
+ ro == null ? void 0 : ro.disconnect();
856
+ clearTimeout(quickTimer);
857
+ clearTimeout(quickApplyTimer);
858
+ window.removeEventListener("pointermove", onResizeMove);
859
+ window.removeEventListener("pointerup", onResizeEnd);
860
+ window.removeEventListener("mouseup", endSelect);
861
+ });
862
+ const getters = /* @__PURE__ */ new WeakMap();
863
+ const cellValue = (rc, row) => {
864
+ if (!rc.col || !row) return void 0;
865
+ let g = getters.get(rc.col);
866
+ if (!g) getters.set(rc.col, g = makeGetter(rc.col));
867
+ return g(row);
868
+ };
869
+ let numFmt = null;
870
+ let numFmtLocale = "";
871
+ const fmtNum = (v) => {
872
+ if (numFmtLocale !== loc.value) {
873
+ numFmt = new Intl.NumberFormat(loc.value, { maximumFractionDigits: 2 });
874
+ numFmtLocale = loc.value;
875
+ }
876
+ return numFmt.format(v);
877
+ };
878
+ const formatValue = (col, v, row) => {
879
+ if (col.valueFormatter) return col.valueFormatter(v, row);
880
+ if (v == null || v === "") return "";
881
+ if (col.type === "number" && typeof v === "number") return fmtNum(v);
882
+ if (col.type === "date") return formatDate(v, loc.value);
883
+ return String(v);
884
+ };
885
+ const formatCell = (rc, row) => rc.col ? formatValue(rc.col, cellValue(rc, row), row) : "";
886
+ const cellParams = (row, rc, rowIndex) => ({ value: cellValue(rc, row), formatted: formatCell(rc, row), row, column: rc.col, rowIndex });
887
+ const groupLabel = (row) => {
888
+ var _a2, _b;
889
+ if (row.kind === "group") {
890
+ const g = row.group;
891
+ if (g.colId === "__tree") return String((_a2 = g.key) != null ? _a2 : "");
892
+ const col = viewCols.value.find((c) => colIdOf(c) === g.colId);
893
+ return col ? formatValue(col, g.key, null) || "(Blank)" : String((_b = g.key) != null ? _b : "");
894
+ }
895
+ if (props.treeData && props.getDataPath && row.data) {
896
+ const p = props.getDataPath(row.data);
897
+ return p[p.length - 1];
898
+ }
899
+ return "";
900
+ };
901
+ const groupAggText = (row, rc) => {
902
+ var _a2;
903
+ if (!rc.col) return "";
904
+ const v = (_a2 = row.group) == null ? void 0 : _a2.agg[rc.id];
905
+ if (v === void 0) return row.data && props.treeData ? formatCell(rc, row.data) : "";
906
+ return formatValue(rc.col, v, null);
907
+ };
908
+ const filterKind = (col) => filterKindOf(col);
909
+ const distinctValues = (id) => {
910
+ const col = baseCols.value.find((c) => colIdOf(c) === id);
911
+ if (!col) return [];
912
+ const get = makeGetter(col);
913
+ const set = /* @__PURE__ */ new Set();
914
+ for (const r of raw.value) {
915
+ set.add(get(r));
916
+ if (set.size > 5e3) break;
917
+ }
918
+ return Array.from(set).sort((a, b) => String(a != null ? a : "").localeCompare(String(b != null ? b : ""), void 0, { numeric: true }));
919
+ };
920
+ const sortIndex = (id) => sortModelList.value.findIndex((s) => s.colId === id);
921
+ const sortDir = (id) => {
922
+ var _a2;
923
+ return (_a2 = sortModelList.value.find((s) => s.colId === id)) == null ? void 0 : _a2.sort;
924
+ };
925
+ const ariaSort = (id) => sortDir(id) === "asc" ? "ascending" : sortDir(id) === "desc" ? "descending" : "none";
926
+ const setSort = (id, dir, multi = false) => {
927
+ const rest = multi ? sortModelList.value.filter((s) => s.colId !== id) : [];
928
+ sortModelRef.value = dir ? [...rest, { colId: id, sort: dir }] : rest;
929
+ };
930
+ let resized = false;
931
+ const onHeaderClick = (e, rc) => {
932
+ if (resized) return void (resized = false);
933
+ if (!rc.col || rc.auto || rc.col.sortable === false) return;
934
+ const cur = sortDir(rc.id);
935
+ const next = cur === "asc" ? "desc" : cur === "desc" ? null : "asc";
936
+ if (e.shiftKey) {
937
+ const list = sortModelList.value.slice();
938
+ const i = list.findIndex((s) => s.colId === rc.id);
939
+ if (next && i >= 0) list[i] = { colId: rc.id, sort: next };
940
+ else if (next) list.push({ colId: rc.id, sort: next });
941
+ else list.splice(i, 1);
942
+ sortModelRef.value = list;
943
+ } else setSort(rc.id, next);
944
+ };
945
+ const setFilter = (id, cond) => {
946
+ const next = { ...filterModelObj.value };
947
+ if (cond) next[id] = cond;
948
+ else delete next[id];
949
+ filterModelRef.value = next;
950
+ };
951
+ const floatingValue = (id) => {
952
+ var _a2;
953
+ const f = filterModelObj.value[id];
954
+ return f && f.kind !== "set" ? (_a2 = f.value) != null ? _a2 : "" : "";
955
+ };
956
+ let floatTimer;
957
+ const onFloatingInput = (e, rc) => {
958
+ const value = e.target.value;
959
+ const kind = filterKind(rc.col);
960
+ clearTimeout(floatTimer);
961
+ floatTimer = setTimeout(() => setFilter(rc.id, value === "" ? void 0 : { kind, op: kind === "text" ? "contains" : "equals", value: kind === "number" ? Number(value) : value }), 180);
962
+ };
963
+ const toggleGroupBy = (id) => groupByRef.value = groupBy.value.includes(id) ? groupBy.value.filter((x) => x !== id) : [...groupBy.value, id];
964
+ const removeGroup = (id) => groupByRef.value = groupBy.value.filter((x) => x !== id);
965
+ const toggleGroup = (row) => {
966
+ if (expandAllFlag.value) {
967
+ const s = new Set(collapsed.value);
968
+ s.has(row.id) ? s.delete(row.id) : s.add(row.id);
969
+ collapsed.value = s;
970
+ } else {
971
+ const s = new Set(expanded.value);
972
+ s.has(row.id) ? s.delete(row.id) : s.add(row.id);
973
+ expanded.value = s;
974
+ }
975
+ };
976
+ const expandAll = () => {
977
+ expandAllFlag.value = true;
978
+ collapsed.value = /* @__PURE__ */ new Set();
979
+ };
980
+ const collapseAll = () => {
981
+ expandAllFlag.value = false;
982
+ expanded.value = /* @__PURE__ */ new Set();
983
+ };
984
+ const toggleDetail = (id) => {
985
+ const s = new Set(detailOpen.value);
986
+ s.has(id) ? s.delete(id) : s.add(id);
987
+ detailOpen.value = s;
988
+ };
989
+ 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 })));
990
+ const setHidden = (id, hide) => {
991
+ colHidden.value = { ...colHidden.value, [id]: hide };
992
+ emitColumnState();
993
+ };
994
+ const setPinned = (id, pin) => {
995
+ colPinned.value = { ...colPinned.value, [id]: pin };
996
+ emitColumnState();
997
+ };
998
+ const chooserCols = computed(() => orderedCols.value.ordered.map((c) => {
999
+ var _a2;
1000
+ return { id: colIdOf(c), title: titleOf(colIdOf(c)), hidden: (_a2 = colHidden.value[colIdOf(c)]) != null ? _a2 : !!c.hide };
1001
+ }));
1002
+ let resizeState = null;
1003
+ const onResizeMove = (e) => {
1004
+ if (!resizeState) return;
1005
+ const w = clamp(resizeState.startW + e.clientX - resizeState.startX, resizeState.min, resizeState.max);
1006
+ colWidth.value = { ...colWidth.value, [resizeState.id]: Math.round(w) };
1007
+ };
1008
+ const onResizeEnd = () => {
1009
+ if (resizeState) {
1010
+ resized = true;
1011
+ setTimeout(() => resized = false, 0);
1012
+ emitColumnState();
1013
+ }
1014
+ resizeState = null;
1015
+ window.removeEventListener("pointermove", onResizeMove);
1016
+ window.removeEventListener("pointerup", onResizeEnd);
1017
+ };
1018
+ const startResize = (e, rc) => {
1019
+ var _a2, _b, _c, _d;
1020
+ resizeState = { id: rc.id, startX: e.clientX, startW: rc.width, min: (_b = (_a2 = rc.col) == null ? void 0 : _a2.minWidth) != null ? _b : 48, max: (_d = (_c = rc.col) == null ? void 0 : _c.maxWidth) != null ? _d : 2e3 };
1021
+ window.addEventListener("pointermove", onResizeMove);
1022
+ window.addEventListener("pointerup", onResizeEnd);
1023
+ };
1024
+ let canvas = null;
1025
+ const autoSize = (ids) => {
1026
+ var _a2, _b;
1027
+ canvas != null ? canvas : canvas = document.createElement("canvas");
1028
+ const ctx = canvas.getContext("2d");
1029
+ if (!ctx || !viewport.value) return;
1030
+ const cs = getComputedStyle(viewport.value);
1031
+ ctx.font = `${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`;
1032
+ const sample = isServer.value ? [] : paged.value.filter((r) => r.kind === "data").slice(0, 300);
1033
+ const next = { ...colWidth.value };
1034
+ for (const c of flatCols.value) {
1035
+ if (c.auto || ids && !ids.includes(c.id)) continue;
1036
+ let w = ctx.measureText(c.title).width + 64;
1037
+ for (const r of sample) w = Math.max(w, ctx.measureText(formatValue(c.col, cellValue(c, r.data), r.data)).width + 32);
1038
+ next[c.id] = Math.ceil(clamp(w, (_a2 = c.col.minWidth) != null ? _a2 : 48, (_b = c.col.maxWidth) != null ? _b : 600));
1039
+ }
1040
+ colWidth.value = next;
1041
+ emitColumnState();
1042
+ };
1043
+ const dragColId = ref(null);
1044
+ const dropTarget = ref(null);
1045
+ const onDragStart = (e, rc) => {
1046
+ var _a2;
1047
+ if (!rc.col || rc.auto || rc.col.lockPosition) return e.preventDefault();
1048
+ dragColId.value = rc.id;
1049
+ (_a2 = e.dataTransfer) == null ? void 0 : _a2.setData("text/plain", rc.id);
1050
+ if (e.dataTransfer) e.dataTransfer.effectAllowed = "move";
1051
+ };
1052
+ const onDragOver = (e, rc) => {
1053
+ if (!dragColId.value || !rc.col || rc.auto) return;
1054
+ dropTarget.value = { id: rc.id, before: e.offsetX < rc.width / 2 };
1055
+ };
1056
+ const onDrop = (rc) => {
1057
+ const from = dragColId.value;
1058
+ const target = dropTarget.value;
1059
+ dragColId.value = null;
1060
+ dropTarget.value = null;
1061
+ if (!from || !target || from === target.id || !rc.col || rc.auto) return;
1062
+ const order = colOrder.value.filter((id) => id !== from);
1063
+ const i = order.indexOf(target.id);
1064
+ order.splice(target.before ? i : i + 1, 0, from);
1065
+ colOrder.value = order;
1066
+ const pin = visibleCols.value.left.some((c) => c.id === target.id) ? "left" : visibleCols.value.right.some((c) => c.id === target.id) ? "right" : null;
1067
+ colPinned.value = { ...colPinned.value, [from]: pin };
1068
+ emitColumnState();
1069
+ };
1070
+ const onGroupDrop = () => {
1071
+ const id = dragColId.value;
1072
+ dragColId.value = null;
1073
+ if (id && !groupBy.value.includes(id)) groupByRef.value = [...groupBy.value, id];
1074
+ };
1075
+ const dataIdsInView = () => isServer.value ? [] : viewIdx.value.map((i) => rowIdOf(viewRows.value[i], i));
1076
+ const setSelected = (ids) => {
1077
+ selectedRef.value = ids;
1078
+ emit("selection-change", ids);
1079
+ };
1080
+ const allSelected = computed(() => {
1081
+ const ids = filteredIdx.value;
1082
+ return ids.length > 0 && selectedIds.value.length >= ids.length && ids.every((i) => selectedSet.value.has(rowIdOf(raw.value[i], i)));
1083
+ });
1084
+ const someSelected = computed(() => !allSelected.value && selectedIds.value.length > 0);
1085
+ const toggleAll = () => setSelected(allSelected.value ? [] : dataIdsInView());
1086
+ const isRowChecked = (row) => row.kind === "group" ? row.group.leafIds.every((id) => selectedSet.value.has(id)) : selectedSet.value.has(row.id);
1087
+ const isRowPartial = (row) => row.kind === "group" && !isRowChecked(row) && row.group.leafIds.some((id) => selectedSet.value.has(id));
1088
+ const toggleRowCheck = (row) => {
1089
+ const ids = row.kind === "group" ? row.group.leafIds : [row.id];
1090
+ const on = isRowChecked(row);
1091
+ const s = new Set(selectedIds.value);
1092
+ ids.forEach((id) => on ? s.delete(id) : s.add(id));
1093
+ setSelected(Array.from(s));
1094
+ };
1095
+ let lastClicked = -1;
1096
+ const onRowClick = (e, vr) => {
1097
+ if (vr.row.kind !== "data") return;
1098
+ emit("row-click", { row: vr.row.data, event: e });
1099
+ if (!props.rowSelection) return;
1100
+ if (props.rowSelection === "single") setSelected(selectedSet.value.has(vr.row.id) && (e.ctrlKey || e.metaKey) ? [] : [vr.row.id]);
1101
+ else if (e.shiftKey && lastClicked >= 0) {
1102
+ const [a, b] = [Math.min(lastClicked, vr.index), Math.max(lastClicked, vr.index)];
1103
+ const ids = new Set(selectedIds.value);
1104
+ for (let i = a; i <= b; i++) {
1105
+ const r = rowAt(i);
1106
+ if ((r == null ? void 0 : r.kind) === "data") ids.add(r.id);
1107
+ }
1108
+ setSelected(Array.from(ids));
1109
+ } else if (e.ctrlKey || e.metaKey) toggleRowCheck(vr.row);
1110
+ else if (!props.selectionColumn) setSelected([vr.row.id]);
1111
+ lastClicked = vr.index;
1112
+ };
1113
+ const focus = ref(null);
1114
+ const cellRange = ref(null);
1115
+ let anchor = null;
1116
+ let selecting = false;
1117
+ const endSelect = () => {
1118
+ selecting = false;
1119
+ window.removeEventListener("mouseup", endSelect);
1120
+ };
1121
+ const setRange = (a, b) => 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) };
1122
+ const inRange = (row, col) => {
1123
+ const r = cellRange.value;
1124
+ return !!r && (r.startRow !== r.endRow || r.startCol !== r.endCol) && row >= r.startRow && row <= r.endRow && col >= r.startCol && col <= r.endCol;
1125
+ };
1126
+ const onCellMousedown = (e, vr, rc) => {
1127
+ if (!rc.col || e.button !== 0) return;
1128
+ const pos = { row: vr.index, col: rc.flatIndex };
1129
+ if (editing.value && !isEditing(vr, rc)) commitEdit();
1130
+ if (e.shiftKey && focus.value) setRange(focus.value, pos);
1131
+ else {
1132
+ focus.value = pos;
1133
+ anchor = pos;
1134
+ setRange(pos, pos);
1135
+ }
1136
+ selecting = true;
1137
+ window.addEventListener("mouseup", endSelect);
1138
+ emit("cell-click", { row: vr.row.data, colId: rc.id, value: cellValue(rc, vr.row.data), event: e });
1139
+ };
1140
+ const onCellEnter = (vr, rc) => {
1141
+ if (selecting && anchor && rc.col) setRange(anchor, { row: vr.index, col: rc.flatIndex });
1142
+ };
1143
+ const editing = ref(null);
1144
+ const isEditable = (col, row) => !!row && (typeof col.editable === "function" ? col.editable(row) : !!col.editable);
1145
+ const isEditing = (vr, rc) => !!editing.value && editing.value.row === vr.index && editing.value.colId === rc.id;
1146
+ const editorKind = (rc) => {
1147
+ var _a2, _b, _c, _d;
1148
+ return (_d = (_a2 = rc.col) == null ? void 0 : _a2.cellEditor) != null ? _d : ((_b = rc.col) == null ? void 0 : _b.type) === "number" ? "number" : ((_c = rc.col) == null ? void 0 : _c.type) === "date" ? "date" : "text";
1149
+ };
1150
+ const undoStack = [];
1151
+ const redoStack = [];
1152
+ const canUndo = ref(false);
1153
+ const applyChanges = (changes, dir) => {
1154
+ for (const c of changes) {
1155
+ const v = dir === "new" ? c.newValue : c.oldValue;
1156
+ if (c.col.valueSetter) c.col.valueSetter(c.row, v);
1157
+ else if (c.col.field) setByPath(c.row, c.col.field, v);
1158
+ emit("cell-value-changed", { row: c.row, colId: colIdOf(c.col), oldValue: dir === "new" ? c.oldValue : c.newValue, newValue: v });
1159
+ }
1160
+ dataVersion.value++;
1161
+ };
1162
+ const record = (changes) => {
1163
+ if (!changes.length) return;
1164
+ applyChanges(changes, "new");
1165
+ undoStack.push(changes);
1166
+ if (undoStack.length > 100) undoStack.shift();
1167
+ redoStack.length = 0;
1168
+ canUndo.value = true;
1169
+ };
1170
+ const undo = () => {
1171
+ const c = undoStack.pop();
1172
+ if (c) {
1173
+ applyChanges(c, "old");
1174
+ redoStack.push(c);
1175
+ }
1176
+ canUndo.value = undoStack.length > 0;
1177
+ };
1178
+ const redo = () => {
1179
+ const c = redoStack.pop();
1180
+ if (c) {
1181
+ applyChanges(c, "new");
1182
+ undoStack.push(c);
1183
+ }
1184
+ canUndo.value = undoStack.length > 0;
1185
+ };
1186
+ const parseFor = (col, text, row) => {
1187
+ if (col.valueParser) return col.valueParser(text, row);
1188
+ if (col.type === "number") return text === "" ? null : Number(text.replace(/[^\d.-]/g, ""));
1189
+ if (col.type === "boolean") return /^(true|1|yes|✓)$/i.test(text);
1190
+ return text;
1191
+ };
1192
+ const startEdit = (rowIndex, flatCol, initial) => {
1193
+ const c = flatCols.value[flatCol];
1194
+ const r = rowAt(rowIndex);
1195
+ if (!c || !r || r.kind !== "data" || !isEditable(c.col, r.data)) return;
1196
+ if (c.col.type === "boolean") return record([{ row: r.data, col: c.col, oldValue: cellValue(c, r.data), newValue: !cellValue(c, r.data) }]);
1197
+ editing.value = { row: rowIndex, colId: c.id, value: initial != null ? initial : cellValue(c, r.data) };
1198
+ nextTick(() => {
1199
+ var _a2, _b;
1200
+ const el = (_a2 = viewport.value) == null ? void 0 : _a2.querySelector(".sq-datagrid__editor");
1201
+ el == null ? void 0 : el.focus();
1202
+ if (initial === void 0) (_b = el == null ? void 0 : el.select) == null ? void 0 : _b.call(el);
1203
+ });
1204
+ };
1205
+ const onEditorInput = (e) => editing.value && (editing.value = { ...editing.value, value: e.target.value });
1206
+ const commitEdit = () => {
1207
+ var _a2;
1208
+ const ed = editing.value;
1209
+ if (!ed) return;
1210
+ editing.value = null;
1211
+ const r = rowAt(ed.row);
1212
+ const c = flatCols.value.find((x) => x.id === ed.colId);
1213
+ if (!(r == null ? void 0 : r.data) || !c) return;
1214
+ const newValue = parseFor(c.col, String((_a2 = ed.value) != null ? _a2 : ""), r.data);
1215
+ const oldValue = cellValue(c, r.data);
1216
+ if (newValue !== oldValue) record([{ row: r.data, col: c.col, oldValue, newValue }]);
1217
+ };
1218
+ const cancelEdit = () => {
1219
+ var _a2;
1220
+ editing.value = null;
1221
+ (_a2 = rootEl()) == null ? void 0 : _a2.focus();
1222
+ };
1223
+ const onEditorKey = (e) => {
1224
+ var _a2;
1225
+ if (e.key === "Enter" || e.key === "Tab") {
1226
+ e.preventDefault();
1227
+ commitEdit();
1228
+ (_a2 = rootEl()) == null ? void 0 : _a2.focus();
1229
+ moveFocus(e.key === "Enter" ? e.shiftKey ? -1 : 1 : 0, e.key === "Tab" ? e.shiftKey ? -1 : 1 : 0, false);
1230
+ } else if (e.key === "Escape") cancelEdit();
1231
+ };
1232
+ const onCellDblclick = (vr, rc) => rc.col && startEdit(vr.index, rc.flatIndex);
1233
+ const rootEl = () => {
1234
+ var _a2;
1235
+ return (_a2 = viewport.value) == null ? void 0 : _a2.parentElement;
1236
+ };
1237
+ const ensureVisible = (row, col) => {
1238
+ const el = viewport.value;
1239
+ if (!el) return;
1240
+ const offs = layout.value.offsets;
1241
+ const top = offs ? offs[row] : row * props.rowHeight;
1242
+ const h = offs ? offs[row + 1] - offs[row] : props.rowHeight;
1243
+ const bodyTop = el.scrollTop;
1244
+ const visibleH = el.clientHeight - headBlock.value;
1245
+ if (top < bodyTop) el.scrollTop = top;
1246
+ else if (top + h > bodyTop + visibleH) el.scrollTop = top + h - visibleH;
1247
+ const c = flatCols.value[col];
1248
+ if (c && !c.pinned) {
1249
+ const ci = visibleCols.value.center.indexOf(c);
1250
+ const x = centerOffsets.value[ci];
1251
+ const viewW = el.clientWidth - leftWidth.value - rightWidth.value;
1252
+ if (x < el.scrollLeft) el.scrollLeft = x;
1253
+ else if (x + c.width > el.scrollLeft + viewW) el.scrollLeft = x + c.width - viewW;
1254
+ }
1255
+ };
1256
+ const moveFocus = (dr, dc, extend) => {
1257
+ var _a2;
1258
+ const f = (_a2 = focus.value) != null ? _a2 : { row: 0, col: 0 };
1259
+ 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)) };
1260
+ focus.value = next;
1261
+ if (extend && anchor) setRange(anchor, next);
1262
+ else {
1263
+ anchor = next;
1264
+ setRange(next, next);
1265
+ }
1266
+ ensureVisible(next.row, next.col);
1267
+ };
1268
+ const rangeCells = () => {
1269
+ var _a2;
1270
+ const r = (_a2 = cellRange.value) != null ? _a2 : focus.value ? { startRow: focus.value.row, endRow: focus.value.row, startCol: focus.value.col, endCol: focus.value.col } : null;
1271
+ return r;
1272
+ };
1273
+ const copy = async (withHeaders = false) => {
1274
+ const r = rangeCells();
1275
+ let lines = [];
1276
+ let header = [];
1277
+ if (props.rowSelection && selectedIds.value.length && (!r || r.startRow === r.endRow && r.startCol === r.endCol)) {
1278
+ const cols = flatCols.value.filter((c) => !c.auto);
1279
+ header = cols.map((c) => c.title);
1280
+ const sel = selectedSet.value;
1281
+ lines = viewIdx.value.filter((i) => sel.has(rowIdOf(viewRows.value[i], i))).map((i) => cols.map((c) => {
1282
+ var _a2;
1283
+ return String((_a2 = cellValue(c, viewRows.value[i])) != null ? _a2 : "");
1284
+ }));
1285
+ } else if (r) {
1286
+ const cols = flatCols.value.slice(r.startCol, r.endCol + 1).filter((c) => !c.auto);
1287
+ header = cols.map((c) => c.title);
1288
+ for (let i = r.startRow; i <= r.endRow; i++) {
1289
+ const row = rowAt(i);
1290
+ if ((row == null ? void 0 : row.kind) === "data") lines.push(cols.map((c) => {
1291
+ var _a2;
1292
+ return String((_a2 = cellValue(c, row.data)) != null ? _a2 : "");
1293
+ }));
1294
+ }
1295
+ }
1296
+ const text = [...withHeaders ? [header] : [], ...lines].map((l) => l.join(" ")).join("\n");
1297
+ try {
1298
+ await navigator.clipboard.writeText(text);
1299
+ } catch {
1300
+ }
1301
+ return text;
1302
+ };
1303
+ const onPaste = (e) => {
1304
+ var _a2;
1305
+ if (editing.value || !focus.value) return;
1306
+ const text = (_a2 = e.clipboardData) == null ? void 0 : _a2.getData("text/plain");
1307
+ if (!text) return;
1308
+ e.preventDefault();
1309
+ const grid = parseTsv(text);
1310
+ const changes = [];
1311
+ grid.forEach((line, dr) => line.forEach((cellText, dc) => {
1312
+ const row = rowAt(focus.value.row + dr);
1313
+ const c = flatCols.value[focus.value.col + dc];
1314
+ if ((row == null ? void 0 : 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) });
1315
+ }));
1316
+ record(changes);
1317
+ };
1318
+ const clearRange = () => {
1319
+ const r = rangeCells();
1320
+ if (!r) return;
1321
+ const changes = [];
1322
+ for (let i = r.startRow; i <= r.endRow; i++)
1323
+ for (let j = r.startCol; j <= r.endCol; j++) {
1324
+ const row = rowAt(i);
1325
+ const c = flatCols.value[j];
1326
+ if ((row == null ? void 0 : 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 : "" });
1327
+ }
1328
+ record(changes);
1329
+ };
1330
+ const onKeydown = (e) => {
1331
+ if (editing.value || e.target.closest("input, select, textarea, .sq-datagrid__toolbar")) return;
1332
+ const mod = e.ctrlKey || e.metaKey;
1333
+ const page2 = Math.max(1, Math.floor((vpHeight.value - headBlock.value) / props.rowHeight) - 1);
1334
+ const map = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1], PageUp: [-page2, 0], PageDown: [page2, 0] };
1335
+ if (map[e.key]) {
1336
+ e.preventDefault();
1337
+ moveFocus(map[e.key][0], map[e.key][1], e.shiftKey);
1338
+ } else if (e.key === "Home") {
1339
+ e.preventDefault();
1340
+ moveFocus(mod ? -rowCount.value : 0, -flatCols.value.length, e.shiftKey);
1341
+ } else if (e.key === "End") {
1342
+ e.preventDefault();
1343
+ moveFocus(mod ? rowCount.value : 0, flatCols.value.length, e.shiftKey);
1344
+ } else if (e.key === "Tab" && focus.value) {
1345
+ e.preventDefault();
1346
+ moveFocus(0, e.shiftKey ? -1 : 1, false);
1347
+ } else if ((e.key === "Enter" || e.key === "F2") && focus.value) {
1348
+ e.preventDefault();
1349
+ const r = rowAt(focus.value.row);
1350
+ (r == null ? void 0 : r.kind) === "group" ? toggleGroup(r) : startEdit(focus.value.row, focus.value.col);
1351
+ } else if (e.key === " " && focus.value && props.rowSelection) {
1352
+ e.preventDefault();
1353
+ const r = rowAt(focus.value.row);
1354
+ if (r && r.kind !== "loading" && r.kind !== "detail") toggleRowCheck(r);
1355
+ } else if (mod && e.key.toLowerCase() === "c") {
1356
+ e.preventDefault();
1357
+ copy(e.shiftKey);
1358
+ } else if (mod && e.key.toLowerCase() === "a") {
1359
+ e.preventDefault();
1360
+ if (props.rowSelection === "multiple") setSelected(dataIdsInView());
1361
+ else cellRange.value = { startRow: 0, endRow: rowCount.value - 1, startCol: 0, endCol: flatCols.value.length - 1 };
1362
+ } else if (mod && e.key.toLowerCase() === "z") {
1363
+ e.preventDefault();
1364
+ e.shiftKey ? redo() : undo();
1365
+ } else if (mod && e.key.toLowerCase() === "y") {
1366
+ e.preventDefault();
1367
+ redo();
1368
+ } else if (e.key === "Delete" || e.key === "Backspace") {
1369
+ e.preventDefault();
1370
+ clearRange();
1371
+ } else if (e.key.length === 1 && !mod && focus.value) startEdit(focus.value.row, focus.value.col, e.key);
1372
+ };
1373
+ const menuOpen = ref(false);
1374
+ const menuAnchor = ref(null);
1375
+ const menuColId = ref(null);
1376
+ const menuMode = ref("column");
1377
+ const ctxPos = ref({ x: 0, y: 0 });
1378
+ const menuCol = computed(() => {
1379
+ var _a2;
1380
+ return menuColId.value ? (_a2 = flatCols.value.find((c) => c.id === menuColId.value)) != null ? _a2 : null : null;
1381
+ });
1382
+ const menuFormatter = (v) => menuCol.value ? formatValue(menuCol.value.col, v, null) : String(v != null ? v : "");
1383
+ const openMenu = (e, id) => {
1384
+ menuMode.value = "column";
1385
+ menuColId.value = id;
1386
+ menuAnchor.value = e.currentTarget;
1387
+ menuOpen.value = true;
1388
+ };
1389
+ const openContext = (e, vr, rc) => {
1390
+ if (!rc.col) return;
1391
+ if (!inRange(vr.index, rc.flatIndex)) {
1392
+ const p = { row: vr.index, col: rc.flatIndex };
1393
+ focus.value = p;
1394
+ anchor = p;
1395
+ setRange(p, p);
1396
+ }
1397
+ const rect = rootEl().getBoundingClientRect();
1398
+ ctxPos.value = { x: e.clientX - rect.left, y: e.clientY - rect.top };
1399
+ menuMode.value = "context";
1400
+ menuColId.value = rc.id;
1401
+ menuAnchor.value = ctxAnchor.value;
1402
+ menuOpen.value = true;
1403
+ };
1404
+ const exportCsv = (opts = {}) => {
1405
+ var _a2;
1406
+ const cols = flatCols.value.filter((c) => !c.auto);
1407
+ const sel = selectedSet.value;
1408
+ const idx = isServer.value ? [] : viewIdx.value.filter((i) => !opts.onlySelected || sel.has(rowIdOf(viewRows.value[i], i)));
1409
+ const body = idx.map((i) => cols.map((c) => formatValue(c.col, cellValue(c, viewRows.value[i]), viewRows.value[i])));
1410
+ const csv = toCsv(cols.map((c) => c.title), body, opts.separator);
1411
+ downloadText((_a2 = opts.fileName) != null ? _a2 : "export.csv", "\uFEFF" + csv, "text/csv;charset=utf-8");
1412
+ return csv;
1413
+ };
1414
+ const bottomRows = computed(() => {
1415
+ const extra = [];
1416
+ if (props.totalsRow && !isServer.value) {
1417
+ const r = {};
1418
+ for (const c of viewCols.value) if (c.aggFunc) {
1419
+ const get = makeGetter(c);
1420
+ const v = aggregate(viewIdx.value.map((i) => get(viewRows.value[i])), c.aggFunc);
1421
+ if (c.field) setByPath(r, c.field, v);
1422
+ else r[colIdOf(c)] = v;
1423
+ }
1424
+ extra.push(r);
1425
+ }
1426
+ return [...props.pinnedBottomRows, ...extra];
1427
+ });
1428
+ const statusText = computed(() => {
1429
+ if (isServer.value) return `${serverCount.value.toLocaleString(loc.value)} rows`;
1430
+ const total = raw.value.length;
1431
+ const shown = filteredIdx.value.length;
1432
+ return shown === total ? `${total.toLocaleString(loc.value)} rows` : `${shown.toLocaleString(loc.value)} of ${total.toLocaleString(loc.value)} rows`;
1433
+ });
1434
+ const rangeStats = computed(() => {
1435
+ const r = cellRange.value;
1436
+ if (!r || r.startRow === r.endRow && r.startCol === r.endCol) return null;
1437
+ const nums = [];
1438
+ let count = 0;
1439
+ const maxCells = 2e5;
1440
+ for (let i = r.startRow; i <= r.endRow && count < maxCells; i++) {
1441
+ const row = rowAt(i);
1442
+ if ((row == null ? void 0 : row.kind) !== "data") continue;
1443
+ for (let j = r.startCol; j <= r.endCol; j++) {
1444
+ const c = flatCols.value[j];
1445
+ if (!c || c.auto) continue;
1446
+ const v = cellValue(c, row.data);
1447
+ if (v != null && v !== "") count++;
1448
+ if (typeof v === "number") nums.push(v);
1449
+ }
1450
+ }
1451
+ if (!nums.length) return { count, sum: 0, avg: 0, min: 0, max: 0 };
1452
+ const sum = nums.reduce((a, b) => a + b, 0);
1453
+ return { count, sum, avg: sum / nums.length, min: Math.min(...nums), max: Math.max(...nums) };
1454
+ });
1455
+ const headerCellClass = (rc) => {
1456
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
1457
+ return {
1458
+ "sq-datagrid__hcell--pinned-left": rc.pinned === "left",
1459
+ "sq-datagrid__hcell--pinned-right": rc.pinned === "right",
1460
+ "sq-datagrid__hcell--edge-left": rc.edgeLeft,
1461
+ "sq-datagrid__hcell--edge-right": rc.edgeRight,
1462
+ "sq-datagrid__hcell--sortable": !!rc.col && !rc.auto && rc.col.sortable !== false,
1463
+ "sq-datagrid__hcell--spacer": !rc.col,
1464
+ "sq-datagrid__hcell--drop-before": ((_a2 = dropTarget.value) == null ? void 0 : _a2.id) === rc.id && dropTarget.value.before,
1465
+ "sq-datagrid__hcell--drop-after": ((_b = dropTarget.value) == null ? void 0 : _b.id) === rc.id && !dropTarget.value.before,
1466
+ [`sq-datagrid__align-${(_e = (_c = rc.col) == null ? void 0 : _c.align) != null ? _e : ((_d = rc.col) == null ? void 0 : _d.type) === "number" ? "right" : "left"}`]: true,
1467
+ [(_g = (_f = rc.col) == null ? void 0 : _f.headerClass) != null ? _g : ""]: !!((_h = rc.col) == null ? void 0 : _h.headerClass)
1468
+ };
1469
+ };
1470
+ const cellAlignClass = (rc) => {
1471
+ var _a2, _b, _c, _d;
1472
+ return {
1473
+ "sq-datagrid__cell--pinned-left": rc.pinned === "left",
1474
+ "sq-datagrid__cell--pinned-right": rc.pinned === "right",
1475
+ "sq-datagrid__cell--edge-left": !!rc.edgeLeft,
1476
+ "sq-datagrid__cell--edge-right": !!rc.edgeRight,
1477
+ [`sq-datagrid__align-${(_d = (_a2 = rc.col) == null ? void 0 : _a2.align) != null ? _d : ((_b = rc.col) == null ? void 0 : _b.type) === "number" ? "right" : ((_c = rc.col) == null ? void 0 : _c.type) === "boolean" ? "center" : "left"}`]: !!rc.col
1478
+ };
1479
+ };
1480
+ const cellClass = (vr, rc) => {
1481
+ const base = cellAlignClass(rc);
1482
+ if (!rc.col) return base;
1483
+ base["sq-datagrid__cell--focused"] = !!focus.value && focus.value.row === vr.index && focus.value.col === rc.flatIndex;
1484
+ base["sq-datagrid__cell--range"] = inRange(vr.index, rc.flatIndex);
1485
+ base["sq-datagrid__cell--editable"] = vr.row.kind === "data" && isEditable(rc.col, vr.row.data);
1486
+ if (rc.col.cellClass && vr.row.kind === "data") {
1487
+ 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;
1488
+ if (extra) base[extra] = true;
1489
+ }
1490
+ return base;
1491
+ };
1492
+ const cellStyle = (vr, rc) => {
1493
+ var _a2;
1494
+ if (!((_a2 = rc.col) == null ? void 0 : _a2.cellStyle) || vr.row.kind !== "data") return rc.style;
1495
+ 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;
1496
+ return extra ? { ...rc.style, ...extra } : rc.style;
1497
+ };
1498
+ const rowClass = (vr) => {
1499
+ const c = {
1500
+ "sq-datagrid__row--group": vr.row.kind === "group",
1501
+ "sq-datagrid__row--detail": vr.row.kind === "detail",
1502
+ "sq-datagrid__row--selected": vr.row.kind === "data" && selectedSet.value.has(vr.row.id),
1503
+ "sq-datagrid__row--odd": vr.index % 2 === 1
1504
+ };
1505
+ if (props.rowClassName && vr.row.data && vr.row.kind === "data") {
1506
+ const x = props.rowClassName(vr.row.data);
1507
+ if (x) c[x] = true;
1508
+ }
1509
+ return c;
1510
+ };
1511
+ const showLoading = computed(() => props.loading || isServer.value && serverLoading.value && serverCount.value === 0);
1512
+ 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` };
1513
+ const api = {
1514
+ getSelectedRows: () => isServer.value ? [] : viewIdx.value.map((i) => viewRows.value[i]).filter((r, k) => selectedSet.value.has(rowIdOf(r, viewIdx.value[k]))),
1515
+ getDisplayedRows: () => display.value,
1516
+ selectAll: () => setSelected(dataIdsInView()),
1517
+ deselectAll: () => setSelected([]),
1518
+ exportCsv,
1519
+ copy,
1520
+ undo,
1521
+ redo,
1522
+ expandAll,
1523
+ collapseAll,
1524
+ autoSize,
1525
+ refresh: () => isServer.value ? purge() : dataVersion.value++,
1526
+ ensureIndexVisible: (i) => {
1527
+ var _a2, _b;
1528
+ return ensureVisible(i, (_b = (_a2 = focus.value) == null ? void 0 : _a2.col) != null ? _b : 0);
1529
+ },
1530
+ getColumnState: () => flatCols.value.filter((c) => !c.auto).map((c) => ({ colId: c.id, width: c.width, hide: false, pinned: c.pinned })),
1531
+ setColumnState: (state) => {
1532
+ colOrder.value = [...state.map((s) => s.colId), ...colOrder.value.filter((id) => !state.some((s) => s.colId === id))];
1533
+ colWidth.value = { ...colWidth.value, ...Object.fromEntries(state.filter((s) => s.width).map((s) => [s.colId, s.width])) };
1534
+ colHidden.value = { ...colHidden.value, ...Object.fromEntries(state.filter((s) => s.hide !== void 0).map((s) => [s.colId, s.hide])) };
1535
+ colPinned.value = { ...colPinned.value, ...Object.fromEntries(state.filter((s) => s.pinned !== void 0).map((s) => [s.colId, s.pinned])) };
1536
+ }
1537
+ };
1538
+ return {
1539
+ ...api,
1540
+ api,
1541
+ viewport,
1542
+ ctxAnchor,
1543
+ scrollLeft,
1544
+ vpWidth,
1545
+ isServer,
1546
+ quick,
1547
+ groupBy,
1548
+ selectedIds,
1549
+ selectedSet,
1550
+ sortModelList,
1551
+ filterModelObj,
1552
+ renderCols,
1553
+ flatCols,
1554
+ totalWidth,
1555
+ hasHeaderGroups,
1556
+ headerGroups,
1557
+ layout,
1558
+ visibleRows,
1559
+ rowCount,
1560
+ filterRowHeight,
1561
+ page,
1562
+ pageSizeState,
1563
+ pageCount,
1564
+ onPageSize,
1565
+ pageRangeText,
1566
+ hasGroups,
1567
+ detailOpen,
1568
+ onScroll,
1569
+ cellValue,
1570
+ formatValue,
1571
+ formatCell,
1572
+ cellParams,
1573
+ groupLabel,
1574
+ groupAggText,
1575
+ filterKind,
1576
+ distinctValues,
1577
+ sortIndex,
1578
+ sortDir,
1579
+ ariaSort,
1580
+ setSort,
1581
+ onHeaderClick,
1582
+ setFilter,
1583
+ floatingValue,
1584
+ onFloatingInput,
1585
+ toggleGroupBy,
1586
+ removeGroup,
1587
+ toggleGroup,
1588
+ toggleDetail,
1589
+ setHidden,
1590
+ setPinned,
1591
+ chooserCols,
1592
+ startResize,
1593
+ dragColId,
1594
+ onDragStart,
1595
+ onDragOver,
1596
+ onDrop,
1597
+ onGroupDrop,
1598
+ allSelected,
1599
+ someSelected,
1600
+ toggleAll,
1601
+ isRowChecked,
1602
+ isRowPartial,
1603
+ toggleRowCheck,
1604
+ onRowClick,
1605
+ onCellMousedown,
1606
+ onCellEnter,
1607
+ editing,
1608
+ isEditing,
1609
+ editorKind,
1610
+ onEditorInput,
1611
+ commitEdit,
1612
+ onEditorKey,
1613
+ onCellDblclick,
1614
+ canUndo,
1615
+ onKeydown,
1616
+ onPaste,
1617
+ menuOpen,
1618
+ menuAnchor,
1619
+ menuMode,
1620
+ menuCol,
1621
+ menuFormatter,
1622
+ openMenu,
1623
+ openContext,
1624
+ ctxPos,
1625
+ bottomRows,
1626
+ statusText,
1627
+ rangeStats,
1628
+ fmtNum,
1629
+ headerCellClass,
1630
+ cellAlignClass,
1631
+ cellClass,
1632
+ cellStyle,
1633
+ rowClass,
1634
+ showLoading,
1635
+ rootStyle,
1636
+ titleOf,
1637
+ toUnit,
1638
+ getByPath,
1639
+ has: (n) => !!slots[n],
1640
+ messages: computed(() => config.locale.messages)
1641
+ };
1642
+ }
1643
+ });
1644
+ var _sfc_render = function render2() {
1645
+ var _vm = this, _c = _vm._self._c;
1646
+ _vm._self._setupProxy;
1647
+ return _c("div", { staticClass: "sq-datagrid sq-surface", class: { "sq-datagrid--striped": _vm.striped, "sq-datagrid--column-lines": _vm.columnLines, "sq-datagrid--scrolled-x": _vm.scrollLeft > 0 }, style: _vm.rootStyle, attrs: { "tabindex": "0", "role": "grid", "aria-rowcount": _vm.rowCount, "aria-colcount": _vm.flatCols.length }, on: { "keydown": _vm.onKeydown, "paste": _vm.onPaste } }, [_c("SqShape", { attrs: { "clip": "" } }), _vm.toolbar || _vm.has("toolbar") ? _c("div", { staticClass: "sq-datagrid__toolbar" }, [_vm._t("toolbar", null, { "api": _vm.api }), _vm.toolbar ? _c("SqTextField", { staticClass: "sq-datagrid__quick", attrs: { "model-value": _vm.quick, "placeholder": _vm.messages.search, "prepend-inner-icon": "search", "density": "compact", "hide-details": "", "clearable": "" }, on: { "update:modelValue": function($event) {
1648
+ _vm.quick = $event || "";
1649
+ } } }) : _vm._e(), _c("span", { staticClass: "sq-spacer" }), _vm.toolbar ? _c("SqMenu", { attrs: { "close-on-content-click": false, "location": "bottom end" }, scopedSlots: _vm._u([{ key: "activator", fn: function() {
1650
+ return [_c("SqBtn", { attrs: { "prepend-icon": "columns", "variant": "text", "color": "surface", "size": "small" } }, [_vm._v("Columns")])];
1651
+ }, proxy: true }], null, false, 1865136461) }, [_c("div", { staticClass: "sq-datagrid__chooser" }, _vm._l(_vm.chooserCols, function(c) {
1652
+ return _c("SqCheckbox", { key: c.id, attrs: { "model-value": !c.hidden, "label": c.title }, on: { "update:modelValue": function($event) {
1653
+ return _vm.setHidden(c.id, !$event);
1654
+ } } });
1655
+ }), 1)]) : _vm._e(), _vm.toolbar ? _c("SqBtn", { attrs: { "prepend-icon": "download", "variant": "text", "color": "surface", "size": "small" }, on: { "click": function($event) {
1656
+ return _vm.exportCsv();
1657
+ } } }, [_vm._v("CSV")]) : _vm._e()], 2) : _vm._e(), _vm.groupPanel && !_vm.treeData && !_vm.isServer ? _c("div", { staticClass: "sq-datagrid__group-panel", on: { "dragover": function($event) {
1658
+ $event.preventDefault();
1659
+ }, "drop": _vm.onGroupDrop } }, [_c("SqIcon", { attrs: { "icon": "menu", "size": "16px" } }), !_vm.groupBy.length ? _c("span", { staticClass: "sq-datagrid__group-hint" }, [_vm._v("Drag a column header here to group rows")]) : _vm._e(), _vm._l(_vm.groupBy, function(id) {
1660
+ return _c("SqChip", { key: id, attrs: { "size": "small", "variant": "tonal", "color": "primary", "closable": "" }, on: { "click:close": function($event) {
1661
+ return _vm.removeGroup(id);
1662
+ } } }, [_vm._v(_vm._s(_vm.titleOf(id)))]);
1663
+ })], 2) : _vm._e(), _c("div", { ref: "viewport", staticClass: "sq-datagrid__viewport", style: { height: _vm.toUnit(_vm.height) }, on: { "&scroll": function($event) {
1664
+ return _vm.onScroll.apply(null, arguments);
1665
+ } } }, [_c("div", { staticClass: "sq-datagrid__canvas", style: { width: _vm.totalWidth + "px" } }, [_c("div", { staticClass: "sq-datagrid__head", attrs: { "role": "rowgroup" } }, [_vm.hasHeaderGroups ? _c("div", { staticClass: "sq-datagrid__header-row sq-datagrid__header-row--groups", style: { height: _vm.headerHeight + "px" } }, _vm._l(_vm.headerGroups, function(g) {
1666
+ return _c("div", { key: g.key, staticClass: "sq-datagrid__header-group", class: g.cls, style: g.style }, [_vm._v(_vm._s(g.label))]);
1667
+ }), 0) : _vm._e(), _c("div", { staticClass: "sq-datagrid__header-row", style: { height: _vm.headerHeight + "px" }, attrs: { "role": "row" } }, _vm._l(_vm.renderCols, function(rc) {
1668
+ return _c("div", { key: rc.key, staticClass: "sq-datagrid__hcell", class: _vm.headerCellClass(rc), style: rc.style, attrs: { "role": "columnheader", "aria-sort": rc.col ? _vm.ariaSort(rc.id) : void 0, "draggable": !!rc.col && !rc.auto && !rc.col.lockPosition }, on: { "click": function($event) {
1669
+ rc.col && _vm.onHeaderClick($event, rc);
1670
+ }, "dragstart": function($event) {
1671
+ return _vm.onDragStart($event, rc);
1672
+ }, "dragover": function($event) {
1673
+ $event.preventDefault();
1674
+ return _vm.onDragOver($event, rc);
1675
+ }, "drop": function($event) {
1676
+ $event.preventDefault();
1677
+ return _vm.onDrop(rc);
1678
+ }, "dragend": function($event) {
1679
+ _vm.dragColId = null;
1680
+ } } }, [rc.col ? [rc.id === "__select" ? _c("span", { staticClass: "sq-datagrid__check", on: { "click": function($event) {
1681
+ $event.stopPropagation();
1682
+ } } }, [_c("SqCheckbox", { attrs: { "model-value": _vm.allSelected, "indeterminate": _vm.someSelected, "aria-label": "Select all rows" }, on: { "update:modelValue": _vm.toggleAll } })], 1) : [_c("span", { staticClass: "sq-datagrid__htitle" }, [_vm._t(`header-${rc.id}`, function() {
1683
+ return [_vm._v(_vm._s(rc.title))];
1684
+ }, { "column": rc.col })], 2), _vm.sortIndex(rc.id) >= 0 ? _c("span", { staticClass: "sq-datagrid__sort" }, [_c("SqIcon", { attrs: { "icon": _vm.sortDir(rc.id) === "asc" ? "arrowUp" : "arrowDown", "size": "14px" } }), _vm.sortModelList.length > 1 ? _c("sup", [_vm._v(_vm._s(_vm.sortIndex(rc.id) + 1))]) : _vm._e()], 1) : _vm._e(), _vm.filterModelObj[rc.id] ? _c("SqIcon", { staticClass: "sq-datagrid__filtered", attrs: { "icon": "filter", "size": "14px" } }) : _vm._e(), !rc.col.suppressMenu && !rc.auto ? _c("button", { staticClass: "sq-datagrid__menu-btn", attrs: { "type": "button", "tabindex": "-1", "aria-label": "Column menu" }, on: { "click": function($event) {
1685
+ $event.stopPropagation();
1686
+ return _vm.openMenu($event, rc.id);
1687
+ } } }, [_c("SqIcon", { attrs: { "icon": "more", "size": "16px" } })], 1) : _vm._e()], rc.col.resizable !== false ? _c("span", { staticClass: "sq-datagrid__resizer", on: { "pointerdown": function($event) {
1688
+ $event.stopPropagation();
1689
+ $event.preventDefault();
1690
+ return _vm.startResize($event, rc);
1691
+ }, "dblclick": function($event) {
1692
+ $event.stopPropagation();
1693
+ return _vm.autoSize([rc.id]);
1694
+ }, "click": function($event) {
1695
+ $event.stopPropagation();
1696
+ } } }) : _vm._e()] : _vm._e()], 2);
1697
+ }), 0), _vm.floatingFilters ? _c("div", { staticClass: "sq-datagrid__header-row sq-datagrid__header-row--filters", style: { height: _vm.filterRowHeight + "px" } }, _vm._l(_vm.renderCols, function(rc) {
1698
+ return _c("div", { key: rc.key, staticClass: "sq-datagrid__hcell sq-datagrid__fcell", class: _vm.headerCellClass(rc), style: rc.style }, [rc.col && !rc.auto && rc.col.filter !== false && _vm.filterKind(rc.col) !== "set" ? _c("input", { staticClass: "sq-datagrid__ffilter sq-squircle", attrs: { "type": _vm.filterKind(rc.col) === "number" ? "number" : _vm.filterKind(rc.col) === "date" ? "date" : "text", "placeholder": _vm.filterKind(rc.col) === "text" ? "…" : "=", "aria-label": `Filter ${rc.title}` }, domProps: { "value": _vm.floatingValue(rc.id) }, on: { "input": function($event) {
1699
+ return _vm.onFloatingInput($event, rc);
1700
+ } } }) : _vm._e()]);
1701
+ }), 0) : _vm._e(), _vm._l(_vm.pinnedTopRows, function(pr, pi) {
1702
+ return _c("div", { key: "pt" + pi, staticClass: "sq-datagrid__row sq-datagrid__row--pinned", style: { height: _vm.rowHeight + "px" } }, _vm._l(_vm.renderCols, function(rc) {
1703
+ return _c("div", { key: rc.key, staticClass: "sq-datagrid__cell", class: _vm.cellAlignClass(rc), style: rc.style }, [rc.col && !rc.auto ? [_vm._t(`cell-${rc.id}`, function() {
1704
+ return [_vm._v(_vm._s(_vm.formatCell(rc, pr)))];
1705
+ }, null, _vm.cellParams(pr, rc, -1))] : _vm._e()], 2);
1706
+ }), 0);
1707
+ })], 2), _c("div", { staticClass: "sq-datagrid__body", style: { height: _vm.layout.total + "px" }, attrs: { "role": "rowgroup" } }, _vm._l(_vm.visibleRows, function(vr) {
1708
+ return _c("div", { key: vr.row.id, staticClass: "sq-datagrid__row", class: _vm.rowClass(vr), style: { transform: `translateY(${vr.top}px)`, height: vr.height + "px" }, attrs: { "role": "row", "aria-rowindex": vr.index + 1, "aria-selected": vr.row.kind === "data" && _vm.rowSelection ? _vm.selectedSet.has(vr.row.id) ? "true" : "false" : void 0 }, on: { "click": function($event) {
1709
+ return _vm.onRowClick($event, vr);
1710
+ }, "dblclick": function($event) {
1711
+ return _vm.$emit("row-dblclick", { row: vr.row.data, event: $event });
1712
+ } } }, [vr.row.kind === "detail" ? _c("div", { staticClass: "sq-datagrid__detail", style: { width: _vm.vpWidth + "px" } }, [_vm._t("detail", null, { "row": vr.row.data })], 2) : _vm._l(_vm.renderCols, function(rc) {
1713
+ var _a, _b, _c2, _d, _e, _f, _g, _h, _i;
1714
+ return _c("div", { key: rc.key, staticClass: "sq-datagrid__cell", class: _vm.cellClass(vr, rc), style: _vm.cellStyle(vr, rc), attrs: { "role": "gridcell" }, on: { "mousedown": function($event) {
1715
+ return _vm.onCellMousedown($event, vr, rc);
1716
+ }, "mouseenter": function($event) {
1717
+ return _vm.onCellEnter(vr, rc);
1718
+ }, "dblclick": function($event) {
1719
+ $event.stopPropagation();
1720
+ return _vm.onCellDblclick(vr, rc);
1721
+ }, "contextmenu": function($event) {
1722
+ $event.preventDefault();
1723
+ return _vm.openContext($event, vr, rc);
1724
+ } } }, [!rc.col ? void 0 : vr.row.kind === "loading" ? _c("span", { staticClass: "sq-datagrid__skeleton sq-skeleton-shimmer" }) : rc.id === "__select" ? _c("span", { staticClass: "sq-datagrid__check", on: { "click": function($event) {
1725
+ $event.stopPropagation();
1726
+ }, "mousedown": function($event) {
1727
+ $event.stopPropagation();
1728
+ } } }, [_c("SqCheckbox", { attrs: { "model-value": _vm.isRowChecked(vr.row), "indeterminate": _vm.isRowPartial(vr.row), "aria-label": "Select row" }, on: { "update:modelValue": function($event) {
1729
+ return _vm.toggleRowCheck(vr.row);
1730
+ } } })], 1) : rc.id === "__group" ? _c("span", { staticClass: "sq-datagrid__group-cell", style: { paddingInlineStart: vr.row.level * 18 + "px" } }, [vr.row.kind === "group" ? _c("button", { staticClass: "sq-datagrid__expander", class: { "sq-datagrid__expander--open": (_a = vr.row.group) == null ? void 0 : _a.expanded }, attrs: { "type": "button", "tabindex": "-1" }, on: { "click": function($event) {
1731
+ $event.stopPropagation();
1732
+ return _vm.toggleGroup(vr.row);
1733
+ } } }, [_c("SqIcon", { attrs: { "icon": "chevronRight", "size": "18px" } })], 1) : _vm.masterDetail && !_vm.treeData ? _c("button", { staticClass: "sq-datagrid__expander", class: { "sq-datagrid__expander--open": _vm.detailOpen.has(vr.row.id) }, attrs: { "type": "button", "tabindex": "-1" }, on: { "click": function($event) {
1734
+ $event.stopPropagation();
1735
+ return _vm.toggleDetail(vr.row.id);
1736
+ } } }, [_c("SqIcon", { attrs: { "icon": "chevronRight", "size": "18px" } })], 1) : _c("span", { staticClass: "sq-datagrid__expander-spacer" }), _c("span", { staticClass: "sq-datagrid__group-key" }, [_vm._t("group", function() {
1737
+ return [_vm._v(_vm._s(_vm.groupLabel(vr.row)))];
1738
+ }, { "row": vr.row })], 2), vr.row.kind === "group" && ((_b = vr.row.group) == null ? void 0 : _b.count) ? _c("span", { staticClass: "sq-datagrid__group-count" }, [_vm._v(_vm._s((_c2 = vr.row.group) == null ? void 0 : _c2.count))]) : _vm._e()]) : vr.row.kind === "group" ? _c("span", { staticClass: "sq-datagrid__agg" }, [_vm._v(_vm._s(_vm.groupAggText(vr.row, rc)))]) : _vm.isEditing(vr, rc) ? _c("span", { staticClass: "sq-datagrid__editor-wrap", on: { "mousedown": function($event) {
1739
+ $event.stopPropagation();
1740
+ } } }, [_vm.editorKind(rc) === "select" ? _c("select", { staticClass: "sq-datagrid__editor", domProps: { "value": String((_e = (_d = _vm.editing) == null ? void 0 : _d.value) != null ? _e : "") }, on: { "change": _vm.onEditorInput, "keydown": function($event) {
1741
+ $event.stopPropagation();
1742
+ return _vm.onEditorKey.apply(null, arguments);
1743
+ }, "blur": _vm.commitEdit } }, _vm._l((_g = (_f = rc.col.cellEditorParams) == null ? void 0 : _f.values) != null ? _g : [], function(opt) {
1744
+ return _c("option", { key: String(opt), domProps: { "value": String(opt) } }, [_vm._v(_vm._s(opt))]);
1745
+ }), 0) : _c("input", { staticClass: "sq-datagrid__editor", attrs: { "type": _vm.editorKind(rc) }, domProps: { "value": (_i = (_h = _vm.editing) == null ? void 0 : _h.value) != null ? _i : "" }, on: { "input": _vm.onEditorInput, "keydown": function($event) {
1746
+ $event.stopPropagation();
1747
+ return _vm.onEditorKey.apply(null, arguments);
1748
+ }, "blur": _vm.commitEdit } })]) : [_vm._t(`cell-${rc.id}`, function() {
1749
+ return [_vm._t("cell", function() {
1750
+ return [rc.col.type === "boolean" ? _c("span", { staticClass: "sq-datagrid__bool", class: { "sq-datagrid__bool--on": !!_vm.cellValue(rc, vr.row.data) } }, [_c("SqIcon", { attrs: { "icon": _vm.cellValue(rc, vr.row.data) ? "check" : "minus", "size": "16px" } })], 1) : _c("span", { staticClass: "sq-datagrid__text" }, [_vm._v(_vm._s(_vm.formatCell(rc, vr.row.data)))])];
1751
+ }, null, _vm.cellParams(vr.row.data, rc, vr.index))];
1752
+ }, null, _vm.cellParams(vr.row.data, rc, vr.index))]], 2);
1753
+ })], 2);
1754
+ }), 0), _vm.bottomRows.length ? _c("div", { staticClass: "sq-datagrid__foot" }, _vm._l(_vm.bottomRows, function(pr, pi) {
1755
+ return _c("div", { key: "pb" + pi, staticClass: "sq-datagrid__row sq-datagrid__row--pinned", style: { height: _vm.rowHeight + "px" } }, _vm._l(_vm.renderCols, function(rc) {
1756
+ return _c("div", { key: rc.key, staticClass: "sq-datagrid__cell", class: _vm.cellAlignClass(rc), style: rc.style }, [rc.id === "__group" ? [_c("strong", [_vm._v("Total")])] : rc.col && !rc.auto ? [_vm._t(`cell-${rc.id}`, function() {
1757
+ return [_vm._v(_vm._s(_vm.formatCell(rc, pr)))];
1758
+ }, null, _vm.cellParams(pr, rc, -1))] : _vm._e()], 2);
1759
+ }), 0);
1760
+ }), 0) : _vm._e()]), _vm.showLoading ? _c("div", { staticClass: "sq-datagrid__overlay" }, [_vm._t("loading", function() {
1761
+ return [_c("SqProgressCircular", { attrs: { "indeterminate": "", "size": 28, "width": 3 } })];
1762
+ })], 2) : !_vm.rowCount ? _c("div", { staticClass: "sq-datagrid__overlay sq-datagrid__overlay--empty" }, [_vm._t("no-rows", function() {
1763
+ return [_c("SqEmptyState", { attrs: { "title": _vm.messages.noData, "icon": "search" } })];
1764
+ })], 2) : _vm._e()]), _vm.statusBar || _vm.pagination ? _c("div", { staticClass: "sq-datagrid__footer" }, [_vm.statusBar ? _c("div", { staticClass: "sq-datagrid__status" }, [_c("span", [_vm._v(_vm._s(_vm.statusText))]), _vm.selectedIds.length ? _c("span", [_vm._v("· " + _vm._s(_vm.selectedIds.length) + " selected")]) : _vm._e(), _vm.rangeStats ? _c("span", { staticClass: "sq-datagrid__range-stats" }, [_vm._v("Count " + _vm._s(_vm.rangeStats.count) + " · Sum " + _vm._s(_vm.fmtNum(_vm.rangeStats.sum)) + " · Avg " + _vm._s(_vm.fmtNum(_vm.rangeStats.avg)) + " · Min " + _vm._s(_vm.fmtNum(_vm.rangeStats.min)) + " · Max " + _vm._s(_vm.fmtNum(_vm.rangeStats.max)))]) : _vm._e()]) : _vm._e(), _c("span", { staticClass: "sq-spacer" }), _vm.pagination && !_vm.isServer ? [_c("span", { staticClass: "sq-datagrid__page-size" }, [_vm._v(_vm._s(_vm.messages.rowsPerPage) + " "), _c("select", { staticClass: "sq-datagrid__page-select sq-squircle", domProps: { "value": _vm.pageSizeState }, on: { "change": _vm.onPageSize } }, _vm._l(_vm.pageSizes, function(s) {
1765
+ return _c("option", { key: s, domProps: { "value": s } }, [_vm._v(_vm._s(s))]);
1766
+ }), 0)]), _c("span", { staticClass: "sq-datagrid__page-range" }, [_vm._v(_vm._s(_vm.pageRangeText))]), _c("SqPagination", { attrs: { "length": _vm.pageCount, "total-visible": 5, "size": "x-small" }, model: { value: _vm.page, callback: function($$v) {
1767
+ _vm.page = $$v;
1768
+ }, expression: "page" } })] : _vm._e()], 2) : _vm._e(), _c("SqMenu", { attrs: { "activator": _vm.menuAnchor || void 0, "close-on-content-click": false, "location": "bottom end", "max-height": 480 }, model: { value: _vm.menuOpen, callback: function($$v) {
1769
+ _vm.menuOpen = $$v;
1770
+ }, expression: "menuOpen" } }, [_vm.menuCol ? _c("div", { staticClass: "sq-datagrid__menu" }, [_vm.menuMode === "column" ? [_vm.menuCol.col.sortable !== false ? _c("SqListItem", { attrs: { "title": "Sort ascending", "prepend-icon": "arrowUp", "link": "" }, on: { "click": function($event) {
1771
+ return _vm.setSort(_vm.menuCol.id, "asc");
1772
+ } } }) : _vm._e(), _vm.menuCol.col.sortable !== false ? _c("SqListItem", { attrs: { "title": "Sort descending", "prepend-icon": "arrowDown", "link": "" }, on: { "click": function($event) {
1773
+ return _vm.setSort(_vm.menuCol.id, "desc");
1774
+ } } }) : _vm._e(), _vm.sortIndex(_vm.menuCol.id) >= 0 ? _c("SqListItem", { attrs: { "title": "Clear sort", "prepend-icon": "sort", "link": "" }, on: { "click": function($event) {
1775
+ return _vm.setSort(_vm.menuCol.id, null);
1776
+ } } }) : _vm._e(), _c("SqDivider"), _c("SqListItem", { attrs: { "title": _vm.menuCol.pinned === "left" ? "Unpin" : "Pin left", "prepend-icon": "pin", "link": "" }, on: { "click": function($event) {
1777
+ return _vm.setPinned(_vm.menuCol.id, _vm.menuCol.pinned === "left" ? null : "left");
1778
+ } } }), _vm.menuCol.pinned !== "right" ? _c("SqListItem", { attrs: { "title": "Pin right", "prepend-icon": "pin", "link": "" }, on: { "click": function($event) {
1779
+ return _vm.setPinned(_vm.menuCol.id, "right");
1780
+ } } }) : _vm._e(), _c("SqListItem", { attrs: { "title": "Autosize column", "prepend-icon": "columns", "link": "" }, on: { "click": function($event) {
1781
+ return _vm.autoSize([_vm.menuCol.id]);
1782
+ } } }), _c("SqListItem", { attrs: { "title": "Autosize all columns", "prepend-icon": "columns", "link": "" }, on: { "click": function($event) {
1783
+ return _vm.autoSize();
1784
+ } } }), !_vm.treeData && !_vm.isServer ? _c("SqListItem", { attrs: { "title": _vm.groupBy.includes(_vm.menuCol.id) ? `Ungroup by ${_vm.menuCol.title}` : `Group by ${_vm.menuCol.title}`, "prepend-icon": "menu", "link": "" }, on: { "click": function($event) {
1785
+ return _vm.toggleGroupBy(_vm.menuCol.id);
1786
+ } } }) : _vm._e(), _c("SqListItem", { attrs: { "title": "Hide column", "prepend-icon": "eyeOff", "link": "" }, on: { "click": function($event) {
1787
+ _vm.setHidden(_vm.menuCol.id, true);
1788
+ _vm.menuOpen = false;
1789
+ } } }), _vm.menuCol.col.filter !== false ? [_c("SqDivider", [_vm._v("Filter")]), _c("SqGridFilter", { attrs: { "kind": _vm.filterKind(_vm.menuCol.col), "model-value": _vm.filterModelObj[_vm.menuCol.id], "values": _vm.distinctValues(_vm.menuCol.id), "formatter": _vm.menuFormatter }, on: { "update:modelValue": function($event) {
1790
+ return _vm.setFilter(_vm.menuCol.id, $event);
1791
+ } } })] : _vm._e()] : [_c("SqListItem", { attrs: { "title": "Copy", "prepend-icon": "copy", "link": "" }, on: { "click": function($event) {
1792
+ _vm.copy(false);
1793
+ _vm.menuOpen = false;
1794
+ } } }), _c("SqListItem", { attrs: { "title": "Copy with headers", "prepend-icon": "copy", "link": "" }, on: { "click": function($event) {
1795
+ _vm.copy(true);
1796
+ _vm.menuOpen = false;
1797
+ } } }), _vm.canUndo ? _c("SqListItem", { attrs: { "title": "Undo", "prepend-icon": "refresh", "link": "" }, on: { "click": function($event) {
1798
+ _vm.undo();
1799
+ _vm.menuOpen = false;
1800
+ } } }) : _vm._e(), _c("SqDivider"), _c("SqListItem", { attrs: { "title": "Export CSV", "prepend-icon": "download", "link": "" }, on: { "click": function($event) {
1801
+ _vm.exportCsv();
1802
+ _vm.menuOpen = false;
1803
+ } } }), _vm.selectedIds.length ? _c("SqListItem", { attrs: { "title": "Export selected rows", "prepend-icon": "download", "link": "" }, on: { "click": function($event) {
1804
+ _vm.exportCsv({ onlySelected: true });
1805
+ _vm.menuOpen = false;
1806
+ } } }) : _vm._e(), _vm.hasGroups ? [_c("SqDivider"), _c("SqListItem", { attrs: { "title": "Expand all", "prepend-icon": "plus", "link": "" }, on: { "click": function($event) {
1807
+ _vm.expandAll();
1808
+ _vm.menuOpen = false;
1809
+ } } }), _c("SqListItem", { attrs: { "title": "Collapse all", "prepend-icon": "minus", "link": "" }, on: { "click": function($event) {
1810
+ _vm.collapseAll();
1811
+ _vm.menuOpen = false;
1812
+ } } })] : _vm._e()]], 2) : _vm._e()]), _c("div", { ref: "ctxAnchor", staticClass: "sq-datagrid__ctx-anchor", style: { left: _vm.ctxPos.x + "px", top: _vm.ctxPos.y + "px" } })], 1);
1813
+ };
1814
+ var _sfc_staticRenderFns = [];
1815
+ var __component__ = /* @__PURE__ */ normalizeComponent(
1816
+ _sfc_main,
1817
+ _sfc_render,
1818
+ _sfc_staticRenderFns
1819
+ );
1820
+ const SqDataGrid = __component__.exports;
1821
+ const componentNames = ["SqDataGrid"];
1822
+ export {
1823
+ SqDataGrid,
1824
+ aggregate,
1825
+ allGroupIds,
1826
+ colIdOf,
1827
+ componentNames,
1828
+ SqDataGrid as default,
1829
+ filterKindOf,
1830
+ filterRows,
1831
+ flatten,
1832
+ groupRows,
1833
+ makeGetter,
1834
+ matchCondition,
1835
+ parseTsv,
1836
+ pivotRows,
1837
+ rowLayout,
1838
+ sortIndices,
1839
+ toCsv,
1840
+ treeRows
1841
+ };
1842
+ //# sourceMappingURL=index.mjs.map