@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 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 { dateTextPattern as u, formatDate as d, formatNumber as f, parseDate as p, parseDateTime as m, parseNumber as h } from "@iyulab/components/dist/utilities/format.js";
6
- import { decodeTsv as g, encodeTsv as _ } from "@iyulab/components/dist/utilities/tsv.js";
7
- import { isImeComposing as v } from "@iyulab/components/dist/utilities/keyboard.js";
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 y = r`
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
- inline-size: 24px;
471
- block-size: 24px;
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: absolute;
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: 10;
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 b(e, t) {
947
- return e == null ? "" : typeof t == "function" ? t(e) : x(t) ? C(e, t) : S(e, t);
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 x(e) {
1010
+ function b(e) {
950
1011
  return /[yMdHhms]/.test(e);
951
1012
  }
952
- function S(e, t) {
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 C(e, t) {
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 w(e, t, n) {
977
- return n.render ? n.render(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : b(e, n.format) : T(e, n);
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 T(e, t) {
1040
+ function w(e, t) {
980
1041
  if (e == null) return "";
981
1042
  switch (t.type) {
982
- case "number": return O(e);
1043
+ case "number": return D(e);
983
1044
  case "boolean": return i`<span class="ft-bool">${e ? "✔" : ""}</span>`;
984
- case "date": return ee(e);
985
- case "datetime": return te(e);
986
- case "select": return E(e, t);
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 E(e, t) {
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 D = {
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 == "number" ? Number.isInteger(e) ? f(e) : f(e, { minimumFractionDigits: 1 }) : String(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" ? d(e) : String(e);
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 ne(e) {
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 re = class {
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 = ne({
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
- }, ie = class {
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 ae(e, t, n) {
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 oe = 100, M = class {
1401
+ var ae = 100, M = class {
1341
1402
  constructor() {
1342
- this._undoStack = [], this._redoStack = [], this._maxSize = oe;
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 se(e, t, n) {
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 _(r);
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 = h(e);
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 p(e) ?? e;
1402
- case "datetime": return m(e) ?? e;
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 ce(e) {
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 le(e) {
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 ue = (() => {
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 de(e) {
1499
+ function ue(e) {
1439
1500
  let t = 4294967295;
1440
- for (let n = 0; n < e.length; n++) t = ue[(t ^ e[n]) & 255] ^ t >>> 8;
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 fe(e) {
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 pe(e) {
1512
+ async function fe(e) {
1452
1513
  let t = [];
1453
1514
  for (let n of e) {
1454
- let e = await me(n.data);
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 me(e) {
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 = 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);
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1500
1561
  }
1501
- function he(e) {
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 he(t) + (e + 1);
1568
+ return me(t) + (e + 1);
1508
1569
  }
1509
- function ge(e) {
1570
+ function he(e) {
1510
1571
  let t = Date.UTC(1899, 11, 30);
1511
1572
  return (e.getTime() - t) / 864e5;
1512
1573
  }
1513
- 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>";
1514
- function Se(e, t) {
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>${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>`;
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 = Se(e, t);
1597
+ let n = xe(e, t);
1537
1598
  return [
1538
1599
  {
1539
1600
  name: "[Content_Types].xml",
1540
- data: F.encode(_e)
1601
+ data: F.encode(ge)
1541
1602
  },
1542
1603
  {
1543
1604
  name: "_rels/.rels",
1544
- data: F.encode(ve)
1605
+ data: F.encode(_e)
1545
1606
  },
1546
1607
  {
1547
1608
  name: "xl/workbook.xml",
1548
- data: F.encode(ye)
1609
+ data: F.encode(ve)
1549
1610
  },
1550
1611
  {
1551
1612
  name: "xl/_rels/workbook.xml.rels",
1552
- data: F.encode(be)
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(xe)
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 De(e, t);
1571
- case "xlsx": return Ce(e, t);
1631
+ case "json": return Ee(e, t);
1632
+ case "xlsx": return Se(e, t);
1572
1633
  }
1573
1634
  }
1574
- async function Te(e, t, n) {
1575
- let r = n === "xlsx" ? await we(e, t) : V(e, t, n);
1576
- return new Blob([r], { type: je(n) });
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 Ee(e, t) {
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(Ee(e[t.key], t), n)).join(n))].join("\n");
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 De(e, t) {
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 Oe(e, t) {
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 ke = {
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
- }, Ae = {
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 Ne(e) {
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 Pe(e) {
1626
- 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;
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 Fe(e) {
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 Ie(e, t) {
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 Fe(o);
1716
+ if (t.compressionMethod === 8) return Pe(o);
1656
1717
  throw Error(`XLSX: Unsupported compression method ${t.compressionMethod}`);
1657
1718
  }
1658
- async function Le(e) {
1659
- let t = new DataView(e), n = Pe(t), r = /* @__PURE__ */ new Map();
1660
- for (let e of n) e.compressedSize === 0 && e.name.endsWith("/") || r.set(e.name, await Ie(t, e));
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 Re = new TextDecoder("utf-8");
1724
+ var Le = new TextDecoder("utf-8");
1664
1725
  function W(e) {
1665
- let t = Re.decode(e);
1726
+ let t = Le.decode(e);
1666
1727
  return new DOMParser().parseFromString(t, "application/xml");
1667
1728
  }
1668
- function ze(e) {
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 Be = /* @__PURE__ */ new Set([
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 Ve(e) {
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 He(e) {
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 ? Be.has(i) : Ve(a)) && t.add(n);
1765
+ (a === void 0 ? ze.has(i) : Be(a)) && t.add(n);
1705
1766
  }), t;
1706
1767
  }
1707
- function Ue(e) {
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 We(e, t) {
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 Ge(e, t, n, r) {
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 = Ke(i.getAttribute("r") ?? "");
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 ? We(e, r) : l;
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 Ke(e) {
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 qe(e) {
1752
- let t = await Le(e), n = ze(t.get("xl/sharedStrings.xml")), r = t.get("xl/worksheets/sheet1.xml");
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 = He(t.get("xl/styles.xml")), a = Ue(t.get("xl/workbook.xml")), o = Ge(r, n, i, a);
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, Je = 200, $ = class extends n {
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 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 = () => {
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 = y;
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
- return this._rowHeightExplicit ?? this._rowHeightFromCss ?? Z;
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 += 36), this.showRowNumbers && (e += 48), 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 Te(n.rows, n.cols, e);
2226
+ return we(n.rows, n.cols, e);
2162
2227
  }
2163
2228
  async exportToFile(e, t) {
2164
- Oe(await this.exportToBlob(e), t ?? `export${Me(e)}`);
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 qe(await e.arrayBuffer());
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 = g(t);
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).getPropertyValue("--ft-row-height").trim();
2376
- if (!e) return;
2377
- let t = parseFloat(e);
2378
- if (!Number.isFinite(t) || t <= 0 || !/px\s*$/.test(e) || t === this._rowHeightFromCss) return;
2379
- let n = this.rowHeight;
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 = ae(this.data, this._filters, (e, t, n) => {
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 && document.activeElement !== e && (e.focus(), e.type === "text" && e.select());
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 < 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.`));
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" && p(e) === null || a.type === "datetime" && typeof e == "string" && m(e) === null) {
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 (!v(e)) {
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 && !v(e)) {
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 = se(this._sortedIndices.map((e) => this.data[e]), n, t);
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 = g(e);
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 += 36), this.showRowNumbers && (n += 48);
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.style.top = "", e.style.bottom = "";
3395
- let t = e.getBoundingClientRect(), n = window.innerHeight;
3396
- t.bottom > n && (e.style.top = "auto", e.style.bottom = "100%");
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 : h(r)
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" && !v(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
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: 36px; height: ${r}px; z-index: 4;">
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
- <input type="checkbox"
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 += 36);
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: 36px; height: ${a}px; z-index: 2;"></div>` : "";
4209
- this.selectable && (c += 36);
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: 36px; height: ${u}px; z-index: 2;">
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 += 36);
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, C = [
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 ? C + " ft-has-comment" : C}
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
- ${w(e[t.key], e, t)}
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") return i`
4350
- <input class="ft-editor ft-editor-date" type="text" inputmode="numeric" placeholder=${u()}
4351
- .value=${ce(n)}
4352
- @keydown=${this._onEditorKeyDown}
4353
- @blur=${() => this._commitEdit()}>
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
- @blur=${() => this._commitEdit()}>
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, w as s, $ as t };
4571
+ export { j as a, M as i, G as n, k as o, V as r, C as s, $ as t };
@@ -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;
@@ -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-MnSI0Ogl.js";
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-MnSI0Ogl.js";
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.44.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": ">=1.56.0",
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 as a `YYYY-MM-DD` text box in every browser language (also `20261002`, `2026/10/2`, `10-02`); pasted dates are normalized to ISO. `datetime` cells edit as `YYYY-MM-DD HH:mm` (local) and store `YYYY-MM-DDTHH:mm`.
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