@iyulab/flex-table 0.44.0 → 0.46.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 +45 -0
- package/README.md +1 -1
- package/dist/{flex-table-MnSI0Ogl.js → flex-table-DIQhqj12.js} +277 -164
- package/dist/flex-table.d.ts +11 -0
- package/dist/flex-table.js +1 -1
- package/dist/react.js +1 -1
- package/package.json +2 -2
- package/skills/iyulab-flex-table/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.46.0] - 2026-10-05
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Date and datetime cells edit with `u-date-picker`** from `@iyulab/components` — the same text box
|
|
8
|
+
(`YYYY-MM-DD`, `YYYY-MM-DD HH:mm`, the same short forms and the same rejection of text that is not a
|
|
9
|
+
date) with a calendar beside it. A day picked in a `date` cell's calendar is the new value; in a
|
|
10
|
+
`datetime` cell the day and time are applied together with Apply. While the calendar is open,
|
|
11
|
+
Escape closes it and the next Escape cancels the edit. Stored values are unchanged: `YYYY-MM-DD`,
|
|
12
|
+
and the local `YYYY-MM-DDTHH:mm`. **Requires `@iyulab/components` 2.0.1** (peer `>=2.0.1`, was
|
|
13
|
+
`>=1.56.0`) — the release in which pressing the calendar keeps focus in the picker.
|
|
14
|
+
|
|
15
|
+
- **A paste leaves the cells it wrote selected**, as spreadsheets do: after Ctrl+V the pasted block
|
|
16
|
+
(including rows it appended) is the selection, so it can be seen, copied, cleared or undone as one
|
|
17
|
+
block. The active cell stays where the paste began. A single-value paste keeps the single-cell
|
|
18
|
+
selection.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **Typing into a cell editor keeps every key.** The editor was focused and its text selected again on
|
|
23
|
+
every update of the table, so in an autocomplete column — whose list updates on each key — the next
|
|
24
|
+
key replaced what was typed (`apx` became `x`). It is now focused once, when editing starts.
|
|
25
|
+
|
|
26
|
+
## [0.45.0] - 2026-10-05
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **Press targets follow `--u-target-size`** (the host's minimum target size from `@iyulab/components`).
|
|
31
|
+
When it is set, rows (and so the header row) are at least that tall — it wins over `row-height` and
|
|
32
|
+
`--ft-row-height`, because it is a floor — and the row-selection column is at least that wide. Column
|
|
33
|
+
menu buttons, menu items, filter fields and the find panel's fields and buttons follow too. Unset,
|
|
34
|
+
nothing changes. The column resize handle and the hidden-column marker keep their size: the column menu
|
|
35
|
+
does the same jobs (Wider · Narrower · Fit to content · Show …) with full-size targets.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **The whole row-selection cell toggles the checkbox**, not just the 16px box (it is now a label). The box
|
|
40
|
+
itself looks the same.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **The column filter dropdown is no longer cut off by the table.** It was positioned inside the table's
|
|
45
|
+
scroll area, so in a short table its lower controls were hidden and could not be pressed. It now floats
|
|
46
|
+
like the column menu does, below the header (or above it when there is no room).
|
|
47
|
+
|
|
3
48
|
## [0.44.0] - 2026-10-05
|
|
4
49
|
|
|
5
50
|
### Added
|
package/README.md
CHANGED
|
@@ -161,7 +161,7 @@ The `validator` callback returns `null` if valid, or an error message string. On
|
|
|
161
161
|
|
|
162
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.
|
|
163
163
|
|
|
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
|
+
A `date` column's built-in editor is `u-date-picker` from `@iyulab/components`: 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`), with a calendar beside it — click the box or press ArrowDown, and a picked day is the new value. 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; in its calendar a day and a time are applied together with Apply. While the calendar is open, Escape closes the calendar; the next Escape cancels the edit.
|
|
165
165
|
|
|
166
166
|
### `format` vs `render`
|
|
167
167
|
|
|
@@ -2,11 +2,12 @@ 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
|
|
5
|
+
import { formatDate as u, formatNumber as d, parseDate as f, parseDateTime as p, parseNumber as m } from "@iyulab/components/dist/utilities/format.js";
|
|
6
|
+
import { decodeTsv as h, encodeTsv as g } from "@iyulab/components/dist/utilities/tsv.js";
|
|
7
|
+
import "@iyulab/components/dist/components/date-picker/UDatePicker.js";
|
|
8
|
+
import { isImeComposing as _ } from "@iyulab/components/dist/utilities/keyboard.js";
|
|
8
9
|
//#region src/styles/flex-table.styles.ts
|
|
9
|
-
var
|
|
10
|
+
var v = r`
|
|
10
11
|
/* --- Theme Variables (Light defaults) --- */
|
|
11
12
|
:host {
|
|
12
13
|
--ft-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
@@ -306,6 +307,35 @@ var y = r`
|
|
|
306
307
|
|
|
307
308
|
.ft-editor-number { text-align: right; }
|
|
308
309
|
|
|
310
|
+
/* 날짜 편집기(u-date-picker) — 텍스트 편집기와 같은 자리·여백·초점선으로 셀을 채운다. 테두리는
|
|
311
|
+
셀의 것이고, 달력은 피커 자신의 팝오버다. */
|
|
312
|
+
u-date-picker.ft-editor {
|
|
313
|
+
display: block;
|
|
314
|
+
padding: 0;
|
|
315
|
+
background: none;
|
|
316
|
+
--u-date-picker-display: block;
|
|
317
|
+
--u-date-picker-width: 100%;
|
|
318
|
+
}
|
|
319
|
+
u-date-picker.ft-editor:focus { outline: none; }
|
|
320
|
+
u-date-picker.ft-editor:focus-within {
|
|
321
|
+
outline: 2px solid var(--ft-active-color);
|
|
322
|
+
outline-offset: -2px;
|
|
323
|
+
}
|
|
324
|
+
u-date-picker.ft-editor::part(field) { height: 100%; }
|
|
325
|
+
u-date-picker.ft-editor::part(container) {
|
|
326
|
+
height: 100%;
|
|
327
|
+
min-height: 0;
|
|
328
|
+
border: none;
|
|
329
|
+
border-radius: 0;
|
|
330
|
+
box-shadow: none;
|
|
331
|
+
background: var(--ft-editor-bg);
|
|
332
|
+
padding: var(--ft-cell-padding-block) var(--ft-cell-padding-inline);
|
|
333
|
+
}
|
|
334
|
+
u-date-picker.ft-editor::part(input) {
|
|
335
|
+
font: inherit;
|
|
336
|
+
color: var(--ft-text-color);
|
|
337
|
+
}
|
|
338
|
+
|
|
309
339
|
select.ft-editor {
|
|
310
340
|
cursor: pointer;
|
|
311
341
|
padding: 4px 6px;
|
|
@@ -467,8 +497,9 @@ var y = r`
|
|
|
467
497
|
display: inline-flex;
|
|
468
498
|
align-items: center;
|
|
469
499
|
justify-content: center;
|
|
470
|
-
|
|
471
|
-
|
|
500
|
+
/* 호스트 하한(--u-target-size)이 있으면 그 값 — 미설정이면 24px. */
|
|
501
|
+
inline-size: max(24px, var(--u-target-size, 0px));
|
|
502
|
+
block-size: max(24px, var(--u-target-size, 0px));
|
|
472
503
|
margin-left: auto;
|
|
473
504
|
flex-shrink: 0;
|
|
474
505
|
border-radius: 4px;
|
|
@@ -496,22 +527,23 @@ var y = r`
|
|
|
496
527
|
opacity: 1;
|
|
497
528
|
}
|
|
498
529
|
|
|
530
|
+
/* 표 밖에 띄운다 — 자리는 머리 칸에 맞춰 스크립트가 정한다(_adjustFilterDropdown). 표의 스크롤 영역에 잘리지 않는다. */
|
|
499
531
|
.ft-filter-dropdown {
|
|
500
|
-
position:
|
|
501
|
-
top: 100%;
|
|
502
|
-
left: 0;
|
|
532
|
+
position: fixed;
|
|
503
533
|
min-width: 200px;
|
|
504
534
|
background: var(--ft-bg);
|
|
505
535
|
border: 1px solid var(--ft-border-color);
|
|
506
536
|
border-radius: 4px;
|
|
507
537
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
508
538
|
padding: 8px;
|
|
509
|
-
z-index:
|
|
539
|
+
z-index: var(--u-layer-floating, 1000);
|
|
510
540
|
box-sizing: border-box;
|
|
511
541
|
}
|
|
512
542
|
|
|
513
543
|
.ft-filter-input {
|
|
514
544
|
width: 100%;
|
|
545
|
+
/* 호스트 하한(--u-target-size, 미설정 = 0) — 아래 필터·찾기 패널의 입력·버튼도 같다. */
|
|
546
|
+
min-height: var(--u-target-size, 0px);
|
|
515
547
|
padding: 4px 8px;
|
|
516
548
|
font: inherit;
|
|
517
549
|
font-size: 13px;
|
|
@@ -547,6 +579,12 @@ var y = r`
|
|
|
547
579
|
color: var(--ft-sort-indicator-color);
|
|
548
580
|
padding: 2px 8px;
|
|
549
581
|
border-radius: 3px;
|
|
582
|
+
box-sizing: border-box;
|
|
583
|
+
display: inline-flex;
|
|
584
|
+
align-items: center;
|
|
585
|
+
justify-content: center;
|
|
586
|
+
min-height: var(--u-target-size, 0px);
|
|
587
|
+
min-width: var(--u-target-size, 0px);
|
|
550
588
|
}
|
|
551
589
|
|
|
552
590
|
.ft-filter-clear:hover {
|
|
@@ -562,6 +600,9 @@ var y = r`
|
|
|
562
600
|
|
|
563
601
|
.ft-filter-mode-select {
|
|
564
602
|
flex: 1;
|
|
603
|
+
box-sizing: border-box;
|
|
604
|
+
min-height: var(--u-target-size, 0px);
|
|
605
|
+
min-width: var(--u-target-size, 0px);
|
|
565
606
|
padding: 3px 6px;
|
|
566
607
|
font: inherit;
|
|
567
608
|
font-size: 12px;
|
|
@@ -616,7 +657,7 @@ var y = r`
|
|
|
616
657
|
.ft-checkbox-header {
|
|
617
658
|
background: var(--ft-header-bg);
|
|
618
659
|
border-bottom: 2px solid var(--ft-border-color);
|
|
619
|
-
}
|
|
660
|
+
}\n .ft-checkbox-header .ft-checkbox-hit {\n margin-block-end: -2px;\n }
|
|
620
661
|
|
|
621
662
|
.ft-checkbox-cell {
|
|
622
663
|
border-bottom: 1px solid var(--ft-border-color);
|
|
@@ -630,6 +671,19 @@ var y = r`
|
|
|
630
671
|
.ft-row-selected .ft-cell { background: var(--ft-selection-bg) !important; }
|
|
631
672
|
.ft-row-selected .ft-row-num { background: var(--ft-selection-bg); }
|
|
632
673
|
|
|
674
|
+
/* 누르는 자리는 칸 전체다(라벨이 입력을 토글한다) — 체크 상자는 16px 그대로. 칸의 좌우 여백(4px)까지 덮는다. */
|
|
675
|
+
.ft-checkbox-hit {
|
|
676
|
+
flex: 1;
|
|
677
|
+
align-self: stretch;
|
|
678
|
+
margin-inline: -4px;
|
|
679
|
+
/* 칸 아래 경계선(본문 1px · 머리 2px)까지 — 행 높이가 곧 누르는 높이가 되게. */
|
|
680
|
+
margin-block-end: -1px;
|
|
681
|
+
display: flex;
|
|
682
|
+
align-items: center;
|
|
683
|
+
justify-content: center;
|
|
684
|
+
cursor: pointer;
|
|
685
|
+
}
|
|
686
|
+
|
|
633
687
|
.ft-checkbox-header input[type="checkbox"],
|
|
634
688
|
.ft-checkbox-cell input[type="checkbox"] {
|
|
635
689
|
width: 16px;
|
|
@@ -679,7 +733,7 @@ var y = r`
|
|
|
679
733
|
all: unset;
|
|
680
734
|
box-sizing: border-box;
|
|
681
735
|
display: block;
|
|
682
|
-
min-block-size: 28px;
|
|
736
|
+
min-block-size: max(28px, var(--u-target-size, 0px));
|
|
683
737
|
padding: 6px 12px;
|
|
684
738
|
cursor: pointer;
|
|
685
739
|
font-size: var(--ft-font-size, 14px);
|
|
@@ -743,7 +797,7 @@ var y = r`
|
|
|
743
797
|
box-sizing: border-box;
|
|
744
798
|
display: block;
|
|
745
799
|
inline-size: 100%;
|
|
746
|
-
min-block-size: 28px;
|
|
800
|
+
min-block-size: max(28px, var(--u-target-size, 0px));
|
|
747
801
|
padding: 6px 14px;
|
|
748
802
|
cursor: pointer;
|
|
749
803
|
font-size: var(--ft-font-size, 14px);
|
|
@@ -859,6 +913,8 @@ var y = r`
|
|
|
859
913
|
.ft-find-input, .ft-find-replace-input {
|
|
860
914
|
flex: 1;
|
|
861
915
|
min-width: 120px;
|
|
916
|
+
/* content-box 다(최소 폭 120px 의 뜻을 바꾸지 않으려고) — 여백 3px ×2 와 테두리 1px ×2 를 뺀다. */
|
|
917
|
+
min-height: max(0px, calc(var(--u-target-size, 0px) - 8px));
|
|
862
918
|
padding: 3px 6px;
|
|
863
919
|
border: 1px solid var(--ft-border-color);
|
|
864
920
|
border-radius: 3px;
|
|
@@ -881,6 +937,9 @@ var y = r`
|
|
|
881
937
|
}
|
|
882
938
|
|
|
883
939
|
.ft-find-panel button {
|
|
940
|
+
box-sizing: border-box;
|
|
941
|
+
min-height: var(--u-target-size, 0px);
|
|
942
|
+
min-width: var(--u-target-size, 0px);
|
|
884
943
|
padding: 2px 8px;
|
|
885
944
|
border: 1px solid var(--ft-border-color);
|
|
886
945
|
border-radius: 3px;
|
|
@@ -902,6 +961,8 @@ var y = r`
|
|
|
902
961
|
.ft-find-panel label {
|
|
903
962
|
display: flex;
|
|
904
963
|
align-items: center;
|
|
964
|
+
min-height: var(--u-target-size, 0px);
|
|
965
|
+
min-width: var(--u-target-size, 0px);
|
|
905
966
|
gap: 2px;
|
|
906
967
|
font-size: 12px;
|
|
907
968
|
cursor: pointer;
|
|
@@ -943,13 +1004,13 @@ var y = r`
|
|
|
943
1004
|
`;
|
|
944
1005
|
//#endregion
|
|
945
1006
|
//#region src/renderers/format.ts
|
|
946
|
-
function
|
|
947
|
-
return e == null ? "" : typeof t == "function" ? t(e) :
|
|
1007
|
+
function y(e, t) {
|
|
1008
|
+
return e == null ? "" : typeof t == "function" ? t(e) : b(t) ? S(e, t) : x(e, t);
|
|
948
1009
|
}
|
|
949
|
-
function
|
|
1010
|
+
function b(e) {
|
|
950
1011
|
return /[yMdHhms]/.test(e);
|
|
951
1012
|
}
|
|
952
|
-
function
|
|
1013
|
+
function x(e, t) {
|
|
953
1014
|
let n = typeof e == "number" ? e : Number(e);
|
|
954
1015
|
if (isNaN(n)) return String(e);
|
|
955
1016
|
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 = {
|
|
@@ -962,7 +1023,7 @@ function S(e, t) {
|
|
|
962
1023
|
style: "percent"
|
|
963
1024
|
}).format(n) : (d = new Intl.NumberFormat(l.get(), u).format(n), a && (d = a + d)), d + "";
|
|
964
1025
|
}
|
|
965
|
-
function
|
|
1026
|
+
function S(e, t) {
|
|
966
1027
|
let n;
|
|
967
1028
|
if (e instanceof Date) n = e;
|
|
968
1029
|
else if (typeof e == "string" || typeof e == "number") n = new Date(e);
|
|
@@ -973,26 +1034,26 @@ function C(e, t) {
|
|
|
973
1034
|
}
|
|
974
1035
|
//#endregion
|
|
975
1036
|
//#region src/renderers/cell-renderer.ts
|
|
976
|
-
function
|
|
977
|
-
return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) :
|
|
1037
|
+
function C(e, t, n) {
|
|
1038
|
+
return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : y(e, n.format) : w(e, n);
|
|
978
1039
|
}
|
|
979
|
-
function
|
|
1040
|
+
function w(e, t) {
|
|
980
1041
|
if (e == null) return "";
|
|
981
1042
|
switch (t.type) {
|
|
982
|
-
case "number": return
|
|
1043
|
+
case "number": return D(e);
|
|
983
1044
|
case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
|
|
984
|
-
case "date": return
|
|
985
|
-
case "datetime": return
|
|
986
|
-
case "select": return
|
|
1045
|
+
case "date": return O(e);
|
|
1046
|
+
case "datetime": return ee(e);
|
|
1047
|
+
case "select": return T(e, t);
|
|
987
1048
|
default: return String(e);
|
|
988
1049
|
}
|
|
989
1050
|
}
|
|
990
|
-
function
|
|
1051
|
+
function T(e, t) {
|
|
991
1052
|
if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
|
|
992
1053
|
let n = t.options.find((t) => t.value === e);
|
|
993
1054
|
return n ? n.label : e == null ? "" : String(e);
|
|
994
1055
|
}
|
|
995
|
-
var
|
|
1056
|
+
var E = {
|
|
996
1057
|
year: "numeric",
|
|
997
1058
|
month: "numeric",
|
|
998
1059
|
day: "numeric",
|
|
@@ -1000,14 +1061,14 @@ var D = {
|
|
|
1000
1061
|
minute: "numeric",
|
|
1001
1062
|
second: "numeric"
|
|
1002
1063
|
};
|
|
1064
|
+
function D(e) {
|
|
1065
|
+
return typeof e == "number" ? Number.isInteger(e) ? d(e) : d(e, { minimumFractionDigits: 1 }) : String(e);
|
|
1066
|
+
}
|
|
1003
1067
|
function O(e) {
|
|
1004
|
-
return typeof e == "
|
|
1068
|
+
return e instanceof Date || typeof e == "string" ? u(e) : String(e);
|
|
1005
1069
|
}
|
|
1006
1070
|
function ee(e) {
|
|
1007
|
-
return e instanceof Date || typeof e == "string" ?
|
|
1008
|
-
}
|
|
1009
|
-
function te(e) {
|
|
1010
|
-
return e instanceof Date || typeof e == "string" ? d(e, D) : String(e);
|
|
1071
|
+
return e instanceof Date || typeof e == "string" ? u(e, E) : String(e);
|
|
1011
1072
|
}
|
|
1012
1073
|
//#endregion
|
|
1013
1074
|
//#region src/locale.ts
|
|
@@ -1130,7 +1191,7 @@ k.register("en", {
|
|
|
1130
1191
|
var A = (e, t) => k.text(e, t);
|
|
1131
1192
|
//#endregion
|
|
1132
1193
|
//#region src/core/selection.ts
|
|
1133
|
-
function
|
|
1194
|
+
function te(e) {
|
|
1134
1195
|
return {
|
|
1135
1196
|
startRow: Math.min(e.startRow, e.endRow),
|
|
1136
1197
|
startCol: Math.min(e.startCol, e.endCol),
|
|
@@ -1138,7 +1199,7 @@ function ne(e) {
|
|
|
1138
1199
|
endCol: Math.max(e.startCol, e.endCol)
|
|
1139
1200
|
};
|
|
1140
1201
|
}
|
|
1141
|
-
var
|
|
1202
|
+
var ne = class {
|
|
1142
1203
|
constructor() {
|
|
1143
1204
|
this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
|
|
1144
1205
|
}
|
|
@@ -1165,7 +1226,7 @@ var re = class {
|
|
|
1165
1226
|
return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
|
|
1166
1227
|
row: e,
|
|
1167
1228
|
col: t
|
|
1168
|
-
}, this.rangeAnchor && (this.range =
|
|
1229
|
+
}, this.rangeAnchor && (this.range = te({
|
|
1169
1230
|
startRow: this.rangeAnchor.row,
|
|
1170
1231
|
startCol: this.rangeAnchor.col,
|
|
1171
1232
|
endRow: e,
|
|
@@ -1236,7 +1297,7 @@ var re = class {
|
|
|
1236
1297
|
shiftMoveRight() {
|
|
1237
1298
|
return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
|
|
1238
1299
|
}
|
|
1239
|
-
},
|
|
1300
|
+
}, re = class {
|
|
1240
1301
|
constructor() {
|
|
1241
1302
|
this.current = null;
|
|
1242
1303
|
}
|
|
@@ -1318,7 +1379,7 @@ var re = class {
|
|
|
1318
1379
|
};
|
|
1319
1380
|
//#endregion
|
|
1320
1381
|
//#region src/core/filtering.ts
|
|
1321
|
-
function
|
|
1382
|
+
function ie(e, t, n) {
|
|
1322
1383
|
if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
|
|
1323
1384
|
let r = [];
|
|
1324
1385
|
for (let i = 0; i < e.length; i++) {
|
|
@@ -1337,9 +1398,9 @@ function ae(e, t, n) {
|
|
|
1337
1398
|
}
|
|
1338
1399
|
//#endregion
|
|
1339
1400
|
//#region src/core/undo.ts
|
|
1340
|
-
var
|
|
1401
|
+
var ae = 100, M = class {
|
|
1341
1402
|
constructor() {
|
|
1342
|
-
this._undoStack = [], this._redoStack = [], this._maxSize =
|
|
1403
|
+
this._undoStack = [], this._redoStack = [], this._maxSize = ae;
|
|
1343
1404
|
}
|
|
1344
1405
|
get maxSize() {
|
|
1345
1406
|
return this._maxSize;
|
|
@@ -1376,7 +1437,7 @@ var oe = 100, M = class {
|
|
|
1376
1437
|
};
|
|
1377
1438
|
//#endregion
|
|
1378
1439
|
//#region src/clipboard/clipboard.ts
|
|
1379
|
-
function
|
|
1440
|
+
function oe(e, t, n) {
|
|
1380
1441
|
let r = [];
|
|
1381
1442
|
for (let i = n.startRow; i <= n.endRow; i++) {
|
|
1382
1443
|
let a = e[i], o = [];
|
|
@@ -1386,20 +1447,20 @@ function se(e, t, n) {
|
|
|
1386
1447
|
}
|
|
1387
1448
|
r.push(o);
|
|
1388
1449
|
}
|
|
1389
|
-
return
|
|
1450
|
+
return g(r);
|
|
1390
1451
|
}
|
|
1391
1452
|
function N(e, t) {
|
|
1392
1453
|
if (e === "") return null;
|
|
1393
1454
|
switch (t.type) {
|
|
1394
1455
|
case "number": {
|
|
1395
|
-
let t =
|
|
1456
|
+
let t = m(e);
|
|
1396
1457
|
if (t !== null) return t;
|
|
1397
1458
|
let n = Number(e.trim());
|
|
1398
1459
|
return e.trim() !== "" && Number.isFinite(n) ? n : e;
|
|
1399
1460
|
}
|
|
1400
1461
|
case "boolean": return e.toLowerCase() === "true" || e === "1";
|
|
1401
|
-
case "date": return
|
|
1402
|
-
case "datetime": return
|
|
1462
|
+
case "date": return f(e) ?? e;
|
|
1463
|
+
case "datetime": return p(e) ?? e;
|
|
1403
1464
|
default: return e;
|
|
1404
1465
|
}
|
|
1405
1466
|
}
|
|
@@ -1409,13 +1470,13 @@ function P(e) {
|
|
|
1409
1470
|
let n = new Intl.NumberFormat(l.get()).formatToParts(1.5).find((e) => e.type === "decimal")?.value;
|
|
1410
1471
|
return n && n !== "." ? t.replace(".", n) : t;
|
|
1411
1472
|
}
|
|
1412
|
-
function
|
|
1473
|
+
function se(e) {
|
|
1413
1474
|
if (e == null || e === "") return "";
|
|
1414
1475
|
if (e instanceof Date) return Number.isNaN(e.getTime()) ? "" : `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
|
|
1415
1476
|
let t = String(e), n = /^(\d{4}-\d{2}-\d{2})(?:$|T)/.exec(t);
|
|
1416
1477
|
return n ? n[1] : t;
|
|
1417
1478
|
}
|
|
1418
|
-
function
|
|
1479
|
+
function ce(e) {
|
|
1419
1480
|
if (e == null || e === "") return "";
|
|
1420
1481
|
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
1482
|
if (n) return `${n[1]} ${n[2]}`;
|
|
@@ -1426,7 +1487,7 @@ function le(e) {
|
|
|
1426
1487
|
}
|
|
1427
1488
|
//#endregion
|
|
1428
1489
|
//#region src/export/xlsx-writer.ts
|
|
1429
|
-
var
|
|
1490
|
+
var le = (() => {
|
|
1430
1491
|
let e = /* @__PURE__ */ new Uint32Array(256);
|
|
1431
1492
|
for (let t = 0; t < 256; t++) {
|
|
1432
1493
|
let n = t;
|
|
@@ -1435,23 +1496,23 @@ var ue = (() => {
|
|
|
1435
1496
|
}
|
|
1436
1497
|
return e;
|
|
1437
1498
|
})();
|
|
1438
|
-
function
|
|
1499
|
+
function ue(e) {
|
|
1439
1500
|
let t = 4294967295;
|
|
1440
|
-
for (let n = 0; n < e.length; n++) t =
|
|
1501
|
+
for (let n = 0; n < e.length; n++) t = le[(t ^ e[n]) & 255] ^ t >>> 8;
|
|
1441
1502
|
return (t ^ 4294967295) >>> 0;
|
|
1442
1503
|
}
|
|
1443
1504
|
var F = new TextEncoder();
|
|
1444
|
-
function
|
|
1505
|
+
function de(e) {
|
|
1445
1506
|
return I(e.map((e) => ({
|
|
1446
1507
|
...e,
|
|
1447
1508
|
body: e.data,
|
|
1448
1509
|
method: 0
|
|
1449
1510
|
})));
|
|
1450
1511
|
}
|
|
1451
|
-
async function
|
|
1512
|
+
async function fe(e) {
|
|
1452
1513
|
let t = [];
|
|
1453
1514
|
for (let n of e) {
|
|
1454
|
-
let e = await
|
|
1515
|
+
let e = await pe(n.data);
|
|
1455
1516
|
t.push(e.length < n.data.length ? {
|
|
1456
1517
|
...n,
|
|
1457
1518
|
body: e,
|
|
@@ -1464,7 +1525,7 @@ async function pe(e) {
|
|
|
1464
1525
|
}
|
|
1465
1526
|
return I(t);
|
|
1466
1527
|
}
|
|
1467
|
-
async function
|
|
1528
|
+
async function pe(e) {
|
|
1468
1529
|
let t = new CompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1469
1530
|
n.write(e), n.close();
|
|
1470
1531
|
let i = [];
|
|
@@ -1478,7 +1539,7 @@ async function me(e) {
|
|
|
1478
1539
|
function I(e) {
|
|
1479
1540
|
let t = [], n = [], r = 0;
|
|
1480
1541
|
for (let i of e) {
|
|
1481
|
-
let e = F.encode(i.name), a =
|
|
1542
|
+
let e = F.encode(i.name), a = ue(i.data), o = i.data.length, s = i.body.length, c = i.method === 8 ? 20 : 10, l = new ArrayBuffer(30 + e.length), u = new DataView(l);
|
|
1482
1543
|
u.setUint32(0, 67324752, !0), u.setUint16(4, c, !0), u.setUint16(6, 0, !0), u.setUint16(8, i.method, !0), u.setUint16(10, 0, !0), u.setUint16(12, 33, !0), u.setUint32(14, a, !0), u.setUint32(18, s, !0), u.setUint32(22, o, !0), u.setUint16(26, e.length, !0), u.setUint16(28, 0, !0), new Uint8Array(l, 30).set(e), t.push(new Uint8Array(l)), t.push(i.body);
|
|
1483
1544
|
let d = new ArrayBuffer(46 + e.length), f = new DataView(d);
|
|
1484
1545
|
f.setUint32(0, 33639248, !0), f.setUint16(4, 20, !0), f.setUint16(6, c, !0), f.setUint16(8, 0, !0), f.setUint16(10, i.method, !0), f.setUint16(12, 0, !0), f.setUint16(14, 33, !0), f.setUint32(16, a, !0), f.setUint32(20, s, !0), f.setUint32(24, o, !0), f.setUint16(28, e.length, !0), f.setUint16(30, 0, !0), f.setUint16(32, 0, !0), f.setUint16(34, 0, !0), f.setUint16(36, 0, !0), f.setUint32(38, 0, !0), f.setUint32(42, r, !0), new Uint8Array(d, 46).set(e), n.push(new Uint8Array(d)), r += 30 + e.length + s;
|
|
@@ -1498,27 +1559,27 @@ function L(e) {
|
|
|
1498
1559
|
function R(e) {
|
|
1499
1560
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1500
1561
|
}
|
|
1501
|
-
function
|
|
1562
|
+
function me(e) {
|
|
1502
1563
|
let t = "";
|
|
1503
1564
|
for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
|
|
1504
1565
|
return t;
|
|
1505
1566
|
}
|
|
1506
1567
|
function z(e, t) {
|
|
1507
|
-
return
|
|
1568
|
+
return me(t) + (e + 1);
|
|
1508
1569
|
}
|
|
1509
|
-
function
|
|
1570
|
+
function he(e) {
|
|
1510
1571
|
let t = Date.UTC(1899, 11, 30);
|
|
1511
1572
|
return (e.getTime() - t) / 864e5;
|
|
1512
1573
|
}
|
|
1513
|
-
var
|
|
1514
|
-
function
|
|
1574
|
+
var ge = "<?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>", _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/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", ve = "<?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>", ye = "<?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>", be = "<?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>";
|
|
1575
|
+
function xe(e, t) {
|
|
1515
1576
|
let n = [], r = t.map((e, t) => `<c r="${z(0, t)}" t="str" s="2"><v>${R(e.label)}</v></c>`);
|
|
1516
1577
|
return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
|
|
1517
1578
|
let i = t.map((t, n) => {
|
|
1518
1579
|
let i = z(r + 1, n), a = e[t.key];
|
|
1519
1580
|
if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
|
|
1520
1581
|
let o = t.type ?? "text";
|
|
1521
|
-
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>${
|
|
1582
|
+
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>${he(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${R(String(a))}</v></c>`;
|
|
1522
1583
|
});
|
|
1523
1584
|
n.push(`<row r="${r + 2}">${i.join("")}</row>`);
|
|
1524
1585
|
}), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -1526,30 +1587,30 @@ function Se(e, t) {
|
|
|
1526
1587
|
<sheetData>${n.join("")}</sheetData>
|
|
1527
1588
|
</worksheet>`;
|
|
1528
1589
|
}
|
|
1590
|
+
function Se(e, t) {
|
|
1591
|
+
return de(B(e, t));
|
|
1592
|
+
}
|
|
1529
1593
|
function Ce(e, t) {
|
|
1530
1594
|
return fe(B(e, t));
|
|
1531
1595
|
}
|
|
1532
|
-
function we(e, t) {
|
|
1533
|
-
return pe(B(e, t));
|
|
1534
|
-
}
|
|
1535
1596
|
function B(e, t) {
|
|
1536
|
-
let n =
|
|
1597
|
+
let n = xe(e, t);
|
|
1537
1598
|
return [
|
|
1538
1599
|
{
|
|
1539
1600
|
name: "[Content_Types].xml",
|
|
1540
|
-
data: F.encode(
|
|
1601
|
+
data: F.encode(ge)
|
|
1541
1602
|
},
|
|
1542
1603
|
{
|
|
1543
1604
|
name: "_rels/.rels",
|
|
1544
|
-
data: F.encode(
|
|
1605
|
+
data: F.encode(_e)
|
|
1545
1606
|
},
|
|
1546
1607
|
{
|
|
1547
1608
|
name: "xl/workbook.xml",
|
|
1548
|
-
data: F.encode(
|
|
1609
|
+
data: F.encode(ve)
|
|
1549
1610
|
},
|
|
1550
1611
|
{
|
|
1551
1612
|
name: "xl/_rels/workbook.xml.rels",
|
|
1552
|
-
data: F.encode(
|
|
1613
|
+
data: F.encode(ye)
|
|
1553
1614
|
},
|
|
1554
1615
|
{
|
|
1555
1616
|
name: "xl/worksheets/sheet1.xml",
|
|
@@ -1557,7 +1618,7 @@ function B(e, t) {
|
|
|
1557
1618
|
},
|
|
1558
1619
|
{
|
|
1559
1620
|
name: "xl/styles.xml",
|
|
1560
|
-
data: F.encode(
|
|
1621
|
+
data: F.encode(be)
|
|
1561
1622
|
}
|
|
1562
1623
|
];
|
|
1563
1624
|
}
|
|
@@ -1567,24 +1628,24 @@ function V(e, t, n) {
|
|
|
1567
1628
|
switch (n) {
|
|
1568
1629
|
case "csv": return H(e, t, ",");
|
|
1569
1630
|
case "tsv": return H(e, t, " ");
|
|
1570
|
-
case "json": return
|
|
1571
|
-
case "xlsx": return
|
|
1631
|
+
case "json": return Ee(e, t);
|
|
1632
|
+
case "xlsx": return Se(e, t);
|
|
1572
1633
|
}
|
|
1573
1634
|
}
|
|
1574
|
-
async function
|
|
1575
|
-
let r = n === "xlsx" ? await
|
|
1576
|
-
return new Blob([r], { type:
|
|
1635
|
+
async function we(e, t, n) {
|
|
1636
|
+
let r = n === "xlsx" ? await Ce(e, t) : V(e, t, n);
|
|
1637
|
+
return new Blob([r], { type: Ae(n) });
|
|
1577
1638
|
}
|
|
1578
|
-
function
|
|
1639
|
+
function Te(e, t) {
|
|
1579
1640
|
return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
|
|
1580
1641
|
}
|
|
1581
1642
|
function H(e, t, n) {
|
|
1582
|
-
return [t.map((e) => U(e.label, n)).join(n), ...e.map((e) => t.map((t) => U(
|
|
1643
|
+
return [t.map((e) => U(e.label, n)).join(n), ...e.map((e) => t.map((t) => U(Te(e[t.key], t), n)).join(n))].join("\n");
|
|
1583
1644
|
}
|
|
1584
1645
|
function U(e, t) {
|
|
1585
1646
|
return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
|
|
1586
1647
|
}
|
|
1587
|
-
function
|
|
1648
|
+
function Ee(e, t) {
|
|
1588
1649
|
let n = e.map((e) => {
|
|
1589
1650
|
let n = {};
|
|
1590
1651
|
for (let r of t) {
|
|
@@ -1595,35 +1656,35 @@ function De(e, t) {
|
|
|
1595
1656
|
});
|
|
1596
1657
|
return JSON.stringify(n, null, 2);
|
|
1597
1658
|
}
|
|
1598
|
-
function
|
|
1659
|
+
function De(e, t) {
|
|
1599
1660
|
let n = URL.createObjectURL(e), r = document.createElement("a");
|
|
1600
1661
|
r.href = n, r.download = t, r.style.display = "none", document.body.appendChild(r), r.click(), document.body.removeChild(r), setTimeout(() => URL.revokeObjectURL(n), 100);
|
|
1601
1662
|
}
|
|
1602
|
-
var
|
|
1663
|
+
var Oe = {
|
|
1603
1664
|
csv: "text/csv;charset=utf-8",
|
|
1604
1665
|
tsv: "text/tab-separated-values;charset=utf-8",
|
|
1605
1666
|
json: "application/json;charset=utf-8",
|
|
1606
1667
|
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
1607
|
-
},
|
|
1668
|
+
}, ke = {
|
|
1608
1669
|
csv: ".csv",
|
|
1609
1670
|
tsv: ".tsv",
|
|
1610
1671
|
json: ".json",
|
|
1611
1672
|
xlsx: ".xlsx"
|
|
1612
1673
|
};
|
|
1674
|
+
function Ae(e) {
|
|
1675
|
+
return Oe[e];
|
|
1676
|
+
}
|
|
1613
1677
|
function je(e) {
|
|
1614
1678
|
return ke[e];
|
|
1615
1679
|
}
|
|
1616
|
-
function Me(e) {
|
|
1617
|
-
return Ae[e];
|
|
1618
|
-
}
|
|
1619
1680
|
//#endregion
|
|
1620
1681
|
//#region src/export/xlsx-reader.ts
|
|
1621
|
-
function
|
|
1682
|
+
function Me(e) {
|
|
1622
1683
|
for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
|
|
1623
1684
|
throw Error("XLSX: End of central directory not found — not a valid ZIP file");
|
|
1624
1685
|
}
|
|
1625
|
-
function
|
|
1626
|
-
let t =
|
|
1686
|
+
function Ne(e) {
|
|
1687
|
+
let t = Me(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
|
|
1627
1688
|
for (; o < s && e.getUint32(o, !0) === 33639248;) {
|
|
1628
1689
|
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));
|
|
1629
1690
|
a.push({
|
|
@@ -1636,7 +1697,7 @@ function Pe(e) {
|
|
|
1636
1697
|
}
|
|
1637
1698
|
return a;
|
|
1638
1699
|
}
|
|
1639
|
-
async function
|
|
1700
|
+
async function Pe(e) {
|
|
1640
1701
|
let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1641
1702
|
n.write(e), n.close();
|
|
1642
1703
|
let i = [];
|
|
@@ -1649,28 +1710,28 @@ async function Fe(e) {
|
|
|
1649
1710
|
for (let e of i) o.set(e, s), s += e.length;
|
|
1650
1711
|
return o;
|
|
1651
1712
|
}
|
|
1652
|
-
async function
|
|
1713
|
+
async function Fe(e, t) {
|
|
1653
1714
|
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);
|
|
1654
1715
|
if (t.compressionMethod === 0) return o.slice();
|
|
1655
|
-
if (t.compressionMethod === 8) return
|
|
1716
|
+
if (t.compressionMethod === 8) return Pe(o);
|
|
1656
1717
|
throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
|
|
1657
1718
|
}
|
|
1658
|
-
async function
|
|
1659
|
-
let t = new DataView(e), n =
|
|
1660
|
-
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await
|
|
1719
|
+
async function Ie(e) {
|
|
1720
|
+
let t = new DataView(e), n = Ne(t), r = /* @__PURE__ */ new Map();
|
|
1721
|
+
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Fe(t, e));
|
|
1661
1722
|
return r;
|
|
1662
1723
|
}
|
|
1663
|
-
var
|
|
1724
|
+
var Le = new TextDecoder("utf-8");
|
|
1664
1725
|
function W(e) {
|
|
1665
|
-
let t =
|
|
1726
|
+
let t = Le.decode(e);
|
|
1666
1727
|
return new DOMParser().parseFromString(t, "application/xml");
|
|
1667
1728
|
}
|
|
1668
|
-
function
|
|
1729
|
+
function Re(e) {
|
|
1669
1730
|
if (!e) return [];
|
|
1670
1731
|
let t = W(e);
|
|
1671
1732
|
return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
|
|
1672
1733
|
}
|
|
1673
|
-
var
|
|
1734
|
+
var ze = /* @__PURE__ */ new Set([
|
|
1674
1735
|
14,
|
|
1675
1736
|
15,
|
|
1676
1737
|
16,
|
|
@@ -1690,29 +1751,29 @@ var Be = /* @__PURE__ */ new Set([
|
|
|
1690
1751
|
57,
|
|
1691
1752
|
58
|
|
1692
1753
|
]);
|
|
1693
|
-
function
|
|
1754
|
+
function Be(e) {
|
|
1694
1755
|
let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
|
|
1695
1756
|
return /[dy]/i.test(t);
|
|
1696
1757
|
}
|
|
1697
|
-
function
|
|
1758
|
+
function Ve(e) {
|
|
1698
1759
|
let t = /* @__PURE__ */ new Set();
|
|
1699
1760
|
if (!e) return t;
|
|
1700
1761
|
let n = W(e), r = /* @__PURE__ */ new Map();
|
|
1701
1762
|
for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
|
|
1702
1763
|
return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
|
|
1703
1764
|
let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
|
|
1704
|
-
(a === void 0 ?
|
|
1765
|
+
(a === void 0 ? ze.has(i) : Be(a)) && t.add(n);
|
|
1705
1766
|
}), t;
|
|
1706
1767
|
}
|
|
1707
|
-
function
|
|
1768
|
+
function He(e) {
|
|
1708
1769
|
if (!e) return !1;
|
|
1709
1770
|
let t = W(e).querySelector("workbookPr")?.getAttribute("date1904");
|
|
1710
1771
|
return t === "1" || t === "true";
|
|
1711
1772
|
}
|
|
1712
|
-
function
|
|
1773
|
+
function Ue(e, t) {
|
|
1713
1774
|
return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
|
|
1714
1775
|
}
|
|
1715
|
-
function
|
|
1776
|
+
function We(e, t, n, r) {
|
|
1716
1777
|
let i = W(e).querySelectorAll("row");
|
|
1717
1778
|
if (i.length === 0) return [];
|
|
1718
1779
|
let a = 0, o = /* @__PURE__ */ new Map();
|
|
@@ -1720,7 +1781,7 @@ function Ge(e, t, n, r) {
|
|
|
1720
1781
|
let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
|
|
1721
1782
|
o.set(i, s);
|
|
1722
1783
|
for (let i of e.querySelectorAll("c")) {
|
|
1723
|
-
let e =
|
|
1784
|
+
let e = Ge(i.getAttribute("r") ?? "");
|
|
1724
1785
|
e > a && (a = e);
|
|
1725
1786
|
let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
|
|
1726
1787
|
if (o === "s") d = t[parseInt(l, 10)] ?? "";
|
|
@@ -1729,7 +1790,7 @@ function Ge(e, t, n, r) {
|
|
|
1729
1790
|
else if (l === "") d = "";
|
|
1730
1791
|
else {
|
|
1731
1792
|
let e = parseFloat(l);
|
|
1732
|
-
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ?
|
|
1793
|
+
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? Ue(e, r) : l;
|
|
1733
1794
|
}
|
|
1734
1795
|
s.set(e, d);
|
|
1735
1796
|
}
|
|
@@ -1743,13 +1804,13 @@ function Ge(e, t, n, r) {
|
|
|
1743
1804
|
}
|
|
1744
1805
|
return c;
|
|
1745
1806
|
}
|
|
1746
|
-
function
|
|
1807
|
+
function Ge(e) {
|
|
1747
1808
|
let t = 0, n = 0;
|
|
1748
1809
|
for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
|
|
1749
1810
|
return t - 1;
|
|
1750
1811
|
}
|
|
1751
|
-
async function
|
|
1752
|
-
let t = await
|
|
1812
|
+
async function Ke(e) {
|
|
1813
|
+
let t = await Ie(e), n = Re(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
|
|
1753
1814
|
if (!r) {
|
|
1754
1815
|
for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
|
|
1755
1816
|
r = n;
|
|
@@ -1757,7 +1818,7 @@ async function qe(e) {
|
|
|
1757
1818
|
}
|
|
1758
1819
|
}
|
|
1759
1820
|
if (!r) throw Error("XLSX: No worksheet found");
|
|
1760
|
-
let i =
|
|
1821
|
+
let i = Ve(t.get("xl/styles.xml")), a = He(t.get("xl/workbook.xml")), o = We(r, n, i, a);
|
|
1761
1822
|
return o.length === 0 ? {
|
|
1762
1823
|
headers: [],
|
|
1763
1824
|
rows: []
|
|
@@ -1788,14 +1849,14 @@ var q = {
|
|
|
1788
1849
|
lt: "<",
|
|
1789
1850
|
gte: "≥",
|
|
1790
1851
|
lte: "≤"
|
|
1791
|
-
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5,
|
|
1852
|
+
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5, qe = 200, $ = class extends n {
|
|
1792
1853
|
constructor(...e) {
|
|
1793
|
-
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
|
|
1854
|
+
super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this._targetFloor = 0, 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 ne(), this._editing = new re(), 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 = () => {
|
|
1794
1855
|
this._commitCommentPopup();
|
|
1795
1856
|
}, 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();
|
|
1796
1857
|
}
|
|
1797
1858
|
static {
|
|
1798
|
-
this.styles =
|
|
1859
|
+
this.styles = v;
|
|
1799
1860
|
}
|
|
1800
1861
|
get data() {
|
|
1801
1862
|
return this._data;
|
|
@@ -1805,7 +1866,8 @@ var q = {
|
|
|
1805
1866
|
this._data = e, n && !this._inUndoRedo && (this.clearUndoOnDataChange && this._undo.clear(), this.clearSelectionOnDataChange && this._rowSelection.selectedCount > 0 && (this._rowSelection.deselectAll(), this._rowSelectionVersion++, this._dispatchRowSelectionEvent())), this.requestUpdate("data", t);
|
|
1806
1867
|
}
|
|
1807
1868
|
get rowHeight() {
|
|
1808
|
-
|
|
1869
|
+
let e = this._rowHeightExplicit ?? this._rowHeightFromCss ?? Z;
|
|
1870
|
+
return Math.max(e, this._targetFloor);
|
|
1809
1871
|
}
|
|
1810
1872
|
set rowHeight(e) {
|
|
1811
1873
|
let t = this.rowHeight;
|
|
@@ -1826,9 +1888,12 @@ var q = {
|
|
|
1826
1888
|
get visibleColumns() {
|
|
1827
1889
|
return this.columns.filter((e) => !e.hidden);
|
|
1828
1890
|
}
|
|
1891
|
+
get _checkboxColWidth() {
|
|
1892
|
+
return Math.max(36, this._targetFloor);
|
|
1893
|
+
}
|
|
1829
1894
|
get _prefixWidth() {
|
|
1830
1895
|
let e = 0;
|
|
1831
|
-
return this.selectable && (e +=
|
|
1896
|
+
return this.selectable && (e += this._checkboxColWidth), this.showRowNumbers && (e += 48), e;
|
|
1832
1897
|
}
|
|
1833
1898
|
get canUndo() {
|
|
1834
1899
|
return this._undo.canUndo;
|
|
@@ -2158,10 +2223,10 @@ var q = {
|
|
|
2158
2223
|
rows: [],
|
|
2159
2224
|
cols: []
|
|
2160
2225
|
};
|
|
2161
|
-
return
|
|
2226
|
+
return we(n.rows, n.cols, e);
|
|
2162
2227
|
}
|
|
2163
2228
|
async exportToFile(e, t) {
|
|
2164
|
-
|
|
2229
|
+
De(await this.exportToBlob(e), t ?? `export${je(e)}`);
|
|
2165
2230
|
}
|
|
2166
2231
|
_exportSlice(e) {
|
|
2167
2232
|
if (e?.selectionOnly) {
|
|
@@ -2234,10 +2299,10 @@ var q = {
|
|
|
2234
2299
|
async importFromFile(e) {
|
|
2235
2300
|
let t = e.name.toLowerCase();
|
|
2236
2301
|
if (t.endsWith(".xlsx")) {
|
|
2237
|
-
let t = await
|
|
2302
|
+
let t = await Ke(await e.arrayBuffer());
|
|
2238
2303
|
this._applyImportedSheet(t);
|
|
2239
2304
|
} else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
|
|
2240
|
-
let t = await e.text(), n =
|
|
2305
|
+
let t = await e.text(), n = h(t);
|
|
2241
2306
|
this._applyImportedRows(n);
|
|
2242
2307
|
} else console.warn(`flex-table importFromFile: unsupported file type "${e.name}"`);
|
|
2243
2308
|
}
|
|
@@ -2372,12 +2437,11 @@ var q = {
|
|
|
2372
2437
|
this.shadowRoot && Array.isArray(this.shadowRoot.adoptedStyleSheets) && (this.shadowRoot.adoptedStyleSheets = [...this._baseStyleSheets, ...this.stylesheets]);
|
|
2373
2438
|
}
|
|
2374
2439
|
_readDensityTokens() {
|
|
2375
|
-
let e = getComputedStyle(this)
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
this._rowHeightFromCss = t, this._rowHeightExplicit === void 0 && this.requestUpdate("rowHeight", n);
|
|
2440
|
+
let e = getComputedStyle(this), t = (t) => {
|
|
2441
|
+
let n = e.getPropertyValue(t).trim(), r = parseFloat(n);
|
|
2442
|
+
return n && Number.isFinite(r) && r > 0 && /px\s*$/.test(n) ? r : void 0;
|
|
2443
|
+
}, n = this.rowHeight, r = t("--ft-row-height");
|
|
2444
|
+
r !== void 0 && (this._rowHeightFromCss = r), this._targetFloor = t("--u-target-size") ?? 0, this.rowHeight !== n && this.requestUpdate("rowHeight", n);
|
|
2381
2445
|
}
|
|
2382
2446
|
_updateColOffsets() {
|
|
2383
2447
|
let e = this.visibleColumns, t = [], n = this._prefixWidth;
|
|
@@ -2427,7 +2491,7 @@ var q = {
|
|
|
2427
2491
|
this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
|
|
2428
2492
|
return;
|
|
2429
2493
|
}
|
|
2430
|
-
if (this._filteredIndices =
|
|
2494
|
+
if (this._filteredIndices = ie(this.data, this._filters, (e, t, n) => {
|
|
2431
2495
|
this.dispatchEvent(new CustomEvent("filter-error", {
|
|
2432
2496
|
detail: {
|
|
2433
2497
|
error: e,
|
|
@@ -2450,14 +2514,23 @@ var q = {
|
|
|
2450
2514
|
_focusEditor() {
|
|
2451
2515
|
if (!this._editingCell) return;
|
|
2452
2516
|
let e = this.shadowRoot?.querySelector(".ft-editor");
|
|
2453
|
-
e &&
|
|
2517
|
+
if (e && this.shadowRoot.activeElement !== e) {
|
|
2518
|
+
if (e.localName === "u-date-picker") {
|
|
2519
|
+
let t = e;
|
|
2520
|
+
t.updateComplete.then(() => {
|
|
2521
|
+
t.isConnected && this.shadowRoot.activeElement !== t && (t.focus(), t.shadowRoot?.querySelector("[part~=\"input\"]")?.select());
|
|
2522
|
+
});
|
|
2523
|
+
return;
|
|
2524
|
+
}
|
|
2525
|
+
e.focus(), e.type === "text" && e.select();
|
|
2526
|
+
}
|
|
2454
2527
|
}
|
|
2455
2528
|
_measureViewport() {
|
|
2456
2529
|
let e = this.clientHeight, t = this.clientWidth;
|
|
2457
2530
|
e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
|
|
2458
2531
|
}
|
|
2459
2532
|
_warnIfUnconstrained() {
|
|
2460
|
-
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount <
|
|
2533
|
+
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < qe || 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.`));
|
|
2461
2534
|
}
|
|
2462
2535
|
_onScroll() {
|
|
2463
2536
|
this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
|
|
@@ -2585,6 +2658,21 @@ var q = {
|
|
|
2585
2658
|
} else this._cancelEdit();
|
|
2586
2659
|
return;
|
|
2587
2660
|
}
|
|
2661
|
+
if (e.type === "date" || e.type === "datetime") {
|
|
2662
|
+
let t = this.shadowRoot?.querySelector("u-date-picker.ft-editor");
|
|
2663
|
+
if (!t) {
|
|
2664
|
+
this._cancelEdit();
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
2667
|
+
if (t.validity?.badInput) {
|
|
2668
|
+
let e = t.shadowRoot?.querySelector("[part~=\"input\"]")?.value ?? "";
|
|
2669
|
+
this._applyEdit(e);
|
|
2670
|
+
return;
|
|
2671
|
+
}
|
|
2672
|
+
let n = t.value || null;
|
|
2673
|
+
this._applyEdit(n && e.type === "datetime" ? n.slice(0, 16) : n);
|
|
2674
|
+
return;
|
|
2675
|
+
}
|
|
2588
2676
|
let t = this.shadowRoot?.querySelector(".ft-editor");
|
|
2589
2677
|
if (t) {
|
|
2590
2678
|
let n = N(t.value, e);
|
|
@@ -2611,7 +2699,7 @@ var q = {
|
|
|
2611
2699
|
}));
|
|
2612
2700
|
return;
|
|
2613
2701
|
}
|
|
2614
|
-
if (a.type === "number" && typeof e == "string" || a.type === "date" && typeof e == "string" &&
|
|
2702
|
+
if (a.type === "number" && typeof e == "string" || a.type === "date" && typeof e == "string" && f(e) === null || a.type === "datetime" && typeof e == "string" && p(e) === null) {
|
|
2615
2703
|
let t = A(a.type === "number" ? "notANumber" : a.type === "date" ? "notADate" : "notADateTime");
|
|
2616
2704
|
this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
|
|
2617
2705
|
detail: {
|
|
@@ -2676,7 +2764,9 @@ var q = {
|
|
|
2676
2764
|
}));
|
|
2677
2765
|
}
|
|
2678
2766
|
_onEditorKeyDown(e) {
|
|
2679
|
-
if (
|
|
2767
|
+
if (_(e)) return;
|
|
2768
|
+
let t = e.currentTarget;
|
|
2769
|
+
if (!(t?.localName === "u-date-picker" && (e.composedPath().some((e) => e instanceof Element && e.part?.contains("popover")) || e.key === "Escape" && Ye(t)))) {
|
|
2680
2770
|
if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
|
|
2681
2771
|
if (e.key === "ArrowDown") {
|
|
2682
2772
|
e.preventDefault(), e.stopPropagation();
|
|
@@ -2744,7 +2834,7 @@ var q = {
|
|
|
2744
2834
|
].includes(t) && this._handleCtrlKey(e)) return;
|
|
2745
2835
|
}
|
|
2746
2836
|
if (t.length !== 0 && this._visibleRowCount !== 0) {
|
|
2747
|
-
if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !
|
|
2837
|
+
if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !_(e)) {
|
|
2748
2838
|
e.preventDefault();
|
|
2749
2839
|
let n = t[this._activeCell.col];
|
|
2750
2840
|
n && this._isCellEditable(n) ? this._startEdit() : e.key === "Enter" && this._fireRowActivate(n);
|
|
@@ -2832,7 +2922,7 @@ var q = {
|
|
|
2832
2922
|
async _handleCopy(e) {
|
|
2833
2923
|
let t = this._selection.getEffectiveRange();
|
|
2834
2924
|
if (!t) return;
|
|
2835
|
-
let n = this.visibleColumns, r =
|
|
2925
|
+
let n = this.visibleColumns, r = oe(this._sortedIndices.map((e) => this.data[e]), n, t);
|
|
2836
2926
|
try {
|
|
2837
2927
|
await navigator.clipboard.writeText(r);
|
|
2838
2928
|
} catch (e) {
|
|
@@ -2858,10 +2948,10 @@ var q = {
|
|
|
2858
2948
|
if (!this._activeCell) return;
|
|
2859
2949
|
let e = await this._readClipboardText();
|
|
2860
2950
|
if (e == null) return;
|
|
2861
|
-
let t =
|
|
2951
|
+
let t = h(e);
|
|
2862
2952
|
if (t.length === 0) return;
|
|
2863
2953
|
let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
|
|
2864
|
-
if (r.length > 0 || n.length > 0) {
|
|
2954
|
+
if (this._selectPastedRange(this._activeCell, t), r.length > 0 || n.length > 0) {
|
|
2865
2955
|
let e = n.length;
|
|
2866
2956
|
this._undo.push({
|
|
2867
2957
|
label: "paste",
|
|
@@ -2899,6 +2989,13 @@ var q = {
|
|
|
2899
2989
|
})), null;
|
|
2900
2990
|
}
|
|
2901
2991
|
}
|
|
2992
|
+
_selectPastedRange(e, t) {
|
|
2993
|
+
let n = Math.max(...t.map((e) => e.length)), r = Math.min(e.row + t.length, this._visibleRowCount) - 1, i = Math.min(e.col + n, this.visibleColumns.length) - 1;
|
|
2994
|
+
(r !== e.row || i !== e.col) && (this._selection.setDimensions(this._visibleRowCount, this.visibleColumns.length), this._selection.setActive(e.row, e.col), this._selection.setActiveWithRange(r, i), this._activeCell = {
|
|
2995
|
+
row: e.row,
|
|
2996
|
+
col: e.col
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2902
2999
|
_expandRowsForPaste(e, t) {
|
|
2903
3000
|
let n = [], r = e + t, i = this.maxRows > 0 ? this.maxRows : Infinity;
|
|
2904
3001
|
for (; this.data.length < r && this.data.length < i;) {
|
|
@@ -3102,7 +3199,7 @@ var q = {
|
|
|
3102
3199
|
}
|
|
3103
3200
|
_getPinnedLeft(e) {
|
|
3104
3201
|
let t = this.visibleColumns, n = 0;
|
|
3105
|
-
this.selectable && (n +=
|
|
3202
|
+
this.selectable && (n += this._checkboxColWidth), this.showRowNumbers && (n += 48);
|
|
3106
3203
|
for (let r = 0; r < e; r++) t[r].pinned === "left" && (n += this._getColWidth(t[r]));
|
|
3107
3204
|
return n;
|
|
3108
3205
|
}
|
|
@@ -3389,11 +3486,12 @@ var q = {
|
|
|
3389
3486
|
}
|
|
3390
3487
|
_adjustFilterDropdown() {
|
|
3391
3488
|
if (!this._openFilterKey) return;
|
|
3392
|
-
let e = this.shadowRoot?.querySelector(".ft-filter-dropdown");
|
|
3393
|
-
if (!e) return;
|
|
3394
|
-
e.
|
|
3395
|
-
|
|
3396
|
-
|
|
3489
|
+
let e = this.shadowRoot?.querySelector(".ft-filter-dropdown"), t = e?.previousElementSibling;
|
|
3490
|
+
if (!e || !t) return;
|
|
3491
|
+
let n = t.getBoundingClientRect(), r = e.getBoundingClientRect(), i = document.documentElement.clientWidth, a = document.documentElement.clientHeight, o = n.bottom;
|
|
3492
|
+
o + r.height > a - 4 && (o = n.top - r.height >= 4 ? n.top - r.height : Math.max(4, a - r.height - 4));
|
|
3493
|
+
let s = Math.max(4, Math.min(n.left, i - r.width - 4));
|
|
3494
|
+
e.style.left = `${s}px`, e.style.top = `${o}px`;
|
|
3397
3495
|
}
|
|
3398
3496
|
_renderFilterDropdown(e) {
|
|
3399
3497
|
let t = e.type ?? "text";
|
|
@@ -3587,7 +3685,7 @@ var q = {
|
|
|
3587
3685
|
i[t] = {
|
|
3588
3686
|
...i[t],
|
|
3589
3687
|
text: r,
|
|
3590
|
-
value: r.trim() === "" ? null :
|
|
3688
|
+
value: r.trim() === "" ? null : m(r)
|
|
3591
3689
|
}, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
|
|
3592
3690
|
}}
|
|
3593
3691
|
@keydown=${(e) => {
|
|
@@ -4093,7 +4191,7 @@ var q = {
|
|
|
4093
4191
|
this._closeFindPanel();
|
|
4094
4192
|
return;
|
|
4095
4193
|
}
|
|
4096
|
-
e.key === "Enter" && !
|
|
4194
|
+
e.key === "Enter" && !_(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
|
|
4097
4195
|
}}>
|
|
4098
4196
|
<div class="ft-find-row">
|
|
4099
4197
|
<input class="ft-find-input" type="text" placeholder=${A("findPlaceholder")}
|
|
@@ -4132,15 +4230,16 @@ var q = {
|
|
|
4132
4230
|
let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
|
|
4133
4231
|
for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
|
|
4134
4232
|
let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
|
|
4135
|
-
style="position: absolute; top: 0; left: ${d + u}px; width:
|
|
4233
|
+
style="position: absolute; top: 0; left: ${d + u}px; width: ${this._checkboxColWidth}px; height: ${r}px; z-index: 4;">
|
|
4136
4234
|
${this._rowSelection.mode === "multi" ? i`
|
|
4137
|
-
|
|
4235
|
+
<!-- 칸 전체가 누르는 자리다(라벨) — 체크 상자는 16px 그대로. -->
|
|
4236
|
+
<label class="ft-checkbox-hit"><input type="checkbox"
|
|
4138
4237
|
.checked=${this._rowSelection.isAllSelected}
|
|
4139
4238
|
.indeterminate=${this._rowSelection.isSomeSelected}
|
|
4140
|
-
@change=${this._onSelectAllChange}>
|
|
4239
|
+
@change=${this._onSelectAllChange}></label>
|
|
4141
4240
|
` : ""}
|
|
4142
4241
|
</div>` : "";
|
|
4143
|
-
this.selectable && (u +=
|
|
4242
|
+
this.selectable && (u += this._checkboxColWidth);
|
|
4144
4243
|
let p = this.showRowNumbers ? i`<div class="ft-row-num-header"
|
|
4145
4244
|
style="position: absolute; top: 0; left: ${d + u}px; width: 48px; height: ${r}px; z-index: 4;">#</div>` : "", m = [];
|
|
4146
4245
|
for (let t of l) m.push(this._renderHeaderCell(e[t], t));
|
|
@@ -4205,8 +4304,8 @@ var q = {
|
|
|
4205
4304
|
_renderFooter(e, t, n) {
|
|
4206
4305
|
if (!this.footerData) return "";
|
|
4207
4306
|
let r = this.visibleColumns, a = this.rowHeight, o = this._totalRowWidth, s = this._scrollLeft, c = 0, l = this.selectable ? i`<div class="ft-footer-cell ft-checkbox-cell"
|
|
4208
|
-
style="position: absolute; top: 0; left: ${s + c}px; width:
|
|
4209
|
-
this.selectable && (c +=
|
|
4307
|
+
style="position: absolute; top: 0; left: ${s + c}px; width: ${this._checkboxColWidth}px; height: ${a}px; z-index: 2;"></div>` : "";
|
|
4308
|
+
this.selectable && (c += this._checkboxColWidth);
|
|
4210
4309
|
let u = this.showRowNumbers ? i`<div class="ft-footer-cell ft-row-num"
|
|
4211
4310
|
style="position: absolute; top: 0; left: ${s + c}px; width: 48px; height: ${a}px; z-index: 2;"></div>` : "", d = [];
|
|
4212
4311
|
for (let e of n) {
|
|
@@ -4233,14 +4332,14 @@ var q = {
|
|
|
4233
4332
|
_renderRow(e, t, n, r, a) {
|
|
4234
4333
|
let o = this.visibleColumns, s = this._toDataIndex(e), c = this.data[s], l = a ?? e * this.rowHeight, u = this.rowHeight, d = this._totalRowWidth, f = e % 2 == 0 ? "ft-row-even" : "ft-row-odd", p = this.selectable && this._rowSelection.isSelected(e), m = this._scrollLeft, h = 0, g = this.selectable ? i`
|
|
4235
4334
|
<div class="ft-checkbox-cell"
|
|
4236
|
-
style="position: absolute; top: 0; left: ${m + h}px; width:
|
|
4237
|
-
<input type="checkbox"
|
|
4335
|
+
style="position: absolute; top: 0; left: ${m + h}px; width: ${this._checkboxColWidth}px; height: ${u}px; z-index: 2;">
|
|
4336
|
+
<label class="ft-checkbox-hit"><input type="checkbox"
|
|
4238
4337
|
.checked=${p}
|
|
4239
4338
|
@click=${(e) => this._onRowCheckboxClick(e)}
|
|
4240
|
-
@change=${(t) => this._onRowCheckboxChange(t, e)}>
|
|
4339
|
+
@change=${(t) => this._onRowCheckboxChange(t, e)}></label>
|
|
4241
4340
|
</div>
|
|
4242
4341
|
` : "";
|
|
4243
|
-
this.selectable && (h +=
|
|
4342
|
+
this.selectable && (h += this._checkboxColWidth);
|
|
4244
4343
|
let _ = this._rowDrag?.active && this._rowDrag.rowIndex === e, v = this.showRowNumbers ? i`
|
|
4245
4344
|
<div class="ft-row-num ${_ ? "ft-col-dragging" : ""}"
|
|
4246
4345
|
style="position: absolute; top: 0; left: ${m + h}px; width: 48px; height: ${u}px; z-index: 2; cursor: grab;"
|
|
@@ -4304,7 +4403,7 @@ var q = {
|
|
|
4304
4403
|
${this._renderEditor(e, t)}
|
|
4305
4404
|
</div>
|
|
4306
4405
|
`;
|
|
4307
|
-
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,
|
|
4406
|
+
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, w = [
|
|
4308
4407
|
"ft-cell",
|
|
4309
4408
|
`ft-type-${t.type ?? "text"}`,
|
|
4310
4409
|
`ft-align-${G(t)}`,
|
|
@@ -4319,7 +4418,7 @@ var q = {
|
|
|
4319
4418
|
t.reveal === "hover" ? "ft-reveal-hover" : ""
|
|
4320
4419
|
].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;
|
|
4321
4420
|
return i`
|
|
4322
|
-
<div class=${D ?
|
|
4421
|
+
<div class=${D ? w + " ft-has-comment" : w}
|
|
4323
4422
|
role="gridcell"
|
|
4324
4423
|
aria-colindex=${r + 1}
|
|
4325
4424
|
data-col-index=${r}
|
|
@@ -4333,7 +4432,7 @@ var q = {
|
|
|
4333
4432
|
@click=${(e) => this._onCellClickEvent(e, n, r)}
|
|
4334
4433
|
@dblclick=${() => this._onCellDblClick(n, r)}>
|
|
4335
4434
|
${O}
|
|
4336
|
-
${
|
|
4435
|
+
${C(e[t.key], e, t)}
|
|
4337
4436
|
</div>
|
|
4338
4437
|
`;
|
|
4339
4438
|
}
|
|
@@ -4346,18 +4445,17 @@ var q = {
|
|
|
4346
4445
|
@keydown=${this._onEditorKeyDown}
|
|
4347
4446
|
@blur=${() => this._commitEdit()}>
|
|
4348
4447
|
`;
|
|
4349
|
-
if (t.type === "date")
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
if (t.type === "datetime") return i`
|
|
4356
|
-
<input class="ft-editor ft-editor-datetime" type="text" placeholder=${`${u()} HH:mm`}
|
|
4357
|
-
.value=${le(n)}
|
|
4448
|
+
if (t.type === "date" || t.type === "datetime") {
|
|
4449
|
+
let e = t.type === "datetime";
|
|
4450
|
+
return i`
|
|
4451
|
+
<u-date-picker class="ft-editor ft-editor-${t.type}" size="sm"
|
|
4452
|
+
mode=${e ? "datetime" : "date"} ?confirm=${e}
|
|
4453
|
+
.value=${Je(n, e)}
|
|
4358
4454
|
@keydown=${this._onEditorKeyDown}
|
|
4359
|
-
@
|
|
4455
|
+
@change=${() => this._commitEdit()}
|
|
4456
|
+
@blur=${() => this._commitEdit()}></u-date-picker>
|
|
4360
4457
|
`;
|
|
4458
|
+
}
|
|
4361
4459
|
if (t.type === "select" && t.options && t.options.length > 0) {
|
|
4362
4460
|
let e = t.options, r = typeof e[0] == "string";
|
|
4363
4461
|
return i`
|
|
@@ -4454,5 +4552,20 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
|
|
|
4454
4552
|
type: Number,
|
|
4455
4553
|
attribute: "max-undo-size"
|
|
4456
4554
|
})], $.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")], $);
|
|
4555
|
+
function Je(e, t) {
|
|
4556
|
+
if (t) {
|
|
4557
|
+
let t = ce(e);
|
|
4558
|
+
return /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(t) ? t.replace(" ", "T") : void 0;
|
|
4559
|
+
}
|
|
4560
|
+
let n = se(e);
|
|
4561
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(n) ? n : void 0;
|
|
4562
|
+
}
|
|
4563
|
+
function Ye(e) {
|
|
4564
|
+
try {
|
|
4565
|
+
return e.matches(":state(open)");
|
|
4566
|
+
} catch {
|
|
4567
|
+
return !1;
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4457
4570
|
//#endregion
|
|
4458
|
-
export { j as a, M as i, G as n, k as o, V as r,
|
|
4571
|
+
export { j as a, M as i, G as n, k as o, V as r, C as s, $ as t };
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement, type PropertyValues } from 'lit';
|
|
2
|
+
import '@iyulab/components/dist/components/date-picker/UDatePicker.js';
|
|
2
3
|
import type { ExportFormat } from './export/export.js';
|
|
3
4
|
import type { CellPosition, CellRange } from './core/selection.js';
|
|
4
5
|
import type { SortCriteria } from './core/sorting.js';
|
|
@@ -52,6 +53,8 @@ export declare class FlexTable extends LitElement {
|
|
|
52
53
|
private _rowHeightExplicit?;
|
|
53
54
|
/** `--ft-row-height` 판독 결과. 판독 전·판독 실패 시 기본값. */
|
|
54
55
|
private _rowHeightFromCss;
|
|
56
|
+
/** 호스트 하한 `--u-target-size`(px) 판독 결과 — 행(그러므로 머리행)과 선택 열 폭의 하한. 미설정이면 0. */
|
|
57
|
+
private _targetFloor;
|
|
55
58
|
showRowNumbers: boolean;
|
|
56
59
|
theme: 'light' | 'dark' | undefined;
|
|
57
60
|
maxRows: number;
|
|
@@ -147,6 +150,8 @@ export declare class FlexTable extends LitElement {
|
|
|
147
150
|
private _comments;
|
|
148
151
|
private _isDragOver;
|
|
149
152
|
get visibleColumns(): ColumnDefinition[];
|
|
153
|
+
/** 행 선택 열의 폭 — 36px, 호스트 하한(`--u-target-size`)이 더 크면 그 값. */
|
|
154
|
+
private get _checkboxColWidth();
|
|
150
155
|
private get _prefixWidth();
|
|
151
156
|
/** Whether an undo operation is available. */
|
|
152
157
|
get canUndo(): boolean;
|
|
@@ -391,6 +396,12 @@ export declare class FlexTable extends LitElement {
|
|
|
391
396
|
private _handleCopy;
|
|
392
397
|
private _handlePaste;
|
|
393
398
|
private _readClipboardText;
|
|
399
|
+
/**
|
|
400
|
+
* After a paste, the cells it wrote are the selection — as in spreadsheets — so the reader sees
|
|
401
|
+
* what changed and can copy, clear or undo it as one block. The active cell stays where the
|
|
402
|
+
* paste began (the same shape as selecting a column: range to the far corner, focus at the start).
|
|
403
|
+
*/
|
|
404
|
+
private _selectPastedRange;
|
|
394
405
|
private _expandRowsForPaste;
|
|
395
406
|
private _applyPasteData;
|
|
396
407
|
private _handleFillDown;
|
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-DIQhqj12.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/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "./flex-table-
|
|
1
|
+
import { t as e } from "./flex-table-DIQhqj12.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.46.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": ">=
|
|
75
|
+
"@iyulab/components": ">=2.0.1",
|
|
76
76
|
"@lit/react": "^1.0.8",
|
|
77
77
|
"react": "^18.0.0 || ^19.0.0"
|
|
78
78
|
},
|
|
@@ -66,7 +66,7 @@ as `text`). See `references/api.md` for every field.
|
|
|
66
66
|
- `editor` returns a Lit template containing an element with class `ft-editor`; its `.value` is committed.
|
|
67
67
|
- `validator` returns `null` when valid, or an error message (the edit is rejected and `validation-error` fires).
|
|
68
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`.
|
|
69
|
-
- `date` cells edit
|
|
69
|
+
- `date` cells edit with `u-date-picker` (a `YYYY-MM-DD` text box in every browser language plus a calendar) (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
70
|
- `conditionalRules` applies `{ when, style }` rules in order; later matches override earlier ones.
|
|
71
71
|
- `pinned: 'left' | 'right'` freezes a column during horizontal scroll.
|
|
72
72
|
|