@iyulab/flex-table 0.12.0 → 0.14.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.
@@ -236,6 +236,36 @@ var s = t`
236
236
  appearance: auto;
237
237
  }
238
238
 
239
+ .ft-autocomplete-dropdown {
240
+ position: absolute;
241
+ top: 100%;
242
+ left: 0;
243
+ z-index: 100;
244
+ min-width: 100%;
245
+ max-height: 180px;
246
+ overflow-y: auto;
247
+ background: var(--ft-editor-bg, #fff);
248
+ border: 1px solid var(--ft-active-color);
249
+ border-top: none;
250
+ box-shadow: 0 4px 8px rgba(0,0,0,0.12);
251
+ }
252
+
253
+ .ft-autocomplete-item {
254
+ padding: 4px 8px;
255
+ cursor: pointer;
256
+ white-space: nowrap;
257
+ overflow: hidden;
258
+ text-overflow: ellipsis;
259
+ font-size: var(--ft-font-size, 14px);
260
+ color: var(--ft-text-color);
261
+ }
262
+
263
+ .ft-autocomplete-item:hover,
264
+ .ft-autocomplete-item.ft-autocomplete-active {
265
+ background: var(--ft-selection-bg);
266
+ color: var(--ft-active-color);
267
+ }
268
+
239
269
  .ft-cell.ft-type-number {
240
270
  text-align: right;
241
271
  font-variant-numeric: tabular-nums;
@@ -439,6 +469,92 @@ var s = t`
439
469
  box-sizing: border-box;
440
470
  }
441
471
 
472
+ /* Header context menu */
473
+ .ft-header-menu {
474
+ background: var(--ft-editor-bg, #fff);
475
+ border: 1px solid var(--ft-border-color);
476
+ box-shadow: 0 2px 8px rgba(0,0,0,0.16);
477
+ min-width: 160px;
478
+ border-radius: 4px;
479
+ overflow: hidden;
480
+ }
481
+
482
+ .ft-header-menu-item {
483
+ padding: 6px 12px;
484
+ cursor: pointer;
485
+ font-size: var(--ft-font-size, 14px);
486
+ color: var(--ft-text-color);
487
+ white-space: nowrap;
488
+ }
489
+
490
+ .ft-header-menu-item:hover {
491
+ background: var(--ft-selection-bg);
492
+ color: var(--ft-active-color);
493
+ }
494
+
495
+ /* Hidden column indicator in header */
496
+ .ft-hidden-col-indicator {
497
+ position: absolute;
498
+ left: 0;
499
+ top: 0;
500
+ height: 100%;
501
+ width: 16px;
502
+ background: var(--ft-selection-bg);
503
+ border-right: 2px solid var(--ft-active-color);
504
+ cursor: pointer;
505
+ display: flex;
506
+ align-items: center;
507
+ justify-content: center;
508
+ font-size: 10px;
509
+ color: var(--ft-active-color);
510
+ padding: 0;
511
+ border-top: none;
512
+ border-bottom: none;
513
+ border-left: none;
514
+ flex-shrink: 0;
515
+ }
516
+
517
+ .ft-hidden-col-indicator:hover {
518
+ background: var(--ft-active-color);
519
+ color: white;
520
+ }
521
+
522
+ /* Body context menu */
523
+ .ft-body-context-menu {
524
+ background: var(--ft-editor-bg, #fff);
525
+ border: 1px solid var(--ft-border-color);
526
+ box-shadow: 0 2px 8px rgba(0,0,0,0.16);
527
+ min-width: 180px;
528
+ border-radius: 4px;
529
+ overflow: hidden;
530
+ padding: 4px 0;
531
+ }
532
+
533
+ .ft-context-menu-item {
534
+ padding: 6px 14px;
535
+ cursor: pointer;
536
+ font-size: var(--ft-font-size, 14px);
537
+ color: var(--ft-text-color);
538
+ white-space: nowrap;
539
+ user-select: none;
540
+ }
541
+
542
+ .ft-context-menu-item:hover {
543
+ background: var(--ft-selection-bg);
544
+ color: var(--ft-active-color);
545
+ }
546
+
547
+ .ft-context-menu-item.ft-context-menu-danger:hover {
548
+ background: #fdd;
549
+ color: #c0392b;
550
+ }
551
+
552
+ .ft-context-menu-separator {
553
+ height: 1px;
554
+ background: var(--ft-border-color);
555
+ margin: 4px 0;
556
+ }
557
+
442
558
  /* Find / Replace panel */
443
559
  .ft-find-panel {
444
560
  position: sticky;
@@ -524,30 +640,60 @@ var s = t`
524
640
  }
525
641
  `;
526
642
  //#endregion
643
+ //#region src/renderers/format.ts
644
+ function c(e, t) {
645
+ return e == null ? "" : typeof t == "function" ? t(e) : l(t) ? d(e, t) : u(e, t);
646
+ }
647
+ function l(e) {
648
+ return /[yMdHhms]/.test(e);
649
+ }
650
+ function u(e, t) {
651
+ let n = typeof e == "number" ? e : Number(e);
652
+ if (isNaN(n)) return String(e);
653
+ 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, l = {
654
+ minimumFractionDigits: c,
655
+ maximumFractionDigits: c,
656
+ useGrouping: o.includes(",")
657
+ }, u;
658
+ return r ? u = new Intl.NumberFormat(void 0, {
659
+ ...l,
660
+ style: "percent"
661
+ }).format(n) : (u = new Intl.NumberFormat(void 0, l).format(n), a && (u = a + u)), u + "";
662
+ }
663
+ function d(e, t) {
664
+ let n;
665
+ if (e instanceof Date) n = e;
666
+ else if (typeof e == "string" || typeof e == "number") n = new Date(e);
667
+ else return String(e);
668
+ if (isNaN(n.getTime())) return String(e);
669
+ let r = String(n.getFullYear()), i = r.slice(-2), a = String(n.getMonth() + 1).padStart(2, "0"), o = String(n.getDate()).padStart(2, "0"), s = String(n.getHours()).padStart(2, "0"), c = String(n.getHours() % 12 || 12).padStart(2, "0"), l = String(n.getMinutes()).padStart(2, "0"), u = String(n.getSeconds()).padStart(2, "0");
670
+ return t.replace("yyyy", r).replace("yy", i).replace("MM", a).replace("dd", o).replace("HH", s).replace("hh", c).replace("mm", l).replace("ss", u);
671
+ }
672
+ //#endregion
527
673
  //#region src/renderers/cell-renderer.ts
528
- function c(e, t, n) {
529
- return n.renderer ? n.renderer(e, t, n) : l(e, n);
674
+ function f(e, t, n) {
675
+ return n.renderer ? n.renderer(e, t, n) : n.format ? typeof n.format == "function" ? n.format(e, t, n) : c(e, n.format) : p(e, n);
530
676
  }
531
- function l(e, t) {
677
+ function p(e, t) {
532
678
  if (e == null) return "";
533
679
  switch (t.type) {
534
- case "number": return d(e);
680
+ case "number": return h(e);
535
681
  case "boolean": return n`<span class="ft-bool">${e ? "✔" : ""}</span>`;
536
- case "date": return f(e);
537
- case "datetime": return p(e);
538
- case "select": return u(e, t);
682
+ case "date": return g(e);
683
+ case "datetime": return _(e);
684
+ case "select": return m(e, t);
539
685
  default: return String(e);
540
686
  }
541
687
  }
542
- function u(e, t) {
688
+ function m(e, t) {
543
689
  if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
544
690
  let n = t.options.find((t) => t.value === e);
545
691
  return n ? n.label : e == null ? "" : String(e);
546
692
  }
547
- function d(e) {
693
+ function h(e) {
548
694
  return typeof e == "number" ? Number.isInteger(e) ? e.toLocaleString() : e.toLocaleString(void 0, { minimumFractionDigits: 1 }) : String(e);
549
695
  }
550
- function f(e) {
696
+ function g(e) {
551
697
  if (e instanceof Date) return e.toLocaleDateString();
552
698
  if (typeof e == "string") {
553
699
  let t = new Date(e);
@@ -555,7 +701,7 @@ function f(e) {
555
701
  }
556
702
  return String(e);
557
703
  }
558
- function p(e) {
704
+ function _(e) {
559
705
  if (e instanceof Date) return e.toLocaleString();
560
706
  if (typeof e == "string") {
561
707
  let t = new Date(e);
@@ -565,7 +711,7 @@ function p(e) {
565
711
  }
566
712
  //#endregion
567
713
  //#region src/core/selection.ts
568
- function m(e) {
714
+ function v(e) {
569
715
  return {
570
716
  startRow: Math.min(e.startRow, e.endRow),
571
717
  startCol: Math.min(e.startCol, e.endCol),
@@ -573,7 +719,7 @@ function m(e) {
573
719
  endCol: Math.max(e.startCol, e.endCol)
574
720
  };
575
721
  }
576
- var h = class {
722
+ var y = class {
577
723
  constructor() {
578
724
  this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
579
725
  }
@@ -600,7 +746,7 @@ var h = class {
600
746
  return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
601
747
  row: e,
602
748
  col: t
603
- }, this.rangeAnchor && (this.range = m({
749
+ }, this.rangeAnchor && (this.range = v({
604
750
  startRow: this.rangeAnchor.row,
605
751
  startCol: this.rangeAnchor.col,
606
752
  endRow: e,
@@ -671,7 +817,7 @@ var h = class {
671
817
  shiftMoveRight() {
672
818
  return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
673
819
  }
674
- }, g = class {
820
+ }, b = class {
675
821
  constructor() {
676
822
  this.current = null;
677
823
  }
@@ -692,7 +838,7 @@ var h = class {
692
838
  let e = this.current;
693
839
  return this.current = null, e;
694
840
  }
695
- }, _ = class {
841
+ }, x = class {
696
842
  constructor() {
697
843
  this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
698
844
  }
@@ -745,7 +891,7 @@ var h = class {
745
891
  };
746
892
  //#endregion
747
893
  //#region src/core/sorting.ts
748
- function v(e, t, n) {
894
+ function S(e, t, n) {
749
895
  let r = Array.from({ length: e.length }, (e, t) => t);
750
896
  if (t.length === 0) return r;
751
897
  let i = /* @__PURE__ */ new Map();
@@ -756,13 +902,13 @@ function v(e, t, n) {
756
902
  if (c && l) continue;
757
903
  if (c) return 1;
758
904
  if (l) return -1;
759
- let u = y(t, s, i.get(a) ?? "text");
905
+ let u = ee(t, s, i.get(a) ?? "text");
760
906
  if (u !== 0) return o === "asc" ? u : -u;
761
907
  }
762
908
  return n - r;
763
909
  }), r;
764
910
  }
765
- function y(e, t, n) {
911
+ function ee(e, t, n) {
766
912
  switch (n) {
767
913
  case "number": {
768
914
  let n = Number(e), r = Number(t);
@@ -777,7 +923,7 @@ function y(e, t, n) {
777
923
  default: return String(e).localeCompare(String(t));
778
924
  }
779
925
  }
780
- function b(e, t, n) {
926
+ function C(e, t, n) {
781
927
  let r = e.find((e) => e.key === t);
782
928
  return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
783
929
  ...e,
@@ -795,7 +941,7 @@ function b(e, t, n) {
795
941
  }
796
942
  //#endregion
797
943
  //#region src/core/filtering.ts
798
- function x(e, t, n) {
944
+ function w(e, t, n) {
799
945
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
800
946
  let r = [];
801
947
  for (let i = 0; i < e.length; i++) {
@@ -814,9 +960,9 @@ function x(e, t, n) {
814
960
  }
815
961
  //#endregion
816
962
  //#region src/core/undo.ts
817
- var S = 100, C = class {
963
+ var T = 100, E = class {
818
964
  constructor() {
819
- this._undoStack = [], this._redoStack = [], this._maxSize = S;
965
+ this._undoStack = [], this._redoStack = [], this._maxSize = T;
820
966
  }
821
967
  get maxSize() {
822
968
  return this._maxSize;
@@ -853,7 +999,7 @@ var S = 100, C = class {
853
999
  };
854
1000
  //#endregion
855
1001
  //#region src/clipboard/clipboard.ts
856
- function w(e, t, n) {
1002
+ function te(e, t, n) {
857
1003
  let r = [];
858
1004
  for (let i = n.startRow; i <= n.endRow; i++) {
859
1005
  let a = e[i], o = [];
@@ -865,7 +1011,7 @@ function w(e, t, n) {
865
1011
  }
866
1012
  return r.join("\n");
867
1013
  }
868
- function T(e) {
1014
+ function ne(e) {
869
1015
  let t = e.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), n = [], r = [], i = 0, a = t.length;
870
1016
  for (; i <= a;) {
871
1017
  if (i === a) {
@@ -894,7 +1040,7 @@ function T(e) {
894
1040
  }
895
1041
  return n;
896
1042
  }
897
- function E(e, t) {
1043
+ function D(e, t) {
898
1044
  if (e === "") return null;
899
1045
  switch (t.type) {
900
1046
  case "number": {
@@ -906,24 +1052,122 @@ function E(e, t) {
906
1052
  }
907
1053
  }
908
1054
  //#endregion
1055
+ //#region src/export/xlsx-writer.ts
1056
+ var re = (() => {
1057
+ let e = new Uint32Array(256);
1058
+ for (let t = 0; t < 256; t++) {
1059
+ let n = t;
1060
+ for (let e = 0; e < 8; e++) n = n & 1 ? 3988292384 ^ n >>> 1 : n >>> 1;
1061
+ e[t] = n;
1062
+ }
1063
+ return e;
1064
+ })();
1065
+ function O(e) {
1066
+ let t = 4294967295;
1067
+ for (let n = 0; n < e.length; n++) t = re[(t ^ e[n]) & 255] ^ t >>> 8;
1068
+ return (t ^ 4294967295) >>> 0;
1069
+ }
1070
+ var k = new TextEncoder();
1071
+ function A(e) {
1072
+ let t = [], n = [], r = 0;
1073
+ for (let i of e) {
1074
+ let e = k.encode(i.name), a = O(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1075
+ c.setUint32(0, 67324752, !0), c.setUint16(4, 20, !0), c.setUint16(6, 0, !0), c.setUint16(8, 0, !0), c.setUint16(10, 0, !0), c.setUint16(12, 33, !0), c.setUint32(14, a, !0), c.setUint32(18, o, !0), c.setUint32(22, o, !0), c.setUint16(26, e.length, !0), c.setUint16(28, 0, !0), new Uint8Array(s, 30).set(e), t.push(new Uint8Array(s)), t.push(i.data);
1076
+ let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
1077
+ u.setUint32(0, 33639248, !0), u.setUint16(4, 20, !0), u.setUint16(6, 20, !0), u.setUint16(8, 0, !0), u.setUint16(10, 0, !0), u.setUint16(12, 0, !0), u.setUint16(14, 33, !0), u.setUint32(16, a, !0), u.setUint32(20, o, !0), u.setUint32(24, o, !0), u.setUint16(28, e.length, !0), u.setUint16(30, 0, !0), u.setUint16(32, 0, !0), u.setUint16(34, 0, !0), u.setUint16(36, 0, !0), u.setUint32(38, 0, !0), u.setUint32(42, r, !0), new Uint8Array(l, 46).set(e), n.push(new Uint8Array(l)), r += 30 + e.length + o;
1078
+ }
1079
+ let i = j(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1080
+ 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), j([
1081
+ ...t,
1082
+ i,
1083
+ new Uint8Array(a)
1084
+ ]);
1085
+ }
1086
+ function j(e) {
1087
+ let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
1088
+ for (let t of e) n.set(t, r), r += t.length;
1089
+ return n;
1090
+ }
1091
+ function M(e) {
1092
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1093
+ }
1094
+ function N(e) {
1095
+ let t = "";
1096
+ for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1097
+ return t;
1098
+ }
1099
+ function P(e, t) {
1100
+ return N(t) + (e + 1);
1101
+ }
1102
+ function F(e) {
1103
+ let t = Date.UTC(1899, 11, 30);
1104
+ return (e.getTime() - t) / 864e5;
1105
+ }
1106
+ var I = "<?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>", L = "<?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>", R = "<?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>", z = "<?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>", B = "<?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>";
1107
+ function V(e, t) {
1108
+ let n = [], r = t.map((e, t) => `<c r="${P(0, t)}" t="str" s="2"><v>${M(e.header)}</v></c>`);
1109
+ return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1110
+ let i = t.map((t, n) => {
1111
+ let i = P(r + 1, n), a = e[t.key];
1112
+ if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1113
+ let o = t.type ?? "text";
1114
+ 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>${F(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${M(String(a))}</v></c>`;
1115
+ });
1116
+ n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1117
+ }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1118
+ <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
1119
+ <sheetData>${n.join("")}</sheetData>
1120
+ </worksheet>`;
1121
+ }
1122
+ function H(e, t) {
1123
+ let n = V(e, t);
1124
+ return A([
1125
+ {
1126
+ name: "[Content_Types].xml",
1127
+ data: k.encode(I)
1128
+ },
1129
+ {
1130
+ name: "_rels/.rels",
1131
+ data: k.encode(L)
1132
+ },
1133
+ {
1134
+ name: "xl/workbook.xml",
1135
+ data: k.encode(R)
1136
+ },
1137
+ {
1138
+ name: "xl/_rels/workbook.xml.rels",
1139
+ data: k.encode(z)
1140
+ },
1141
+ {
1142
+ name: "xl/worksheets/sheet1.xml",
1143
+ data: k.encode(n)
1144
+ },
1145
+ {
1146
+ name: "xl/styles.xml",
1147
+ data: k.encode(B)
1148
+ }
1149
+ ]);
1150
+ }
1151
+ //#endregion
909
1152
  //#region src/export/export.ts
910
- function D(e, t, n) {
1153
+ function U(e, t, n) {
911
1154
  switch (n) {
912
- case "csv": return k(e, t, ",");
913
- case "tsv": return k(e, t, " ");
914
- case "json": return j(e, t);
1155
+ case "csv": return G(e, t, ",");
1156
+ case "tsv": return G(e, t, " ");
1157
+ case "json": return q(e, t);
1158
+ case "xlsx": return H(e, t);
915
1159
  }
916
1160
  }
917
- function O(e, t) {
1161
+ function W(e, t) {
918
1162
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
919
1163
  }
920
- function k(e, t, n) {
921
- return [t.map((e) => A(e.header, n)).join(n), ...e.map((e) => t.map((t) => A(O(e[t.key], t), n)).join(n))].join("\n");
1164
+ function G(e, t, n) {
1165
+ return [t.map((e) => K(e.header, n)).join(n), ...e.map((e) => t.map((t) => K(W(e[t.key], t), n)).join(n))].join("\n");
922
1166
  }
923
- function A(e, t) {
1167
+ function K(e, t) {
924
1168
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
925
1169
  }
926
- function j(e, t) {
1170
+ function q(e, t) {
927
1171
  let n = e.map((e) => {
928
1172
  let n = {};
929
1173
  for (let r of t) {
@@ -934,28 +1178,30 @@ function j(e, t) {
934
1178
  });
935
1179
  return JSON.stringify(n, null, 2);
936
1180
  }
937
- function M(e, t, n) {
1181
+ function J(e, t, n) {
938
1182
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
939
1183
  a.href = i, a.download = t, a.style.display = "none", document.body.appendChild(a), a.click(), document.body.removeChild(a), setTimeout(() => URL.revokeObjectURL(i), 100);
940
1184
  }
941
- var N = {
1185
+ var ie = {
942
1186
  csv: "text/csv;charset=utf-8",
943
1187
  tsv: "text/tab-separated-values;charset=utf-8",
944
- json: "application/json;charset=utf-8"
945
- }, P = {
1188
+ json: "application/json;charset=utf-8",
1189
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1190
+ }, ae = {
946
1191
  csv: ".csv",
947
1192
  tsv: ".tsv",
948
- json: ".json"
1193
+ json: ".json",
1194
+ xlsx: ".xlsx"
949
1195
  };
950
- function F(e) {
951
- return N[e];
1196
+ function oe(e) {
1197
+ return ie[e];
952
1198
  }
953
- function I(e) {
954
- return P[e];
1199
+ function se(e) {
1200
+ return ae[e];
955
1201
  }
956
1202
  //#endregion
957
1203
  //#region \0@oxc-project+runtime@0.130.0/helpers/decorate.js
958
- function L(e, t, n, r) {
1204
+ function Y(e, t, n, r) {
959
1205
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
960
1206
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
961
1207
  else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
@@ -963,9 +1209,9 @@ function L(e, t, n, r) {
963
1209
  }
964
1210
  //#endregion
965
1211
  //#region src/flex-table.ts
966
- var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1212
+ var X = 120, Z = 40, ce = 32, Q = 5, $ = class extends e {
967
1213
  constructor(...e) {
968
- super(...e), this.columns = [], this.data = [], this.rowHeight = B, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new h(), this._editing = new g(), this._rowSelection = new _(), this._undo = new C(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, 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._invalidCells = /* @__PURE__ */ new Map(), this._textFilterState = /* @__PURE__ */ new Map(), this._numberFilterState = /* @__PURE__ */ new Map(), this._dateFilterState = /* @__PURE__ */ new Map();
1214
+ super(...e), this.columns = [], this.data = [], this.rowHeight = ce, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new y(), this._editing = new b(), this._rowSelection = new x(), this._undo = new E(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, 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._invalidCells = /* @__PURE__ */ new Map(), this._textFilterState = /* @__PURE__ */ new Map(), this._numberFilterState = /* @__PURE__ */ new Map(), this._dateFilterState = /* @__PURE__ */ new Map();
969
1215
  }
970
1216
  static {
971
1217
  this.styles = s;
@@ -1149,6 +1395,29 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1149
1395
  composed: !0
1150
1396
  })), this._dispatchUndoStateEvent();
1151
1397
  }
1398
+ hideColumn(e) {
1399
+ this._setColumnHidden(e, !0);
1400
+ }
1401
+ showColumn(e) {
1402
+ this._setColumnHidden(e, !1);
1403
+ }
1404
+ _setColumnHidden(e, t) {
1405
+ let n = this.columns.findIndex((t) => t.key === e);
1406
+ n !== -1 && (this.columns = this.columns.map((e, r) => r === n ? {
1407
+ ...e,
1408
+ hidden: t
1409
+ } : e), this.dispatchEvent(new CustomEvent("column-visibility-change", {
1410
+ detail: {
1411
+ key: e,
1412
+ hidden: t
1413
+ },
1414
+ bubbles: !0,
1415
+ composed: !0
1416
+ })));
1417
+ }
1418
+ getHiddenColumns() {
1419
+ return this.columns.filter((e) => e.hidden);
1420
+ }
1152
1421
  addRow(e, t) {
1153
1422
  if (this.maxRows > 0 && this.data.length >= this.maxRows) return null;
1154
1423
  let n = e ?? this._createEmptyRow(), r = t ?? this.data.length;
@@ -1251,12 +1520,12 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1251
1520
  if (!t) return "";
1252
1521
  let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
1253
1522
  for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
1254
- return D(r, n, e);
1523
+ return U(r, n, e);
1255
1524
  }
1256
- return D(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
1525
+ return U(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
1257
1526
  }
1258
1527
  exportToFile(e, t) {
1259
- M(this.exportToString(e), t ?? `export${I(e)}`, F(e));
1528
+ J(this.exportToString(e), t ?? `export${se(e)}`, oe(e));
1260
1529
  }
1261
1530
  _getSelectedDataRows() {
1262
1531
  let e = this._selection.getEffectiveRange();
@@ -1269,8 +1538,8 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1269
1538
  return this._columnWidths.get(e);
1270
1539
  }
1271
1540
  _getColWidth(e) {
1272
- let t = this._columnWidths.get(e.key) ?? e.width ?? R;
1273
- return Math.max(t, e.minWidth ?? z);
1541
+ let t = this._columnWidths.get(e.key) ?? e.width ?? X;
1542
+ return Math.max(t, e.minWidth ?? Z);
1274
1543
  }
1275
1544
  get headerHeight() {
1276
1545
  return this.rowHeight + 8;
@@ -1282,10 +1551,10 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1282
1551
  return this._visibleRowCount * this.rowHeight;
1283
1552
  }
1284
1553
  get visibleRange() {
1285
- let e = Math.max(0, this._scrollTop - this.headerHeight), t = Math.max(0, Math.floor(e / this.rowHeight) - V), n = Math.ceil(this._viewportHeight / this.rowHeight);
1554
+ let e = Math.max(0, this._scrollTop - this.headerHeight), t = Math.max(0, Math.floor(e / this.rowHeight) - Q), n = Math.ceil(this._viewportHeight / this.rowHeight);
1286
1555
  return {
1287
1556
  start: t,
1288
- end: Math.min(this._visibleRowCount, Math.floor(e / this.rowHeight) + n + V)
1557
+ end: Math.min(this._visibleRowCount, Math.floor(e / this.rowHeight) + n + Q)
1289
1558
  };
1290
1559
  }
1291
1560
  connectedCallback() {
@@ -1318,13 +1587,13 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1318
1587
  i = r;
1319
1588
  break;
1320
1589
  }
1321
- i = Math.max(0, i - V);
1590
+ i = Math.max(0, i - Q);
1322
1591
  let a = e.length;
1323
1592
  for (let e = i; e < t.length; e++) if (t[e] > r) {
1324
1593
  a = e;
1325
1594
  break;
1326
1595
  }
1327
- return a = Math.min(e.length, a + V), {
1596
+ return a = Math.min(e.length, a + Q), {
1328
1597
  start: i,
1329
1598
  end: a
1330
1599
  };
@@ -1340,7 +1609,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1340
1609
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
1341
1610
  return;
1342
1611
  }
1343
- if (this._filteredIndices = x(this.data, this._filters, (e, t, n) => {
1612
+ if (this._filteredIndices = w(this.data, this._filters, (e, t, n) => {
1344
1613
  this.dispatchEvent(new CustomEvent("filter-error", {
1345
1614
  detail: {
1346
1615
  error: e,
@@ -1353,7 +1622,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1353
1622
  }), this._filters.length === 0 && this._sortCriteria.length === 0) this._sortedIndices = Array.from({ length: this.data.length }, (e, t) => t);
1354
1623
  else if (this._sortCriteria.length === 0) this._sortedIndices = [...this._filteredIndices];
1355
1624
  else {
1356
- let e = v(this._filteredIndices.map((e) => this.data[e]), this._sortCriteria, this.visibleColumns);
1625
+ let e = S(this._filteredIndices.map((e) => this.data[e]), this._sortCriteria, this.visibleColumns);
1357
1626
  this._sortedIndices = e.map((e) => this._filteredIndices[e]);
1358
1627
  }
1359
1628
  }
@@ -1373,17 +1642,19 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1373
1642
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
1374
1643
  }
1375
1644
  _onDocumentClick() {
1376
- this._openFilterKey &&= null;
1645
+ this._openFilterKey &&= null, this._headerMenu &&= null, this._bodyContextMenu &&= null;
1377
1646
  }
1378
1647
  _onContextMenu(e) {
1379
1648
  let t = e.composedPath().find((e) => e instanceof HTMLElement && e.classList.contains("ft-cell"));
1380
1649
  if (!t) return;
1650
+ e.preventDefault();
1381
1651
  let n = t.parentElement;
1382
1652
  if (!n || !n.classList.contains("ft-row")) return;
1383
1653
  let r = parseInt(t.dataset.colIndex ?? "-1", 10), i = n.style.top, a = Math.round(parseInt(i, 10) / this.rowHeight);
1384
1654
  if (r < 0 || a < 0) return;
1385
1655
  let o = this._toDataIndex(a), s = this.visibleColumns[r];
1386
- s && this.dispatchEvent(new CustomEvent("context-menu", {
1656
+ if (!s) return;
1657
+ let c = new CustomEvent("context-menu", {
1387
1658
  detail: {
1388
1659
  x: e.clientX,
1389
1660
  y: e.clientY,
@@ -1394,7 +1665,17 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1394
1665
  rowData: this.data[o]
1395
1666
  },
1396
1667
  bubbles: !0,
1397
- composed: !0
1668
+ composed: !0,
1669
+ cancelable: !0
1670
+ });
1671
+ this.dispatchEvent(c), this.showContextMenu && !c.defaultPrevented && (this._bodyContextMenu = {
1672
+ rowIndex: a,
1673
+ colIndex: r,
1674
+ dataIndex: o,
1675
+ x: e.clientX,
1676
+ y: e.clientY
1677
+ }, requestAnimationFrame(() => {
1678
+ document.addEventListener("click", this._onDocumentClick, { once: !0 });
1398
1679
  }));
1399
1680
  }
1400
1681
  _onCellClickEvent(e, t, n) {
@@ -1467,14 +1748,30 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1467
1748
  }
1468
1749
  let t = this.shadowRoot?.querySelector(".ft-editor");
1469
1750
  if (t) {
1470
- let n = E(t.value, e);
1751
+ let n = D(t.value, e);
1471
1752
  this._applyEdit(n);
1472
1753
  } else this._cancelEdit();
1473
1754
  }
1474
1755
  _applyEdit(e) {
1756
+ this._autocompleteState = null;
1475
1757
  let t = this._editing.commit();
1476
1758
  if (this._editingCell = null, !t) return;
1477
1759
  let { row: n, col: r } = t.position, i = this._toDataIndex(n), a = this.visibleColumns[r], o = t.originalValue;
1760
+ if (a.autocomplete === "strict" && e != null && e !== "" && !this._getAutocompleteCandidates(a, "").includes(String(e))) {
1761
+ let t = "Value must be from the existing list";
1762
+ this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
1763
+ detail: {
1764
+ row: i,
1765
+ col: r,
1766
+ key: a.key,
1767
+ value: e,
1768
+ error: t
1769
+ },
1770
+ bubbles: !0,
1771
+ composed: !0
1772
+ }));
1773
+ return;
1774
+ }
1478
1775
  if (a.validator) {
1479
1776
  let t = a.validator(e, this.data[i], a);
1480
1777
  if (t) {
@@ -1513,6 +1810,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1513
1810
  })), this._dispatchUndoStateEvent();
1514
1811
  }
1515
1812
  _cancelEdit() {
1813
+ this._autocompleteState = null;
1516
1814
  let e = this._editing.cancel();
1517
1815
  this._editingCell = null, e && this.dispatchEvent(new CustomEvent("cell-edit-cancel", {
1518
1816
  detail: {
@@ -1524,8 +1822,56 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1524
1822
  }));
1525
1823
  }
1526
1824
  _onEditorKeyDown(e) {
1825
+ if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
1826
+ if (e.key === "ArrowDown") {
1827
+ e.preventDefault(), e.stopPropagation();
1828
+ let t = this._autocompleteState.candidates.length;
1829
+ this._autocompleteState = {
1830
+ ...this._autocompleteState,
1831
+ activeIndex: Math.min(this._autocompleteState.activeIndex + 1, t - 1)
1832
+ };
1833
+ return;
1834
+ }
1835
+ if (e.key === "ArrowUp") {
1836
+ e.preventDefault(), e.stopPropagation(), this._autocompleteState = {
1837
+ ...this._autocompleteState,
1838
+ activeIndex: Math.max(this._autocompleteState.activeIndex - 1, -1)
1839
+ };
1840
+ return;
1841
+ }
1842
+ if (e.key === "Enter" && this._autocompleteState.activeIndex >= 0) {
1843
+ e.preventDefault(), e.stopPropagation();
1844
+ let t = this._autocompleteState.candidates[this._autocompleteState.activeIndex];
1845
+ this._selectAutocompleteCandidate(t);
1846
+ return;
1847
+ }
1848
+ if (e.key === "Escape") {
1849
+ e.preventDefault(), e.stopPropagation(), this._autocompleteState = null;
1850
+ return;
1851
+ }
1852
+ }
1527
1853
  e.key === "Enter" ? (e.preventDefault(), e.stopPropagation(), this._commitEdit(), this._selection.moveDown(), this._syncActiveCell()) : e.key === "Tab" ? (e.preventDefault(), e.stopPropagation(), this._commitEdit(), e.shiftKey ? this._selection.movePrev() : this._selection.moveNext(), this._syncActiveCell()) : e.key === "Escape" && (e.preventDefault(), e.stopPropagation(), this._cancelEdit());
1528
1854
  }
1855
+ _getAutocompleteCandidates(e, t) {
1856
+ let n = t.toLowerCase(), r = /* @__PURE__ */ new Set(), i = [];
1857
+ for (let a of this.data) {
1858
+ let o = a[e.key];
1859
+ if (o == null) continue;
1860
+ let s = String(o);
1861
+ if (!r.has(s) && (t === "" || s.toLowerCase().includes(n)) && (r.add(s), i.push(s), i.length >= 20)) break;
1862
+ }
1863
+ return i;
1864
+ }
1865
+ _onAutocompleteInput(e, t) {
1866
+ let n = e.target.value, r = this._getAutocompleteCandidates(t, n).filter((e) => e !== n);
1867
+ this._autocompleteState = r.length > 0 ? {
1868
+ candidates: r,
1869
+ activeIndex: -1
1870
+ } : null;
1871
+ }
1872
+ _selectAutocompleteCandidate(e) {
1873
+ this._autocompleteState = null, this._applyEdit(e), this._selection.moveDown(), this._syncActiveCell();
1874
+ }
1529
1875
  _syncActiveCell() {
1530
1876
  this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._scrollToActiveCell(), this._dispatchSelectionEvent();
1531
1877
  }
@@ -1595,7 +1941,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1595
1941
  e.preventDefault();
1596
1942
  let n = t[this._activeCell.col];
1597
1943
  if (!n) return !0;
1598
- let r = this._columnWidths.get(n.key) ?? n.width ?? R, i = e.key === "ArrowRight" ? 20 : -20, a = n.minWidth ?? z, o = Math.max(a, r + i);
1944
+ let r = this._columnWidths.get(n.key) ?? n.width ?? X, i = e.key === "ArrowRight" ? 20 : -20, a = n.minWidth ?? Z, o = Math.max(a, r + i);
1599
1945
  return this._columnWidths.set(n.key, o), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
1600
1946
  detail: {
1601
1947
  key: n.key,
@@ -1624,7 +1970,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1624
1970
  async _handleCopy(e) {
1625
1971
  let t = this._selection.getEffectiveRange();
1626
1972
  if (!t) return;
1627
- let n = this.visibleColumns, r = w(this._sortedIndices.map((e) => this.data[e]), n, t);
1973
+ let n = this.visibleColumns, r = te(this._sortedIndices.map((e) => this.data[e]), n, t);
1628
1974
  try {
1629
1975
  await navigator.clipboard.writeText(r);
1630
1976
  } catch (e) {
@@ -1650,7 +1996,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1650
1996
  if (!this._activeCell) return;
1651
1997
  let e = await this._readClipboardText();
1652
1998
  if (e == null) return;
1653
- let t = T(e);
1999
+ let t = ne(e);
1654
2000
  if (t.length === 0) return;
1655
2001
  let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
1656
2002
  if (r.length > 0 || n.length > 0) {
@@ -1708,7 +2054,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1708
2054
  for (let a = 0; a < t[i].length; a++) {
1709
2055
  let s = e.col + a;
1710
2056
  if (s >= n.length) break;
1711
- let c = n[s], l = this.data[o][c.key], u = E(t[i][a], c);
2057
+ let c = n[s], l = this.data[o][c.key], u = D(t[i][a], c);
1712
2058
  this.data[o][c.key] = u, r.push({
1713
2059
  row: o,
1714
2060
  col: s,
@@ -1773,7 +2119,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1773
2119
  for (let r = e.startCol + 1; r <= e.endCol; r++) {
1774
2120
  let e = t[r];
1775
2121
  if (!e || !this._isCellEditable(e)) continue;
1776
- let a = E(o == null ? "" : String(o), e);
2122
+ let a = D(o == null ? "" : String(o), e);
1777
2123
  n.push({
1778
2124
  row: i,
1779
2125
  key: e.key,
@@ -1864,7 +2210,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1864
2210
  this._selectColumn(n);
1865
2211
  return;
1866
2212
  }
1867
- t.sortable !== !1 && (this._sortCriteria = b(this._sortCriteria, t.key, e.shiftKey), this.dataMode !== "server" && this._recomputeView(), this.requestUpdate(), this.dispatchEvent(new CustomEvent("sort-change", {
2213
+ t.sortable !== !1 && (this._sortCriteria = C(this._sortCriteria, t.key, e.shiftKey), this.dataMode !== "server" && this._recomputeView(), this.requestUpdate(), this.dispatchEvent(new CustomEvent("sort-change", {
1868
2214
  detail: { criteria: [...this._sortCriteria] },
1869
2215
  bubbles: !0,
1870
2216
  composed: !0
@@ -1906,15 +2252,25 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1906
2252
  c || l ? "ft-pinned" : ""
1907
2253
  ].filter(Boolean).join(" "), d = i ? a ? a.direction === "asc" ? "ascending" : "descending" : "none" : void 0, f = this._getColWidth(e), p = this.headerHeight, m = this._colLeftOffsets[t] ?? 0, h;
1908
2254
  h = c ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(t)}px; width: ${f}px; height: ${p}px; z-index: 4;` : l ? `position: absolute; top: 0; right: ${-this._scrollLeft + this._getPinnedRight(t)}px; width: ${f}px; height: ${p}px; z-index: 4;` : `left: ${m}px; width: ${f}px; height: ${p}px;`;
1909
- let g = this._colDrag?.active && this._colDrag.colIndex === t;
2255
+ let g = this._colDrag?.active && this._colDrag.colIndex === t, _ = [...u.split(" "), g ? "ft-col-dragging" : ""].filter(Boolean).join(" "), v = this.columns, y = v.findIndex((t) => t.key === e.key), b = [];
2256
+ if (y > 0) for (let e = y - 1; e >= 0 && v[e].hidden; e--) b.push(v[e]);
2257
+ let x = b.length > 0;
1910
2258
  return n`
1911
- <div class=${[...u.split(" "), g ? "ft-col-dragging" : ""].filter(Boolean).join(" ")}
2259
+ <div class=${_}
1912
2260
  role="columnheader"
1913
2261
  data-col-index=${t}
1914
2262
  style=${h}
1915
2263
  aria-sort=${d ?? r}
2264
+ @contextmenu=${(t) => this._onHeaderContextMenu(t, e)}
1916
2265
  @mousedown=${(n) => this._onHeaderMouseDown(n, e, t)}
1917
2266
  @click=${i ? (t) => this._onHeaderClick(t, e) : void 0}>
2267
+ ${x ? n`
2268
+ <button class="ft-hidden-col-indicator"
2269
+ title="Show hidden column(s)"
2270
+ @click=${(t) => {
2271
+ t.stopPropagation(), this._showHiddenBefore(e);
2272
+ }}>&#x276F;</button>
2273
+ ` : ""}
1918
2274
  <span>${e.header}</span>
1919
2275
  ${a ? n`<span class="ft-sort-indicator">${a.direction === "asc" ? "▲" : "▼"}</span>` : ""}
1920
2276
  ${o >= 0 ? n`<span class="ft-sort-order">${o + 1}</span>` : ""}
@@ -1936,6 +2292,139 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
1936
2292
  ${this._openFilterKey === e.key ? this._renderFilterDropdown(e) : ""}
1937
2293
  `;
1938
2294
  }
2295
+ _onHeaderContextMenu(e, t) {
2296
+ e.preventDefault();
2297
+ let n = this.columns, r = n.findIndex((e) => e.key === t.key), i = [];
2298
+ for (let e = r - 1; e >= 0 && n[e].hidden; e--) i.push(n[e]);
2299
+ for (let e = r + 1; e < n.length && n[e].hidden; e++) i.push(n[e]);
2300
+ this._headerMenu = {
2301
+ key: t.key,
2302
+ x: e.clientX,
2303
+ y: e.clientY,
2304
+ hiddenNeighbors: i
2305
+ }, this.dispatchEvent(new CustomEvent("header-context-menu", {
2306
+ detail: {
2307
+ key: t.key,
2308
+ header: t.header,
2309
+ x: e.clientX,
2310
+ y: e.clientY
2311
+ },
2312
+ bubbles: !0,
2313
+ composed: !0
2314
+ })), requestAnimationFrame(() => {
2315
+ document.addEventListener("click", this._onDocumentClick, { once: !0 });
2316
+ });
2317
+ }
2318
+ _showHiddenBefore(e) {
2319
+ let t = this.columns, n = t.findIndex((t) => t.key === e.key);
2320
+ for (let e = n - 1; e >= 0 && t[e].hidden; e--) this._setColumnHidden(t[e].key, !1);
2321
+ }
2322
+ _renderHeaderContextMenu() {
2323
+ if (!this._headerMenu) return r;
2324
+ let { key: e, x: t, y: i, hiddenNeighbors: a } = this._headerMenu;
2325
+ return this.columns.find((t) => t.key === e) ? n`
2326
+ <div class="ft-header-menu" style="position: fixed; left: ${t}px; top: ${i}px; z-index: 200;"
2327
+ @mousedown=${(e) => e.stopPropagation()}>
2328
+ <div class="ft-header-menu-item"
2329
+ @click=${() => {
2330
+ this._setColumnHidden(e, !0), this._headerMenu = null;
2331
+ }}>
2332
+ Hide column
2333
+ </div>
2334
+ ${a.map((e) => n`
2335
+ <div class="ft-header-menu-item"
2336
+ @click=${() => {
2337
+ this._setColumnHidden(e.key, !1), this._headerMenu = null;
2338
+ }}>
2339
+ Show: ${e.header}
2340
+ </div>
2341
+ `)}
2342
+ </div>
2343
+ ` : r;
2344
+ }
2345
+ _renderBodyContextMenu() {
2346
+ if (!this._bodyContextMenu) return r;
2347
+ let { colIndex: e, dataIndex: t, x: i, y: a } = this._bodyContextMenu, o = this.visibleColumns[e];
2348
+ if (!o) return r;
2349
+ let s = this.data[t]?.[o.key], c = this._filters.some((e) => e.key === o.key), l = () => {
2350
+ this._bodyContextMenu = null;
2351
+ };
2352
+ return n`
2353
+ <div class="ft-body-context-menu" style="position: fixed; left: ${i + 200 > window.innerWidth ? i - 200 : i}px; top: ${a + 280 > window.innerHeight ? a - 280 : a}px; z-index: 200;"
2354
+ @mousedown=${(e) => e.stopPropagation()}>
2355
+ <div class="ft-context-menu-item"
2356
+ @click=${() => {
2357
+ this._handleCopy(!1), l();
2358
+ }}>
2359
+ Copy
2360
+ </div>
2361
+ <div class="ft-context-menu-separator"></div>
2362
+ <div class="ft-context-menu-item"
2363
+ @click=${() => {
2364
+ this.addRow(void 0, t), l();
2365
+ }}>
2366
+ Insert row above
2367
+ </div>
2368
+ <div class="ft-context-menu-item"
2369
+ @click=${() => {
2370
+ this.addRow(void 0, t + 1), l();
2371
+ }}>
2372
+ Insert row below
2373
+ </div>
2374
+ <div class="ft-context-menu-item ft-context-menu-danger"
2375
+ @click=${() => {
2376
+ this.deleteRows([t]), l();
2377
+ }}>
2378
+ Delete row
2379
+ </div>
2380
+ <div class="ft-context-menu-separator"></div>
2381
+ <div class="ft-context-menu-item"
2382
+ @click=${() => {
2383
+ this._setColumnHidden(o.key, !0), l();
2384
+ }}>
2385
+ Hide column
2386
+ </div>
2387
+ <div class="ft-context-menu-separator"></div>
2388
+ <div class="ft-context-menu-item"
2389
+ @click=${() => {
2390
+ this._applySortFromMenu(o.key, "asc"), l();
2391
+ }}>
2392
+ Sort ascending ↑
2393
+ </div>
2394
+ <div class="ft-context-menu-item"
2395
+ @click=${() => {
2396
+ this._applySortFromMenu(o.key, "desc"), l();
2397
+ }}>
2398
+ Sort descending ↓
2399
+ </div>
2400
+ <div class="ft-context-menu-separator"></div>
2401
+ <div class="ft-context-menu-item"
2402
+ @click=${() => {
2403
+ this.setFilter(o.key, (e) => e === s), l();
2404
+ }}>
2405
+ Filter by this value
2406
+ </div>
2407
+ ${c ? n`
2408
+ <div class="ft-context-menu-item"
2409
+ @click=${() => {
2410
+ this.removeFilter(o.key), l();
2411
+ }}>
2412
+ Clear filter
2413
+ </div>
2414
+ ` : ""}
2415
+ </div>
2416
+ `;
2417
+ }
2418
+ _applySortFromMenu(e, t) {
2419
+ this.columns.find((t) => t.key === e) && (this._sortCriteria = [{
2420
+ key: e,
2421
+ direction: t
2422
+ }], this._sortedIndices = S(this.data, this._sortCriteria, this.columns), this.dispatchEvent(new CustomEvent("sort-change", {
2423
+ detail: { sortCriteria: [...this._sortCriteria] },
2424
+ bubbles: !0,
2425
+ composed: !0
2426
+ })), this.requestUpdate());
2427
+ }
1939
2428
  _adjustFilterDropdown() {
1940
2429
  if (!this._openFilterKey) return;
1941
2430
  let e = this.shadowRoot?.querySelector(".ft-filter-dropdown");
@@ -2076,7 +2565,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2076
2565
  if (!n) return;
2077
2566
  let r = this.shadowRoot?.querySelectorAll(`.ft-cell[data-col-index="${t}"]`), i = 0, a = this.shadowRoot?.querySelector(`.ft-header-cell[data-col-index="${t}"]`);
2078
2567
  if (a && (i = Math.max(i, a.scrollWidth)), r) for (let e of r) i = Math.max(i, e.scrollWidth);
2079
- let o = n.minWidth ?? z, s = Math.max(o, i + 8);
2568
+ let o = n.minWidth ?? Z, s = Math.max(o, i + 8);
2080
2569
  this._columnWidths.set(n.key, s), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
2081
2570
  detail: {
2082
2571
  key: n.key,
@@ -2089,7 +2578,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2089
2578
  }
2090
2579
  _onResizeStart(e, t) {
2091
2580
  e.preventDefault(), e.stopPropagation();
2092
- let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? R;
2581
+ let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? X;
2093
2582
  this._resizing = {
2094
2583
  colIndex: t,
2095
2584
  startX: e.clientX,
@@ -2097,13 +2586,13 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2097
2586
  };
2098
2587
  let i = (e) => {
2099
2588
  if (!this._resizing) return;
2100
- let t = e.clientX - this._resizing.startX, r = n.minWidth ?? z, i = Math.max(r, this._resizing.startWidth + t);
2589
+ let t = e.clientX - this._resizing.startX, r = n.minWidth ?? Z, i = Math.max(r, this._resizing.startWidth + t);
2101
2590
  this._columnWidths.set(n.key, i), this.requestUpdate();
2102
2591
  }, a = () => {
2103
2592
  document.removeEventListener("mousemove", i), document.removeEventListener("mouseup", o), this._resizeCleanup = null;
2104
2593
  }, o = () => {
2105
2594
  if (a(), this._resizing) {
2106
- let e = this._columnWidths.get(n.key) ?? R;
2595
+ let e = this._columnWidths.get(n.key) ?? X;
2107
2596
  this.dispatchEvent(new CustomEvent("column-resize", {
2108
2597
  detail: {
2109
2598
  key: n.key,
@@ -2553,6 +3042,8 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2553
3042
  ${this.footerData ? this._renderFooter(i, a, o) : ""}
2554
3043
  ${_}
2555
3044
  ${g}
3045
+ ${this._renderHeaderContextMenu()}
3046
+ ${this._renderBodyContextMenu()}
2556
3047
  `;
2557
3048
  }
2558
3049
  _onSelectAllChange(e) {
@@ -2616,11 +3107,17 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2616
3107
  `;
2617
3108
  }
2618
3109
  _renderCell(e, t, i, a) {
2619
- let o = this._activeCell?.row === i && this._activeCell?.col === a, s = this._editingCell?.row === i && this._editingCell?.col === a, l = this._selection.isInRange(i, a), u = t.pinned === "left", d = t.pinned === "right", f = u || d, p = this._getColWidth(t), m = this.rowHeight, h = this._colLeftOffsets[a] ?? 0, g;
2620
- g = u ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(a)}px; width: ${p}px; height: ${m}px; z-index: 2;` : d ? `position: absolute; top: 0; right: ${-this._scrollLeft + this._getPinnedRight(a)}px; width: ${p}px; height: ${m}px; z-index: 2;` : `left: ${h}px; width: ${p}px; height: ${m}px;`;
3110
+ let o = this._activeCell?.row === i && this._activeCell?.col === a, s = this._editingCell?.row === i && this._editingCell?.col === a, c = this._selection.isInRange(i, a), l = t.pinned === "left", u = t.pinned === "right", d = l || u, p = this._getColWidth(t), m = this.rowHeight, h = this._colLeftOffsets[a] ?? 0, g;
3111
+ g = l ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(a)}px; width: ${p}px; height: ${m}px; z-index: 2;` : u ? `position: absolute; top: 0; right: ${-this._scrollLeft + this._getPinnedRight(a)}px; width: ${p}px; height: ${m}px; z-index: 2;` : `left: ${h}px; width: ${p}px; height: ${m}px;`;
2621
3112
  let _ = !this._isCellEditable(t);
3113
+ if (t.conditionalRules && t.conditionalRules.length > 0) {
3114
+ let n = e[t.key], r = {};
3115
+ for (let i of t.conditionalRules) i.when(n, e, t) && (i.style.background && (r.background = i.style.background), i.style.color && (r.color = i.style.color), i.style.fontWeight && (r["font-weight"] = i.style.fontWeight), i.style.fontStyle && (r["font-style"] = i.style.fontStyle));
3116
+ let i = Object.entries(r).map(([e, t]) => `${e}: ${t}`).join("; ");
3117
+ i && (g += " " + i + ";");
3118
+ }
2622
3119
  if (s) return n`
2623
- <div class="ft-cell ft-editing ft-active ${f ? "ft-pinned" : ""}" role="gridcell"
3120
+ <div class="ft-cell ft-editing ft-active ${d ? "ft-pinned" : ""}" role="gridcell"
2624
3121
  data-col-index=${a}
2625
3122
  aria-selected="true"
2626
3123
  aria-readonly=${_ ? "true" : r}
@@ -2628,14 +3125,14 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2628
3125
  ${this._renderEditor(e, t)}
2629
3126
  </div>
2630
3127
  `;
2631
- let v = o || l, y = this._isCellInvalid(i, a), b = (this._findState?.results ?? []).findIndex((e) => e.row === i && e.col === a), x = b >= 0, S = x && b === this._findState.currentIndex;
3128
+ let v = o || c, y = this._isCellInvalid(i, a), b = (this._findState?.results ?? []).findIndex((e) => e.row === i && e.col === a), x = b >= 0, S = x && b === this._findState.currentIndex;
2632
3129
  return n`
2633
3130
  <div class=${[
2634
3131
  "ft-cell",
2635
3132
  `ft-type-${t.type ?? "text"}`,
2636
3133
  o ? "ft-active" : "",
2637
- l ? "ft-selected" : "",
2638
- f ? "ft-pinned" : "",
3134
+ c ? "ft-selected" : "",
3135
+ d ? "ft-pinned" : "",
2639
3136
  y ? "ft-invalid" : "",
2640
3137
  S ? "ft-find-current" : x ? "ft-find-match" : ""
2641
3138
  ].filter(Boolean).join(" ")}
@@ -2650,45 +3147,67 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2650
3147
  @mouseenter=${() => this._onCellMouseEnter(i, a)}
2651
3148
  @click=${(e) => this._onCellClickEvent(e, i, a)}
2652
3149
  @dblclick=${() => this._onCellDblClick(i, a)}>
2653
- ${c(e[t.key], e, t)}
3150
+ ${f(e[t.key], e, t)}
2654
3151
  </div>
2655
3152
  `;
2656
3153
  }
2657
3154
  _renderEditor(e, t) {
2658
3155
  if (t.editor) return t.editor(e[t.key], e, t);
2659
- let r = e[t.key], i = r == null ? "" : String(r);
3156
+ let i = e[t.key], a = i == null ? "" : String(i);
2660
3157
  if (t.type === "number") return n`
2661
3158
  <input class="ft-editor ft-editor-number" type="number"
2662
- .value=${i}
3159
+ .value=${a}
2663
3160
  @keydown=${this._onEditorKeyDown}
2664
3161
  @blur=${() => this._commitEdit()}>
2665
3162
  `;
2666
3163
  if (t.type === "date") return n`
2667
3164
  <input class="ft-editor" type="date"
2668
- .value=${this._toDateInputValue(r)}
3165
+ .value=${this._toDateInputValue(i)}
2669
3166
  @keydown=${this._onEditorKeyDown}
2670
3167
  @blur=${() => this._commitEdit()}>
2671
3168
  `;
2672
3169
  if (t.type === "datetime") return n`
2673
3170
  <input class="ft-editor" type="datetime-local"
2674
- .value=${this._toDateTimeInputValue(r)}
3171
+ .value=${this._toDateTimeInputValue(i)}
2675
3172
  @keydown=${this._onEditorKeyDown}
2676
3173
  @blur=${() => this._commitEdit()}>
2677
3174
  `;
2678
3175
  if (t.type === "select" && t.options && t.options.length > 0) {
2679
- let e = t.options, i = typeof e[0] == "string";
3176
+ let e = t.options, r = typeof e[0] == "string";
2680
3177
  return n`
2681
3178
  <select class="ft-editor"
2682
3179
  @keydown=${this._onEditorKeyDown}
2683
3180
  @blur=${() => this._commitEdit()}
2684
3181
  @change=${() => this._commitEdit()}>
2685
- ${i ? e.map((e) => n`<option value=${e} ?selected=${e === r}>${e}</option>`) : e.map((e) => n`<option value=${String(e.value)} ?selected=${e.value === r}>${e.label}</option>`)}
3182
+ ${r ? e.map((e) => n`<option value=${e} ?selected=${e === i}>${e}</option>`) : e.map((e) => n`<option value=${String(e.value)} ?selected=${e.value === i}>${e.label}</option>`)}
2686
3183
  </select>
3184
+ `;
3185
+ }
3186
+ if (t.autocomplete) {
3187
+ let e = this._autocompleteState?.candidates ?? [], i = this._autocompleteState?.activeIndex ?? -1;
3188
+ return n`
3189
+ <input class="ft-editor" type="text"
3190
+ .value=${a}
3191
+ @input=${(e) => this._onAutocompleteInput(e, t)}
3192
+ @keydown=${this._onEditorKeyDown}
3193
+ @blur=${() => this._commitEdit()}>
3194
+ ${e.length > 0 ? n`
3195
+ <div class="ft-autocomplete-dropdown">
3196
+ ${e.map((e, t) => n`
3197
+ <div class="ft-autocomplete-item ${t === i ? "ft-autocomplete-active" : ""}"
3198
+ @mousedown=${(t) => {
3199
+ t.preventDefault(), this._selectAutocompleteCandidate(e);
3200
+ }}>
3201
+ ${e}
3202
+ </div>
3203
+ `)}
3204
+ </div>
3205
+ ` : r}
2687
3206
  `;
2688
3207
  }
2689
3208
  return n`
2690
3209
  <input class="ft-editor" type="text"
2691
- .value=${i}
3210
+ .value=${a}
2692
3211
  @keydown=${this._onEditorKeyDown}
2693
3212
  @blur=${() => this._commitEdit()}>
2694
3213
  `;
@@ -2704,36 +3223,39 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
2704
3223
  return isNaN(t.getTime()) ? "" : `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}T${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
2705
3224
  }
2706
3225
  };
2707
- L([a({ type: Array })], H.prototype, "columns", void 0), L([a({
3226
+ Y([a({ type: Array })], $.prototype, "columns", void 0), Y([a({
2708
3227
  type: Array,
2709
3228
  hasChanged: () => !0
2710
- })], H.prototype, "data", void 0), L([a({
3229
+ })], $.prototype, "data", void 0), Y([a({
2711
3230
  type: Number,
2712
3231
  attribute: "row-height"
2713
- })], H.prototype, "rowHeight", void 0), L([a({
3232
+ })], $.prototype, "rowHeight", void 0), Y([a({
2714
3233
  type: Boolean,
2715
3234
  attribute: "show-row-numbers"
2716
- })], H.prototype, "showRowNumbers", void 0), L([a({
3235
+ })], $.prototype, "showRowNumbers", void 0), Y([a({
2717
3236
  type: String,
2718
3237
  reflect: !0
2719
- })], H.prototype, "theme", void 0), L([a({
3238
+ })], $.prototype, "theme", void 0), Y([a({
2720
3239
  type: Number,
2721
3240
  attribute: "max-rows"
2722
- })], H.prototype, "maxRows", void 0), L([a({ type: Boolean })], H.prototype, "editable", void 0), L([a({
3241
+ })], $.prototype, "maxRows", void 0), Y([a({ type: Boolean })], $.prototype, "editable", void 0), Y([a({
2723
3242
  type: Boolean,
2724
3243
  attribute: "show-filters"
2725
- })], H.prototype, "showFilters", void 0), L([a({ type: Boolean })], H.prototype, "selectable", void 0), L([a({
3244
+ })], $.prototype, "showFilters", void 0), Y([a({
3245
+ type: Boolean,
3246
+ attribute: "show-context-menu"
3247
+ })], $.prototype, "showContextMenu", void 0), Y([a({ type: Boolean })], $.prototype, "selectable", void 0), Y([a({
2726
3248
  type: String,
2727
3249
  attribute: "selection-mode"
2728
- })], H.prototype, "selectionMode", null), L([a({
3250
+ })], $.prototype, "selectionMode", null), Y([a({
2729
3251
  type: String,
2730
3252
  attribute: "data-mode"
2731
- })], H.prototype, "dataMode", void 0), L([a({
3253
+ })], $.prototype, "dataMode", void 0), Y([a({
2732
3254
  type: Object,
2733
3255
  attribute: "footer-data"
2734
- })], H.prototype, "footerData", void 0), L([a({
3256
+ })], $.prototype, "footerData", void 0), Y([a({
2735
3257
  type: Number,
2736
3258
  attribute: "max-undo-size"
2737
- })], H.prototype, "maxUndoSize", null), L([o()], H.prototype, "_scrollTop", void 0), L([o()], H.prototype, "_scrollLeft", void 0), L([o()], H.prototype, "_viewportHeight", void 0), L([o()], H.prototype, "_viewportWidth", void 0), L([o()], H.prototype, "_activeCell", void 0), L([o()], H.prototype, "_editingCell", void 0), L([o()], H.prototype, "_sortCriteria", void 0), L([o()], H.prototype, "_openFilterKey", void 0), L([o()], H.prototype, "_rowSelectionVersion", void 0), H = L([i("flex-table")], H);
3259
+ })], $.prototype, "maxUndoSize", null), Y([o()], $.prototype, "_scrollTop", void 0), Y([o()], $.prototype, "_scrollLeft", void 0), Y([o()], $.prototype, "_viewportHeight", void 0), Y([o()], $.prototype, "_viewportWidth", void 0), Y([o()], $.prototype, "_activeCell", void 0), Y([o()], $.prototype, "_editingCell", void 0), Y([o()], $.prototype, "_sortCriteria", void 0), Y([o()], $.prototype, "_openFilterKey", void 0), Y([o()], $.prototype, "_rowSelectionVersion", void 0), Y([o()], $.prototype, "_autocompleteState", void 0), Y([o()], $.prototype, "_headerMenu", void 0), Y([o()], $.prototype, "_bodyContextMenu", void 0), $ = Y([i("flex-table")], $);
2738
3260
  //#endregion
2739
- export { c as a, _ as i, D as n, C as r, H as t };
3261
+ export { f as a, x as i, U as n, E as r, $ as t };