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