@iyulab/flex-table 0.38.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,27 @@
|
|
|
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
|
+
|
|
3
25
|
## [0.38.0] - 2026-09-23
|
|
4
26
|
|
|
5
27
|
### 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
|
*/
|
|
@@ -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,7 +1505,9 @@ 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() {
|
|
@@ -1600,7 +1628,7 @@ function ee(e, t) {
|
|
|
1600
1628
|
case "number": return re(e);
|
|
1601
1629
|
case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
|
|
1602
1630
|
case "date": return ie(e);
|
|
1603
|
-
case "datetime": return
|
|
1631
|
+
case "datetime": return ae(e);
|
|
1604
1632
|
case "select": return te(e, t);
|
|
1605
1633
|
default: return String(e);
|
|
1606
1634
|
}
|
|
@@ -1624,13 +1652,13 @@ function re(e) {
|
|
|
1624
1652
|
function ie(e) {
|
|
1625
1653
|
return e instanceof Date || typeof e == "string" ? E(e) : String(e);
|
|
1626
1654
|
}
|
|
1627
|
-
function
|
|
1655
|
+
function ae(e) {
|
|
1628
1656
|
return e instanceof Date || typeof e == "string" ? E(e, ne) : String(e);
|
|
1629
1657
|
}
|
|
1630
1658
|
//#endregion
|
|
1631
1659
|
//#region src/locale.ts
|
|
1632
|
-
var
|
|
1633
|
-
|
|
1660
|
+
var O = v.namespace("flex-table");
|
|
1661
|
+
O.register("en", {
|
|
1634
1662
|
showHiddenColumns: "Show hidden column(s)",
|
|
1635
1663
|
columnMenu: "Column menu",
|
|
1636
1664
|
cellActions: "Cell actions",
|
|
@@ -1683,7 +1711,7 @@ k.register("en", {
|
|
|
1683
1711
|
booleanTrue: "True",
|
|
1684
1712
|
booleanFalse: "False",
|
|
1685
1713
|
dropFileToImport: "Drop file to import (.xlsx / .csv)"
|
|
1686
|
-
}),
|
|
1714
|
+
}), O.register("ko", {
|
|
1687
1715
|
showHiddenColumns: "숨긴 열 보기",
|
|
1688
1716
|
columnMenu: "열 메뉴",
|
|
1689
1717
|
cellActions: "셀 작업",
|
|
@@ -1737,10 +1765,10 @@ k.register("en", {
|
|
|
1737
1765
|
booleanFalse: "거짓",
|
|
1738
1766
|
dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)"
|
|
1739
1767
|
});
|
|
1740
|
-
var
|
|
1768
|
+
var k = (e, t) => O.text(e, t);
|
|
1741
1769
|
//#endregion
|
|
1742
1770
|
//#region src/core/selection.ts
|
|
1743
|
-
function
|
|
1771
|
+
function oe(e) {
|
|
1744
1772
|
return {
|
|
1745
1773
|
startRow: Math.min(e.startRow, e.endRow),
|
|
1746
1774
|
startCol: Math.min(e.startCol, e.endCol),
|
|
@@ -1748,7 +1776,7 @@ function ae(e) {
|
|
|
1748
1776
|
endCol: Math.max(e.startCol, e.endCol)
|
|
1749
1777
|
};
|
|
1750
1778
|
}
|
|
1751
|
-
var
|
|
1779
|
+
var se = class {
|
|
1752
1780
|
constructor() {
|
|
1753
1781
|
this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
|
|
1754
1782
|
}
|
|
@@ -1775,7 +1803,7 @@ var oe = class {
|
|
|
1775
1803
|
return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
|
|
1776
1804
|
row: e,
|
|
1777
1805
|
col: t
|
|
1778
|
-
}, this.rangeAnchor && (this.range =
|
|
1806
|
+
}, this.rangeAnchor && (this.range = oe({
|
|
1779
1807
|
startRow: this.rangeAnchor.row,
|
|
1780
1808
|
startCol: this.rangeAnchor.col,
|
|
1781
1809
|
endRow: e,
|
|
@@ -1846,7 +1874,7 @@ var oe = class {
|
|
|
1846
1874
|
shiftMoveRight() {
|
|
1847
1875
|
return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
|
|
1848
1876
|
}
|
|
1849
|
-
},
|
|
1877
|
+
}, A = class {
|
|
1850
1878
|
constructor() {
|
|
1851
1879
|
this.current = null;
|
|
1852
1880
|
}
|
|
@@ -1986,7 +2014,7 @@ var le = 100, M = class {
|
|
|
1986
2014
|
};
|
|
1987
2015
|
//#endregion
|
|
1988
2016
|
//#region src/clipboard/clipboard.ts
|
|
1989
|
-
function
|
|
2017
|
+
function ue(e, t, n) {
|
|
1990
2018
|
let r = [];
|
|
1991
2019
|
for (let i = n.startRow; i <= n.endRow; i++) {
|
|
1992
2020
|
let a = e[i], o = [];
|
|
@@ -1998,7 +2026,7 @@ function N(e, t, n) {
|
|
|
1998
2026
|
}
|
|
1999
2027
|
return r.join("\n");
|
|
2000
2028
|
}
|
|
2001
|
-
function
|
|
2029
|
+
function N(e) {
|
|
2002
2030
|
let t = e.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), n = [], r = [], i = 0, a = t.length;
|
|
2003
2031
|
for (; i <= a;) {
|
|
2004
2032
|
if (i === a) {
|
|
@@ -2028,7 +2056,7 @@ function P(e) {
|
|
|
2028
2056
|
}
|
|
2029
2057
|
return n;
|
|
2030
2058
|
}
|
|
2031
|
-
function
|
|
2059
|
+
function P(e, t) {
|
|
2032
2060
|
if (e === "") return null;
|
|
2033
2061
|
switch (t.type) {
|
|
2034
2062
|
case "number": {
|
|
@@ -2041,7 +2069,7 @@ function F(e, t) {
|
|
|
2041
2069
|
}
|
|
2042
2070
|
//#endregion
|
|
2043
2071
|
//#region src/export/xlsx-writer.ts
|
|
2044
|
-
var
|
|
2072
|
+
var de = (() => {
|
|
2045
2073
|
let e = /* @__PURE__ */ new Uint32Array(256);
|
|
2046
2074
|
for (let t = 0; t < 256; t++) {
|
|
2047
2075
|
let n = t;
|
|
@@ -2050,56 +2078,56 @@ var ue = (() => {
|
|
|
2050
2078
|
}
|
|
2051
2079
|
return e;
|
|
2052
2080
|
})();
|
|
2053
|
-
function
|
|
2081
|
+
function fe(e) {
|
|
2054
2082
|
let t = 4294967295;
|
|
2055
|
-
for (let n = 0; n < e.length; n++) t =
|
|
2083
|
+
for (let n = 0; n < e.length; n++) t = de[(t ^ e[n]) & 255] ^ t >>> 8;
|
|
2056
2084
|
return (t ^ 4294967295) >>> 0;
|
|
2057
2085
|
}
|
|
2058
|
-
var
|
|
2059
|
-
function
|
|
2086
|
+
var F = new TextEncoder();
|
|
2087
|
+
function pe(e) {
|
|
2060
2088
|
let t = [], n = [], r = 0;
|
|
2061
2089
|
for (let i of e) {
|
|
2062
|
-
let e =
|
|
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);
|
|
2063
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);
|
|
2064
2092
|
let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
|
|
2065
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;
|
|
2066
2094
|
}
|
|
2067
|
-
let i =
|
|
2068
|
-
return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0),
|
|
2095
|
+
let i = I(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
|
|
2096
|
+
return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), I([
|
|
2069
2097
|
...t,
|
|
2070
2098
|
i,
|
|
2071
2099
|
new Uint8Array(a)
|
|
2072
2100
|
]);
|
|
2073
2101
|
}
|
|
2074
|
-
function
|
|
2102
|
+
function I(e) {
|
|
2075
2103
|
let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
|
|
2076
2104
|
for (let t of e) n.set(t, r), r += t.length;
|
|
2077
2105
|
return n;
|
|
2078
2106
|
}
|
|
2079
|
-
function
|
|
2107
|
+
function L(e) {
|
|
2080
2108
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
2081
2109
|
}
|
|
2082
|
-
function
|
|
2110
|
+
function R(e) {
|
|
2083
2111
|
let t = "";
|
|
2084
2112
|
for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
|
|
2085
2113
|
return t;
|
|
2086
2114
|
}
|
|
2087
|
-
function
|
|
2088
|
-
return
|
|
2115
|
+
function z(e, t) {
|
|
2116
|
+
return R(t) + (e + 1);
|
|
2089
2117
|
}
|
|
2090
|
-
function
|
|
2118
|
+
function B(e) {
|
|
2091
2119
|
let t = Date.UTC(1899, 11, 30);
|
|
2092
2120
|
return (e.getTime() - t) / 864e5;
|
|
2093
2121
|
}
|
|
2094
|
-
var
|
|
2095
|
-
function
|
|
2096
|
-
let n = [], r = t.map((e, t) => `<c r="${
|
|
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>`);
|
|
2097
2125
|
return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
|
|
2098
2126
|
let i = t.map((t, n) => {
|
|
2099
|
-
let i =
|
|
2127
|
+
let i = z(r + 1, n), a = e[t.key];
|
|
2100
2128
|
if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
|
|
2101
2129
|
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>${
|
|
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>`;
|
|
2103
2131
|
});
|
|
2104
2132
|
n.push(`<row r="${r + 2}">${i.join("")}</row>`);
|
|
2105
2133
|
}), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -2107,55 +2135,55 @@ function ve(e, t) {
|
|
|
2107
2135
|
<sheetData>${n.join("")}</sheetData>
|
|
2108
2136
|
</worksheet>`;
|
|
2109
2137
|
}
|
|
2110
|
-
function
|
|
2111
|
-
let n =
|
|
2112
|
-
return
|
|
2138
|
+
function be(e, t) {
|
|
2139
|
+
let n = ye(e, t);
|
|
2140
|
+
return pe([
|
|
2113
2141
|
{
|
|
2114
2142
|
name: "[Content_Types].xml",
|
|
2115
|
-
data:
|
|
2143
|
+
data: F.encode(me)
|
|
2116
2144
|
},
|
|
2117
2145
|
{
|
|
2118
2146
|
name: "_rels/.rels",
|
|
2119
|
-
data:
|
|
2147
|
+
data: F.encode(he)
|
|
2120
2148
|
},
|
|
2121
2149
|
{
|
|
2122
2150
|
name: "xl/workbook.xml",
|
|
2123
|
-
data:
|
|
2151
|
+
data: F.encode(ge)
|
|
2124
2152
|
},
|
|
2125
2153
|
{
|
|
2126
2154
|
name: "xl/_rels/workbook.xml.rels",
|
|
2127
|
-
data:
|
|
2155
|
+
data: F.encode(_e)
|
|
2128
2156
|
},
|
|
2129
2157
|
{
|
|
2130
2158
|
name: "xl/worksheets/sheet1.xml",
|
|
2131
|
-
data:
|
|
2159
|
+
data: F.encode(n)
|
|
2132
2160
|
},
|
|
2133
2161
|
{
|
|
2134
2162
|
name: "xl/styles.xml",
|
|
2135
|
-
data:
|
|
2163
|
+
data: F.encode(ve)
|
|
2136
2164
|
}
|
|
2137
2165
|
]);
|
|
2138
2166
|
}
|
|
2139
2167
|
//#endregion
|
|
2140
2168
|
//#region src/export/export.ts
|
|
2141
|
-
function
|
|
2169
|
+
function V(e, t, n) {
|
|
2142
2170
|
switch (n) {
|
|
2143
|
-
case "csv": return
|
|
2144
|
-
case "tsv": return
|
|
2145
|
-
case "json": return
|
|
2146
|
-
case "xlsx": return
|
|
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);
|
|
2147
2175
|
}
|
|
2148
2176
|
}
|
|
2149
|
-
function
|
|
2177
|
+
function xe(e, t) {
|
|
2150
2178
|
return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
|
|
2151
2179
|
}
|
|
2152
|
-
function
|
|
2153
|
-
return [t.map((e) =>
|
|
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");
|
|
2154
2182
|
}
|
|
2155
|
-
function
|
|
2183
|
+
function U(e, t) {
|
|
2156
2184
|
return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
|
|
2157
2185
|
}
|
|
2158
|
-
function
|
|
2186
|
+
function Se(e, t) {
|
|
2159
2187
|
let n = e.map((e) => {
|
|
2160
2188
|
let n = {};
|
|
2161
2189
|
for (let r of t) {
|
|
@@ -2166,35 +2194,35 @@ function xe(e, t) {
|
|
|
2166
2194
|
});
|
|
2167
2195
|
return JSON.stringify(n, null, 2);
|
|
2168
2196
|
}
|
|
2169
|
-
function
|
|
2197
|
+
function Ce(e, t, n) {
|
|
2170
2198
|
let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
|
|
2171
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);
|
|
2172
2200
|
}
|
|
2173
|
-
var
|
|
2201
|
+
var we = {
|
|
2174
2202
|
csv: "text/csv;charset=utf-8",
|
|
2175
2203
|
tsv: "text/tab-separated-values;charset=utf-8",
|
|
2176
2204
|
json: "application/json;charset=utf-8",
|
|
2177
2205
|
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
2178
|
-
},
|
|
2206
|
+
}, Te = {
|
|
2179
2207
|
csv: ".csv",
|
|
2180
2208
|
tsv: ".tsv",
|
|
2181
2209
|
json: ".json",
|
|
2182
2210
|
xlsx: ".xlsx"
|
|
2183
2211
|
};
|
|
2184
|
-
function Te(e) {
|
|
2185
|
-
return Ce[e];
|
|
2186
|
-
}
|
|
2187
2212
|
function Ee(e) {
|
|
2188
2213
|
return we[e];
|
|
2189
2214
|
}
|
|
2215
|
+
function De(e) {
|
|
2216
|
+
return Te[e];
|
|
2217
|
+
}
|
|
2190
2218
|
//#endregion
|
|
2191
2219
|
//#region src/export/xlsx-reader.ts
|
|
2192
|
-
function
|
|
2220
|
+
function Oe(e) {
|
|
2193
2221
|
for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
|
|
2194
2222
|
throw Error("XLSX: End of central directory not found — not a valid ZIP file");
|
|
2195
2223
|
}
|
|
2196
|
-
function
|
|
2197
|
-
let t =
|
|
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;
|
|
2198
2226
|
for (; o < s && e.getUint32(o, !0) === 33639248;) {
|
|
2199
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));
|
|
2200
2228
|
a.push({
|
|
@@ -2207,7 +2235,7 @@ function Oe(e) {
|
|
|
2207
2235
|
}
|
|
2208
2236
|
return a;
|
|
2209
2237
|
}
|
|
2210
|
-
async function
|
|
2238
|
+
async function Ae(e) {
|
|
2211
2239
|
let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
2212
2240
|
n.write(e), n.close();
|
|
2213
2241
|
let i = [];
|
|
@@ -2220,69 +2248,107 @@ async function ke(e) {
|
|
|
2220
2248
|
for (let e of i) o.set(e, s), s += e.length;
|
|
2221
2249
|
return o;
|
|
2222
2250
|
}
|
|
2223
|
-
async function
|
|
2251
|
+
async function je(e, t) {
|
|
2224
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);
|
|
2225
2253
|
if (t.compressionMethod === 0) return o.slice();
|
|
2226
|
-
if (t.compressionMethod === 8) return
|
|
2254
|
+
if (t.compressionMethod === 8) return Ae(o);
|
|
2227
2255
|
throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
|
|
2228
2256
|
}
|
|
2229
|
-
async function
|
|
2230
|
-
let t = new DataView(e), n =
|
|
2231
|
-
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await
|
|
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));
|
|
2232
2260
|
return r;
|
|
2233
2261
|
}
|
|
2234
|
-
var
|
|
2235
|
-
function
|
|
2236
|
-
let t =
|
|
2262
|
+
var Ne = new TextDecoder("utf-8");
|
|
2263
|
+
function W(e) {
|
|
2264
|
+
let t = Ne.decode(e);
|
|
2237
2265
|
return new DOMParser().parseFromString(t, "application/xml");
|
|
2238
2266
|
}
|
|
2239
|
-
function
|
|
2267
|
+
function Pe(e) {
|
|
2240
2268
|
if (!e) return [];
|
|
2241
|
-
let t =
|
|
2269
|
+
let t = W(e);
|
|
2242
2270
|
return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
|
|
2243
2271
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
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);
|
|
2295
|
+
}
|
|
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);
|
|
2247
2313
|
}
|
|
2248
|
-
function
|
|
2249
|
-
let
|
|
2250
|
-
if (
|
|
2251
|
-
let
|
|
2252
|
-
for (let e of
|
|
2253
|
-
let
|
|
2254
|
-
|
|
2255
|
-
for (let
|
|
2256
|
-
let e =
|
|
2257
|
-
e >
|
|
2258
|
-
let
|
|
2259
|
-
if (
|
|
2260
|
-
else if (
|
|
2261
|
-
else if (
|
|
2262
|
-
else if (
|
|
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 = "";
|
|
2263
2329
|
else {
|
|
2264
|
-
let e = parseFloat(
|
|
2265
|
-
|
|
2330
|
+
let e = parseFloat(l);
|
|
2331
|
+
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? ze(e, r) : l;
|
|
2266
2332
|
}
|
|
2267
|
-
|
|
2333
|
+
s.set(e, d);
|
|
2268
2334
|
}
|
|
2269
2335
|
}
|
|
2270
|
-
if (
|
|
2271
|
-
let
|
|
2272
|
-
for (let e = 0; e <=
|
|
2273
|
-
let t =
|
|
2274
|
-
for (let e = 0; e <=
|
|
2275
|
-
|
|
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);
|
|
2276
2342
|
}
|
|
2277
|
-
return
|
|
2343
|
+
return c;
|
|
2278
2344
|
}
|
|
2279
|
-
function
|
|
2345
|
+
function Ve(e) {
|
|
2280
2346
|
let t = 0, n = 0;
|
|
2281
2347
|
for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
|
|
2282
2348
|
return t - 1;
|
|
2283
2349
|
}
|
|
2284
|
-
async function
|
|
2285
|
-
let t = await
|
|
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");
|
|
2286
2352
|
if (!r) {
|
|
2287
2353
|
for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
|
|
2288
2354
|
r = n;
|
|
@@ -2290,13 +2356,13 @@ async function Le(e) {
|
|
|
2290
2356
|
}
|
|
2291
2357
|
}
|
|
2292
2358
|
if (!r) throw Error("XLSX: No worksheet found");
|
|
2293
|
-
let i =
|
|
2294
|
-
return
|
|
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 ? {
|
|
2295
2361
|
headers: [],
|
|
2296
2362
|
rows: []
|
|
2297
2363
|
} : {
|
|
2298
|
-
headers:
|
|
2299
|
-
rows:
|
|
2364
|
+
headers: o[0],
|
|
2365
|
+
rows: o.slice(1)
|
|
2300
2366
|
};
|
|
2301
2367
|
}
|
|
2302
2368
|
//#endregion
|
|
@@ -2316,9 +2382,9 @@ var q = {
|
|
|
2316
2382
|
lt: "<",
|
|
2317
2383
|
gte: "≥",
|
|
2318
2384
|
lte: "≤"
|
|
2319
|
-
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5,
|
|
2385
|
+
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5, He = 200, $ = class extends n {
|
|
2320
2386
|
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
|
|
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 = () => {
|
|
2322
2388
|
this._commitCommentPopup();
|
|
2323
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();
|
|
2324
2390
|
}
|
|
@@ -2683,12 +2749,12 @@ var q = {
|
|
|
2683
2749
|
if (!t) return "";
|
|
2684
2750
|
let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
|
|
2685
2751
|
for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
|
|
2686
|
-
return
|
|
2752
|
+
return V(r, n, e);
|
|
2687
2753
|
}
|
|
2688
|
-
return
|
|
2754
|
+
return V(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
|
|
2689
2755
|
}
|
|
2690
2756
|
exportToFile(e, t) {
|
|
2691
|
-
|
|
2757
|
+
Ce(this.exportToString(e), t ?? `export${De(e)}`, Ee(e));
|
|
2692
2758
|
}
|
|
2693
2759
|
setComment(e, t, n) {
|
|
2694
2760
|
let r = this.getComment(e, t);
|
|
@@ -2745,10 +2811,10 @@ var q = {
|
|
|
2745
2811
|
async importFromFile(e) {
|
|
2746
2812
|
let t = e.name.toLowerCase();
|
|
2747
2813
|
if (t.endsWith(".xlsx")) {
|
|
2748
|
-
let t = await
|
|
2814
|
+
let t = await G(await e.arrayBuffer());
|
|
2749
2815
|
this._applyImportedSheet(t);
|
|
2750
2816
|
} else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
|
|
2751
|
-
let t =
|
|
2817
|
+
let t = N(await e.text());
|
|
2752
2818
|
this._applyImportedRows(t);
|
|
2753
2819
|
} else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
|
|
2754
2820
|
}
|
|
@@ -2759,7 +2825,7 @@ var q = {
|
|
|
2759
2825
|
let a = t.get(e);
|
|
2760
2826
|
if (!a) return;
|
|
2761
2827
|
let o = this.columns.find((e) => e.key === a);
|
|
2762
|
-
r[a] = o ?
|
|
2828
|
+
r[a] = o ? P(n[i] ?? "", o) : n[i] ?? null;
|
|
2763
2829
|
}), r;
|
|
2764
2830
|
}), r = [...this.data];
|
|
2765
2831
|
this.data = n, this._undo.push({
|
|
@@ -2784,7 +2850,7 @@ var q = {
|
|
|
2784
2850
|
let a = n.get(t);
|
|
2785
2851
|
if (!a) return;
|
|
2786
2852
|
let o = this.columns.find((e) => e.key === a);
|
|
2787
|
-
r[a] = o ?
|
|
2853
|
+
r[a] = o ? P(e[i] ?? "", o) : e[i] ?? null;
|
|
2788
2854
|
}), r;
|
|
2789
2855
|
}), i = [...this.data];
|
|
2790
2856
|
this.data = r, this._undo.push({
|
|
@@ -2852,6 +2918,14 @@ var q = {
|
|
|
2852
2918
|
get frozenRowsHeight() {
|
|
2853
2919
|
return this._frozenRowCount * this.rowHeight;
|
|
2854
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
|
+
}
|
|
2855
2929
|
get totalBodyHeight() {
|
|
2856
2930
|
return Math.max(0, this._visibleRowCount - this._frozenRowCount) * this.rowHeight;
|
|
2857
2931
|
}
|
|
@@ -2960,7 +3034,7 @@ var q = {
|
|
|
2960
3034
|
e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
|
|
2961
3035
|
}
|
|
2962
3036
|
_warnIfUnconstrained() {
|
|
2963
|
-
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount <
|
|
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.`));
|
|
2964
3038
|
}
|
|
2965
3039
|
_onScroll() {
|
|
2966
3040
|
this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
|
|
@@ -3090,7 +3164,7 @@ var q = {
|
|
|
3090
3164
|
}
|
|
3091
3165
|
let t = this.shadowRoot?.querySelector(".ft-editor");
|
|
3092
3166
|
if (t) {
|
|
3093
|
-
let n =
|
|
3167
|
+
let n = P(t.value, e);
|
|
3094
3168
|
this._applyEdit(n);
|
|
3095
3169
|
} else this._cancelEdit();
|
|
3096
3170
|
}
|
|
@@ -3318,7 +3392,7 @@ var q = {
|
|
|
3318
3392
|
async _handleCopy(e) {
|
|
3319
3393
|
let t = this._selection.getEffectiveRange();
|
|
3320
3394
|
if (!t) return;
|
|
3321
|
-
let n = this.visibleColumns, r =
|
|
3395
|
+
let n = this.visibleColumns, r = ue(this._sortedIndices.map((e) => this.data[e]), n, t);
|
|
3322
3396
|
try {
|
|
3323
3397
|
await navigator.clipboard.writeText(r);
|
|
3324
3398
|
} catch (e) {
|
|
@@ -3344,7 +3418,7 @@ var q = {
|
|
|
3344
3418
|
if (!this._activeCell) return;
|
|
3345
3419
|
let e = await this._readClipboardText();
|
|
3346
3420
|
if (e == null) return;
|
|
3347
|
-
let t =
|
|
3421
|
+
let t = N(e);
|
|
3348
3422
|
if (t.length === 0) return;
|
|
3349
3423
|
let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
|
|
3350
3424
|
if (r.length > 0 || n.length > 0) {
|
|
@@ -3402,7 +3476,7 @@ var q = {
|
|
|
3402
3476
|
for (let a = 0; a < t[i].length; a++) {
|
|
3403
3477
|
let s = e.col + a;
|
|
3404
3478
|
if (s >= n.length) break;
|
|
3405
|
-
let c = n[s], l = this.data[o][c.key], u =
|
|
3479
|
+
let c = n[s], l = this.data[o][c.key], u = P(t[i][a], c);
|
|
3406
3480
|
this.data[o][c.key] = u, r.push({
|
|
3407
3481
|
row: o,
|
|
3408
3482
|
col: s,
|
|
@@ -3467,7 +3541,7 @@ var q = {
|
|
|
3467
3541
|
for (let r = e.startCol + 1; r <= e.endCol; r++) {
|
|
3468
3542
|
let e = t[r];
|
|
3469
3543
|
if (!e || !this._isCellEditable(e)) continue;
|
|
3470
|
-
let a =
|
|
3544
|
+
let a = P(o == null ? "" : String(o), e);
|
|
3471
3545
|
n.push({
|
|
3472
3546
|
row: i,
|
|
3473
3547
|
key: e.key,
|
|
@@ -3626,7 +3700,7 @@ var q = {
|
|
|
3626
3700
|
@click=${n ? (t) => this._onHeaderClick(t, e) : void 0}>
|
|
3627
3701
|
${x ? i`
|
|
3628
3702
|
<button class="ft-hidden-col-indicator"
|
|
3629
|
-
title=${
|
|
3703
|
+
title=${k("showHiddenColumns")}
|
|
3630
3704
|
@click=${(t) => {
|
|
3631
3705
|
t.stopPropagation(), this._showHiddenBefore(e);
|
|
3632
3706
|
}}>❯</button>
|
|
@@ -3636,8 +3710,8 @@ var q = {
|
|
|
3636
3710
|
${o >= 0 ? i`<span class="ft-sort-order">${o + 1}</span>` : ""}
|
|
3637
3711
|
<button class="ft-column-menu-btn ${s ? "ft-filter-active" : ""}"
|
|
3638
3712
|
type="button"
|
|
3639
|
-
title=${
|
|
3640
|
-
aria-label=${
|
|
3713
|
+
title=${k("columnMenu")}
|
|
3714
|
+
aria-label=${k("columnMenuFor", { header: e.header })}
|
|
3641
3715
|
aria-haspopup="menu"
|
|
3642
3716
|
aria-expanded=${this._headerMenu?.key === e.key ? "true" : "false"}
|
|
3643
3717
|
@mousedown=${(e) => e.stopPropagation()}
|
|
@@ -3756,26 +3830,26 @@ var q = {
|
|
|
3756
3830
|
}}>${t}</button>
|
|
3757
3831
|
`;
|
|
3758
3832
|
return i`
|
|
3759
|
-
<div class="ft-header-menu" role="menu" aria-label=${
|
|
3833
|
+
<div class="ft-header-menu" role="menu" aria-label=${k("columnMenuRegion", { header: o.header })}
|
|
3760
3834
|
style="position: fixed; left: ${t}px; top: ${n}px; z-index: 200;"
|
|
3761
3835
|
@mousedown=${(e) => e.stopPropagation()}
|
|
3762
3836
|
@keydown=${(e) => this._onHeaderMenuKeydown(e)}>
|
|
3763
3837
|
${o.sortable === !1 ? a : i`
|
|
3764
|
-
${c("sort-asc",
|
|
3765
|
-
${c("sort-desc",
|
|
3838
|
+
${c("sort-asc", k("sortAscending"), () => this._applySortFromMenu(e, "asc"))}
|
|
3839
|
+
${c("sort-desc", k("sortDescending"), () => this._applySortFromMenu(e, "desc"))}
|
|
3766
3840
|
<div class="ft-header-menu-separator" role="separator"></div>
|
|
3767
3841
|
`}
|
|
3768
3842
|
${this.showFilters ? i`
|
|
3769
|
-
${c("filter",
|
|
3770
|
-
${s ? c("clear-filter",
|
|
3843
|
+
${c("filter", k("filter"), () => this._openFilterFromMenu(e))}
|
|
3844
|
+
${s ? c("clear-filter", k("clearFilter"), () => this._clearColumnFilter(e)) : a}
|
|
3771
3845
|
<div class="ft-header-menu-separator" role="separator"></div>
|
|
3772
3846
|
` : a}
|
|
3773
|
-
${c("hide",
|
|
3774
|
-
${r.map((e) => c("show",
|
|
3847
|
+
${c("hide", k("hideColumn"), () => this._setColumnHidden(e, !0))}
|
|
3848
|
+
${r.map((e) => c("show", k("showColumn", { header: e.header }), () => this._setColumnHidden(e.key, !1)))}
|
|
3775
3849
|
<div class="ft-header-menu-separator" role="separator"></div>
|
|
3776
|
-
${c("autofit",
|
|
3777
|
-
${c("wider",
|
|
3778
|
-
${c("narrower",
|
|
3850
|
+
${c("autofit", k("autoFitWidth"), () => this._autoFitColumn(e))}
|
|
3851
|
+
${c("wider", k("wider"), () => this._resizeColumnBy(e, X), !0)}
|
|
3852
|
+
${c("narrower", k("narrower"), () => this._resizeColumnBy(e, -20), !0)}
|
|
3779
3853
|
</div>
|
|
3780
3854
|
`;
|
|
3781
3855
|
}
|
|
@@ -3793,26 +3867,26 @@ var q = {
|
|
|
3793
3867
|
}}>${e}</button>
|
|
3794
3868
|
`, f = i`<div class="ft-context-menu-separator" role="separator"></div>`;
|
|
3795
3869
|
return i`
|
|
3796
|
-
<div class="ft-body-context-menu" role="menu" aria-label=${
|
|
3870
|
+
<div class="ft-body-context-menu" role="menu" aria-label=${k("cellActions")}
|
|
3797
3871
|
style="position: fixed; left: ${n}px; top: ${r}px; z-index: 200;"
|
|
3798
3872
|
@mousedown=${(e) => e.stopPropagation()}
|
|
3799
3873
|
@keydown=${(e) => this._onMenuKeydown(e, ".ft-body-context-menu", l)}>
|
|
3800
|
-
${d(
|
|
3874
|
+
${d(k("copy"), () => this._handleCopy(!1))}
|
|
3801
3875
|
${f}
|
|
3802
|
-
${d(
|
|
3803
|
-
${d(
|
|
3804
|
-
${d(
|
|
3876
|
+
${d(k("insertRowAbove"), () => this.addRow(void 0, t))}
|
|
3877
|
+
${d(k("insertRowBelow"), () => this.addRow(void 0, t + 1))}
|
|
3878
|
+
${d(k("deleteRow"), () => this.deleteRows([t]), !0)}
|
|
3805
3879
|
${f}
|
|
3806
|
-
${d(
|
|
3880
|
+
${d(k("hideColumn"), () => this._setColumnHidden(o.key, !0))}
|
|
3807
3881
|
${f}
|
|
3808
|
-
${d(`${
|
|
3809
|
-
${d(`${
|
|
3882
|
+
${d(`${k("sortAscending")} ↑`, () => this._applySortFromMenu(o.key, "asc"))}
|
|
3883
|
+
${d(`${k("sortDescending")} ↓`, () => this._applySortFromMenu(o.key, "desc"))}
|
|
3810
3884
|
${f}
|
|
3811
|
-
${d(
|
|
3812
|
-
${c ? d(
|
|
3885
|
+
${d(k("filterByThisValue"), () => this.setFilter(o.key, (e) => e === s))}
|
|
3886
|
+
${c ? d(k("clearFilter"), () => this.removeFilter(o.key)) : a}
|
|
3813
3887
|
${f}
|
|
3814
|
-
${d(
|
|
3815
|
-
${u ? d(
|
|
3888
|
+
${d(k(u ? "editComment" : "addComment"), () => this._openCommentPopup(t, o.key, n, r))}
|
|
3889
|
+
${u ? d(k("deleteComment"), () => this.setComment(t, o.key, null), !0) : a}
|
|
3816
3890
|
</div>
|
|
3817
3891
|
`;
|
|
3818
3892
|
}
|
|
@@ -3844,13 +3918,13 @@ var q = {
|
|
|
3844
3918
|
@mousedown=${(e) => e.stopPropagation()}>
|
|
3845
3919
|
<textarea class="ft-comment-popup-textarea"
|
|
3846
3920
|
rows="4"
|
|
3847
|
-
placeholder=${
|
|
3921
|
+
placeholder=${k("addCommentPlaceholder")}
|
|
3848
3922
|
@keydown=${(e) => {
|
|
3849
3923
|
e.key === "Escape" && (e.preventDefault(), this._cancelCommentPopup()), e.key === "Enter" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this._commitCommentPopup());
|
|
3850
3924
|
}}></textarea>
|
|
3851
3925
|
<div class="ft-comment-popup-buttons">
|
|
3852
|
-
<button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${
|
|
3853
|
-
<button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${
|
|
3926
|
+
<button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>${k("cancel")}</button>
|
|
3927
|
+
<button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>${k("save")}</button>
|
|
3854
3928
|
</div>
|
|
3855
3929
|
</div>
|
|
3856
3930
|
`;
|
|
@@ -3886,7 +3960,7 @@ var q = {
|
|
|
3886
3960
|
<div class="ft-filter-dropdown" @click=${(e) => e.stopPropagation()}>
|
|
3887
3961
|
${t === "boolean" ? this._renderBooleanFilter(e) : t === "number" ? this._renderNumberFilter(e) : t === "date" || t === "datetime" ? this._renderDateFilter(e) : this._renderTextFilter(e)}
|
|
3888
3962
|
<div class="ft-filter-actions">
|
|
3889
|
-
<button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${
|
|
3963
|
+
<button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${k("clear")}</button>
|
|
3890
3964
|
</div>
|
|
3891
3965
|
</div>
|
|
3892
3966
|
`;
|
|
@@ -3919,7 +3993,7 @@ var q = {
|
|
|
3919
3993
|
let n = this._emptyFilterState.get(e) ?? "";
|
|
3920
3994
|
return i`
|
|
3921
3995
|
<div class="ft-filter-empty-row">
|
|
3922
|
-
<label>${
|
|
3996
|
+
<label>${k("blankCells")}</label>
|
|
3923
3997
|
<select class="ft-filter-mode-select"
|
|
3924
3998
|
.value=${n}
|
|
3925
3999
|
@change=${(n) => {
|
|
@@ -3929,9 +4003,9 @@ var q = {
|
|
|
3929
4003
|
@keydown=${(e) => {
|
|
3930
4004
|
e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
|
|
3931
4005
|
}}>
|
|
3932
|
-
<option value="">${
|
|
3933
|
-
<option value="empty">${
|
|
3934
|
-
<option value="non-empty">${
|
|
4006
|
+
<option value="">${k("blankAll")}</option>
|
|
4007
|
+
<option value="empty">${k("emptyOnly")}</option>
|
|
4008
|
+
<option value="non-empty">${k("nonEmptyOnly")}</option>
|
|
3935
4009
|
</select>
|
|
3936
4010
|
</div>
|
|
3937
4011
|
`;
|
|
@@ -4007,13 +4081,13 @@ var q = {
|
|
|
4007
4081
|
@keydown=${(e) => {
|
|
4008
4082
|
e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
|
|
4009
4083
|
}}>
|
|
4010
|
-
<option value="contains">${
|
|
4011
|
-
<option value="starts">${
|
|
4012
|
-
<option value="ends">${
|
|
4013
|
-
<option value="wildcard">${
|
|
4084
|
+
<option value="contains">${k("contains")}</option>
|
|
4085
|
+
<option value="starts">${k("startsWith")}</option>
|
|
4086
|
+
<option value="ends">${k("endsWith")}</option>
|
|
4087
|
+
<option value="wildcard">${k("wildcard")}</option>
|
|
4014
4088
|
</select>
|
|
4015
4089
|
</div>
|
|
4016
|
-
<input class="ft-filter-input" type="text" placeholder=${
|
|
4090
|
+
<input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")}
|
|
4017
4091
|
.value=${t.value}
|
|
4018
4092
|
@input=${(t) => {
|
|
4019
4093
|
let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
|
|
@@ -4064,7 +4138,7 @@ var q = {
|
|
|
4064
4138
|
}}>
|
|
4065
4139
|
${Object.keys(q).map((e) => i`<option value=${e}>${q[e]}</option>`)}
|
|
4066
4140
|
</select>
|
|
4067
|
-
<input class="ft-filter-input ft-num-cond-input" type="number" placeholder=${
|
|
4141
|
+
<input class="ft-filter-input ft-num-cond-input" type="number" placeholder=${k("valuePlaceholder")}
|
|
4068
4142
|
.value=${n.value == null ? "" : String(n.value)}
|
|
4069
4143
|
@input=${(n) => {
|
|
4070
4144
|
let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
|
|
@@ -4125,13 +4199,13 @@ var q = {
|
|
|
4125
4199
|
let t = e.type === "datetime" ? "datetime-local" : "date", n = this._dateFilterState.get(e.key) ?? {};
|
|
4126
4200
|
return i`
|
|
4127
4201
|
<div class="ft-filter-range">
|
|
4128
|
-
<input class="ft-filter-input" type=${t} placeholder=${
|
|
4202
|
+
<input class="ft-filter-input" type=${t} placeholder=${k("fromPlaceholder")}
|
|
4129
4203
|
.value=${n.from ?? ""}
|
|
4130
4204
|
@input=${(t) => this._applyDateFilter(e.key, t, "from")}
|
|
4131
4205
|
@keydown=${(e) => {
|
|
4132
4206
|
e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
|
|
4133
4207
|
}}>
|
|
4134
|
-
<input class="ft-filter-input" type=${t} placeholder=${
|
|
4208
|
+
<input class="ft-filter-input" type=${t} placeholder=${k("toPlaceholder")}
|
|
4135
4209
|
.value=${n.to ?? ""}
|
|
4136
4210
|
@input=${(t) => this._applyDateFilter(e.key, t, "to")}
|
|
4137
4211
|
@keydown=${(e) => {
|
|
@@ -4157,9 +4231,9 @@ var q = {
|
|
|
4157
4231
|
@keydown=${(e) => {
|
|
4158
4232
|
e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
|
|
4159
4233
|
}}>
|
|
4160
|
-
<option value="all">${
|
|
4161
|
-
<option value="true">\u2714 ${
|
|
4162
|
-
<option value="false">\u2718 ${
|
|
4234
|
+
<option value="all">${k("all")}</option>
|
|
4235
|
+
<option value="true">\u2714 ${k("booleanTrue")}</option>
|
|
4236
|
+
<option value="false">\u2718 ${k("booleanFalse")}</option>
|
|
4163
4237
|
</select>
|
|
4164
4238
|
${this._renderEmptyFilterRow(e.key)}
|
|
4165
4239
|
`;
|
|
@@ -4286,7 +4360,7 @@ var q = {
|
|
|
4286
4360
|
}
|
|
4287
4361
|
_updateFillDrag(e) {
|
|
4288
4362
|
if (!this._fillDrag) return;
|
|
4289
|
-
let t = this.getBoundingClientRect(), n = e.clientX - t.left + this._scrollLeft - this._prefixWidth, r = e.clientY
|
|
4363
|
+
let t = this.getBoundingClientRect(), n = e.clientX - t.left + this._scrollLeft - this._prefixWidth, r = this._rowSpaceY(e.clientY), i = this.visibleColumns, a = 0;
|
|
4290
4364
|
for (let e = 0; e < i.length; e++) (this._colLeftOffsets[e] ?? 0) <= n && (a = e);
|
|
4291
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;
|
|
4292
4366
|
u = Math.abs(c) >= Math.abs(l) ? c >= 0 ? {
|
|
@@ -4419,9 +4493,9 @@ var q = {
|
|
|
4419
4493
|
_updateRowDrag(e) {
|
|
4420
4494
|
if (!this._rowDrag) return;
|
|
4421
4495
|
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
|
|
4496
|
+
let t = this.getBoundingClientRect(), n = this._rowSpaceY(e.clientY), r = this.rowHeight, i = Math.round(n / r);
|
|
4423
4497
|
i = Math.max(0, Math.min(this._visibleRowCount, i)), this._rowDrag.rowIndex < i && i--, this._rowDrag.targetIndex = i;
|
|
4424
|
-
let a = this.
|
|
4498
|
+
let a = this._rowBoundaryViewportY(i);
|
|
4425
4499
|
this._rowDragIndicatorY = Math.max(this.headerHeight, Math.min(a, t.height)), this.requestUpdate();
|
|
4426
4500
|
}
|
|
4427
4501
|
_finishRowDrag() {
|
|
@@ -4579,39 +4653,39 @@ var q = {
|
|
|
4579
4653
|
e.key === "Enter" && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
|
|
4580
4654
|
}}>
|
|
4581
4655
|
<div class="ft-find-row">
|
|
4582
|
-
<input class="ft-find-input" type="text" placeholder=${
|
|
4656
|
+
<input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")}
|
|
4583
4657
|
.value=${t}
|
|
4584
4658
|
@input=${(e) => {
|
|
4585
4659
|
this._findState.query = e.target.value, this._findSearch();
|
|
4586
4660
|
}}>
|
|
4587
4661
|
<span class="ft-find-count">${c > 0 ? `${l}/${c}` : t ? "0 results" : ""}</span>
|
|
4588
|
-
<button @click=${() => this._findPrev()} title=${
|
|
4589
|
-
<button @click=${() => this._findNext()} title=${
|
|
4590
|
-
<label title=${
|
|
4662
|
+
<button @click=${() => this._findPrev()} title=${k("findPrevious")}>◀</button>
|
|
4663
|
+
<button @click=${() => this._findNext()} title=${k("findNext")}>▶</button>
|
|
4664
|
+
<label title=${k("matchCase")}><input type="checkbox" ?checked=${r} @change=${(e) => {
|
|
4591
4665
|
this._findState.matchCase = e.target.checked, this._findSearch();
|
|
4592
4666
|
}}> Aa</label>
|
|
4593
|
-
<label title=${
|
|
4667
|
+
<label title=${k("wholeCell")}><input type="checkbox" ?checked=${a} @change=${(e) => {
|
|
4594
4668
|
this._findState.wholeCell = e.target.checked, this._findSearch();
|
|
4595
4669
|
}}> [ ]</label>
|
|
4596
|
-
<button @click=${() => this._closeFindPanel()} title=${
|
|
4670
|
+
<button @click=${() => this._closeFindPanel()} title=${k("closeFind")}>✕</button>
|
|
4597
4671
|
</div>
|
|
4598
4672
|
${e === "replace" ? i`
|
|
4599
4673
|
<div class="ft-find-row">
|
|
4600
|
-
<input class="ft-find-replace-input" type="text" placeholder=${
|
|
4674
|
+
<input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")}
|
|
4601
4675
|
.value=${n}
|
|
4602
4676
|
@input=${(e) => {
|
|
4603
4677
|
this._findState.replaceWith = e.target.value;
|
|
4604
4678
|
}}>
|
|
4605
|
-
<button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${
|
|
4606
|
-
<button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${
|
|
4679
|
+
<button @click=${() => this._replaceOne()} ?disabled=${c === 0}>${k("replace")}</button>
|
|
4680
|
+
<button @click=${() => this._replaceAll()} ?disabled=${c === 0}>${k("replaceAll")}</button>
|
|
4607
4681
|
</div>
|
|
4608
4682
|
` : ""}
|
|
4609
4683
|
</div>
|
|
4610
4684
|
`;
|
|
4611
4685
|
}
|
|
4612
4686
|
render() {
|
|
4613
|
-
let e = this.visibleColumns, t = this.importEnabled && this._isDragOver ? i`<div class="ft-import-overlay">${
|
|
4614
|
-
if (e.length === 0) return i`${t}${n}<div class="ft-empty">${
|
|
4687
|
+
let e = this.visibleColumns, t = this.importEnabled && this._isDragOver ? i`<div class="ft-import-overlay">${k("dropFileToImport")}</div>` : a, n = this.loading ? i`<div class="ft-loading-overlay"></div>` : a;
|
|
4688
|
+
if (e.length === 0) return i`${t}${n}<div class="ft-empty">${k("noColumnsDefined")}</div>`;
|
|
4615
4689
|
let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
|
|
4616
4690
|
for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
|
|
4617
4691
|
let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
|
|
@@ -4920,4 +4994,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
|
|
|
4920
4994
|
attribute: "max-undo-size"
|
|
4921
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")], $);
|
|
4922
4996
|
//#endregion
|
|
4923
|
-
export {
|
|
4997
|
+
export { O as a, j as i, V as n, D as o, M as r, $ as t };
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -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;
|
package/dist/flex-table.js
CHANGED
|
@@ -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-
|
|
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