@freegridjs/core 1.9.5 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/freegrid.css +27 -8
- package/dist/cdn/freegrid.esm.js +24 -24
- package/dist/cdn/freegrid.min.js +22 -22
- package/dist/index.d.ts +3 -3
- package/dist/index.js +432 -78
- package/dist/locales/de.d.ts +1 -1
- package/dist/locales/de.js +2 -0
- package/dist/locales/en.d.ts +1 -1
- package/dist/locales/en.js +2 -0
- package/dist/locales/es.d.ts +1 -1
- package/dist/locales/es.js +2 -0
- package/dist/locales/fr.d.ts +1 -1
- package/dist/locales/fr.js +2 -0
- package/dist/locales/id.d.ts +1 -1
- package/dist/locales/id.js +2 -0
- package/dist/locales/it.d.ts +1 -1
- package/dist/locales/it.js +2 -0
- package/dist/locales/ja.d.ts +1 -1
- package/dist/locales/ja.js +2 -0
- package/dist/locales/ko.d.ts +1 -1
- package/dist/locales/ko.js +2 -0
- package/dist/locales/pt-BR.d.ts +1 -1
- package/dist/locales/pt-BR.js +2 -0
- package/dist/locales/ru.d.ts +1 -1
- package/dist/locales/ru.js +2 -0
- package/dist/locales/th.d.ts +1 -1
- package/dist/locales/th.js +2 -0
- package/dist/locales/vi.d.ts +1 -1
- package/dist/locales/vi.js +2 -0
- package/dist/locales/zh-CN.d.ts +1 -1
- package/dist/locales/zh-CN.js +2 -0
- package/dist/locales/zh-TW.d.ts +1 -1
- package/dist/locales/zh-TW.js +2 -0
- package/dist/styles.css +27 -8
- package/dist/{types-CIOv3MoN.d.ts → types-D5xV-gww.d.ts} +22 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -432,9 +432,10 @@ var ColumnModel = class {
|
|
|
432
432
|
setContainerWidth(width) {
|
|
433
433
|
if (width === this.containerWidth) return false;
|
|
434
434
|
this.containerWidth = width;
|
|
435
|
-
const
|
|
435
|
+
const sig = () => this.displayed().map((c) => `${c.width}${c.region}`).join();
|
|
436
|
+
const before = sig();
|
|
436
437
|
this.relayout();
|
|
437
|
-
return before !==
|
|
438
|
+
return before !== sig();
|
|
438
439
|
}
|
|
439
440
|
roots() {
|
|
440
441
|
return this.roots_;
|
|
@@ -608,7 +609,19 @@ var ColumnModel = class {
|
|
|
608
609
|
return excess > 0 ? d > 0 : excess < 0 ? d < 0 : false;
|
|
609
610
|
});
|
|
610
611
|
if (!clamped.length) {
|
|
611
|
-
|
|
612
|
+
let rest = free;
|
|
613
|
+
for (const n of pending) {
|
|
614
|
+
const w = clampWidth(n.def, share(n));
|
|
615
|
+
flexWidth.set(n, w);
|
|
616
|
+
rest -= w;
|
|
617
|
+
}
|
|
618
|
+
for (const n of pending) {
|
|
619
|
+
if (rest < 1) break;
|
|
620
|
+
const w = flexWidth.get(n);
|
|
621
|
+
if (clampWidth(n.def, w + 1) !== w + 1) continue;
|
|
622
|
+
flexWidth.set(n, w + 1);
|
|
623
|
+
rest--;
|
|
624
|
+
}
|
|
612
625
|
break;
|
|
613
626
|
}
|
|
614
627
|
let used = 0;
|
|
@@ -624,13 +637,16 @@ var ColumnModel = class {
|
|
|
624
637
|
const next = { left: [], center: [], right: [] };
|
|
625
638
|
this.leafById = /* @__PURE__ */ new Map();
|
|
626
639
|
let index = 0;
|
|
640
|
+
const pinnedWidth = visible.reduce((s, n) => s + (n.pinned ? widthOf(n) : 0), 0);
|
|
641
|
+
const unpin = this.containerWidth > 0 && pinnedWidth > this.containerWidth * 0.75;
|
|
642
|
+
const x = { left: 0, center: 0, right: 0 };
|
|
627
643
|
for (const r of REGIONS) {
|
|
628
|
-
|
|
644
|
+
const to = unpin ? "center" : r;
|
|
629
645
|
for (const n of visible) {
|
|
630
646
|
if ((n.pinned ?? "center") !== r) continue;
|
|
631
|
-
const col = { id: n.id, def: n.def, node: n, width: widthOf(n), region:
|
|
632
|
-
x += col.width;
|
|
633
|
-
next[
|
|
647
|
+
const col = { id: n.id, def: n.def, node: n, width: widthOf(n), region: to, left: x[to], index: index++ };
|
|
648
|
+
x[to] += col.width;
|
|
649
|
+
next[to].push(col);
|
|
634
650
|
this.leafById.set(n.id, col);
|
|
635
651
|
}
|
|
636
652
|
}
|
|
@@ -1361,6 +1377,7 @@ var REGIONS2 = ["left", "center", "right"];
|
|
|
1361
1377
|
var NUM_OPS = [[">=", "gte"], ["<=", "lte"], ["<>", "ne"], ["!=", "ne"], [">", "gt"], ["<", "lt"], ["=", "eq"]];
|
|
1362
1378
|
var DATE_OPS = [[">", "after"], ["<", "before"], ["=", "equals"]];
|
|
1363
1379
|
var RANGE = /^(.+?)\s*(?:~|\.\.)\s*(.+)$/;
|
|
1380
|
+
var MULTI = "~many";
|
|
1364
1381
|
var toNumber = (s) => {
|
|
1365
1382
|
const n = Number(s.replace(/[,\s₩$€¥]/g, ""));
|
|
1366
1383
|
return s.trim() !== "" && Number.isFinite(n) ? n : null;
|
|
@@ -1460,8 +1477,21 @@ var FilterRow = class {
|
|
|
1460
1477
|
box.closest(".fg-filter-cell").classList.toggle("fg-filter-active", !!model);
|
|
1461
1478
|
if (box === box.ownerDocument.activeElement || box.getRootNode().activeElement === box) continue;
|
|
1462
1479
|
if (box instanceof HTMLSelectElement) {
|
|
1463
|
-
const
|
|
1464
|
-
|
|
1480
|
+
const many = model?.type === "set" && model.values.length > 1 ? model.values.length : 0;
|
|
1481
|
+
let multi = box.querySelector(`option[value="${MULTI}"]`);
|
|
1482
|
+
if (many) {
|
|
1483
|
+
if (!multi) {
|
|
1484
|
+
multi = el("option", "", { value: MULTI });
|
|
1485
|
+
multi.disabled = true;
|
|
1486
|
+
box.options[0].after(multi);
|
|
1487
|
+
}
|
|
1488
|
+
multi.textContent = this.grid.store.state.locale.setSelected.replace("{n}", String(many));
|
|
1489
|
+
box.value = MULTI;
|
|
1490
|
+
} else {
|
|
1491
|
+
multi?.remove();
|
|
1492
|
+
const v = model?.type === "set" && model.values.length === 1 ? JSON.stringify(model.values[0]) : "";
|
|
1493
|
+
if ([...box.options].some((o) => o.value === v)) box.value = v;
|
|
1494
|
+
}
|
|
1465
1495
|
} else box.value = filterText(model);
|
|
1466
1496
|
box.classList.remove("fg-filter-bad");
|
|
1467
1497
|
}
|
|
@@ -1475,6 +1505,10 @@ var FilterRow = class {
|
|
|
1475
1505
|
if (!def) continue;
|
|
1476
1506
|
const v = select.value;
|
|
1477
1507
|
this.fillOptions(select, def);
|
|
1508
|
+
if (v === MULTI) {
|
|
1509
|
+
this.rebuilt = true;
|
|
1510
|
+
continue;
|
|
1511
|
+
}
|
|
1478
1512
|
if (v && ![...select.options].some((o) => o.value === v)) {
|
|
1479
1513
|
const o = el("option", "", { value: v });
|
|
1480
1514
|
o.textContent = String(JSON.parse(v));
|
|
@@ -1495,7 +1529,7 @@ var FilterRow = class {
|
|
|
1495
1529
|
select.replaceChildren(all2, ...opts);
|
|
1496
1530
|
}
|
|
1497
1531
|
cell(c, h) {
|
|
1498
|
-
const cell = el("div", "fg-filter-cell");
|
|
1532
|
+
const cell = el("div", "fg-filter-cell", { role: "gridcell" });
|
|
1499
1533
|
cell.style.left = `${c.left}px`;
|
|
1500
1534
|
cell.style.width = `${c.width}px`;
|
|
1501
1535
|
cell.style.height = `${h}px`;
|
|
@@ -2055,6 +2089,7 @@ var Renderer = class {
|
|
|
2055
2089
|
};
|
|
2056
2090
|
this.overlayKey = "";
|
|
2057
2091
|
this.heightFn = null;
|
|
2092
|
+
this.freeBadge = null;
|
|
2058
2093
|
this.onCardClick = (e) => {
|
|
2059
2094
|
const target = e.target;
|
|
2060
2095
|
const card = target.closest(".fg-card");
|
|
@@ -2262,6 +2297,7 @@ var Renderer = class {
|
|
|
2262
2297
|
if (ref.nextElementSibling !== b) ref.after(b);
|
|
2263
2298
|
ref = b;
|
|
2264
2299
|
}
|
|
2300
|
+
this.placeFreeBadge();
|
|
2265
2301
|
}
|
|
2266
2302
|
/** "No rows" / "Loading" over the body, or the noRowsOverlay / loadingOverlay given in the options. */
|
|
2267
2303
|
paintOverlay(count) {
|
|
@@ -2352,7 +2388,7 @@ var Renderer = class {
|
|
|
2352
2388
|
const { grid } = this;
|
|
2353
2389
|
const state = grid.store.state;
|
|
2354
2390
|
const total = grid.rowModel.server ? count : grid.viewRows().length;
|
|
2355
|
-
const key = `${this.version}.${grid.valuesVersion}|${count}|${total}|${state.selected.size}|${JSON.stringify(state.range)}|${state.locale.code}`;
|
|
2391
|
+
const key = `${this.version}.${grid.valuesVersion}|${count}|${total}|${state.selected.size}|${JSON.stringify(state.range)}|${JSON.stringify(state.extraRanges)}|${state.locale.code}`;
|
|
2356
2392
|
if (this.statusEl && key === this.statusKey) return;
|
|
2357
2393
|
this.statusKey = key;
|
|
2358
2394
|
this.statusEl ?? (this.statusEl = el("div", "fg-statusbar", { role: "status", "aria-live": "polite" }));
|
|
@@ -3224,12 +3260,21 @@ var Renderer = class {
|
|
|
3224
3260
|
/** Small "free version" mark in the bottom-right corner (unlicensed company domains flagged on freegrid.app). */
|
|
3225
3261
|
showFreeBadge() {
|
|
3226
3262
|
if (this.root.querySelector(".fg-free-badge")) return;
|
|
3227
|
-
const a = el("
|
|
3263
|
+
const a = el("div", "fg-free-badge", { "aria-hidden": "true" });
|
|
3228
3264
|
a.innerHTML = '<svg viewBox="0 0 32 32" width="14" height="14" aria-hidden="true"><rect width="32" height="32" rx="7" fill="#0E1726"/><path d="M7 11.5h18M7 16.5h18M7 21.5h18M13 7v18" stroke="#fff" stroke-width="2" stroke-linecap="round"/><rect x="14" y="12.5" width="11" height="3" rx="1" fill="#F2A900"/></svg>';
|
|
3229
3265
|
const text2 = el("span");
|
|
3230
3266
|
text2.textContent = `FreeGrid \xB7 ${this.grid.store.state.locale.freeBadge}`;
|
|
3231
3267
|
a.append(text2);
|
|
3232
3268
|
this.root.append(a);
|
|
3269
|
+
this.freeBadge = a;
|
|
3270
|
+
this.placeFreeBadge();
|
|
3271
|
+
}
|
|
3272
|
+
/** The free badge sits above the status bar and pager, not on them. */
|
|
3273
|
+
placeFreeBadge() {
|
|
3274
|
+
if (!this.freeBadge) return;
|
|
3275
|
+
const below = (this.statusEl?.isConnected ? this.statusEl.offsetHeight : 0) + (this.pagerEl?.isConnected ? this.pagerEl.offsetHeight : 0);
|
|
3276
|
+
const bottom = below ? `${below + 22}px` : "";
|
|
3277
|
+
if (this.freeBadge.style.bottom !== bottom) this.freeBadge.style.bottom = bottom;
|
|
3233
3278
|
}
|
|
3234
3279
|
/** Card view applies when enabled and the grid is narrower than the breakpoint. */
|
|
3235
3280
|
useCards() {
|
|
@@ -3549,6 +3594,8 @@ var en = {
|
|
|
3549
3594
|
apply: "Apply",
|
|
3550
3595
|
reset: "Reset",
|
|
3551
3596
|
selectAll: "(Select all)",
|
|
3597
|
+
setSelected: "({n} selected)",
|
|
3598
|
+
noAggregate: "No aggregate",
|
|
3552
3599
|
search: "Search\u2026",
|
|
3553
3600
|
blanks: "(Blanks)",
|
|
3554
3601
|
value: "Value",
|
|
@@ -3779,7 +3826,8 @@ var DEFAULT_KEYMAP = {
|
|
|
3779
3826
|
"Ctrl+Z": "undo",
|
|
3780
3827
|
"Ctrl+Y": "redo",
|
|
3781
3828
|
"Ctrl+Shift+Z": "redo",
|
|
3782
|
-
"Ctrl+F": "find"
|
|
3829
|
+
"Ctrl+F": "find",
|
|
3830
|
+
"Alt+ArrowDown": "columnMenu"
|
|
3783
3831
|
};
|
|
3784
3832
|
function comboOf(e) {
|
|
3785
3833
|
const parts = [];
|
|
@@ -3928,6 +3976,8 @@ function attachBody(grid) {
|
|
|
3928
3976
|
case "paste":
|
|
3929
3977
|
navigator.clipboard?.readText?.().then((t) => grid.pasteText(t), () => void 0);
|
|
3930
3978
|
return true;
|
|
3979
|
+
case "columnMenu":
|
|
3980
|
+
return grid.menu.openAtFocus();
|
|
3931
3981
|
}
|
|
3932
3982
|
if (!f) return false;
|
|
3933
3983
|
if (!grid.editor.canEdit(f.rowIndex, f.colId)) return false;
|
|
@@ -4156,14 +4206,14 @@ function attachBody(grid) {
|
|
|
4156
4206
|
const nested = (e) => e.target?.closest?.(".fg-root") !== root;
|
|
4157
4207
|
const onCopy = (e) => {
|
|
4158
4208
|
if (fromField(e) || nested(e)) return;
|
|
4159
|
-
const text2 = grid.
|
|
4209
|
+
const text2 = grid.copyText(false);
|
|
4160
4210
|
if (!text2 || !e.clipboardData) return;
|
|
4161
4211
|
e.clipboardData.setData("text/plain", text2);
|
|
4162
4212
|
e.preventDefault();
|
|
4163
4213
|
};
|
|
4164
4214
|
const onCut = (e) => {
|
|
4165
4215
|
if (fromField(e) || nested(e)) return;
|
|
4166
|
-
const text2 = grid.
|
|
4216
|
+
const text2 = grid.copyText(false);
|
|
4167
4217
|
if (!text2 || !e.clipboardData) return;
|
|
4168
4218
|
e.clipboardData.setData("text/plain", text2);
|
|
4169
4219
|
e.preventDefault();
|
|
@@ -4530,7 +4580,9 @@ var ColumnChooserDialog = class {
|
|
|
4530
4580
|
if (!eventInside(e, popup)) this.close();
|
|
4531
4581
|
};
|
|
4532
4582
|
const onKey = (e) => {
|
|
4533
|
-
if (e.key
|
|
4583
|
+
if (e.key !== "Escape") return;
|
|
4584
|
+
this.close();
|
|
4585
|
+
this.grid.renderer.gridEl.focus();
|
|
4534
4586
|
};
|
|
4535
4587
|
document.addEventListener("pointerdown", onDown, true);
|
|
4536
4588
|
document.addEventListener("keydown", onKey, true);
|
|
@@ -4669,12 +4721,13 @@ var ContextMenu = class {
|
|
|
4669
4721
|
const node = grid.columns.getNode(colId);
|
|
4670
4722
|
const def = node?.def;
|
|
4671
4723
|
const dataCol = !!def && !isSystemCol(colId);
|
|
4724
|
+
const checked = grid.store.state.selected.size ? grid.shownSelectedRows() : [];
|
|
4672
4725
|
const items = [
|
|
4673
4726
|
{ label: loc.copy, shortcut: shortcut("C"), action: () => grid.copyToClipboard(false) },
|
|
4674
4727
|
{ label: loc.copyWithHeaders, action: () => grid.copyToClipboard(true) },
|
|
4675
4728
|
// after the copy items, so defaultItems indexes from earlier versions still point at the same entries
|
|
4676
4729
|
{ label: loc.cut, shortcut: shortcut("X"), action: () => grid.cutToClipboard() },
|
|
4677
|
-
...
|
|
4730
|
+
...checked.length ? [{ label: loc.copyRows, action: () => grid.copyToClipboard(false, true) }] : [],
|
|
4678
4731
|
{ label: loc.paste, shortcut: shortcut("V"), action: () => this.pasteFromClipboard() }
|
|
4679
4732
|
];
|
|
4680
4733
|
if (grid.history.canUndo() || grid.history.canRedo()) {
|
|
@@ -4684,8 +4737,8 @@ var ContextMenu = class {
|
|
|
4684
4737
|
{ label: loc.redo, shortcut: shortcut("Y"), action: () => grid.redo(), disabled: !grid.history.canRedo() }
|
|
4685
4738
|
);
|
|
4686
4739
|
}
|
|
4687
|
-
if (grid.options.rowSelection &&
|
|
4688
|
-
items.push({ label: loc.deleteRows, action: () => grid.
|
|
4740
|
+
if (grid.options.rowSelection && checked.length) {
|
|
4741
|
+
items.push({ label: loc.deleteRows, action: () => grid.removeRows(checked) });
|
|
4689
4742
|
}
|
|
4690
4743
|
if (dataCol) {
|
|
4691
4744
|
items.push("separator", { label: loc.autosizeThis, action: () => grid.autoSize([colId]) });
|
|
@@ -4780,7 +4833,9 @@ var ContextMenu = class {
|
|
|
4780
4833
|
popupParent(this.grid.renderer.root).append(popup);
|
|
4781
4834
|
const w = popup.offsetWidth || 220, h = popup.offsetHeight || 300;
|
|
4782
4835
|
popup.style.left = `${Math.max(4, Math.min(x, window.innerWidth - w - 4))}px`;
|
|
4783
|
-
|
|
4836
|
+
const top = Math.max(4, Math.min(y, window.innerHeight - h - 4));
|
|
4837
|
+
popup.style.top = `${top}px`;
|
|
4838
|
+
popup.style.maxHeight = `${Math.max(120, window.innerHeight - top - 8)}px`;
|
|
4784
4839
|
this.popup = popup;
|
|
4785
4840
|
const onDown = (e) => {
|
|
4786
4841
|
if (!eventInside(e, popup)) this.close();
|
|
@@ -5070,10 +5125,28 @@ var Finder = class {
|
|
|
5070
5125
|
else this.next();
|
|
5071
5126
|
}
|
|
5072
5127
|
});
|
|
5073
|
-
this.grid.renderer
|
|
5128
|
+
const { root, headerEl, main } = this.grid.renderer;
|
|
5129
|
+
root.append(bar);
|
|
5130
|
+
const box = root.getBoundingClientRect(), head = headerEl.getBoundingClientRect(), area = main.getBoundingClientRect();
|
|
5131
|
+
if (head.height) bar.style.top = `${Math.round(head.bottom - box.top) + 6}px`;
|
|
5132
|
+
if (area.width) bar.style.right = `${Math.max(0, Math.round(box.right - area.right)) + 18}px`;
|
|
5074
5133
|
this.bar = bar;
|
|
5075
5134
|
input.focus();
|
|
5076
5135
|
}
|
|
5136
|
+
/** setLocale: the open bar's placeholder, button labels and "no matches" in the new language. */
|
|
5137
|
+
relabel() {
|
|
5138
|
+
if (!this.bar) return;
|
|
5139
|
+
const loc = this.grid.store.state.locale;
|
|
5140
|
+
const input = this.bar.querySelector("input");
|
|
5141
|
+
input.placeholder = loc.findPlaceholder;
|
|
5142
|
+
input.setAttribute("aria-label", loc.findPlaceholder);
|
|
5143
|
+
const labels = [loc.findPrevious, loc.findNext, loc.close];
|
|
5144
|
+
this.bar.querySelectorAll(".fg-findbar-btn").forEach((b, i) => {
|
|
5145
|
+
b.setAttribute("aria-label", labels[i]);
|
|
5146
|
+
b.title = labels[i];
|
|
5147
|
+
});
|
|
5148
|
+
this.updateCount();
|
|
5149
|
+
}
|
|
5077
5150
|
closeBar() {
|
|
5078
5151
|
this.bar?.remove();
|
|
5079
5152
|
this.bar = null;
|
|
@@ -5326,7 +5399,7 @@ var CellEditor = class {
|
|
|
5326
5399
|
const col = this.grid.columns.getColumn(colId);
|
|
5327
5400
|
if (!col?.def.field || rowIndex < 0 || rowIndex >= this.grid.rowModel.getRowCount()) return false;
|
|
5328
5401
|
const node = this.grid.rowModel.getRow(rowIndex);
|
|
5329
|
-
return !node.kind && cellEditable(col.def, node.data, rowIndex);
|
|
5402
|
+
return !node.kind && this.grid.cellEditable(col.def, node.data, rowIndex);
|
|
5330
5403
|
}
|
|
5331
5404
|
start(rowIndex, colId, initialText) {
|
|
5332
5405
|
if (this.cur && !this.commit(null)) return false;
|
|
@@ -5552,6 +5625,7 @@ var CellEditor = class {
|
|
|
5552
5625
|
i = cols.length - 1;
|
|
5553
5626
|
if (!this.session) r--;
|
|
5554
5627
|
}
|
|
5628
|
+
while (r !== rowIndex && r >= 0 && r < count && grid.rowModel.getRow(r)?.kind) r += step;
|
|
5555
5629
|
if (r < 0 || r >= count) return;
|
|
5556
5630
|
this.start(r, cols[i].id);
|
|
5557
5631
|
}
|
|
@@ -6661,9 +6735,9 @@ function exportColumns(grid, ids) {
|
|
|
6661
6735
|
return grid.columns.displayed().filter((c) => !isSystemCol(c.id)).map((c) => ({ id: c.id, def: c.def, node: c.node, width: c.width }));
|
|
6662
6736
|
}
|
|
6663
6737
|
function exportRows(grid, mode) {
|
|
6664
|
-
if (mode === "selected") return grid.
|
|
6738
|
+
if (mode === "selected") return grid.shownSelectedRows();
|
|
6665
6739
|
if (mode === "all") return grid.rowModel.server ? grid.rowModel.dataRows().map((n) => n.data) : grid.viewRows();
|
|
6666
|
-
return grid.
|
|
6740
|
+
return grid.orderedDataRows().map((n) => n.data);
|
|
6667
6741
|
}
|
|
6668
6742
|
var header = (def, id) => def.header ?? def.field ?? id;
|
|
6669
6743
|
var ALIGNS = ["left", "center", "right"];
|
|
@@ -7754,6 +7828,35 @@ function buildPivot(source, config, defOf, labels, locale) {
|
|
|
7754
7828
|
});
|
|
7755
7829
|
return { columns: [...rowColumns, ...valueColumns], rows, groupBy: cfg.rows.slice(0, -1) };
|
|
7756
7830
|
}
|
|
7831
|
+
var ROLLUP = /* @__PURE__ */ new WeakMap();
|
|
7832
|
+
function rollupSource(row) {
|
|
7833
|
+
return ROLLUP.get(row);
|
|
7834
|
+
}
|
|
7835
|
+
function buildRollup(source, defs) {
|
|
7836
|
+
const keys = defs.filter((d) => !d.aggFunc);
|
|
7837
|
+
const values = defs.filter((d) => d.aggFunc && d.field && !d.valueGetter);
|
|
7838
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7839
|
+
for (const r of source) {
|
|
7840
|
+
const k = keys.map((d) => setKey(getCellValue(d, r))).join("");
|
|
7841
|
+
let list = buckets.get(k);
|
|
7842
|
+
if (!list) buckets.set(k, list = []);
|
|
7843
|
+
list.push(r);
|
|
7844
|
+
}
|
|
7845
|
+
const rows = [];
|
|
7846
|
+
for (const src of buckets.values()) {
|
|
7847
|
+
const row = { ...src[0] };
|
|
7848
|
+
for (const d of values) {
|
|
7849
|
+
try {
|
|
7850
|
+
row[d.field] = aggregate(d.aggFunc, src.map((r) => getCellValue(d, r)), src);
|
|
7851
|
+
} catch {
|
|
7852
|
+
row[d.field] = null;
|
|
7853
|
+
}
|
|
7854
|
+
}
|
|
7855
|
+
ROLLUP.set(row, src);
|
|
7856
|
+
rows.push(row);
|
|
7857
|
+
}
|
|
7858
|
+
return rows;
|
|
7859
|
+
}
|
|
7757
7860
|
|
|
7758
7861
|
// src/features.ts
|
|
7759
7862
|
var PAID_FEATURES = {
|
|
@@ -7779,7 +7882,7 @@ var PAID_FEATURES = {
|
|
|
7779
7882
|
};
|
|
7780
7883
|
|
|
7781
7884
|
// src/version.ts
|
|
7782
|
-
var version = "1.
|
|
7885
|
+
var version = "1.10.0";
|
|
7783
7886
|
|
|
7784
7887
|
// src/license.ts
|
|
7785
7888
|
var PUBLIC_KEY = { kty: "EC", crv: "P-256", x: "sUTKkglZmk-HMKPNub8p7AeLBKesHCU8irIkw9rJlbE", y: "j0U_aKRDR7iApY9UpaD3hUemhBLZJwDv9-QiT_hUyw8" };
|
|
@@ -8078,6 +8181,12 @@ var ColumnMenu = class {
|
|
|
8078
8181
|
if (grouped.length) g.push([loc.expandAll, () => this.grid.expandAll(true)], [loc.collapseAll, () => this.grid.expandAll(false)]);
|
|
8079
8182
|
popup.append(this.section(g));
|
|
8080
8183
|
}
|
|
8184
|
+
if (this.grid.getRollup()) {
|
|
8185
|
+
const cur = def.aggFunc ?? null;
|
|
8186
|
+
const mark = (on, label) => `${on ? "\u2713 " : ""}${label}`;
|
|
8187
|
+
const aggs = ["sum", "avg", "min", "max", "count"].map((a) => [mark(cur === a, loc[a]), () => this.grid.setColumnAggFunc(colId, a)]);
|
|
8188
|
+
popup.append(this.section([[mark(!cur, loc.noAggregate), () => this.grid.setColumnAggFunc(colId, null)], ...aggs]));
|
|
8189
|
+
}
|
|
8081
8190
|
const items = [
|
|
8082
8191
|
[loc.autosizeThis, () => this.grid.autoSize([colId])],
|
|
8083
8192
|
[loc.autosizeAll, () => this.grid.autoSize()]
|
|
@@ -8105,14 +8214,30 @@ var ColumnMenu = class {
|
|
|
8105
8214
|
this.close();
|
|
8106
8215
|
this.grid.renderer.gridEl.focus();
|
|
8107
8216
|
};
|
|
8217
|
+
const onScroll = () => this.close();
|
|
8218
|
+
const scroller = this.grid.renderer.scroller;
|
|
8108
8219
|
document.addEventListener("pointerdown", onDown, true);
|
|
8109
8220
|
document.addEventListener("keydown", onKey, true);
|
|
8221
|
+
scroller.addEventListener("scroll", onScroll, { passive: true });
|
|
8110
8222
|
this.off.push(
|
|
8111
8223
|
() => document.removeEventListener("pointerdown", onDown, true),
|
|
8112
|
-
() => document.removeEventListener("keydown", onKey, true)
|
|
8224
|
+
() => document.removeEventListener("keydown", onKey, true),
|
|
8225
|
+
() => scroller.removeEventListener("scroll", onScroll)
|
|
8113
8226
|
);
|
|
8114
8227
|
popup.querySelector(".fg-filter-value:not([hidden]), .fg-set-search, .fg-menu-item")?.focus();
|
|
8115
8228
|
}
|
|
8229
|
+
/** Keyboard (Alt+ArrowDown): the menu of the focused cell's column (else the first column), under its header. */
|
|
8230
|
+
openAtFocus() {
|
|
8231
|
+
const { grid } = this;
|
|
8232
|
+
const f = grid.store.state.focus;
|
|
8233
|
+
const colId = f && !isSystemCol(f.colId) ? f.colId : grid.columns.displayed().find((c) => !isSystemCol(c.id))?.id;
|
|
8234
|
+
if (!colId) return false;
|
|
8235
|
+
const root = grid.renderer.root;
|
|
8236
|
+
const id = CSS.escape(colId);
|
|
8237
|
+
const anchor = root.querySelector(`.fg-header-cell:not(.fg-header-group)[data-col="${id}"]`) ?? (f ? root.querySelector(`.fg-row[data-row="${f.rowIndex}"] .fg-cell[data-col="${id}"]`) : null) ?? grid.renderer.gridEl;
|
|
8238
|
+
this.open(colId, anchor);
|
|
8239
|
+
return true;
|
|
8240
|
+
}
|
|
8116
8241
|
/** The filter UI of a column (used by the menu and the filters panel); `done` runs after apply/reset. */
|
|
8117
8242
|
filterSection(colId, done) {
|
|
8118
8243
|
const node = this.grid.columns.getNode(colId);
|
|
@@ -8137,6 +8262,8 @@ var ColumnMenu = class {
|
|
|
8137
8262
|
b.addEventListener("click", () => {
|
|
8138
8263
|
run2();
|
|
8139
8264
|
this.close();
|
|
8265
|
+
const a = activeElement(this.grid.renderer.root);
|
|
8266
|
+
if (!a || a === document.body || !a.isConnected) this.grid.renderer.gridEl.focus({ preventScroll: true });
|
|
8140
8267
|
});
|
|
8141
8268
|
s.append(b);
|
|
8142
8269
|
}
|
|
@@ -8333,6 +8460,7 @@ var RowModel = class {
|
|
|
8333
8460
|
this.sorted = [];
|
|
8334
8461
|
this.display = [];
|
|
8335
8462
|
this.indexById = null;
|
|
8463
|
+
this.orderedCache = null;
|
|
8336
8464
|
this.layoutCache = null;
|
|
8337
8465
|
/** Searchable text of each row, kept between quick filter keystrokes. */
|
|
8338
8466
|
this.quickCache = null;
|
|
@@ -8391,6 +8519,13 @@ var RowModel = class {
|
|
|
8391
8519
|
fullCount() {
|
|
8392
8520
|
return this.full.length;
|
|
8393
8521
|
}
|
|
8522
|
+
dataRowsBefore(index) {
|
|
8523
|
+
const end = Math.min(index, this.full.length);
|
|
8524
|
+
if (this.full === this.sorted) return end;
|
|
8525
|
+
let n = 0;
|
|
8526
|
+
for (let k = 0; k < end; k++) if (!this.full[k].kind) n++;
|
|
8527
|
+
return n;
|
|
8528
|
+
}
|
|
8394
8529
|
dataCount() {
|
|
8395
8530
|
return this.sorted.length;
|
|
8396
8531
|
}
|
|
@@ -8411,6 +8546,19 @@ var RowModel = class {
|
|
|
8411
8546
|
dataRows() {
|
|
8412
8547
|
return this.sorted;
|
|
8413
8548
|
}
|
|
8549
|
+
/** Filtered data rows in display order, as if every group and tree row were expanded. */
|
|
8550
|
+
orderedDataRows() {
|
|
8551
|
+
const c = this.orderedCache;
|
|
8552
|
+
if (c && c.full === this.full) return c.rows;
|
|
8553
|
+
const d = this.last.display;
|
|
8554
|
+
let rows = this.sorted;
|
|
8555
|
+
if (d && (d.getParentId || d.groupBy.length)) {
|
|
8556
|
+
const open = { ...d, expanded: /* @__PURE__ */ new Map(), defaultExpanded: -1, detailOpen: /* @__PURE__ */ new Set(), lazyChildren: void 0 };
|
|
8557
|
+
rows = this.buildDisplay(open, this.last.sort ?? [], this.last.collator ?? this.deps.collator()).filter((n) => !n.kind);
|
|
8558
|
+
}
|
|
8559
|
+
this.orderedCache = { full: this.full, rows };
|
|
8560
|
+
return rows;
|
|
8561
|
+
}
|
|
8414
8562
|
allNodes() {
|
|
8415
8563
|
return this.nodes;
|
|
8416
8564
|
}
|
|
@@ -8813,6 +8961,7 @@ var ServerRowModel = class {
|
|
|
8813
8961
|
/** Server-side grouping, while groupBy has columns. */
|
|
8814
8962
|
this.groups = null;
|
|
8815
8963
|
this.displayIn = null;
|
|
8964
|
+
this.quiet = false;
|
|
8816
8965
|
}
|
|
8817
8966
|
get bs() {
|
|
8818
8967
|
return this.page ? this.page.size : this.deps.blockSize;
|
|
@@ -8911,9 +9060,19 @@ var ServerRowModel = class {
|
|
|
8911
9060
|
const abs = this.base + index;
|
|
8912
9061
|
const hit = this.peek(abs);
|
|
8913
9062
|
if (hit) return hit;
|
|
8914
|
-
if (index >= 0 && index < this.getRowCount()) this.ensure(Math.floor(abs / this.bs));
|
|
9063
|
+
if (!this.quiet && index >= 0 && index < this.getRowCount()) this.ensure(Math.floor(abs / this.bs));
|
|
8915
9064
|
return this.placeholder(abs);
|
|
8916
9065
|
}
|
|
9066
|
+
/** Run `fn` with getRow answering from loaded blocks only (rows not loaded stay placeholders, nothing is requested). */
|
|
9067
|
+
withoutLoading(fn) {
|
|
9068
|
+
const was = this.quiet;
|
|
9069
|
+
this.quiet = true;
|
|
9070
|
+
try {
|
|
9071
|
+
return fn();
|
|
9072
|
+
} finally {
|
|
9073
|
+
this.quiet = was;
|
|
9074
|
+
}
|
|
9075
|
+
}
|
|
8917
9076
|
ensure(k) {
|
|
8918
9077
|
const cur = this.blocks.get(k);
|
|
8919
9078
|
if (cur && (cur.state !== "failed" || Date.now() < (cur.retryAt ?? 0))) return;
|
|
@@ -9335,17 +9494,23 @@ var FilterBuilder = class {
|
|
|
9335
9494
|
actions.append(reset, ok);
|
|
9336
9495
|
popup.append(head, join, list, addBtn, actions);
|
|
9337
9496
|
popupParent(grid.renderer.root).append(popup);
|
|
9497
|
+
if (!rows.length) addBtn.click();
|
|
9338
9498
|
const r = grid.renderer.root.getBoundingClientRect();
|
|
9339
9499
|
const w = popup.offsetWidth || 460;
|
|
9340
9500
|
popup.style.left = `${Math.max(4, Math.min(r.left + 24, (window.innerWidth || 1024) - w - 4))}px`;
|
|
9341
|
-
|
|
9501
|
+
const header2 = grid.renderer.headerEl.getBoundingClientRect();
|
|
9502
|
+
const vh = window.innerHeight || 768;
|
|
9503
|
+
const top = Math.max(4, Math.min((header2.height ? header2.bottom : r.top) + 8, vh - (popup.offsetHeight || 0) - 4));
|
|
9504
|
+
popup.style.top = `${top}px`;
|
|
9505
|
+
popup.style.maxHeight = `${Math.max(160, vh - top - 8)}px`;
|
|
9342
9506
|
this.popup = popup;
|
|
9343
|
-
if (!rows.length) addBtn.click();
|
|
9344
9507
|
const onDown = (e) => {
|
|
9345
9508
|
if (!eventInside(e, popup)) this.close();
|
|
9346
9509
|
};
|
|
9347
9510
|
const onKey = (e) => {
|
|
9348
|
-
if (e.key
|
|
9511
|
+
if (e.key !== "Escape") return;
|
|
9512
|
+
this.close();
|
|
9513
|
+
grid.renderer.gridEl.focus();
|
|
9349
9514
|
};
|
|
9350
9515
|
document.addEventListener("pointerdown", onDown, true);
|
|
9351
9516
|
document.addEventListener("keydown", onKey, true);
|
|
@@ -9483,8 +9648,8 @@ var FormatDialog = class {
|
|
|
9483
9648
|
CF_PRESETS.forEach((p, k) => {
|
|
9484
9649
|
const b = el("button", "fg-cf-swatch", { type: "button", "aria-label": cf.styles[p.key], title: cf.styles[p.key], "aria-pressed": String(k === preset) });
|
|
9485
9650
|
b.textContent = p.key === "bold" ? "B" : "Aa";
|
|
9486
|
-
|
|
9487
|
-
|
|
9651
|
+
b.style.background = p.style.background ?? "#ffffff";
|
|
9652
|
+
b.style.color = p.style.color ?? "#1f2430";
|
|
9488
9653
|
b.addEventListener("click", () => {
|
|
9489
9654
|
preset = k;
|
|
9490
9655
|
for (const s of swatches.children) s.setAttribute("aria-pressed", String(s === b));
|
|
@@ -9583,7 +9748,9 @@ var FormatDialog = class {
|
|
|
9583
9748
|
if (!eventInside(e, popup)) this.close();
|
|
9584
9749
|
};
|
|
9585
9750
|
const onKey = (e) => {
|
|
9586
|
-
if (e.key
|
|
9751
|
+
if (e.key !== "Escape") return;
|
|
9752
|
+
this.close();
|
|
9753
|
+
grid.renderer.gridEl.focus();
|
|
9587
9754
|
};
|
|
9588
9755
|
document.addEventListener("pointerdown", onDown, true);
|
|
9589
9756
|
document.addEventListener("keydown", onKey, true);
|
|
@@ -10027,6 +10194,10 @@ var Grid = class {
|
|
|
10027
10194
|
this.sourceDefs = [];
|
|
10028
10195
|
this.pivotCfg = null;
|
|
10029
10196
|
this.pivotData = null;
|
|
10197
|
+
/** rollup option / setRollup: rows merged by the shown columns without an aggFunc. */
|
|
10198
|
+
this.rollupOn = false;
|
|
10199
|
+
/** The merged rows while rollup applies (not while pivoting), else null. */
|
|
10200
|
+
this.rollupData = null;
|
|
10030
10201
|
/** Grouping state from before pivot mode, restored when it ends. */
|
|
10031
10202
|
this.savedGroup = null;
|
|
10032
10203
|
/** 0-based page and rows per page (pagination only). */
|
|
@@ -10093,6 +10264,8 @@ var Grid = class {
|
|
|
10093
10264
|
}
|
|
10094
10265
|
};
|
|
10095
10266
|
this.density = "normal";
|
|
10267
|
+
/** Set by the cellPadding option or setCellPadding; null: the theme / density value. */
|
|
10268
|
+
this.cellPadding = null;
|
|
10096
10269
|
// ── merge, aggregates, fill, pinned rows ────────────────────
|
|
10097
10270
|
/** `sortWithinMerges` is on. */
|
|
10098
10271
|
this.sortWithin = false;
|
|
@@ -10173,6 +10346,7 @@ var Grid = class {
|
|
|
10173
10346
|
this.renderer.applyTheme();
|
|
10174
10347
|
if (options.flashDuration) this.renderer.root.style.setProperty("--fg-flash-duration", `${this.flashMs()}ms`);
|
|
10175
10348
|
this.renderer.applyFont(this.font.size, this.font.family);
|
|
10349
|
+
if (options.cellPadding != null) this.applyCellPadding(options.cellPadding);
|
|
10176
10350
|
this.menu = new ColumnMenu(this);
|
|
10177
10351
|
this.chooser = new ColumnChooserDialog(this);
|
|
10178
10352
|
this.contextMenu = new ContextMenu(this);
|
|
@@ -10208,6 +10382,7 @@ var Grid = class {
|
|
|
10208
10382
|
this.disposers.push(() => ro.disconnect());
|
|
10209
10383
|
}
|
|
10210
10384
|
if (options.pivot) this.setPivot(options.pivot);
|
|
10385
|
+
if (options.rollup) this.setRollup(true);
|
|
10211
10386
|
void needsFreeBadge(options.licenseKey).then((show) => {
|
|
10212
10387
|
if (show && !this.destroyed) this.renderer.showFreeBadge();
|
|
10213
10388
|
});
|
|
@@ -10286,6 +10461,7 @@ var Grid = class {
|
|
|
10286
10461
|
}
|
|
10287
10462
|
/** Column definitions or visibility changed; filters/quick filter may depend on them. */
|
|
10288
10463
|
columnsChanged() {
|
|
10464
|
+
this.rebuildRollup();
|
|
10289
10465
|
this.rowModel.invalidate();
|
|
10290
10466
|
this.updateRows();
|
|
10291
10467
|
this.refreshSummary();
|
|
@@ -10308,7 +10484,7 @@ var Grid = class {
|
|
|
10308
10484
|
}
|
|
10309
10485
|
updateRows() {
|
|
10310
10486
|
const paged = !!this.options.pagination;
|
|
10311
|
-
const data = this.
|
|
10487
|
+
const data = this.viewRows();
|
|
10312
10488
|
this.rowModel.update({ ...this.store.state, data, display: this.display(), page: paged ? { index: this.page, size: this.pageSize } : null });
|
|
10313
10489
|
if (paged && this.page >= this.getPageCount()) {
|
|
10314
10490
|
this.page = this.getPageCount() - 1;
|
|
@@ -10316,9 +10492,63 @@ var Grid = class {
|
|
|
10316
10492
|
}
|
|
10317
10493
|
}
|
|
10318
10494
|
// ── pivot ───────────────────────────────────────────────────
|
|
10319
|
-
/** Rows behind the view: the pivot table while pivoting, else the source data. */
|
|
10495
|
+
/** Rows behind the view: the pivot table while pivoting, the merged rows with rollup, else the source data. */
|
|
10320
10496
|
viewRows() {
|
|
10321
|
-
return this.pivotData ?? this.store.state.data;
|
|
10497
|
+
return this.pivotData ?? this.rollupData ?? this.store.state.data;
|
|
10498
|
+
}
|
|
10499
|
+
// ── rollup ──────────────────────────────────────────────────
|
|
10500
|
+
getRollup() {
|
|
10501
|
+
return this.rollupOn;
|
|
10502
|
+
}
|
|
10503
|
+
setRollup(on) {
|
|
10504
|
+
on = !!on;
|
|
10505
|
+
if (on && !this.allow("pivot")) return;
|
|
10506
|
+
if (on && this.clientOnly("rollup")) return;
|
|
10507
|
+
if (on && this.options.treeData) {
|
|
10508
|
+
warn("rollup is not available with treeData");
|
|
10509
|
+
return;
|
|
10510
|
+
}
|
|
10511
|
+
if (on === this.rollupOn) return;
|
|
10512
|
+
this.editor.cancel();
|
|
10513
|
+
this.rollupOn = on;
|
|
10514
|
+
this.store.set({ range: null, focus: null });
|
|
10515
|
+
this.columnsChanged();
|
|
10516
|
+
}
|
|
10517
|
+
/** Merge the source rows again (rollup on, not pivoting); the view is updated by the caller. */
|
|
10518
|
+
rebuildRollup() {
|
|
10519
|
+
this.rollupData = this.rollupOn && !this.pivotCfg ? buildRollup(this.store.state.data, this.dataColumns().map((c) => c.def)) : null;
|
|
10520
|
+
}
|
|
10521
|
+
/** The source rows behind `rows`: merged rollup rows stand for the rows they merge (for group and summary values). */
|
|
10522
|
+
sourceRowsOf(rows) {
|
|
10523
|
+
return this.rollupData ? rows.flatMap((r) => rollupSource(r) ?? [r]) : rows;
|
|
10524
|
+
}
|
|
10525
|
+
/** Whether a cell can be changed: never on merged rollup rows. */
|
|
10526
|
+
cellEditable(def, row, rowIndex) {
|
|
10527
|
+
return !this.rollupData && cellEditable(def, row, rowIndex);
|
|
10528
|
+
}
|
|
10529
|
+
/** Set or clear a column's aggFunc (null: no aggregate, so with rollup it becomes a column the rows merge by). */
|
|
10530
|
+
setColumnAggFunc(colId, aggFunc) {
|
|
10531
|
+
if (aggFunc !== null && typeof aggFunc !== "function" && !["sum", "avg", "min", "max", "count"].includes(aggFunc)) {
|
|
10532
|
+
warn(`setColumnAggFunc: unknown aggFunc "${String(aggFunc)}"`);
|
|
10533
|
+
return;
|
|
10534
|
+
}
|
|
10535
|
+
let found = false;
|
|
10536
|
+
const map = (defs2) => defs2.map((d) => {
|
|
10537
|
+
if (!d || typeof d !== "object") return d;
|
|
10538
|
+
if (Array.isArray(d.children)) return { ...d, children: map(d.children) };
|
|
10539
|
+
if ((d.id ?? d.field) !== colId) return d;
|
|
10540
|
+
found = true;
|
|
10541
|
+
const next = { ...d };
|
|
10542
|
+
if (aggFunc) next.aggFunc = aggFunc;
|
|
10543
|
+
else delete next.aggFunc;
|
|
10544
|
+
return next;
|
|
10545
|
+
});
|
|
10546
|
+
const defs = map(this.sourceDefs);
|
|
10547
|
+
if (!found) {
|
|
10548
|
+
warn(`setColumnAggFunc: no column "${colId}"`);
|
|
10549
|
+
return;
|
|
10550
|
+
}
|
|
10551
|
+
this.setColumns(defs);
|
|
10322
10552
|
}
|
|
10323
10553
|
/** Leaf columns of the user's definitions (not the pivot columns). */
|
|
10324
10554
|
sourceLeaves() {
|
|
@@ -10376,6 +10606,7 @@ var Grid = class {
|
|
|
10376
10606
|
afterPivotSwitch() {
|
|
10377
10607
|
this.page = 0;
|
|
10378
10608
|
this.store.set({ sort: [], filters: {}, range: null, focus: null });
|
|
10609
|
+
this.rebuildRollup();
|
|
10379
10610
|
this.rowModel.invalidate();
|
|
10380
10611
|
this.updateRows();
|
|
10381
10612
|
this.displayVersion++;
|
|
@@ -10484,12 +10715,31 @@ var Grid = class {
|
|
|
10484
10715
|
} finally {
|
|
10485
10716
|
this.keepRange = false;
|
|
10486
10717
|
}
|
|
10718
|
+
this.clampRanges();
|
|
10487
10719
|
}
|
|
10488
10720
|
this.editor.sync();
|
|
10489
10721
|
if (flashKeys.size && this.options.flashCells !== false) this.flash(flashKeys);
|
|
10490
10722
|
this.events.emit("transactionApplied", result);
|
|
10491
10723
|
return result;
|
|
10492
10724
|
}
|
|
10725
|
+
/** Kept ranges and focus after the row count shrank: cut to the last row, dropped when wholly past it. */
|
|
10726
|
+
clampRanges() {
|
|
10727
|
+
const count = this.rowModel.getRowCount();
|
|
10728
|
+
const { range, extraRanges, focus } = this.store.state;
|
|
10729
|
+
const clamp = (r) => {
|
|
10730
|
+
if (!r || r.start.rowIndex < count && r.end.rowIndex < count) return r;
|
|
10731
|
+
if (Math.min(r.start.rowIndex, r.end.rowIndex) >= count) return null;
|
|
10732
|
+
return { start: { ...r.start, rowIndex: Math.min(r.start.rowIndex, count - 1) }, end: { ...r.end, rowIndex: Math.min(r.end.rowIndex, count - 1) } };
|
|
10733
|
+
};
|
|
10734
|
+
const extras = extraRanges.map(clamp).filter((r) => !!r);
|
|
10735
|
+
if (extras.length !== extraRanges.length || extras.some((r, i) => r !== extraRanges[i])) this.store.set({ extraRanges: extras });
|
|
10736
|
+
if (focus && focus.rowIndex >= count) this.store.set({ focus: count ? { ...focus, rowIndex: count - 1 } : null });
|
|
10737
|
+
const next = clamp(range);
|
|
10738
|
+
if (next !== range) {
|
|
10739
|
+
this.store.set({ range: next });
|
|
10740
|
+
this.events.emit("rangeChange", { range: next && { start: { ...next.start }, end: { ...next.end } } });
|
|
10741
|
+
}
|
|
10742
|
+
}
|
|
10493
10743
|
/** One transaction against `data` (remove → update → add); returns the new array. */
|
|
10494
10744
|
/** Whether rows changed in `fields` could filter, sort, group or move differently. */
|
|
10495
10745
|
viewReads(fields) {
|
|
@@ -10644,14 +10894,24 @@ var Grid = class {
|
|
|
10644
10894
|
}
|
|
10645
10895
|
if (want("groupBy") && Array.isArray(state.groupBy)) this.setGroupBy(state.groupBy.filter(known));
|
|
10646
10896
|
if (want("pivot")) this.setPivot(state.pivot ?? null);
|
|
10647
|
-
|
|
10648
|
-
if (want("
|
|
10649
|
-
const
|
|
10650
|
-
|
|
10651
|
-
this.events.emit("filterChange", { filters: { ...filters } });
|
|
10897
|
+
const query = {};
|
|
10898
|
+
if (want("sort") && Array.isArray(state.sort)) {
|
|
10899
|
+
const sort = this.checkSort(state.sort.filter((x) => x && known(x.colId)));
|
|
10900
|
+
if (sort) query.sort = sort;
|
|
10652
10901
|
}
|
|
10653
|
-
if (want("
|
|
10654
|
-
|
|
10902
|
+
if (want("filters") && state.filters && typeof state.filters === "object") {
|
|
10903
|
+
query.filters = Object.fromEntries(Object.entries(state.filters).filter(([id]) => known(id)));
|
|
10904
|
+
}
|
|
10905
|
+
if (want("advancedFilter")) {
|
|
10906
|
+
const f = state.advancedFilter;
|
|
10907
|
+
const next = f && typeof f === "object" && Array.isArray(f.conditions) && f.conditions.length ? f : null;
|
|
10908
|
+
if (next !== this.store.state.advancedFilter && (!next || this.allow("advancedFilter"))) query.advancedFilter = next;
|
|
10909
|
+
}
|
|
10910
|
+
if (want("quickFilter") && typeof state.quickFilter === "string") query.quickFilter = state.quickFilter;
|
|
10911
|
+
this.store.set(query);
|
|
10912
|
+
if (query.sort) this.events.emit("sortChange", { sort: [...query.sort] });
|
|
10913
|
+
if (query.filters) this.events.emit("filterChange", { filters: { ...query.filters } });
|
|
10914
|
+
if ("advancedFilter" in query) this.events.emit("advancedFilterChange", { advancedFilter: query.advancedFilter ?? null });
|
|
10655
10915
|
if (want("expanded") && state.expanded && typeof state.expanded === "object") {
|
|
10656
10916
|
const expanded = new Map(Object.entries(state.expanded).filter(([, v]) => typeof v === "boolean"));
|
|
10657
10917
|
if (this.savedGroup) this.savedGroup.expanded = expanded;
|
|
@@ -10677,11 +10937,13 @@ var Grid = class {
|
|
|
10677
10937
|
rows.forEach((r, k) => {
|
|
10678
10938
|
nums[k] = r.kind ? 0 : ++n;
|
|
10679
10939
|
});
|
|
10680
|
-
|
|
10940
|
+
const first = this.page * this.pageSize;
|
|
10941
|
+
const offset = this.options.pagination && !this.rowModel.server ? this.rowModel.dataRowsBefore?.(first) ?? first : 0;
|
|
10942
|
+
this.rowNumberCache = { rows, nums, offset };
|
|
10681
10943
|
}
|
|
10682
10944
|
const v = this.rowNumberCache.nums[i];
|
|
10683
10945
|
if (!v) return null;
|
|
10684
|
-
return v +
|
|
10946
|
+
return v + this.rowNumberCache.offset;
|
|
10685
10947
|
}
|
|
10686
10948
|
getPage() {
|
|
10687
10949
|
return this.options.pagination ? this.page : 0;
|
|
@@ -10733,6 +10995,7 @@ var Grid = class {
|
|
|
10733
10995
|
/** Server rows: drop the cache and load again. */
|
|
10734
10996
|
refreshRows() {
|
|
10735
10997
|
if (this.rowModel instanceof ServerRowModel) {
|
|
10998
|
+
this.saveEditBeforeReload();
|
|
10736
10999
|
this.rowModel.purge();
|
|
10737
11000
|
this.renderer.invalidate({ rows: true });
|
|
10738
11001
|
}
|
|
@@ -10742,6 +11005,12 @@ var Grid = class {
|
|
|
10742
11005
|
this.renderer.invalidate({ header: true, rows: true });
|
|
10743
11006
|
this.events.emit("rowsLoaded", total === null ? { start, end } : { start, end, total });
|
|
10744
11007
|
}
|
|
11008
|
+
/** Server rows are about to be dropped: save an open editor to its row first, else it is left over another row. */
|
|
11009
|
+
saveEditBeforeReload() {
|
|
11010
|
+
if (!this.rowModel.server) return;
|
|
11011
|
+
this.editor.endRow(true);
|
|
11012
|
+
if (this.editor.active && !this.editor.commit(null)) this.editor.cancel();
|
|
11013
|
+
}
|
|
10745
11014
|
serverFailed(start, end, error) {
|
|
10746
11015
|
if (this.destroyed) return;
|
|
10747
11016
|
warn(`datasource.getRows failed for rows ${start}\u2013${end}`);
|
|
@@ -10890,7 +11159,7 @@ var Grid = class {
|
|
|
10890
11159
|
let m = this.aggCache.map.get(node.group);
|
|
10891
11160
|
if (!m) this.aggCache.map.set(node.group, m = /* @__PURE__ */ new Map());
|
|
10892
11161
|
if (!m.has(colId)) {
|
|
10893
|
-
const rows = node.group.rows;
|
|
11162
|
+
const rows = this.sourceRowsOf(node.group.rows);
|
|
10894
11163
|
try {
|
|
10895
11164
|
m.set(colId, aggregate(def.aggFunc, rows.map((r) => getCellValue(def, r)), rows));
|
|
10896
11165
|
} catch {
|
|
@@ -11083,10 +11352,33 @@ var Grid = class {
|
|
|
11083
11352
|
this.renderer.invalidateHeights();
|
|
11084
11353
|
this.layoutChanged();
|
|
11085
11354
|
}
|
|
11355
|
+
/** Store and apply the padding; false when the value is not valid. */
|
|
11356
|
+
applyCellPadding(px) {
|
|
11357
|
+
if (px != null && !(typeof px === "number" && Number.isFinite(px) && px >= 0)) {
|
|
11358
|
+
warn("cellPadding must be a number of px, 0 or more");
|
|
11359
|
+
return false;
|
|
11360
|
+
}
|
|
11361
|
+
this.cellPadding = px;
|
|
11362
|
+
if (px == null) this.renderer.root.style.removeProperty("--fg-cell-px");
|
|
11363
|
+
else this.renderer.root.style.setProperty("--fg-cell-px", `${px}px`);
|
|
11364
|
+
return true;
|
|
11365
|
+
}
|
|
11366
|
+
setCellPadding(px) {
|
|
11367
|
+
if (px === this.cellPadding || !this.applyCellPadding(px)) return;
|
|
11368
|
+
this.menu.close();
|
|
11369
|
+
this.layoutChanged();
|
|
11370
|
+
}
|
|
11371
|
+
/** The padding in use: the set value, else the theme / density CSS variable. */
|
|
11372
|
+
getCellPadding() {
|
|
11373
|
+
if (this.cellPadding != null) return this.cellPadding;
|
|
11374
|
+
const v = parseFloat(getComputedStyle(this.renderer.root).getPropertyValue("--fg-cell-px"));
|
|
11375
|
+
return Number.isFinite(v) ? v : 12;
|
|
11376
|
+
}
|
|
11086
11377
|
/** Copy the grid font variables onto an element rendered outside the root (popups, drag ghost). */
|
|
11087
11378
|
applyFontTo(target) {
|
|
11088
11379
|
if (this.font.size) target.style.setProperty("--fg-font-size", `${this.font.size}px`);
|
|
11089
11380
|
if (this.font.family) target.style.setProperty("--fg-font", this.font.family);
|
|
11381
|
+
if (this.cellPadding != null) target.style.setProperty("--fg-cell-px", `${this.cellPadding}px`);
|
|
11090
11382
|
}
|
|
11091
11383
|
/** Current summary configuration and values, or null when there are no summary rows. */
|
|
11092
11384
|
summary() {
|
|
@@ -11115,7 +11407,7 @@ var Grid = class {
|
|
|
11115
11407
|
}
|
|
11116
11408
|
const scope = opts.scope ?? "filtered";
|
|
11117
11409
|
const rows = scope === "all" ? this.rowModel.allNodes().map((n) => n.data) : scope === "selected" ? this.selectedRows() : this.rowModel.dataRows().map((n) => n.data);
|
|
11118
|
-
this.summaryValues = computeSummary(opts.rows, rows, (id) => this.columns.getNode(id)?.def);
|
|
11410
|
+
this.summaryValues = computeSummary(opts.rows, this.sourceRowsOf(rows), (id) => this.columns.getNode(id)?.def);
|
|
11119
11411
|
}
|
|
11120
11412
|
// ── cell ranges ─────────────────────────────────────────────
|
|
11121
11413
|
dataColumns() {
|
|
@@ -11208,12 +11500,11 @@ var Grid = class {
|
|
|
11208
11500
|
out = [];
|
|
11209
11501
|
for (let i = b.r1; i <= b.r2; i++) {
|
|
11210
11502
|
const node = this.rowModel.getRow(i);
|
|
11211
|
-
if (!node.kind) out.push(node.data);
|
|
11503
|
+
if (node && !node.kind) out.push(node.data);
|
|
11212
11504
|
}
|
|
11213
11505
|
cols = displayed.slice(b.c1, b.c2 + 1).filter((c) => !isSystemCol(c.id));
|
|
11214
11506
|
} else if (checkedRows) {
|
|
11215
|
-
|
|
11216
|
-
out = this.rowModel.dataRows().filter((n) => sel.has(n.id)).map((n) => n.data);
|
|
11507
|
+
out = this.shownSelectedRows();
|
|
11217
11508
|
cols = this.dataColumns();
|
|
11218
11509
|
} else {
|
|
11219
11510
|
const f = this.store.state.focus;
|
|
@@ -11268,8 +11559,17 @@ var Grid = class {
|
|
|
11268
11559
|
if (text2) this.clearCells(true);
|
|
11269
11560
|
return text2;
|
|
11270
11561
|
}
|
|
11562
|
+
/** Text a copy puts on the clipboard. Server rows: only the loaded rows, with a warning about the rest. */
|
|
11563
|
+
copyText(headers, rows = false) {
|
|
11564
|
+
const m = this.rowModel;
|
|
11565
|
+
if (!(m instanceof ServerRowModel)) return this.selectionTSV(headers, rows);
|
|
11566
|
+
const text2 = m.withoutLoading(() => this.selectionTSV(headers, rows));
|
|
11567
|
+
const missing = rows ? 0 : m.withoutLoading(() => this.unloadedInRanges());
|
|
11568
|
+
if (missing) warn(`copy: ${missing} row${missing > 1 ? "s" : ""} of the range ${missing > 1 ? "are" : "is"} not loaded and ${missing > 1 ? "were" : "was"} not copied`);
|
|
11569
|
+
return text2;
|
|
11570
|
+
}
|
|
11271
11571
|
copyToClipboard(headers, rows = false) {
|
|
11272
|
-
const text2 = this.
|
|
11572
|
+
const text2 = this.copyText(headers, rows);
|
|
11273
11573
|
if (text2 && typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
|
|
11274
11574
|
try {
|
|
11275
11575
|
navigator.clipboard.writeText(text2)?.catch?.(() => void 0);
|
|
@@ -11278,6 +11578,14 @@ var Grid = class {
|
|
|
11278
11578
|
}
|
|
11279
11579
|
return text2;
|
|
11280
11580
|
}
|
|
11581
|
+
/** Server rows: how many rows the ranges cover that are not loaded (placeholders). */
|
|
11582
|
+
unloadedInRanges() {
|
|
11583
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
11584
|
+
for (const b of this.allRangeBounds()) for (let i = b.r1; i <= b.r2; i++) {
|
|
11585
|
+
if (this.rowModel.getRow(i)?.kind === "loading") seen2.add(i);
|
|
11586
|
+
}
|
|
11587
|
+
return seen2.size;
|
|
11588
|
+
}
|
|
11281
11589
|
pasteText(text2) {
|
|
11282
11590
|
const matrix = parseTSV(text2);
|
|
11283
11591
|
const result = { changed: 0, skipped: 0 };
|
|
@@ -11300,19 +11608,21 @@ var Grid = class {
|
|
|
11300
11608
|
const single = matrix.length === 1 && matrix[0].length === 1;
|
|
11301
11609
|
const rows = single && b ? b.r2 - b.r1 + 1 : matrix.length;
|
|
11302
11610
|
const width = single && b ? b.c2 - b.c1 + 1 : Math.max(...matrix.map((r) => r.length));
|
|
11303
|
-
for (let dr = 0; dr < rows;
|
|
11304
|
-
const ri = r0 + dr;
|
|
11305
|
-
if (ri >= count) break;
|
|
11611
|
+
for (let ri = r0, dr = 0; ri < count && dr < rows; ri++) {
|
|
11306
11612
|
const node = this.rowModel.getRow(ri);
|
|
11307
|
-
if (node.kind)
|
|
11613
|
+
if (node.kind) {
|
|
11614
|
+
if (single && b) dr++;
|
|
11615
|
+
continue;
|
|
11616
|
+
}
|
|
11617
|
+
const line2 = dr++;
|
|
11308
11618
|
for (let dc = 0; dc < width; dc++) {
|
|
11309
11619
|
const col = displayed[c0 + dc];
|
|
11310
11620
|
if (!col) break;
|
|
11311
11621
|
if (isSystemCol(col.id)) continue;
|
|
11312
|
-
const raw = single && b ? matrix[0][0] : matrix[
|
|
11622
|
+
const raw = single && b ? matrix[0][0] : matrix[line2]?.[dc];
|
|
11313
11623
|
if (raw === void 0) continue;
|
|
11314
11624
|
const def = col.def;
|
|
11315
|
-
if (!def.field || !cellEditable(def, node.data, ri)) {
|
|
11625
|
+
if (!def.field || !this.cellEditable(def, node.data, ri)) {
|
|
11316
11626
|
result.skipped++;
|
|
11317
11627
|
continue;
|
|
11318
11628
|
}
|
|
@@ -11380,7 +11690,7 @@ var Grid = class {
|
|
|
11380
11690
|
const id = this.rowModel.idOf(row);
|
|
11381
11691
|
const rowIndex = this.rowModel.indexOfId(id);
|
|
11382
11692
|
for (const c of cols) {
|
|
11383
|
-
if (!cellEditable(c.def, row, rowIndex < 0 ? i : rowIndex)) continue;
|
|
11693
|
+
if (!this.cellEditable(c.def, row, rowIndex < 0 ? i : rowIndex)) continue;
|
|
11384
11694
|
const message = this.cellError(c.def, row, row[c.def.field]);
|
|
11385
11695
|
if (message !== null) out.push({ row, rowIndex, colId: c.id, message });
|
|
11386
11696
|
}
|
|
@@ -11645,26 +11955,36 @@ var Grid = class {
|
|
|
11645
11955
|
const col = displayed[c];
|
|
11646
11956
|
const node = this.rowModel.getRow(r);
|
|
11647
11957
|
const def = col?.def;
|
|
11648
|
-
if (!node || node.kind || !def?.field || isSystemCol(col.id) || !cellEditable(def, node.data, r)) return;
|
|
11958
|
+
if (!node || node.kind || !def?.field || isSystemCol(col.id) || !this.cellEditable(def, node.data, r)) return;
|
|
11649
11959
|
if (this.cellError(def, node.data, value2) !== null) return;
|
|
11650
11960
|
this.writeCell(changes, node.data, def.field, col.id, r, value2);
|
|
11651
11961
|
};
|
|
11652
11962
|
const value = (r, c) => getCellValue(displayed[c].def, this.rowModel.getRow(r).data);
|
|
11963
|
+
const dataRow = (r) => {
|
|
11964
|
+
const node = this.rowModel.getRow(r);
|
|
11965
|
+
return !!node && !node.kind;
|
|
11966
|
+
};
|
|
11967
|
+
const keep = (from, to, ok) => {
|
|
11968
|
+
const out = [];
|
|
11969
|
+
for (let i = from; i <= to; i++) if (ok(i)) out.push(i);
|
|
11970
|
+
return out;
|
|
11971
|
+
};
|
|
11972
|
+
const dataCol = (c) => !!displayed[c] && !isSystemCol(displayed[c].id);
|
|
11653
11973
|
if (t.r1 < src.r1 || t.r2 > src.r2) {
|
|
11974
|
+
const down = keep(src.r2 + 1, t.r2, dataRow), up = keep(t.r1, src.r1 - 1, dataRow).reverse();
|
|
11975
|
+
const rows = keep(src.r1, src.r2, dataRow);
|
|
11654
11976
|
for (let c = src.c1; c <= src.c2; c++) {
|
|
11655
|
-
const
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
fillSeries(down, t.r2 - src.r2).forEach((v, k) => write(src.r2 + 1 + k, c, v));
|
|
11659
|
-
fillSeries(up, src.r1 - t.r1).forEach((v, k) => write(src.r1 - 1 - k, c, v));
|
|
11977
|
+
const seed = rows.map((r) => value(r, c));
|
|
11978
|
+
fillSeries(seed, down.length).forEach((v, k) => write(down[k], c, v));
|
|
11979
|
+
fillSeries([...seed].reverse(), up.length).forEach((v, k) => write(up[k], c, v));
|
|
11660
11980
|
}
|
|
11661
11981
|
} else if (t.c1 < src.c1 || t.c2 > src.c2) {
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
fillSeries(
|
|
11667
|
-
fillSeries(
|
|
11982
|
+
const right = keep(src.c2 + 1, t.c2, dataCol), left = keep(t.c1, src.c1 - 1, dataCol).reverse();
|
|
11983
|
+
const cols = keep(src.c1, src.c2, dataCol);
|
|
11984
|
+
for (const r of keep(src.r1, src.r2, dataRow)) {
|
|
11985
|
+
const seed = cols.map((c) => value(r, c));
|
|
11986
|
+
fillSeries(seed, right.length).forEach((v, k) => write(r, right[k], v));
|
|
11987
|
+
fillSeries([...seed].reverse(), left.length).forEach((v, k) => write(r, left[k], v));
|
|
11668
11988
|
}
|
|
11669
11989
|
} else return;
|
|
11670
11990
|
this.endCellTx(changes);
|
|
@@ -11733,7 +12053,7 @@ var Grid = class {
|
|
|
11733
12053
|
const node = this.rowModel.getRow(r);
|
|
11734
12054
|
for (let c = box.c1; c <= box.c2; c++) {
|
|
11735
12055
|
const def = displayed[c]?.def;
|
|
11736
|
-
if (node && !node.kind && def?.field && cellEditable(def, node.data, r) && (!cut || this.copyAllowed(def, node.data))) this.writeCell(changes, node.data, def.field, displayed[c].id, r, null);
|
|
12056
|
+
if (node && !node.kind && def?.field && this.cellEditable(def, node.data, r) && (!cut || this.copyAllowed(def, node.data))) this.writeCell(changes, node.data, def.field, displayed[c].id, r, null);
|
|
11737
12057
|
}
|
|
11738
12058
|
}
|
|
11739
12059
|
this.endCellTx(changes);
|
|
@@ -11887,8 +12207,9 @@ var Grid = class {
|
|
|
11887
12207
|
const cols = (ids ? ids.map((id) => this.columns.getColumn(id)) : this.columns.displayed()).filter((c) => !!c && isResizable(c.def));
|
|
11888
12208
|
const { first, last } = this.renderer.renderedRange();
|
|
11889
12209
|
const code = this.store.state.locale.code;
|
|
11890
|
-
const
|
|
11891
|
-
const
|
|
12210
|
+
const pad4 = this.getCellPadding() * 2;
|
|
12211
|
+
const HEADER_EXTRA = pad4 + 22 + 6 + 14;
|
|
12212
|
+
const CELL_EXTRA = pad4;
|
|
11892
12213
|
for (const col of cols) {
|
|
11893
12214
|
let w = this.renderer.measureText(col.def.header ?? col.def.field ?? "", true) + HEADER_EXTRA;
|
|
11894
12215
|
const fmt = getFormatter(col.def, code);
|
|
@@ -11906,6 +12227,13 @@ var Grid = class {
|
|
|
11906
12227
|
this.columnsChanged();
|
|
11907
12228
|
}
|
|
11908
12229
|
setSort(sort) {
|
|
12230
|
+
const valid = this.checkSort(sort);
|
|
12231
|
+
if (!valid) return;
|
|
12232
|
+
this.store.set({ sort: valid });
|
|
12233
|
+
this.events.emit("sortChange", { sort: [...valid] });
|
|
12234
|
+
}
|
|
12235
|
+
/** The known, well-formed sort items, or null when a beforeSort handler refused them. */
|
|
12236
|
+
checkSort(sort) {
|
|
11909
12237
|
const valid = sort.filter((s) => {
|
|
11910
12238
|
const node = this.columns.getNode(s.colId);
|
|
11911
12239
|
if (!node || node.children) {
|
|
@@ -11914,9 +12242,7 @@ var Grid = class {
|
|
|
11914
12242
|
}
|
|
11915
12243
|
return s.dir === "asc" || s.dir === "desc";
|
|
11916
12244
|
});
|
|
11917
|
-
|
|
11918
|
-
this.store.set({ sort: valid });
|
|
11919
|
-
this.events.emit("sortChange", { sort: [...valid] });
|
|
12245
|
+
return this.veto("beforeSort", { sort: valid.map((s) => ({ ...s })) }) ? null : valid;
|
|
11920
12246
|
}
|
|
11921
12247
|
toggleSort(colId, additive) {
|
|
11922
12248
|
const cur = this.store.state.sort;
|
|
@@ -12086,6 +12412,15 @@ var Grid = class {
|
|
|
12086
12412
|
const sel = this.store.state.selected;
|
|
12087
12413
|
return sel.size ? this.rowModel.allNodes().filter((n) => sel.has(n.id)).map((n) => n.data) : [];
|
|
12088
12414
|
}
|
|
12415
|
+
/** Filtered data rows in display order (group buckets, parents before children), collapsed ones included. */
|
|
12416
|
+
orderedDataRows() {
|
|
12417
|
+
return this.rowModel.orderedDataRows?.() ?? this.rowModel.dataRows();
|
|
12418
|
+
}
|
|
12419
|
+
/** Checked rows that pass the filters, in display order: what copy, export and delete of the checked rows act on. */
|
|
12420
|
+
shownSelectedRows() {
|
|
12421
|
+
const sel = this.store.state.selected;
|
|
12422
|
+
return sel.size ? this.orderedDataRows().filter((n) => sel.has(n.id)).map((n) => n.data) : [];
|
|
12423
|
+
}
|
|
12089
12424
|
withSelect(defs) {
|
|
12090
12425
|
const sys = [];
|
|
12091
12426
|
const rn = this.options.rowNumbers;
|
|
@@ -12157,12 +12492,26 @@ var Grid = class {
|
|
|
12157
12492
|
});
|
|
12158
12493
|
this.columnsChanged();
|
|
12159
12494
|
}
|
|
12495
|
+
/** Close every popup of this grid (menus and dialogs); focus that was in one goes back to the grid. */
|
|
12496
|
+
closePopups() {
|
|
12497
|
+
const r = this.renderer.root.getRootNode();
|
|
12498
|
+
const inPopup = !!(r.activeElement ?? document.activeElement)?.closest(".fg-menu");
|
|
12499
|
+
this.menu.close();
|
|
12500
|
+
this.chooser.close();
|
|
12501
|
+
this.contextMenu.close();
|
|
12502
|
+
this.filterBuilder.close();
|
|
12503
|
+
this.formatDialog.close();
|
|
12504
|
+
this.assistantPanel.close();
|
|
12505
|
+
if (inPopup) this.renderer.gridEl.focus({ preventScroll: true });
|
|
12506
|
+
}
|
|
12160
12507
|
onChange(keys) {
|
|
12161
12508
|
const has = (...k) => k.some((x) => keys.includes(x));
|
|
12509
|
+
if (has("sort", "filters", "quickFilter", "advancedFilter")) this.saveEditBeforeReload();
|
|
12162
12510
|
if (this.pivotCfg && has("data", "locale")) this.rebuildPivot(false);
|
|
12511
|
+
if (this.rollupOn && has("data")) this.rebuildRollup();
|
|
12512
|
+
if (has("locale", "theme")) this.closePopups();
|
|
12163
12513
|
if (has("locale")) {
|
|
12164
|
-
this.
|
|
12165
|
-
this.chooser.close();
|
|
12514
|
+
this.finder.relabel();
|
|
12166
12515
|
this.sideBar?.refresh();
|
|
12167
12516
|
this.rowModel.invalidate();
|
|
12168
12517
|
}
|
|
@@ -12267,6 +12616,11 @@ var Grid = class {
|
|
|
12267
12616
|
setTheme: guard((t) => this.store.set({ theme: t })),
|
|
12268
12617
|
setLocale: guard((l) => this.store.set({ locale: resolveLocale(l) })),
|
|
12269
12618
|
setFont: guard((f) => this.setFont(f)),
|
|
12619
|
+
setCellPadding: guard((px) => this.setCellPadding(px)),
|
|
12620
|
+
getCellPadding: guard(() => this.getCellPadding()),
|
|
12621
|
+
setRollup: guard((on) => this.setRollup(on)),
|
|
12622
|
+
getRollup: guard(() => this.getRollup()),
|
|
12623
|
+
setColumnAggFunc: guard((id, agg) => this.setColumnAggFunc(id, agg)),
|
|
12270
12624
|
setColumnVisible: guard((id, v) => this.setColumnsVisible([id], v)),
|
|
12271
12625
|
autoSizeColumns: guard((ids) => this.autoSize(ids)),
|
|
12272
12626
|
resetColumnState: guard(() => this.resetColumns()),
|