@iyulab/flex-table 0.38.0 → 0.38.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,38 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.38.2] - 2026-09-24
4
+
5
+ ### Fixed
6
+
7
+ - 🔴 **`useODataSource` no longer drops `@odata.nextLink`.** With server-driven paging, a server
8
+ returns fewer rows than the requested `$top` and a link to the rest. The hook kept only the
9
+ first response, so a table whose `pageSize` exceeded the server's page size showed a short page
10
+ while `totalCount` and the pager still looked right. It now follows the link until the page is
11
+ filled. A link outside the request's origin, or one that returns to a page already read, is
12
+ reported through `error` rather than followed or silently dropped.
13
+
14
+ ## [0.38.1] - 2026-09-23
15
+
16
+ ### Fixed
17
+
18
+ - 🔴 **XLSX import no longer turns styled numbers into dates.** A number was read as a date whenever
19
+ its cell had any non-default style and its value fell between 1 and 73050 — so bold figures,
20
+ thousands separators, currency and percentage formats (most numbers in a real business
21
+ spreadsheet) came in as dates: a price of 12,450 became `1934-01-30`. Whether a number is a date
22
+ is now decided by the cell style's number format, read from `styles.xml`: the built-in date
23
+ formats, and custom formats whose code draws a day or a year (text in quotes, escaped characters
24
+ and bracketed sections such as `[Red]` or `[$-409]` are not counted). Time-only formats stay
25
+ numbers.
26
+ - 🔴 **Imported dates are no longer one day early.** The serial-to-date conversion subtracted a day,
27
+ so a date exported by the table and imported back came in as the day before.
28
+ - **Row drag and the fill handle hit the frozen row under the pointer while the table is
29
+ scrolled.** Frozen rows stay put as a sticky band, but both gestures added the scroll offset to
30
+ the pointer position everywhere, so over the band they pointed at the body row hidden behind
31
+ it: a row dropped onto a frozen row landed further down, and a fill dragged up into the band
32
+ stopped short of it. The drop indicator is drawn at the right place too.
33
+ - **XLSX import honors the 1904 date system** (`workbookPr date1904`, used by workbooks created on
34
+ a Mac), which otherwise shifts every date by four years.
35
+
3
36
  ## [0.38.0] - 2026-09-23
4
37
 
5
38
  ### Fixed
package/README.md CHANGED
@@ -729,7 +729,7 @@ The hook returns:
729
729
 
730
730
  | Field | Description |
731
731
  |---|---|
732
- | `data` / `totalCount` | Current page rows and the server's total (`@odata.count`) |
732
+ | `data` / `totalCount` | Current page rows and the server's total (`@odata.count`). When the server pages its response (`@odata.nextLink`, e.g. a page size smaller than `pageSize`), the hook follows the link until the page is filled; a link outside the request's origin, or one that returns to a page already read, is reported through `error` instead of showing a short page |
733
733
  | `loading` | A request is in flight |
734
734
  | `error` | Message of the last failed request, or `null`. **Render this** — a failed request otherwise leaves the grid silently empty |
735
735
  | `page` / `setPage` | Zero-based page index |
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "../sorting-CjfjRxwL.js";
2
- import { r as t } from "../use-odata-source-6fVz-CLu.js";
2
+ import { r as t } from "../use-odata-source-l9dVCi9l.js";
3
3
  import { useCallback as n, useMemo as r, useState as i } from "react";
4
4
  //#region src/array/use-array-source.ts
5
5
  function a(t, { search: n, sortCriteria: r, page: i, pageSize: a, columns: o, searchFields: s }) {
@@ -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
  */
@@ -946,7 +946,9 @@ var l = r`
946
946
  alertMessage: "رسالة",
947
947
  remove: "إزالة",
948
948
  closeTab: "إغلاق علامة التبويب",
949
- breadcrumb: "مسار التنقل"
949
+ breadcrumb: "مسار التنقل",
950
+ confirm: "تأكيد",
951
+ cancel: "إلغاء"
950
952
  },
951
953
  "../assets/locales/de.json": {
952
954
  valueMissing: "Dieses Feld ist erforderlich",
@@ -987,7 +989,9 @@ var l = r`
987
989
  alertMessage: "Nachricht",
988
990
  remove: "Entfernen",
989
991
  closeTab: "Tab schließen",
990
- breadcrumb: "Navigationspfad"
992
+ breadcrumb: "Navigationspfad",
993
+ confirm: "Bestätigen",
994
+ cancel: "Abbrechen"
991
995
  },
992
996
  "../assets/locales/en.json": {
993
997
  valueMissing: "This field is required",
@@ -1028,7 +1032,9 @@ var l = r`
1028
1032
  alertMessage: "Message",
1029
1033
  remove: "Remove",
1030
1034
  closeTab: "Close tab",
1031
- breadcrumb: "Breadcrumb"
1035
+ breadcrumb: "Breadcrumb",
1036
+ confirm: "Confirm",
1037
+ cancel: "Cancel"
1032
1038
  },
1033
1039
  "../assets/locales/es.json": {
1034
1040
  valueMissing: "Este campo es obligatorio",
@@ -1069,7 +1075,9 @@ var l = r`
1069
1075
  alertMessage: "Mensaje",
1070
1076
  remove: "Quitar",
1071
1077
  closeTab: "Cerrar pestaña",
1072
- breadcrumb: "Ruta de navegación"
1078
+ breadcrumb: "Ruta de navegación",
1079
+ confirm: "Confirmar",
1080
+ cancel: "Cancelar"
1073
1081
  },
1074
1082
  "../assets/locales/fr.json": {
1075
1083
  valueMissing: "Ce champ est obligatoire",
@@ -1110,7 +1118,9 @@ var l = r`
1110
1118
  alertMessage: "Message",
1111
1119
  remove: "Supprimer",
1112
1120
  closeTab: "Fermer l'onglet",
1113
- breadcrumb: "Fil d'Ariane"
1121
+ breadcrumb: "Fil d'Ariane",
1122
+ confirm: "Confirmer",
1123
+ cancel: "Annuler"
1114
1124
  },
1115
1125
  "../assets/locales/id.json": {
1116
1126
  valueMissing: "Kolom ini wajib diisi",
@@ -1151,7 +1161,9 @@ var l = r`
1151
1161
  alertMessage: "Pesan",
1152
1162
  remove: "Hapus",
1153
1163
  closeTab: "Tutup tab",
1154
- breadcrumb: "Navigasi remah roti"
1164
+ breadcrumb: "Navigasi remah roti",
1165
+ confirm: "Konfirmasi",
1166
+ cancel: "Batal"
1155
1167
  },
1156
1168
  "../assets/locales/ja.json": {
1157
1169
  valueMissing: "この項目は必須です",
@@ -1192,7 +1204,9 @@ var l = r`
1192
1204
  alertMessage: "メッセージ",
1193
1205
  remove: "削除",
1194
1206
  closeTab: "タブを閉じる",
1195
- breadcrumb: "パンくずリスト"
1207
+ breadcrumb: "パンくずリスト",
1208
+ confirm: "OK",
1209
+ cancel: "キャンセル"
1196
1210
  },
1197
1211
  "../assets/locales/ko.json": {
1198
1212
  valueMissing: "필수 항목입니다",
@@ -1233,7 +1247,9 @@ var l = r`
1233
1247
  alertMessage: "메시지",
1234
1248
  remove: "제거",
1235
1249
  closeTab: "탭 닫기",
1236
- breadcrumb: "탐색 경로"
1250
+ breadcrumb: "탐색 경로",
1251
+ confirm: "확인",
1252
+ cancel: "취소"
1237
1253
  },
1238
1254
  "../assets/locales/pt-BR.json": {
1239
1255
  valueMissing: "Este campo é obrigatório",
@@ -1274,7 +1290,9 @@ var l = r`
1274
1290
  alertMessage: "Mensagem",
1275
1291
  remove: "Remover",
1276
1292
  closeTab: "Fechar aba",
1277
- breadcrumb: "Trilha de navegação"
1293
+ breadcrumb: "Trilha de navegação",
1294
+ confirm: "Confirmar",
1295
+ cancel: "Cancelar"
1278
1296
  },
1279
1297
  "../assets/locales/ru.json": {
1280
1298
  valueMissing: "Это поле обязательно для заполнения",
@@ -1315,7 +1333,9 @@ var l = r`
1315
1333
  alertMessage: "Сообщение",
1316
1334
  remove: "Удалить",
1317
1335
  closeTab: "Закрыть вкладку",
1318
- breadcrumb: "Навигационная цепочка"
1336
+ breadcrumb: "Навигационная цепочка",
1337
+ confirm: "Подтвердить",
1338
+ cancel: "Отмена"
1319
1339
  },
1320
1340
  "../assets/locales/th.json": {
1321
1341
  valueMissing: "จำเป็นต้องกรอกข้อมูลนี้",
@@ -1356,7 +1376,9 @@ var l = r`
1356
1376
  alertMessage: "ข้อความ",
1357
1377
  remove: "ลบ",
1358
1378
  closeTab: "ปิดแท็บ",
1359
- breadcrumb: "เส้นทางการนำทาง"
1379
+ breadcrumb: "เส้นทางการนำทาง",
1380
+ confirm: "ยืนยัน",
1381
+ cancel: "ยกเลิก"
1360
1382
  },
1361
1383
  "../assets/locales/vi.json": {
1362
1384
  valueMissing: "Trường này là bắt buộc",
@@ -1397,7 +1419,9 @@ var l = r`
1397
1419
  alertMessage: "Thông báo",
1398
1420
  remove: "Xóa",
1399
1421
  closeTab: "Đóng tab",
1400
- 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"
1401
1425
  },
1402
1426
  "../assets/locales/zh-CN.json": {
1403
1427
  valueMissing: "此项为必填项",
@@ -1438,7 +1462,9 @@ var l = r`
1438
1462
  alertMessage: "消息",
1439
1463
  remove: "移除",
1440
1464
  closeTab: "关闭标签页",
1441
- breadcrumb: "面包屑导航"
1465
+ breadcrumb: "面包屑导航",
1466
+ confirm: "确定",
1467
+ cancel: "取消"
1442
1468
  },
1443
1469
  "../assets/locales/zh-TW.json": {
1444
1470
  valueMissing: "此欄位為必填",
@@ -1479,32 +1505,40 @@ var l = r`
1479
1505
  alertMessage: "訊息",
1480
1506
  remove: "移除",
1481
1507
  closeTab: "關閉分頁",
1482
- breadcrumb: "麵包屑導覽"
1508
+ breadcrumb: "麵包屑導覽",
1509
+ confirm: "確定",
1510
+ cancel: "取消"
1483
1511
  }
1484
1512
  })).map(([e, t]) => [(e.split("/").pop()?.replace(".json", "") || "").toLowerCase(), t])), d = /* @__PURE__ */ new Map();
1485
1513
  function f() {
1486
1514
  return typeof document < "u" && document.documentElement?.lang ? document.documentElement.lang : typeof window < "u" && typeof navigator < "u" && navigator.language ? navigator.language : "en";
1487
1515
  }
1488
- var p = f();
1489
- function m(e) {
1490
- let t = e.toLowerCase(), n = t.split("-")[0];
1491
- return n === t ? [t, "en"] : [
1492
- t,
1493
- n,
1516
+ var p = f(), m = {
1517
+ "zh-hant": "zh-tw",
1518
+ "zh-hk": "zh-tw",
1519
+ "zh-mo": "zh-tw",
1520
+ zh: "zh-cn",
1521
+ pt: "pt-br"
1522
+ };
1523
+ function h(e) {
1524
+ let t = e.toLowerCase().split("-"), n = t.map((e, n) => t.slice(0, t.length - n).join("-")), r = n.find((e) => e in m), i = r ? [
1525
+ ...n,
1526
+ m[r],
1494
1527
  "en"
1495
- ];
1528
+ ] : [...n, "en"];
1529
+ return [...new Set(i)];
1496
1530
  }
1497
- function h(e, t) {
1531
+ function g(e, t) {
1498
1532
  return t ? e.replace(/\{(\w+)\}/g, (e, n) => t[n] == null ? `{${n}}` : String(t[n])) : e;
1499
1533
  }
1500
- function g(e, t) {
1501
- for (let n of m(e)) {
1534
+ function _(e, t) {
1535
+ for (let n of h(e)) {
1502
1536
  let e = d.get(n)?.[t] ?? u.get(n)?.[t];
1503
1537
  if (e) return e;
1504
1538
  }
1505
1539
  return u.get("en")[t];
1506
1540
  }
1507
- var _ = /* @__PURE__ */ new Map(), v = class {
1541
+ var v = /* @__PURE__ */ new Map(), y = class {
1508
1542
  constructor() {}
1509
1543
  static set(e) {
1510
1544
  p = e;
@@ -1520,38 +1554,40 @@ var _ = /* @__PURE__ */ new Map(), v = class {
1520
1554
  });
1521
1555
  }
1522
1556
  static getValue(e, t) {
1523
- return h(g(p, e), t);
1557
+ return g(_(p, e), t);
1524
1558
  }
1525
1559
  static namespace(e) {
1560
+ let t = (t, n, r) => {
1561
+ let i = v.get(e);
1562
+ for (let e of h(t || p)) {
1563
+ let t = i?.get(e)?.[n];
1564
+ if (t) return g(t, r);
1565
+ }
1566
+ return n;
1567
+ };
1526
1568
  return {
1527
1569
  name: e,
1528
1570
  register(t, n) {
1529
- let r = _.get(e) ?? /* @__PURE__ */ new Map(), i = t.toLowerCase();
1571
+ let r = v.get(e) ?? /* @__PURE__ */ new Map(), i = t.toLowerCase();
1530
1572
  r.set(i, {
1531
1573
  ...r.get(i),
1532
1574
  ...n
1533
- }), _.set(e, r);
1575
+ }), v.set(e, r);
1534
1576
  },
1535
- text(t, n) {
1536
- let r = _.get(e);
1537
- for (let e of m(p)) {
1538
- let i = r?.get(e)?.[t];
1539
- if (i) return h(i, n);
1540
- }
1541
- return t;
1542
- }
1577
+ text: (e, n) => t(void 0, e, n),
1578
+ textIn: t
1543
1579
  };
1544
1580
  }
1545
1581
  };
1546
1582
  //#endregion
1547
1583
  //#region src/renderers/format.ts
1548
- function y(e, t) {
1549
- return e == null ? "" : typeof t == "function" ? t(e) : b(t) ? S(e, t) : x(e, t);
1584
+ function b(e, t) {
1585
+ return e == null ? "" : typeof t == "function" ? t(e) : x(t) ? C(e, t) : S(e, t);
1550
1586
  }
1551
- function b(e) {
1587
+ function x(e) {
1552
1588
  return /[yMdHhms]/.test(e);
1553
1589
  }
1554
- function x(e, t) {
1590
+ function S(e, t) {
1555
1591
  let n = typeof e == "number" ? e : Number(e);
1556
1592
  if (isNaN(n)) return String(e);
1557
1593
  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 = {
@@ -1559,12 +1595,12 @@ function x(e, t) {
1559
1595
  maximumFractionDigits: c,
1560
1596
  useGrouping: o.includes(",")
1561
1597
  }, u;
1562
- return r ? u = new Intl.NumberFormat(v.get(), {
1598
+ return r ? u = new Intl.NumberFormat(y.get(), {
1563
1599
  ...l,
1564
1600
  style: "percent"
1565
- }).format(n) : (u = new Intl.NumberFormat(v.get(), l).format(n), a && (u = a + u)), u + "";
1601
+ }).format(n) : (u = new Intl.NumberFormat(y.get(), l).format(n), a && (u = a + u)), u + "";
1566
1602
  }
1567
- function S(e, t) {
1603
+ function C(e, t) {
1568
1604
  let n;
1569
1605
  if (e instanceof Date) n = e;
1570
1606
  else if (typeof e == "string" || typeof e == "number") n = new Date(e);
@@ -1575,24 +1611,24 @@ function S(e, t) {
1575
1611
  }
1576
1612
  //#endregion
1577
1613
  //#region node_modules/@iyulab/components/dist/utilities/format.js
1578
- function C(e) {
1614
+ function w(e) {
1579
1615
  let [t, n, r] = e.split("-").map(Number);
1580
1616
  return Number.isNaN(t) || Number.isNaN(n) || Number.isNaN(r) ? new Date(e) : new Date(t, n - 1, r);
1581
1617
  }
1582
- function w(e) {
1583
- return typeof e == "string" ? C(e) : e;
1584
- }
1585
- function T(e, t, n) {
1586
- return new Intl.NumberFormat(n ?? v.get(), t).format(e);
1618
+ function T(e) {
1619
+ return typeof e == "string" ? w(e) : e;
1587
1620
  }
1588
1621
  function E(e, t, n) {
1589
- let r = w(e);
1590
- return Number.isNaN(r.getTime()) ? String(e) : new Intl.DateTimeFormat(n ?? v.get(), t).format(r);
1622
+ return new Intl.NumberFormat(n ?? y.get(), t).format(e);
1623
+ }
1624
+ function D(e, t, n) {
1625
+ let r = T(e);
1626
+ return Number.isNaN(r.getTime()) ? String(e) : new Intl.DateTimeFormat(n ?? y.get(), t).format(r);
1591
1627
  }
1592
1628
  //#endregion
1593
1629
  //#region src/renderers/cell-renderer.ts
1594
- function D(e, t, n) {
1595
- 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);
1630
+ function O(e, t, n) {
1631
+ return n.renderer ? n.renderer(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : b(e, n.format) : ee(e, n);
1596
1632
  }
1597
1633
  function ee(e, t) {
1598
1634
  if (e == null) return "";
@@ -1600,7 +1636,7 @@ function ee(e, t) {
1600
1636
  case "number": return re(e);
1601
1637
  case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
1602
1638
  case "date": return ie(e);
1603
- case "datetime": return O(e);
1639
+ case "datetime": return ae(e);
1604
1640
  case "select": return te(e, t);
1605
1641
  default: return String(e);
1606
1642
  }
@@ -1619,17 +1655,17 @@ var ne = {
1619
1655
  second: "numeric"
1620
1656
  };
1621
1657
  function re(e) {
1622
- return typeof e == "number" ? Number.isInteger(e) ? T(e) : T(e, { minimumFractionDigits: 1 }) : String(e);
1658
+ return typeof e == "number" ? Number.isInteger(e) ? E(e) : E(e, { minimumFractionDigits: 1 }) : String(e);
1623
1659
  }
1624
1660
  function ie(e) {
1625
- return e instanceof Date || typeof e == "string" ? E(e) : String(e);
1661
+ return e instanceof Date || typeof e == "string" ? D(e) : String(e);
1626
1662
  }
1627
- function O(e) {
1628
- return e instanceof Date || typeof e == "string" ? E(e, ne) : String(e);
1663
+ function ae(e) {
1664
+ return e instanceof Date || typeof e == "string" ? D(e, ne) : String(e);
1629
1665
  }
1630
1666
  //#endregion
1631
1667
  //#region src/locale.ts
1632
- var k = v.namespace("flex-table");
1668
+ var k = y.namespace("flex-table");
1633
1669
  k.register("en", {
1634
1670
  showHiddenColumns: "Show hidden column(s)",
1635
1671
  columnMenu: "Column menu",
@@ -1740,7 +1776,7 @@ k.register("en", {
1740
1776
  var A = (e, t) => k.text(e, t);
1741
1777
  //#endregion
1742
1778
  //#region src/core/selection.ts
1743
- function ae(e) {
1779
+ function oe(e) {
1744
1780
  return {
1745
1781
  startRow: Math.min(e.startRow, e.endRow),
1746
1782
  startCol: Math.min(e.startCol, e.endCol),
@@ -1748,7 +1784,7 @@ function ae(e) {
1748
1784
  endCol: Math.max(e.startCol, e.endCol)
1749
1785
  };
1750
1786
  }
1751
- var oe = class {
1787
+ var j = class {
1752
1788
  constructor() {
1753
1789
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
1754
1790
  }
@@ -1775,7 +1811,7 @@ var oe = class {
1775
1811
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
1776
1812
  row: e,
1777
1813
  col: t
1778
- }, this.rangeAnchor && (this.range = ae({
1814
+ }, this.rangeAnchor && (this.range = oe({
1779
1815
  startRow: this.rangeAnchor.row,
1780
1816
  startCol: this.rangeAnchor.col,
1781
1817
  endRow: e,
@@ -1867,7 +1903,7 @@ var oe = class {
1867
1903
  let e = this.current;
1868
1904
  return this.current = null, e;
1869
1905
  }
1870
- }, j = class {
1906
+ }, M = class {
1871
1907
  constructor() {
1872
1908
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
1873
1909
  }
@@ -1947,7 +1983,7 @@ function ce(e, t, n) {
1947
1983
  }
1948
1984
  //#endregion
1949
1985
  //#region src/core/undo.ts
1950
- var le = 100, M = class {
1986
+ var le = 100, N = class {
1951
1987
  constructor() {
1952
1988
  this._undoStack = [], this._redoStack = [], this._maxSize = le;
1953
1989
  }
@@ -1986,7 +2022,7 @@ var le = 100, M = class {
1986
2022
  };
1987
2023
  //#endregion
1988
2024
  //#region src/clipboard/clipboard.ts
1989
- function N(e, t, n) {
2025
+ function ue(e, t, n) {
1990
2026
  let r = [];
1991
2027
  for (let i = n.startRow; i <= n.endRow; i++) {
1992
2028
  let a = e[i], o = [];
@@ -2041,7 +2077,7 @@ function F(e, t) {
2041
2077
  }
2042
2078
  //#endregion
2043
2079
  //#region src/export/xlsx-writer.ts
2044
- var ue = (() => {
2080
+ var de = (() => {
2045
2081
  let e = /* @__PURE__ */ new Uint32Array(256);
2046
2082
  for (let t = 0; t < 256; t++) {
2047
2083
  let n = t;
@@ -2050,16 +2086,16 @@ var ue = (() => {
2050
2086
  }
2051
2087
  return e;
2052
2088
  })();
2053
- function de(e) {
2089
+ function fe(e) {
2054
2090
  let t = 4294967295;
2055
- for (let n = 0; n < e.length; n++) t = ue[(t ^ e[n]) & 255] ^ t >>> 8;
2091
+ for (let n = 0; n < e.length; n++) t = de[(t ^ e[n]) & 255] ^ t >>> 8;
2056
2092
  return (t ^ 4294967295) >>> 0;
2057
2093
  }
2058
2094
  var I = new TextEncoder();
2059
- function fe(e) {
2095
+ function pe(e) {
2060
2096
  let t = [], n = [], r = 0;
2061
2097
  for (let i of e) {
2062
- let e = I.encode(i.name), a = de(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
2098
+ let e = I.encode(i.name), a = fe(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
2063
2099
  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);
2064
2100
  let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
2065
2101
  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;
@@ -2087,19 +2123,19 @@ function z(e) {
2087
2123
  function B(e, t) {
2088
2124
  return z(t) + (e + 1);
2089
2125
  }
2090
- function V(e) {
2126
+ function me(e) {
2091
2127
  let t = Date.UTC(1899, 11, 30);
2092
2128
  return (e.getTime() - t) / 864e5;
2093
2129
  }
2094
- var pe = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>\n <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>\n <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>\n <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>\n</Types>", me = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", he = "<?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>", ge = "<?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>", _e = "<?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>";
2095
- function ve(e, t) {
2130
+ var he = "<?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>", ge = "<?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>", _e = "<?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>", ve = "<?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>", ye = "<?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>";
2131
+ function be(e, t) {
2096
2132
  let n = [], r = t.map((e, t) => `<c r="${B(0, t)}" t="str" s="2"><v>${R(e.header)}</v></c>`);
2097
2133
  return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
2098
2134
  let i = t.map((t, n) => {
2099
2135
  let i = B(r + 1, n), a = e[t.key];
2100
2136
  if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
2101
2137
  let o = t.type ?? "text";
2102
- 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>${V(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${R(String(a))}</v></c>`;
2138
+ 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>${R(String(a))}</v></c>`;
2103
2139
  });
2104
2140
  n.push(`<row r="${r + 2}">${i.join("")}</row>`);
2105
2141
  }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -2107,24 +2143,24 @@ function ve(e, t) {
2107
2143
  <sheetData>${n.join("")}</sheetData>
2108
2144
  </worksheet>`;
2109
2145
  }
2110
- function ye(e, t) {
2111
- let n = ve(e, t);
2112
- return fe([
2146
+ function xe(e, t) {
2147
+ let n = be(e, t);
2148
+ return pe([
2113
2149
  {
2114
2150
  name: "[Content_Types].xml",
2115
- data: I.encode(pe)
2151
+ data: I.encode(he)
2116
2152
  },
2117
2153
  {
2118
2154
  name: "_rels/.rels",
2119
- data: I.encode(me)
2155
+ data: I.encode(ge)
2120
2156
  },
2121
2157
  {
2122
2158
  name: "xl/workbook.xml",
2123
- data: I.encode(he)
2159
+ data: I.encode(_e)
2124
2160
  },
2125
2161
  {
2126
2162
  name: "xl/_rels/workbook.xml.rels",
2127
- data: I.encode(ge)
2163
+ data: I.encode(ve)
2128
2164
  },
2129
2165
  {
2130
2166
  name: "xl/worksheets/sheet1.xml",
@@ -2132,30 +2168,30 @@ function ye(e, t) {
2132
2168
  },
2133
2169
  {
2134
2170
  name: "xl/styles.xml",
2135
- data: I.encode(_e)
2171
+ data: I.encode(ye)
2136
2172
  }
2137
2173
  ]);
2138
2174
  }
2139
2175
  //#endregion
2140
2176
  //#region src/export/export.ts
2141
- function H(e, t, n) {
2177
+ function V(e, t, n) {
2142
2178
  switch (n) {
2143
- case "csv": return U(e, t, ",");
2144
- case "tsv": return U(e, t, " ");
2145
- case "json": return xe(e, t);
2146
- case "xlsx": return ye(e, t);
2179
+ case "csv": return H(e, t, ",");
2180
+ case "tsv": return H(e, t, " ");
2181
+ case "json": return Ce(e, t);
2182
+ case "xlsx": return xe(e, t);
2147
2183
  }
2148
2184
  }
2149
- function be(e, t) {
2185
+ function Se(e, t) {
2150
2186
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
2151
2187
  }
2152
- function U(e, t, n) {
2153
- return [t.map((e) => W(e.header, n)).join(n), ...e.map((e) => t.map((t) => W(be(e[t.key], t), n)).join(n))].join("\n");
2188
+ function H(e, t, n) {
2189
+ return [t.map((e) => U(e.header, n)).join(n), ...e.map((e) => t.map((t) => U(Se(e[t.key], t), n)).join(n))].join("\n");
2154
2190
  }
2155
- function W(e, t) {
2191
+ function U(e, t) {
2156
2192
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
2157
2193
  }
2158
- function xe(e, t) {
2194
+ function Ce(e, t) {
2159
2195
  let n = e.map((e) => {
2160
2196
  let n = {};
2161
2197
  for (let r of t) {
@@ -2166,35 +2202,35 @@ function xe(e, t) {
2166
2202
  });
2167
2203
  return JSON.stringify(n, null, 2);
2168
2204
  }
2169
- function Se(e, t, n) {
2205
+ function we(e, t, n) {
2170
2206
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
2171
2207
  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);
2172
2208
  }
2173
- var Ce = {
2209
+ var Te = {
2174
2210
  csv: "text/csv;charset=utf-8",
2175
2211
  tsv: "text/tab-separated-values;charset=utf-8",
2176
2212
  json: "application/json;charset=utf-8",
2177
2213
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
2178
- }, we = {
2214
+ }, Ee = {
2179
2215
  csv: ".csv",
2180
2216
  tsv: ".tsv",
2181
2217
  json: ".json",
2182
2218
  xlsx: ".xlsx"
2183
2219
  };
2184
- function Te(e) {
2185
- return Ce[e];
2220
+ function De(e) {
2221
+ return Te[e];
2186
2222
  }
2187
- function Ee(e) {
2188
- return we[e];
2223
+ function Oe(e) {
2224
+ return Ee[e];
2189
2225
  }
2190
2226
  //#endregion
2191
2227
  //#region src/export/xlsx-reader.ts
2192
- function De(e) {
2228
+ function ke(e) {
2193
2229
  for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
2194
2230
  throw Error("XLSX: End of central directory not found — not a valid ZIP file");
2195
2231
  }
2196
- function Oe(e) {
2197
- 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;
2232
+ function Ae(e) {
2233
+ let t = ke(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
2198
2234
  for (; o < s && e.getUint32(o, !0) === 33639248;) {
2199
2235
  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));
2200
2236
  a.push({
@@ -2207,7 +2243,7 @@ function Oe(e) {
2207
2243
  }
2208
2244
  return a;
2209
2245
  }
2210
- async function ke(e) {
2246
+ async function je(e) {
2211
2247
  let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
2212
2248
  n.write(e), n.close();
2213
2249
  let i = [];
@@ -2220,69 +2256,107 @@ async function ke(e) {
2220
2256
  for (let e of i) o.set(e, s), s += e.length;
2221
2257
  return o;
2222
2258
  }
2223
- async function Ae(e, t) {
2259
+ async function Me(e, t) {
2224
2260
  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);
2225
2261
  if (t.compressionMethod === 0) return o.slice();
2226
- if (t.compressionMethod === 8) return ke(o);
2262
+ if (t.compressionMethod === 8) return je(o);
2227
2263
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
2228
2264
  }
2229
- async function je(e) {
2230
- let t = new DataView(e), n = Oe(t), r = /* @__PURE__ */ new Map();
2231
- for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ae(t, e));
2265
+ async function Ne(e) {
2266
+ let t = new DataView(e), n = Ae(t), r = /* @__PURE__ */ new Map();
2267
+ for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Me(t, e));
2232
2268
  return r;
2233
2269
  }
2234
- var Me = new TextDecoder("utf-8");
2235
- function G(e) {
2236
- let t = Me.decode(e);
2270
+ var Pe = new TextDecoder("utf-8");
2271
+ function W(e) {
2272
+ let t = Pe.decode(e);
2237
2273
  return new DOMParser().parseFromString(t, "application/xml");
2238
2274
  }
2239
- function Ne(e) {
2275
+ function Fe(e) {
2240
2276
  if (!e) return [];
2241
- let t = G(e);
2277
+ let t = W(e);
2242
2278
  return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
2243
2279
  }
2244
- function Pe(e) {
2245
- let t = (e - 1) * 864e5 + Date.UTC(1899, 11, 30);
2246
- return new Date(t).toISOString().slice(0, 10);
2280
+ var Ie = /* @__PURE__ */ new Set([
2281
+ 14,
2282
+ 15,
2283
+ 16,
2284
+ 17,
2285
+ 22,
2286
+ 27,
2287
+ 28,
2288
+ 29,
2289
+ 30,
2290
+ 31,
2291
+ 36,
2292
+ 50,
2293
+ 51,
2294
+ 52,
2295
+ 53,
2296
+ 54,
2297
+ 57,
2298
+ 58
2299
+ ]);
2300
+ function Le(e) {
2301
+ let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
2302
+ return /[dy]/i.test(t);
2303
+ }
2304
+ function Re(e) {
2305
+ let t = /* @__PURE__ */ new Set();
2306
+ if (!e) return t;
2307
+ let n = W(e), r = /* @__PURE__ */ new Map();
2308
+ for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
2309
+ return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
2310
+ let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
2311
+ (a === void 0 ? Ie.has(i) : Le(a)) && t.add(n);
2312
+ }), t;
2247
2313
  }
2248
- function Fe(e, t) {
2249
- let n = G(e).querySelectorAll("row");
2250
- if (n.length === 0) return [];
2251
- let r = 0, i = /* @__PURE__ */ new Map();
2252
- for (let e of n) {
2253
- let n = parseInt(e.getAttribute("r") ?? "1", 10) - 1, a = /* @__PURE__ */ new Map();
2254
- i.set(n, a);
2255
- for (let n of e.querySelectorAll("c")) {
2256
- let e = Ie(n.getAttribute("r") ?? "");
2257
- e > r && (r = e);
2258
- let i = n.getAttribute("t") ?? "", o = n.getAttribute("s") ?? "", s = n.querySelector("v")?.textContent ?? "", c = n.querySelector("is > t")?.textContent ?? null, l;
2259
- if (i === "s") l = t[parseInt(s, 10)] ?? "";
2260
- else if (i === "str" || i === "inlineStr") l = c ?? s;
2261
- else if (i === "b") l = s === "1" ? "true" : "false";
2262
- else if (s === "") l = "";
2314
+ function ze(e) {
2315
+ if (!e) return !1;
2316
+ let t = W(e).querySelector("workbookPr")?.getAttribute("date1904");
2317
+ return t === "1" || t === "true";
2318
+ }
2319
+ function Be(e, t) {
2320
+ return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
2321
+ }
2322
+ function Ve(e, t, n, r) {
2323
+ let i = W(e).querySelectorAll("row");
2324
+ if (i.length === 0) return [];
2325
+ let a = 0, o = /* @__PURE__ */ new Map();
2326
+ for (let e of i) {
2327
+ let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
2328
+ o.set(i, s);
2329
+ for (let i of e.querySelectorAll("c")) {
2330
+ let e = He(i.getAttribute("r") ?? "");
2331
+ e > a && (a = e);
2332
+ let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
2333
+ if (o === "s") d = t[parseInt(l, 10)] ?? "";
2334
+ else if (o === "str" || o === "inlineStr") d = u ?? l;
2335
+ else if (o === "b") d = l === "1" ? "true" : "false";
2336
+ else if (l === "") d = "";
2263
2337
  else {
2264
- let e = parseFloat(s);
2265
- l = !isNaN(e) && o !== "" && parseInt(o, 10) > 0 && e >= 1 && e <= 73050 ? Pe(e) : s;
2338
+ let e = parseFloat(l);
2339
+ d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Be(e, r) : l;
2266
2340
  }
2267
- a.set(e, l);
2341
+ s.set(e, d);
2268
2342
  }
2269
2343
  }
2270
- if (i.size === 0) return [];
2271
- let a = Math.max(...i.keys()), o = [];
2272
- for (let e = 0; e <= a; e++) {
2273
- let t = i.get(e) ?? /* @__PURE__ */ new Map(), n = [];
2274
- for (let e = 0; e <= r; e++) n.push(t.get(e) ?? "");
2275
- o.push(n);
2344
+ if (o.size === 0) return [];
2345
+ let s = Math.max(...o.keys()), c = [];
2346
+ for (let e = 0; e <= s; e++) {
2347
+ let t = o.get(e) ?? /* @__PURE__ */ new Map(), n = [];
2348
+ for (let e = 0; e <= a; e++) n.push(t.get(e) ?? "");
2349
+ c.push(n);
2276
2350
  }
2277
- return o;
2351
+ return c;
2278
2352
  }
2279
- function Ie(e) {
2353
+ function He(e) {
2280
2354
  let t = 0, n = 0;
2281
2355
  for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
2282
2356
  return t - 1;
2283
2357
  }
2284
- async function Le(e) {
2285
- let t = await je(e), n = Ne(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
2358
+ async function G(e) {
2359
+ let t = await Ne(e), n = Fe(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
2286
2360
  if (!r) {
2287
2361
  for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
2288
2362
  r = n;
@@ -2290,17 +2364,17 @@ async function Le(e) {
2290
2364
  }
2291
2365
  }
2292
2366
  if (!r) throw Error("XLSX: No worksheet found");
2293
- let i = Fe(r, n);
2294
- return i.length === 0 ? {
2367
+ let i = Re(t.get("xl/styles.xml")), a = ze(t.get("xl/workbook.xml")), o = Ve(r, n, i, a);
2368
+ return o.length === 0 ? {
2295
2369
  headers: [],
2296
2370
  rows: []
2297
2371
  } : {
2298
- headers: i[0],
2299
- rows: i.slice(1)
2372
+ headers: o[0],
2373
+ rows: o.slice(1)
2300
2374
  };
2301
2375
  }
2302
2376
  //#endregion
2303
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
2377
+ //#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
2304
2378
  function K(e, t, n, r) {
2305
2379
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
2306
2380
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
@@ -2316,9 +2390,9 @@ var q = {
2316
2390
  lt: "<",
2317
2391
  gte: "≥",
2318
2392
  lte: "≤"
2319
- }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Re = 200, $ = class extends n {
2393
+ }, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Ue = 200, $ = class extends n {
2320
2394
  constructor(...e) {
2321
- 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 oe(), this._editing = new se(), 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 = () => {
2395
+ 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 j(), this._editing = new se(), this._rowSelection = new M(), this._undo = new N(), 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 = () => {
2322
2396
  this._commitCommentPopup();
2323
2397
  }, 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();
2324
2398
  }
@@ -2683,12 +2757,12 @@ var q = {
2683
2757
  if (!t) return "";
2684
2758
  let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
2685
2759
  for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
2686
- return H(r, n, e);
2760
+ return V(r, n, e);
2687
2761
  }
2688
- return H(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2762
+ return V(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
2689
2763
  }
2690
2764
  exportToFile(e, t) {
2691
- Se(this.exportToString(e), t ?? `export${Ee(e)}`, Te(e));
2765
+ we(this.exportToString(e), t ?? `export${Oe(e)}`, De(e));
2692
2766
  }
2693
2767
  setComment(e, t, n) {
2694
2768
  let r = this.getComment(e, t);
@@ -2745,7 +2819,7 @@ var q = {
2745
2819
  async importFromFile(e) {
2746
2820
  let t = e.name.toLowerCase();
2747
2821
  if (t.endsWith(".xlsx")) {
2748
- let t = await Le(await e.arrayBuffer());
2822
+ let t = await G(await e.arrayBuffer());
2749
2823
  this._applyImportedSheet(t);
2750
2824
  } else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
2751
2825
  let t = P(await e.text());
@@ -2852,6 +2926,14 @@ var q = {
2852
2926
  get frozenRowsHeight() {
2853
2927
  return this._frozenRowCount * this.rowHeight;
2854
2928
  }
2929
+ _rowSpaceY(e) {
2930
+ let t = e - this.getBoundingClientRect().top - this.headerHeight;
2931
+ return t < this.frozenRowsHeight ? t : t + this._scrollTop;
2932
+ }
2933
+ _rowBoundaryViewportY(e) {
2934
+ let t = this.headerHeight + e * this.rowHeight;
2935
+ return e <= this._frozenRowCount ? t : Math.max(this.headerHeight + this.frozenRowsHeight, t - this._scrollTop);
2936
+ }
2855
2937
  get totalBodyHeight() {
2856
2938
  return Math.max(0, this._visibleRowCount - this._frozenRowCount) * this.rowHeight;
2857
2939
  }
@@ -2960,7 +3042,7 @@ var q = {
2960
3042
  e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
2961
3043
  }
2962
3044
  _warnIfUnconstrained() {
2963
- this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Re || 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.`));
3045
+ this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Ue || 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.`));
2964
3046
  }
2965
3047
  _onScroll() {
2966
3048
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
@@ -3318,7 +3400,7 @@ var q = {
3318
3400
  async _handleCopy(e) {
3319
3401
  let t = this._selection.getEffectiveRange();
3320
3402
  if (!t) return;
3321
- let n = this.visibleColumns, r = N(this._sortedIndices.map((e) => this.data[e]), n, t);
3403
+ let n = this.visibleColumns, r = ue(this._sortedIndices.map((e) => this.data[e]), n, t);
3322
3404
  try {
3323
3405
  await navigator.clipboard.writeText(r);
3324
3406
  } catch (e) {
@@ -4286,7 +4368,7 @@ var q = {
4286
4368
  }
4287
4369
  _updateFillDrag(e) {
4288
4370
  if (!this._fillDrag) return;
4289
- 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;
4371
+ let t = this.getBoundingClientRect(), n = e.clientX - t.left + this._scrollLeft - this._prefixWidth, r = this._rowSpaceY(e.clientY), i = this.visibleColumns, a = 0;
4290
4372
  for (let e = 0; e < i.length; e++) (this._colLeftOffsets[e] ?? 0) <= n && (a = e);
4291
4373
  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;
4292
4374
  u = Math.abs(c) >= Math.abs(l) ? c >= 0 ? {
@@ -4419,9 +4501,9 @@ var q = {
4419
4501
  _updateRowDrag(e) {
4420
4502
  if (!this._rowDrag) return;
4421
4503
  this._rowDrag.ghost && (this._rowDrag.ghost.style.left = `${e.clientX + 12}px`, this._rowDrag.ghost.style.top = `${e.clientY - 10}px`);
4422
- let t = this.getBoundingClientRect(), n = e.clientY - t.top + this._scrollTop - this.headerHeight, r = this.rowHeight, i = Math.round(n / r);
4504
+ let t = this.getBoundingClientRect(), n = this._rowSpaceY(e.clientY), r = this.rowHeight, i = Math.round(n / r);
4423
4505
  i = Math.max(0, Math.min(this._visibleRowCount, i)), this._rowDrag.rowIndex < i && i--, this._rowDrag.targetIndex = i;
4424
- let a = this.headerHeight + i * r - this._scrollTop;
4506
+ let a = this._rowBoundaryViewportY(i);
4425
4507
  this._rowDragIndicatorY = Math.max(this.headerHeight, Math.min(a, t.height)), this.requestUpdate();
4426
4508
  }
4427
4509
  _finishRowDrag() {
@@ -4782,7 +4864,7 @@ var q = {
4782
4864
  @click=${(e) => this._onCellClickEvent(e, n, r)}
4783
4865
  @dblclick=${() => this._onCellDblClick(n, r)}>
4784
4866
  ${E}
4785
- ${D(e[t.key], e, t)}
4867
+ ${O(e[t.key], e, t)}
4786
4868
  </div>
4787
4869
  `;
4788
4870
  }
@@ -4920,4 +5002,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
4920
5002
  attribute: "max-undo-size"
4921
5003
  })], $.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")], $);
4922
5004
  //#endregion
4923
- export { k as a, j as i, H as n, D as o, M as r, $ as t };
5005
+ export { k as a, M as i, V as n, O as o, N 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-DcIjmfEK.js";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./flex-table-JGaGcJTl.js";
2
2
  export { a as FlexTable, t as RowSelectionState, i as UndoStack, n as exportData, e as flexTableLocale, r as renderCell };
@@ -1,2 +1,2 @@
1
- import { i as e, n as t, t as n } from "../use-odata-source-6fVz-CLu.js";
1
+ import { i as e, n as t, t as n } from "../use-odata-source-l9dVCi9l.js";
2
2
  export { n as buildSearchExpression, t as parseOrderBy, e as useODataSource };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-DcIjmfEK.js";
1
+ import { t as e } from "./flex-table-JGaGcJTl.js";
2
2
  import t from "react";
3
3
  import { createComponent as n } from "@lit/react";
4
4
  var r = n({
@@ -42,24 +42,39 @@ function s(s, c = {}) {
42
42
  let e = a(M);
43
43
  e && (n.search = e);
44
44
  }
45
- let r = i(n), o = `${h ?? window.location.origin}${s}${r}`;
46
- return g(o, { signal: e.signal }).then(async (e) => {
47
- if (!e.ok) {
48
- (e.status === 401 || e.status === 403) && _ && _(e);
49
- let t = await e.text().catch(() => ""), n = `Request failed (${e.status})`;
45
+ let r = i(n), o = `${h ?? window.location.origin}${s}${r}`, c = async (t) => {
46
+ let n = await g(t, { signal: e.signal });
47
+ if (!n.ok) {
48
+ (n.status === 401 || n.status === 403) && _ && _(n);
49
+ let e = await n.text().catch(() => ""), t = `Request failed (${n.status})`;
50
50
  try {
51
- let e = JSON.parse(t);
52
- n = e?.error?.message ?? e?.message ?? n;
51
+ let n = JSON.parse(e);
52
+ t = n?.error?.message ?? n?.message ?? t;
53
53
  } catch {}
54
- throw Error(n);
54
+ throw Error(t);
55
55
  }
56
- return e.json();
57
- }).then((t) => {
56
+ return n.json();
57
+ };
58
+ return (async () => {
59
+ let e = await c(o), t = [...e.value ?? e], n = new URL(o).origin, r = /* @__PURE__ */ new Set([o]), i = o, a = e["@odata.nextLink"];
60
+ for (; typeof a == "string" && a && t.length < l;) {
61
+ let e = new URL(a, i);
62
+ if (e.origin !== n) throw Error(`OData nextLink points outside the source origin (${e.origin})`);
63
+ if (i = e.toString(), r.has(i)) throw Error(`OData nextLink repeats an already-read page (${i})`);
64
+ r.add(i);
65
+ let o = await c(i);
66
+ t.push(...o.value ?? []), a = o["@odata.nextLink"];
67
+ }
68
+ return {
69
+ count: e["@odata.count"],
70
+ rows: t
71
+ };
72
+ })().then(({ count: t, rows: n }) => {
58
73
  if (e.signal.aborted) return;
59
- let n = t["@odata.count"] ?? 0;
60
- b(t.value ?? t), S(n), E(null);
61
- let r = n === 0 ? 0 : Math.ceil(n / l) - 1;
62
- O > r && k(r);
74
+ let r = t ?? 0;
75
+ b(n), S(r), E(null);
76
+ let i = r === 0 ? 0 : Math.ceil(r / l) - 1;
77
+ O > i && k(i);
63
78
  }).catch((t) => {
64
79
  e.signal.aborted || t.name !== "AbortError" && (E(t.message), b([]), S(0));
65
80
  }).finally(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.38.0",
3
+ "version": "0.38.2",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",