@iyulab/flex-table 0.41.1 → 0.42.0
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 +31 -0
- package/README.md +14 -1
- package/dist/clipboard/clipboard.d.ts +6 -0
- package/dist/{flex-table-C6PFutM_.js → flex-table-BdnkC234.js} +157 -130
- package/dist/flex-table.d.ts +0 -3
- package/dist/flex-table.js +1 -1
- package/dist/locale.d.ts +1 -1
- package/dist/models/types.d.ts +9 -0
- package/dist/react.js +1 -1
- package/package.json +2 -2
- package/skills/iyulab-flex-table/SKILL.md +1 -2
- package/skills/iyulab-flex-table/references/api.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.42.0] - 2026-10-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`reveal: 'hover'` column option** — the column's content shows only while its row is hovered,
|
|
8
|
+
holds focus or is selected; for a row-actions column, so a list does not repeat the same buttons
|
|
9
|
+
on every row. The content stays focusable (Tab reveals it), touch screens always show it, and it
|
|
10
|
+
is not printed.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **The virtual scroll renders only the rows it needs above the view.** The first row in view was
|
|
15
|
+
computed as if the header and the frozen rows scrolled away with the body, so up to
|
|
16
|
+
(header + frozen rows) ÷ row height extra rows were rendered above the view — ten with eight frozen
|
|
17
|
+
rows. What is visible does not change.
|
|
18
|
+
|
|
19
|
+
## [0.41.2] - 2026-10-03
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **The `datetime` cell editor shows and takes `YYYY-MM-DD HH:mm` in every browser language.** It was the
|
|
24
|
+
native `datetime-local` input, which follows the browser's UI language. It is now a text box in local
|
|
25
|
+
time that reads `2026-10-02 14:05` (`9:05`, a date alone is midnight), stores the local
|
|
26
|
+
`YYYY-MM-DDTHH:mm` string as before, and rejects text it cannot read with `validation-error`
|
|
27
|
+
("Enter a date and time as YYYY-MM-DD HH:mm", new `flexTableLocale` key `notADateTime`).
|
|
28
|
+
- **Pasting `2026-10-02 14:05` into a datetime column stores `2026-10-02T14:05`.** Other text stays text.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **The `@iyulab/components` peer is `>=1.56.0`** — date-times are read with its `parseDateTime`.
|
|
33
|
+
|
|
3
34
|
## [0.41.1] - 2026-10-03
|
|
4
35
|
|
|
5
36
|
### Fixed
|
package/README.md
CHANGED
|
@@ -151,6 +151,7 @@ interface ColumnDefinition {
|
|
|
151
151
|
validator?: CellValidator; // Validate before commit: (value, row, col) => string | null
|
|
152
152
|
conditionalRules?: ConditionalRule[]; // Per-cell style rules, see below
|
|
153
153
|
mergeRepeated?: boolean | ((row, previousRow, col) => boolean); // Merge runs of repeated values, see below
|
|
154
|
+
reveal?: 'always' | 'hover'; // 'hover': show only while the row is hovered, focused or selected (row actions)
|
|
154
155
|
}
|
|
155
156
|
```
|
|
156
157
|
|
|
@@ -160,7 +161,7 @@ The `validator` callback returns `null` if valid, or an error message string. On
|
|
|
160
161
|
|
|
161
162
|
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
163
|
|
|
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.
|
|
164
|
+
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
165
|
|
|
165
166
|
### `format` vs `render`
|
|
166
167
|
|
|
@@ -198,6 +199,18 @@ const columns: ColumnDefinition<Order>[] = [
|
|
|
198
199
|
|
|
199
200
|
Rules are evaluated in order and combined; later matching rules override earlier ones for overlapping style properties.
|
|
200
201
|
|
|
202
|
+
### Row actions that appear on hover
|
|
203
|
+
|
|
204
|
+
A column of row actions (edit, a "more" menu) repeated on every row turns a list into a wall of
|
|
205
|
+
buttons. `reveal: 'hover'` shows that column's content only while its row is hovered, holds focus or
|
|
206
|
+
is selected. The controls stay in the DOM and focusable — Tab reveals them — touch screens (no
|
|
207
|
+
hover) always show them, and they are not printed.
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
{ key: 'actions', label: '', width: 72, editable: false, reveal: 'hover',
|
|
211
|
+
render: (_, row) => html`<u-button size="sm" variant="ghost" aria-label="Edit">…</u-button>` }
|
|
212
|
+
```
|
|
213
|
+
|
|
201
214
|
### Merging Repeated Values
|
|
202
215
|
|
|
203
216
|
A list of child rows under a parent — order lines under an order, boxes under a shipment — repeats the parent's columns on every line. `mergeRepeated` draws each run of repeated values as one merged cell: the value shows once, on the run's first row, and the lines between the run's rows are dropped.
|
|
@@ -17,3 +17,9 @@ export declare function editableNumber(value: number): string;
|
|
|
17
17
|
* negative offsets); a `Date` uses its local day. Anything else is shown as it is.
|
|
18
18
|
*/
|
|
19
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 { dateTextPattern as u, formatDate as d, formatNumber as f, parseDate as p,
|
|
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;
|
|
@@ -918,16 +918,38 @@ var v = r`
|
|
|
918
918
|
outline: 2px solid var(--ft-find-color);
|
|
919
919
|
outline-offset: -2px;
|
|
920
920
|
}
|
|
921
|
+
|
|
922
|
+
/* reveal: 'hover' — a row-actions column shows while the row is hovered, focused or selected.
|
|
923
|
+
opacity (not display/visibility) keeps the controls focusable, so Tab reveals them. */
|
|
924
|
+
.ft-cell.ft-reveal-hover > * {
|
|
925
|
+
opacity: 0;
|
|
926
|
+
transition: opacity var(--u-duration-fast, 140ms) ease-out;
|
|
927
|
+
}
|
|
928
|
+
.ft-row:hover .ft-cell.ft-reveal-hover > *,
|
|
929
|
+
.ft-row:focus-within .ft-cell.ft-reveal-hover > *,
|
|
930
|
+
.ft-row-selected .ft-cell.ft-reveal-hover > *,
|
|
931
|
+
.ft-cell.ft-reveal-hover.ft-active > * {
|
|
932
|
+
opacity: 1;
|
|
933
|
+
}
|
|
934
|
+
@media (hover: none) {
|
|
935
|
+
.ft-cell.ft-reveal-hover > * { opacity: 1; }
|
|
936
|
+
}
|
|
937
|
+
@media (prefers-reduced-motion: reduce) {
|
|
938
|
+
.ft-cell.ft-reveal-hover > * { transition: none; }
|
|
939
|
+
}
|
|
940
|
+
@media print {
|
|
941
|
+
.ft-cell.ft-reveal-hover > * { visibility: hidden; }
|
|
942
|
+
}
|
|
921
943
|
`;
|
|
922
944
|
//#endregion
|
|
923
945
|
//#region src/renderers/format.ts
|
|
924
|
-
function
|
|
925
|
-
return e == null ? "" : typeof t == "function" ? t(e) :
|
|
946
|
+
function b(e, t) {
|
|
947
|
+
return e == null ? "" : typeof t == "function" ? t(e) : x(t) ? C(e, t) : S(e, t);
|
|
926
948
|
}
|
|
927
|
-
function
|
|
949
|
+
function x(e) {
|
|
928
950
|
return /[yMdHhms]/.test(e);
|
|
929
951
|
}
|
|
930
|
-
function
|
|
952
|
+
function S(e, t) {
|
|
931
953
|
let n = typeof e == "number" ? e : Number(e);
|
|
932
954
|
if (isNaN(n)) return String(e);
|
|
933
955
|
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 +962,7 @@ function x(e, t) {
|
|
|
940
962
|
style: "percent"
|
|
941
963
|
}).format(n) : (d = new Intl.NumberFormat(l.get(), u).format(n), a && (d = a + d)), d + "";
|
|
942
964
|
}
|
|
943
|
-
function
|
|
965
|
+
function C(e, t) {
|
|
944
966
|
let n;
|
|
945
967
|
if (e instanceof Date) n = e;
|
|
946
968
|
else if (typeof e == "string" || typeof e == "number") n = new Date(e);
|
|
@@ -951,26 +973,26 @@ function S(e, t) {
|
|
|
951
973
|
}
|
|
952
974
|
//#endregion
|
|
953
975
|
//#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) :
|
|
976
|
+
function w(e, t, n) {
|
|
977
|
+
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
978
|
}
|
|
957
|
-
function
|
|
979
|
+
function T(e, t) {
|
|
958
980
|
if (e == null) return "";
|
|
959
981
|
switch (t.type) {
|
|
960
|
-
case "number": return
|
|
982
|
+
case "number": return O(e);
|
|
961
983
|
case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
|
|
962
|
-
case "date": return
|
|
963
|
-
case "datetime": return
|
|
964
|
-
case "select": return
|
|
984
|
+
case "date": return ee(e);
|
|
985
|
+
case "datetime": return te(e);
|
|
986
|
+
case "select": return E(e, t);
|
|
965
987
|
default: return String(e);
|
|
966
988
|
}
|
|
967
989
|
}
|
|
968
|
-
function
|
|
990
|
+
function E(e, t) {
|
|
969
991
|
if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
|
|
970
992
|
let n = t.options.find((t) => t.value === e);
|
|
971
993
|
return n ? n.label : e == null ? "" : String(e);
|
|
972
994
|
}
|
|
973
|
-
var
|
|
995
|
+
var D = {
|
|
974
996
|
year: "numeric",
|
|
975
997
|
month: "numeric",
|
|
976
998
|
day: "numeric",
|
|
@@ -978,14 +1000,14 @@ var E = {
|
|
|
978
1000
|
minute: "numeric",
|
|
979
1001
|
second: "numeric"
|
|
980
1002
|
};
|
|
981
|
-
function
|
|
1003
|
+
function O(e) {
|
|
982
1004
|
return typeof e == "number" ? Number.isInteger(e) ? f(e) : f(e, { minimumFractionDigits: 1 }) : String(e);
|
|
983
1005
|
}
|
|
984
|
-
function
|
|
1006
|
+
function ee(e) {
|
|
985
1007
|
return e instanceof Date || typeof e == "string" ? d(e) : String(e);
|
|
986
1008
|
}
|
|
987
|
-
function
|
|
988
|
-
return e instanceof Date || typeof e == "string" ? d(e,
|
|
1009
|
+
function te(e) {
|
|
1010
|
+
return e instanceof Date || typeof e == "string" ? d(e, D) : String(e);
|
|
989
1011
|
}
|
|
990
1012
|
//#endregion
|
|
991
1013
|
//#region src/locale.ts
|
|
@@ -1045,6 +1067,7 @@ k.register("en", {
|
|
|
1045
1067
|
dropFileToImport: "Drop file to import (.xlsx / .csv)",
|
|
1046
1068
|
notANumber: "Enter a number",
|
|
1047
1069
|
notADate: "Enter a date as YYYY-MM-DD",
|
|
1070
|
+
notADateTime: "Enter a date and time as YYYY-MM-DD HH:mm",
|
|
1048
1071
|
notInList: "Value must be from the existing list"
|
|
1049
1072
|
}), k.register("ko", {
|
|
1050
1073
|
showHiddenColumns: "숨긴 열 보기",
|
|
@@ -1101,12 +1124,13 @@ k.register("en", {
|
|
|
1101
1124
|
dropFileToImport: "가져올 파일을 놓으세요 (.xlsx / .csv)",
|
|
1102
1125
|
notANumber: "숫자를 입력하세요",
|
|
1103
1126
|
notADate: "날짜를 YYYY-MM-DD 로 입력하세요",
|
|
1127
|
+
notADateTime: "날짜와 시간을 YYYY-MM-DD HH:mm 으로 입력하세요",
|
|
1104
1128
|
notInList: "목록에 있는 값이어야 합니다"
|
|
1105
1129
|
});
|
|
1106
1130
|
var A = (e, t) => k.text(e, t);
|
|
1107
1131
|
//#endregion
|
|
1108
1132
|
//#region src/core/selection.ts
|
|
1109
|
-
function
|
|
1133
|
+
function ne(e) {
|
|
1110
1134
|
return {
|
|
1111
1135
|
startRow: Math.min(e.startRow, e.endRow),
|
|
1112
1136
|
startCol: Math.min(e.startCol, e.endCol),
|
|
@@ -1114,7 +1138,7 @@ function te(e) {
|
|
|
1114
1138
|
endCol: Math.max(e.startCol, e.endCol)
|
|
1115
1139
|
};
|
|
1116
1140
|
}
|
|
1117
|
-
var
|
|
1141
|
+
var re = class {
|
|
1118
1142
|
constructor() {
|
|
1119
1143
|
this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
|
|
1120
1144
|
}
|
|
@@ -1141,7 +1165,7 @@ var ne = class {
|
|
|
1141
1165
|
return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
|
|
1142
1166
|
row: e,
|
|
1143
1167
|
col: t
|
|
1144
|
-
}, this.rangeAnchor && (this.range =
|
|
1168
|
+
}, this.rangeAnchor && (this.range = ne({
|
|
1145
1169
|
startRow: this.rangeAnchor.row,
|
|
1146
1170
|
startCol: this.rangeAnchor.col,
|
|
1147
1171
|
endRow: e,
|
|
@@ -1212,7 +1236,7 @@ var ne = class {
|
|
|
1212
1236
|
shiftMoveRight() {
|
|
1213
1237
|
return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
|
|
1214
1238
|
}
|
|
1215
|
-
},
|
|
1239
|
+
}, ie = class {
|
|
1216
1240
|
constructor() {
|
|
1217
1241
|
this.current = null;
|
|
1218
1242
|
}
|
|
@@ -1294,7 +1318,7 @@ var ne = class {
|
|
|
1294
1318
|
};
|
|
1295
1319
|
//#endregion
|
|
1296
1320
|
//#region src/core/filtering.ts
|
|
1297
|
-
function
|
|
1321
|
+
function ae(e, t, n) {
|
|
1298
1322
|
if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
|
|
1299
1323
|
let r = [];
|
|
1300
1324
|
for (let i = 0; i < e.length; i++) {
|
|
@@ -1313,9 +1337,9 @@ function ie(e, t, n) {
|
|
|
1313
1337
|
}
|
|
1314
1338
|
//#endregion
|
|
1315
1339
|
//#region src/core/undo.ts
|
|
1316
|
-
var
|
|
1340
|
+
var oe = 100, M = class {
|
|
1317
1341
|
constructor() {
|
|
1318
|
-
this._undoStack = [], this._redoStack = [], this._maxSize =
|
|
1342
|
+
this._undoStack = [], this._redoStack = [], this._maxSize = oe;
|
|
1319
1343
|
}
|
|
1320
1344
|
get maxSize() {
|
|
1321
1345
|
return this._maxSize;
|
|
@@ -1352,7 +1376,7 @@ var ae = 100, M = class {
|
|
|
1352
1376
|
};
|
|
1353
1377
|
//#endregion
|
|
1354
1378
|
//#region src/clipboard/clipboard.ts
|
|
1355
|
-
function
|
|
1379
|
+
function se(e, t, n) {
|
|
1356
1380
|
let r = [];
|
|
1357
1381
|
for (let i = n.startRow; i <= n.endRow; i++) {
|
|
1358
1382
|
let a = e[i], o = [];
|
|
@@ -1362,19 +1386,20 @@ function oe(e, t, n) {
|
|
|
1362
1386
|
}
|
|
1363
1387
|
r.push(o);
|
|
1364
1388
|
}
|
|
1365
|
-
return
|
|
1389
|
+
return _(r);
|
|
1366
1390
|
}
|
|
1367
1391
|
function N(e, t) {
|
|
1368
1392
|
if (e === "") return null;
|
|
1369
1393
|
switch (t.type) {
|
|
1370
1394
|
case "number": {
|
|
1371
|
-
let t =
|
|
1395
|
+
let t = h(e);
|
|
1372
1396
|
if (t !== null) return t;
|
|
1373
1397
|
let n = Number(e.trim());
|
|
1374
1398
|
return e.trim() !== "" && Number.isFinite(n) ? n : e;
|
|
1375
1399
|
}
|
|
1376
1400
|
case "boolean": return e.toLowerCase() === "true" || e === "1";
|
|
1377
1401
|
case "date": return p(e) ?? e;
|
|
1402
|
+
case "datetime": return m(e) ?? e;
|
|
1378
1403
|
default: return e;
|
|
1379
1404
|
}
|
|
1380
1405
|
}
|
|
@@ -1384,15 +1409,24 @@ function P(e) {
|
|
|
1384
1409
|
let n = new Intl.NumberFormat(l.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
|
|
1385
1410
|
return n && n !== "." ? t.replace(".", n) : t;
|
|
1386
1411
|
}
|
|
1387
|
-
function
|
|
1412
|
+
function ce(e) {
|
|
1388
1413
|
if (e == null || e === "") return "";
|
|
1389
1414
|
if (e instanceof Date) return Number.isNaN(e.getTime()) ? "" : `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
|
|
1390
1415
|
let t = String(e), n = /^(\d{4}-\d{2}-\d{2})(?:$|T)/.exec(t);
|
|
1391
1416
|
return n ? n[1] : t;
|
|
1392
1417
|
}
|
|
1418
|
+
function le(e) {
|
|
1419
|
+
if (e == null || e === "") return "";
|
|
1420
|
+
let t = e instanceof Date ? "" : String(e), n = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(t);
|
|
1421
|
+
if (n) return `${n[1]} ${n[2]}`;
|
|
1422
|
+
let r = e instanceof Date ? e : /^\d{4}-\d{2}-\d{2}T/.test(t) ? new Date(t) : null;
|
|
1423
|
+
if (!r || Number.isNaN(r.getTime())) return t;
|
|
1424
|
+
let i = (e) => String(e).padStart(2, "0");
|
|
1425
|
+
return `${r.getFullYear()}-${i(r.getMonth() + 1)}-${i(r.getDate())} ${i(r.getHours())}:${i(r.getMinutes())}`;
|
|
1426
|
+
}
|
|
1393
1427
|
//#endregion
|
|
1394
1428
|
//#region src/export/xlsx-writer.ts
|
|
1395
|
-
var
|
|
1429
|
+
var ue = (() => {
|
|
1396
1430
|
let e = /* @__PURE__ */ new Uint32Array(256);
|
|
1397
1431
|
for (let t = 0; t < 256; t++) {
|
|
1398
1432
|
let n = t;
|
|
@@ -1401,16 +1435,16 @@ var ce = (() => {
|
|
|
1401
1435
|
}
|
|
1402
1436
|
return e;
|
|
1403
1437
|
})();
|
|
1404
|
-
function
|
|
1438
|
+
function de(e) {
|
|
1405
1439
|
let t = 4294967295;
|
|
1406
|
-
for (let n = 0; n < e.length; n++) t =
|
|
1440
|
+
for (let n = 0; n < e.length; n++) t = ue[(t ^ e[n]) & 255] ^ t >>> 8;
|
|
1407
1441
|
return (t ^ 4294967295) >>> 0;
|
|
1408
1442
|
}
|
|
1409
1443
|
var F = new TextEncoder();
|
|
1410
|
-
function
|
|
1444
|
+
function fe(e) {
|
|
1411
1445
|
let t = [], n = [], r = 0;
|
|
1412
1446
|
for (let i of e) {
|
|
1413
|
-
let e = F.encode(i.name), a =
|
|
1447
|
+
let e = F.encode(i.name), a = de(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
|
|
1414
1448
|
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);
|
|
1415
1449
|
let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
|
|
1416
1450
|
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;
|
|
@@ -1430,27 +1464,27 @@ function I(e) {
|
|
|
1430
1464
|
function L(e) {
|
|
1431
1465
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1432
1466
|
}
|
|
1433
|
-
function
|
|
1467
|
+
function pe(e) {
|
|
1434
1468
|
let t = "";
|
|
1435
1469
|
for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
|
|
1436
1470
|
return t;
|
|
1437
1471
|
}
|
|
1438
1472
|
function R(e, t) {
|
|
1439
|
-
return
|
|
1473
|
+
return pe(t) + (e + 1);
|
|
1440
1474
|
}
|
|
1441
|
-
function
|
|
1475
|
+
function me(e) {
|
|
1442
1476
|
let t = Date.UTC(1899, 11, 30);
|
|
1443
1477
|
return (e.getTime() - t) / 864e5;
|
|
1444
1478
|
}
|
|
1445
|
-
var
|
|
1446
|
-
function
|
|
1479
|
+
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>";
|
|
1480
|
+
function ye(e, t) {
|
|
1447
1481
|
let n = [], r = t.map((e, t) => `<c r="${R(0, t)}" t="str" s="2"><v>${L(e.label)}</v></c>`);
|
|
1448
1482
|
return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
|
|
1449
1483
|
let i = t.map((t, n) => {
|
|
1450
1484
|
let i = R(r + 1, n), a = e[t.key];
|
|
1451
1485
|
if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
|
|
1452
1486
|
let o = t.type ?? "text";
|
|
1453
|
-
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>${
|
|
1487
|
+
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>`;
|
|
1454
1488
|
});
|
|
1455
1489
|
n.push(`<row r="${r + 2}">${i.join("")}</row>`);
|
|
1456
1490
|
}), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -1458,24 +1492,24 @@ function _e(e, t) {
|
|
|
1458
1492
|
<sheetData>${n.join("")}</sheetData>
|
|
1459
1493
|
</worksheet>`;
|
|
1460
1494
|
}
|
|
1461
|
-
function
|
|
1462
|
-
let n =
|
|
1463
|
-
return
|
|
1495
|
+
function be(e, t) {
|
|
1496
|
+
let n = ye(e, t);
|
|
1497
|
+
return fe([
|
|
1464
1498
|
{
|
|
1465
1499
|
name: "[Content_Types].xml",
|
|
1466
|
-
data: F.encode(
|
|
1500
|
+
data: F.encode(z)
|
|
1467
1501
|
},
|
|
1468
1502
|
{
|
|
1469
1503
|
name: "_rels/.rels",
|
|
1470
|
-
data: F.encode(
|
|
1504
|
+
data: F.encode(he)
|
|
1471
1505
|
},
|
|
1472
1506
|
{
|
|
1473
1507
|
name: "xl/workbook.xml",
|
|
1474
|
-
data: F.encode(
|
|
1508
|
+
data: F.encode(ge)
|
|
1475
1509
|
},
|
|
1476
1510
|
{
|
|
1477
1511
|
name: "xl/_rels/workbook.xml.rels",
|
|
1478
|
-
data: F.encode(
|
|
1512
|
+
data: F.encode(_e)
|
|
1479
1513
|
},
|
|
1480
1514
|
{
|
|
1481
1515
|
name: "xl/worksheets/sheet1.xml",
|
|
@@ -1483,7 +1517,7 @@ function ve(e, t) {
|
|
|
1483
1517
|
},
|
|
1484
1518
|
{
|
|
1485
1519
|
name: "xl/styles.xml",
|
|
1486
|
-
data: F.encode(
|
|
1520
|
+
data: F.encode(ve)
|
|
1487
1521
|
}
|
|
1488
1522
|
]);
|
|
1489
1523
|
}
|
|
@@ -1493,20 +1527,20 @@ function B(e, t, n) {
|
|
|
1493
1527
|
switch (n) {
|
|
1494
1528
|
case "csv": return V(e, t, ",");
|
|
1495
1529
|
case "tsv": return V(e, t, " ");
|
|
1496
|
-
case "json": return
|
|
1497
|
-
case "xlsx": return
|
|
1530
|
+
case "json": return Se(e, t);
|
|
1531
|
+
case "xlsx": return be(e, t);
|
|
1498
1532
|
}
|
|
1499
1533
|
}
|
|
1500
|
-
function
|
|
1534
|
+
function xe(e, t) {
|
|
1501
1535
|
return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
|
|
1502
1536
|
}
|
|
1503
1537
|
function V(e, t, n) {
|
|
1504
|
-
return [t.map((e) => H(e.label, n)).join(n), ...e.map((e) => t.map((t) => H(
|
|
1538
|
+
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");
|
|
1505
1539
|
}
|
|
1506
1540
|
function H(e, t) {
|
|
1507
1541
|
return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
|
|
1508
1542
|
}
|
|
1509
|
-
function
|
|
1543
|
+
function Se(e, t) {
|
|
1510
1544
|
let n = e.map((e) => {
|
|
1511
1545
|
let n = {};
|
|
1512
1546
|
for (let r of t) {
|
|
@@ -1517,35 +1551,35 @@ function be(e, t) {
|
|
|
1517
1551
|
});
|
|
1518
1552
|
return JSON.stringify(n, null, 2);
|
|
1519
1553
|
}
|
|
1520
|
-
function
|
|
1554
|
+
function Ce(e, t, n) {
|
|
1521
1555
|
let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
|
|
1522
1556
|
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);
|
|
1523
1557
|
}
|
|
1524
|
-
var
|
|
1558
|
+
var U = {
|
|
1525
1559
|
csv: "text/csv;charset=utf-8",
|
|
1526
1560
|
tsv: "text/tab-separated-values;charset=utf-8",
|
|
1527
1561
|
json: "application/json;charset=utf-8",
|
|
1528
1562
|
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
1529
|
-
},
|
|
1563
|
+
}, we = {
|
|
1530
1564
|
csv: ".csv",
|
|
1531
1565
|
tsv: ".tsv",
|
|
1532
1566
|
json: ".json",
|
|
1533
1567
|
xlsx: ".xlsx"
|
|
1534
1568
|
};
|
|
1535
|
-
function we(e) {
|
|
1536
|
-
return Se[e];
|
|
1537
|
-
}
|
|
1538
1569
|
function Te(e) {
|
|
1539
|
-
return
|
|
1570
|
+
return U[e];
|
|
1571
|
+
}
|
|
1572
|
+
function Ee(e) {
|
|
1573
|
+
return we[e];
|
|
1540
1574
|
}
|
|
1541
1575
|
//#endregion
|
|
1542
1576
|
//#region src/export/xlsx-reader.ts
|
|
1543
|
-
function
|
|
1577
|
+
function De(e) {
|
|
1544
1578
|
for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
|
|
1545
1579
|
throw Error("XLSX: End of central directory not found — not a valid ZIP file");
|
|
1546
1580
|
}
|
|
1547
|
-
function
|
|
1548
|
-
let t =
|
|
1581
|
+
function Oe(e) {
|
|
1582
|
+
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;
|
|
1549
1583
|
for (; o < s && e.getUint32(o, !0) === 33639248;) {
|
|
1550
1584
|
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));
|
|
1551
1585
|
a.push({
|
|
@@ -1558,7 +1592,7 @@ function De(e) {
|
|
|
1558
1592
|
}
|
|
1559
1593
|
return a;
|
|
1560
1594
|
}
|
|
1561
|
-
async function
|
|
1595
|
+
async function ke(e) {
|
|
1562
1596
|
let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1563
1597
|
n.write(e), n.close();
|
|
1564
1598
|
let i = [];
|
|
@@ -1571,28 +1605,28 @@ async function Oe(e) {
|
|
|
1571
1605
|
for (let e of i) o.set(e, s), s += e.length;
|
|
1572
1606
|
return o;
|
|
1573
1607
|
}
|
|
1574
|
-
async function
|
|
1608
|
+
async function Ae(e, t) {
|
|
1575
1609
|
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);
|
|
1576
1610
|
if (t.compressionMethod === 0) return o.slice();
|
|
1577
|
-
if (t.compressionMethod === 8) return
|
|
1611
|
+
if (t.compressionMethod === 8) return ke(o);
|
|
1578
1612
|
throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
|
|
1579
1613
|
}
|
|
1580
|
-
async function
|
|
1581
|
-
let t = new DataView(e), n =
|
|
1582
|
-
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await
|
|
1614
|
+
async function je(e) {
|
|
1615
|
+
let t = new DataView(e), n = Oe(t), r = /* @__PURE__ */ new Map();
|
|
1616
|
+
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ae(t, e));
|
|
1583
1617
|
return r;
|
|
1584
1618
|
}
|
|
1585
|
-
var
|
|
1586
|
-
function
|
|
1587
|
-
let t =
|
|
1619
|
+
var Me = new TextDecoder("utf-8");
|
|
1620
|
+
function W(e) {
|
|
1621
|
+
let t = Me.decode(e);
|
|
1588
1622
|
return new DOMParser().parseFromString(t, "application/xml");
|
|
1589
1623
|
}
|
|
1590
|
-
function
|
|
1624
|
+
function Ne(e) {
|
|
1591
1625
|
if (!e) return [];
|
|
1592
|
-
let t =
|
|
1626
|
+
let t = W(e);
|
|
1593
1627
|
return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
|
|
1594
1628
|
}
|
|
1595
|
-
var
|
|
1629
|
+
var Pe = /* @__PURE__ */ new Set([
|
|
1596
1630
|
14,
|
|
1597
1631
|
15,
|
|
1598
1632
|
16,
|
|
@@ -1612,37 +1646,37 @@ var Ne = /* @__PURE__ */ new Set([
|
|
|
1612
1646
|
57,
|
|
1613
1647
|
58
|
|
1614
1648
|
]);
|
|
1615
|
-
function
|
|
1649
|
+
function Fe(e) {
|
|
1616
1650
|
let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
|
|
1617
1651
|
return /[dy]/i.test(t);
|
|
1618
1652
|
}
|
|
1619
|
-
function
|
|
1653
|
+
function Ie(e) {
|
|
1620
1654
|
let t = /* @__PURE__ */ new Set();
|
|
1621
1655
|
if (!e) return t;
|
|
1622
|
-
let n =
|
|
1656
|
+
let n = W(e), r = /* @__PURE__ */ new Map();
|
|
1623
1657
|
for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
|
|
1624
1658
|
return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
|
|
1625
1659
|
let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
|
|
1626
|
-
(a === void 0 ?
|
|
1660
|
+
(a === void 0 ? Pe.has(i) : Fe(a)) && t.add(n);
|
|
1627
1661
|
}), t;
|
|
1628
1662
|
}
|
|
1629
|
-
function
|
|
1663
|
+
function Le(e) {
|
|
1630
1664
|
if (!e) return !1;
|
|
1631
|
-
let t =
|
|
1665
|
+
let t = W(e).querySelector("workbookPr")?.getAttribute("date1904");
|
|
1632
1666
|
return t === "1" || t === "true";
|
|
1633
1667
|
}
|
|
1634
|
-
function
|
|
1668
|
+
function Re(e, t) {
|
|
1635
1669
|
return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
|
|
1636
1670
|
}
|
|
1637
|
-
function
|
|
1638
|
-
let i =
|
|
1671
|
+
function ze(e, t, n, r) {
|
|
1672
|
+
let i = W(e).querySelectorAll("row");
|
|
1639
1673
|
if (i.length === 0) return [];
|
|
1640
1674
|
let a = 0, o = /* @__PURE__ */ new Map();
|
|
1641
1675
|
for (let e of i) {
|
|
1642
1676
|
let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
|
|
1643
1677
|
o.set(i, s);
|
|
1644
1678
|
for (let i of e.querySelectorAll("c")) {
|
|
1645
|
-
let e =
|
|
1679
|
+
let e = Be(i.getAttribute("r") ?? "");
|
|
1646
1680
|
e > a && (a = e);
|
|
1647
1681
|
let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
|
|
1648
1682
|
if (o === "s") d = t[parseInt(l, 10)] ?? "";
|
|
@@ -1651,7 +1685,7 @@ function Le(e, t, n, r) {
|
|
|
1651
1685
|
else if (l === "") d = "";
|
|
1652
1686
|
else {
|
|
1653
1687
|
let e = parseFloat(l);
|
|
1654
|
-
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ?
|
|
1688
|
+
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Re(e, r) : l;
|
|
1655
1689
|
}
|
|
1656
1690
|
s.set(e, d);
|
|
1657
1691
|
}
|
|
@@ -1665,13 +1699,13 @@ function Le(e, t, n, r) {
|
|
|
1665
1699
|
}
|
|
1666
1700
|
return c;
|
|
1667
1701
|
}
|
|
1668
|
-
function
|
|
1702
|
+
function Be(e) {
|
|
1669
1703
|
let t = 0, n = 0;
|
|
1670
1704
|
for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
|
|
1671
1705
|
return t - 1;
|
|
1672
1706
|
}
|
|
1673
|
-
async function
|
|
1674
|
-
let t = await
|
|
1707
|
+
async function Ve(e) {
|
|
1708
|
+
let t = await je(e), n = Ne(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
|
|
1675
1709
|
if (!r) {
|
|
1676
1710
|
for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
|
|
1677
1711
|
r = n;
|
|
@@ -1679,7 +1713,7 @@ async function ze(e) {
|
|
|
1679
1713
|
}
|
|
1680
1714
|
}
|
|
1681
1715
|
if (!r) throw Error("XLSX: No worksheet found");
|
|
1682
|
-
let i =
|
|
1716
|
+
let i = Ie(t.get("xl/styles.xml")), a = Le(t.get("xl/workbook.xml")), o = ze(r, n, i, a);
|
|
1683
1717
|
return o.length === 0 ? {
|
|
1684
1718
|
headers: [],
|
|
1685
1719
|
rows: []
|
|
@@ -1710,14 +1744,14 @@ var q = {
|
|
|
1710
1744
|
lt: "<",
|
|
1711
1745
|
gte: "≥",
|
|
1712
1746
|
lte: "≤"
|
|
1713
|
-
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5,
|
|
1747
|
+
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5, He = 200, $ = class extends n {
|
|
1714
1748
|
constructor(...e) {
|
|
1715
|
-
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
|
|
1749
|
+
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 = () => {
|
|
1716
1750
|
this._commitCommentPopup();
|
|
1717
1751
|
}, 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();
|
|
1718
1752
|
}
|
|
1719
1753
|
static {
|
|
1720
|
-
this.styles =
|
|
1754
|
+
this.styles = y;
|
|
1721
1755
|
}
|
|
1722
1756
|
get data() {
|
|
1723
1757
|
return this._data;
|
|
@@ -2082,7 +2116,7 @@ var q = {
|
|
|
2082
2116
|
return B(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
|
|
2083
2117
|
}
|
|
2084
2118
|
exportToFile(e, t) {
|
|
2085
|
-
|
|
2119
|
+
Ce(this.exportToString(e), t ?? `export${Ee(e)}`, Te(e));
|
|
2086
2120
|
}
|
|
2087
2121
|
setComment(e, t, n) {
|
|
2088
2122
|
let r = this.getComment(e, t);
|
|
@@ -2139,10 +2173,10 @@ var q = {
|
|
|
2139
2173
|
async importFromFile(e) {
|
|
2140
2174
|
let t = e.name.toLowerCase();
|
|
2141
2175
|
if (t.endsWith(".xlsx")) {
|
|
2142
|
-
let t = await
|
|
2176
|
+
let t = await Ve(await e.arrayBuffer());
|
|
2143
2177
|
this._applyImportedSheet(t);
|
|
2144
2178
|
} else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
|
|
2145
|
-
let t = await e.text(), n =
|
|
2179
|
+
let t = await e.text(), n = g(t);
|
|
2146
2180
|
this._applyImportedRows(n);
|
|
2147
2181
|
} else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
|
|
2148
2182
|
}
|
|
@@ -2258,10 +2292,10 @@ var q = {
|
|
|
2258
2292
|
return Math.max(0, this._visibleRowCount - this._frozenRowCount) * this.rowHeight;
|
|
2259
2293
|
}
|
|
2260
2294
|
get visibleRange() {
|
|
2261
|
-
let e = this._frozenRowCount, t = Math.max(0, this._scrollTop
|
|
2295
|
+
let e = this._frozenRowCount, t = e + Math.floor(Math.max(0, this._scrollTop) / this.rowHeight), n = Math.max(e, t - Q), r = Math.max(0, this._viewportHeight - this.headerHeight - this.frozenRowsHeight), i = Math.ceil(r / this.rowHeight) + 1;
|
|
2262
2296
|
return {
|
|
2263
|
-
start:
|
|
2264
|
-
end: Math.min(this._visibleRowCount,
|
|
2297
|
+
start: n,
|
|
2298
|
+
end: Math.min(this._visibleRowCount, t + i + Q)
|
|
2265
2299
|
};
|
|
2266
2300
|
}
|
|
2267
2301
|
connectedCallback() {
|
|
@@ -2332,7 +2366,7 @@ var q = {
|
|
|
2332
2366
|
this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
|
|
2333
2367
|
return;
|
|
2334
2368
|
}
|
|
2335
|
-
if (this._filteredIndices =
|
|
2369
|
+
if (this._filteredIndices = ae(this.data, this._filters, (e, t, n) => {
|
|
2336
2370
|
this.dispatchEvent(new CustomEvent("filter-error", {
|
|
2337
2371
|
detail: {
|
|
2338
2372
|
error: e,
|
|
@@ -2362,7 +2396,7 @@ var q = {
|
|
|
2362
2396
|
e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
|
|
2363
2397
|
}
|
|
2364
2398
|
_warnIfUnconstrained() {
|
|
2365
|
-
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount <
|
|
2399
|
+
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.`));
|
|
2366
2400
|
}
|
|
2367
2401
|
_onScroll() {
|
|
2368
2402
|
this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
|
|
@@ -2516,8 +2550,8 @@ var q = {
|
|
|
2516
2550
|
}));
|
|
2517
2551
|
return;
|
|
2518
2552
|
}
|
|
2519
|
-
if (a.type === "number" && typeof e == "string" || a.type === "date" && typeof e == "string" && p(e) === null) {
|
|
2520
|
-
let t = A(a.type === "number" ? "notANumber" : "notADate");
|
|
2553
|
+
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) {
|
|
2554
|
+
let t = A(a.type === "number" ? "notANumber" : a.type === "date" ? "notADate" : "notADateTime");
|
|
2521
2555
|
this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
|
|
2522
2556
|
detail: {
|
|
2523
2557
|
row: i,
|
|
@@ -2581,7 +2615,7 @@ var q = {
|
|
|
2581
2615
|
}));
|
|
2582
2616
|
}
|
|
2583
2617
|
_onEditorKeyDown(e) {
|
|
2584
|
-
if (!
|
|
2618
|
+
if (!v(e)) {
|
|
2585
2619
|
if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
|
|
2586
2620
|
if (e.key === "ArrowDown") {
|
|
2587
2621
|
e.preventDefault(), e.stopPropagation();
|
|
@@ -2649,7 +2683,7 @@ var q = {
|
|
|
2649
2683
|
].includes(t) && this._handleCtrlKey(e)) return;
|
|
2650
2684
|
}
|
|
2651
2685
|
if (t.length !== 0 && this._visibleRowCount !== 0) {
|
|
2652
|
-
if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !
|
|
2686
|
+
if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !v(e)) {
|
|
2653
2687
|
e.preventDefault();
|
|
2654
2688
|
let n = t[this._activeCell.col];
|
|
2655
2689
|
n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n);
|
|
@@ -2737,7 +2771,7 @@ var q = {
|
|
|
2737
2771
|
async _handleCopy(e) {
|
|
2738
2772
|
let t = this._selection.getEffectiveRange();
|
|
2739
2773
|
if (!t) return;
|
|
2740
|
-
let n = this.visibleColumns, r =
|
|
2774
|
+
let n = this.visibleColumns, r = se(this._sortedIndices.map((e) => this.data[e]), n, t);
|
|
2741
2775
|
try {
|
|
2742
2776
|
await navigator.clipboard.writeText(r);
|
|
2743
2777
|
} catch (e) {
|
|
@@ -2763,7 +2797,7 @@ var q = {
|
|
|
2763
2797
|
if (!this._activeCell) return;
|
|
2764
2798
|
let e = await this._readClipboardText();
|
|
2765
2799
|
if (e == null) return;
|
|
2766
|
-
let t =
|
|
2800
|
+
let t = g(e);
|
|
2767
2801
|
if (t.length === 0) return;
|
|
2768
2802
|
let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
|
|
2769
2803
|
if (r.length > 0 || n.length > 0) {
|
|
@@ -3492,7 +3526,7 @@ var q = {
|
|
|
3492
3526
|
i[t] = {
|
|
3493
3527
|
...i[t],
|
|
3494
3528
|
text: r,
|
|
3495
|
-
value: r.trim() === "" ? null :
|
|
3529
|
+
value: r.trim() === "" ? null : h(r)
|
|
3496
3530
|
}, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
|
|
3497
3531
|
}}
|
|
3498
3532
|
@keydown=${(e) => {
|
|
@@ -3998,7 +4032,7 @@ var q = {
|
|
|
3998
4032
|
this._closeFindPanel();
|
|
3999
4033
|
return;
|
|
4000
4034
|
}
|
|
4001
|
-
e.key === "Enter" && !
|
|
4035
|
+
e.key === "Enter" && !v(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
|
|
4002
4036
|
}}>
|
|
4003
4037
|
<div class="ft-find-row">
|
|
4004
4038
|
<input class="ft-find-input" type="text" placeholder=${A("findPlaceholder")}
|
|
@@ -4209,7 +4243,7 @@ var q = {
|
|
|
4209
4243
|
${this._renderEditor(e, t)}
|
|
4210
4244
|
</div>
|
|
4211
4245
|
`;
|
|
4212
|
-
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,
|
|
4246
|
+
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 = [
|
|
4213
4247
|
"ft-cell",
|
|
4214
4248
|
`ft-type-${t.type ?? "text"}`,
|
|
4215
4249
|
`ft-align-${G(t)}`,
|
|
@@ -4220,10 +4254,11 @@ var q = {
|
|
|
4220
4254
|
S ? "ft-find-current" : x ? "ft-find-match" : "",
|
|
4221
4255
|
o ? `ft-merge-${o.headParity}` : "",
|
|
4222
4256
|
o?.continues ? "ft-merge-continued" : "",
|
|
4223
|
-
o?.opensDown ? "ft-merge-open" : ""
|
|
4257
|
+
o?.opensDown ? "ft-merge-open" : "",
|
|
4258
|
+
t.reveal === "hover" ? "ft-reveal-hover" : ""
|
|
4224
4259
|
].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;
|
|
4225
4260
|
return i`
|
|
4226
|
-
<div class=${D ?
|
|
4261
|
+
<div class=${D ? C + " ft-has-comment" : C}
|
|
4227
4262
|
role="gridcell"
|
|
4228
4263
|
aria-colindex=${r + 1}
|
|
4229
4264
|
data-col-index=${r}
|
|
@@ -4237,7 +4272,7 @@ var q = {
|
|
|
4237
4272
|
@click=${(e) => this._onCellClickEvent(e, n, r)}
|
|
4238
4273
|
@dblclick=${() => this._onCellDblClick(n, r)}>
|
|
4239
4274
|
${O}
|
|
4240
|
-
${
|
|
4275
|
+
${w(e[t.key], e, t)}
|
|
4241
4276
|
</div>
|
|
4242
4277
|
`;
|
|
4243
4278
|
}
|
|
@@ -4252,19 +4287,16 @@ var q = {
|
|
|
4252
4287
|
`;
|
|
4253
4288
|
if (t.type === "date") return i`
|
|
4254
4289
|
<input class="ft-editor ft-editor-date" type="text" inputmode="numeric" placeholder=${u()}
|
|
4255
|
-
.value=${
|
|
4290
|
+
.value=${ce(n)}
|
|
4256
4291
|
@keydown=${this._onEditorKeyDown}
|
|
4257
4292
|
@blur=${() => this._commitEdit()}>
|
|
4258
4293
|
`;
|
|
4259
|
-
if (t.type === "datetime")
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
<input class="ft-editor" type="datetime-local"
|
|
4263
|
-
.value=${e}
|
|
4294
|
+
if (t.type === "datetime") return i`
|
|
4295
|
+
<input class="ft-editor ft-editor-datetime" type="text" placeholder=${`${u()} HH:mm`}
|
|
4296
|
+
.value=${le(n)}
|
|
4264
4297
|
@keydown=${this._onEditorKeyDown}
|
|
4265
4298
|
@blur=${() => this._commitEdit()}>
|
|
4266
4299
|
`;
|
|
4267
|
-
}
|
|
4268
4300
|
if (t.type === "select" && t.options && t.options.length > 0) {
|
|
4269
4301
|
let e = t.options, r = typeof e[0] == "string";
|
|
4270
4302
|
return i`
|
|
@@ -4305,11 +4337,6 @@ var q = {
|
|
|
4305
4337
|
@blur=${() => this._commitEdit()}>
|
|
4306
4338
|
`;
|
|
4307
4339
|
}
|
|
4308
|
-
_toDateTimeInputValue(e) {
|
|
4309
|
-
if (!e) return "";
|
|
4310
|
-
let t = e instanceof Date ? e : new Date(String(e));
|
|
4311
|
-
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")}`;
|
|
4312
|
-
}
|
|
4313
4340
|
};
|
|
4314
4341
|
K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
|
|
4315
4342
|
type: Array,
|
|
@@ -4367,4 +4394,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
|
|
|
4367
4394
|
attribute: "max-undo-size"
|
|
4368
4395
|
})], $.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")], $);
|
|
4369
4396
|
//#endregion
|
|
4370
|
-
export { j as a, M as i, G as n, k as o, B as r,
|
|
4397
|
+
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,9 +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
|
-
/** Convert value to YYYY-MM-DDTHH:mm for datetime-local input (local timezone) */
|
|
530
|
-
private _toDateTimeInputValue;
|
|
531
528
|
}
|
|
532
529
|
declare global {
|
|
533
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-BdnkC234.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' | 'notADate' | '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/models/types.d.ts
CHANGED
|
@@ -115,6 +115,15 @@ export interface ColumnDefinition<T = DataRow> {
|
|
|
115
115
|
* the top of the scrolled view and below frozen rows, so it never scrolls out of sight.
|
|
116
116
|
*/
|
|
117
117
|
mergeRepeated?: boolean | ((row: T, previousRow: T, col: ColumnDefinition<T>) => boolean);
|
|
118
|
+
/**
|
|
119
|
+
* When the column's content shows.
|
|
120
|
+
* - `'always'` (default)
|
|
121
|
+
* - `'hover'`: only while the row is hovered, holds focus, or is selected — for a row-actions
|
|
122
|
+
* column (edit, a "more" menu), so a list does not repeat the same buttons on every row. The
|
|
123
|
+
* content stays in the DOM and keyboard focus reveals it; on touch screens (no hover) it is
|
|
124
|
+
* always shown, and it is not printed.
|
|
125
|
+
*/
|
|
126
|
+
reveal?: 'always' | 'hover';
|
|
118
127
|
}
|
|
119
128
|
/** Style applied to a cell by a conditional formatting rule */
|
|
120
129
|
export interface CellStyle {
|
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-BdnkC234.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.
|
|
3
|
+
"version": "0.42.0",
|
|
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
|
},
|
|
@@ -4,7 +4,6 @@ description: Spreadsheet-grade data grid web component (`<flex-table>`, built wi
|
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: iyulab
|
|
7
|
-
version: "0.40.1"
|
|
8
7
|
---
|
|
9
8
|
|
|
10
9
|
# @iyulab/flex-table
|
|
@@ -67,7 +66,7 @@ as `text`). See `references/api.md` for every field.
|
|
|
67
66
|
- `editor` returns a Lit template containing an element with class `ft-editor`; its `.value` is committed.
|
|
68
67
|
- `validator` returns `null` when valid, or an error message (the edit is rejected and `validation-error` fires).
|
|
69
68
|
- `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.
|
|
69
|
+
- `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`.
|
|
71
70
|
- `conditionalRules` applies `{ when, style }` rules in order; later matches override earlier ones.
|
|
72
71
|
- `pinned: 'left' | 'right'` freezes a column during horizontal scroll.
|
|
73
72
|
|
|
@@ -66,6 +66,7 @@ Replacing `data` with the same array reference does not trigger the clear-on-cha
|
|
|
66
66
|
| `validator` | `CellValidator<T>` | `(value, row, col) => string \| null \| undefined` |
|
|
67
67
|
| `conditionalRules` | `ConditionalRule<T>[]` | `{ when(value, row, col): boolean, style: CellStyle }` |
|
|
68
68
|
| `mergeRepeated` | `boolean \| (row, previousRow, col) => boolean` | Draw a run of repeated values as one merged cell; values, sort, filter and export are unchanged |
|
|
69
|
+
| `reveal` | `'always' \| 'hover'` | `'hover'`: content shows only while the row is hovered, focused or selected — for a row-actions column; stays focusable, always shown without hover, not printed |
|
|
69
70
|
|
|
70
71
|
`CellStyle` = `{ background?, color?, fontWeight?: 'bold' | 'normal', fontStyle?: 'italic' | 'normal' }`.
|
|
71
72
|
|