@iyulab/flex-table 0.43.0 → 0.45.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 +37 -0
- package/README.md +3 -2
- package/dist/export/export.d.ts +6 -1
- package/dist/export/xlsx-deflate.test.d.ts +1 -0
- package/dist/export/xlsx-writer.d.ts +8 -1
- package/dist/{flex-table-BdnkC234.js → flex-table-Bv41ls8b.js} +215 -118
- package/dist/flex-table.d.ts +18 -3
- package/dist/flex-table.js +1 -1
- package/dist/react.js +1 -1
- package/package.json +1 -1
- package/skills/iyulab-flex-table/references/api.md +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.45.0] - 2026-10-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Press targets follow `--u-target-size`** (the host's minimum target size from `@iyulab/components`).
|
|
8
|
+
When it is set, rows (and so the header row) are at least that tall — it wins over `row-height` and
|
|
9
|
+
`--ft-row-height`, because it is a floor — and the row-selection column is at least that wide. Column
|
|
10
|
+
menu buttons, menu items, filter fields and the find panel's fields and buttons follow too. Unset,
|
|
11
|
+
nothing changes. The column resize handle and the hidden-column marker keep their size: the column menu
|
|
12
|
+
does the same jobs (Wider · Narrower · Fit to content · Show …) with full-size targets.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **The whole row-selection cell toggles the checkbox**, not just the 16px box (it is now a label). The box
|
|
17
|
+
itself looks the same.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **The column filter dropdown is no longer cut off by the table.** It was positioned inside the table's
|
|
22
|
+
scroll area, so in a short table its lower controls were hidden and could not be pressed. It now floats
|
|
23
|
+
like the column menu does, below the header (or above it when there is no room).
|
|
24
|
+
|
|
25
|
+
## [0.44.0] - 2026-10-05
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **`exportToBlob(format, options?)`** — the export as a `Blob` typed with the format's MIME type.
|
|
30
|
+
XLSX comes out DEFLATE-compressed (platform `CompressionStream`), a fraction of the stored size —
|
|
31
|
+
a 500-row sheet is under a quarter of it.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- **`exportToFile` returns `Promise<void>` and downloads a compressed XLSX.** It was synchronous and
|
|
36
|
+
wrote the workbook uncompressed (ZIP STORE). Calling it without `await` still works.
|
|
37
|
+
`exportToString` stays synchronous and still returns an uncompressed workbook for `'xlsx'` — use
|
|
38
|
+
`exportToBlob` when the bytes leave the browser.
|
|
39
|
+
|
|
3
40
|
## [0.43.0] - 2026-10-04
|
|
4
41
|
|
|
5
42
|
### Changed
|
package/README.md
CHANGED
|
@@ -276,8 +276,9 @@ Default is `false`, matching `clear-undo-on-data-change`.
|
|
|
276
276
|
|
|
277
277
|
| Method | Returns | Description |
|
|
278
278
|
|--------|---------|-------------|
|
|
279
|
-
| `exportToString(format, options?)` | `string \| Uint8Array` | Export to `'csv'` / `'tsv'` / `'json'` (a string) or `'xlsx'` (bytes). Pass `{ selectionOnly: true }` for selection range |
|
|
280
|
-
| `
|
|
279
|
+
| `exportToString(format, options?)` | `string \| Uint8Array` | Export to `'csv'` / `'tsv'` / `'json'` (a string) or `'xlsx'` (bytes, uncompressed). Pass `{ selectionOnly: true }` for selection range |
|
|
280
|
+
| `exportToBlob(format, options?)` | `Promise<Blob>` | The same export as a `Blob` of the format's MIME type — `'xlsx'` is DEFLATE-compressed |
|
|
281
|
+
| `exportToFile(format, filename?)` | `Promise<void>` | Export and trigger browser file download (`'xlsx'` compressed) |
|
|
281
282
|
|
|
282
283
|
## Events
|
|
283
284
|
|
package/dist/export/export.d.ts
CHANGED
|
@@ -5,9 +5,14 @@ export type ExportFormat = 'csv' | 'tsv' | 'json' | 'xlsx';
|
|
|
5
5
|
* Returns string for text formats (csv/tsv/json) or Uint8Array for xlsx.
|
|
6
6
|
*/
|
|
7
7
|
export declare function exportData(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat): string | Uint8Array<ArrayBuffer>;
|
|
8
|
+
/**
|
|
9
|
+
* Export data as a `Blob` of the format's MIME type. XLSX is DEFLATE-compressed (unlike `exportData`,
|
|
10
|
+
* which stays synchronous and therefore stores the workbook uncompressed).
|
|
11
|
+
*/
|
|
12
|
+
export declare function exportDataBlob(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat): Promise<Blob>;
|
|
8
13
|
/**
|
|
9
14
|
* Trigger a file download in the browser.
|
|
10
15
|
*/
|
|
11
|
-
export declare function
|
|
16
|
+
export declare function downloadBlob(blob: Blob, filename: string): void;
|
|
12
17
|
export declare function getExportMimeType(format: ExportFormat): string;
|
|
13
18
|
export declare function getExportExtension(format: ExportFormat): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal XLSX writer — no external dependencies.
|
|
3
|
-
* Generates OOXML (.xlsx) files
|
|
3
|
+
* Generates OOXML (.xlsx) files — ZIP STORE (sync) or DEFLATE (async, platform CompressionStream).
|
|
4
4
|
* Supports string, number, boolean, and date cell types.
|
|
5
5
|
*/
|
|
6
6
|
import type { ColumnDefinition, DataRow } from '../models/types.js';
|
|
@@ -10,7 +10,14 @@ export interface ZipFile {
|
|
|
10
10
|
}
|
|
11
11
|
/** @internal 테스트가 실물에 가까운 통합 문서(스타일·1904 날짜 체계)를 조립하는 데 쓴다. */
|
|
12
12
|
export declare function buildZip(files: ZipFile[]): Uint8Array<ArrayBuffer>;
|
|
13
|
+
/**
|
|
14
|
+
* DEFLATE 로 압축한 ZIP. 항목마다 압축본이 원본보다 작을 때만 DEFLATE 를 쓰고, 아니면 STORE 로 둔다.
|
|
15
|
+
* 압축은 플랫폼 `CompressionStream('deflate-raw')` 라 비동기다 — 읽기 쪽이 이미 `DecompressionStream` 을 쓴다.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildZipDeflated(files: ZipFile[]): Promise<Uint8Array<ArrayBuffer>>;
|
|
13
18
|
/**
|
|
14
19
|
* Build an XLSX file as a Uint8Array.
|
|
15
20
|
*/
|
|
16
21
|
export declare function buildXlsx(data: DataRow[], columns: ColumnDefinition[]): Uint8Array<ArrayBuffer>;
|
|
22
|
+
/** Build a DEFLATE-compressed XLSX file — the same workbook as `buildXlsx`, a fraction of the size. */
|
|
23
|
+
export declare function buildXlsxDeflated(data: DataRow[], columns: ColumnDefinition[]): Promise<Uint8Array<ArrayBuffer>>;
|
|
@@ -467,8 +467,9 @@ var y = r`
|
|
|
467
467
|
display: inline-flex;
|
|
468
468
|
align-items: center;
|
|
469
469
|
justify-content: center;
|
|
470
|
-
|
|
471
|
-
|
|
470
|
+
/* 호스트 하한(--u-target-size)이 있으면 그 값 — 미설정이면 24px. */
|
|
471
|
+
inline-size: max(24px, var(--u-target-size, 0px));
|
|
472
|
+
block-size: max(24px, var(--u-target-size, 0px));
|
|
472
473
|
margin-left: auto;
|
|
473
474
|
flex-shrink: 0;
|
|
474
475
|
border-radius: 4px;
|
|
@@ -496,22 +497,23 @@ var y = r`
|
|
|
496
497
|
opacity: 1;
|
|
497
498
|
}
|
|
498
499
|
|
|
500
|
+
/* 표 밖에 띄운다 — 자리는 머리 칸에 맞춰 스크립트가 정한다(_adjustFilterDropdown). 표의 스크롤 영역에 잘리지 않는다. */
|
|
499
501
|
.ft-filter-dropdown {
|
|
500
|
-
position:
|
|
501
|
-
top: 100%;
|
|
502
|
-
left: 0;
|
|
502
|
+
position: fixed;
|
|
503
503
|
min-width: 200px;
|
|
504
504
|
background: var(--ft-bg);
|
|
505
505
|
border: 1px solid var(--ft-border-color);
|
|
506
506
|
border-radius: 4px;
|
|
507
507
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
508
508
|
padding: 8px;
|
|
509
|
-
z-index:
|
|
509
|
+
z-index: var(--u-layer-floating, 1000);
|
|
510
510
|
box-sizing: border-box;
|
|
511
511
|
}
|
|
512
512
|
|
|
513
513
|
.ft-filter-input {
|
|
514
514
|
width: 100%;
|
|
515
|
+
/* 호스트 하한(--u-target-size, 미설정 = 0) — 아래 필터·찾기 패널의 입력·버튼도 같다. */
|
|
516
|
+
min-height: var(--u-target-size, 0px);
|
|
515
517
|
padding: 4px 8px;
|
|
516
518
|
font: inherit;
|
|
517
519
|
font-size: 13px;
|
|
@@ -547,6 +549,12 @@ var y = r`
|
|
|
547
549
|
color: var(--ft-sort-indicator-color);
|
|
548
550
|
padding: 2px 8px;
|
|
549
551
|
border-radius: 3px;
|
|
552
|
+
box-sizing: border-box;
|
|
553
|
+
display: inline-flex;
|
|
554
|
+
align-items: center;
|
|
555
|
+
justify-content: center;
|
|
556
|
+
min-height: var(--u-target-size, 0px);
|
|
557
|
+
min-width: var(--u-target-size, 0px);
|
|
550
558
|
}
|
|
551
559
|
|
|
552
560
|
.ft-filter-clear:hover {
|
|
@@ -562,6 +570,9 @@ var y = r`
|
|
|
562
570
|
|
|
563
571
|
.ft-filter-mode-select {
|
|
564
572
|
flex: 1;
|
|
573
|
+
box-sizing: border-box;
|
|
574
|
+
min-height: var(--u-target-size, 0px);
|
|
575
|
+
min-width: var(--u-target-size, 0px);
|
|
565
576
|
padding: 3px 6px;
|
|
566
577
|
font: inherit;
|
|
567
578
|
font-size: 12px;
|
|
@@ -616,7 +627,7 @@ var y = r`
|
|
|
616
627
|
.ft-checkbox-header {
|
|
617
628
|
background: var(--ft-header-bg);
|
|
618
629
|
border-bottom: 2px solid var(--ft-border-color);
|
|
619
|
-
}
|
|
630
|
+
}\n .ft-checkbox-header .ft-checkbox-hit {\n margin-block-end: -2px;\n }
|
|
620
631
|
|
|
621
632
|
.ft-checkbox-cell {
|
|
622
633
|
border-bottom: 1px solid var(--ft-border-color);
|
|
@@ -630,6 +641,19 @@ var y = r`
|
|
|
630
641
|
.ft-row-selected .ft-cell { background: var(--ft-selection-bg) !important; }
|
|
631
642
|
.ft-row-selected .ft-row-num { background: var(--ft-selection-bg); }
|
|
632
643
|
|
|
644
|
+
/* 누르는 자리는 칸 전체다(라벨이 입력을 토글한다) — 체크 상자는 16px 그대로. 칸의 좌우 여백(4px)까지 덮는다. */
|
|
645
|
+
.ft-checkbox-hit {
|
|
646
|
+
flex: 1;
|
|
647
|
+
align-self: stretch;
|
|
648
|
+
margin-inline: -4px;
|
|
649
|
+
/* 칸 아래 경계선(본문 1px · 머리 2px)까지 — 행 높이가 곧 누르는 높이가 되게. */
|
|
650
|
+
margin-block-end: -1px;
|
|
651
|
+
display: flex;
|
|
652
|
+
align-items: center;
|
|
653
|
+
justify-content: center;
|
|
654
|
+
cursor: pointer;
|
|
655
|
+
}
|
|
656
|
+
|
|
633
657
|
.ft-checkbox-header input[type="checkbox"],
|
|
634
658
|
.ft-checkbox-cell input[type="checkbox"] {
|
|
635
659
|
width: 16px;
|
|
@@ -679,7 +703,7 @@ var y = r`
|
|
|
679
703
|
all: unset;
|
|
680
704
|
box-sizing: border-box;
|
|
681
705
|
display: block;
|
|
682
|
-
min-block-size: 28px;
|
|
706
|
+
min-block-size: max(28px, var(--u-target-size, 0px));
|
|
683
707
|
padding: 6px 12px;
|
|
684
708
|
cursor: pointer;
|
|
685
709
|
font-size: var(--ft-font-size, 14px);
|
|
@@ -743,7 +767,7 @@ var y = r`
|
|
|
743
767
|
box-sizing: border-box;
|
|
744
768
|
display: block;
|
|
745
769
|
inline-size: 100%;
|
|
746
|
-
min-block-size: 28px;
|
|
770
|
+
min-block-size: max(28px, var(--u-target-size, 0px));
|
|
747
771
|
padding: 6px 14px;
|
|
748
772
|
cursor: pointer;
|
|
749
773
|
font-size: var(--ft-font-size, 14px);
|
|
@@ -859,6 +883,8 @@ var y = r`
|
|
|
859
883
|
.ft-find-input, .ft-find-replace-input {
|
|
860
884
|
flex: 1;
|
|
861
885
|
min-width: 120px;
|
|
886
|
+
/* content-box 다(최소 폭 120px 의 뜻을 바꾸지 않으려고) — 여백 3px ×2 와 테두리 1px ×2 를 뺀다. */
|
|
887
|
+
min-height: max(0px, calc(var(--u-target-size, 0px) - 8px));
|
|
862
888
|
padding: 3px 6px;
|
|
863
889
|
border: 1px solid var(--ft-border-color);
|
|
864
890
|
border-radius: 3px;
|
|
@@ -881,6 +907,9 @@ var y = r`
|
|
|
881
907
|
}
|
|
882
908
|
|
|
883
909
|
.ft-find-panel button {
|
|
910
|
+
box-sizing: border-box;
|
|
911
|
+
min-height: var(--u-target-size, 0px);
|
|
912
|
+
min-width: var(--u-target-size, 0px);
|
|
884
913
|
padding: 2px 8px;
|
|
885
914
|
border: 1px solid var(--ft-border-color);
|
|
886
915
|
border-radius: 3px;
|
|
@@ -902,6 +931,8 @@ var y = r`
|
|
|
902
931
|
.ft-find-panel label {
|
|
903
932
|
display: flex;
|
|
904
933
|
align-items: center;
|
|
934
|
+
min-height: var(--u-target-size, 0px);
|
|
935
|
+
min-width: var(--u-target-size, 0px);
|
|
905
936
|
gap: 2px;
|
|
906
937
|
font-size: 12px;
|
|
907
938
|
cursor: pointer;
|
|
@@ -1442,49 +1473,83 @@ function de(e) {
|
|
|
1442
1473
|
}
|
|
1443
1474
|
var F = new TextEncoder();
|
|
1444
1475
|
function fe(e) {
|
|
1476
|
+
return I(e.map((e) => ({
|
|
1477
|
+
...e,
|
|
1478
|
+
body: e.data,
|
|
1479
|
+
method: 0
|
|
1480
|
+
})));
|
|
1481
|
+
}
|
|
1482
|
+
async function pe(e) {
|
|
1483
|
+
let t = [];
|
|
1484
|
+
for (let n of e) {
|
|
1485
|
+
let e = await me(n.data);
|
|
1486
|
+
t.push(e.length < n.data.length ? {
|
|
1487
|
+
...n,
|
|
1488
|
+
body: e,
|
|
1489
|
+
method: 8
|
|
1490
|
+
} : {
|
|
1491
|
+
...n,
|
|
1492
|
+
body: n.data,
|
|
1493
|
+
method: 0
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
return I(t);
|
|
1497
|
+
}
|
|
1498
|
+
async function me(e) {
|
|
1499
|
+
let t = new CompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1500
|
+
n.write(e), n.close();
|
|
1501
|
+
let i = [];
|
|
1502
|
+
for (;;) {
|
|
1503
|
+
let { done: e, value: t } = await r.read();
|
|
1504
|
+
if (e) break;
|
|
1505
|
+
i.push(t);
|
|
1506
|
+
}
|
|
1507
|
+
return L(i);
|
|
1508
|
+
}
|
|
1509
|
+
function I(e) {
|
|
1445
1510
|
let t = [], n = [], r = 0;
|
|
1446
1511
|
for (let i of e) {
|
|
1447
|
-
let e = F.encode(i.name), a = de(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length),
|
|
1448
|
-
|
|
1449
|
-
let
|
|
1450
|
-
|
|
1512
|
+
let e = F.encode(i.name), a = de(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);
|
|
1513
|
+
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);
|
|
1514
|
+
let d = new ArrayBuffer(46 + e.length), f = new DataView(d);
|
|
1515
|
+
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;
|
|
1451
1516
|
}
|
|
1452
|
-
let i =
|
|
1453
|
-
return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0),
|
|
1517
|
+
let i = L(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
|
|
1518
|
+
return o.setUint32(0, 101010256, !0), o.setUint16(4, 0, !0), o.setUint16(6, 0, !0), o.setUint16(8, e.length, !0), o.setUint16(10, e.length, !0), o.setUint32(12, i.length, !0), o.setUint32(16, r, !0), o.setUint16(20, 0, !0), L([
|
|
1454
1519
|
...t,
|
|
1455
1520
|
i,
|
|
1456
1521
|
new Uint8Array(a)
|
|
1457
1522
|
]);
|
|
1458
1523
|
}
|
|
1459
|
-
function
|
|
1524
|
+
function L(e) {
|
|
1460
1525
|
let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
|
|
1461
1526
|
for (let t of e) n.set(t, r), r += t.length;
|
|
1462
1527
|
return n;
|
|
1463
1528
|
}
|
|
1464
|
-
function
|
|
1529
|
+
function R(e) {
|
|
1465
1530
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1466
1531
|
}
|
|
1467
|
-
function
|
|
1532
|
+
function he(e) {
|
|
1468
1533
|
let t = "";
|
|
1469
1534
|
for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
|
|
1470
1535
|
return t;
|
|
1471
1536
|
}
|
|
1472
|
-
function
|
|
1473
|
-
return
|
|
1537
|
+
function z(e, t) {
|
|
1538
|
+
return he(t) + (e + 1);
|
|
1474
1539
|
}
|
|
1475
|
-
function
|
|
1540
|
+
function ge(e) {
|
|
1476
1541
|
let t = Date.UTC(1899, 11, 30);
|
|
1477
1542
|
return (e.getTime() - t) / 864e5;
|
|
1478
1543
|
}
|
|
1479
|
-
var
|
|
1480
|
-
function
|
|
1481
|
-
let n = [], r = t.map((e, t) => `<c r="${
|
|
1544
|
+
var _e = "<?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>", ve = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>\n</Relationships>", ye = "<?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>", be = "<?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>", xe = "<?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>";
|
|
1545
|
+
function Se(e, t) {
|
|
1546
|
+
let n = [], r = t.map((e, t) => `<c r="${z(0, t)}" t="str" s="2"><v>${R(e.label)}</v></c>`);
|
|
1482
1547
|
return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
|
|
1483
1548
|
let i = t.map((t, n) => {
|
|
1484
|
-
let i =
|
|
1549
|
+
let i = z(r + 1, n), a = e[t.key];
|
|
1485
1550
|
if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
|
|
1486
1551
|
let o = t.type ?? "text";
|
|
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>${
|
|
1552
|
+
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>${ge(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>`;
|
|
1488
1553
|
});
|
|
1489
1554
|
n.push(`<row r="${r + 2}">${i.join("")}</row>`);
|
|
1490
1555
|
}), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
@@ -1492,24 +1557,30 @@ function ye(e, t) {
|
|
|
1492
1557
|
<sheetData>${n.join("")}</sheetData>
|
|
1493
1558
|
</worksheet>`;
|
|
1494
1559
|
}
|
|
1495
|
-
function
|
|
1496
|
-
|
|
1497
|
-
|
|
1560
|
+
function Ce(e, t) {
|
|
1561
|
+
return fe(B(e, t));
|
|
1562
|
+
}
|
|
1563
|
+
function we(e, t) {
|
|
1564
|
+
return pe(B(e, t));
|
|
1565
|
+
}
|
|
1566
|
+
function B(e, t) {
|
|
1567
|
+
let n = Se(e, t);
|
|
1568
|
+
return [
|
|
1498
1569
|
{
|
|
1499
1570
|
name: "[Content_Types].xml",
|
|
1500
|
-
data: F.encode(
|
|
1571
|
+
data: F.encode(_e)
|
|
1501
1572
|
},
|
|
1502
1573
|
{
|
|
1503
1574
|
name: "_rels/.rels",
|
|
1504
|
-
data: F.encode(
|
|
1575
|
+
data: F.encode(ve)
|
|
1505
1576
|
},
|
|
1506
1577
|
{
|
|
1507
1578
|
name: "xl/workbook.xml",
|
|
1508
|
-
data: F.encode(
|
|
1579
|
+
data: F.encode(ye)
|
|
1509
1580
|
},
|
|
1510
1581
|
{
|
|
1511
1582
|
name: "xl/_rels/workbook.xml.rels",
|
|
1512
|
-
data: F.encode(
|
|
1583
|
+
data: F.encode(be)
|
|
1513
1584
|
},
|
|
1514
1585
|
{
|
|
1515
1586
|
name: "xl/worksheets/sheet1.xml",
|
|
@@ -1517,30 +1588,34 @@ function be(e, t) {
|
|
|
1517
1588
|
},
|
|
1518
1589
|
{
|
|
1519
1590
|
name: "xl/styles.xml",
|
|
1520
|
-
data: F.encode(
|
|
1591
|
+
data: F.encode(xe)
|
|
1521
1592
|
}
|
|
1522
|
-
]
|
|
1593
|
+
];
|
|
1523
1594
|
}
|
|
1524
1595
|
//#endregion
|
|
1525
1596
|
//#region src/export/export.ts
|
|
1526
|
-
function
|
|
1597
|
+
function V(e, t, n) {
|
|
1527
1598
|
switch (n) {
|
|
1528
|
-
case "csv": return
|
|
1529
|
-
case "tsv": return
|
|
1530
|
-
case "json": return
|
|
1531
|
-
case "xlsx": return
|
|
1599
|
+
case "csv": return H(e, t, ",");
|
|
1600
|
+
case "tsv": return H(e, t, " ");
|
|
1601
|
+
case "json": return De(e, t);
|
|
1602
|
+
case "xlsx": return Ce(e, t);
|
|
1532
1603
|
}
|
|
1533
1604
|
}
|
|
1534
|
-
function
|
|
1605
|
+
async function Te(e, t, n) {
|
|
1606
|
+
let r = n === "xlsx" ? await we(e, t) : V(e, t, n);
|
|
1607
|
+
return new Blob([r], { type: je(n) });
|
|
1608
|
+
}
|
|
1609
|
+
function Ee(e, t) {
|
|
1535
1610
|
return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
|
|
1536
1611
|
}
|
|
1537
|
-
function
|
|
1538
|
-
return [t.map((e) =>
|
|
1612
|
+
function H(e, t, n) {
|
|
1613
|
+
return [t.map((e) => U(e.label, n)).join(n), ...e.map((e) => t.map((t) => U(Ee(e[t.key], t), n)).join(n))].join("\n");
|
|
1539
1614
|
}
|
|
1540
|
-
function
|
|
1615
|
+
function U(e, t) {
|
|
1541
1616
|
return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
|
|
1542
1617
|
}
|
|
1543
|
-
function
|
|
1618
|
+
function De(e, t) {
|
|
1544
1619
|
let n = e.map((e) => {
|
|
1545
1620
|
let n = {};
|
|
1546
1621
|
for (let r of t) {
|
|
@@ -1551,35 +1626,35 @@ function Se(e, t) {
|
|
|
1551
1626
|
});
|
|
1552
1627
|
return JSON.stringify(n, null, 2);
|
|
1553
1628
|
}
|
|
1554
|
-
function
|
|
1555
|
-
let
|
|
1556
|
-
|
|
1629
|
+
function Oe(e, t) {
|
|
1630
|
+
let n = URL.createObjectURL(e), r = document.createElement("a");
|
|
1631
|
+
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);
|
|
1557
1632
|
}
|
|
1558
|
-
var
|
|
1633
|
+
var ke = {
|
|
1559
1634
|
csv: "text/csv;charset=utf-8",
|
|
1560
1635
|
tsv: "text/tab-separated-values;charset=utf-8",
|
|
1561
1636
|
json: "application/json;charset=utf-8",
|
|
1562
1637
|
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
1563
|
-
},
|
|
1638
|
+
}, Ae = {
|
|
1564
1639
|
csv: ".csv",
|
|
1565
1640
|
tsv: ".tsv",
|
|
1566
1641
|
json: ".json",
|
|
1567
1642
|
xlsx: ".xlsx"
|
|
1568
1643
|
};
|
|
1569
|
-
function
|
|
1570
|
-
return
|
|
1644
|
+
function je(e) {
|
|
1645
|
+
return ke[e];
|
|
1571
1646
|
}
|
|
1572
|
-
function
|
|
1573
|
-
return
|
|
1647
|
+
function Me(e) {
|
|
1648
|
+
return Ae[e];
|
|
1574
1649
|
}
|
|
1575
1650
|
//#endregion
|
|
1576
1651
|
//#region src/export/xlsx-reader.ts
|
|
1577
|
-
function
|
|
1652
|
+
function Ne(e) {
|
|
1578
1653
|
for (let t = e.byteLength - 22; t >= 0; t--) if (e.getUint32(t, !0) === 101010256) return t;
|
|
1579
1654
|
throw Error("XLSX: End of central directory not found — not a valid ZIP file");
|
|
1580
1655
|
}
|
|
1581
|
-
function
|
|
1582
|
-
let t =
|
|
1656
|
+
function Pe(e) {
|
|
1657
|
+
let t = Ne(e), n = e.getUint32(t + 16, !0), r = e.getUint32(t + 12, !0), i = new TextDecoder("utf-8"), a = [], o = n, s = n + r;
|
|
1583
1658
|
for (; o < s && e.getUint32(o, !0) === 33639248;) {
|
|
1584
1659
|
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));
|
|
1585
1660
|
a.push({
|
|
@@ -1592,7 +1667,7 @@ function Oe(e) {
|
|
|
1592
1667
|
}
|
|
1593
1668
|
return a;
|
|
1594
1669
|
}
|
|
1595
|
-
async function
|
|
1670
|
+
async function Fe(e) {
|
|
1596
1671
|
let t = new DecompressionStream("deflate-raw"), n = t.writable.getWriter(), r = t.readable.getReader();
|
|
1597
1672
|
n.write(e), n.close();
|
|
1598
1673
|
let i = [];
|
|
@@ -1605,28 +1680,28 @@ async function ke(e) {
|
|
|
1605
1680
|
for (let e of i) o.set(e, s), s += e.length;
|
|
1606
1681
|
return o;
|
|
1607
1682
|
}
|
|
1608
|
-
async function
|
|
1683
|
+
async function Ie(e, t) {
|
|
1609
1684
|
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);
|
|
1610
1685
|
if (t.compressionMethod === 0) return o.slice();
|
|
1611
|
-
if (t.compressionMethod === 8) return
|
|
1686
|
+
if (t.compressionMethod === 8) return Fe(o);
|
|
1612
1687
|
throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
|
|
1613
1688
|
}
|
|
1614
|
-
async function
|
|
1615
|
-
let t = new DataView(e), n =
|
|
1616
|
-
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await
|
|
1689
|
+
async function Le(e) {
|
|
1690
|
+
let t = new DataView(e), n = Pe(t), r = /* @__PURE__ */ new Map();
|
|
1691
|
+
for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ie(t, e));
|
|
1617
1692
|
return r;
|
|
1618
1693
|
}
|
|
1619
|
-
var
|
|
1694
|
+
var Re = new TextDecoder("utf-8");
|
|
1620
1695
|
function W(e) {
|
|
1621
|
-
let t =
|
|
1696
|
+
let t = Re.decode(e);
|
|
1622
1697
|
return new DOMParser().parseFromString(t, "application/xml");
|
|
1623
1698
|
}
|
|
1624
|
-
function
|
|
1699
|
+
function ze(e) {
|
|
1625
1700
|
if (!e) return [];
|
|
1626
1701
|
let t = W(e);
|
|
1627
1702
|
return Array.from(t.querySelectorAll("si")).map((e) => Array.from(e.querySelectorAll("t")).map((e) => e.textContent ?? "").join(""));
|
|
1628
1703
|
}
|
|
1629
|
-
var
|
|
1704
|
+
var Be = /* @__PURE__ */ new Set([
|
|
1630
1705
|
14,
|
|
1631
1706
|
15,
|
|
1632
1707
|
16,
|
|
@@ -1646,29 +1721,29 @@ var Pe = /* @__PURE__ */ new Set([
|
|
|
1646
1721
|
57,
|
|
1647
1722
|
58
|
|
1648
1723
|
]);
|
|
1649
|
-
function
|
|
1724
|
+
function Ve(e) {
|
|
1650
1725
|
let t = e.replace(/"[^"]*"/g, "").replace(/\\./g, "").replace(/\[[^\]]*\]/g, "").split(";")[0];
|
|
1651
1726
|
return /[dy]/i.test(t);
|
|
1652
1727
|
}
|
|
1653
|
-
function
|
|
1728
|
+
function He(e) {
|
|
1654
1729
|
let t = /* @__PURE__ */ new Set();
|
|
1655
1730
|
if (!e) return t;
|
|
1656
1731
|
let n = W(e), r = /* @__PURE__ */ new Map();
|
|
1657
1732
|
for (let e of Array.from(n.querySelectorAll("numFmts > numFmt"))) r.set(parseInt(e.getAttribute("numFmtId") ?? "", 10), e.getAttribute("formatCode") ?? "");
|
|
1658
1733
|
return Array.from(n.querySelectorAll("cellXfs > xf")).forEach((e, n) => {
|
|
1659
1734
|
let i = parseInt(e.getAttribute("numFmtId") ?? "0", 10), a = r.get(i);
|
|
1660
|
-
(a === void 0 ?
|
|
1735
|
+
(a === void 0 ? Be.has(i) : Ve(a)) && t.add(n);
|
|
1661
1736
|
}), t;
|
|
1662
1737
|
}
|
|
1663
|
-
function
|
|
1738
|
+
function Ue(e) {
|
|
1664
1739
|
if (!e) return !1;
|
|
1665
1740
|
let t = W(e).querySelector("workbookPr")?.getAttribute("date1904");
|
|
1666
1741
|
return t === "1" || t === "true";
|
|
1667
1742
|
}
|
|
1668
|
-
function
|
|
1743
|
+
function We(e, t) {
|
|
1669
1744
|
return new Date((t ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30)) + Math.floor(e) * 864e5).toISOString().slice(0, 10);
|
|
1670
1745
|
}
|
|
1671
|
-
function
|
|
1746
|
+
function Ge(e, t, n, r) {
|
|
1672
1747
|
let i = W(e).querySelectorAll("row");
|
|
1673
1748
|
if (i.length === 0) return [];
|
|
1674
1749
|
let a = 0, o = /* @__PURE__ */ new Map();
|
|
@@ -1676,7 +1751,7 @@ function ze(e, t, n, r) {
|
|
|
1676
1751
|
let i = parseInt(e.getAttribute("r") ?? "1", 10) - 1, s = /* @__PURE__ */ new Map();
|
|
1677
1752
|
o.set(i, s);
|
|
1678
1753
|
for (let i of e.querySelectorAll("c")) {
|
|
1679
|
-
let e =
|
|
1754
|
+
let e = Ke(i.getAttribute("r") ?? "");
|
|
1680
1755
|
e > a && (a = e);
|
|
1681
1756
|
let o = i.getAttribute("t") ?? "", c = i.getAttribute("s") ?? "", l = i.querySelector("v")?.textContent ?? "", u = i.querySelector("is > t")?.textContent ?? null, d;
|
|
1682
1757
|
if (o === "s") d = t[parseInt(l, 10)] ?? "";
|
|
@@ -1685,7 +1760,7 @@ function ze(e, t, n, r) {
|
|
|
1685
1760
|
else if (l === "") d = "";
|
|
1686
1761
|
else {
|
|
1687
1762
|
let e = parseFloat(l);
|
|
1688
|
-
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ?
|
|
1763
|
+
d = c !== "" && n.has(parseInt(c, 10)) && !isNaN(e) && e >= 0 ? We(e, r) : l;
|
|
1689
1764
|
}
|
|
1690
1765
|
s.set(e, d);
|
|
1691
1766
|
}
|
|
@@ -1699,13 +1774,13 @@ function ze(e, t, n, r) {
|
|
|
1699
1774
|
}
|
|
1700
1775
|
return c;
|
|
1701
1776
|
}
|
|
1702
|
-
function
|
|
1777
|
+
function Ke(e) {
|
|
1703
1778
|
let t = 0, n = 0;
|
|
1704
1779
|
for (; n < e.length && e[n] >= "A" && e[n] <= "Z";) t = t * 26 + (e.charCodeAt(n) - 64), n++;
|
|
1705
1780
|
return t - 1;
|
|
1706
1781
|
}
|
|
1707
|
-
async function
|
|
1708
|
-
let t = await
|
|
1782
|
+
async function qe(e) {
|
|
1783
|
+
let t = await Le(e), n = ze(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
|
|
1709
1784
|
if (!r) {
|
|
1710
1785
|
for (let [e, n] of t) if (e.toLowerCase().includes("worksheets/sheet")) {
|
|
1711
1786
|
r = n;
|
|
@@ -1713,7 +1788,7 @@ async function Ve(e) {
|
|
|
1713
1788
|
}
|
|
1714
1789
|
}
|
|
1715
1790
|
if (!r) throw Error("XLSX: No worksheet found");
|
|
1716
|
-
let i =
|
|
1791
|
+
let i = He(t.get("xl/styles.xml")), a = Ue(t.get("xl/workbook.xml")), o = Ge(r, n, i, a);
|
|
1717
1792
|
return o.length === 0 ? {
|
|
1718
1793
|
headers: [],
|
|
1719
1794
|
rows: []
|
|
@@ -1744,9 +1819,9 @@ var q = {
|
|
|
1744
1819
|
lt: "<",
|
|
1745
1820
|
gte: "≥",
|
|
1746
1821
|
lte: "≤"
|
|
1747
|
-
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5,
|
|
1822
|
+
}, J = 120, Y = 40, X = 20, Z = 32, Q = 5, Je = 200, $ = class extends n {
|
|
1748
1823
|
constructor(...e) {
|
|
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 = () => {
|
|
1824
|
+
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 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 = () => {
|
|
1750
1825
|
this._commitCommentPopup();
|
|
1751
1826
|
}, 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();
|
|
1752
1827
|
}
|
|
@@ -1761,7 +1836,8 @@ var q = {
|
|
|
1761
1836
|
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);
|
|
1762
1837
|
}
|
|
1763
1838
|
get rowHeight() {
|
|
1764
|
-
|
|
1839
|
+
let e = this._rowHeightExplicit ?? this._rowHeightFromCss ?? Z;
|
|
1840
|
+
return Math.max(e, this._targetFloor);
|
|
1765
1841
|
}
|
|
1766
1842
|
set rowHeight(e) {
|
|
1767
1843
|
let t = this.rowHeight;
|
|
@@ -1782,9 +1858,12 @@ var q = {
|
|
|
1782
1858
|
get visibleColumns() {
|
|
1783
1859
|
return this.columns.filter((e) => !e.hidden);
|
|
1784
1860
|
}
|
|
1861
|
+
get _checkboxColWidth() {
|
|
1862
|
+
return Math.max(36, this._targetFloor);
|
|
1863
|
+
}
|
|
1785
1864
|
get _prefixWidth() {
|
|
1786
1865
|
let e = 0;
|
|
1787
|
-
return this.selectable && (e +=
|
|
1866
|
+
return this.selectable && (e += this._checkboxColWidth), this.showRowNumbers && (e += 48), e;
|
|
1788
1867
|
}
|
|
1789
1868
|
get canUndo() {
|
|
1790
1869
|
return this._undo.canUndo;
|
|
@@ -2106,17 +2185,34 @@ var q = {
|
|
|
2106
2185
|
return e;
|
|
2107
2186
|
}
|
|
2108
2187
|
exportToString(e, t) {
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
if (!t) return "";
|
|
2112
|
-
let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
|
|
2113
|
-
for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
|
|
2114
|
-
return B(r, n, e);
|
|
2115
|
-
}
|
|
2116
|
-
return B(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
|
|
2188
|
+
let n = this._exportSlice(t);
|
|
2189
|
+
return n ? V(n.rows, n.cols, e) : "";
|
|
2117
2190
|
}
|
|
2118
|
-
|
|
2119
|
-
|
|
2191
|
+
async exportToBlob(e, t) {
|
|
2192
|
+
let n = this._exportSlice(t) ?? {
|
|
2193
|
+
rows: [],
|
|
2194
|
+
cols: []
|
|
2195
|
+
};
|
|
2196
|
+
return Te(n.rows, n.cols, e);
|
|
2197
|
+
}
|
|
2198
|
+
async exportToFile(e, t) {
|
|
2199
|
+
Oe(await this.exportToBlob(e), t ?? `export${Me(e)}`);
|
|
2200
|
+
}
|
|
2201
|
+
_exportSlice(e) {
|
|
2202
|
+
if (e?.selectionOnly) {
|
|
2203
|
+
let e = this._selection.getEffectiveRange();
|
|
2204
|
+
if (!e) return null;
|
|
2205
|
+
let t = this.visibleColumns.slice(e.startCol, e.endCol + 1), n = [];
|
|
2206
|
+
for (let t = e.startRow; t <= e.endRow; t++) n.push(this.data[this._toDataIndex(t)]);
|
|
2207
|
+
return {
|
|
2208
|
+
rows: n,
|
|
2209
|
+
cols: t
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
return {
|
|
2213
|
+
rows: this._sortedIndices.map((e) => this.data[e]),
|
|
2214
|
+
cols: this.visibleColumns
|
|
2215
|
+
};
|
|
2120
2216
|
}
|
|
2121
2217
|
setComment(e, t, n) {
|
|
2122
2218
|
let r = this.getComment(e, t);
|
|
@@ -2173,7 +2269,7 @@ var q = {
|
|
|
2173
2269
|
async importFromFile(e) {
|
|
2174
2270
|
let t = e.name.toLowerCase();
|
|
2175
2271
|
if (t.endsWith(".xlsx")) {
|
|
2176
|
-
let t = await
|
|
2272
|
+
let t = await qe(await e.arrayBuffer());
|
|
2177
2273
|
this._applyImportedSheet(t);
|
|
2178
2274
|
} else if (t.endsWith(".csv") || t.endsWith(".tsv")) {
|
|
2179
2275
|
let t = await e.text(), n = g(t);
|
|
@@ -2311,12 +2407,11 @@ var q = {
|
|
|
2311
2407
|
this.shadowRoot && Array.isArray(this.shadowRoot.adoptedStyleSheets) && (this.shadowRoot.adoptedStyleSheets = [...this._baseStyleSheets, ...this.stylesheets]);
|
|
2312
2408
|
}
|
|
2313
2409
|
_readDensityTokens() {
|
|
2314
|
-
let e = getComputedStyle(this)
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
this._rowHeightFromCss = t, this._rowHeightExplicit === void 0 && this.requestUpdate("rowHeight", n);
|
|
2410
|
+
let e = getComputedStyle(this), t = (t) => {
|
|
2411
|
+
let n = e.getPropertyValue(t).trim(), r = parseFloat(n);
|
|
2412
|
+
return n && Number.isFinite(r) && r > 0 && /px\s*$/.test(n) ? r : void 0;
|
|
2413
|
+
}, n = this.rowHeight, r = t("--ft-row-height");
|
|
2414
|
+
r !== void 0 && (this._rowHeightFromCss = r), this._targetFloor = t("--u-target-size") ?? 0, this.rowHeight !== n && this.requestUpdate("rowHeight", n);
|
|
2320
2415
|
}
|
|
2321
2416
|
_updateColOffsets() {
|
|
2322
2417
|
let e = this.visibleColumns, t = [], n = this._prefixWidth;
|
|
@@ -2396,7 +2491,7 @@ var q = {
|
|
|
2396
2491
|
e !== this._viewportHeight && (this._viewportHeight = e), t !== this._viewportWidth && (this._viewportWidth = t), this._warnIfUnconstrained();
|
|
2397
2492
|
}
|
|
2398
2493
|
_warnIfUnconstrained() {
|
|
2399
|
-
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount <
|
|
2494
|
+
this._warnedUnconstrained || process.env.NODE_ENV === "production" || this._visibleRowCount < Je || 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.`));
|
|
2400
2495
|
}
|
|
2401
2496
|
_onScroll() {
|
|
2402
2497
|
this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
|
|
@@ -3041,7 +3136,7 @@ var q = {
|
|
|
3041
3136
|
}
|
|
3042
3137
|
_getPinnedLeft(e) {
|
|
3043
3138
|
let t = this.visibleColumns, n = 0;
|
|
3044
|
-
this.selectable && (n +=
|
|
3139
|
+
this.selectable && (n += this._checkboxColWidth), this.showRowNumbers && (n += 48);
|
|
3045
3140
|
for (let r = 0; r < e; r++) t[r].pinned === "left" && (n += this._getColWidth(t[r]));
|
|
3046
3141
|
return n;
|
|
3047
3142
|
}
|
|
@@ -3328,11 +3423,12 @@ var q = {
|
|
|
3328
3423
|
}
|
|
3329
3424
|
_adjustFilterDropdown() {
|
|
3330
3425
|
if (!this._openFilterKey) return;
|
|
3331
|
-
let e = this.shadowRoot?.querySelector(".ft-filter-dropdown");
|
|
3332
|
-
if (!e) return;
|
|
3333
|
-
e.
|
|
3334
|
-
|
|
3335
|
-
|
|
3426
|
+
let e = this.shadowRoot?.querySelector(".ft-filter-dropdown"), t = e?.previousElementSibling;
|
|
3427
|
+
if (!e || !t) return;
|
|
3428
|
+
let n = t.getBoundingClientRect(), r = e.getBoundingClientRect(), i = document.documentElement.clientWidth, a = document.documentElement.clientHeight, o = n.bottom;
|
|
3429
|
+
o + r.height > a - 4 && (o = n.top - r.height >= 4 ? n.top - r.height : Math.max(4, a - r.height - 4));
|
|
3430
|
+
let s = Math.max(4, Math.min(n.left, i - r.width - 4));
|
|
3431
|
+
e.style.left = `${s}px`, e.style.top = `${o}px`;
|
|
3336
3432
|
}
|
|
3337
3433
|
_renderFilterDropdown(e) {
|
|
3338
3434
|
let t = e.type ?? "text";
|
|
@@ -4071,15 +4167,16 @@ var q = {
|
|
|
4071
4167
|
let r = this.headerHeight, o = this._totalRowWidth, { start: s, end: c } = this.visibleColRange, l = [];
|
|
4072
4168
|
for (let t = 0; t < e.length; t++) (e[t].pinned === "left" || e[t].pinned === "right") && (t < s || t >= c) && l.push(t);
|
|
4073
4169
|
let u = 0, d = this._scrollLeft, f = this.selectable ? i`<div class="ft-checkbox-header"
|
|
4074
|
-
style="position: absolute; top: 0; left: ${d + u}px; width:
|
|
4170
|
+
style="position: absolute; top: 0; left: ${d + u}px; width: ${this._checkboxColWidth}px; height: ${r}px; z-index: 4;">
|
|
4075
4171
|
${this._rowSelection.mode === "multi" ? i`
|
|
4076
|
-
|
|
4172
|
+
<!-- 칸 전체가 누르는 자리다(라벨) — 체크 상자는 16px 그대로. -->
|
|
4173
|
+
<label class="ft-checkbox-hit"><input type="checkbox"
|
|
4077
4174
|
.checked=${this._rowSelection.isAllSelected}
|
|
4078
4175
|
.indeterminate=${this._rowSelection.isSomeSelected}
|
|
4079
|
-
@change=${this._onSelectAllChange}>
|
|
4176
|
+
@change=${this._onSelectAllChange}></label>
|
|
4080
4177
|
` : ""}
|
|
4081
4178
|
</div>` : "";
|
|
4082
|
-
this.selectable && (u +=
|
|
4179
|
+
this.selectable && (u += this._checkboxColWidth);
|
|
4083
4180
|
let p = this.showRowNumbers ? i`<div class="ft-row-num-header"
|
|
4084
4181
|
style="position: absolute; top: 0; left: ${d + u}px; width: 48px; height: ${r}px; z-index: 4;">#</div>` : "", m = [];
|
|
4085
4182
|
for (let t of l) m.push(this._renderHeaderCell(e[t], t));
|
|
@@ -4144,8 +4241,8 @@ var q = {
|
|
|
4144
4241
|
_renderFooter(e, t, n) {
|
|
4145
4242
|
if (!this.footerData) return "";
|
|
4146
4243
|
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"
|
|
4147
|
-
style="position: absolute; top: 0; left: ${s + c}px; width:
|
|
4148
|
-
this.selectable && (c +=
|
|
4244
|
+
style="position: absolute; top: 0; left: ${s + c}px; width: ${this._checkboxColWidth}px; height: ${a}px; z-index: 2;"></div>` : "";
|
|
4245
|
+
this.selectable && (c += this._checkboxColWidth);
|
|
4149
4246
|
let u = this.showRowNumbers ? i`<div class="ft-footer-cell ft-row-num"
|
|
4150
4247
|
style="position: absolute; top: 0; left: ${s + c}px; width: 48px; height: ${a}px; z-index: 2;"></div>` : "", d = [];
|
|
4151
4248
|
for (let e of n) {
|
|
@@ -4172,14 +4269,14 @@ var q = {
|
|
|
4172
4269
|
_renderRow(e, t, n, r, a) {
|
|
4173
4270
|
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`
|
|
4174
4271
|
<div class="ft-checkbox-cell"
|
|
4175
|
-
style="position: absolute; top: 0; left: ${m + h}px; width:
|
|
4176
|
-
<input type="checkbox"
|
|
4272
|
+
style="position: absolute; top: 0; left: ${m + h}px; width: ${this._checkboxColWidth}px; height: ${u}px; z-index: 2;">
|
|
4273
|
+
<label class="ft-checkbox-hit"><input type="checkbox"
|
|
4177
4274
|
.checked=${p}
|
|
4178
4275
|
@click=${(e) => this._onRowCheckboxClick(e)}
|
|
4179
|
-
@change=${(t) => this._onRowCheckboxChange(t, e)}>
|
|
4276
|
+
@change=${(t) => this._onRowCheckboxChange(t, e)}></label>
|
|
4180
4277
|
</div>
|
|
4181
4278
|
` : "";
|
|
4182
|
-
this.selectable && (h +=
|
|
4279
|
+
this.selectable && (h += this._checkboxColWidth);
|
|
4183
4280
|
let _ = this._rowDrag?.active && this._rowDrag.rowIndex === e, v = this.showRowNumbers ? i`
|
|
4184
4281
|
<div class="ft-row-num ${_ ? "ft-col-dragging" : ""}"
|
|
4185
4282
|
style="position: absolute; top: 0; left: ${m + h}px; width: 48px; height: ${u}px; z-index: 2; cursor: grab;"
|
|
@@ -4394,4 +4491,4 @@ K([s({ type: Array })], $.prototype, "columns", void 0), K([s({
|
|
|
4394
4491
|
attribute: "max-undo-size"
|
|
4395
4492
|
})], $.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")], $);
|
|
4396
4493
|
//#endregion
|
|
4397
|
-
export { j as a, M as i, G as n, k as o,
|
|
4494
|
+
export { j as a, M as i, G as n, k as o, V as r, w as s, $ as t };
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -52,6 +52,8 @@ export declare class FlexTable extends LitElement {
|
|
|
52
52
|
private _rowHeightExplicit?;
|
|
53
53
|
/** `--ft-row-height` 판독 결과. 판독 전·판독 실패 시 기본값. */
|
|
54
54
|
private _rowHeightFromCss;
|
|
55
|
+
/** 호스트 하한 `--u-target-size`(px) 판독 결과 — 행(그러므로 머리행)과 선택 열 폭의 하한. 미설정이면 0. */
|
|
56
|
+
private _targetFloor;
|
|
55
57
|
showRowNumbers: boolean;
|
|
56
58
|
theme: 'light' | 'dark' | undefined;
|
|
57
59
|
maxRows: number;
|
|
@@ -147,6 +149,8 @@ export declare class FlexTable extends LitElement {
|
|
|
147
149
|
private _comments;
|
|
148
150
|
private _isDragOver;
|
|
149
151
|
get visibleColumns(): ColumnDefinition[];
|
|
152
|
+
/** 행 선택 열의 폭 — 36px, 호스트 하한(`--u-target-size`)이 더 크면 그 값. */
|
|
153
|
+
private get _checkboxColWidth();
|
|
150
154
|
private get _prefixWidth();
|
|
151
155
|
/** Whether an undo operation is available. */
|
|
152
156
|
get canUndo(): boolean;
|
|
@@ -251,16 +255,27 @@ export declare class FlexTable extends LitElement {
|
|
|
251
255
|
}>): void;
|
|
252
256
|
private _createEmptyRow;
|
|
253
257
|
/**
|
|
254
|
-
* Export table data to string in the specified format.
|
|
258
|
+
* Export table data to string in the specified format. Synchronous — XLSX comes back as an
|
|
259
|
+
* uncompressed workbook; use `exportToBlob` for a compressed one.
|
|
255
260
|
* @param options.selectionOnly - Export only the currently selected range
|
|
256
261
|
*/
|
|
257
262
|
exportToString(format: ExportFormat, options?: {
|
|
258
263
|
selectionOnly?: boolean;
|
|
259
264
|
}): string | Uint8Array<ArrayBuffer>;
|
|
260
265
|
/**
|
|
261
|
-
* Export table data
|
|
266
|
+
* Export table data as a `Blob` of the format's MIME type. XLSX is DEFLATE-compressed.
|
|
267
|
+
* @param options.selectionOnly - Export only the currently selected range
|
|
268
|
+
*/
|
|
269
|
+
exportToBlob(format: ExportFormat, options?: {
|
|
270
|
+
selectionOnly?: boolean;
|
|
271
|
+
}): Promise<Blob>;
|
|
272
|
+
/**
|
|
273
|
+
* Export table data and trigger file download. XLSX is DEFLATE-compressed; the promise settles
|
|
274
|
+
* once the download has been handed to the browser.
|
|
262
275
|
*/
|
|
263
|
-
exportToFile(format: ExportFormat, filename?: string): void
|
|
276
|
+
exportToFile(format: ExportFormat, filename?: string): Promise<void>;
|
|
277
|
+
/** 내보낼 행·열 — 선택만이면 선택 범위(없으면 `null`), 아니면 정렬 순서의 전체 행 · 보이는 열. */
|
|
278
|
+
private _exportSlice;
|
|
264
279
|
/**
|
|
265
280
|
* Set a comment on the cell at the given data index and column key.
|
|
266
281
|
* Pass an empty string or null to remove the comment.
|
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-Bv41ls8b.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-Bv41ls8b.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
|
@@ -127,8 +127,9 @@ Enter/Escape and blur-to-commit behavior.
|
|
|
127
127
|
| `setComment(dataIndex, colKey, text)` | `null` or `''` removes; undoable |
|
|
128
128
|
| `getComment(dataIndex, colKey)` / `clearComments()` | |
|
|
129
129
|
| `importFromFile(file)` | `Promise<void>`; `.xlsx`, `.csv`, `.tsv`; fires `data-import` |
|
|
130
|
-
| `exportToString(format, { selectionOnly? })` | `string \| Uint8Array`; format `'csv' \| 'tsv' \| 'json' \| 'xlsx'` (xlsx returns bytes) |
|
|
131
|
-
| `
|
|
130
|
+
| `exportToString(format, { selectionOnly? })` | `string \| Uint8Array`; format `'csv' \| 'tsv' \| 'json' \| 'xlsx'` (xlsx returns uncompressed bytes — synchronous) |
|
|
131
|
+
| `exportToBlob(format, { selectionOnly? })` | `Promise<Blob>` typed with the format's MIME; xlsx is DEFLATE-compressed |
|
|
132
|
+
| `exportToFile(format, filename?)` | `Promise<void>` — triggers a download (xlsx compressed) |
|
|
132
133
|
|
|
133
134
|
## Events
|
|
134
135
|
|