@iyulab/flex-table 0.41.0 → 0.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.41.1] - 2026-10-03
4
+
5
+ ### Fixed
6
+
7
+ - **The `date` cell editor shows and takes `YYYY-MM-DD` in every browser language.** It was the native
8
+ date input, which shows the browser's UI language (`10/02/2026` in an English browser) whatever the
9
+ page's `Locale`. It is now a text box that also reads `2026/10/2`, `20261002`, `2026. 10. 2.` and
10
+ `10-02` (this year), stores the ISO date string as before, and rejects text that is not a date with
11
+ `validation-error` ("Enter a date as YYYY-MM-DD", new `flexTableLocale` key `notADate`).
12
+ - **The editor no longer shifts a date string by a day.** It read `'2026-10-02'` with `new Date()`
13
+ (UTC midnight), which is the previous day west of UTC.
14
+ - **Pasting `2026/10/2` into a date column stores `2026-10-02`.** Text that is not a date still stays text.
15
+
16
+ ### Changed
17
+
18
+ - **The `@iyulab/components` peer is `>=1.55.0`** — dates are read with its `parseDate`.
19
+
3
20
  ## [0.41.0] - 2026-10-03
4
21
 
5
22
  ### Added
package/README.md CHANGED
@@ -160,6 +160,8 @@ The `validator` callback returns `null` if valid, or an error message string. On
160
160
 
161
161
  A `number` column's built-in editor reads numbers the way people type them in the active `Locale` — `1,5` on a comma-decimal page is 1.5, `1.234,5` is 1234.5 — and shows the value with that locale's decimal separator. Text that is not a number is rejected the same way as a validator failure (`error` is the localized "Enter a number"). The number filter's conditions and pasted values are read the same way; pasted text that is not a number stays text.
162
162
 
163
+ A `date` column's built-in editor is a text box that shows and takes `YYYY-MM-DD` in every browser language (the native date input would show the browser's UI language, e.g. `10/02/2026`). It also reads `2026/10/2`, `20261002` and `10-02` (this year), stores the ISO date string, and rejects text that is not a date (`error` is the localized "Enter a date as YYYY-MM-DD"). Pasted dates are read the same way.
164
+
163
165
  ### `format` vs `render`
164
166
 
165
167
  Both control how a cell's raw value is displayed, but they differ in what they replace:
@@ -11,3 +11,9 @@ export declare function parseValueForColumn(raw: string, col: ColumnDefinition):
11
11
  * kept (`1234.5` → `1234,5` on a German page). The inverse is {@link parseValueForColumn}.
12
12
  */
13
13
  export declare function editableNumber(value: number): string;
14
+ /**
15
+ * A `date` cell's value as `YYYY-MM-DD` for editing — the form the editor reads back. A date string
16
+ * keeps its own calendar day (`new Date('2026-10-02')` would be UTC midnight, the day before in
17
+ * negative offsets); a `Date` uses its local day. Anything else is shown as it is.
18
+ */
19
+ export declare function editableDate(value: unknown): string;
@@ -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, 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";
5
+ import { dateTextPattern as u, formatDate as d, formatNumber as f, parseDate as p, parseNumber as m } from "@iyulab/components/dist/utilities/format.js";
6
+ import { decodeTsv as h, encodeTsv as g } from "@iyulab/components/dist/utilities/tsv.js";
7
+ import { isImeComposing as _ } from "@iyulab/components/dist/utilities/keyboard.js";
8
8
  //#region src/styles/flex-table.styles.ts
9
- var g = r`
9
+ var v = r`
10
10
  /* --- Theme Variables (Light defaults) --- */
11
11
  :host {
12
12
  --ft-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -921,13 +921,13 @@ var g = r`
921
921
  `;
922
922
  //#endregion
923
923
  //#region src/renderers/format.ts
924
- function _(e, t) {
925
- return e == null ? "" : typeof t == "function" ? t(e) : v(t) ? b(e, t) : y(e, t);
924
+ function y(e, t) {
925
+ return e == null ? "" : typeof t == "function" ? t(e) : b(t) ? S(e, t) : x(e, t);
926
926
  }
927
- function v(e) {
927
+ function b(e) {
928
928
  return /[yMdHhms]/.test(e);
929
929
  }
930
- function y(e, t) {
930
+ function x(e, t) {
931
931
  let n = typeof e == "number" ? e : Number(e);
932
932
  if (isNaN(n)) return String(e);
933
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 = {
@@ -940,7 +940,7 @@ function y(e, t) {
940
940
  style: "percent"
941
941
  }).format(n) : (d = new Intl.NumberFormat(l.get(), u).format(n), a && (d = a + d)), d + "";
942
942
  }
943
- function b(e, t) {
943
+ function S(e, t) {
944
944
  let n;
945
945
  if (e instanceof Date) n = e;
946
946
  else if (typeof e == "string" || typeof e == "number") n = new Date(e);
@@ -951,26 +951,26 @@ function b(e, t) {
951
951
  }
952
952
  //#endregion
953
953
  //#region src/renderers/cell-renderer.ts
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);
954
+ function C(e, t, n) {
955
+ return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : y(e, n.format) : w(e, n);
956
956
  }
957
- function S(e, t) {
957
+ function w(e, t) {
958
958
  if (e == null) return "";
959
959
  switch (t.type) {
960
- case "number": return T(e);
960
+ case "number": return D(e);
961
961
  case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
962
- case "date": return E(e);
963
- case "datetime": return D(e);
964
- case "select": return C(e, t);
962
+ case "date": return O(e);
963
+ case "datetime": return ee(e);
964
+ case "select": return T(e, t);
965
965
  default: return String(e);
966
966
  }
967
967
  }
968
- function C(e, t) {
968
+ function T(e, t) {
969
969
  if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
970
970
  let n = t.options.find((t) => t.value === e);
971
971
  return n ? n.label : e == null ? "" : String(e);
972
972
  }
973
- var w = {
973
+ var E = {
974
974
  year: "numeric",
975
975
  month: "numeric",
976
976
  day: "numeric",
@@ -978,19 +978,19 @@ var w = {
978
978
  minute: "numeric",
979
979
  second: "numeric"
980
980
  };
981
- function T(e) {
982
- return typeof e == "number" ? Number.isInteger(e) ? d(e) : d(e, { minimumFractionDigits: 1 }) : String(e);
981
+ function D(e) {
982
+ return typeof e == "number" ? Number.isInteger(e) ? f(e) : f(e, { minimumFractionDigits: 1 }) : String(e);
983
983
  }
984
- function E(e) {
985
- return e instanceof Date || typeof e == "string" ? u(e) : String(e);
984
+ function O(e) {
985
+ return e instanceof Date || typeof e == "string" ? d(e) : String(e);
986
986
  }
987
- function D(e) {
988
- return e instanceof Date || typeof e == "string" ? u(e, w) : String(e);
987
+ function ee(e) {
988
+ return e instanceof Date || typeof e == "string" ? d(e, E) : String(e);
989
989
  }
990
990
  //#endregion
991
991
  //#region src/locale.ts
992
- var O = l.namespace("flex-table");
993
- O.register("en", {
992
+ var k = l.namespace("flex-table");
993
+ k.register("en", {
994
994
  showHiddenColumns: "Show hidden column(s)",
995
995
  columnMenu: "Column menu",
996
996
  cellActions: "Cell actions",
@@ -1044,8 +1044,9 @@ O.register("en", {
1044
1044
  booleanFalse: "False",
1045
1045
  dropFileToImport: "Drop file to import (.xlsx / .csv)",
1046
1046
  notANumber: "Enter a number",
1047
+ notADate: "Enter a date as YYYY-MM-DD",
1047
1048
  notInList: "Value must be from the existing list"
1048
- }), O.register("ko", {
1049
+ }), k.register("ko", {
1049
1050
  showHiddenColumns: "숨긴 열 보기",
1050
1051
  columnMenu: "열 메뉴",
1051
1052
  cellActions: "셀 작업",
@@ -1099,12 +1100,13 @@ O.register("en", {
1099
1100
  booleanFalse: "거짓",
1100
1101
  dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)",
1101
1102
  notANumber: "숫자를 입력하세요",
1103
+ notADate: "날짜를 YYYY-MM-DD 로 입력하세요",
1102
1104
  notInList: "목록에 있는 값이어야 합니다"
1103
1105
  });
1104
- var k = (e, t) => O.text(e, t);
1106
+ var A = (e, t) => k.text(e, t);
1105
1107
  //#endregion
1106
1108
  //#region src/core/selection.ts
1107
- function ee(e) {
1109
+ function te(e) {
1108
1110
  return {
1109
1111
  startRow: Math.min(e.startRow, e.endRow),
1110
1112
  startCol: Math.min(e.startCol, e.endCol),
@@ -1112,7 +1114,7 @@ function ee(e) {
1112
1114
  endCol: Math.max(e.startCol, e.endCol)
1113
1115
  };
1114
1116
  }
1115
- var te = class {
1117
+ var ne = class {
1116
1118
  constructor() {
1117
1119
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
1118
1120
  }
@@ -1139,7 +1141,7 @@ var te = class {
1139
1141
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
1140
1142
  row: e,
1141
1143
  col: t
1142
- }, this.rangeAnchor && (this.range = ee({
1144
+ }, this.rangeAnchor && (this.range = te({
1143
1145
  startRow: this.rangeAnchor.row,
1144
1146
  startCol: this.rangeAnchor.col,
1145
1147
  endRow: e,
@@ -1210,7 +1212,7 @@ var te = class {
1210
1212
  shiftMoveRight() {
1211
1213
  return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
1212
1214
  }
1213
- }, ne = class {
1215
+ }, re = class {
1214
1216
  constructor() {
1215
1217
  this.current = null;
1216
1218
  }
@@ -1231,7 +1233,7 @@ var te = class {
1231
1233
  let e = this.current;
1232
1234
  return this.current = null, e;
1233
1235
  }
1234
- }, A = class {
1236
+ }, j = class {
1235
1237
  constructor() {
1236
1238
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
1237
1239
  }
@@ -1292,7 +1294,7 @@ var te = class {
1292
1294
  };
1293
1295
  //#endregion
1294
1296
  //#region src/core/filtering.ts
1295
- function re(e, t, n) {
1297
+ function ie(e, t, n) {
1296
1298
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
1297
1299
  let r = [];
1298
1300
  for (let i = 0; i < e.length; i++) {
@@ -1311,9 +1313,9 @@ function re(e, t, n) {
1311
1313
  }
1312
1314
  //#endregion
1313
1315
  //#region src/core/undo.ts
1314
- var ie = 100, j = class {
1316
+ var ae = 100, M = class {
1315
1317
  constructor() {
1316
- this._undoStack = [], this._redoStack = [], this._maxSize = ie;
1318
+ this._undoStack = [], this._redoStack = [], this._maxSize = ae;
1317
1319
  }
1318
1320
  get maxSize() {
1319
1321
  return this._maxSize;
@@ -1350,7 +1352,7 @@ var ie = 100, j = class {
1350
1352
  };
1351
1353
  //#endregion
1352
1354
  //#region src/clipboard/clipboard.ts
1353
- function ae(e, t, n) {
1355
+ function oe(e, t, n) {
1354
1356
  let r = [];
1355
1357
  for (let i = n.startRow; i <= n.endRow; i++) {
1356
1358
  let a = e[i], o = [];
@@ -1360,30 +1362,37 @@ function ae(e, t, n) {
1360
1362
  }
1361
1363
  r.push(o);
1362
1364
  }
1363
- return m(r);
1365
+ return g(r);
1364
1366
  }
1365
- function M(e, t) {
1367
+ function N(e, t) {
1366
1368
  if (e === "") return null;
1367
1369
  switch (t.type) {
1368
1370
  case "number": {
1369
- let t = f(e);
1371
+ let t = m(e);
1370
1372
  if (t !== null) return t;
1371
1373
  let n = Number(e.trim());
1372
1374
  return e.trim() !== "" && Number.isFinite(n) ? n : e;
1373
1375
  }
1374
1376
  case "boolean": return e.toLowerCase() === "true" || e === "1";
1377
+ case "date": return p(e) ?? e;
1375
1378
  default: return e;
1376
1379
  }
1377
1380
  }
1378
- function N(e) {
1381
+ function P(e) {
1379
1382
  let t = String(e);
1380
1383
  if (!Number.isFinite(e) || t.includes("e")) return t;
1381
1384
  let n = new Intl.NumberFormat(l.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
1382
1385
  return n && n !== "." ? t.replace(".", n) : t;
1383
1386
  }
1387
+ function se(e) {
1388
+ if (e == null || e === "") return "";
1389
+ if (e instanceof Date) return Number.isNaN(e.getTime()) ? "" : `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
1390
+ let t = String(e), n = /^(\d{4}-\d{2}-\d{2})(?:$|T)/.exec(t);
1391
+ return n ? n[1] : t;
1392
+ }
1384
1393
  //#endregion
1385
1394
  //#region src/export/xlsx-writer.ts
1386
- var oe = (() => {
1395
+ var ce = (() => {
1387
1396
  let e = /* @__PURE__ */ new Uint32Array(256);
1388
1397
  for (let t = 0; t < 256; t++) {
1389
1398
  let n = t;
@@ -1392,56 +1401,56 @@ var oe = (() => {
1392
1401
  }
1393
1402
  return e;
1394
1403
  })();
1395
- function se(e) {
1404
+ function le(e) {
1396
1405
  let t = 4294967295;
1397
- for (let n = 0; n < e.length; n++) t = oe[(t ^ e[n]) & 255] ^ t >>> 8;
1406
+ for (let n = 0; n < e.length; n++) t = ce[(t ^ e[n]) & 255] ^ t >>> 8;
1398
1407
  return (t ^ 4294967295) >>> 0;
1399
1408
  }
1400
- var P = new TextEncoder();
1401
- function ce(e) {
1409
+ var F = new TextEncoder();
1410
+ function ue(e) {
1402
1411
  let t = [], n = [], r = 0;
1403
1412
  for (let i of e) {
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);
1413
+ let e = F.encode(i.name), a = le(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1405
1414
  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);
1406
1415
  let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
1407
1416
  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;
1408
1417
  }
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([
1418
+ let i = I(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1419
+ 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), I([
1411
1420
  ...t,
1412
1421
  i,
1413
1422
  new Uint8Array(a)
1414
1423
  ]);
1415
1424
  }
1416
- function F(e) {
1425
+ function I(e) {
1417
1426
  let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
1418
1427
  for (let t of e) n.set(t, r), r += t.length;
1419
1428
  return n;
1420
1429
  }
1421
- function I(e) {
1430
+ function L(e) {
1422
1431
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1423
1432
  }
1424
- function le(e) {
1433
+ function de(e) {
1425
1434
  let t = "";
1426
1435
  for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1427
1436
  return t;
1428
1437
  }
1429
- function L(e, t) {
1430
- return le(t) + (e + 1);
1438
+ function R(e, t) {
1439
+ return de(t) + (e + 1);
1431
1440
  }
1432
- function ue(e) {
1441
+ function fe(e) {
1433
1442
  let t = Date.UTC(1899, 11, 30);
1434
1443
  return (e.getTime() - t) / 864e5;
1435
1444
  }
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>`);
1445
+ var pe = "<?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>", 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/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", z = "<?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>", he = "<?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>", ge = "<?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>";
1446
+ function _e(e, t) {
1447
+ let n = [], r = t.map((e, t) => `<c r="${R(0, t)}" t="str" s="2"><v>${L(e.label)}</v></c>`);
1439
1448
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1440
1449
  let i = t.map((t, n) => {
1441
- let i = L(r + 1, n), a = e[t.key];
1450
+ let i = R(r + 1, n), a = e[t.key];
1442
1451
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1443
1452
  let o = t.type ?? "text";
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>`;
1453
+ 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>${fe(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${L(String(a))}</v></c>`;
1445
1454
  });
1446
1455
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1447
1456
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -1449,32 +1458,32 @@ function z(e, t) {
1449
1458
  <sheetData>${n.join("")}</sheetData>
1450
1459
  </worksheet>`;
1451
1460
  }
1452
- function he(e, t) {
1453
- let n = z(e, t);
1454
- return ce([
1461
+ function ve(e, t) {
1462
+ let n = _e(e, t);
1463
+ return ue([
1455
1464
  {
1456
1465
  name: "[Content_Types].xml",
1457
- data: P.encode(de)
1466
+ data: F.encode(pe)
1458
1467
  },
1459
1468
  {
1460
1469
  name: "_rels/.rels",
1461
- data: P.encode(fe)
1470
+ data: F.encode(me)
1462
1471
  },
1463
1472
  {
1464
1473
  name: "xl/workbook.xml",
1465
- data: P.encode(pe)
1474
+ data: F.encode(z)
1466
1475
  },
1467
1476
  {
1468
1477
  name: "xl/_rels/workbook.xml.rels",
1469
- data: P.encode(me)
1478
+ data: F.encode(he)
1470
1479
  },
1471
1480
  {
1472
1481
  name: "xl/worksheets/sheet1.xml",
1473
- data: P.encode(n)
1482
+ data: F.encode(n)
1474
1483
  },
1475
1484
  {
1476
1485
  name: "xl/styles.xml",
1477
- data: P.encode(R)
1486
+ data: F.encode(ge)
1478
1487
  }
1479
1488
  ]);
1480
1489
  }
@@ -1484,20 +1493,20 @@ function B(e, t, n) {
1484
1493
  switch (n) {
1485
1494
  case "csv": return V(e, t, ",");
1486
1495
  case "tsv": return V(e, t, " ");
1487
- case "json": return _e(e, t);
1488
- case "xlsx": return he(e, t);
1496
+ case "json": return be(e, t);
1497
+ case "xlsx": return ve(e, t);
1489
1498
  }
1490
1499
  }
1491
- function ge(e, t) {
1500
+ function ye(e, t) {
1492
1501
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
1493
1502
  }
1494
1503
  function V(e, t, 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");
1504
+ return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(ye(e[t.key], t), n)).join(n))].join("\n");
1496
1505
  }
1497
1506
  function H(e, t) {
1498
1507
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
1499
1508
  }
1500
- function _e(e, t) {
1509
+ function be(e, t) {
1501
1510
  let n = e.map((e) => {
1502
1511
  let n = {};
1503
1512
  for (let r of t) {
@@ -1508,35 +1517,35 @@ function _e(e, t) {
1508
1517
  });
1509
1518
  return JSON.stringify(n, null, 2);
1510
1519
  }
1511
- function ve(e, t, n) {
1520
+ function xe(e, t, n) {
1512
1521
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
1513
1522
  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);
1514
1523
  }
1515
- var ye = {
1524
+ var Se = {
1516
1525
  csv: "text/csv;charset=utf-8",
1517
1526
  tsv: "text/tab-separated-values;charset=utf-8",
1518
1527
  json: "application/json;charset=utf-8",
1519
1528
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1520
- }, be = {
1529
+ }, Ce = {
1521
1530
  csv: ".csv",
1522
1531
  tsv: ".tsv",
1523
1532
  json: ".json",
1524
1533
  xlsx: ".xlsx"
1525
1534
  };
1526
- function xe(e) {
1527
- return ye[e];
1535
+ function we(e) {
1536
+ return Se[e];
1528
1537
  }
1529
- function Se(e) {
1530
- return be[e];
1538
+ function Te(e) {
1539
+ return Ce[e];
1531
1540
  }
1532
1541
  //#endregion
1533
1542
  //#region src/export/xlsx-reader.ts
1534
- function Ce(e) {
1543
+ function Ee(e) {
1535
1544
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
1536
1545
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
1537
1546
  }
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;
1547
+ function De(e) {
1548
+ let t = Ee(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
1540
1549
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
1541
1550
  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));
1542
1551
  a.push({
@@ -1549,7 +1558,7 @@ function we(e) {
1549
1558
  }
1550
1559
  return a;
1551
1560
  }
1552
- async function Te(e) {
1561
+ async function Oe(e) {
1553
1562
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
1554
1563
  n.write(e), n.close();
1555
1564
  let i = [];
@@ -1562,28 +1571,28 @@ async function Te(e) {
1562
1571
  for (let e of i) o.set(e, s), s += e.length;
1563
1572
  return o;
1564
1573
  }
1565
- async function Ee(e, t) {
1574
+ async function ke(e, t) {
1566
1575
  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);
1567
1576
  if (t.compressionMethod === 0) return o.slice();
1568
- if (t.compressionMethod === 8) return Te(o);
1577
+ if (t.compressionMethod === 8) return Oe(o);
1569
1578
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
1570
1579
  }
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));
1580
+ async function Ae(e) {
1581
+ let t = new DataView(e), n = De(t), r = /* @__PURE__ */ new Map();
1582
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await ke(t, e));
1574
1583
  return r;
1575
1584
  }
1576
- var Oe = new TextDecoder("utf-8");
1585
+ var je = new TextDecoder("utf-8");
1577
1586
  function U(e) {
1578
- let t = Oe.decode(e);
1587
+ let t = je.decode(e);
1579
1588
  return new DOMParser().parseFromString(t, "application/xml");
1580
1589
  }
1581
- function ke(e) {
1590
+ function Me(e) {
1582
1591
  if (!e) return [];
1583
1592
  let t = U(e);
1584
1593
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
1585
1594
  }
1586
- var Ae = /* @__PURE__ */ new Set([
1595
+ var Ne = /* @__PURE__ */ new Set([
1587
1596
  14,
1588
1597
  15,
1589
1598
  16,
@@ -1603,29 +1612,29 @@ var Ae = /* @__PURE__ */ new Set([
1603
1612
  57,
1604
1613
  58
1605
1614
  ]);
1606
- function je(e) {
1615
+ function Pe(e) {
1607
1616
  let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
1608
1617
  return /[dy]/i.test(t);
1609
1618
  }
1610
- function Me(e) {
1619
+ function Fe(e) {
1611
1620
  let t = /* @__PURE__ */ new Set();
1612
1621
  if (!e) return t;
1613
1622
  let n = U(e), r = /* @__PURE__ */ new Map();
1614
1623
  for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
1615
1624
  return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
1616
1625
  let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
1617
- (a === void 0 ? Ae.has(i) : je(a)) && t.add(n);
1626
+ (a === void 0 ? Ne.has(i) : Pe(a)) && t.add(n);
1618
1627
  }), t;
1619
1628
  }
1620
- function Ne(e) {
1629
+ function Ie(e) {
1621
1630
  if (!e) return !1;
1622
1631
  let t = U(e).querySelector("workbookPr")?.getAttribute("date1904");
1623
1632
  return t === "1" || t === "true";
1624
1633
  }
1625
- function Pe(e, t) {
1634
+ function W(e, t) {
1626
1635
  return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
1627
1636
  }
1628
- function Fe(e, t, n, r) {
1637
+ function Le(e, t, n, r) {
1629
1638
  let i = U(e).querySelectorAll("row");
1630
1639
  if (i.length === 0) return [];
1631
1640
  let a = 0, o = /* @__PURE__ */ new Map();
@@ -1633,7 +1642,7 @@ function Fe(e, t, n, r) {
1633
1642
  let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
1634
1643
  o.set(i, s);
1635
1644
  for (let i of e.querySelectorAll("c")) {
1636
- let e = Ie(i.getAttribute("r") ?? "");
1645
+ let e = Re(i.getAttribute("r") ?? "");
1637
1646
  e > a && (a = e);
1638
1647
  let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
1639
1648
  if (o === "s") d = t[parseInt(l, 10)] ?? "";
@@ -1642,7 +1651,7 @@ function Fe(e, t, n, r) {
1642
1651
  else if (l === "") d = "";
1643
1652
  else {
1644
1653
  let e = parseFloat(l);
1645
- d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Pe(e, r) : l;
1654
+ d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? W(e, r) : l;
1646
1655
  }
1647
1656
  s.set(e, d);
1648
1657
  }
@@ -1656,13 +1665,13 @@ function Fe(e, t, n, r) {
1656
1665
  }
1657
1666
  return c;
1658
1667
  }
1659
- function Ie(e) {
1668
+ function Re(e) {
1660
1669
  let t = 0, n = 0;
1661
1670
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
1662
1671
  return t - 1;
1663
1672
  }
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");
1673
+ async function ze(e) {
1674
+ let t = await Ae(e), n = Me(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1666
1675
  if (!r) {
1667
1676
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
1668
1677
  r = n;
@@ -1670,7 +1679,7 @@ async function W(e) {
1670
1679
  }
1671
1680
  }
1672
1681
  if (!r) throw Error("XLSX: No worksheet found");
1673
- let i = Me(t.get("xl/styles.xml")), a = Ne(t.get("xl/workbook.xml")), o = Fe(r, n, i, a);
1682
+ let i = Fe(t.get("xl/styles.xml")), a = Ie(t.get("xl/workbook.xml")), o = Le(r, n, i, a);
1674
1683
  return o.length === 0 ? {
1675
1684
  headers: [],
1676
1685
  rows: []
@@ -1701,14 +1710,14 @@ var q = {
1701
1710
  lt: "<",
1702
1711
  gte: "≥",
1703
1712
  lte: "≤"
1704
- }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Le = 200, $ = class extends n {
1713
+ }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Be = 200, $ = class extends n {
1705
1714
  constructor(...e) {
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 = () => {
1715
+ 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 ne(), this._editing = new re(), this._rowSelection = new j(), this._undo = new M(), 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 = () => {
1707
1716
  this._commitCommentPopup();
1708
1717
  }, 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();
1709
1718
  }
1710
1719
  static {
1711
- this.styles = g;
1720
+ this.styles = v;
1712
1721
  }
1713
1722
  get data() {
1714
1723
  return this._data;
@@ -2073,7 +2082,7 @@ var q = {
2073
2082
  return B(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2074
2083
  }
2075
2084
  exportToFile(e, t) {
2076
- ve(this.exportToString(e), t ?? `export${Se(e)}`, xe(e));
2085
+ xe(this.exportToString(e), t ?? `export${Te(e)}`, we(e));
2077
2086
  }
2078
2087
  setComment(e, t, n) {
2079
2088
  let r = this.getComment(e, t);
@@ -2130,10 +2139,10 @@ var q = {
2130
2139
  async importFromFile(e) {
2131
2140
  let t = e.name.toLowerCase();
2132
2141
  if (t.endsWith(".xlsx")) {
2133
- let t = await W(await e.arrayBuffer());
2142
+ let t = await ze(await e.arrayBuffer());
2134
2143
  this._applyImportedSheet(t);
2135
2144
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
2136
- let t = await e.text(), n = p(t);
2145
+ let t = await e.text(), n = h(t);
2137
2146
  this._applyImportedRows(n);
2138
2147
  } else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
2139
2148
  }
@@ -2144,7 +2153,7 @@ var q = {
2144
2153
  let a = t.get(e);
2145
2154
  if (!a) return;
2146
2155
  let o = this.columns.find((e) => e.key === a);
2147
- r[a] = o ? M(n[i] ?? "", o) : n[i] ?? null;
2156
+ r[a] = o ? N(n[i] ?? "", o) : n[i] ?? null;
2148
2157
  }), r;
2149
2158
  }), r = [...this.data];
2150
2159
  this.data = n, this._undo.push({
@@ -2169,7 +2178,7 @@ var q = {
2169
2178
  let a = n.get(t);
2170
2179
  if (!a) return;
2171
2180
  let o = this.columns.find((e) => e.key === a);
2172
- r[a] = o ? M(e[i] ?? "", o) : e[i] ?? null;
2181
+ r[a] = o ? N(e[i] ?? "", o) : e[i] ?? null;
2173
2182
  }), r;
2174
2183
  }), i = [...this.data];
2175
2184
  this.data = r, this._undo.push({
@@ -2323,7 +2332,7 @@ var q = {
2323
2332
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
2324
2333
  return;
2325
2334
  }
2326
- if (this._filteredIndices = re(this.data, this._filters, (e, t, n) => {
2335
+ if (this._filteredIndices = ie(this.data, this._filters, (e, t, n) => {
2327
2336
  this.dispatchEvent(new CustomEvent("filter-error", {
2328
2337
  detail: {
2329
2338
  error: e,
@@ -2353,7 +2362,7 @@ var q = {
2353
2362
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2354
2363
  }
2355
2364
  _warnIfUnconstrained() {
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.`));
2365
+ this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Be || 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.`));
2357
2366
  }
2358
2367
  _onScroll() {
2359
2368
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -2483,7 +2492,7 @@ var q = {
2483
2492
  }
2484
2493
  let t = this.shadowRoot?.querySelector(".ft-editor");
2485
2494
  if (t) {
2486
- let n = M(t.value, e);
2495
+ let n = N(t.value, e);
2487
2496
  this._applyEdit(n);
2488
2497
  } else this._cancelEdit();
2489
2498
  }
@@ -2493,7 +2502,7 @@ var q = {
2493
2502
  if (this._editingCell = null, !t) return;
2494
2503
  let { row: n, col: r } = t.position, i = this._toDataIndex(n), a = this.visibleColumns[r], o = t.originalValue;
2495
2504
  if (a.autocomplete === "strict" && e != null && e !== "" && !this._getAutocompleteCandidates(a, "").includes(String(e))) {
2496
- let t = k("notInList");
2505
+ let t = A("notInList");
2497
2506
  this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
2498
2507
  detail: {
2499
2508
  row: i,
@@ -2507,8 +2516,8 @@ var q = {
2507
2516
  }));
2508
2517
  return;
2509
2518
  }
2510
- if (a.type === "number" && typeof e == "string") {
2511
- let t = k("notANumber");
2519
+ if (a.type === "number" && typeof e == "string" || a.type === "date" && typeof e == "string" && p(e) === null) {
2520
+ let t = A(a.type === "number" ? "notANumber" : "notADate");
2512
2521
  this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
2513
2522
  detail: {
2514
2523
  row: i,
@@ -2572,7 +2581,7 @@ var q = {
2572
2581
  }));
2573
2582
  }
2574
2583
  _onEditorKeyDown(e) {
2575
- if (!h(e)) {
2584
+ if (!_(e)) {
2576
2585
  if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
2577
2586
  if (e.key === "ArrowDown") {
2578
2587
  e.preventDefault(), e.stopPropagation();
@@ -2640,7 +2649,7 @@ var q = {
2640
2649
  ].includes(t) && this._handleCtrlKey(e)) return;
2641
2650
  }
2642
2651
  if (t.length !== 0 && this._visibleRowCount !== 0) {
2643
- if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !h(e)) {
2652
+ if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !_(e)) {
2644
2653
  e.preventDefault();
2645
2654
  let n = t[this._activeCell.col];
2646
2655
  n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n);
@@ -2728,7 +2737,7 @@ var q = {
2728
2737
  async _handleCopy(e) {
2729
2738
  let t = this._selection.getEffectiveRange();
2730
2739
  if (!t) return;
2731
- let n = this.visibleColumns, r = ae(this._sortedIndices.map((e) => this.data[e]), n, t);
2740
+ let n = this.visibleColumns, r = oe(this._sortedIndices.map((e) => this.data[e]), n, t);
2732
2741
  try {
2733
2742
  await navigator.clipboard.writeText(r);
2734
2743
  } catch (e) {
@@ -2754,7 +2763,7 @@ var q = {
2754
2763
  if (!this._activeCell) return;
2755
2764
  let e = await this._readClipboardText();
2756
2765
  if (e == null) return;
2757
- let t = p(e);
2766
+ let t = h(e);
2758
2767
  if (t.length === 0) return;
2759
2768
  let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
2760
2769
  if (r.length > 0 || n.length > 0) {
@@ -2812,7 +2821,7 @@ var q = {
2812
2821
  for (let a = 0; a < t[i].length; a++) {
2813
2822
  let s = e.col + a;
2814
2823
  if (s >= n.length) break;
2815
- let c = n[s], l = this.data[o][c.key], u = M(t[i][a], c);
2824
+ let c = n[s], l = this.data[o][c.key], u = N(t[i][a], c);
2816
2825
  this.data[o][c.key] = u, r.push({
2817
2826
  row: o,
2818
2827
  col: s,
@@ -2877,7 +2886,7 @@ var q = {
2877
2886
  for (let r = e.startCol + 1; r <= e.endCol; r++) {
2878
2887
  let e = t[r];
2879
2888
  if (!e || !this._isCellEditable(e)) continue;
2880
- let a = M(o == null ? "" : String(o), e);
2889
+ let a = N(o == null ? "" : String(o), e);
2881
2890
  n.push({
2882
2891
  row: i,
2883
2892
  key: e.key,
@@ -3037,7 +3046,7 @@ var q = {
3037
3046
  @click=${n ? (t) => this._onHeaderClick(t, e) : void 0}>
3038
3047
  ${C ? i`
3039
3048
  <button class="ft-hidden-col-indicator"
3040
- title=${k("showHiddenColumns")}
3049
+ title=${A("showHiddenColumns")}
3041
3050
  @click=${(t) => {
3042
3051
  t.stopPropagation(), this._showHiddenBefore(e);
3043
3052
  }}>&#x276F;</button>
@@ -3047,8 +3056,8 @@ var q = {
3047
3056
  ${o >= 0 ? i`<span class="ft-sort-order">${o + 1}</span>` : ""}
3048
3057
  <button class="ft-column-menu-btn ${s ? "ft-filter-active" : ""}"
3049
3058
  type="button"
3050
- title=${k("columnMenu")}
3051
- aria-label=${k("columnMenuFor", { header: e.label })}
3059
+ title=${A("columnMenu")}
3060
+ aria-label=${A("columnMenuFor", { header: e.label })}
3052
3061
  aria-haspopup="menu"
3053
3062
  aria-expanded=${this._headerMenu?.key === e.key ? "true" : "false"}
3054
3063
  @mousedown=${(e) => e.stopPropagation()}
@@ -3167,26 +3176,26 @@ var q = {
3167
3176
  }}>${t}</button>
3168
3177
  `;
3169
3178
  return i`
3170
- <div class="ft-header-menu" role="menu" aria-label=${k("columnMenuRegion", { header: o.label })}
3179
+ <div class="ft-header-menu" role="menu" aria-label=${A("columnMenuRegion", { header: o.label })}
3171
3180
  style="position: fixed; left: ${t}px; top: ${n}px; z-index: var(--u-layer-floating, 1000);"
3172
3181
  @mousedown=${(e) => e.stopPropagation()}
3173
3182
  @keydown=${(e) => this._onHeaderMenuKeydown(e)}>
3174
3183
  ${o.sortable === !1 ? a : i`
3175
- ${c("sort-asc", k("sortAscending"), () => this._applySortFromMenu(e, "asc"))}
3176
- ${c("sort-desc", k("sortDescending"), () => this._applySortFromMenu(e, "desc"))}
3184
+ ${c("sort-asc", A("sortAscending"), () => this._applySortFromMenu(e, "asc"))}
3185
+ ${c("sort-desc", A("sortDescending"), () => this._applySortFromMenu(e, "desc"))}
3177
3186
  <div class="ft-header-menu-separator" role="separator"></div>
3178
3187
  `}
3179
3188
  ${this.showFilters ? i`
3180
- ${c("filter", k("filter"), () => this._openFilterFromMenu(e))}
3181
- ${s ? c("clear-filter", k("clearFilter"), () => this._clearColumnFilter(e)) : a}
3189
+ ${c("filter", A("filter"), () => this._openFilterFromMenu(e))}
3190
+ ${s ? c("clear-filter", A("clearFilter"), () => this._clearColumnFilter(e)) : a}
3182
3191
  <div class="ft-header-menu-separator" role="separator"></div>
3183
3192
  ` : a}
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)))}
3193
+ ${c("hide", A("hideColumn"), () => this._setColumnHidden(e, !0))}
3194
+ ${r.map((e) => c("show", A("showColumn", { header: e.label }), () => this._setColumnHidden(e.key, !1)))}
3186
3195
  <div class="ft-header-menu-separator" role="separator"></div>
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)}
3196
+ ${c("autofit", A("autoFitWidth"), () => this._autoFitColumn(e))}
3197
+ ${c("wider", A("wider"), () => this._resizeColumnBy(e, X), !0)}
3198
+ ${c("narrower", A("narrower"), () => this._resizeColumnBy(e, -20), !0)}
3190
3199
  </div>
3191
3200
  `;
3192
3201
  }
@@ -3204,26 +3213,26 @@ var q = {
3204
3213
  }}>${e}</button>
3205
3214
  `, f = i`<div class="ft-context-menu-separator" role="separator"></div>`;
3206
3215
  return i`
3207
- <div class="ft-body-context-menu" role="menu" aria-label=${k("cellActions")}
3216
+ <div class="ft-body-context-menu" role="menu" aria-label=${A("cellActions")}
3208
3217
  style="position: fixed; left: ${n}px; top: ${r}px; z-index: var(--u-layer-floating, 1000);"
3209
3218
  @mousedown=${(e) => e.stopPropagation()}
3210
3219
  @keydown=${(e) => this._onMenuKeydown(e, ".ft-body-context-menu", l)}>
3211
- ${d(k("copy"), () => this._handleCopy(!1))}
3220
+ ${d(A("copy"), () => this._handleCopy(!1))}
3212
3221
  ${f}
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)}
3222
+ ${d(A("insertRowAbove"), () => this.addRow(void 0, t))}
3223
+ ${d(A("insertRowBelow"), () => this.addRow(void 0, t + 1))}
3224
+ ${d(A("deleteRow"), () => this.deleteRows([t]), !0)}
3216
3225
  ${f}
3217
- ${d(k("hideColumn"), () => this._setColumnHidden(o.key, !0))}
3226
+ ${d(A("hideColumn"), () => this._setColumnHidden(o.key, !0))}
3218
3227
  ${f}
3219
- ${d(`${k("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
3220
- ${d(`${k("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
3228
+ ${d(`${A("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
3229
+ ${d(`${A("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
3221
3230
  ${f}
3222
- ${d(k("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
3223
- ${c ? d(k("clearFilter"), () => this.removeFilter(o.key)) : a}
3231
+ ${d(A("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
3232
+ ${c ? d(A("clearFilter"), () => this.removeFilter(o.key)) : a}
3224
3233
  ${f}
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}
3234
+ ${d(A(u ? "editComment" : "addComment"), () => this._openCommentPopup(t, o.key, n, r))}
3235
+ ${u ? d(A("deleteComment"), () => this.setComment(t, o.key, null), !0) : a}
3227
3236
  </div>
3228
3237
  `;
3229
3238
  }
@@ -3255,13 +3264,13 @@ var q = {
3255
3264
  @mousedown=${(e) => e.stopPropagation()}>
3256
3265
  <textarea class="ft-comment-popup-textarea"
3257
3266
  rows="4"
3258
- placeholder=${k("addCommentPlaceholder")}
3267
+ placeholder=${A("addCommentPlaceholder")}
3259
3268
  @keydown=${(e) => {
3260
3269
  e.key === "Escape" && (e.preventDefault(), this._cancelCommentPopup()), e.key === "Enter" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this._commitCommentPopup());
3261
3270
  }}></textarea>
3262
3271
  <div class="ft-comment-popup-buttons">
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>
3272
+ <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${A("cancel")}</button>
3273
+ <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${A("save")}</button>
3265
3274
  </div>
3266
3275
  </div>
3267
3276
  `;
@@ -3297,7 +3306,7 @@ var q = {
3297
3306
  <div class="ft-filter-dropdown" @click=${(e) => e.stopPropagation()}>
3298
3307
  ${t === "boolean" ? this._renderBooleanFilter(e) : t === "number" ? this._renderNumberFilter(e) : t === "date" || t === "datetime" ? this._renderDateFilter(e) : this._renderTextFilter(e)}
3299
3308
  <div class="ft-filter-actions">
3300
- <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${k("clear")}</button>
3309
+ <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${A("clear")}</button>
3301
3310
  </div>
3302
3311
  </div>
3303
3312
  `;
@@ -3330,7 +3339,7 @@ var q = {
3330
3339
  let n = this._emptyFilterState.get(e) ?? "";
3331
3340
  return i`
3332
3341
  <div class="ft-filter-empty-row">
3333
- <label>${k("blankCells")}</label>
3342
+ <label>${A("blankCells")}</label>
3334
3343
  <select class="ft-filter-mode-select"
3335
3344
  .value=${n}
3336
3345
  @change=${(n) => {
@@ -3340,9 +3349,9 @@ var q = {
3340
3349
  @keydown=${(e) => {
3341
3350
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3342
3351
  }}>
3343
- <option value="">${k("blankAll")}</option>
3344
- <option value="empty">${k("emptyOnly")}</option>
3345
- <option value="non-empty">${k("nonEmptyOnly")}</option>
3352
+ <option value="">${A("blankAll")}</option>
3353
+ <option value="empty">${A("emptyOnly")}</option>
3354
+ <option value="non-empty">${A("nonEmptyOnly")}</option>
3346
3355
  </select>
3347
3356
  </div>
3348
3357
  `;
@@ -3418,13 +3427,13 @@ var q = {
3418
3427
  @keydown=${(e) => {
3419
3428
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3420
3429
  }}>
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>
3430
+ <option value="contains">${A("contains")}</option>
3431
+ <option value="starts">${A("startsWith")}</option>
3432
+ <option value="ends">${A("endsWith")}</option>
3433
+ <option value="wildcard">${A("wildcard")}</option>
3425
3434
  </select>
3426
3435
  </div>
3427
- <input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")}
3436
+ <input class="ft-filter-input" type="text" placeholder=${A("searchPlaceholder")}
3428
3437
  .value=${t.value}
3429
3438
  @input=${(t) => {
3430
3439
  let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
@@ -3475,15 +3484,15 @@ var q = {
3475
3484
  }}>
3476
3485
  ${Object.keys(q).map((e) => i`<option value=${e}>${q[e]}</option>`)}
3477
3486
  </select>
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))}
3487
+ <input class="ft-filter-input ft-num-cond-input" type="text" inputmode="decimal" placeholder=${A("valuePlaceholder")}
3488
+ .value=${n.text ?? (n.value == null ? "" : P(n.value))}
3480
3489
  aria-invalid=${n.text && n.value == null ? "true" : "false"}
3481
3490
  @input=${(n) => {
3482
3491
  let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
3483
3492
  i[t] = {
3484
3493
  ...i[t],
3485
3494
  text: r,
3486
- value: r.trim() === "" ? null : f(r)
3495
+ value: r.trim() === "" ? null : m(r)
3487
3496
  }, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
3488
3497
  }}
3489
3498
  @keydown=${(e) => {
@@ -3538,13 +3547,13 @@ var q = {
3538
3547
  let t = e.type === "datetime" ? "datetime-local" : "date", n = this._dateFilterState.get(e.key) ?? {};
3539
3548
  return i`
3540
3549
  <div class="ft-filter-range">
3541
- <input class="ft-filter-input" type=${t} placeholder=${k("fromPlaceholder")}
3550
+ <input class="ft-filter-input" type=${t} placeholder=${A("fromPlaceholder")}
3542
3551
  .value=${n.from ?? ""}
3543
3552
  @input=${(t) => this._applyDateFilter(e.key, t, "from")}
3544
3553
  @keydown=${(e) => {
3545
3554
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3546
3555
  }}>
3547
- <input class="ft-filter-input" type=${t} placeholder=${k("toPlaceholder")}
3556
+ <input class="ft-filter-input" type=${t} placeholder=${A("toPlaceholder")}
3548
3557
  .value=${n.to ?? ""}
3549
3558
  @input=${(t) => this._applyDateFilter(e.key, t, "to")}
3550
3559
  @keydown=${(e) => {
@@ -3570,9 +3579,9 @@ var q = {
3570
3579
  @keydown=${(e) => {
3571
3580
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3572
3581
  }}>
3573
- <option value="all">${k("all")}</option>
3574
- <option value="true">\u2714 ${k("booleanTrue")}</option>
3575
- <option value="false">\u2718 ${k("booleanFalse")}</option>
3582
+ <option value="all">${A("all")}</option>
3583
+ <option value="true">\u2714 ${A("booleanTrue")}</option>
3584
+ <option value="false">\u2718 ${A("booleanFalse")}</option>
3576
3585
  </select>
3577
3586
  ${this._renderEmptyFilterRow(e.key)}
3578
3587
  `;
@@ -3989,42 +3998,42 @@ var q = {
3989
3998
  this._closeFindPanel();
3990
3999
  return;
3991
4000
  }
3992
- e.key === "Enter" && !h(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
4001
+ e.key === "Enter" && !_(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
3993
4002
  }}>
3994
4003
  <div class="ft-find-row">
3995
- <input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")}
4004
+ <input class="ft-find-input" type="text" placeholder=${A("findPlaceholder")}
3996
4005
  .value=${t}
3997
4006
  @input=${(e) => {
3998
4007
  this._findState.query = e.target.value, this._findSearch();
3999
4008
  }}>
4000
4009
  <span class="ft-find-count">${c > 0 ? `${l}/${c}` : t ? "0 results" : ""}</span>
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) => {
4010
+ <button @click=${() => this._findPrev()} title=${A("findPrevious")}>◀</button>
4011
+ <button @click=${() => this._findNext()} title=${A("findNext")}>▶</button>
4012
+ <label title=${A("matchCase")}><input type="checkbox" ?checked=${r} @change=${(e) => {
4004
4013
  this._findState.matchCase = e.target.checked, this._findSearch();
4005
4014
  }}> Aa</label>
4006
- <label title=${k("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
4015
+ <label title=${A("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
4007
4016
  this._findState.wholeCell = e.target.checked, this._findSearch();
4008
4017
  }}> [ ]</label>
4009
- <button @click=${() => this._closeFindPanel()} title=${k("closeFind")}>✕</button>
4018
+ <button @click=${() => this._closeFindPanel()} title=${A("closeFind")}>✕</button>
4010
4019
  </div>
4011
4020
  ${e === "replace" ? i`
4012
4021
  <div class="ft-find-row">
4013
- <input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")}
4022
+ <input class="ft-find-replace-input" type="text" placeholder=${A("replaceWithPlaceholder")}
4014
4023
  .value=${n}
4015
4024
  @input=${(e) => {
4016
4025
  this._findState.replaceWith = e.target.value;
4017
4026
  }}>
4018
- <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${k("replace")}</button>
4019
- <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${k("replaceAll")}</button>
4027
+ <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${A("replace")}</button>
4028
+ <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${A("replaceAll")}</button>
4020
4029
  </div>
4021
4030
  ` : ""}
4022
4031
  </div>
4023
4032
  `;
4024
4033
  }
4025
4034
  render() {
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>`;
4035
+ let e = this.visibleColumns, t = this.importEnabled && this._isDragOver ? i`<div class="ft-import-overlay">${A("dropFileToImport")}</div>` : a, n = this.loading ? i`<div class="ft-loading-overlay"></div>` : a;
4036
+ if (e.length === 0) return i`${t}${n}<div class="ft-empty">${A("noColumnsDefined")}</div>`;
4028
4037
  let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
4029
4038
  for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
4030
4039
  let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
@@ -4200,7 +4209,7 @@ var q = {
4200
4209
  ${this._renderEditor(e, t)}
4201
4210
  </div>
4202
4211
  `;
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 = [
4212
+ let v = s || l, y = this._isCellInvalid(n, r), b = (this._findState?.results ?? []).findIndex((e) => e.row === n && e.col === r), x = b >= 0, S = x && b === this._findState.currentIndex, w = [
4204
4213
  "ft-cell",
4205
4214
  `ft-type-${t.type ?? "text"}`,
4206
4215
  `ft-align-${G(t)}`,
@@ -4208,7 +4217,7 @@ var q = {
4208
4217
  l ? "ft-selected" : "",
4209
4218
  f ? "ft-pinned" : "",
4210
4219
  y ? "ft-invalid" : "",
4211
- C ? "ft-find-current" : S ? "ft-find-match" : "",
4220
+ S ? "ft-find-current" : x ? "ft-find-match" : "",
4212
4221
  o ? `ft-merge-${o.headParity}` : "",
4213
4222
  o?.continues ? "ft-merge-continued" : "",
4214
4223
  o?.opensDown ? "ft-merge-open" : ""
@@ -4228,7 +4237,7 @@ var q = {
4228
4237
  @click=${(e) => this._onCellClickEvent(e, n, r)}
4229
4238
  @dblclick=${() => this._onCellDblClick(n, r)}>
4230
4239
  ${O}
4231
- ${x(e[t.key], e, t)}
4240
+ ${C(e[t.key], e, t)}
4232
4241
  </div>
4233
4242
  `;
4234
4243
  }
@@ -4237,19 +4246,16 @@ var q = {
4237
4246
  let n = e[t.key], r = n == null ? "" : String(n);
4238
4247
  if (t.type === "number") return i`
4239
4248
  <input class="ft-editor ft-editor-number" type="text" inputmode="decimal"
4240
- .value=${typeof n == "number" ? N(n) : r}
4249
+ .value=${typeof n == "number" ? P(n) : r}
4241
4250
  @keydown=${this._onEditorKeyDown}
4242
4251
  @blur=${() => this._commitEdit()}>
4243
4252
  `;
4244
- if (t.type === "date") {
4245
- let e = this._toDateInputValue(n);
4246
- return i`
4247
- <input class="ft-editor" type="date"
4248
- .value=${e}
4253
+ if (t.type === "date") return i`
4254
+ <input class="ft-editor ft-editor-date" type="text" inputmode="numeric" placeholder=${u()}
4255
+ .value=${se(n)}
4249
4256
  @keydown=${this._onEditorKeyDown}
4250
4257
  @blur=${() => this._commitEdit()}>
4251
4258
  `;
4252
- }
4253
4259
  if (t.type === "datetime") {
4254
4260
  let e = this._toDateTimeInputValue(n);
4255
4261
  return i`
@@ -4299,11 +4305,6 @@ var q = {
4299
4305
  @blur=${() => this._commitEdit()}>
4300
4306
  `;
4301
4307
  }
4302
- _toDateInputValue(e) {
4303
- if (!e) return "";
4304
- let t = e instanceof Date ? e : new Date(String(e));
4305
- return isNaN(t.getTime()) ? "" : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`;
4306
- }
4307
4308
  _toDateTimeInputValue(e) {
4308
4309
  if (!e) return "";
4309
4310
  let t = e instanceof Date ? e : new Date(String(e));
@@ -4366,4 +4367,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4366
4367
  attribute: "max-undo-size"
4367
4368
  })], $.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")], $);
4368
4369
  //#endregion
4369
- export { A as a, j as i, G as n, O as o, B as r, x as s, $ as t };
4370
+ export { j as a, M as i, G as n, k as o, B as r, C as s, $ as t };
@@ -526,7 +526,6 @@ export declare class FlexTable extends LitElement {
526
526
  private _renderCell;
527
527
  private _renderEditor;
528
528
  /** Convert value to YYYY-MM-DD for date input (local timezone) */
529
- private _toDateInputValue;
530
529
  /** Convert value to YYYY-MM-DDTHH:mm for datetime-local input (local timezone) */
531
530
  private _toDateTimeInputValue;
532
531
  }
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-BF46G1Uw.js";
1
+ import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-C6PFutM_.js";
2
2
  export { o as FlexTable, e as RowSelectionState, t as UndoStack, n as effectiveAlign, i as exportData, r as flexTableLocale, a as renderCell };
package/dist/locale.d.ts CHANGED
@@ -25,7 +25,7 @@
25
25
  * (아이콘 자리의 글리프)는 어느 로케일에서도 같은 것을 뜻하며, 번역하면 오히려 읽히지 않는다.
26
26
  * 그 판단은 «번역하지 않기로 한 것»이지 «빠뜨린 것»이 아니다.
27
27
  */
28
- export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | 'clear' | 'blankCells' | 'emptyOnly' | 'nonEmptyOnly' | 'blankAll' | 'all' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'searchPlaceholder' | 'valuePlaceholder' | 'fromPlaceholder' | 'toPlaceholder' | 'findPlaceholder' | 'findPrevious' | 'findNext' | 'matchCase' | 'wholeCell' | 'closeFind' | 'replaceWithPlaceholder' | 'replace' | 'replaceAll' | 'sortAscending' | 'sortDescending' | 'filter' | 'clearFilter' | 'hideColumn' | 'showColumn' | 'autoFitWidth' | 'wider' | 'narrower' | 'columnMenuFor' | 'columnMenuRegion' | 'copy' | 'insertRowAbove' | 'insertRowBelow' | 'deleteRow' | 'filterByThisValue' | 'addComment' | 'editComment' | 'deleteComment' | 'booleanTrue' | 'booleanFalse' | 'dropFileToImport' | 'notANumber' | 'notInList';
28
+ export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | 'clear' | 'blankCells' | 'emptyOnly' | 'nonEmptyOnly' | 'blankAll' | 'all' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'searchPlaceholder' | 'valuePlaceholder' | 'fromPlaceholder' | 'toPlaceholder' | 'findPlaceholder' | 'findPrevious' | 'findNext' | 'matchCase' | 'wholeCell' | 'closeFind' | 'replaceWithPlaceholder' | 'replace' | 'replaceAll' | 'sortAscending' | 'sortDescending' | 'filter' | 'clearFilter' | 'hideColumn' | 'showColumn' | 'autoFitWidth' | 'wider' | 'narrower' | 'columnMenuFor' | 'columnMenuRegion' | 'copy' | 'insertRowAbove' | 'insertRowBelow' | 'deleteRow' | 'filterByThisValue' | 'addComment' | 'editComment' | 'deleteComment' | 'booleanTrue' | 'booleanFalse' | 'dropFileToImport' | 'notANumber' | 'notADate' | 'notInList';
29
29
  /** 이 패키지의 chrome 문자열 묶음. 소비자가 `register()` 로 언어를 더하거나 문구를 덮을 수 있다. */
30
30
  export declare const flexTableLocale: import("@iyulab/components/dist/utilities/Locale.js").LocaleNamespace<FlexTableMessageKey>;
31
31
  /** 짧은 조회 별칭 — 렌더 코드가 읽히게 유지한다. */
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-BF46G1Uw.js";
1
+ import { t as e } from "./flex-table-C6PFutM_.js";
2
2
  import { i as t, t as n } from "./query-Dw4iO0ir.js";
3
3
  import { t as r } from "./view-DiLr-TdY.js";
4
4
  import i, { useCallback as a, useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.41.0",
3
+ "version": "0.41.1",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",
@@ -72,7 +72,7 @@
72
72
  "odata-query": "^8.1.0"
73
73
  },
74
74
  "peerDependencies": {
75
- "@iyulab/components": ">=1.54.0",
75
+ "@iyulab/components": ">=1.55.0",
76
76
  "@lit/react": "^1.0.8",
77
77
  "react": "^18.0.0 || ^19.0.0"
78
78
  },
@@ -67,6 +67,7 @@ as `text`). See `references/api.md` for every field.
67
67
  - `editor` returns a Lit template containing an element with class `ft-editor`; its `.value` is committed.
68
68
  - `validator` returns `null` when valid, or an error message (the edit is rejected and `validation-error` fires).
69
69
  - `number` cells, the number filter and paste read numbers in the active `Locale` (`1,5` is 1.5 on a comma-decimal page); an edit that is not a number is rejected with `validation-error`.
70
+ - `date` cells edit as a `YYYY-MM-DD` text box in every browser language (also `20261002`, `2026/10/2`, `10-02`); pasted dates are normalized to ISO.
70
71
  - `conditionalRules` applies `{ when, style }` rules in order; later matches override earlier ones.
71
72
  - `pinned: 'left' | 'right'` freezes a column during horizontal scroll.
72
73