@iyulab/flex-table 0.40.2 → 0.41.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.
@@ -2,11 +2,11 @@ import { n as e, t } from "./sorting-CjfjRxwL.js";
2
2
  import { LitElement as n, css as r, html as i, nothing as a } from "lit";
3
3
  import { customElement as o, property as s, state as c } from "lit/decorators.js";
4
4
  import { Locale as l } from "@iyulab/components/dist/utilities/Locale.js";
5
- import { formatDate as u, formatNumber as d } from "@iyulab/components/dist/utilities/format.js";
6
- import { decodeTsv as f, encodeTsv as p } from "@iyulab/components/dist/utilities/tsv.js";
7
- import { isImeComposing as m } from "@iyulab/components/dist/utilities/keyboard.js";
5
+ import { formatDate as u, formatNumber as d, parseNumber as f } from "@iyulab/components/dist/utilities/format.js";
6
+ import { decodeTsv as p, encodeTsv as m } from "@iyulab/components/dist/utilities/tsv.js";
7
+ import { isImeComposing as h } from "@iyulab/components/dist/utilities/keyboard.js";
8
8
  //#region src/styles/flex-table.styles.ts
9
- var h = r`
9
+ var g = r`
10
10
  /* --- Theme Variables (Light defaults) --- */
11
11
  :host {
12
12
  --ft-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -262,6 +262,15 @@ var h = r`
262
262
  .ft-row-even:hover .ft-cell { background: var(--ft-row-hover-bg); }
263
263
  .ft-row-odd:hover .ft-cell { background: var(--ft-row-odd-hover-bg); }
264
264
 
265
+ /* mergeRepeated — one surface per run: the row it starts on sets the background, the lines
266
+ inside the run go, and the repeated values stay in the DOM (copy, find and screen readers
267
+ read them) but are not painted. A selected or active cell paints its value again. */
268
+ .ft-row-even .ft-cell.ft-merge-even:not(.ft-invalid), .ft-row-odd .ft-cell.ft-merge-even:not(.ft-invalid) { background: var(--ft-row-even-bg); }
269
+ .ft-row-even .ft-cell.ft-merge-odd:not(.ft-invalid), .ft-row-odd .ft-cell.ft-merge-odd:not(.ft-invalid) { background: var(--ft-row-odd-bg); }
270
+ .ft-cell.ft-merge-open { border-bottom-color: transparent; }
271
+ .ft-cell.ft-merge-continued:not(.ft-active):not(.ft-selected) { color: transparent; }
272
+ .ft-cell.ft-merge-continued:not(.ft-active):not(.ft-selected) > :not(.ft-comment-indicator) { opacity: 0; }
273
+
265
274
  .ft-cell.ft-active {
266
275
  outline: 2px solid var(--ft-active-color);
267
276
  outline-offset: -2px;
@@ -912,13 +921,13 @@ var h = r`
912
921
  `;
913
922
  //#endregion
914
923
  //#region src/renderers/format.ts
915
- function g(e, t) {
916
- return e == null ? "" : typeof t == "function" ? t(e) : _(t) ? y(e, t) : v(e, t);
924
+ function _(e, t) {
925
+ return e == null ? "" : typeof t == "function" ? t(e) : v(t) ? b(e, t) : y(e, t);
917
926
  }
918
- function _(e) {
927
+ function v(e) {
919
928
  return /[yMdHhms]/.test(e);
920
929
  }
921
- function v(e, t) {
930
+ function y(e, t) {
922
931
  let n = typeof e == "number" ? e : Number(e);
923
932
  if (isNaN(n)) return String(e);
924
933
  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, u = {
@@ -931,7 +940,7 @@ function v(e, t) {
931
940
  style: "percent"
932
941
  }).format(n) : (d = new Intl.NumberFormat(l.get(), u).format(n), a && (d = a + d)), d + "";
933
942
  }
934
- function y(e, t) {
943
+ function b(e, t) {
935
944
  let n;
936
945
  if (e instanceof Date) n = e;
937
946
  else if (typeof e == "string" || typeof e == "number") n = new Date(e);
@@ -942,26 +951,26 @@ function y(e, t) {
942
951
  }
943
952
  //#endregion
944
953
  //#region src/renderers/cell-renderer.ts
945
- function b(e, t, n) {
946
- return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : g(e, n.format) : x(e, n);
954
+ function x(e, t, n) {
955
+ return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : _(e, n.format) : S(e, n);
947
956
  }
948
- function x(e, t) {
957
+ function S(e, t) {
949
958
  if (e == null) return "";
950
959
  switch (t.type) {
951
- case "number": return w(e);
960
+ case "number": return T(e);
952
961
  case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
953
- case "date": return T(e);
954
- case "datetime": return E(e);
955
- case "select": return S(e, t);
962
+ case "date": return E(e);
963
+ case "datetime": return D(e);
964
+ case "select": return C(e, t);
956
965
  default: return String(e);
957
966
  }
958
967
  }
959
- function S(e, t) {
968
+ function C(e, t) {
960
969
  if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
961
970
  let n = t.options.find((t) => t.value === e);
962
971
  return n ? n.label : e == null ? "" : String(e);
963
972
  }
964
- var C = {
973
+ var w = {
965
974
  year: "numeric",
966
975
  month: "numeric",
967
976
  day: "numeric",
@@ -969,19 +978,19 @@ var C = {
969
978
  minute: "numeric",
970
979
  second: "numeric"
971
980
  };
972
- function w(e) {
981
+ function T(e) {
973
982
  return typeof e == "number" ? Number.isInteger(e) ? d(e) : d(e, { minimumFractionDigits: 1 }) : String(e);
974
983
  }
975
- function T(e) {
984
+ function E(e) {
976
985
  return e instanceof Date || typeof e == "string" ? u(e) : String(e);
977
986
  }
978
- function E(e) {
979
- return e instanceof Date || typeof e == "string" ? u(e, C) : String(e);
987
+ function D(e) {
988
+ return e instanceof Date || typeof e == "string" ? u(e, w) : String(e);
980
989
  }
981
990
  //#endregion
982
991
  //#region src/locale.ts
983
- var D = l.namespace("flex-table");
984
- D.register("en", {
992
+ var O = l.namespace("flex-table");
993
+ O.register("en", {
985
994
  showHiddenColumns: "Show hidden column(s)",
986
995
  columnMenu: "Column menu",
987
996
  cellActions: "Cell actions",
@@ -1033,8 +1042,10 @@ D.register("en", {
1033
1042
  deleteComment: "Delete Comment",
1034
1043
  booleanTrue: "True",
1035
1044
  booleanFalse: "False",
1036
- dropFileToImport: "Drop file to import (.xlsx / .csv)"
1037
- }), D.register("ko", {
1045
+ dropFileToImport: "Drop file to import (.xlsx / .csv)",
1046
+ notANumber: "Enter a number",
1047
+ notInList: "Value must be from the existing list"
1048
+ }), O.register("ko", {
1038
1049
  showHiddenColumns: "숨긴 열 보기",
1039
1050
  columnMenu: "열 메뉴",
1040
1051
  cellActions: "셀 작업",
@@ -1086,9 +1097,11 @@ D.register("en", {
1086
1097
  deleteComment: "메모 삭제",
1087
1098
  booleanTrue: "참",
1088
1099
  booleanFalse: "거짓",
1089
- dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)"
1100
+ dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)",
1101
+ notANumber: "숫자를 입력하세요",
1102
+ notInList: "목록에 있는 값이어야 합니다"
1090
1103
  });
1091
- var O = (e, t) => D.text(e, t);
1104
+ var k = (e, t) => O.text(e, t);
1092
1105
  //#endregion
1093
1106
  //#region src/core/selection.ts
1094
1107
  function ee(e) {
@@ -1218,7 +1231,7 @@ var te = class {
1218
1231
  let e = this.current;
1219
1232
  return this.current = null, e;
1220
1233
  }
1221
- }, k = class {
1234
+ }, A = class {
1222
1235
  constructor() {
1223
1236
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
1224
1237
  }
@@ -1298,7 +1311,7 @@ function re(e, t, n) {
1298
1311
  }
1299
1312
  //#endregion
1300
1313
  //#region src/core/undo.ts
1301
- var ie = 100, A = class {
1314
+ var ie = 100, j = class {
1302
1315
  constructor() {
1303
1316
  this._undoStack = [], this._redoStack = [], this._maxSize = ie;
1304
1317
  }
@@ -1347,22 +1360,30 @@ function ae(e, t, n) {
1347
1360
  }
1348
1361
  r.push(o);
1349
1362
  }
1350
- return p(r);
1363
+ return m(r);
1351
1364
  }
1352
- function j(e, t) {
1365
+ function M(e, t) {
1353
1366
  if (e === "") return null;
1354
1367
  switch (t.type) {
1355
1368
  case "number": {
1356
- let t = Number(e);
1357
- return isNaN(t) ? e : t;
1369
+ let t = f(e);
1370
+ if (t !== null) return t;
1371
+ let n = Number(e.trim());
1372
+ return e.trim() !== "" && Number.isFinite(n) ? n : e;
1358
1373
  }
1359
1374
  case "boolean": return e.toLowerCase() === "true" || e === "1";
1360
1375
  default: return e;
1361
1376
  }
1362
1377
  }
1378
+ function N(e) {
1379
+ let t = String(e);
1380
+ if (!Number.isFinite(e) || t.includes("e")) return t;
1381
+ let n = new Intl.NumberFormat(l.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
1382
+ return n && n !== "." ? t.replace(".", n) : t;
1383
+ }
1363
1384
  //#endregion
1364
1385
  //#region src/export/xlsx-writer.ts
1365
- var M = (() => {
1386
+ var oe = (() => {
1366
1387
  let e = /* @__PURE__ */ new Uint32Array(256);
1367
1388
  for (let t = 0; t < 256; t++) {
1368
1389
  let n = t;
@@ -1371,56 +1392,56 @@ var M = (() => {
1371
1392
  }
1372
1393
  return e;
1373
1394
  })();
1374
- function oe(e) {
1395
+ function se(e) {
1375
1396
  let t = 4294967295;
1376
- for (let n = 0; n < e.length; n++) t = M[(t ^ e[n]) & 255] ^ t >>> 8;
1397
+ for (let n = 0; n < e.length; n++) t = oe[(t ^ e[n]) & 255] ^ t >>> 8;
1377
1398
  return (t ^ 4294967295) >>> 0;
1378
1399
  }
1379
- var N = new TextEncoder();
1380
- function se(e) {
1400
+ var P = new TextEncoder();
1401
+ function ce(e) {
1381
1402
  let t = [], n = [], r = 0;
1382
1403
  for (let i of e) {
1383
- let e = N.encode(i.name), a = oe(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1404
+ let e = P.encode(i.name), a = se(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1384
1405
  c.setUint32(0, 67324752, !0), c.setUint16(4, 20, !0), c.setUint16(6, 0, !0), c.setUint16(8, 0, !0), c.setUint16(10, 0, !0), c.setUint16(12, 33, !0), c.setUint32(14, a, !0), c.setUint32(18, o, !0), c.setUint32(22, o, !0), c.setUint16(26, e.length, !0), c.setUint16(28, 0, !0), new Uint8Array(s, 30).set(e), t.push(new Uint8Array(s)), t.push(i.data);
1385
1406
  let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
1386
1407
  u.setUint32(0, 33639248, !0), u.setUint16(4, 20, !0), u.setUint16(6, 20, !0), u.setUint16(8, 0, !0), u.setUint16(10, 0, !0), u.setUint16(12, 0, !0), u.setUint16(14, 33, !0), u.setUint32(16, a, !0), u.setUint32(20, o, !0), u.setUint32(24, o, !0), u.setUint16(28, e.length, !0), u.setUint16(30, 0, !0), u.setUint16(32, 0, !0), u.setUint16(34, 0, !0), u.setUint16(36, 0, !0), u.setUint32(38, 0, !0), u.setUint32(42, r, !0), new Uint8Array(l, 46).set(e), n.push(new Uint8Array(l)), r += 30 + e.length + o;
1387
1408
  }
1388
- let i = P(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1389
- return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), P([
1409
+ let i = F(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1410
+ return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), F([
1390
1411
  ...t,
1391
1412
  i,
1392
1413
  new Uint8Array(a)
1393
1414
  ]);
1394
1415
  }
1395
- function P(e) {
1416
+ function F(e) {
1396
1417
  let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
1397
1418
  for (let t of e) n.set(t, r), r += t.length;
1398
1419
  return n;
1399
1420
  }
1400
- function F(e) {
1421
+ function I(e) {
1401
1422
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1402
1423
  }
1403
- function ce(e) {
1424
+ function le(e) {
1404
1425
  let t = "";
1405
1426
  for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1406
1427
  return t;
1407
1428
  }
1408
- function I(e, t) {
1409
- return ce(t) + (e + 1);
1429
+ function L(e, t) {
1430
+ return le(t) + (e + 1);
1410
1431
  }
1411
- function le(e) {
1432
+ function ue(e) {
1412
1433
  let t = Date.UTC(1899, 11, 30);
1413
1434
  return (e.getTime() - t) / 864e5;
1414
1435
  }
1415
- var ue = "<?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>", de = "<?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>", fe = "<?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>", pe = "<?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>", L = "<?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>";
1416
- function R(e, t) {
1417
- let n = [], r = t.map((e, t) => `<c r="${I(0, t)}" t="str" s="2"><v>${F(e.label)}</v></c>`);
1436
+ var de = "<?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>", fe = "<?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>", pe = "<?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>", me = "<?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>", R = "<?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>";
1437
+ function z(e, t) {
1438
+ let n = [], r = t.map((e, t) => `<c r="${L(0, t)}" t="str" s="2"><v>${I(e.label)}</v></c>`);
1418
1439
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1419
1440
  let i = t.map((t, n) => {
1420
- let i = I(r + 1, n), a = e[t.key];
1441
+ let i = L(r + 1, n), a = e[t.key];
1421
1442
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1422
1443
  let o = t.type ?? "text";
1423
- 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>${le(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${F(String(a))}</v></c>`;
1444
+ 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>${ue(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>`;
1424
1445
  });
1425
1446
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1426
1447
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -1428,32 +1449,32 @@ function R(e, t) {
1428
1449
  <sheetData>${n.join("")}</sheetData>
1429
1450
  </worksheet>`;
1430
1451
  }
1431
- function z(e, t) {
1432
- let n = R(e, t);
1433
- return se([
1452
+ function he(e, t) {
1453
+ let n = z(e, t);
1454
+ return ce([
1434
1455
  {
1435
1456
  name: "[Content_Types].xml",
1436
- data: N.encode(ue)
1457
+ data: P.encode(de)
1437
1458
  },
1438
1459
  {
1439
1460
  name: "_rels/.rels",
1440
- data: N.encode(de)
1461
+ data: P.encode(fe)
1441
1462
  },
1442
1463
  {
1443
1464
  name: "xl/workbook.xml",
1444
- data: N.encode(fe)
1465
+ data: P.encode(pe)
1445
1466
  },
1446
1467
  {
1447
1468
  name: "xl/_rels/workbook.xml.rels",
1448
- data: N.encode(pe)
1469
+ data: P.encode(me)
1449
1470
  },
1450
1471
  {
1451
1472
  name: "xl/worksheets/sheet1.xml",
1452
- data: N.encode(n)
1473
+ data: P.encode(n)
1453
1474
  },
1454
1475
  {
1455
1476
  name: "xl/styles.xml",
1456
- data: N.encode(L)
1477
+ data: P.encode(R)
1457
1478
  }
1458
1479
  ]);
1459
1480
  }
@@ -1463,20 +1484,20 @@ function B(e, t, n) {
1463
1484
  switch (n) {
1464
1485
  case "csv": return V(e, t, ",");
1465
1486
  case "tsv": return V(e, t, " ");
1466
- case "json": return he(e, t);
1467
- case "xlsx": return z(e, t);
1487
+ case "json": return _e(e, t);
1488
+ case "xlsx": return he(e, t);
1468
1489
  }
1469
1490
  }
1470
- function me(e, t) {
1491
+ function ge(e, t) {
1471
1492
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
1472
1493
  }
1473
1494
  function V(e, t, n) {
1474
- return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(me(e[t.key], t), n)).join(n))].join("\n");
1495
+ return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(ge(e[t.key], t), n)).join(n))].join("\n");
1475
1496
  }
1476
1497
  function H(e, t) {
1477
1498
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
1478
1499
  }
1479
- function he(e, t) {
1500
+ function _e(e, t) {
1480
1501
  let n = e.map((e) => {
1481
1502
  let n = {};
1482
1503
  for (let r of t) {
@@ -1487,35 +1508,35 @@ function he(e, t) {
1487
1508
  });
1488
1509
  return JSON.stringify(n, null, 2);
1489
1510
  }
1490
- function ge(e, t, n) {
1511
+ function ve(e, t, n) {
1491
1512
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
1492
1513
  a.href = i, a.download = t, a.style.display = "none", document.body.appendChild(a), a.click(), document.body.removeChild(a), setTimeout(() => URL.revokeObjectURL(i), 100);
1493
1514
  }
1494
- var _e = {
1515
+ var ye = {
1495
1516
  csv: "text/csv;charset=utf-8",
1496
1517
  tsv: "text/tab-separated-values;charset=utf-8",
1497
1518
  json: "application/json;charset=utf-8",
1498
1519
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1499
- }, ve = {
1520
+ }, be = {
1500
1521
  csv: ".csv",
1501
1522
  tsv: ".tsv",
1502
1523
  json: ".json",
1503
1524
  xlsx: ".xlsx"
1504
1525
  };
1505
- function ye(e) {
1506
- return _e[e];
1526
+ function xe(e) {
1527
+ return ye[e];
1507
1528
  }
1508
- function be(e) {
1509
- return ve[e];
1529
+ function Se(e) {
1530
+ return be[e];
1510
1531
  }
1511
1532
  //#endregion
1512
1533
  //#region src/export/xlsx-reader.ts
1513
- function xe(e) {
1534
+ function Ce(e) {
1514
1535
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
1515
1536
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
1516
1537
  }
1517
- function Se(e) {
1518
- let t = xe(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
1538
+ function we(e) {
1539
+ let t = Ce(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
1519
1540
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
1520
1541
  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));
1521
1542
  a.push({
@@ -1528,7 +1549,7 @@ function Se(e) {
1528
1549
  }
1529
1550
  return a;
1530
1551
  }
1531
- async function Ce(e) {
1552
+ async function Te(e) {
1532
1553
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
1533
1554
  n.write(e), n.close();
1534
1555
  let i = [];
@@ -1541,28 +1562,28 @@ async function Ce(e) {
1541
1562
  for (let e of i) o.set(e, s), s += e.length;
1542
1563
  return o;
1543
1564
  }
1544
- async function we(e, t) {
1565
+ async function Ee(e, t) {
1545
1566
  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);
1546
1567
  if (t.compressionMethod === 0) return o.slice();
1547
- if (t.compressionMethod === 8) return Ce(o);
1568
+ if (t.compressionMethod === 8) return Te(o);
1548
1569
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
1549
1570
  }
1550
- async function Te(e) {
1551
- let t = new DataView(e), n = Se(t), r = /* @__PURE__ */ new Map();
1552
- for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await we(t, e));
1571
+ async function De(e) {
1572
+ let t = new DataView(e), n = we(t), r = /* @__PURE__ */ new Map();
1573
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ee(t, e));
1553
1574
  return r;
1554
1575
  }
1555
- var Ee = new TextDecoder("utf-8");
1576
+ var Oe = new TextDecoder("utf-8");
1556
1577
  function U(e) {
1557
- let t = Ee.decode(e);
1578
+ let t = Oe.decode(e);
1558
1579
  return new DOMParser().parseFromString(t, "application/xml");
1559
1580
  }
1560
- function De(e) {
1581
+ function ke(e) {
1561
1582
  if (!e) return [];
1562
1583
  let t = U(e);
1563
1584
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
1564
1585
  }
1565
- var Oe = /* @__PURE__ */ new Set([
1586
+ var Ae = /* @__PURE__ */ new Set([
1566
1587
  14,
1567
1588
  15,
1568
1589
  16,
@@ -1582,29 +1603,29 @@ var Oe = /* @__PURE__ */ new Set([
1582
1603
  57,
1583
1604
  58
1584
1605
  ]);
1585
- function ke(e) {
1606
+ function je(e) {
1586
1607
  let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
1587
1608
  return /[dy]/i.test(t);
1588
1609
  }
1589
- function Ae(e) {
1610
+ function Me(e) {
1590
1611
  let t = /* @__PURE__ */ new Set();
1591
1612
  if (!e) return t;
1592
1613
  let n = U(e), r = /* @__PURE__ */ new Map();
1593
1614
  for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
1594
1615
  return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
1595
1616
  let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
1596
- (a === void 0 ? Oe.has(i) : ke(a)) && t.add(n);
1617
+ (a === void 0 ? Ae.has(i) : je(a)) && t.add(n);
1597
1618
  }), t;
1598
1619
  }
1599
- function je(e) {
1620
+ function Ne(e) {
1600
1621
  if (!e) return !1;
1601
1622
  let t = U(e).querySelector("workbookPr")?.getAttribute("date1904");
1602
1623
  return t === "1" || t === "true";
1603
1624
  }
1604
- function Me(e, t) {
1625
+ function Pe(e, t) {
1605
1626
  return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
1606
1627
  }
1607
- function Ne(e, t, n, r) {
1628
+ function Fe(e, t, n, r) {
1608
1629
  let i = U(e).querySelectorAll("row");
1609
1630
  if (i.length === 0) return [];
1610
1631
  let a = 0, o = /* @__PURE__ */ new Map();
@@ -1612,7 +1633,7 @@ function Ne(e, t, n, r) {
1612
1633
  let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
1613
1634
  o.set(i, s);
1614
1635
  for (let i of e.querySelectorAll("c")) {
1615
- let e = W(i.getAttribute("r") ?? "");
1636
+ let e = Ie(i.getAttribute("r") ?? "");
1616
1637
  e > a && (a = e);
1617
1638
  let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
1618
1639
  if (o === "s") d = t[parseInt(l, 10)] ?? "";
@@ -1621,7 +1642,7 @@ function Ne(e, t, n, r) {
1621
1642
  else if (l === "") d = "";
1622
1643
  else {
1623
1644
  let e = parseFloat(l);
1624
- d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Me(e, r) : l;
1645
+ d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Pe(e, r) : l;
1625
1646
  }
1626
1647
  s.set(e, d);
1627
1648
  }
@@ -1635,13 +1656,13 @@ function Ne(e, t, n, r) {
1635
1656
  }
1636
1657
  return c;
1637
1658
  }
1638
- function W(e) {
1659
+ function Ie(e) {
1639
1660
  let t = 0, n = 0;
1640
1661
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
1641
1662
  return t - 1;
1642
1663
  }
1643
- async function Pe(e) {
1644
- let t = await Te(e), n = De(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1664
+ async function W(e) {
1665
+ let t = await De(e), n = ke(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1645
1666
  if (!r) {
1646
1667
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
1647
1668
  r = n;
@@ -1649,7 +1670,7 @@ async function Pe(e) {
1649
1670
  }
1650
1671
  }
1651
1672
  if (!r) throw Error("XLSX: No worksheet found");
1652
- let i = Ae(t.get("xl/styles.xml")), a = je(t.get("xl/workbook.xml")), o = Ne(r, n, i, a);
1673
+ let i = Me(t.get("xl/styles.xml")), a = Ne(t.get("xl/workbook.xml")), o = Fe(r, n, i, a);
1653
1674
  return o.length === 0 ? {
1654
1675
  headers: [],
1655
1676
  rows: []
@@ -1664,7 +1685,7 @@ function G(e) {
1664
1685
  return e.align ? e.align : e.type === "number" ? "end" : e.type === "boolean" ? "center" : "start";
1665
1686
  }
1666
1687
  //#endregion
1667
- //#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
1688
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/decorate.js
1668
1689
  function K(e, t, n, r) {
1669
1690
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
1670
1691
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
@@ -1680,14 +1701,14 @@ var q = {
1680
1701
  lt: "<",
1681
1702
  gte: "≥",
1682
1703
  lte: "≤"
1683
- }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Fe = 200, $ = class extends n {
1704
+ }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Le = 200, $ = class extends n {
1684
1705
  constructor(...e) {
1685
- super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", 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._editingCell = null, this._sortCriteria = [], this._selection = new te(), this._editing = new ne(), this._rowSelection = new k(), this._undo = new A(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = 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._warnedUnconstrained = !1, this._onCommentPopupOutsideClick = () => {
1706
+ super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", 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._editingCell = null, this._sortCriteria = [], this._selection = new te(), this._editing = new ne(), this._rowSelection = new A(), this._undo = new j(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = 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._warnedUnconstrained = !1, this._onCommentPopupOutsideClick = () => {
1686
1707
  this._commitCommentPopup();
1687
1708
  }, 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();
1688
1709
  }
1689
1710
  static {
1690
- this.styles = h;
1711
+ this.styles = g;
1691
1712
  }
1692
1713
  get data() {
1693
1714
  return this._data;
@@ -2052,7 +2073,7 @@ var q = {
2052
2073
  return B(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2053
2074
  }
2054
2075
  exportToFile(e, t) {
2055
- ge(this.exportToString(e), t ?? `export${be(e)}`, ye(e));
2076
+ ve(this.exportToString(e), t ?? `export${Se(e)}`, xe(e));
2056
2077
  }
2057
2078
  setComment(e, t, n) {
2058
2079
  let r = this.getComment(e, t);
@@ -2109,10 +2130,10 @@ var q = {
2109
2130
  async importFromFile(e) {
2110
2131
  let t = e.name.toLowerCase();
2111
2132
  if (t.endsWith(".xlsx")) {
2112
- let t = await Pe(await e.arrayBuffer());
2133
+ let t = await W(await e.arrayBuffer());
2113
2134
  this._applyImportedSheet(t);
2114
2135
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
2115
- let t = await e.text(), n = f(t);
2136
+ let t = await e.text(), n = p(t);
2116
2137
  this._applyImportedRows(n);
2117
2138
  } else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
2118
2139
  }
@@ -2123,7 +2144,7 @@ var q = {
2123
2144
  let a = t.get(e);
2124
2145
  if (!a) return;
2125
2146
  let o = this.columns.find((e) => e.key === a);
2126
- r[a] = o ? j(n[i] ?? "", o) : n[i] ?? null;
2147
+ r[a] = o ? M(n[i] ?? "", o) : n[i] ?? null;
2127
2148
  }), r;
2128
2149
  }), r = [...this.data];
2129
2150
  this.data = n, this._undo.push({
@@ -2148,7 +2169,7 @@ var q = {
2148
2169
  let a = n.get(t);
2149
2170
  if (!a) return;
2150
2171
  let o = this.columns.find((e) => e.key === a);
2151
- r[a] = o ? j(e[i] ?? "", o) : e[i] ?? null;
2172
+ r[a] = o ? M(e[i] ?? "", o) : e[i] ?? null;
2152
2173
  }), r;
2153
2174
  }), i = [...this.data];
2154
2175
  this.data = r, this._undo.push({
@@ -2291,7 +2312,7 @@ var q = {
2291
2312
  }
2292
2313
  updated(e) {
2293
2314
  this._focusEditor(), this._adjustFilterDropdown(), e.has("_headerMenu") && this._keepMenuInView(".ft-header-menu"), e.has("_bodyContextMenu") && this._bodyContextMenu && (this._keepMenuInView(".ft-body-context-menu"), this.shadowRoot?.querySelector(".ft-body-context-menu [role=\"menuitem\"]")?.focus()), e.has("stylesheets") && this._syncStylesheets();
2294
- let t = String(this._visibleRowCount), n = String(this.visibleColumns.length);
2315
+ let t = String(1 + this._visibleRowCount + +!!this.footerData), n = String(this.visibleColumns.length);
2295
2316
  if (this.getAttribute("aria-rowcount") !== t && this.setAttribute("aria-rowcount", t), this.getAttribute("aria-colcount") !== n && this.setAttribute("aria-colcount", n), this.loading ? this.getAttribute("aria-busy") !== "true" && this.setAttribute("aria-busy", "true") : this.hasAttribute("aria-busy") && this.removeAttribute("aria-busy"), e.has("_commentPopup") && this._commentPopup) {
2296
2317
  let e = this.shadowRoot?.querySelector(".ft-comment-popup textarea");
2297
2318
  e && (e.value = this.getComment(this._commentPopup.dataIndex, this._commentPopup.colKey) ?? "", e.focus(), e.select());
@@ -2325,14 +2346,14 @@ var q = {
2325
2346
  _focusEditor() {
2326
2347
  if (!this._editingCell) return;
2327
2348
  let e = this.shadowRoot?.querySelector(".ft-editor");
2328
- e && document.activeElement !== e && (e.focus(), (e.type === "text" || e.type === "number") && e.select());
2349
+ e && document.activeElement !== e && (e.focus(), e.type === "text" && e.select());
2329
2350
  }
2330
2351
  _measureViewport() {
2331
2352
  let e = this.clientHeight, t = this.clientWidth;
2332
2353
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2333
2354
  }
2334
2355
  _warnIfUnconstrained() {
2335
- this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Fe || 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.`));
2356
+ this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Le || 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.`));
2336
2357
  }
2337
2358
  _onScroll() {
2338
2359
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -2462,7 +2483,7 @@ var q = {
2462
2483
  }
2463
2484
  let t = this.shadowRoot?.querySelector(".ft-editor");
2464
2485
  if (t) {
2465
- let n = j(t.value, e);
2486
+ let n = M(t.value, e);
2466
2487
  this._applyEdit(n);
2467
2488
  } else this._cancelEdit();
2468
2489
  }
@@ -2472,7 +2493,22 @@ var q = {
2472
2493
  if (this._editingCell = null, !t) return;
2473
2494
  let { row: n, col: r } = t.position, i = this._toDataIndex(n), a = this.visibleColumns[r], o = t.originalValue;
2474
2495
  if (a.autocomplete === "strict" && e != null && e !== "" && !this._getAutocompleteCandidates(a, "").includes(String(e))) {
2475
- let t = "Value must be from the existing list";
2496
+ let t = k("notInList");
2497
+ this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
2498
+ detail: {
2499
+ row: i,
2500
+ col: r,
2501
+ key: a.key,
2502
+ value: e,
2503
+ error: t
2504
+ },
2505
+ bubbles: !0,
2506
+ composed: !0
2507
+ }));
2508
+ return;
2509
+ }
2510
+ if (a.type === "number" && typeof e == "string") {
2511
+ let t = k("notANumber");
2476
2512
  this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
2477
2513
  detail: {
2478
2514
  row: i,
@@ -2536,7 +2572,7 @@ var q = {
2536
2572
  }));
2537
2573
  }
2538
2574
  _onEditorKeyDown(e) {
2539
- if (!m(e)) {
2575
+ if (!h(e)) {
2540
2576
  if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
2541
2577
  if (e.key === "ArrowDown") {
2542
2578
  e.preventDefault(), e.stopPropagation();
@@ -2604,7 +2640,7 @@ var q = {
2604
2640
  ].includes(t) && this._handleCtrlKey(e)) return;
2605
2641
  }
2606
2642
  if (t.length !== 0 && this._visibleRowCount !== 0) {
2607
- if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !m(e)) {
2643
+ if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !h(e)) {
2608
2644
  e.preventDefault();
2609
2645
  let n = t[this._activeCell.col];
2610
2646
  n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n);
@@ -2718,7 +2754,7 @@ var q = {
2718
2754
  if (!this._activeCell) return;
2719
2755
  let e = await this._readClipboardText();
2720
2756
  if (e == null) return;
2721
- let t = f(e);
2757
+ let t = p(e);
2722
2758
  if (t.length === 0) return;
2723
2759
  let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
2724
2760
  if (r.length > 0 || n.length > 0) {
@@ -2776,7 +2812,7 @@ var q = {
2776
2812
  for (let a = 0; a < t[i].length; a++) {
2777
2813
  let s = e.col + a;
2778
2814
  if (s >= n.length) break;
2779
- let c = n[s], l = this.data[o][c.key], u = j(t[i][a], c);
2815
+ let c = n[s], l = this.data[o][c.key], u = M(t[i][a], c);
2780
2816
  this.data[o][c.key] = u, r.push({
2781
2817
  row: o,
2782
2818
  col: s,
@@ -2841,7 +2877,7 @@ var q = {
2841
2877
  for (let r = e.startCol + 1; r <= e.endCol; r++) {
2842
2878
  let e = t[r];
2843
2879
  if (!e || !this._isCellEditable(e)) continue;
2844
- let a = j(o == null ? "" : String(o), e);
2880
+ let a = M(o == null ? "" : String(o), e);
2845
2881
  n.push({
2846
2882
  row: i,
2847
2883
  key: e.key,
@@ -2992,6 +3028,7 @@ var q = {
2992
3028
  return i`
2993
3029
  <div class=${y}
2994
3030
  role="columnheader"
3031
+ aria-colindex=${t + 1}
2995
3032
  data-col-index=${t}
2996
3033
  style=${_}
2997
3034
  aria-sort=${p ?? a}
@@ -3000,7 +3037,7 @@ var q = {
3000
3037
  @click=${n ? (t) => this._onHeaderClick(t, e) : void 0}>
3001
3038
  ${C ? i`
3002
3039
  <button class="ft-hidden-col-indicator"
3003
- title=${O("showHiddenColumns")}
3040
+ title=${k("showHiddenColumns")}
3004
3041
  @click=${(t) => {
3005
3042
  t.stopPropagation(), this._showHiddenBefore(e);
3006
3043
  }}>&#x276F;</button>
@@ -3010,8 +3047,8 @@ var q = {
3010
3047
  ${o >= 0 ? i`<span class="ft-sort-order">${o + 1}</span>` : ""}
3011
3048
  <button class="ft-column-menu-btn ${s ? "ft-filter-active" : ""}"
3012
3049
  type="button"
3013
- title=${O("columnMenu")}
3014
- aria-label=${O("columnMenuFor", { header: e.label })}
3050
+ title=${k("columnMenu")}
3051
+ aria-label=${k("columnMenuFor", { header: e.label })}
3015
3052
  aria-haspopup="menu"
3016
3053
  aria-expanded=${this._headerMenu?.key === e.key ? "true" : "false"}
3017
3054
  @mousedown=${(e) => e.stopPropagation()}
@@ -3130,26 +3167,26 @@ var q = {
3130
3167
  }}>${t}</button>
3131
3168
  `;
3132
3169
  return i`
3133
- <div class="ft-header-menu" role="menu" aria-label=${O("columnMenuRegion", { header: o.label })}
3170
+ <div class="ft-header-menu" role="menu" aria-label=${k("columnMenuRegion", { header: o.label })}
3134
3171
  style="position: fixed; left: ${t}px; top: ${n}px; z-index: var(--u-layer-floating, 1000);"
3135
3172
  @mousedown=${(e) => e.stopPropagation()}
3136
3173
  @keydown=${(e) => this._onHeaderMenuKeydown(e)}>
3137
3174
  ${o.sortable === !1 ? a : i`
3138
- ${c("sort-asc", O("sortAscending"), () => this._applySortFromMenu(e, "asc"))}
3139
- ${c("sort-desc", O("sortDescending"), () => this._applySortFromMenu(e, "desc"))}
3175
+ ${c("sort-asc", k("sortAscending"), () => this._applySortFromMenu(e, "asc"))}
3176
+ ${c("sort-desc", k("sortDescending"), () => this._applySortFromMenu(e, "desc"))}
3140
3177
  <div class="ft-header-menu-separator" role="separator"></div>
3141
3178
  `}
3142
3179
  ${this.showFilters ? i`
3143
- ${c("filter", O("filter"), () => this._openFilterFromMenu(e))}
3144
- ${s ? c("clear-filter", O("clearFilter"), () => this._clearColumnFilter(e)) : a}
3180
+ ${c("filter", k("filter"), () => this._openFilterFromMenu(e))}
3181
+ ${s ? c("clear-filter", k("clearFilter"), () => this._clearColumnFilter(e)) : a}
3145
3182
  <div class="ft-header-menu-separator" role="separator"></div>
3146
3183
  ` : a}
3147
- ${c("hide", O("hideColumn"), () => this._setColumnHidden(e, !0))}
3148
- ${r.map((e) => c("show", O("showColumn", { header: e.label }), () => this._setColumnHidden(e.key, !1)))}
3184
+ ${c("hide", k("hideColumn"), () => this._setColumnHidden(e, !0))}
3185
+ ${r.map((e) => c("show", k("showColumn", { header: e.label }), () => this._setColumnHidden(e.key, !1)))}
3149
3186
  <div class="ft-header-menu-separator" role="separator"></div>
3150
- ${c("autofit", O("autoFitWidth"), () => this._autoFitColumn(e))}
3151
- ${c("wider", O("wider"), () => this._resizeColumnBy(e, X), !0)}
3152
- ${c("narrower", O("narrower"), () => this._resizeColumnBy(e, -20), !0)}
3187
+ ${c("autofit", k("autoFitWidth"), () => this._autoFitColumn(e))}
3188
+ ${c("wider", k("wider"), () => this._resizeColumnBy(e, X), !0)}
3189
+ ${c("narrower", k("narrower"), () => this._resizeColumnBy(e, -20), !0)}
3153
3190
  </div>
3154
3191
  `;
3155
3192
  }
@@ -3167,26 +3204,26 @@ var q = {
3167
3204
  }}>${e}</button>
3168
3205
  `, f = i`<div class="ft-context-menu-separator" role="separator"></div>`;
3169
3206
  return i`
3170
- <div class="ft-body-context-menu" role="menu" aria-label=${O("cellActions")}
3207
+ <div class="ft-body-context-menu" role="menu" aria-label=${k("cellActions")}
3171
3208
  style="position: fixed; left: ${n}px; top: ${r}px; z-index: var(--u-layer-floating, 1000);"
3172
3209
  @mousedown=${(e) => e.stopPropagation()}
3173
3210
  @keydown=${(e) => this._onMenuKeydown(e, ".ft-body-context-menu", l)}>
3174
- ${d(O("copy"), () => this._handleCopy(!1))}
3211
+ ${d(k("copy"), () => this._handleCopy(!1))}
3175
3212
  ${f}
3176
- ${d(O("insertRowAbove"), () => this.addRow(void 0, t))}
3177
- ${d(O("insertRowBelow"), () => this.addRow(void 0, t + 1))}
3178
- ${d(O("deleteRow"), () => this.deleteRows([t]), !0)}
3213
+ ${d(k("insertRowAbove"), () => this.addRow(void 0, t))}
3214
+ ${d(k("insertRowBelow"), () => this.addRow(void 0, t + 1))}
3215
+ ${d(k("deleteRow"), () => this.deleteRows([t]), !0)}
3179
3216
  ${f}
3180
- ${d(O("hideColumn"), () => this._setColumnHidden(o.key, !0))}
3217
+ ${d(k("hideColumn"), () => this._setColumnHidden(o.key, !0))}
3181
3218
  ${f}
3182
- ${d(`${O("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
3183
- ${d(`${O("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
3219
+ ${d(`${k("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
3220
+ ${d(`${k("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
3184
3221
  ${f}
3185
- ${d(O("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
3186
- ${c ? d(O("clearFilter"), () => this.removeFilter(o.key)) : a}
3222
+ ${d(k("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
3223
+ ${c ? d(k("clearFilter"), () => this.removeFilter(o.key)) : a}
3187
3224
  ${f}
3188
- ${d(O(u ? "editComment" : "addComment"), () => this._openCommentPopup(t, o.key, n, r))}
3189
- ${u ? d(O("deleteComment"), () => this.setComment(t, o.key, null), !0) : a}
3225
+ ${d(k(u ? "editComment" : "addComment"), () => this._openCommentPopup(t, o.key, n, r))}
3226
+ ${u ? d(k("deleteComment"), () => this.setComment(t, o.key, null), !0) : a}
3190
3227
  </div>
3191
3228
  `;
3192
3229
  }
@@ -3218,13 +3255,13 @@ var q = {
3218
3255
  @mousedown=${(e) => e.stopPropagation()}>
3219
3256
  <textarea class="ft-comment-popup-textarea"
3220
3257
  rows="4"
3221
- placeholder=${O("addCommentPlaceholder")}
3258
+ placeholder=${k("addCommentPlaceholder")}
3222
3259
  @keydown=${(e) => {
3223
3260
  e.key === "Escape" && (e.preventDefault(), this._cancelCommentPopup()), e.key === "Enter" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this._commitCommentPopup());
3224
3261
  }}></textarea>
3225
3262
  <div class="ft-comment-popup-buttons">
3226
- <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${O("cancel")}</button>
3227
- <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${O("save")}</button>
3263
+ <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${k("cancel")}</button>
3264
+ <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${k("save")}</button>
3228
3265
  </div>
3229
3266
  </div>
3230
3267
  `;
@@ -3260,7 +3297,7 @@ var q = {
3260
3297
  <div class="ft-filter-dropdown" @click=${(e) => e.stopPropagation()}>
3261
3298
  ${t === "boolean" ? this._renderBooleanFilter(e) : t === "number" ? this._renderNumberFilter(e) : t === "date" || t === "datetime" ? this._renderDateFilter(e) : this._renderTextFilter(e)}
3262
3299
  <div class="ft-filter-actions">
3263
- <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${O("clear")}</button>
3300
+ <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${k("clear")}</button>
3264
3301
  </div>
3265
3302
  </div>
3266
3303
  `;
@@ -3293,7 +3330,7 @@ var q = {
3293
3330
  let n = this._emptyFilterState.get(e) ?? "";
3294
3331
  return i`
3295
3332
  <div class="ft-filter-empty-row">
3296
- <label>${O("blankCells")}</label>
3333
+ <label>${k("blankCells")}</label>
3297
3334
  <select class="ft-filter-mode-select"
3298
3335
  .value=${n}
3299
3336
  @change=${(n) => {
@@ -3303,9 +3340,9 @@ var q = {
3303
3340
  @keydown=${(e) => {
3304
3341
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3305
3342
  }}>
3306
- <option value="">${O("blankAll")}</option>
3307
- <option value="empty">${O("emptyOnly")}</option>
3308
- <option value="non-empty">${O("nonEmptyOnly")}</option>
3343
+ <option value="">${k("blankAll")}</option>
3344
+ <option value="empty">${k("emptyOnly")}</option>
3345
+ <option value="non-empty">${k("nonEmptyOnly")}</option>
3309
3346
  </select>
3310
3347
  </div>
3311
3348
  `;
@@ -3381,13 +3418,13 @@ var q = {
3381
3418
  @keydown=${(e) => {
3382
3419
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3383
3420
  }}>
3384
- <option value="contains">${O("contains")}</option>
3385
- <option value="starts">${O("startsWith")}</option>
3386
- <option value="ends">${O("endsWith")}</option>
3387
- <option value="wildcard">${O("wildcard")}</option>
3421
+ <option value="contains">${k("contains")}</option>
3422
+ <option value="starts">${k("startsWith")}</option>
3423
+ <option value="ends">${k("endsWith")}</option>
3424
+ <option value="wildcard">${k("wildcard")}</option>
3388
3425
  </select>
3389
3426
  </div>
3390
- <input class="ft-filter-input" type="text" placeholder=${O("searchPlaceholder")}
3427
+ <input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")}
3391
3428
  .value=${t.value}
3392
3429
  @input=${(t) => {
3393
3430
  let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
@@ -3438,13 +3475,15 @@ var q = {
3438
3475
  }}>
3439
3476
  ${Object.keys(q).map((e) => i`<option value=${e}>${q[e]}</option>`)}
3440
3477
  </select>
3441
- <input class="ft-filter-input ft-num-cond-input" type="number" placeholder=${O("valuePlaceholder")}
3442
- .value=${n.value == null ? "" : String(n.value)}
3478
+ <input class="ft-filter-input ft-num-cond-input" type="text" inputmode="decimal" placeholder=${k("valuePlaceholder")}
3479
+ .value=${n.text ?? (n.value == null ? "" : N(n.value))}
3480
+ aria-invalid=${n.text && n.value == null ? "true" : "false"}
3443
3481
  @input=${(n) => {
3444
3482
  let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
3445
3483
  i[t] = {
3446
3484
  ...i[t],
3447
- value: r === "" ? null : Number(r)
3485
+ text: r,
3486
+ value: r.trim() === "" ? null : f(r)
3448
3487
  }, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
3449
3488
  }}
3450
3489
  @keydown=${(e) => {
@@ -3499,13 +3538,13 @@ var q = {
3499
3538
  let t = e.type === "datetime" ? "datetime-local" : "date", n = this._dateFilterState.get(e.key) ?? {};
3500
3539
  return i`
3501
3540
  <div class="ft-filter-range">
3502
- <input class="ft-filter-input" type=${t} placeholder=${O("fromPlaceholder")}
3541
+ <input class="ft-filter-input" type=${t} placeholder=${k("fromPlaceholder")}
3503
3542
  .value=${n.from ?? ""}
3504
3543
  @input=${(t) => this._applyDateFilter(e.key, t, "from")}
3505
3544
  @keydown=${(e) => {
3506
3545
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3507
3546
  }}>
3508
- <input class="ft-filter-input" type=${t} placeholder=${O("toPlaceholder")}
3547
+ <input class="ft-filter-input" type=${t} placeholder=${k("toPlaceholder")}
3509
3548
  .value=${n.to ?? ""}
3510
3549
  @input=${(t) => this._applyDateFilter(e.key, t, "to")}
3511
3550
  @keydown=${(e) => {
@@ -3531,9 +3570,9 @@ var q = {
3531
3570
  @keydown=${(e) => {
3532
3571
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3533
3572
  }}>
3534
- <option value="all">${O("all")}</option>
3535
- <option value="true">\u2714 ${O("booleanTrue")}</option>
3536
- <option value="false">\u2718 ${O("booleanFalse")}</option>
3573
+ <option value="all">${k("all")}</option>
3574
+ <option value="true">\u2714 ${k("booleanTrue")}</option>
3575
+ <option value="false">\u2718 ${k("booleanFalse")}</option>
3537
3576
  </select>
3538
3577
  ${this._renderEmptyFilterRow(e.key)}
3539
3578
  `;
@@ -3950,42 +3989,42 @@ var q = {
3950
3989
  this._closeFindPanel();
3951
3990
  return;
3952
3991
  }
3953
- e.key === "Enter" && !m(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
3992
+ e.key === "Enter" && !h(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
3954
3993
  }}>
3955
3994
  <div class="ft-find-row">
3956
- <input class="ft-find-input" type="text" placeholder=${O("findPlaceholder")}
3995
+ <input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")}
3957
3996
  .value=${t}
3958
3997
  @input=${(e) => {
3959
3998
  this._findState.query = e.target.value, this._findSearch();
3960
3999
  }}>
3961
4000
  <span class="ft-find-count">${c > 0 ? `${l}/${c}` : t ? "0 results" : ""}</span>
3962
- <button @click=${() => this._findPrev()} title=${O("findPrevious")}>◀</button>
3963
- <button @click=${() => this._findNext()} title=${O("findNext")}>▶</button>
3964
- <label title=${O("matchCase")}><input type="checkbox" ?checked=${r} @change=${(e) => {
4001
+ <button @click=${() => this._findPrev()} title=${k("findPrevious")}>◀</button>
4002
+ <button @click=${() => this._findNext()} title=${k("findNext")}>▶</button>
4003
+ <label title=${k("matchCase")}><input type="checkbox" ?checked=${r} @change=${(e) => {
3965
4004
  this._findState.matchCase = e.target.checked, this._findSearch();
3966
4005
  }}> Aa</label>
3967
- <label title=${O("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
4006
+ <label title=${k("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
3968
4007
  this._findState.wholeCell = e.target.checked, this._findSearch();
3969
4008
  }}> [ ]</label>
3970
- <button @click=${() => this._closeFindPanel()} title=${O("closeFind")}>✕</button>
4009
+ <button @click=${() => this._closeFindPanel()} title=${k("closeFind")}>✕</button>
3971
4010
  </div>
3972
4011
  ${e === "replace" ? i`
3973
4012
  <div class="ft-find-row">
3974
- <input class="ft-find-replace-input" type="text" placeholder=${O("replaceWithPlaceholder")}
4013
+ <input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")}
3975
4014
  .value=${n}
3976
4015
  @input=${(e) => {
3977
4016
  this._findState.replaceWith = e.target.value;
3978
4017
  }}>
3979
- <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${O("replace")}</button>
3980
- <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${O("replaceAll")}</button>
4018
+ <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${k("replace")}</button>
4019
+ <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${k("replaceAll")}</button>
3981
4020
  </div>
3982
4021
  ` : ""}
3983
4022
  </div>
3984
4023
  `;
3985
4024
  }
3986
4025
  render() {
3987
- let e = this.visibleColumns, t = this.importEnabled && this._isDragOver ? i`<div class="ft-import-overlay">${O("dropFileToImport")}</div>` : a, n = this.loading ? i`<div class="ft-loading-overlay"></div>` : a;
3988
- if (e.length === 0) return i`${t}${n}<div class="ft-empty">${O("noColumnsDefined")}</div>`;
4026
+ let e = this.visibleColumns, t = this.importEnabled && this._isDragOver ? i`<div class="ft-import-overlay">${k("dropFileToImport")}</div>` : a, n = this.loading ? i`<div class="ft-loading-overlay"></div>` : a;
4027
+ if (e.length === 0) return i`${t}${n}<div class="ft-empty">${k("noColumnsDefined")}</div>`;
3989
4028
  let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
3990
4029
  for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
3991
4030
  let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
@@ -4007,7 +4046,7 @@ var q = {
4007
4046
  let e = this.data.length === 0 ? this.emptyMessage : this.noMatchingMessage;
4008
4047
  return i`
4009
4048
  ${n}
4010
- <div class="ft-header" role="row" style="width: ${o}px; height: ${r}px;">
4049
+ <div class="ft-header" role="row" aria-rowindex="1" style="width: ${o}px; height: ${r}px;">
4011
4050
  ${f}${p}
4012
4051
  ${m}
4013
4052
  ${h}
@@ -4022,7 +4061,7 @@ var q = {
4022
4061
  ${t}
4023
4062
  ${n}
4024
4063
  ${this._renderFindPanel()}
4025
- <div class="ft-header" role="row" style="width: ${o}px; height: ${r}px;">
4064
+ <div class="ft-header" role="row" aria-rowindex="1" style="width: ${o}px; height: ${r}px;">
4026
4065
  ${f}${p}
4027
4066
  ${m}
4028
4067
  ${h}
@@ -4069,19 +4108,19 @@ var q = {
4069
4108
  for (let e of n) {
4070
4109
  let t = r[e], n = this._getColWidth(t), o = t.pinned === "right" ? `position: absolute; top: 0; left: ${this._getPinnedRightLeft(e)}px; width: ${n}px; height: ${a}px; z-index: 2;` : `position: absolute; top: 0; left: ${s + this._getPinnedLeft(e)}px; width: ${n}px; height: ${a}px; z-index: 2;`;
4071
4110
  d.push(i`
4072
- <div class="ft-footer-cell ft-pinned" style=${o}>
4111
+ <div class="ft-footer-cell ft-pinned" role="gridcell" aria-colindex=${e + 1} style=${o}>
4073
4112
  ${this.footerData[t.key] ?? ""}</div>
4074
4113
  `);
4075
4114
  }
4076
4115
  for (let n = e; n < t; n++) {
4077
4116
  let e = r[n], t = this._getColWidth(e), o = this._colLeftOffsets[n] ?? 0, c = e.pinned === "left", l = e.pinned === "right", u = c || l, f;
4078
4117
  f = c ? `position: absolute; top: 0; left: ${s + this._getPinnedLeft(n)}px; width: ${t}px; height: ${a}px; z-index: 2;` : l ? `position: absolute; top: 0; right: ${-s + this._getPinnedRight(n)}px; width: ${t}px; height: ${a}px; z-index: 2;` : `left: ${o}px; width: ${t}px; height: ${a}px;`, d.push(i`
4079
- <div class="ft-footer-cell ${u ? "ft-pinned" : ""}" style=${f}>
4118
+ <div class="ft-footer-cell ${u ? "ft-pinned" : ""}" role="gridcell" aria-colindex=${n + 1} style=${f}>
4080
4119
  ${this.footerData[e.key] ?? ""}</div>
4081
4120
  `);
4082
4121
  }
4083
4122
  return i`
4084
- <div class="ft-footer" role="row" style="width: ${o}px; height: ${a}px;">
4123
+ <div class="ft-footer" role="row" aria-rowindex=${this._visibleRowCount + 2} style="width: ${o}px; height: ${a}px;">
4085
4124
  ${l}${u}
4086
4125
  ${d}
4087
4126
  </div>
@@ -4104,60 +4143,92 @@ var q = {
4104
4143
  @mousedown=${(t) => this._onRowNumMouseDown(t, e)}
4105
4144
  @click=${() => this._onRowNumberClick(e)}>${s + 1}</div>
4106
4145
  ` : "", y = [];
4107
- for (let t of r) y.push(this._renderCell(c, o[t], e, t));
4108
- for (let r = t; r < n; r++) y.push(this._renderCell(c, o[r], e, r));
4146
+ for (let t of r) y.push(this._renderCell(c, o[t], e, t, this._mergeState(o[t], e)));
4147
+ for (let r = t; r < n; r++) y.push(this._renderCell(c, o[r], e, r, this._mergeState(o[r], e)));
4109
4148
  return i`
4110
- <div class="ft-row ${f} ${p ? "ft-row-selected" : ""}" role="row"
4149
+ <div class="ft-row ${f} ${p ? "ft-row-selected" : ""}" role="row" aria-rowindex=${e + 2}
4111
4150
  style="top: ${l}px; height: ${u}px; width: ${d}px;">
4112
4151
  ${g}${v}
4113
4152
  ${y}
4114
4153
  </div>
4115
4154
  `;
4116
4155
  }
4117
- _renderCell(e, t, n, r) {
4118
- let o = this._activeCell?.row === n && this._activeCell?.col === r, s = this._editingCell?.row === n && this._editingCell?.col === r, c = this._selection.isInRange(n, r), l = t.pinned === "left", u = t.pinned === "right", d = l || u, f = this._getColWidth(t), p = this.rowHeight, m = this._colLeftOffsets[r] ?? 0, h;
4119
- h = l ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(r)}px; width: ${f}px; height: ${p}px; z-index: 2;` : u ? `position: absolute; top: 0; left: ${this._getPinnedRightLeft(r)}px; width: ${f}px; height: ${p}px; z-index: 2;` : `left: ${m}px; width: ${f}px; height: ${p}px;`;
4120
- let g = !this._isCellEditable(t);
4156
+ _continuesRun(e, t) {
4157
+ let n = e.mergeRepeated;
4158
+ if (!n || t <= 0 || t >= this._visibleRowCount) return !1;
4159
+ let r = this.data[this._toDataIndex(t)], i = this.data[this._toDataIndex(t - 1)];
4160
+ if (!r || !i) return !1;
4161
+ if (typeof n == "function") return n(r, i, e);
4162
+ let a = r[e.key];
4163
+ if (a == null || a === "") return !1;
4164
+ let o = i[e.key];
4165
+ return a instanceof Date && o instanceof Date ? a.getTime() === o.getTime() : Object.is(a, o);
4166
+ }
4167
+ _isForcedRunHead(e) {
4168
+ let t = this._frozenRowCount;
4169
+ return e === t ? !0 : e < t ? !1 : e === t + Math.floor((this._scrollTop + this.rowHeight / 2) / this.rowHeight);
4170
+ }
4171
+ _mergeState(e, t) {
4172
+ if (!e.mergeRepeated) return null;
4173
+ let n = !this._isForcedRunHead(t) && this._continuesRun(e, t), r = !this._isForcedRunHead(t + 1) && this._continuesRun(e, t + 1);
4174
+ if (!n && !r) return null;
4175
+ let i = t;
4176
+ for (; i > 0 && !this._isForcedRunHead(i) && this._continuesRun(e, i);) i--;
4177
+ return {
4178
+ continues: n,
4179
+ opensDown: r,
4180
+ headParity: i % 2 == 0 ? "even" : "odd"
4181
+ };
4182
+ }
4183
+ _renderCell(e, t, n, r, o = null) {
4184
+ let s = this._activeCell?.row === n && this._activeCell?.col === r, c = this._editingCell?.row === n && this._editingCell?.col === r, l = this._selection.isInRange(n, r), u = t.pinned === "left", d = t.pinned === "right", f = u || d, p = this._getColWidth(t), m = this.rowHeight, h = this._colLeftOffsets[r] ?? 0, g;
4185
+ g = u ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(r)}px; width: ${p}px; height: ${m}px; z-index: 2;` : d ? `position: absolute; top: 0; left: ${this._getPinnedRightLeft(r)}px; width: ${p}px; height: ${m}px; z-index: 2;` : `left: ${h}px; width: ${p}px; height: ${m}px;`;
4186
+ let _ = !this._isCellEditable(t);
4121
4187
  if (t.conditionalRules && t.conditionalRules.length > 0) {
4122
4188
  let n = e[t.key], r = {};
4123
4189
  for (let i of t.conditionalRules) i.when(n, e, t) && (i.style.background && (r.background = i.style.background), i.style.color && (r.color = i.style.color), i.style.fontWeight && (r["font-weight"] = i.style.fontWeight), i.style.fontStyle && (r["font-style"] = i.style.fontStyle));
4124
4190
  let i = Object.entries(r).map(([e, t]) => `${e}: ${t}`).join("; ");
4125
- i && (h += " " + i + ";");
4191
+ i && (g += " " + i + ";");
4126
4192
  }
4127
- if (s) return i`
4128
- <div class="ft-cell ft-editing ft-active ${d ? "ft-pinned" : ""}" role="gridcell"
4193
+ if (c) return i`
4194
+ <div class="ft-cell ft-editing ft-active ${f ? "ft-pinned" : ""}" role="gridcell"
4195
+ aria-colindex=${r + 1}
4129
4196
  data-col-index=${r}
4130
4197
  aria-selected="true"
4131
- aria-readonly=${g ? "true" : a}
4132
- style=${h}>
4198
+ aria-readonly=${_ ? "true" : a}
4199
+ style=${g}>
4133
4200
  ${this._renderEditor(e, t)}
4134
4201
  </div>
4135
4202
  `;
4136
- let _ = o || c, v = this._isCellInvalid(n, r), y = (this._findState?.results ?? []).findIndex((e) => e.row === n && e.col === r), x = y >= 0, S = x && y === this._findState.currentIndex, C = [
4203
+ let v = s || l, y = this._isCellInvalid(n, r), b = (this._findState?.results ?? []).findIndex((e) => e.row === n && e.col === r), S = b >= 0, C = S && b === this._findState.currentIndex, w = [
4137
4204
  "ft-cell",
4138
4205
  `ft-type-${t.type ?? "text"}`,
4139
4206
  `ft-align-${G(t)}`,
4140
- o ? "ft-active" : "",
4141
- c ? "ft-selected" : "",
4142
- d ? "ft-pinned" : "",
4143
- v ? "ft-invalid" : "",
4144
- S ? "ft-find-current" : x ? "ft-find-match" : ""
4145
- ].filter(Boolean).join(" "), w = this._toDataIndex(n), T = this._comments.get(w)?.get(t.key) ?? null, E = T !== null, D = E ? i`<div class="ft-comment-indicator" title=${T}></div>` : a;
4207
+ s ? "ft-active" : "",
4208
+ l ? "ft-selected" : "",
4209
+ f ? "ft-pinned" : "",
4210
+ y ? "ft-invalid" : "",
4211
+ C ? "ft-find-current" : S ? "ft-find-match" : "",
4212
+ o ? `ft-merge-${o.headParity}` : "",
4213
+ o?.continues ? "ft-merge-continued" : "",
4214
+ o?.opensDown ? "ft-merge-open" : ""
4215
+ ].filter(Boolean).join(" "), T = this._toDataIndex(n), E = this._comments.get(T)?.get(t.key) ?? null, D = E !== null, O = D ? i`<div class="ft-comment-indicator" title=${E}></div>` : a;
4146
4216
  return i`
4147
- <div class=${E ? C + " ft-has-comment" : C}
4217
+ <div class=${D ? w + " ft-has-comment" : w}
4148
4218
  role="gridcell"
4219
+ aria-colindex=${r + 1}
4149
4220
  data-col-index=${r}
4150
- aria-selected=${_ ? "true" : "false"}
4151
- aria-readonly=${g ? "true" : a}
4152
- aria-invalid=${v ? "true" : a}
4153
- title=${v ?? a}
4154
- style=${h}
4221
+ aria-selected=${v ? "true" : "false"}
4222
+ aria-readonly=${_ ? "true" : a}
4223
+ aria-invalid=${y ? "true" : a}
4224
+ title=${y ?? a}
4225
+ style=${g}
4155
4226
  @mousedown=${(e) => this._onCellMouseDown(e, n, r)}
4156
4227
  @mouseenter=${() => this._onCellMouseEnter(n, r)}
4157
4228
  @click=${(e) => this._onCellClickEvent(e, n, r)}
4158
4229
  @dblclick=${() => this._onCellDblClick(n, r)}>
4159
- ${D}
4160
- ${b(e[t.key], e, t)}
4230
+ ${O}
4231
+ ${x(e[t.key], e, t)}
4161
4232
  </div>
4162
4233
  `;
4163
4234
  }
@@ -4165,8 +4236,8 @@ var q = {
4165
4236
  if (t.editor) return t.editor(e[t.key], e, t);
4166
4237
  let n = e[t.key], r = n == null ? "" : String(n);
4167
4238
  if (t.type === "number") return i`
4168
- <input class="ft-editor ft-editor-number" type="number"
4169
- .value=${r}
4239
+ <input class="ft-editor ft-editor-number" type="text" inputmode="decimal"
4240
+ .value=${typeof n == "number" ? N(n) : r}
4170
4241
  @keydown=${this._onEditorKeyDown}
4171
4242
  @blur=${() => this._commitEdit()}>
4172
4243
  `;
@@ -4295,4 +4366,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4295
4366
  attribute: "max-undo-size"
4296
4367
  })], $.prototype, "maxUndoSize", null), K([c()], $.prototype, "_scrollTop", void 0), K([c()], $.prototype, "_scrollLeft", void 0), K([c()], $.prototype, "_viewportHeight", void 0), K([c()], $.prototype, "_viewportWidth", void 0), K([c()], $.prototype, "_activeCell", void 0), K([c()], $.prototype, "_editingCell", void 0), K([c()], $.prototype, "_sortCriteria", void 0), K([c()], $.prototype, "_openFilterKey", void 0), K([c()], $.prototype, "_rowSelectionVersion", void 0), K([c()], $.prototype, "_autocompleteState", void 0), K([c()], $.prototype, "_headerMenu", void 0), K([c()], $.prototype, "_bodyContextMenu", void 0), K([c()], $.prototype, "_commentPopup", void 0), K([c()], $.prototype, "_isDragOver", void 0), $ = K([o("flex-table")], $);
4297
4368
  //#endregion
4298
- export { k as a, A as i, G as n, D as o, B as r, b as s, $ as t };
4369
+ export { A as a, j as i, G as n, O as o, B as r, x as s, $ as t };