@iyulab/flex-table 0.58.0 → 0.59.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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.59.0] - 2026-10-07
4
+
5
+ ### Changed (breaking)
6
+
7
+ - **A plain click on a body cell fires `row-activate`** (`via: 'click'`), as Enter on a non-editable cell does
8
+ (`via: 'keyboard'`) and as `u-rich-table` does. A read-only list had no pointer way to open a row, so it opened rows on
9
+ `cell-select` — which is focus and also fires when Tab arrives on the grid: one Tab into the table opened the first
10
+ row. A Shift / Ctrl / Cmd click (extends the selection), the click that ends a drag, and a click on a control the
11
+ cell renders (a link, a button, a field) do not activate. A listener that only wants Enter checks
12
+ `e.detail.via === 'keyboard'`.
13
+ - `cell-select` carries the row's `id` — `row` is the visible position, which is not the row in `data` once a client
14
+ sort or filter is on.
15
+ - Requires `@iyulab/components` 2.15.0 (the shared «pressed a control» test, `isFromControl`).
16
+
17
+ ### Migration
18
+
19
+ - Open rows on `row-activate`, not `cell-select`.
20
+ - If you listened to `row-activate` for Enter only (a picker that confirms on Enter), add
21
+ `if (e.detail.via !== 'keyboard') return;`.
22
+
3
23
  ## [0.58.0] - 2026-10-07
4
24
 
5
25
  ### Added
package/README.md CHANGED
@@ -303,7 +303,7 @@ type-checks without a cast. The React wrapper's `on*` props carry the same types
303
303
 
304
304
  | Event | Detail | Description |
305
305
  |-------|--------|-------------|
306
- | `cell-select` | `{ row, col }` or `null` | Cell focus changed (`null` when no cell is active) |
306
+ | `cell-select` | `{ row, col, id }` or `null` | Cell focus changed (`null` when no cell is active). `row`/`col` are visible positions, `id` the row's id. Fires when keyboard focus arrives on the grid too — it is focus, not a choice: open rows on `row-activate` |
307
307
  | `cell-edit-start` | `{ row, col, key, value }` | Cell editing started |
308
308
  | `cell-edit-commit` | `{ row, col, key, oldValue, newValue }` | Cell value committed |
309
309
  | `cell-edit-cancel` | `{ row, col }` | Cell edit cancelled (Escape, or its row left `data`). `row` is the data index (`-1` once the row is gone) |
@@ -315,7 +315,7 @@ type-checks without a cast. The React wrapper's `on*` props carry the same types
315
315
  |-------|--------|-------------|
316
316
  | `row-add` | `{ row, index }` | Row added |
317
317
  | `row-delete` | `{ indices, rows }` | Rows deleted |
318
- | `row-activate` | `{ row, id, index, col, key }` | Enter pressed on a non-editable cell — the grid's own contract for "activate this row" (e.g. navigate to a detail view), guaranteed even though the internal Enter handler prevents the keystroke from reliably reaching a listener the host attaches to the same element |
318
+ | `row-activate` | `{ row, id, via, index, col, key }` | "Open this row" (e.g. navigate to a detail view): a plain click on a body cell (`via: 'click'`), or Enter on a non-editable cell (`via: 'keyboard'`). Not a Shift / Ctrl / Cmd click (those extend the selection), the click that ends a drag, or a click on a control the cell renders (a link, a button). The grid's own contract — its Enter handler keeps the keystroke from reliably reaching a listener the host attaches to the same element |
319
319
  | `batch-update` | `{ changes: [{ row, key, oldValue, newValue }] }` | Batch update applied |
320
320
  | `row-reorder` | `{ from, to }` | Row dragged to a new place (data indices) |
321
321
  | `data-import` | `{ count }` | Rows imported from a file |
package/dist/events.d.ts CHANGED
@@ -84,11 +84,16 @@ export interface FlexTableEventMap {
84
84
  from: number;
85
85
  to: number;
86
86
  }>;
87
- /** Enter on a non-editable cell — "activate this row". `index` is the data index, `col` the visible column index. */
88
- /** `id` — the row's id (`getRowId`); `index` — its position in `data`; `key` — the active column's key. */
87
+ /**
88
+ * "Open this row": a plain click on a body cell, or Enter on a non-editable cell. `via` tells them apart.
89
+ * Not a click that selects a range (Shift / Ctrl / Cmd), ends a drag, or presses a control the cell renders.
90
+ * `id` — the row's id (`getRowId`); `index` — its position in `data`; `col` — the visible column index;
91
+ * `key` — that column's key.
92
+ */
89
93
  'row-activate': CustomEvent<{
90
94
  row: DataRow;
91
95
  id: string;
96
+ via: 'click' | 'keyboard';
92
97
  index: number;
93
98
  col: number;
94
99
  key: string | undefined;
@@ -97,8 +102,13 @@ export interface FlexTableEventMap {
97
102
  'batch-update': CustomEvent<{
98
103
  changes: CellChange[];
99
104
  }>;
100
- /** The active cell moved; `null` when there is none. */
101
- 'cell-select': CustomEvent<CellPosition | null>;
105
+ /**
106
+ * The active cell moved — by pointer, keyboard, or focus arriving on the grid; `null` when there is none.
107
+ * `row`/`col` are visible positions, `id` the row's id. This is focus, not a choice: open a row on `row-activate`.
108
+ */
109
+ 'cell-select': CustomEvent<(CellPosition & {
110
+ id: string;
111
+ }) | null>;
102
112
  /** `row` is the data index, `col` the visible column index. */
103
113
  'cell-edit-start': CustomEvent<{
104
114
  row: number;
@@ -8,8 +8,9 @@ import { decodeTsv as g, encodeTsv as _ } from "@iyulab/components/dist/utilitie
8
8
  import "@iyulab/components/dist/components/date-picker/UDatePicker.js";
9
9
  import { isImeComposing as v } from "@iyulab/components/dist/utilities/keyboard.js";
10
10
  import { copyFromKey as y, isTextEntry as b, pasteFromKey as x } from "@iyulab/components/dist/utilities/clipboard.js";
11
+ import { isFromControl as S } from "@iyulab/components/dist/utilities/elements.js";
11
12
  //#region src/styles/flex-table.styles.ts
12
- var S = i`
13
+ var C = i`
13
14
  /* --- Theme Variables (Light defaults) --- */
14
15
  :host {
15
16
  --ft-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -1028,13 +1029,13 @@ var S = i`
1028
1029
  `;
1029
1030
  //#endregion
1030
1031
  //#region src/renderers/format.ts
1031
- function C(e, t) {
1032
- return e == null ? "" : typeof t == "function" ? t(e) : w(t) ? E(e, t) : T(e, t);
1032
+ function w(e, t) {
1033
+ return e == null ? "" : typeof t == "function" ? t(e) : T(t) ? ee(e, t) : E(e, t);
1033
1034
  }
1034
- function w(e) {
1035
+ function T(e) {
1035
1036
  return /[yMdHhms]/.test(e);
1036
1037
  }
1037
- function T(e, t) {
1038
+ function E(e, t) {
1038
1039
  let n = typeof e == "number" ? e : Number(e);
1039
1040
  if (isNaN(n)) return String(e);
1040
1041
  let r = t.endsWith("%"), i = t.match(/^([^#0.,%]+)/), a = i ? i[1] : "", o = t.replace(/^[^#0.,%]+/, "").replace(/%$/, ""), s = o.match(/\.([0#]+)$/), c = s ? s[1].length : 0, l = {
@@ -1047,7 +1048,7 @@ function T(e, t) {
1047
1048
  style: "percent"
1048
1049
  }).format(n) : (d = new Intl.NumberFormat(u.get(), l).format(n), a && (d = a + d)), d + "";
1049
1050
  }
1050
- function E(e, t) {
1051
+ function ee(e, t) {
1051
1052
  let n;
1052
1053
  if (e instanceof Date) n = e;
1053
1054
  else if (typeof e == "string" || typeof e == "number") n = new Date(e);
@@ -1059,25 +1060,25 @@ function E(e, t) {
1059
1060
  //#endregion
1060
1061
  //#region src/renderers/cell-renderer.ts
1061
1062
  function D(e, t, n) {
1062
- return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : C(e, n.format) : ee(e, n);
1063
+ return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : w(e, n.format) : te(e, n);
1063
1064
  }
1064
- function ee(e, t) {
1065
+ function te(e, t) {
1065
1066
  if (e == null) return "";
1066
1067
  switch (t.type) {
1067
- case "number": return re(e);
1068
+ case "number": return ie(e);
1068
1069
  case "boolean": return a`<span class="ft-bool">${e ? "✔" : ""}</span>`;
1069
- case "date": return ie(e);
1070
- case "datetime": return ae(e);
1071
- case "select": return te(e, t);
1070
+ case "date": return ae(e);
1071
+ case "datetime": return oe(e);
1072
+ case "select": return ne(e, t);
1072
1073
  default: return String(e);
1073
1074
  }
1074
1075
  }
1075
- function te(e, t) {
1076
+ function ne(e, t) {
1076
1077
  if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
1077
1078
  let n = t.options.find((t) => t.value === e);
1078
1079
  return n ? n.label : e == null ? "" : String(e);
1079
1080
  }
1080
- var ne = {
1081
+ var re = {
1081
1082
  year: "numeric",
1082
1083
  month: "numeric",
1083
1084
  day: "numeric",
@@ -1085,18 +1086,18 @@ var ne = {
1085
1086
  minute: "numeric",
1086
1087
  second: "numeric"
1087
1088
  };
1088
- function re(e) {
1089
+ function ie(e) {
1089
1090
  return typeof e == "number" ? Number.isInteger(e) ? f(e) : f(e, { minimumFractionDigits: 1 }) : String(e);
1090
1091
  }
1091
- function ie(e) {
1092
+ function ae(e) {
1092
1093
  return e instanceof Date || typeof e == "string" ? d(e) : String(e);
1093
1094
  }
1094
- function ae(e) {
1095
- return e instanceof Date || typeof e == "string" ? d(e, ne) : String(e);
1095
+ function oe(e) {
1096
+ return e instanceof Date || typeof e == "string" ? d(e, re) : String(e);
1096
1097
  }
1097
1098
  //#endregion
1098
1099
  //#region src/core/selection.ts
1099
- function oe(e) {
1100
+ function se(e) {
1100
1101
  return {
1101
1102
  startRow: Math.min(e.startRow, e.endRow),
1102
1103
  startCol: Math.min(e.startCol, e.endCol),
@@ -1104,7 +1105,7 @@ function oe(e) {
1104
1105
  endCol: Math.max(e.startCol, e.endCol)
1105
1106
  };
1106
1107
  }
1107
- var se = class {
1108
+ var ce = class {
1108
1109
  constructor() {
1109
1110
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
1110
1111
  }
@@ -1131,7 +1132,7 @@ var se = class {
1131
1132
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
1132
1133
  row: e,
1133
1134
  col: t
1134
- }, this.rangeAnchor && (this.range = oe({
1135
+ }, this.rangeAnchor && (this.range = se({
1135
1136
  startRow: this.rangeAnchor.row,
1136
1137
  startCol: this.rangeAnchor.col,
1137
1138
  endRow: e,
@@ -1202,7 +1203,7 @@ var se = class {
1202
1203
  shiftMoveRight() {
1203
1204
  return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
1204
1205
  }
1205
- }, ce = class {
1206
+ }, O = class {
1206
1207
  constructor() {
1207
1208
  this.current = null;
1208
1209
  }
@@ -1224,7 +1225,7 @@ var se = class {
1224
1225
  let e = this.current;
1225
1226
  return this.current = null, e;
1226
1227
  }
1227
- }, O = class {
1228
+ }, k = class {
1228
1229
  constructor() {
1229
1230
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi";
1230
1231
  }
@@ -1291,7 +1292,7 @@ var se = class {
1291
1292
  };
1292
1293
  //#endregion
1293
1294
  //#region src/core/filtering.ts
1294
- function k(e, t, n) {
1295
+ function le(e, t, n) {
1295
1296
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
1296
1297
  let r = [];
1297
1298
  for (let i = 0; i < e.length; i++) {
@@ -1310,9 +1311,9 @@ function k(e, t, n) {
1310
1311
  }
1311
1312
  //#endregion
1312
1313
  //#region src/core/undo.ts
1313
- var le = 100, A = class {
1314
+ var ue = 100, A = class {
1314
1315
  constructor() {
1315
- this._undoStack = [], this._redoStack = [], this._maxSize = le;
1316
+ this._undoStack = [], this._redoStack = [], this._maxSize = ue;
1316
1317
  }
1317
1318
  get maxSize() {
1318
1319
  return this._maxSize;
@@ -1349,7 +1350,7 @@ var le = 100, A = class {
1349
1350
  };
1350
1351
  //#endregion
1351
1352
  //#region src/clipboard/clipboard.ts
1352
- function ue(e, t, n) {
1353
+ function de(e, t, n) {
1353
1354
  let r = [];
1354
1355
  for (let i = n.startRow; i <= n.endRow; i++) {
1355
1356
  let a = e[i], o = [];
@@ -1382,13 +1383,13 @@ function M(e) {
1382
1383
  let n = new Intl.NumberFormat(u.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
1383
1384
  return n && n !== "." ? t.replace(".", n) : t;
1384
1385
  }
1385
- function de(e) {
1386
+ function fe(e) {
1386
1387
  if (e == null || e === "") return "";
1387
1388
  if (e instanceof Date) return Number.isNaN(e.getTime()) ? "" : `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
1388
1389
  let t = String(e), n = /^(\d{4}-\d{2}-\d{2})(?:$|T)/.exec(t);
1389
1390
  return n ? n[1] : t;
1390
1391
  }
1391
- function fe(e) {
1392
+ function pe(e) {
1392
1393
  if (e == null || e === "") return "";
1393
1394
  let t = e instanceof Date ? "" : String(e), n = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(t);
1394
1395
  if (n) return `${n[1]} ${n[2]}`;
@@ -1399,7 +1400,7 @@ function fe(e) {
1399
1400
  }
1400
1401
  //#endregion
1401
1402
  //#region src/export/xlsx-writer.ts
1402
- var pe = (() => {
1403
+ var me = (() => {
1403
1404
  let e = /* @__PURE__ */ new Uint32Array(256);
1404
1405
  for (let t = 0; t < 256; t++) {
1405
1406
  let n = t;
@@ -1408,23 +1409,23 @@ var pe = (() => {
1408
1409
  }
1409
1410
  return e;
1410
1411
  })();
1411
- function me(e) {
1412
+ function he(e) {
1412
1413
  let t = 4294967295;
1413
- for (let n = 0; n < e.length; n++) t = pe[(t ^ e[n]) & 255] ^ t >>> 8;
1414
+ for (let n = 0; n < e.length; n++) t = me[(t ^ e[n]) & 255] ^ t >>> 8;
1414
1415
  return (t ^ 4294967295) >>> 0;
1415
1416
  }
1416
1417
  var N = new TextEncoder();
1417
- function he(e) {
1418
+ function ge(e) {
1418
1419
  return P(e.map((e) => ({
1419
1420
  ...e,
1420
1421
  body: e.data,
1421
1422
  method: 0
1422
1423
  })));
1423
1424
  }
1424
- async function ge(e) {
1425
+ async function _e(e) {
1425
1426
  let t = [];
1426
1427
  for (let n of e) {
1427
- let e = await _e(n.data);
1428
+ let e = await ve(n.data);
1428
1429
  t.push(e.length < n.data.length ? {
1429
1430
  ...n,
1430
1431
  body: e,
@@ -1437,7 +1438,7 @@ async function ge(e) {
1437
1438
  }
1438
1439
  return P(t);
1439
1440
  }
1440
- async function _e(e) {
1441
+ async function ve(e) {
1441
1442
  let t = new CompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
1442
1443
  n.write(e), n.close();
1443
1444
  let i = [];
@@ -1451,7 +1452,7 @@ async function _e(e) {
1451
1452
  function P(e) {
1452
1453
  let t = [], n = [], r = 0;
1453
1454
  for (let i of e) {
1454
- let e = N.encode(i.name), a = me(i.data), o = i.data.length, s = i.body.length, c = i.method === 8 ? 20 : 10, l = new ArrayBuffer(30 + e.length), u = new DataView(l);
1455
+ let e = N.encode(i.name), a = he(i.data), o = i.data.length, s = i.body.length, c = i.method === 8 ? 20 : 10, l = new ArrayBuffer(30 + e.length), u = new DataView(l);
1455
1456
  u.setUint32(0, 67324752, !0), u.setUint16(4, c, !0), u.setUint16(6, 0, !0), u.setUint16(8, i.method, !0), u.setUint16(10, 0, !0), u.setUint16(12, 33, !0), u.setUint32(14, a, !0), u.setUint32(18, s, !0), u.setUint32(22, o, !0), u.setUint16(26, e.length, !0), u.setUint16(28, 0, !0), new Uint8Array(l, 30).set(e), t.push(new Uint8Array(l)), t.push(i.body);
1456
1457
  let d = new ArrayBuffer(46 + e.length), f = new DataView(d);
1457
1458
  f.setUint32(0, 33639248, !0), f.setUint16(4, 20, !0), f.setUint16(6, c, !0), f.setUint16(8, 0, !0), f.setUint16(10, i.method, !0), f.setUint16(12, 0, !0), f.setUint16(14, 33, !0), f.setUint32(16, a, !0), f.setUint32(20, s, !0), f.setUint32(24, o, !0), f.setUint16(28, e.length, !0), f.setUint16(30, 0, !0), f.setUint16(32, 0, !0), f.setUint16(34, 0, !0), f.setUint16(36, 0, !0), f.setUint32(38, 0, !0), f.setUint32(42, r, !0), new Uint8Array(d, 46).set(e), n.push(new Uint8Array(d)), r += 30 + e.length + s;
@@ -1471,27 +1472,27 @@ function F(e) {
1471
1472
  function I(e) {
1472
1473
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1473
1474
  }
1474
- function ve(e) {
1475
+ function ye(e) {
1475
1476
  let t = "";
1476
1477
  for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1477
1478
  return t;
1478
1479
  }
1479
1480
  function L(e, t) {
1480
- return ve(t) + (e + 1);
1481
+ return ye(t) + (e + 1);
1481
1482
  }
1482
- function ye(e) {
1483
+ function be(e) {
1483
1484
  let t = Date.UTC(1899, 11, 30);
1484
1485
  return (e.getTime() - t) / 864e5;
1485
1486
  }
1486
- var be = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", xe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", Se = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\n <sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>\n</workbook>", Ce = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n</Relationships>", we = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n <numFmts count=\"1\"><numFmt numFmtId=\"164\" formatCode=\"yyyy-mm-dd\"/></numFmts>\n <fonts count=\"2\">\n <font><sz val=\"11\"/><name val=\"Calibri\"/></font>\n <font><sz val=\"11\"/><b/><name val=\"Calibri\"/></font>\n </fonts>\n <fills count=\"2\">\n <fill><patternFill patternType=\"none\"/></fill>\n <fill><patternFill patternType=\"gray125\"/></fill>\n </fills>\n <borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>\n <cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>\n <cellXfs count=\"3\">\n <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>\n <xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>\n <xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>\n </cellXfs>\n</styleSheet>";
1487
- function Te(e, t) {
1487
+ var xe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", Se = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", Ce = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\n <sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>\n</workbook>", we = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n</Relationships>", Te = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">\n <numFmts count=\"1\"><numFmt numFmtId=\"164\" formatCode=\"yyyy-mm-dd\"/></numFmts>\n <fonts count=\"2\">\n <font><sz val=\"11\"/><name val=\"Calibri\"/></font>\n <font><sz val=\"11\"/><b/><name val=\"Calibri\"/></font>\n </fonts>\n <fills count=\"2\">\n <fill><patternFill patternType=\"none\"/></fill>\n <fill><patternFill patternType=\"gray125\"/></fill>\n </fills>\n <borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders>\n <cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>\n <cellXfs count=\"3\">\n <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>\n <xf numFmtId=\"164\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"/>\n <xf numFmtId=\"0\" fontId=\"1\" fillId=\"0\" borderId=\"0\" xfId=\"0\" applyFont=\"1\"/>\n </cellXfs>\n</styleSheet>";
1488
+ function Ee(e, t) {
1488
1489
  let n = [], r = t.map((e, t) => `<c r="${L(0, t)}" t="str" s="2"><v>${I(e.label)}</v></c>`);
1489
1490
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1490
1491
  let i = t.map((t, n) => {
1491
1492
  let i = L(r + 1, n), a = e[t.key];
1492
1493
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1493
1494
  let o = t.type ?? "text";
1494
- return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${ye(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${I(String(a))}</v></c>`;
1495
+ return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${be(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${I(String(a))}</v></c>`;
1495
1496
  });
1496
1497
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1497
1498
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -1499,30 +1500,30 @@ function Te(e, t) {
1499
1500
  <sheetData>${n.join("")}</sheetData>
1500
1501
  </worksheet>`;
1501
1502
  }
1502
- function Ee(e, t) {
1503
- return he(R(e, t));
1504
- }
1505
1503
  function De(e, t) {
1506
1504
  return ge(R(e, t));
1507
1505
  }
1506
+ function Oe(e, t) {
1507
+ return _e(R(e, t));
1508
+ }
1508
1509
  function R(e, t) {
1509
- let n = Te(e, t);
1510
+ let n = Ee(e, t);
1510
1511
  return [
1511
1512
  {
1512
1513
  name: "[Content_Types].xml",
1513
- data: N.encode(be)
1514
+ data: N.encode(xe)
1514
1515
  },
1515
1516
  {
1516
1517
  name: "_rels/.rels",
1517
- data: N.encode(xe)
1518
+ data: N.encode(Se)
1518
1519
  },
1519
1520
  {
1520
1521
  name: "xl/workbook.xml",
1521
- data: N.encode(Se)
1522
+ data: N.encode(Ce)
1522
1523
  },
1523
1524
  {
1524
1525
  name: "xl/_rels/workbook.xml.rels",
1525
- data: N.encode(Ce)
1526
+ data: N.encode(we)
1526
1527
  },
1527
1528
  {
1528
1529
  name: "xl/worksheets/sheet1.xml",
@@ -1530,7 +1531,7 @@ function R(e, t) {
1530
1531
  },
1531
1532
  {
1532
1533
  name: "xl/styles.xml",
1533
- data: N.encode(we)
1534
+ data: N.encode(Te)
1534
1535
  }
1535
1536
  ];
1536
1537
  }
@@ -1538,26 +1539,26 @@ function R(e, t) {
1538
1539
  //#region src/export/export.ts
1539
1540
  function z(e, t, n) {
1540
1541
  switch (n) {
1541
- case "csv": return V(e, t, ",");
1542
- case "tsv": return V(e, t, " ");
1543
- case "json": return ke(e, t);
1544
- case "xlsx": return Ee(e, t);
1542
+ case "csv": return B(e, t, ",");
1543
+ case "tsv": return B(e, t, " ");
1544
+ case "json": return je(e, t);
1545
+ case "xlsx": return De(e, t);
1545
1546
  }
1546
1547
  }
1547
- async function Oe(e, t, n) {
1548
- let r = n === "xlsx" ? await De(e, t) : z(e, t, n);
1549
- return new Blob([r], { type: Ne(n) });
1548
+ async function ke(e, t, n) {
1549
+ let r = n === "xlsx" ? await Oe(e, t) : z(e, t, n);
1550
+ return new Blob([r], { type: Fe(n) });
1550
1551
  }
1551
- function B(e, t) {
1552
+ function Ae(e, t) {
1552
1553
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
1553
1554
  }
1554
- function V(e, t, n) {
1555
- return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(B(e[t.key], t), n)).join(n))].join("\n");
1555
+ function B(e, t, n) {
1556
+ return [t.map((e) => V(e.label, n)).join(n), ...e.map((e) => t.map((t) => V(Ae(e[t.key], t), n)).join(n))].join("\n");
1556
1557
  }
1557
- function H(e, t) {
1558
+ function V(e, t) {
1558
1559
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
1559
1560
  }
1560
- function ke(e, t) {
1561
+ function je(e, t) {
1561
1562
  let n = e.map((e) => {
1562
1563
  let n = {};
1563
1564
  for (let r of t) {
@@ -1568,35 +1569,35 @@ function ke(e, t) {
1568
1569
  });
1569
1570
  return JSON.stringify(n, null, 2);
1570
1571
  }
1571
- function Ae(e, t) {
1572
+ function Me(e, t) {
1572
1573
  let n = URL.createObjectURL(e), r = document.createElement("a");
1573
1574
  r.href = n, r.download = t, r.style.display = "none", document.body.appendChild(r), r.click(), document.body.removeChild(r), setTimeout(() => URL.revokeObjectURL(n), 100);
1574
1575
  }
1575
- var je = {
1576
+ var Ne = {
1576
1577
  csv: "text/csv;charset=utf-8",
1577
1578
  tsv: "text/tab-separated-values;charset=utf-8",
1578
1579
  json: "application/json;charset=utf-8",
1579
1580
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1580
- }, Me = {
1581
+ }, Pe = {
1581
1582
  csv: ".csv",
1582
1583
  tsv: ".tsv",
1583
1584
  json: ".json",
1584
1585
  xlsx: ".xlsx"
1585
1586
  };
1586
- function Ne(e) {
1587
- return je[e];
1587
+ function Fe(e) {
1588
+ return Ne[e];
1588
1589
  }
1589
- function Pe(e) {
1590
- return Me[e];
1590
+ function H(e) {
1591
+ return Pe[e];
1591
1592
  }
1592
1593
  //#endregion
1593
1594
  //#region src/export/xlsx-reader.ts
1594
- function Fe(e) {
1595
+ function Ie(e) {
1595
1596
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
1596
1597
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
1597
1598
  }
1598
- function Ie(e) {
1599
- let t = Fe(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
1599
+ function Le(e) {
1600
+ let t = Ie(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
1600
1601
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
1601
1602
  let t = e.getUint16(o + 10, !0), n = e.getUint32(o + 20, !0), r = e.getUint32(o + 24, !0), s = e.getUint16(o + 28, !0), c = e.getUint16(o + 30, !0), l = e.getUint16(o + 32, !0), u = e.getUint32(o + 42, !0), d = i.decode(new Uint8Array(e.buffer, o + 46, s));
1602
1603
  a.push({
@@ -1609,7 +1610,7 @@ function Ie(e) {
1609
1610
  }
1610
1611
  return a;
1611
1612
  }
1612
- async function Le(e) {
1613
+ async function Re(e) {
1613
1614
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
1614
1615
  n.write(e), n.close();
1615
1616
  let i = [];
@@ -1622,28 +1623,28 @@ async function Le(e) {
1622
1623
  for (let e of i) o.set(e, s), s += e.length;
1623
1624
  return o;
1624
1625
  }
1625
- async function Re(e, t) {
1626
+ async function ze(e, t) {
1626
1627
  let n = t.localHeaderOffset, r = e.getUint16(n + 26, !0), i = e.getUint16(n + 28, !0), a = n + 30 + r + i, o = new Uint8Array(e.buffer, a, t.compressedSize);
1627
1628
  if (t.compressionMethod === 0) return o.slice();
1628
- if (t.compressionMethod === 8) return Le(o);
1629
+ if (t.compressionMethod === 8) return Re(o);
1629
1630
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
1630
1631
  }
1631
- async function ze(e) {
1632
- let t = new DataView(e), n = Ie(t), r = /* @__PURE__ */ new Map();
1633
- for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Re(t, e));
1632
+ async function Be(e) {
1633
+ let t = new DataView(e), n = Le(t), r = /* @__PURE__ */ new Map();
1634
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await ze(t, e));
1634
1635
  return r;
1635
1636
  }
1636
- var Be = new TextDecoder("utf-8");
1637
+ var Ve = new TextDecoder("utf-8");
1637
1638
  function U(e) {
1638
- let t = Be.decode(e);
1639
+ let t = Ve.decode(e);
1639
1640
  return new DOMParser().parseFromString(t, "application/xml");
1640
1641
  }
1641
- function Ve(e) {
1642
+ function He(e) {
1642
1643
  if (!e) return [];
1643
1644
  let t = U(e);
1644
1645
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
1645
1646
  }
1646
- var He = /* @__PURE__ */ new Set([
1647
+ var Ue = /* @__PURE__ */ new Set([
1647
1648
  14,
1648
1649
  15,
1649
1650
  16,
@@ -1663,29 +1664,29 @@ var He = /* @__PURE__ */ new Set([
1663
1664
  57,
1664
1665
  58
1665
1666
  ]);
1666
- function Ue(e) {
1667
+ function We(e) {
1667
1668
  let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
1668
1669
  return /[dy]/i.test(t);
1669
1670
  }
1670
- function We(e) {
1671
+ function Ge(e) {
1671
1672
  let t = /* @__PURE__ */ new Set();
1672
1673
  if (!e) return t;
1673
1674
  let n = U(e), r = /* @__PURE__ */ new Map();
1674
1675
  for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
1675
1676
  return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
1676
1677
  let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
1677
- (a === void 0 ? He.has(i) : Ue(a)) && t.add(n);
1678
+ (a === void 0 ? Ue.has(i) : We(a)) && t.add(n);
1678
1679
  }), t;
1679
1680
  }
1680
- function Ge(e) {
1681
+ function Ke(e) {
1681
1682
  if (!e) return !1;
1682
1683
  let t = U(e).querySelector("workbookPr")?.getAttribute("date1904");
1683
1684
  return t === "1" || t === "true";
1684
1685
  }
1685
- function Ke(e, t) {
1686
+ function qe(e, t) {
1686
1687
  return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
1687
1688
  }
1688
- function qe(e, t, n, r) {
1689
+ function Je(e, t, n, r) {
1689
1690
  let i = U(e).querySelectorAll("row");
1690
1691
  if (i.length === 0) return [];
1691
1692
  let a = 0, o = /* @__PURE__ */ new Map();
@@ -1693,7 +1694,7 @@ function qe(e, t, n, r) {
1693
1694
  let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
1694
1695
  o.set(i, s);
1695
1696
  for (let i of e.querySelectorAll("c")) {
1696
- let e = Je(i.getAttribute("r") ?? "");
1697
+ let e = Ye(i.getAttribute("r") ?? "");
1697
1698
  e > a && (a = e);
1698
1699
  let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
1699
1700
  if (o === "s") d = t[parseInt(l, 10)] ?? "";
@@ -1702,7 +1703,7 @@ function qe(e, t, n, r) {
1702
1703
  else if (l === "") d = "";
1703
1704
  else {
1704
1705
  let e = parseFloat(l);
1705
- d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Ke(e, r) : l;
1706
+ d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? qe(e, r) : l;
1706
1707
  }
1707
1708
  s.set(e, d);
1708
1709
  }
@@ -1716,13 +1717,13 @@ function qe(e, t, n, r) {
1716
1717
  }
1717
1718
  return c;
1718
1719
  }
1719
- function Je(e) {
1720
+ function Ye(e) {
1720
1721
  let t = 0, n = 0;
1721
1722
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
1722
1723
  return t - 1;
1723
1724
  }
1724
- async function Ye(e) {
1725
- let t = await ze(e), n = Ve(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1725
+ async function Xe(e) {
1726
+ let t = await Be(e), n = He(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1726
1727
  if (!r) {
1727
1728
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
1728
1729
  r = n;
@@ -1730,7 +1731,7 @@ async function Ye(e) {
1730
1731
  }
1731
1732
  }
1732
1733
  if (!r) throw Error("XLSX: No worksheet found");
1733
- let i = We(t.get("xl/styles.xml")), a = Ge(t.get("xl/workbook.xml")), o = qe(r, n, i, a);
1734
+ let i = Ge(t.get("xl/styles.xml")), a = Ke(t.get("xl/workbook.xml")), o = Je(r, n, i, a);
1734
1735
  return o.length === 0 ? {
1735
1736
  headers: [],
1736
1737
  rows: []
@@ -1761,9 +1762,9 @@ var K = {
1761
1762
  lt: "<",
1762
1763
  gte: "≥",
1763
1764
  lte: "≤"
1764
- }, q = 120, J = 40, Y = 20, X = 32, Z = 5, Xe = 200, Q = class extends r {
1765
+ }, q = 120, J = 40, Y = 20, X = 32, Z = 5, Ze = 200, Q = class extends r {
1765
1766
  constructor(...e) {
1766
- super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this.rowKey = "_id", this._rowHeightFromCss = X, this._targetFloor = 0, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "", this.noMatchingMessage = "", this.error = null, this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._headerCol = null, this._focusedCellEl = null, this._editingCell = null, this._sortCriteria = [], this._selection = new se(), this._editing = new ce(), this._rowSelection = new O(), this._undo = new A(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowId = null, this._unkeyedIds = /* @__PURE__ */ new WeakMap(), this._unkeyedSeq = 0, this._visibleIdsCache = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._editorMoving = !1, this._onEditorBlur = (e) => {
1767
+ super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this.rowKey = "_id", this._rowHeightFromCss = X, this._targetFloor = 0, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "", this.noMatchingMessage = "", this.error = null, this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._headerCol = null, this._focusedCellEl = null, this._editingCell = null, this._sortCriteria = [], this._selection = new ce(), this._editing = new O(), this._rowSelection = new k(), this._undo = new A(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowId = null, this._unkeyedIds = /* @__PURE__ */ new WeakMap(), this._unkeyedSeq = 0, this._visibleIdsCache = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._editorMoving = !1, this._onEditorBlur = (e) => {
1767
1768
  !this._editorMoving && e.currentTarget?.isConnected && this._commitEdit();
1768
1769
  }, this._warnedUnconstrained = !1, this._onHostFocus = (e) => {
1769
1770
  e.composedPath()[0] !== this || this._activeCell || this._headerCol !== null || this.visibleColumns.length !== 0 && this.matches(":focus-visible") && (this._visibleRowCount > 0 ? (this._selection.setActive(0, 0), this._syncActiveCell()) : this._headerCol = 0);
@@ -1786,7 +1787,7 @@ var K = {
1786
1787
  }, this._invalidCells = /* @__PURE__ */ new Map(), this._textFilterState = /* @__PURE__ */ new Map(), this._numberFilterState = /* @__PURE__ */ new Map(), this._dateFilterState = /* @__PURE__ */ new Map(), this._emptyFilterState = /* @__PURE__ */ new Map();
1787
1788
  }
1788
1789
  static {
1789
- this.styles = S;
1790
+ this.styles = C;
1790
1791
  }
1791
1792
  get data() {
1792
1793
  return this._data;
@@ -2171,10 +2172,10 @@ var K = {
2171
2172
  rows: [],
2172
2173
  cols: []
2173
2174
  };
2174
- return Oe(n.rows, n.cols, e);
2175
+ return ke(n.rows, n.cols, e);
2175
2176
  }
2176
2177
  async exportToFile(e, t) {
2177
- Ae(await this.exportToBlob(e), t ?? `export${Pe(e)}`);
2178
+ Me(await this.exportToBlob(e), t ?? `export${H(e)}`);
2178
2179
  }
2179
2180
  _exportSlice(e) {
2180
2181
  if (e?.selectionOnly) {
@@ -2251,7 +2252,7 @@ var K = {
2251
2252
  async importFromFile(e) {
2252
2253
  let t = e.name.toLowerCase();
2253
2254
  if (t.endsWith(".xlsx")) {
2254
- let t = await Ye(await e.arrayBuffer());
2255
+ let t = await Xe(await e.arrayBuffer());
2255
2256
  this._applyImportedSheet(t);
2256
2257
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
2257
2258
  let t = await e.text(), n = g(t);
@@ -2435,7 +2436,7 @@ var K = {
2435
2436
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
2436
2437
  return;
2437
2438
  }
2438
- if (this._filteredIndices = k(this.data, this._filters, (e, t, n) => {
2439
+ if (this._filteredIndices = le(this.data, this._filters, (e, t, n) => {
2439
2440
  this._emit("filter-error", {
2440
2441
  error: e,
2441
2442
  row: t,
@@ -2490,7 +2491,7 @@ var K = {
2490
2491
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2491
2492
  }
2492
2493
  _warnIfUnconstrained() {
2493
- this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Xe || this.scrollHeight > this.clientHeight + 1 || (this._warnedUnconstrained = !0, console.warn(`[@iyulab/flex-table] ${this._visibleRowCount} rows but the host has no height constraint — it grew to fit every row, so virtual scrolling is off and all rows are rendered. Give the host a height (e.g. height: 400px, or flex: 1 1 auto with min-height: 0 inside a sized parent) so it becomes the scroll container.`));
2494
+ this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Ze || this.scrollHeight > this.clientHeight + 1 || (this._warnedUnconstrained = !0, console.warn(`[@iyulab/flex-table] ${this._visibleRowCount} rows but the host has no height constraint — it grew to fit every row, so virtual scrolling is off and all rows are rendered. Give the host a height (e.g. height: 400px, or flex: 1 1 auto with min-height: 0 inside a sized parent) so it becomes the scroll container.`));
2494
2495
  }
2495
2496
  _onScroll() {
2496
2497
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -2538,7 +2539,9 @@ var K = {
2538
2539
  this._wasDrag = !1;
2539
2540
  return;
2540
2541
  }
2541
- this._isDragging = !1, this._editing.current && this._commitEdit(), e.shiftKey ? this._selection.setActiveWithRange(t, n) : e.ctrlKey || e.metaKey ? this._selection.toggleCell(t, n) : this._selection.setActive(t, n), this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._dispatchSelectionEvent(), this.requestUpdate();
2542
+ this._isDragging = !1, this._editing.current && this._commitEdit();
2543
+ let r = e.shiftKey || e.ctrlKey || e.metaKey;
2544
+ e.shiftKey ? this._selection.setActiveWithRange(t, n) : e.ctrlKey || e.metaKey ? this._selection.toggleCell(t, n) : this._selection.setActive(t, n), this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._dispatchSelectionEvent(), this.requestUpdate(), !r && !S(e, e.currentTarget) && this._fireRowActivate(this.visibleColumns[n], "click");
2542
2545
  }
2543
2546
  _onCellMouseDown(e, t, n) {
2544
2547
  if (e.button !== 0 || e.shiftKey) return;
@@ -2573,13 +2576,14 @@ var K = {
2573
2576
  _isCellEditable(e) {
2574
2577
  return !(!this.editable || e.editable === !1);
2575
2578
  }
2576
- _fireRowActivate(e) {
2579
+ _fireRowActivate(e, t) {
2577
2580
  if (!this._activeCell) return;
2578
- let t = this._toDataIndex(this._activeCell.row), n = this.data[t];
2579
- n && this._emit("row-activate", {
2580
- row: n,
2581
- id: this.getRowId(n),
2582
- index: t,
2581
+ let n = this._toDataIndex(this._activeCell.row), r = this.data[n];
2582
+ r && this._emit("row-activate", {
2583
+ row: r,
2584
+ id: this.getRowId(r),
2585
+ via: t,
2586
+ index: n,
2583
2587
  col: this._activeCell.col,
2584
2588
  key: e?.key
2585
2589
  });
@@ -2794,7 +2798,7 @@ var K = {
2794
2798
  if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !v(e)) {
2795
2799
  e.preventDefault();
2796
2800
  let n = t[this._activeCell.col];
2797
- n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n);
2801
+ n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n, "keyboard");
2798
2802
  return;
2799
2803
  }
2800
2804
  if (!this._selection.activeCell) {
@@ -2953,7 +2957,7 @@ var K = {
2953
2957
  let e = this._selection.getEffectiveRange();
2954
2958
  return e ? {
2955
2959
  range: e,
2956
- text: ue(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e)
2960
+ text: de(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e)
2957
2961
  } : null;
2958
2962
  }
2959
2963
  async _copyFromMenu() {
@@ -3182,7 +3186,11 @@ var K = {
3182
3186
  n < this.scrollLeft ? this.scrollLeft = n : r > this.scrollLeft + this.clientWidth && (this.scrollLeft = r - this.clientWidth);
3183
3187
  }
3184
3188
  _dispatchSelectionEvent() {
3185
- this._emit("cell-select", this._activeCell ? { ...this._activeCell } : null);
3189
+ let e = this._activeCell, t = e ? this.data[this._toDataIndex(e.row)] : void 0;
3190
+ this._emit("cell-select", e ? {
3191
+ ...e,
3192
+ id: t ? this.getRowId(t) : ""
3193
+ } : null);
3186
3194
  }
3187
3195
  _onHeaderClick(e, t) {
3188
3196
  if (this._wasHeaderDrag) {
@@ -4479,7 +4487,7 @@ var K = {
4479
4487
  return a`
4480
4488
  <u-date-picker class="ft-editor ft-editor-${t.type}" size="sm" aria-label=${t.label}
4481
4489
  mode=${e ? "datetime" : "date"} ?confirm=${e}
4482
- .value=${Ze(n, e)}
4490
+ .value=${Qe(n, e)}
4483
4491
  @keydown=${this._onEditorKeyDown}
4484
4492
  @change=${() => this._commitEdit()}
4485
4493
  @blur=${this._onEditorBlur}></u-date-picker>
@@ -4586,12 +4594,12 @@ G([c({ type: Array })], Q.prototype, "columns", void 0), G([c({
4586
4594
  type: Number,
4587
4595
  attribute: "max-undo-size"
4588
4596
  })], Q.prototype, "maxUndoSize", null), G([l()], Q.prototype, "_scrollTop", void 0), G([l()], Q.prototype, "_scrollLeft", void 0), G([l()], Q.prototype, "_viewportHeight", void 0), G([l()], Q.prototype, "_viewportWidth", void 0), G([l()], Q.prototype, "_activeCell", void 0), G([l()], Q.prototype, "_headerCol", void 0), G([l()], Q.prototype, "_editingCell", void 0), G([l()], Q.prototype, "_sortCriteria", void 0), G([l()], Q.prototype, "_openFilterKey", void 0), G([l()], Q.prototype, "_rowSelectionVersion", void 0), G([l()], Q.prototype, "_autocompleteState", void 0), G([l()], Q.prototype, "_headerMenu", void 0), G([l()], Q.prototype, "_bodyContextMenu", void 0), G([l()], Q.prototype, "_commentPopup", void 0), G([l()], Q.prototype, "_isDragOver", void 0), Q = G([s("flex-table")], Q);
4589
- function Ze(e, t) {
4597
+ function Qe(e, t) {
4590
4598
  if (t) {
4591
- let t = fe(e);
4599
+ let t = pe(e);
4592
4600
  return /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(t) ? t.replace(" ", "T") : void 0;
4593
4601
  }
4594
- let n = de(e);
4602
+ let n = fe(e);
4595
4603
  return /^\d{4}-\d{2}-\d{2}$/.test(n) ? n : void 0;
4596
4604
  }
4597
4605
  function $(e) {
@@ -4602,4 +4610,4 @@ function $(e) {
4602
4610
  }
4603
4611
  }
4604
4612
  //#endregion
4605
- export { O as a, A as i, W as n, D as o, z as r, Q as t };
4613
+ export { k as a, A as i, W as n, D as o, z as r, Q as t };
@@ -1,3 +1,3 @@
1
- import { a as e, i as t, n, o as r, r as i, t as a } from "./flex-table-B1W8VEBa.js";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./flex-table-BDTykqUE.js";
2
2
  import { t as o } from "./locale-Cfm-vJji.js";
3
3
  export { a as FlexTable, e as RowSelectionState, t as UndoStack, n as effectiveAlign, i as exportData, o as flexTableLocale, r as renderCell };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-B1W8VEBa.js";
1
+ import { t as e } from "./flex-table-BDTykqUE.js";
2
2
  import { i as t } from "./query-Dw4iO0ir.js";
3
3
  import { t as n } from "./source-DOue0Ti3.js";
4
4
  import { t as r } from "./view-DiLr-TdY.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.58.0",
3
+ "version": "0.59.0",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",
@@ -74,7 +74,7 @@
74
74
  "odata-query": "^8.1.0"
75
75
  },
76
76
  "peerDependencies": {
77
- "@iyulab/components": ">=2.8.0",
77
+ "@iyulab/components": ">=2.15.0",
78
78
  "@lit/react": "^1.0.8",
79
79
  "react": "^18.0.0 || ^19.0.0"
80
80
  },
@@ -76,7 +76,8 @@ Use `updateRows([{ row, key, value }])` for programmatic edits (undoable, fires
76
76
 
77
77
  **Editing and read-only.** `editable` defaults to `true`. For a read-only grid set
78
78
  `table.editable = false` (a property, since a boolean attribute cannot express `false`) — Enter on a non-editable cell then fires
79
- `row-activate`, the grid's "open this row" contract.
79
+ `row-activate`, the grid's "open this row" contract; a plain click on a cell fires it too (`via: 'click'`).
80
+ Open a row's detail on `row-activate`, never on `cell-select` — that one is focus and fires when Tab arrives on the grid.
80
81
 
81
82
  **Row selection is kept by row id.** Enable with `selectable` (`selection-mode="single|multi"`).
82
83
  The id is the row's `row-key` field (`_id` by default, as in `u-rich-table`) or a `rowKey` function, so
@@ -143,14 +143,14 @@ cast, and the React `on*` props carry the same types.
143
143
 
144
144
  | Event | `detail` |
145
145
  |---|---|
146
- | `cell-select` | `{ row, col }` (or `null`) |
146
+ | `cell-select` | `{ row, col, id }` (or `null`) — focus moved (also when the keyboard arrives); `row`/`col` visible positions |
147
147
  | `cell-edit-start` | `{ row, col, key, value }` |
148
148
  | `cell-edit-commit` | `{ row, col, key, oldValue, newValue }` |
149
149
  | `cell-edit-cancel` | `{ row, col }` — `row`: data index (`-1` once the row left `data`) |
150
150
  | `validation-error` | `{ row, col, key, value, error }` |
151
151
  | `row-add` | `{ row, index }` |
152
152
  | `row-delete` | `{ indices, rows }` |
153
- | `row-activate` | `{ row, id, index, col, key }` — Enter on a non-editable cell |
153
+ | `row-activate` | `{ row, id, via, index, col, key }` — a plain click on a cell (`via: 'click'`) or Enter on a non-editable cell (`'keyboard'`); not a Shift/Ctrl/Cmd click, a drag, or a control in the cell |
154
154
  | `row-reorder` | `{ from, to }` |
155
155
  | `batch-update` | `{ changes }` |
156
156
  | `column-add` | `{ column, index }` |