@iyulab/flex-table 0.37.0 → 0.38.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,49 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.38.1] - 2026-09-23
4
+
5
+ ### Fixed
6
+
7
+ - 🔴 **XLSX import no longer turns styled numbers into dates.** A number was read as a date whenever
8
+ its cell had any non-default style and its value fell between 1 and 73050 — so bold figures,
9
+ thousands separators, currency and percentage formats (most numbers in a real business
10
+ spreadsheet) came in as dates: a price of 12,450 became `1934-01-30`. Whether a number is a date
11
+ is now decided by the cell style's number format, read from `styles.xml`: the built-in date
12
+ formats, and custom formats whose code draws a day or a year (text in quotes, escaped characters
13
+ and bracketed sections such as `[Red]` or `[$-409]` are not counted). Time-only formats stay
14
+ numbers.
15
+ - 🔴 **Imported dates are no longer one day early.** The serial-to-date conversion subtracted a day,
16
+ so a date exported by the table and imported back came in as the day before.
17
+ - **Row drag and the fill handle hit the frozen row under the pointer while the table is
18
+ scrolled.** Frozen rows stay put as a sticky band, but both gestures added the scroll offset to
19
+ the pointer position everywhere, so over the band they pointed at the body row hidden behind
20
+ it: a row dropped onto a frozen row landed further down, and a fill dragged up into the band
21
+ stopped short of it. The drop indicator is drawn at the right place too.
22
+ - **XLSX import honors the 1904 date system** (`workbookPr date1904`, used by workbooks created on
23
+ a Mac), which otherwise shifts every date by four years.
24
+
25
+ ## [0.38.0] - 2026-09-23
26
+
27
+ ### Fixed
28
+
29
+ - 🔴 **Cell values follow the app's locale, not the browser's.** The built-in `number`, `date` and
30
+ `datetime` formatting called `toLocaleString()` without a locale, so values followed the runtime
31
+ default while the table's own menus and labels already followed `Locale`. An app set to Korean
32
+ and opened in an English browser showed Korean menus over `9/9/2026, 8:16:01 AM`. Values now go
33
+ through `@iyulab/components`' `formatDate`/`formatNumber`, which use `Locale.get()`, and the
34
+ numeric `format` patterns (`#,##0.00` and friends) use the same locale for their separators.
35
+ - **A date-only value such as `"2026-09-09"` is read as that local date.** It was parsed as UTC
36
+ midnight, so in timezones behind UTC a `date` column showed the previous day.
37
+
38
+ ### Changed
39
+
40
+ - 🔴 **The `@iyulab/components` peer range is now `>=1.27.0`** (was `>=1.24.0`). The formatters come
41
+ from that package's `format` module, which first shipped in 1.27.0; the old range admitted
42
+ versions without it.
43
+
44
+ ⚠ **Visible change:** if your app's `Locale` differs from the browser's language, dates and numbers in
45
+ the table now appear in the app's format. Nothing changes when the two agree.
46
+
3
47
  ## [0.37.0] - 2026-09-20
4
48
 
5
49
  ### Fixed
@@ -4,6 +4,12 @@
4
4
  * Supports string, number, boolean, and date cell types.
5
5
  */
6
6
  import type { ColumnDefinition, DataRow } from '../models/types.js';
7
+ export interface ZipFile {
8
+ name: string;
9
+ data: Uint8Array;
10
+ }
11
+ /** @internal 테스트가 실물에 가까운 통합 문서(스타일·1904 날짜 체계)를 조립하는 데 쓴다. */
12
+ export declare function buildZip(files: ZipFile[]): Uint8Array<ArrayBuffer>;
7
13
  /**
8
14
  * Build an XLSX file as a Uint8Array.
9
15
  */
@@ -906,80 +906,7 @@ var l = r`
906
906
  outline: 2px solid var(--ft-find-color);
907
907
  outline-offset: -2px;
908
908
  }
909
- `;
910
- //#endregion
911
- //#region src/renderers/format.ts
912
- function u(e, t) {
913
- return e == null ? "" : typeof t == "function" ? t(e) : d(t) ? p(e, t) : f(e, t);
914
- }
915
- function d(e) {
916
- return /[yMdHhms]/.test(e);
917
- }
918
- function f(e, t) {
919
- let n = typeof e == "number" ? e : Number(e);
920
- if (isNaN(n)) return String(e);
921
- let r = t.endsWith("%"), i = t.match(/^([^#0.,%]+)/), a = i ? i[1] : "", o = t.replace(/^[^#0.,%]+/, "").replace(/%$/, ""), s = o.match(/\.([0#]+)$/), c = s ? s[1].length : 0, l = {
922
- minimumFractionDigits: c,
923
- maximumFractionDigits: c,
924
- useGrouping: o.includes(",")
925
- }, u;
926
- return r ? u = new Intl.NumberFormat(void 0, {
927
- ...l,
928
- style: "percent"
929
- }).format(n) : (u = new Intl.NumberFormat(void 0, l).format(n), a && (u = a + u)), u + "";
930
- }
931
- function p(e, t) {
932
- let n;
933
- if (e instanceof Date) n = e;
934
- else if (typeof e == "string" || typeof e == "number") n = new Date(e);
935
- else return String(e);
936
- if (isNaN(n.getTime())) return String(e);
937
- let r = String(n.getFullYear()), i = r.slice(-2), a = String(n.getMonth() + 1).padStart(2, "0"), o = String(n.getDate()).padStart(2, "0"), s = String(n.getHours()).padStart(2, "0"), c = String(n.getHours() % 12 || 12).padStart(2, "0"), l = String(n.getMinutes()).padStart(2, "0"), u = String(n.getSeconds()).padStart(2, "0");
938
- return t.replace("yyyy", r).replace("yy", i).replace("MM", a).replace("dd", o).replace("HH", s).replace("hh", c).replace("mm", l).replace("ss", u);
939
- }
940
- //#endregion
941
- //#region src/renderers/cell-renderer.ts
942
- function m(e, t, n) {
943
- return n.renderer ? n.renderer(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : u(e, n.format) : h(e, n);
944
- }
945
- function h(e, t) {
946
- if (e == null) return "";
947
- switch (t.type) {
948
- case "number": return _(e);
949
- case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
950
- case "date": return v(e);
951
- case "datetime": return y(e);
952
- case "select": return g(e, t);
953
- default: return String(e);
954
- }
955
- }
956
- function g(e, t) {
957
- if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
958
- let n = t.options.find((t) => t.value === e);
959
- return n ? n.label : e == null ? "" : String(e);
960
- }
961
- function _(e) {
962
- return typeof e == "number" ? Number.isInteger(e) ? e.toLocaleString() : e.toLocaleString(void 0, { minimumFractionDigits: 1 }) : String(e);
963
- }
964
- function v(e) {
965
- if (e instanceof Date) return e.toLocaleDateString();
966
- if (typeof e == "string") {
967
- let t = new Date(e);
968
- return isNaN(t.getTime()) ? e : t.toLocaleDateString();
969
- }
970
- return String(e);
971
- }
972
- function y(e) {
973
- if (e instanceof Date) return e.toLocaleString();
974
- if (typeof e == "string") {
975
- let t = new Date(e);
976
- return isNaN(t.getTime()) ? e : t.toLocaleString();
977
- }
978
- return String(e);
979
- }
980
- //#endregion
981
- //#region node_modules/@iyulab/components/dist/utilities/Locale.js
982
- var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
909
+ `, u = new Map(Object.entries(/* #__PURE__ */ Object.assign({
983
910
  "../assets/locales/ar.json": {
984
911
  valueMissing: "هذا الحقل مطلوب",
985
912
  badInput: "يرجى إدخال قيمة صالحة",
@@ -1019,7 +946,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1019
946
  alertMessage: "رسالة",
1020
947
  remove: "إزالة",
1021
948
  closeTab: "إغلاق علامة التبويب",
1022
- breadcrumb: "مسار التنقل"
949
+ breadcrumb: "مسار التنقل",
950
+ confirm: "تأكيد",
951
+ cancel: "إلغاء"
1023
952
  },
1024
953
  "../assets/locales/de.json": {
1025
954
  valueMissing: "Dieses Feld ist erforderlich",
@@ -1060,7 +989,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1060
989
  alertMessage: "Nachricht",
1061
990
  remove: "Entfernen",
1062
991
  closeTab: "Tab schließen",
1063
- breadcrumb: "Navigationspfad"
992
+ breadcrumb: "Navigationspfad",
993
+ confirm: "Bestätigen",
994
+ cancel: "Abbrechen"
1064
995
  },
1065
996
  "../assets/locales/en.json": {
1066
997
  valueMissing: "This field is required",
@@ -1101,7 +1032,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1101
1032
  alertMessage: "Message",
1102
1033
  remove: "Remove",
1103
1034
  closeTab: "Close tab",
1104
- breadcrumb: "Breadcrumb"
1035
+ breadcrumb: "Breadcrumb",
1036
+ confirm: "Confirm",
1037
+ cancel: "Cancel"
1105
1038
  },
1106
1039
  "../assets/locales/es.json": {
1107
1040
  valueMissing: "Este campo es obligatorio",
@@ -1142,7 +1075,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1142
1075
  alertMessage: "Mensaje",
1143
1076
  remove: "Quitar",
1144
1077
  closeTab: "Cerrar pestaña",
1145
- breadcrumb: "Ruta de navegación"
1078
+ breadcrumb: "Ruta de navegación",
1079
+ confirm: "Confirmar",
1080
+ cancel: "Cancelar"
1146
1081
  },
1147
1082
  "../assets/locales/fr.json": {
1148
1083
  valueMissing: "Ce champ est obligatoire",
@@ -1183,7 +1118,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1183
1118
  alertMessage: "Message",
1184
1119
  remove: "Supprimer",
1185
1120
  closeTab: "Fermer l'onglet",
1186
- breadcrumb: "Fil d'Ariane"
1121
+ breadcrumb: "Fil d'Ariane",
1122
+ confirm: "Confirmer",
1123
+ cancel: "Annuler"
1187
1124
  },
1188
1125
  "../assets/locales/id.json": {
1189
1126
  valueMissing: "Kolom ini wajib diisi",
@@ -1224,7 +1161,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1224
1161
  alertMessage: "Pesan",
1225
1162
  remove: "Hapus",
1226
1163
  closeTab: "Tutup tab",
1227
- breadcrumb: "Navigasi remah roti"
1164
+ breadcrumb: "Navigasi remah roti",
1165
+ confirm: "Konfirmasi",
1166
+ cancel: "Batal"
1228
1167
  },
1229
1168
  "../assets/locales/ja.json": {
1230
1169
  valueMissing: "この項目は必須です",
@@ -1265,7 +1204,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1265
1204
  alertMessage: "メッセージ",
1266
1205
  remove: "削除",
1267
1206
  closeTab: "タブを閉じる",
1268
- breadcrumb: "パンくずリスト"
1207
+ breadcrumb: "パンくずリスト",
1208
+ confirm: "OK",
1209
+ cancel: "キャンセル"
1269
1210
  },
1270
1211
  "../assets/locales/ko.json": {
1271
1212
  valueMissing: "필수 항목입니다",
@@ -1306,7 +1247,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1306
1247
  alertMessage: "메시지",
1307
1248
  remove: "제거",
1308
1249
  closeTab: "탭 닫기",
1309
- breadcrumb: "탐색 경로"
1250
+ breadcrumb: "탐색 경로",
1251
+ confirm: "확인",
1252
+ cancel: "취소"
1310
1253
  },
1311
1254
  "../assets/locales/pt-BR.json": {
1312
1255
  valueMissing: "Este campo é obrigatório",
@@ -1347,7 +1290,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1347
1290
  alertMessage: "Mensagem",
1348
1291
  remove: "Remover",
1349
1292
  closeTab: "Fechar aba",
1350
- breadcrumb: "Trilha de navegação"
1293
+ breadcrumb: "Trilha de navegação",
1294
+ confirm: "Confirmar",
1295
+ cancel: "Cancelar"
1351
1296
  },
1352
1297
  "../assets/locales/ru.json": {
1353
1298
  valueMissing: "Это поле обязательно для заполнения",
@@ -1388,7 +1333,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1388
1333
  alertMessage: "Сообщение",
1389
1334
  remove: "Удалить",
1390
1335
  closeTab: "Закрыть вкладку",
1391
- breadcrumb: "Навигационная цепочка"
1336
+ breadcrumb: "Навигационная цепочка",
1337
+ confirm: "Подтвердить",
1338
+ cancel: "Отмена"
1392
1339
  },
1393
1340
  "../assets/locales/th.json": {
1394
1341
  valueMissing: "จำเป็นต้องกรอกข้อมูลนี้",
@@ -1429,7 +1376,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1429
1376
  alertMessage: "ข้อความ",
1430
1377
  remove: "ลบ",
1431
1378
  closeTab: "ปิดแท็บ",
1432
- breadcrumb: "เส้นทางการนำทาง"
1379
+ breadcrumb: "เส้นทางการนำทาง",
1380
+ confirm: "ยืนยัน",
1381
+ cancel: "ยกเลิก"
1433
1382
  },
1434
1383
  "../assets/locales/vi.json": {
1435
1384
  valueMissing: "Trường này là bắt buộc",
@@ -1470,7 +1419,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1470
1419
  alertMessage: "Thông báo",
1471
1420
  remove: "Xóa",
1472
1421
  closeTab: "Đóng tab",
1473
- breadcrumb: "Đường dẫn điều hướng"
1422
+ breadcrumb: "Đường dẫn điều hướng",
1423
+ confirm: "Xác nhận",
1424
+ cancel: "Hủy"
1474
1425
  },
1475
1426
  "../assets/locales/zh-CN.json": {
1476
1427
  valueMissing: "此项为必填项",
@@ -1511,7 +1462,9 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1511
1462
  alertMessage: "消息",
1512
1463
  remove: "移除",
1513
1464
  closeTab: "关闭标签页",
1514
- breadcrumb: "面包屑导航"
1465
+ breadcrumb: "面包屑导航",
1466
+ confirm: "确定",
1467
+ cancel: "取消"
1515
1468
  },
1516
1469
  "../assets/locales/zh-TW.json": {
1517
1470
  valueMissing: "此欄位為必填",
@@ -1552,14 +1505,16 @@ var b = new Map(Object.entries(/* #__PURE__ */ Object.assign({
1552
1505
  alertMessage: "訊息",
1553
1506
  remove: "移除",
1554
1507
  closeTab: "關閉分頁",
1555
- breadcrumb: "麵包屑導覽"
1508
+ breadcrumb: "麵包屑導覽",
1509
+ confirm: "確定",
1510
+ cancel: "取消"
1556
1511
  }
1557
- })).map(([e, t]) => [(e.split("/").pop()?.replace(".json", "") || "").toLowerCase(), t])), x = /* @__PURE__ */ new Map();
1558
- function S() {
1512
+ })).map(([e, t]) => [(e.split("/").pop()?.replace(".json", "") || "").toLowerCase(), t])), d = /* @__PURE__ */ new Map();
1513
+ function f() {
1559
1514
  return typeof document < "u" && document.documentElement?.lang ? document.documentElement.lang : typeof window < "u" && typeof navigator < "u" && navigator.language ? navigator.language : "en";
1560
1515
  }
1561
- var C = S();
1562
- function w(e) {
1516
+ var p = f();
1517
+ function m(e) {
1563
1518
  let t = e.toLowerCase(), n = t.split("-")[0];
1564
1519
  return n === t ? [t, "en"] : [
1565
1520
  t,
@@ -1567,55 +1522,142 @@ function w(e) {
1567
1522
  "en"
1568
1523
  ];
1569
1524
  }
1570
- function T(e, t) {
1525
+ function h(e, t) {
1571
1526
  return t ? e.replace(/\{(\w+)\}/g, (e, n) => t[n] == null ? `{${n}}` : String(t[n])) : e;
1572
1527
  }
1573
- function E(e, t) {
1574
- for (let n of w(e)) {
1575
- let e = x.get(n)?.[t] ?? b.get(n)?.[t];
1528
+ function g(e, t) {
1529
+ for (let n of m(e)) {
1530
+ let e = d.get(n)?.[t] ?? u.get(n)?.[t];
1576
1531
  if (e) return e;
1577
1532
  }
1578
- return b.get("en")[t];
1533
+ return u.get("en")[t];
1579
1534
  }
1580
- var D = /* @__PURE__ */ new Map(), O = class {
1535
+ var _ = /* @__PURE__ */ new Map(), v = class {
1581
1536
  constructor() {}
1582
1537
  static set(e) {
1583
- C = e;
1538
+ p = e;
1584
1539
  }
1585
1540
  static get() {
1586
- return C;
1541
+ return p;
1587
1542
  }
1588
1543
  static register(e, t) {
1589
- let n = e.toLowerCase(), r = x.get(n) ?? b.get(n) ?? b.get("en");
1590
- x.set(n, {
1544
+ let n = e.toLowerCase(), r = d.get(n) ?? u.get(n) ?? u.get("en");
1545
+ d.set(n, {
1591
1546
  ...r,
1592
1547
  ...t
1593
1548
  });
1594
1549
  }
1595
1550
  static getValue(e, t) {
1596
- return T(E(C, e), t);
1551
+ return h(g(p, e), t);
1597
1552
  }
1598
1553
  static namespace(e) {
1599
1554
  return {
1600
1555
  name: e,
1601
1556
  register(t, n) {
1602
- let r = D.get(e) ?? /* @__PURE__ */ new Map(), i = t.toLowerCase();
1557
+ let r = _.get(e) ?? /* @__PURE__ */ new Map(), i = t.toLowerCase();
1603
1558
  r.set(i, {
1604
1559
  ...r.get(i),
1605
1560
  ...n
1606
- }), D.set(e, r);
1561
+ }), _.set(e, r);
1607
1562
  },
1608
1563
  text(t, n) {
1609
- let r = D.get(e);
1610
- for (let e of w(C)) {
1564
+ let r = _.get(e);
1565
+ for (let e of m(p)) {
1611
1566
  let i = r?.get(e)?.[t];
1612
- if (i) return T(i, n);
1567
+ if (i) return h(i, n);
1613
1568
  }
1614
1569
  return t;
1615
1570
  }
1616
1571
  };
1617
1572
  }
1618
- }.namespace("flex-table");
1573
+ };
1574
+ //#endregion
1575
+ //#region src/renderers/format.ts
1576
+ function y(e, t) {
1577
+ return e == null ? "" : typeof t == "function" ? t(e) : b(t) ? S(e, t) : x(e, t);
1578
+ }
1579
+ function b(e) {
1580
+ return /[yMdHhms]/.test(e);
1581
+ }
1582
+ function x(e, t) {
1583
+ let n = typeof e == "number" ? e : Number(e);
1584
+ if (isNaN(n)) return String(e);
1585
+ let r = t.endsWith("%"), i = t.match(/^([^#0.,%]+)/), a = i ? i[1] : "", o = t.replace(/^[^#0.,%]+/, "").replace(/%$/, ""), s = o.match(/\.([0#]+)$/), c = s ? s[1].length : 0, l = {
1586
+ minimumFractionDigits: c,
1587
+ maximumFractionDigits: c,
1588
+ useGrouping: o.includes(",")
1589
+ }, u;
1590
+ return r ? u = new Intl.NumberFormat(v.get(), {
1591
+ ...l,
1592
+ style: "percent"
1593
+ }).format(n) : (u = new Intl.NumberFormat(v.get(), l).format(n), a && (u = a + u)), u + "";
1594
+ }
1595
+ function S(e, t) {
1596
+ let n;
1597
+ if (e instanceof Date) n = e;
1598
+ else if (typeof e == "string" || typeof e == "number") n = new Date(e);
1599
+ else return String(e);
1600
+ if (isNaN(n.getTime())) return String(e);
1601
+ let r = String(n.getFullYear()), i = r.slice(-2), a = String(n.getMonth() + 1).padStart(2, "0"), o = String(n.getDate()).padStart(2, "0"), s = String(n.getHours()).padStart(2, "0"), c = String(n.getHours() % 12 || 12).padStart(2, "0"), l = String(n.getMinutes()).padStart(2, "0"), u = String(n.getSeconds()).padStart(2, "0");
1602
+ return t.replace("yyyy", r).replace("yy", i).replace("MM", a).replace("dd", o).replace("HH", s).replace("hh", c).replace("mm", l).replace("ss", u);
1603
+ }
1604
+ //#endregion
1605
+ //#region node_modules/@iyulab/components/dist/utilities/format.js
1606
+ function C(e) {
1607
+ let [t, n, r] = e.split("-").map(Number);
1608
+ return Number.isNaN(t) || Number.isNaN(n) || Number.isNaN(r) ? new Date(e) : new Date(t, n - 1, r);
1609
+ }
1610
+ function w(e) {
1611
+ return typeof e == "string" ? C(e) : e;
1612
+ }
1613
+ function T(e, t, n) {
1614
+ return new Intl.NumberFormat(n ?? v.get(), t).format(e);
1615
+ }
1616
+ function E(e, t, n) {
1617
+ let r = w(e);
1618
+ return Number.isNaN(r.getTime()) ? String(e) : new Intl.DateTimeFormat(n ?? v.get(), t).format(r);
1619
+ }
1620
+ //#endregion
1621
+ //#region src/renderers/cell-renderer.ts
1622
+ function D(e, t, n) {
1623
+ return n.renderer ? n.renderer(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : y(e, n.format) : ee(e, n);
1624
+ }
1625
+ function ee(e, t) {
1626
+ if (e == null) return "";
1627
+ switch (t.type) {
1628
+ case "number": return re(e);
1629
+ case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
1630
+ case "date": return ie(e);
1631
+ case "datetime": return ae(e);
1632
+ case "select": return te(e, t);
1633
+ default: return String(e);
1634
+ }
1635
+ }
1636
+ function te(e, t) {
1637
+ if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
1638
+ let n = t.options.find((t) => t.value === e);
1639
+ return n ? n.label : e == null ? "" : String(e);
1640
+ }
1641
+ var ne = {
1642
+ year: "numeric",
1643
+ month: "numeric",
1644
+ day: "numeric",
1645
+ hour: "numeric",
1646
+ minute: "numeric",
1647
+ second: "numeric"
1648
+ };
1649
+ function re(e) {
1650
+ return typeof e == "number" ? Number.isInteger(e) ? T(e) : T(e, { minimumFractionDigits: 1 }) : String(e);
1651
+ }
1652
+ function ie(e) {
1653
+ return e instanceof Date || typeof e == "string" ? E(e) : String(e);
1654
+ }
1655
+ function ae(e) {
1656
+ return e instanceof Date || typeof e == "string" ? E(e, ne) : String(e);
1657
+ }
1658
+ //#endregion
1659
+ //#region src/locale.ts
1660
+ var O = v.namespace("flex-table");
1619
1661
  O.register("en", {
1620
1662
  showHiddenColumns: "Show hidden column(s)",
1621
1663
  columnMenu: "Column menu",
@@ -1726,7 +1768,7 @@ O.register("en", {
1726
1768
  var k = (e, t) => O.text(e, t);
1727
1769
  //#endregion
1728
1770
  //#region src/core/selection.ts
1729
- function ee(e) {
1771
+ function oe(e) {
1730
1772
  return {
1731
1773
  startRow: Math.min(e.startRow, e.endRow),
1732
1774
  startCol: Math.min(e.startCol, e.endCol),
@@ -1734,7 +1776,7 @@ function ee(e) {
1734
1776
  endCol: Math.max(e.startCol, e.endCol)
1735
1777
  };
1736
1778
  }
1737
- var te = class {
1779
+ var se = class {
1738
1780
  constructor() {
1739
1781
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
1740
1782
  }
@@ -1761,7 +1803,7 @@ var te = class {
1761
1803
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
1762
1804
  row: e,
1763
1805
  col: t
1764
- }, this.rangeAnchor && (this.range = ee({
1806
+ }, this.rangeAnchor && (this.range = oe({
1765
1807
  startRow: this.rangeAnchor.row,
1766
1808
  startCol: this.rangeAnchor.col,
1767
1809
  endRow: e,
@@ -1832,7 +1874,7 @@ var te = class {
1832
1874
  shiftMoveRight() {
1833
1875
  return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
1834
1876
  }
1835
- }, ne = class {
1877
+ }, A = class {
1836
1878
  constructor() {
1837
1879
  this.current = null;
1838
1880
  }
@@ -1853,7 +1895,7 @@ var te = class {
1853
1895
  let e = this.current;
1854
1896
  return this.current = null, e;
1855
1897
  }
1856
- }, A = class {
1898
+ }, j = class {
1857
1899
  constructor() {
1858
1900
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
1859
1901
  }
@@ -1914,7 +1956,7 @@ var te = class {
1914
1956
  };
1915
1957
  //#endregion
1916
1958
  //#region src/core/filtering.ts
1917
- function j(e, t, n) {
1959
+ function ce(e, t, n) {
1918
1960
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
1919
1961
  let r = [];
1920
1962
  for (let i = 0; i < e.length; i++) {
@@ -1933,9 +1975,9 @@ function j(e, t, n) {
1933
1975
  }
1934
1976
  //#endregion
1935
1977
  //#region src/core/undo.ts
1936
- var re = 100, M = class {
1978
+ var le = 100, M = class {
1937
1979
  constructor() {
1938
- this._undoStack = [], this._redoStack = [], this._maxSize = re;
1980
+ this._undoStack = [], this._redoStack = [], this._maxSize = le;
1939
1981
  }
1940
1982
  get maxSize() {
1941
1983
  return this._maxSize;
@@ -1972,7 +2014,7 @@ var re = 100, M = class {
1972
2014
  };
1973
2015
  //#endregion
1974
2016
  //#region src/clipboard/clipboard.ts
1975
- function ie(e, t, n) {
2017
+ function ue(e, t, n) {
1976
2018
  let r = [];
1977
2019
  for (let i = n.startRow; i <= n.endRow; i++) {
1978
2020
  let a = e[i], o = [];
@@ -2027,7 +2069,7 @@ function P(e, t) {
2027
2069
  }
2028
2070
  //#endregion
2029
2071
  //#region src/export/xlsx-writer.ts
2030
- var ae = (() => {
2072
+ var de = (() => {
2031
2073
  let e = /* @__PURE__ */ new Uint32Array(256);
2032
2074
  for (let t = 0; t < 256; t++) {
2033
2075
  let n = t;
@@ -2036,16 +2078,16 @@ var ae = (() => {
2036
2078
  }
2037
2079
  return e;
2038
2080
  })();
2039
- function oe(e) {
2081
+ function fe(e) {
2040
2082
  let t = 4294967295;
2041
- for (let n = 0; n < e.length; n++) t = ae[(t ^ e[n]) & 255] ^ t >>> 8;
2083
+ for (let n = 0; n < e.length; n++) t = de[(t ^ e[n]) & 255] ^ t >>> 8;
2042
2084
  return (t ^ 4294967295) >>> 0;
2043
2085
  }
2044
2086
  var F = new TextEncoder();
2045
- function se(e) {
2087
+ function pe(e) {
2046
2088
  let t = [], n = [], r = 0;
2047
2089
  for (let i of e) {
2048
- let e = F.encode(i.name), a = oe(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
2090
+ let e = F.encode(i.name), a = fe(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
2049
2091
  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);
2050
2092
  let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
2051
2093
  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;
@@ -2065,27 +2107,27 @@ function I(e) {
2065
2107
  function L(e) {
2066
2108
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2067
2109
  }
2068
- function ce(e) {
2110
+ function R(e) {
2069
2111
  let t = "";
2070
2112
  for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
2071
2113
  return t;
2072
2114
  }
2073
- function R(e, t) {
2074
- return ce(t) + (e + 1);
2115
+ function z(e, t) {
2116
+ return R(t) + (e + 1);
2075
2117
  }
2076
- function le(e) {
2118
+ function B(e) {
2077
2119
  let t = Date.UTC(1899, 11, 30);
2078
2120
  return (e.getTime() - t) / 864e5;
2079
2121
  }
2080
- var ue = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", de = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", fe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">\n <sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>\n</workbook>", z = "<?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>", B = "<?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>";
2081
- function V(e, t) {
2082
- let n = [], r = t.map((e, t) => `<c r="${R(0, t)}" t="str" s="2"><v>${L(e.header)}</v></c>`);
2122
+ var me = "<?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>";
2123
+ function ye(e, t) {
2124
+ let n = [], r = t.map((e, t) => `<c r="${z(0, t)}" t="str" s="2"><v>${L(e.header)}</v></c>`);
2083
2125
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
2084
2126
  let i = t.map((t, n) => {
2085
- let i = R(r + 1, n), a = e[t.key];
2127
+ let i = z(r + 1, n), a = e[t.key];
2086
2128
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
2087
2129
  let o = t.type ?? "text";
2088
- return o === "number" && typeof a == "number" ? `<c r="${i}"><v>${a}</v></c>` : (o === "date" || o === "datetime") && a instanceof Date ? `<c r="${i}" s="1"><v>${le(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${L(String(a))}</v></c>`;
2130
+ 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>${B(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>`;
2089
2131
  });
2090
2132
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
2091
2133
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -2093,24 +2135,24 @@ function V(e, t) {
2093
2135
  <sheetData>${n.join("")}</sheetData>
2094
2136
  </worksheet>`;
2095
2137
  }
2096
- function pe(e, t) {
2097
- let n = V(e, t);
2098
- return se([
2138
+ function be(e, t) {
2139
+ let n = ye(e, t);
2140
+ return pe([
2099
2141
  {
2100
2142
  name: "[Content_Types].xml",
2101
- data: F.encode(ue)
2143
+ data: F.encode(me)
2102
2144
  },
2103
2145
  {
2104
2146
  name: "_rels/.rels",
2105
- data: F.encode(de)
2147
+ data: F.encode(he)
2106
2148
  },
2107
2149
  {
2108
2150
  name: "xl/workbook.xml",
2109
- data: F.encode(fe)
2151
+ data: F.encode(ge)
2110
2152
  },
2111
2153
  {
2112
2154
  name: "xl/_rels/workbook.xml.rels",
2113
- data: F.encode(z)
2155
+ data: F.encode(_e)
2114
2156
  },
2115
2157
  {
2116
2158
  name: "xl/worksheets/sheet1.xml",
@@ -2118,30 +2160,30 @@ function pe(e, t) {
2118
2160
  },
2119
2161
  {
2120
2162
  name: "xl/styles.xml",
2121
- data: F.encode(B)
2163
+ data: F.encode(ve)
2122
2164
  }
2123
2165
  ]);
2124
2166
  }
2125
2167
  //#endregion
2126
2168
  //#region src/export/export.ts
2127
- function H(e, t, n) {
2169
+ function V(e, t, n) {
2128
2170
  switch (n) {
2129
- case "csv": return U(e, t, ",");
2130
- case "tsv": return U(e, t, " ");
2131
- case "json": return he(e, t);
2132
- case "xlsx": return pe(e, t);
2171
+ case "csv": return H(e, t, ",");
2172
+ case "tsv": return H(e, t, " ");
2173
+ case "json": return Se(e, t);
2174
+ case "xlsx": return be(e, t);
2133
2175
  }
2134
2176
  }
2135
- function me(e, t) {
2177
+ function xe(e, t) {
2136
2178
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
2137
2179
  }
2138
- function U(e, t, n) {
2139
- return [t.map((e) => W(e.header, n)).join(n), ...e.map((e) => t.map((t) => W(me(e[t.key], t), n)).join(n))].join("\n");
2180
+ function H(e, t, n) {
2181
+ return [t.map((e) => U(e.header, n)).join(n), ...e.map((e) => t.map((t) => U(xe(e[t.key], t), n)).join(n))].join("\n");
2140
2182
  }
2141
- function W(e, t) {
2183
+ function U(e, t) {
2142
2184
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
2143
2185
  }
2144
- function he(e, t) {
2186
+ function Se(e, t) {
2145
2187
  let n = e.map((e) => {
2146
2188
  let n = {};
2147
2189
  for (let r of t) {
@@ -2152,35 +2194,35 @@ function he(e, t) {
2152
2194
  });
2153
2195
  return JSON.stringify(n, null, 2);
2154
2196
  }
2155
- function ge(e, t, n) {
2197
+ function Ce(e, t, n) {
2156
2198
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
2157
2199
  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);
2158
2200
  }
2159
- var _e = {
2201
+ var we = {
2160
2202
  csv: "text/csv;charset=utf-8",
2161
2203
  tsv: "text/tab-separated-values;charset=utf-8",
2162
2204
  json: "application/json;charset=utf-8",
2163
2205
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
2164
- }, ve = {
2206
+ }, Te = {
2165
2207
  csv: ".csv",
2166
2208
  tsv: ".tsv",
2167
2209
  json: ".json",
2168
2210
  xlsx: ".xlsx"
2169
2211
  };
2170
- function ye(e) {
2171
- return _e[e];
2212
+ function Ee(e) {
2213
+ return we[e];
2172
2214
  }
2173
- function be(e) {
2174
- return ve[e];
2215
+ function De(e) {
2216
+ return Te[e];
2175
2217
  }
2176
2218
  //#endregion
2177
2219
  //#region src/export/xlsx-reader.ts
2178
- function xe(e) {
2220
+ function Oe(e) {
2179
2221
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
2180
2222
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
2181
2223
  }
2182
- function Se(e) {
2183
- let t = xe(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
2224
+ function ke(e) {
2225
+ let t = Oe(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
2184
2226
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
2185
2227
  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));
2186
2228
  a.push({
@@ -2193,7 +2235,7 @@ function Se(e) {
2193
2235
  }
2194
2236
  return a;
2195
2237
  }
2196
- async function Ce(e) {
2238
+ async function Ae(e) {
2197
2239
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
2198
2240
  n.write(e), n.close();
2199
2241
  let i = [];
@@ -2206,69 +2248,107 @@ async function Ce(e) {
2206
2248
  for (let e of i) o.set(e, s), s += e.length;
2207
2249
  return o;
2208
2250
  }
2209
- async function we(e, t) {
2251
+ async function je(e, t) {
2210
2252
  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);
2211
2253
  if (t.compressionMethod === 0) return o.slice();
2212
- if (t.compressionMethod === 8) return Ce(o);
2254
+ if (t.compressionMethod === 8) return Ae(o);
2213
2255
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
2214
2256
  }
2215
- async function Te(e) {
2216
- let t = new DataView(e), n = Se(t), r = /* @__PURE__ */ new Map();
2217
- for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await we(t, e));
2257
+ async function Me(e) {
2258
+ let t = new DataView(e), n = ke(t), r = /* @__PURE__ */ new Map();
2259
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await je(t, e));
2218
2260
  return r;
2219
2261
  }
2220
- var Ee = new TextDecoder("utf-8");
2221
- function G(e) {
2222
- let t = Ee.decode(e);
2262
+ var Ne = new TextDecoder("utf-8");
2263
+ function W(e) {
2264
+ let t = Ne.decode(e);
2223
2265
  return new DOMParser().parseFromString(t, "application/xml");
2224
2266
  }
2225
- function De(e) {
2267
+ function Pe(e) {
2226
2268
  if (!e) return [];
2227
- let t = G(e);
2269
+ let t = W(e);
2228
2270
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
2229
2271
  }
2230
- function Oe(e) {
2231
- let t = (e - 1) * 864e5 + Date.UTC(1899, 11, 30);
2232
- return new Date(t).toISOString().slice(0, 10);
2272
+ var Fe = /* @__PURE__ */ new Set([
2273
+ 14,
2274
+ 15,
2275
+ 16,
2276
+ 17,
2277
+ 22,
2278
+ 27,
2279
+ 28,
2280
+ 29,
2281
+ 30,
2282
+ 31,
2283
+ 36,
2284
+ 50,
2285
+ 51,
2286
+ 52,
2287
+ 53,
2288
+ 54,
2289
+ 57,
2290
+ 58
2291
+ ]);
2292
+ function Ie(e) {
2293
+ let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
2294
+ return /[dy]/i.test(t);
2233
2295
  }
2234
- function ke(e, t) {
2235
- let n = G(e).querySelectorAll("row");
2236
- if (n.length === 0) return [];
2237
- let r = 0, i = /* @__PURE__ */ new Map();
2238
- for (let e of n) {
2239
- let n = parseInt(e.getAttribute("r") ?? "1", 10) - 1, a = /* @__PURE__ */ new Map();
2240
- i.set(n, a);
2241
- for (let n of e.querySelectorAll("c")) {
2242
- let e = Ae(n.getAttribute("r") ?? "");
2243
- e > r && (r = e);
2244
- let i = n.getAttribute("t") ?? "", o = n.getAttribute("s") ?? "", s = n.querySelector("v")?.textContent ?? "", c = n.querySelector("is > t")?.textContent ?? null, l;
2245
- if (i === "s") l = t[parseInt(s, 10)] ?? "";
2246
- else if (i === "str" || i === "inlineStr") l = c ?? s;
2247
- else if (i === "b") l = s === "1" ? "true" : "false";
2248
- else if (s === "") l = "";
2296
+ function Le(e) {
2297
+ let t = /* @__PURE__ */ new Set();
2298
+ if (!e) return t;
2299
+ let n = W(e), r = /* @__PURE__ */ new Map();
2300
+ for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
2301
+ return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
2302
+ let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
2303
+ (a === void 0 ? Fe.has(i) : Ie(a)) && t.add(n);
2304
+ }), t;
2305
+ }
2306
+ function Re(e) {
2307
+ if (!e) return !1;
2308
+ let t = W(e).querySelector("workbookPr")?.getAttribute("date1904");
2309
+ return t === "1" || t === "true";
2310
+ }
2311
+ function ze(e, t) {
2312
+ return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
2313
+ }
2314
+ function Be(e, t, n, r) {
2315
+ let i = W(e).querySelectorAll("row");
2316
+ if (i.length === 0) return [];
2317
+ let a = 0, o = /* @__PURE__ */ new Map();
2318
+ for (let e of i) {
2319
+ let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
2320
+ o.set(i, s);
2321
+ for (let i of e.querySelectorAll("c")) {
2322
+ let e = Ve(i.getAttribute("r") ?? "");
2323
+ e > a && (a = e);
2324
+ let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
2325
+ if (o === "s") d = t[parseInt(l, 10)] ?? "";
2326
+ else if (o === "str" || o === "inlineStr") d = u ?? l;
2327
+ else if (o === "b") d = l === "1" ? "true" : "false";
2328
+ else if (l === "") d = "";
2249
2329
  else {
2250
- let e = parseFloat(s);
2251
- l = !isNaN(e) && o !== "" && parseInt(o, 10) > 0 && e >= 1 && e <= 73050 ? Oe(e) : s;
2330
+ let e = parseFloat(l);
2331
+ d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? ze(e, r) : l;
2252
2332
  }
2253
- a.set(e, l);
2333
+ s.set(e, d);
2254
2334
  }
2255
2335
  }
2256
- if (i.size === 0) return [];
2257
- let a = Math.max(...i.keys()), o = [];
2258
- for (let e = 0; e <= a; e++) {
2259
- let t = i.get(e) ?? /* @__PURE__ */ new Map(), n = [];
2260
- for (let e = 0; e <= r; e++) n.push(t.get(e) ?? "");
2261
- o.push(n);
2336
+ if (o.size === 0) return [];
2337
+ let s = Math.max(...o.keys()), c = [];
2338
+ for (let e = 0; e <= s; e++) {
2339
+ let t = o.get(e) ?? /* @__PURE__ */ new Map(), n = [];
2340
+ for (let e = 0; e <= a; e++) n.push(t.get(e) ?? "");
2341
+ c.push(n);
2262
2342
  }
2263
- return o;
2343
+ return c;
2264
2344
  }
2265
- function Ae(e) {
2345
+ function Ve(e) {
2266
2346
  let t = 0, n = 0;
2267
2347
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
2268
2348
  return t - 1;
2269
2349
  }
2270
- async function je(e) {
2271
- let t = await Te(e), n = De(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
2350
+ async function G(e) {
2351
+ let t = await Me(e), n = Pe(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
2272
2352
  if (!r) {
2273
2353
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
2274
2354
  r = n;
@@ -2276,13 +2356,13 @@ async function je(e) {
2276
2356
  }
2277
2357
  }
2278
2358
  if (!r) throw Error("XLSX: No worksheet found");
2279
- let i = ke(r, n);
2280
- return i.length === 0 ? {
2359
+ let i = Le(t.get("xl/styles.xml")), a = Re(t.get("xl/workbook.xml")), o = Be(r, n, i, a);
2360
+ return o.length === 0 ? {
2281
2361
  headers: [],
2282
2362
  rows: []
2283
2363
  } : {
2284
- headers: i[0],
2285
- rows: i.slice(1)
2364
+ headers: o[0],
2365
+ rows: o.slice(1)
2286
2366
  };
2287
2367
  }
2288
2368
  //#endregion
@@ -2302,9 +2382,9 @@ var q = {
2302
2382
  lt: "<",
2303
2383
  gte: "≥",
2304
2384
  lte: "≤"
2305
- }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Me = 200, $ = class extends n {
2385
+ }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, He = 200, $ = class extends n {
2306
2386
  constructor(...e) {
2307
- 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 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 = () => {
2387
+ 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 se(), this._editing = new A(), 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 = () => {
2308
2388
  this._commitCommentPopup();
2309
2389
  }, 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();
2310
2390
  }
@@ -2669,12 +2749,12 @@ var q = {
2669
2749
  if (!t) return "";
2670
2750
  let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
2671
2751
  for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
2672
- return H(r, n, e);
2752
+ return V(r, n, e);
2673
2753
  }
2674
- return H(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2754
+ return V(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2675
2755
  }
2676
2756
  exportToFile(e, t) {
2677
- ge(this.exportToString(e), t ?? `export${be(e)}`, ye(e));
2757
+ Ce(this.exportToString(e), t ?? `export${De(e)}`, Ee(e));
2678
2758
  }
2679
2759
  setComment(e, t, n) {
2680
2760
  let r = this.getComment(e, t);
@@ -2731,7 +2811,7 @@ var q = {
2731
2811
  async importFromFile(e) {
2732
2812
  let t = e.name.toLowerCase();
2733
2813
  if (t.endsWith(".xlsx")) {
2734
- let t = await je(await e.arrayBuffer());
2814
+ let t = await G(await e.arrayBuffer());
2735
2815
  this._applyImportedSheet(t);
2736
2816
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
2737
2817
  let t = N(await e.text());
@@ -2838,6 +2918,14 @@ var q = {
2838
2918
  get frozenRowsHeight() {
2839
2919
  return this._frozenRowCount * this.rowHeight;
2840
2920
  }
2921
+ _rowSpaceY(e) {
2922
+ let t = e - this.getBoundingClientRect().top - this.headerHeight;
2923
+ return t < this.frozenRowsHeight ? t : t + this._scrollTop;
2924
+ }
2925
+ _rowBoundaryViewportY(e) {
2926
+ let t = this.headerHeight + e * this.rowHeight;
2927
+ return e <= this._frozenRowCount ? t : Math.max(this.headerHeight + this.frozenRowsHeight, t - this._scrollTop);
2928
+ }
2841
2929
  get totalBodyHeight() {
2842
2930
  return Math.max(0, this._visibleRowCount - this._frozenRowCount) * this.rowHeight;
2843
2931
  }
@@ -2916,7 +3004,7 @@ var q = {
2916
3004
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
2917
3005
  return;
2918
3006
  }
2919
- if (this._filteredIndices = j(this.data, this._filters, (e, t, n) => {
3007
+ if (this._filteredIndices = ce(this.data, this._filters, (e, t, n) => {
2920
3008
  this.dispatchEvent(new CustomEvent("filter-error", {
2921
3009
  detail: {
2922
3010
  error: e,
@@ -2946,7 +3034,7 @@ var q = {
2946
3034
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2947
3035
  }
2948
3036
  _warnIfUnconstrained() {
2949
- this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Me || 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.`));
3037
+ 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.`));
2950
3038
  }
2951
3039
  _onScroll() {
2952
3040
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -3304,7 +3392,7 @@ var q = {
3304
3392
  async _handleCopy(e) {
3305
3393
  let t = this._selection.getEffectiveRange();
3306
3394
  if (!t) return;
3307
- let n = this.visibleColumns, r = ie(this._sortedIndices.map((e) => this.data[e]), n, t);
3395
+ let n = this.visibleColumns, r = ue(this._sortedIndices.map((e) => this.data[e]), n, t);
3308
3396
  try {
3309
3397
  await navigator.clipboard.writeText(r);
3310
3398
  } catch (e) {
@@ -4272,7 +4360,7 @@ var q = {
4272
4360
  }
4273
4361
  _updateFillDrag(e) {
4274
4362
  if (!this._fillDrag) return;
4275
- let t = this.getBoundingClientRect(), n = e.clientX - t.left + this._scrollLeft - this._prefixWidth, r = e.clientY - t.top + this._scrollTop - this.headerHeight, i = this.visibleColumns, a = 0;
4363
+ let t = this.getBoundingClientRect(), n = e.clientX - t.left + this._scrollLeft - this._prefixWidth, r = this._rowSpaceY(e.clientY), i = this.visibleColumns, a = 0;
4276
4364
  for (let e = 0; e < i.length; e++) (this._colLeftOffsets[e] ?? 0) <= n && (a = e);
4277
4365
  let o = Math.max(0, Math.min(this._visibleRowCount - 1, Math.floor(r / this.rowHeight))), { sourceRange: s } = this._fillDrag, c = o - s.endRow, l = a - s.endCol, u;
4278
4366
  u = Math.abs(c) >= Math.abs(l) ? c >= 0 ? {
@@ -4405,9 +4493,9 @@ var q = {
4405
4493
  _updateRowDrag(e) {
4406
4494
  if (!this._rowDrag) return;
4407
4495
  this._rowDrag.ghost && (this._rowDrag.ghost.style.left = `${e.clientX + 12}px`, this._rowDrag.ghost.style.top = `${e.clientY - 10}px`);
4408
- let t = this.getBoundingClientRect(), n = e.clientY - t.top + this._scrollTop - this.headerHeight, r = this.rowHeight, i = Math.round(n / r);
4496
+ let t = this.getBoundingClientRect(), n = this._rowSpaceY(e.clientY), r = this.rowHeight, i = Math.round(n / r);
4409
4497
  i = Math.max(0, Math.min(this._visibleRowCount, i)), this._rowDrag.rowIndex < i && i--, this._rowDrag.targetIndex = i;
4410
- let a = this.headerHeight + i * r - this._scrollTop;
4498
+ let a = this._rowBoundaryViewportY(i);
4411
4499
  this._rowDragIndicatorY = Math.max(this.headerHeight, Math.min(a, t.height)), this.requestUpdate();
4412
4500
  }
4413
4501
  _finishRowDrag() {
@@ -4727,48 +4815,48 @@ var q = {
4727
4815
  `;
4728
4816
  }
4729
4817
  _renderCell(e, t, n, r) {
4730
- let o = this._activeCell?.row === n && this._activeCell?.col === r, s = this._editingCell?.row === n && this._editingCell?.col === r, c = this._selection.isInRange(n, r), l = t.pinned === "left", u = t.pinned === "right", d = l || u, f = this._getColWidth(t), p = this.rowHeight, h = this._colLeftOffsets[r] ?? 0, g;
4731
- g = l ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(r)}px; width: ${f}px; height: ${p}px; z-index: 2;` : u ? `position: absolute; top: 0; left: ${this._getPinnedRightLeft(r)}px; width: ${f}px; height: ${p}px; z-index: 2;` : `left: ${h}px; width: ${f}px; height: ${p}px;`;
4732
- let _ = !this._isCellEditable(t);
4818
+ let o = this._activeCell?.row === n && this._activeCell?.col === r, s = this._editingCell?.row === n && this._editingCell?.col === r, c = this._selection.isInRange(n, r), l = t.pinned === "left", u = t.pinned === "right", d = l || u, f = this._getColWidth(t), p = this.rowHeight, m = this._colLeftOffsets[r] ?? 0, h;
4819
+ h = l ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(r)}px; width: ${f}px; height: ${p}px; z-index: 2;` : u ? `position: absolute; top: 0; left: ${this._getPinnedRightLeft(r)}px; width: ${f}px; height: ${p}px; z-index: 2;` : `left: ${m}px; width: ${f}px; height: ${p}px;`;
4820
+ let g = !this._isCellEditable(t);
4733
4821
  if (t.conditionalRules && t.conditionalRules.length > 0) {
4734
4822
  let n = e[t.key], r = {};
4735
4823
  for (let i of t.conditionalRules) i.when(n, e, t) && (i.style.background && (r.background = i.style.background), i.style.color && (r.color = i.style.color), i.style.fontWeight && (r["font-weight"] = i.style.fontWeight), i.style.fontStyle && (r["font-style"] = i.style.fontStyle));
4736
4824
  let i = Object.entries(r).map(([e, t]) => `${e}: ${t}`).join("; ");
4737
- i && (g += " " + i + ";");
4825
+ i && (h += " " + i + ";");
4738
4826
  }
4739
4827
  if (s) return i`
4740
4828
  <div class="ft-cell ft-editing ft-active ${d ? "ft-pinned" : ""}" role="gridcell"
4741
4829
  data-col-index=${r}
4742
4830
  aria-selected="true"
4743
- aria-readonly=${_ ? "true" : a}
4744
- style=${g}>
4831
+ aria-readonly=${g ? "true" : a}
4832
+ style=${h}>
4745
4833
  ${this._renderEditor(e, t)}
4746
4834
  </div>
4747
4835
  `;
4748
- let v = o || c, 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 = [
4836
+ let _ = o || c, v = this._isCellInvalid(n, r), y = (this._findState?.results ?? []).findIndex((e) => e.row === n && e.col === r), b = y >= 0, x = b && y === this._findState.currentIndex, S = [
4749
4837
  "ft-cell",
4750
4838
  `ft-type-${t.type ?? "text"}`,
4751
4839
  o ? "ft-active" : "",
4752
4840
  c ? "ft-selected" : "",
4753
4841
  d ? "ft-pinned" : "",
4754
- y ? "ft-invalid" : "",
4755
- S ? "ft-find-current" : x ? "ft-find-match" : ""
4756
- ].filter(Boolean).join(" "), w = this._toDataIndex(n), T = this._comments.get(w)?.get(t.key) ?? null, E = T !== null, D = E ? i`<div class="ft-comment-indicator" title=${T}></div>` : a;
4842
+ v ? "ft-invalid" : "",
4843
+ x ? "ft-find-current" : b ? "ft-find-match" : ""
4844
+ ].filter(Boolean).join(" "), C = this._toDataIndex(n), w = this._comments.get(C)?.get(t.key) ?? null, T = w !== null, E = T ? i`<div class="ft-comment-indicator" title=${w}></div>` : a;
4757
4845
  return i`
4758
- <div class=${E ? C + " ft-has-comment" : C}
4846
+ <div class=${T ? S + " ft-has-comment" : S}
4759
4847
  role="gridcell"
4760
4848
  data-col-index=${r}
4761
- aria-selected=${v ? "true" : "false"}
4762
- aria-readonly=${_ ? "true" : a}
4763
- aria-invalid=${y ? "true" : a}
4764
- title=${y ?? a}
4765
- style=${g}
4849
+ aria-selected=${_ ? "true" : "false"}
4850
+ aria-readonly=${g ? "true" : a}
4851
+ aria-invalid=${v ? "true" : a}
4852
+ title=${v ?? a}
4853
+ style=${h}
4766
4854
  @mousedown=${(e) => this._onCellMouseDown(e, n, r)}
4767
4855
  @mouseenter=${() => this._onCellMouseEnter(n, r)}
4768
4856
  @click=${(e) => this._onCellClickEvent(e, n, r)}
4769
4857
  @dblclick=${() => this._onCellDblClick(n, r)}>
4770
- ${D}
4771
- ${m(e[t.key], e, t)}
4858
+ ${E}
4859
+ ${D(e[t.key], e, t)}
4772
4860
  </div>
4773
4861
  `;
4774
4862
  }
@@ -4906,4 +4994,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4906
4994
  attribute: "max-undo-size"
4907
4995
  })], $.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")], $);
4908
4996
  //#endregion
4909
- export { O as a, A as i, H as n, m as o, M as r, $ as t };
4997
+ export { O as a, j as i, V as n, D as o, M as r, $ as t };
@@ -306,6 +306,14 @@ export declare class FlexTable extends LitElement {
306
306
  private get _visibleRowCount();
307
307
  private get _frozenRowCount();
308
308
  private get frozenRowsHeight();
309
+ /**
310
+ * 포인터의 뷰포트 y → 행 좌표(행 영역 맨 위 = 0, 픽셀). 고정 행 띠는 `position: sticky` 라
311
+ * 스크롤해도 제자리이므로, 그 띠 위에서는 스크롤 양을 더하지 않는다 — 더하면 띠 뒤에 가려진
312
+ * 본문 행을 가리킨다. 행 끌기·채우기 핸들이 같은 식을 쓴다.
313
+ */
314
+ private _rowSpaceY;
315
+ /** 행 경계 `index`(행 `index` 의 위 선)의 뷰포트 y(호스트 기준). 고정 띠 뒤로 가려지는 본문 경계는 띠 아래 선에 붙인다. */
316
+ private _rowBoundaryViewportY;
309
317
  private get totalBodyHeight();
310
318
  private get visibleRange();
311
319
  connectedCallback(): void;
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, t as a } from "./flex-table-BAQbidin.js";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./flex-table-DbbqD5Jn.js";
2
2
  export { a as FlexTable, t as RowSelectionState, i as UndoStack, n as exportData, e as flexTableLocale, r as renderCell };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-BAQbidin.js";
1
+ import { t as e } from "./flex-table-DbbqD5Jn.js";
2
2
  import t from "react";
3
3
  import { createComponent as n } from "@lit/react";
4
4
  var r = n({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.37.0",
3
+ "version": "0.38.1",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",
@@ -71,7 +71,7 @@
71
71
  "odata-query": "^8.1.0"
72
72
  },
73
73
  "peerDependencies": {
74
- "@iyulab/components": ">=1.24.0",
74
+ "@iyulab/components": ">=1.27.0",
75
75
  "@lit/react": "^1.0.0",
76
76
  "react": "^18.0.0 || ^19.0.0"
77
77
  },