@iyulab/flex-table 0.41.0 → 0.41.2

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,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.41.2] - 2026-10-03
4
+
5
+ ### Fixed
6
+
7
+ - **The `datetime` cell editor shows and takes `YYYY-MM-DD HH:mm` in every browser language.** It was the
8
+ native `datetime-local` input, which follows the browser's UI language. It is now a text box in local
9
+ time that reads `2026-10-02 14:05` (`9:05`, a date alone is midnight), stores the local
10
+ `YYYY-MM-DDTHH:mm` string as before, and rejects text it cannot read with `validation-error`
11
+ ("Enter a date and time as YYYY-MM-DD HH:mm", new `flexTableLocale` key `notADateTime`).
12
+ - **Pasting `2026-10-02 14:05` into a datetime column stores `2026-10-02T14:05`.** Other text stays text.
13
+
14
+ ### Changed
15
+
16
+ - **The `@iyulab/components` peer is `>=1.56.0`** — date-times are read with its `parseDateTime`.
17
+
18
+ ## [0.41.1] - 2026-10-03
19
+
20
+ ### Fixed
21
+
22
+ - **The `date` cell editor shows and takes `YYYY-MM-DD` in every browser language.** It was the native
23
+ date input, which shows the browser's UI language (`10/02/2026` in an English browser) whatever the
24
+ page's `Locale`. It is now a text box that also reads `2026/10/2`, `20261002`, `2026. 10. 2.` and
25
+ `10-02` (this year), stores the ISO date string as before, and rejects text that is not a date with
26
+ `validation-error` ("Enter a date as YYYY-MM-DD", new `flexTableLocale` key `notADate`).
27
+ - **The editor no longer shifts a date string by a day.** It read `'2026-10-02'` with `new Date()`
28
+ (UTC midnight), which is the previous day west of UTC.
29
+ - **Pasting `2026/10/2` into a date column stores `2026-10-02`.** Text that is not a date still stays text.
30
+
31
+ ### Changed
32
+
33
+ - **The `@iyulab/components` peer is `>=1.55.0`** — dates are read with its `parseDate`.
34
+
3
35
  ## [0.41.0] - 2026-10-03
4
36
 
5
37
  ### 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. A `datetime` column's editor works the same with a time: it shows `YYYY-MM-DD HH:mm` in local time, reads `2026-10-02 14:05` (a date alone is midnight), and stores the local `YYYY-MM-DDTHH:mm` string.
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,15 @@ 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;
20
+ /**
21
+ * A `datetime` cell's value as `YYYY-MM-DD HH:mm` (local) for editing — the form the editor reads
22
+ * back. A local date-time string (`2026-10-02T14:05`, no offset) keeps its wall-clock time; a `Date`
23
+ * or a string with an offset (`Z`, `+09:00`) is shown in local time. Anything else is shown as it is.
24
+ */
25
+ export declare function editableDateTime(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, parseDateTime as m, parseNumber as h } from "@iyulab/components/dist/utilities/format.js";
6
+ import { decodeTsv as g, encodeTsv as _ } from "@iyulab/components/dist/utilities/tsv.js";
7
+ import { isImeComposing as v } from "@iyulab/components/dist/utilities/keyboard.js";
8
8
  //#region src/styles/flex-table.styles.ts
9
- var g = r`
9
+ var y = 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 b(e, t) {
925
+ return e == null ? "" : typeof t == "function" ? t(e) : x(t) ? C(e, t) : S(e, t);
926
926
  }
927
- function v(e) {
927
+ function x(e) {
928
928
  return /[yMdHhms]/.test(e);
929
929
  }
930
- function y(e, t) {
930
+ function S(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 C(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 w(e, t, n) {
955
+ return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : b(e, n.format) : T(e, n);
956
956
  }
957
- function S(e, t) {
957
+ function T(e, t) {
958
958
  if (e == null) return "";
959
959
  switch (t.type) {
960
- case "number": return T(e);
960
+ case "number": return O(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 ee(e);
963
+ case "datetime": return te(e);
964
+ case "select": return E(e, t);
965
965
  default: return String(e);
966
966
  }
967
967
  }
968
- function C(e, t) {
968
+ function E(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 D = {
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 O(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 ee(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 te(e) {
988
+ return e instanceof Date || typeof e == "string" ? d(e, D) : 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,10 @@ 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",
1048
+ notADateTime: "Enter a date and time as YYYY-MM-DD HH:mm",
1047
1049
  notInList: "Value must be from the existing list"
1048
- }), O.register("ko", {
1050
+ }), k.register("ko", {
1049
1051
  showHiddenColumns: "숨긴 열 보기",
1050
1052
  columnMenu: "열 메뉴",
1051
1053
  cellActions: "셀 작업",
@@ -1099,12 +1101,14 @@ O.register("en", {
1099
1101
  booleanFalse: "거짓",
1100
1102
  dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)",
1101
1103
  notANumber: "숫자를 입력하세요",
1104
+ notADate: "날짜를 YYYY-MM-DD 로 입력하세요",
1105
+ notADateTime: "날짜와 시간을 YYYY-MM-DD HH:mm 으로 입력하세요",
1102
1106
  notInList: "목록에 있는 값이어야 합니다"
1103
1107
  });
1104
- var k = (e, t) => O.text(e, t);
1108
+ var A = (e, t) => k.text(e, t);
1105
1109
  //#endregion
1106
1110
  //#region src/core/selection.ts
1107
- function ee(e) {
1111
+ function ne(e) {
1108
1112
  return {
1109
1113
  startRow: Math.min(e.startRow, e.endRow),
1110
1114
  startCol: Math.min(e.startCol, e.endCol),
@@ -1112,7 +1116,7 @@ function ee(e) {
1112
1116
  endCol: Math.max(e.startCol, e.endCol)
1113
1117
  };
1114
1118
  }
1115
- var te = class {
1119
+ var re = class {
1116
1120
  constructor() {
1117
1121
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
1118
1122
  }
@@ -1139,7 +1143,7 @@ var te = class {
1139
1143
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
1140
1144
  row: e,
1141
1145
  col: t
1142
- }, this.rangeAnchor && (this.range = ee({
1146
+ }, this.rangeAnchor && (this.range = ne({
1143
1147
  startRow: this.rangeAnchor.row,
1144
1148
  startCol: this.rangeAnchor.col,
1145
1149
  endRow: e,
@@ -1210,7 +1214,7 @@ var te = class {
1210
1214
  shiftMoveRight() {
1211
1215
  return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
1212
1216
  }
1213
- }, ne = class {
1217
+ }, ie = class {
1214
1218
  constructor() {
1215
1219
  this.current = null;
1216
1220
  }
@@ -1231,7 +1235,7 @@ var te = class {
1231
1235
  let e = this.current;
1232
1236
  return this.current = null, e;
1233
1237
  }
1234
- }, A = class {
1238
+ }, j = class {
1235
1239
  constructor() {
1236
1240
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
1237
1241
  }
@@ -1292,7 +1296,7 @@ var te = class {
1292
1296
  };
1293
1297
  //#endregion
1294
1298
  //#region src/core/filtering.ts
1295
- function re(e, t, n) {
1299
+ function ae(e, t, n) {
1296
1300
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
1297
1301
  let r = [];
1298
1302
  for (let i = 0; i < e.length; i++) {
@@ -1311,9 +1315,9 @@ function re(e, t, n) {
1311
1315
  }
1312
1316
  //#endregion
1313
1317
  //#region src/core/undo.ts
1314
- var ie = 100, j = class {
1318
+ var oe = 100, M = class {
1315
1319
  constructor() {
1316
- this._undoStack = [], this._redoStack = [], this._maxSize = ie;
1320
+ this._undoStack = [], this._redoStack = [], this._maxSize = oe;
1317
1321
  }
1318
1322
  get maxSize() {
1319
1323
  return this._maxSize;
@@ -1350,7 +1354,7 @@ var ie = 100, j = class {
1350
1354
  };
1351
1355
  //#endregion
1352
1356
  //#region src/clipboard/clipboard.ts
1353
- function ae(e, t, n) {
1357
+ function se(e, t, n) {
1354
1358
  let r = [];
1355
1359
  for (let i = n.startRow; i <= n.endRow; i++) {
1356
1360
  let a = e[i], o = [];
@@ -1360,30 +1364,47 @@ function ae(e, t, n) {
1360
1364
  }
1361
1365
  r.push(o);
1362
1366
  }
1363
- return m(r);
1367
+ return _(r);
1364
1368
  }
1365
- function M(e, t) {
1369
+ function N(e, t) {
1366
1370
  if (e === "") return null;
1367
1371
  switch (t.type) {
1368
1372
  case "number": {
1369
- let t = f(e);
1373
+ let t = h(e);
1370
1374
  if (t !== null) return t;
1371
1375
  let n = Number(e.trim());
1372
1376
  return e.trim() !== "" && Number.isFinite(n) ? n : e;
1373
1377
  }
1374
1378
  case "boolean": return e.toLowerCase() === "true" || e === "1";
1379
+ case "date": return p(e) ?? e;
1380
+ case "datetime": return m(e) ?? e;
1375
1381
  default: return e;
1376
1382
  }
1377
1383
  }
1378
- function N(e) {
1384
+ function P(e) {
1379
1385
  let t = String(e);
1380
1386
  if (!Number.isFinite(e) || t.includes("e")) return t;
1381
1387
  let n = new Intl.NumberFormat(l.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
1382
1388
  return n && n !== "." ? t.replace(".", n) : t;
1383
1389
  }
1390
+ function ce(e) {
1391
+ if (e == null || e === "") return "";
1392
+ if (e instanceof Date) return Number.isNaN(e.getTime()) ? "" : `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
1393
+ let t = String(e), n = /^(\d{4}-\d{2}-\d{2})(?:$|T)/.exec(t);
1394
+ return n ? n[1] : t;
1395
+ }
1396
+ function le(e) {
1397
+ if (e == null || e === "") return "";
1398
+ let t = e instanceof Date ? "" : String(e), n = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(t);
1399
+ if (n) return `${n[1]} ${n[2]}`;
1400
+ let r = e instanceof Date ? e : /^\d{4}-\d{2}-\d{2}T/.test(t) ? new Date(t) : null;
1401
+ if (!r || Number.isNaN(r.getTime())) return t;
1402
+ let i = (e) => String(e).padStart(2, "0");
1403
+ return `${r.getFullYear()}-${i(r.getMonth() + 1)}-${i(r.getDate())} ${i(r.getHours())}:${i(r.getMinutes())}`;
1404
+ }
1384
1405
  //#endregion
1385
1406
  //#region src/export/xlsx-writer.ts
1386
- var oe = (() => {
1407
+ var ue = (() => {
1387
1408
  let e = /* @__PURE__ */ new Uint32Array(256);
1388
1409
  for (let t = 0; t < 256; t++) {
1389
1410
  let n = t;
@@ -1392,56 +1413,56 @@ var oe = (() => {
1392
1413
  }
1393
1414
  return e;
1394
1415
  })();
1395
- function se(e) {
1416
+ function de(e) {
1396
1417
  let t = 4294967295;
1397
- for (let n = 0; n < e.length; n++) t = oe[(t ^ e[n]) & 255] ^ t >>> 8;
1418
+ for (let n = 0; n < e.length; n++) t = ue[(t ^ e[n]) & 255] ^ t >>> 8;
1398
1419
  return (t ^ 4294967295) >>> 0;
1399
1420
  }
1400
- var P = new TextEncoder();
1401
- function ce(e) {
1421
+ var F = new TextEncoder();
1422
+ function fe(e) {
1402
1423
  let t = [], n = [], r = 0;
1403
1424
  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);
1425
+ let e = F.encode(i.name), a = de(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1405
1426
  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
1427
  let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
1407
1428
  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
1429
  }
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([
1430
+ let i = I(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1431
+ 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
1432
  ...t,
1412
1433
  i,
1413
1434
  new Uint8Array(a)
1414
1435
  ]);
1415
1436
  }
1416
- function F(e) {
1437
+ function I(e) {
1417
1438
  let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
1418
1439
  for (let t of e) n.set(t, r), r += t.length;
1419
1440
  return n;
1420
1441
  }
1421
- function I(e) {
1442
+ function L(e) {
1422
1443
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1423
1444
  }
1424
- function le(e) {
1445
+ function pe(e) {
1425
1446
  let t = "";
1426
1447
  for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1427
1448
  return t;
1428
1449
  }
1429
- function L(e, t) {
1430
- return le(t) + (e + 1);
1450
+ function R(e, t) {
1451
+ return pe(t) + (e + 1);
1431
1452
  }
1432
- function ue(e) {
1453
+ function me(e) {
1433
1454
  let t = Date.UTC(1899, 11, 30);
1434
1455
  return (e.getTime() - t) / 864e5;
1435
1456
  }
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>`);
1457
+ var z = "<?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>", 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/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", ge = "<?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>", _e = "<?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>", ve = "<?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>";
1458
+ function ye(e, t) {
1459
+ let n = [], r = t.map((e, t) => `<c r="${R(0, t)}" t="str" s="2"><v>${L(e.label)}</v></c>`);
1439
1460
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1440
1461
  let i = t.map((t, n) => {
1441
- let i = L(r + 1, n), a = e[t.key];
1462
+ let i = R(r + 1, n), a = e[t.key];
1442
1463
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1443
1464
  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>`;
1465
+ 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>${me(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
1466
  });
1446
1467
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1447
1468
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -1449,32 +1470,32 @@ function z(e, t) {
1449
1470
  <sheetData>${n.join("")}</sheetData>
1450
1471
  </worksheet>`;
1451
1472
  }
1452
- function he(e, t) {
1453
- let n = z(e, t);
1454
- return ce([
1473
+ function be(e, t) {
1474
+ let n = ye(e, t);
1475
+ return fe([
1455
1476
  {
1456
1477
  name: "[Content_Types].xml",
1457
- data: P.encode(de)
1478
+ data: F.encode(z)
1458
1479
  },
1459
1480
  {
1460
1481
  name: "_rels/.rels",
1461
- data: P.encode(fe)
1482
+ data: F.encode(he)
1462
1483
  },
1463
1484
  {
1464
1485
  name: "xl/workbook.xml",
1465
- data: P.encode(pe)
1486
+ data: F.encode(ge)
1466
1487
  },
1467
1488
  {
1468
1489
  name: "xl/_rels/workbook.xml.rels",
1469
- data: P.encode(me)
1490
+ data: F.encode(_e)
1470
1491
  },
1471
1492
  {
1472
1493
  name: "xl/worksheets/sheet1.xml",
1473
- data: P.encode(n)
1494
+ data: F.encode(n)
1474
1495
  },
1475
1496
  {
1476
1497
  name: "xl/styles.xml",
1477
- data: P.encode(R)
1498
+ data: F.encode(ve)
1478
1499
  }
1479
1500
  ]);
1480
1501
  }
@@ -1484,20 +1505,20 @@ function B(e, t, n) {
1484
1505
  switch (n) {
1485
1506
  case "csv": return V(e, t, ",");
1486
1507
  case "tsv": return V(e, t, " ");
1487
- case "json": return _e(e, t);
1488
- case "xlsx": return he(e, t);
1508
+ case "json": return Se(e, t);
1509
+ case "xlsx": return be(e, t);
1489
1510
  }
1490
1511
  }
1491
- function ge(e, t) {
1512
+ function xe(e, t) {
1492
1513
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
1493
1514
  }
1494
1515
  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");
1516
+ return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(xe(e[t.key], t), n)).join(n))].join("\n");
1496
1517
  }
1497
1518
  function H(e, t) {
1498
1519
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
1499
1520
  }
1500
- function _e(e, t) {
1521
+ function Se(e, t) {
1501
1522
  let n = e.map((e) => {
1502
1523
  let n = {};
1503
1524
  for (let r of t) {
@@ -1508,35 +1529,35 @@ function _e(e, t) {
1508
1529
  });
1509
1530
  return JSON.stringify(n, null, 2);
1510
1531
  }
1511
- function ve(e, t, n) {
1532
+ function Ce(e, t, n) {
1512
1533
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
1513
1534
  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
1535
  }
1515
- var ye = {
1536
+ var U = {
1516
1537
  csv: "text/csv;charset=utf-8",
1517
1538
  tsv: "text/tab-separated-values;charset=utf-8",
1518
1539
  json: "application/json;charset=utf-8",
1519
1540
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1520
- }, be = {
1541
+ }, we = {
1521
1542
  csv: ".csv",
1522
1543
  tsv: ".tsv",
1523
1544
  json: ".json",
1524
1545
  xlsx: ".xlsx"
1525
1546
  };
1526
- function xe(e) {
1527
- return ye[e];
1547
+ function Te(e) {
1548
+ return U[e];
1528
1549
  }
1529
- function Se(e) {
1530
- return be[e];
1550
+ function Ee(e) {
1551
+ return we[e];
1531
1552
  }
1532
1553
  //#endregion
1533
1554
  //#region src/export/xlsx-reader.ts
1534
- function Ce(e) {
1555
+ function De(e) {
1535
1556
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
1536
1557
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
1537
1558
  }
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;
1559
+ function Oe(e) {
1560
+ let t = De(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
1561
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
1541
1562
  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
1563
  a.push({
@@ -1549,7 +1570,7 @@ function we(e) {
1549
1570
  }
1550
1571
  return a;
1551
1572
  }
1552
- async function Te(e) {
1573
+ async function ke(e) {
1553
1574
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
1554
1575
  n.write(e), n.close();
1555
1576
  let i = [];
@@ -1562,28 +1583,28 @@ async function Te(e) {
1562
1583
  for (let e of i) o.set(e, s), s += e.length;
1563
1584
  return o;
1564
1585
  }
1565
- async function Ee(e, t) {
1586
+ async function Ae(e, t) {
1566
1587
  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
1588
  if (t.compressionMethod === 0) return o.slice();
1568
- if (t.compressionMethod === 8) return Te(o);
1589
+ if (t.compressionMethod === 8) return ke(o);
1569
1590
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
1570
1591
  }
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));
1592
+ async function je(e) {
1593
+ let t = new DataView(e), n = Oe(t), r = /* @__PURE__ */ new Map();
1594
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ae(t, e));
1574
1595
  return r;
1575
1596
  }
1576
- var Oe = new TextDecoder("utf-8");
1577
- function U(e) {
1578
- let t = Oe.decode(e);
1597
+ var Me = new TextDecoder("utf-8");
1598
+ function W(e) {
1599
+ let t = Me.decode(e);
1579
1600
  return new DOMParser().parseFromString(t, "application/xml");
1580
1601
  }
1581
- function ke(e) {
1602
+ function Ne(e) {
1582
1603
  if (!e) return [];
1583
- let t = U(e);
1604
+ let t = W(e);
1584
1605
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
1585
1606
  }
1586
- var Ae = /* @__PURE__ */ new Set([
1607
+ var Pe = /* @__PURE__ */ new Set([
1587
1608
  14,
1588
1609
  15,
1589
1610
  16,
@@ -1603,37 +1624,37 @@ var Ae = /* @__PURE__ */ new Set([
1603
1624
  57,
1604
1625
  58
1605
1626
  ]);
1606
- function je(e) {
1627
+ function Fe(e) {
1607
1628
  let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
1608
1629
  return /[dy]/i.test(t);
1609
1630
  }
1610
- function Me(e) {
1631
+ function Ie(e) {
1611
1632
  let t = /* @__PURE__ */ new Set();
1612
1633
  if (!e) return t;
1613
- let n = U(e), r = /* @__PURE__ */ new Map();
1634
+ let n = W(e), r = /* @__PURE__ */ new Map();
1614
1635
  for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
1615
1636
  return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
1616
1637
  let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
1617
- (a === void 0 ? Ae.has(i) : je(a)) && t.add(n);
1638
+ (a === void 0 ? Pe.has(i) : Fe(a)) && t.add(n);
1618
1639
  }), t;
1619
1640
  }
1620
- function Ne(e) {
1641
+ function Le(e) {
1621
1642
  if (!e) return !1;
1622
- let t = U(e).querySelector("workbookPr")?.getAttribute("date1904");
1643
+ let t = W(e).querySelector("workbookPr")?.getAttribute("date1904");
1623
1644
  return t === "1" || t === "true";
1624
1645
  }
1625
- function Pe(e, t) {
1646
+ function Re(e, t) {
1626
1647
  return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
1627
1648
  }
1628
- function Fe(e, t, n, r) {
1629
- let i = U(e).querySelectorAll("row");
1649
+ function ze(e, t, n, r) {
1650
+ let i = W(e).querySelectorAll("row");
1630
1651
  if (i.length === 0) return [];
1631
1652
  let a = 0, o = /* @__PURE__ */ new Map();
1632
1653
  for (let e of i) {
1633
1654
  let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
1634
1655
  o.set(i, s);
1635
1656
  for (let i of e.querySelectorAll("c")) {
1636
- let e = Ie(i.getAttribute("r") ?? "");
1657
+ let e = Be(i.getAttribute("r") ?? "");
1637
1658
  e > a && (a = e);
1638
1659
  let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
1639
1660
  if (o === "s") d = t[parseInt(l, 10)] ?? "";
@@ -1642,7 +1663,7 @@ function Fe(e, t, n, r) {
1642
1663
  else if (l === "") d = "";
1643
1664
  else {
1644
1665
  let e = parseFloat(l);
1645
- d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Pe(e, r) : l;
1666
+ d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Re(e, r) : l;
1646
1667
  }
1647
1668
  s.set(e, d);
1648
1669
  }
@@ -1656,13 +1677,13 @@ function Fe(e, t, n, r) {
1656
1677
  }
1657
1678
  return c;
1658
1679
  }
1659
- function Ie(e) {
1680
+ function Be(e) {
1660
1681
  let t = 0, n = 0;
1661
1682
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
1662
1683
  return t - 1;
1663
1684
  }
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");
1685
+ async function Ve(e) {
1686
+ let t = await je(e), n = Ne(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
1666
1687
  if (!r) {
1667
1688
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
1668
1689
  r = n;
@@ -1670,7 +1691,7 @@ async function W(e) {
1670
1691
  }
1671
1692
  }
1672
1693
  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);
1694
+ let i = Ie(t.get("xl/styles.xml")), a = Le(t.get("xl/workbook.xml")), o = ze(r, n, i, a);
1674
1695
  return o.length === 0 ? {
1675
1696
  headers: [],
1676
1697
  rows: []
@@ -1701,14 +1722,14 @@ var q = {
1701
1722
  lt: "<",
1702
1723
  gte: "≥",
1703
1724
  lte: "≤"
1704
- }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Le = 200, $ = class extends n {
1725
+ }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, He = 200, $ = class extends n {
1705
1726
  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 = () => {
1727
+ 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 re(), this._editing = new ie(), 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
1728
  this._commitCommentPopup();
1708
1729
  }, 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
1730
  }
1710
1731
  static {
1711
- this.styles = g;
1732
+ this.styles = y;
1712
1733
  }
1713
1734
  get data() {
1714
1735
  return this._data;
@@ -2073,7 +2094,7 @@ var q = {
2073
2094
  return B(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2074
2095
  }
2075
2096
  exportToFile(e, t) {
2076
- ve(this.exportToString(e), t ?? `export${Se(e)}`, xe(e));
2097
+ Ce(this.exportToString(e), t ?? `export${Ee(e)}`, Te(e));
2077
2098
  }
2078
2099
  setComment(e, t, n) {
2079
2100
  let r = this.getComment(e, t);
@@ -2130,10 +2151,10 @@ var q = {
2130
2151
  async importFromFile(e) {
2131
2152
  let t = e.name.toLowerCase();
2132
2153
  if (t.endsWith(".xlsx")) {
2133
- let t = await W(await e.arrayBuffer());
2154
+ let t = await Ve(await e.arrayBuffer());
2134
2155
  this._applyImportedSheet(t);
2135
2156
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
2136
- let t = await e.text(), n = p(t);
2157
+ let t = await e.text(), n = g(t);
2137
2158
  this._applyImportedRows(n);
2138
2159
  } else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
2139
2160
  }
@@ -2144,7 +2165,7 @@ var q = {
2144
2165
  let a = t.get(e);
2145
2166
  if (!a) return;
2146
2167
  let o = this.columns.find((e) => e.key === a);
2147
- r[a] = o ? M(n[i] ?? "", o) : n[i] ?? null;
2168
+ r[a] = o ? N(n[i] ?? "", o) : n[i] ?? null;
2148
2169
  }), r;
2149
2170
  }), r = [...this.data];
2150
2171
  this.data = n, this._undo.push({
@@ -2169,7 +2190,7 @@ var q = {
2169
2190
  let a = n.get(t);
2170
2191
  if (!a) return;
2171
2192
  let o = this.columns.find((e) => e.key === a);
2172
- r[a] = o ? M(e[i] ?? "", o) : e[i] ?? null;
2193
+ r[a] = o ? N(e[i] ?? "", o) : e[i] ?? null;
2173
2194
  }), r;
2174
2195
  }), i = [...this.data];
2175
2196
  this.data = r, this._undo.push({
@@ -2323,7 +2344,7 @@ var q = {
2323
2344
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
2324
2345
  return;
2325
2346
  }
2326
- if (this._filteredIndices = re(this.data, this._filters, (e, t, n) => {
2347
+ if (this._filteredIndices = ae(this.data, this._filters, (e, t, n) => {
2327
2348
  this.dispatchEvent(new CustomEvent("filter-error", {
2328
2349
  detail: {
2329
2350
  error: e,
@@ -2353,7 +2374,7 @@ var q = {
2353
2374
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2354
2375
  }
2355
2376
  _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.`));
2377
+ this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < He || 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
2378
  }
2358
2379
  _onScroll() {
2359
2380
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -2483,7 +2504,7 @@ var q = {
2483
2504
  }
2484
2505
  let t = this.shadowRoot?.querySelector(".ft-editor");
2485
2506
  if (t) {
2486
- let n = M(t.value, e);
2507
+ let n = N(t.value, e);
2487
2508
  this._applyEdit(n);
2488
2509
  } else this._cancelEdit();
2489
2510
  }
@@ -2493,7 +2514,7 @@ var q = {
2493
2514
  if (this._editingCell = null, !t) return;
2494
2515
  let { row: n, col: r } = t.position, i = this._toDataIndex(n), a = this.visibleColumns[r], o = t.originalValue;
2495
2516
  if (a.autocomplete === "strict" && e != null && e !== "" && !this._getAutocompleteCandidates(a, "").includes(String(e))) {
2496
- let t = k("notInList");
2517
+ let t = A("notInList");
2497
2518
  this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
2498
2519
  detail: {
2499
2520
  row: i,
@@ -2507,8 +2528,8 @@ var q = {
2507
2528
  }));
2508
2529
  return;
2509
2530
  }
2510
- if (a.type === "number" && typeof e == "string") {
2511
- let t = k("notANumber");
2531
+ if (a.type === "number" && typeof e == "string" || a.type === "date" && typeof e == "string" && p(e) === null || a.type === "datetime" && typeof e == "string" && m(e) === null) {
2532
+ let t = A(a.type === "number" ? "notANumber" : a.type === "date" ? "notADate" : "notADateTime");
2512
2533
  this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
2513
2534
  detail: {
2514
2535
  row: i,
@@ -2572,7 +2593,7 @@ var q = {
2572
2593
  }));
2573
2594
  }
2574
2595
  _onEditorKeyDown(e) {
2575
- if (!h(e)) {
2596
+ if (!v(e)) {
2576
2597
  if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
2577
2598
  if (e.key === "ArrowDown") {
2578
2599
  e.preventDefault(), e.stopPropagation();
@@ -2640,7 +2661,7 @@ var q = {
2640
2661
  ].includes(t) && this._handleCtrlKey(e)) return;
2641
2662
  }
2642
2663
  if (t.length !== 0 && this._visibleRowCount !== 0) {
2643
- if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !h(e)) {
2664
+ if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !v(e)) {
2644
2665
  e.preventDefault();
2645
2666
  let n = t[this._activeCell.col];
2646
2667
  n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n);
@@ -2728,7 +2749,7 @@ var q = {
2728
2749
  async _handleCopy(e) {
2729
2750
  let t = this._selection.getEffectiveRange();
2730
2751
  if (!t) return;
2731
- let n = this.visibleColumns, r = ae(this._sortedIndices.map((e) => this.data[e]), n, t);
2752
+ let n = this.visibleColumns, r = se(this._sortedIndices.map((e) => this.data[e]), n, t);
2732
2753
  try {
2733
2754
  await navigator.clipboard.writeText(r);
2734
2755
  } catch (e) {
@@ -2754,7 +2775,7 @@ var q = {
2754
2775
  if (!this._activeCell) return;
2755
2776
  let e = await this._readClipboardText();
2756
2777
  if (e == null) return;
2757
- let t = p(e);
2778
+ let t = g(e);
2758
2779
  if (t.length === 0) return;
2759
2780
  let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
2760
2781
  if (r.length > 0 || n.length > 0) {
@@ -2812,7 +2833,7 @@ var q = {
2812
2833
  for (let a = 0; a < t[i].length; a++) {
2813
2834
  let s = e.col + a;
2814
2835
  if (s >= n.length) break;
2815
- let c = n[s], l = this.data[o][c.key], u = M(t[i][a], c);
2836
+ let c = n[s], l = this.data[o][c.key], u = N(t[i][a], c);
2816
2837
  this.data[o][c.key] = u, r.push({
2817
2838
  row: o,
2818
2839
  col: s,
@@ -2877,7 +2898,7 @@ var q = {
2877
2898
  for (let r = e.startCol + 1; r <= e.endCol; r++) {
2878
2899
  let e = t[r];
2879
2900
  if (!e || !this._isCellEditable(e)) continue;
2880
- let a = M(o == null ? "" : String(o), e);
2901
+ let a = N(o == null ? "" : String(o), e);
2881
2902
  n.push({
2882
2903
  row: i,
2883
2904
  key: e.key,
@@ -3037,7 +3058,7 @@ var q = {
3037
3058
  @click=${n ? (t) => this._onHeaderClick(t, e) : void 0}>
3038
3059
  ${C ? i`
3039
3060
  <button class="ft-hidden-col-indicator"
3040
- title=${k("showHiddenColumns")}
3061
+ title=${A("showHiddenColumns")}
3041
3062
  @click=${(t) => {
3042
3063
  t.stopPropagation(), this._showHiddenBefore(e);
3043
3064
  }}>&#x276F;</button>
@@ -3047,8 +3068,8 @@ var q = {
3047
3068
  ${o >= 0 ? i`<span class="ft-sort-order">${o + 1}</span>` : ""}
3048
3069
  <button class="ft-column-menu-btn ${s ? "ft-filter-active" : ""}"
3049
3070
  type="button"
3050
- title=${k("columnMenu")}
3051
- aria-label=${k("columnMenuFor", { header: e.label })}
3071
+ title=${A("columnMenu")}
3072
+ aria-label=${A("columnMenuFor", { header: e.label })}
3052
3073
  aria-haspopup="menu"
3053
3074
  aria-expanded=${this._headerMenu?.key === e.key ? "true" : "false"}
3054
3075
  @mousedown=${(e) => e.stopPropagation()}
@@ -3167,26 +3188,26 @@ var q = {
3167
3188
  }}>${t}</button>
3168
3189
  `;
3169
3190
  return i`
3170
- <div class="ft-header-menu" role="menu" aria-label=${k("columnMenuRegion", { header: o.label })}
3191
+ <div class="ft-header-menu" role="menu" aria-label=${A("columnMenuRegion", { header: o.label })}
3171
3192
  style="position: fixed; left: ${t}px; top: ${n}px; z-index: var(--u-layer-floating, 1000);"
3172
3193
  @mousedown=${(e) => e.stopPropagation()}
3173
3194
  @keydown=${(e) => this._onHeaderMenuKeydown(e)}>
3174
3195
  ${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"))}
3196
+ ${c("sort-asc", A("sortAscending"), () => this._applySortFromMenu(e, "asc"))}
3197
+ ${c("sort-desc", A("sortDescending"), () => this._applySortFromMenu(e, "desc"))}
3177
3198
  <div class="ft-header-menu-separator" role="separator"></div>
3178
3199
  `}
3179
3200
  ${this.showFilters ? i`
3180
- ${c("filter", k("filter"), () => this._openFilterFromMenu(e))}
3181
- ${s ? c("clear-filter", k("clearFilter"), () => this._clearColumnFilter(e)) : a}
3201
+ ${c("filter", A("filter"), () => this._openFilterFromMenu(e))}
3202
+ ${s ? c("clear-filter", A("clearFilter"), () => this._clearColumnFilter(e)) : a}
3182
3203
  <div class="ft-header-menu-separator" role="separator"></div>
3183
3204
  ` : 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)))}
3205
+ ${c("hide", A("hideColumn"), () => this._setColumnHidden(e, !0))}
3206
+ ${r.map((e) => c("show", A("showColumn", { header: e.label }), () => this._setColumnHidden(e.key, !1)))}
3186
3207
  <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)}
3208
+ ${c("autofit", A("autoFitWidth"), () => this._autoFitColumn(e))}
3209
+ ${c("wider", A("wider"), () => this._resizeColumnBy(e, X), !0)}
3210
+ ${c("narrower", A("narrower"), () => this._resizeColumnBy(e, -20), !0)}
3190
3211
  </div>
3191
3212
  `;
3192
3213
  }
@@ -3204,26 +3225,26 @@ var q = {
3204
3225
  }}>${e}</button>
3205
3226
  `, f = i`<div class="ft-context-menu-separator" role="separator"></div>`;
3206
3227
  return i`
3207
- <div class="ft-body-context-menu" role="menu" aria-label=${k("cellActions")}
3228
+ <div class="ft-body-context-menu" role="menu" aria-label=${A("cellActions")}
3208
3229
  style="position: fixed; left: ${n}px; top: ${r}px; z-index: var(--u-layer-floating, 1000);"
3209
3230
  @mousedown=${(e) => e.stopPropagation()}
3210
3231
  @keydown=${(e) => this._onMenuKeydown(e, ".ft-body-context-menu", l)}>
3211
- ${d(k("copy"), () => this._handleCopy(!1))}
3232
+ ${d(A("copy"), () => this._handleCopy(!1))}
3212
3233
  ${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)}
3234
+ ${d(A("insertRowAbove"), () => this.addRow(void 0, t))}
3235
+ ${d(A("insertRowBelow"), () => this.addRow(void 0, t + 1))}
3236
+ ${d(A("deleteRow"), () => this.deleteRows([t]), !0)}
3216
3237
  ${f}
3217
- ${d(k("hideColumn"), () => this._setColumnHidden(o.key, !0))}
3238
+ ${d(A("hideColumn"), () => this._setColumnHidden(o.key, !0))}
3218
3239
  ${f}
3219
- ${d(`${k("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
3220
- ${d(`${k("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
3240
+ ${d(`${A("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
3241
+ ${d(`${A("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
3221
3242
  ${f}
3222
- ${d(k("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
3223
- ${c ? d(k("clearFilter"), () => this.removeFilter(o.key)) : a}
3243
+ ${d(A("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
3244
+ ${c ? d(A("clearFilter"), () => this.removeFilter(o.key)) : a}
3224
3245
  ${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}
3246
+ ${d(A(u ? "editComment" : "addComment"), () => this._openCommentPopup(t, o.key, n, r))}
3247
+ ${u ? d(A("deleteComment"), () => this.setComment(t, o.key, null), !0) : a}
3227
3248
  </div>
3228
3249
  `;
3229
3250
  }
@@ -3255,13 +3276,13 @@ var q = {
3255
3276
  @mousedown=${(e) => e.stopPropagation()}>
3256
3277
  <textarea class="ft-comment-popup-textarea"
3257
3278
  rows="4"
3258
- placeholder=${k("addCommentPlaceholder")}
3279
+ placeholder=${A("addCommentPlaceholder")}
3259
3280
  @keydown=${(e) => {
3260
3281
  e.key === "Escape" && (e.preventDefault(), this._cancelCommentPopup()), e.key === "Enter" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this._commitCommentPopup());
3261
3282
  }}></textarea>
3262
3283
  <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>
3284
+ <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${A("cancel")}</button>
3285
+ <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${A("save")}</button>
3265
3286
  </div>
3266
3287
  </div>
3267
3288
  `;
@@ -3297,7 +3318,7 @@ var q = {
3297
3318
  <div class="ft-filter-dropdown" @click=${(e) => e.stopPropagation()}>
3298
3319
  ${t === "boolean" ? this._renderBooleanFilter(e) : t === "number" ? this._renderNumberFilter(e) : t === "date" || t === "datetime" ? this._renderDateFilter(e) : this._renderTextFilter(e)}
3299
3320
  <div class="ft-filter-actions">
3300
- <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${k("clear")}</button>
3321
+ <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${A("clear")}</button>
3301
3322
  </div>
3302
3323
  </div>
3303
3324
  `;
@@ -3330,7 +3351,7 @@ var q = {
3330
3351
  let n = this._emptyFilterState.get(e) ?? "";
3331
3352
  return i`
3332
3353
  <div class="ft-filter-empty-row">
3333
- <label>${k("blankCells")}</label>
3354
+ <label>${A("blankCells")}</label>
3334
3355
  <select class="ft-filter-mode-select"
3335
3356
  .value=${n}
3336
3357
  @change=${(n) => {
@@ -3340,9 +3361,9 @@ var q = {
3340
3361
  @keydown=${(e) => {
3341
3362
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3342
3363
  }}>
3343
- <option value="">${k("blankAll")}</option>
3344
- <option value="empty">${k("emptyOnly")}</option>
3345
- <option value="non-empty">${k("nonEmptyOnly")}</option>
3364
+ <option value="">${A("blankAll")}</option>
3365
+ <option value="empty">${A("emptyOnly")}</option>
3366
+ <option value="non-empty">${A("nonEmptyOnly")}</option>
3346
3367
  </select>
3347
3368
  </div>
3348
3369
  `;
@@ -3418,13 +3439,13 @@ var q = {
3418
3439
  @keydown=${(e) => {
3419
3440
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3420
3441
  }}>
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>
3442
+ <option value="contains">${A("contains")}</option>
3443
+ <option value="starts">${A("startsWith")}</option>
3444
+ <option value="ends">${A("endsWith")}</option>
3445
+ <option value="wildcard">${A("wildcard")}</option>
3425
3446
  </select>
3426
3447
  </div>
3427
- <input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")}
3448
+ <input class="ft-filter-input" type="text" placeholder=${A("searchPlaceholder")}
3428
3449
  .value=${t.value}
3429
3450
  @input=${(t) => {
3430
3451
  let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
@@ -3475,15 +3496,15 @@ var q = {
3475
3496
  }}>
3476
3497
  ${Object.keys(q).map((e) => i`<option value=${e}>${q[e]}</option>`)}
3477
3498
  </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))}
3499
+ <input class="ft-filter-input ft-num-cond-input" type="text" inputmode="decimal" placeholder=${A("valuePlaceholder")}
3500
+ .value=${n.text ?? (n.value == null ? "" : P(n.value))}
3480
3501
  aria-invalid=${n.text && n.value == null ? "true" : "false"}
3481
3502
  @input=${(n) => {
3482
3503
  let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
3483
3504
  i[t] = {
3484
3505
  ...i[t],
3485
3506
  text: r,
3486
- value: r.trim() === "" ? null : f(r)
3507
+ value: r.trim() === "" ? null : h(r)
3487
3508
  }, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
3488
3509
  }}
3489
3510
  @keydown=${(e) => {
@@ -3538,13 +3559,13 @@ var q = {
3538
3559
  let t = e.type === "datetime" ? "datetime-local" : "date", n = this._dateFilterState.get(e.key) ?? {};
3539
3560
  return i`
3540
3561
  <div class="ft-filter-range">
3541
- <input class="ft-filter-input" type=${t} placeholder=${k("fromPlaceholder")}
3562
+ <input class="ft-filter-input" type=${t} placeholder=${A("fromPlaceholder")}
3542
3563
  .value=${n.from ?? ""}
3543
3564
  @input=${(t) => this._applyDateFilter(e.key, t, "from")}
3544
3565
  @keydown=${(e) => {
3545
3566
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3546
3567
  }}>
3547
- <input class="ft-filter-input" type=${t} placeholder=${k("toPlaceholder")}
3568
+ <input class="ft-filter-input" type=${t} placeholder=${A("toPlaceholder")}
3548
3569
  .value=${n.to ?? ""}
3549
3570
  @input=${(t) => this._applyDateFilter(e.key, t, "to")}
3550
3571
  @keydown=${(e) => {
@@ -3570,9 +3591,9 @@ var q = {
3570
3591
  @keydown=${(e) => {
3571
3592
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
3572
3593
  }}>
3573
- <option value="all">${k("all")}</option>
3574
- <option value="true">\u2714 ${k("booleanTrue")}</option>
3575
- <option value="false">\u2718 ${k("booleanFalse")}</option>
3594
+ <option value="all">${A("all")}</option>
3595
+ <option value="true">\u2714 ${A("booleanTrue")}</option>
3596
+ <option value="false">\u2718 ${A("booleanFalse")}</option>
3576
3597
  </select>
3577
3598
  ${this._renderEmptyFilterRow(e.key)}
3578
3599
  `;
@@ -3989,42 +4010,42 @@ var q = {
3989
4010
  this._closeFindPanel();
3990
4011
  return;
3991
4012
  }
3992
- e.key === "Enter" && !h(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
4013
+ e.key === "Enter" && !v(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
3993
4014
  }}>
3994
4015
  <div class="ft-find-row">
3995
- <input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")}
4016
+ <input class="ft-find-input" type="text" placeholder=${A("findPlaceholder")}
3996
4017
  .value=${t}
3997
4018
  @input=${(e) => {
3998
4019
  this._findState.query = e.target.value, this._findSearch();
3999
4020
  }}>
4000
4021
  <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) => {
4022
+ <button @click=${() => this._findPrev()} title=${A("findPrevious")}>◀</button>
4023
+ <button @click=${() => this._findNext()} title=${A("findNext")}>▶</button>
4024
+ <label title=${A("matchCase")}><input type="checkbox" ?checked=${r} @change=${(e) => {
4004
4025
  this._findState.matchCase = e.target.checked, this._findSearch();
4005
4026
  }}> Aa</label>
4006
- <label title=${k("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
4027
+ <label title=${A("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
4007
4028
  this._findState.wholeCell = e.target.checked, this._findSearch();
4008
4029
  }}> [ ]</label>
4009
- <button @click=${() => this._closeFindPanel()} title=${k("closeFind")}>✕</button>
4030
+ <button @click=${() => this._closeFindPanel()} title=${A("closeFind")}>✕</button>
4010
4031
  </div>
4011
4032
  ${e === "replace" ? i`
4012
4033
  <div class="ft-find-row">
4013
- <input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")}
4034
+ <input class="ft-find-replace-input" type="text" placeholder=${A("replaceWithPlaceholder")}
4014
4035
  .value=${n}
4015
4036
  @input=${(e) => {
4016
4037
  this._findState.replaceWith = e.target.value;
4017
4038
  }}>
4018
- <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${k("replace")}</button>
4019
- <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${k("replaceAll")}</button>
4039
+ <button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${A("replace")}</button>
4040
+ <button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${A("replaceAll")}</button>
4020
4041
  </div>
4021
4042
  ` : ""}
4022
4043
  </div>
4023
4044
  `;
4024
4045
  }
4025
4046
  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>`;
4047
+ 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;
4048
+ if (e.length === 0) return i`${t}${n}<div class="ft-empty">${A("noColumnsDefined")}</div>`;
4028
4049
  let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
4029
4050
  for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
4030
4051
  let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
@@ -4200,7 +4221,7 @@ var q = {
4200
4221
  ${this._renderEditor(e, t)}
4201
4222
  </div>
4202
4223
  `;
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 = [
4224
+ 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, C = [
4204
4225
  "ft-cell",
4205
4226
  `ft-type-${t.type ?? "text"}`,
4206
4227
  `ft-align-${G(t)}`,
@@ -4208,13 +4229,13 @@ var q = {
4208
4229
  l ? "ft-selected" : "",
4209
4230
  f ? "ft-pinned" : "",
4210
4231
  y ? "ft-invalid" : "",
4211
- C ? "ft-find-current" : S ? "ft-find-match" : "",
4232
+ S ? "ft-find-current" : x ? "ft-find-match" : "",
4212
4233
  o ? `ft-merge-${o.headParity}` : "",
4213
4234
  o?.continues ? "ft-merge-continued" : "",
4214
4235
  o?.opensDown ? "ft-merge-open" : ""
4215
4236
  ].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;
4216
4237
  return i`
4217
- <div class=${D ? w + " ft-has-comment" : w}
4238
+ <div class=${D ? C + " ft-has-comment" : C}
4218
4239
  role="gridcell"
4219
4240
  aria-colindex=${r + 1}
4220
4241
  data-col-index=${r}
@@ -4228,7 +4249,7 @@ var q = {
4228
4249
  @click=${(e) => this._onCellClickEvent(e, n, r)}
4229
4250
  @dblclick=${() => this._onCellDblClick(n, r)}>
4230
4251
  ${O}
4231
- ${x(e[t.key], e, t)}
4252
+ ${w(e[t.key], e, t)}
4232
4253
  </div>
4233
4254
  `;
4234
4255
  }
@@ -4237,28 +4258,22 @@ var q = {
4237
4258
  let n = e[t.key], r = n == null ? "" : String(n);
4238
4259
  if (t.type === "number") return i`
4239
4260
  <input class="ft-editor ft-editor-number" type="text" inputmode="decimal"
4240
- .value=${typeof n == "number" ? N(n) : r}
4261
+ .value=${typeof n == "number" ? P(n) : r}
4241
4262
  @keydown=${this._onEditorKeyDown}
4242
4263
  @blur=${() => this._commitEdit()}>
4243
4264
  `;
4244
- if (t.type === "date") {
4245
- let e = this._toDateInputValue(n);
4246
- return i`
4247
- <input class="ft-editor" type="date"
4248
- .value=${e}
4265
+ if (t.type === "date") return i`
4266
+ <input class="ft-editor ft-editor-date" type="text" inputmode="numeric" placeholder=${u()}
4267
+ .value=${ce(n)}
4249
4268
  @keydown=${this._onEditorKeyDown}
4250
4269
  @blur=${() => this._commitEdit()}>
4251
4270
  `;
4252
- }
4253
- if (t.type === "datetime") {
4254
- let e = this._toDateTimeInputValue(n);
4255
- return i`
4256
- <input class="ft-editor" type="datetime-local"
4257
- .value=${e}
4271
+ if (t.type === "datetime") return i`
4272
+ <input class="ft-editor ft-editor-datetime" type="text" placeholder=${`${u()} HH:mm`}
4273
+ .value=${le(n)}
4258
4274
  @keydown=${this._onEditorKeyDown}
4259
4275
  @blur=${() => this._commitEdit()}>
4260
4276
  `;
4261
- }
4262
4277
  if (t.type === "select" && t.options && t.options.length > 0) {
4263
4278
  let e = t.options, r = typeof e[0] == "string";
4264
4279
  return i`
@@ -4299,16 +4314,6 @@ var q = {
4299
4314
  @blur=${() => this._commitEdit()}>
4300
4315
  `;
4301
4316
  }
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
- _toDateTimeInputValue(e) {
4308
- if (!e) return "";
4309
- let t = e instanceof Date ? e : new Date(String(e));
4310
- return isNaN(t.getTime()) ? "" : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}T${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
4311
- }
4312
4317
  };
4313
4318
  K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4314
4319
  type: Array,
@@ -4366,4 +4371,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4366
4371
  attribute: "max-undo-size"
4367
4372
  })], $.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
4373
  //#endregion
4369
- export { A as a, j as i, G as n, O as o, B as r, x as s, $ as t };
4374
+ export { j as a, M as i, G as n, k as o, B as r, w as s, $ as t };
@@ -525,10 +525,6 @@ export declare class FlexTable extends LitElement {
525
525
  private _mergeState;
526
526
  private _renderCell;
527
527
  private _renderEditor;
528
- /** Convert value to YYYY-MM-DD for date input (local timezone) */
529
- private _toDateInputValue;
530
- /** Convert value to YYYY-MM-DDTHH:mm for datetime-local input (local timezone) */
531
- private _toDateTimeInputValue;
532
528
  }
533
529
  declare global {
534
530
  interface HTMLElementTagNameMap {
@@ -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-CZPubYVD.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' | 'notADateTime' | '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-CZPubYVD.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.2",
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.56.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. `datetime` cells edit as `YYYY-MM-DD HH:mm` (local) and store `YYYY-MM-DDTHH:mm`.
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