@iyulab/flex-table 0.11.0 → 0.13.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/dist/{flex-table-DJvbRtBl.js → flex-table-zJST_6sy.js} +383 -96
- package/dist/flex-table.d.ts +15 -0
- package/dist/flex-table.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/models/types.d.ts +27 -0
- package/dist/react.js +1 -1
- package/dist/renderers/format.d.ts +19 -0
- package/dist/renderers/format.test.d.ts +1 -0
- package/package.json +1 -1
|
@@ -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,56 @@ 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
|
+
|
|
442
522
|
/* Find / Replace panel */
|
|
443
523
|
.ft-find-panel {
|
|
444
524
|
position: sticky;
|
|
@@ -524,30 +604,60 @@ var s = t`
|
|
|
524
604
|
}
|
|
525
605
|
`;
|
|
526
606
|
//#endregion
|
|
607
|
+
//#region src/renderers/format.ts
|
|
608
|
+
function c(e, t) {
|
|
609
|
+
return e == null ? "" : typeof t == "function" ? t(e) : l(t) ? d(e, t) : u(e, t);
|
|
610
|
+
}
|
|
611
|
+
function l(e) {
|
|
612
|
+
return /[yMdHhms]/.test(e);
|
|
613
|
+
}
|
|
614
|
+
function u(e, t) {
|
|
615
|
+
let n = typeof e == "number" ? e : Number(e);
|
|
616
|
+
if (isNaN(n)) return String(e);
|
|
617
|
+
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 = {
|
|
618
|
+
minimumFractionDigits: c,
|
|
619
|
+
maximumFractionDigits: c,
|
|
620
|
+
useGrouping: o.includes(",")
|
|
621
|
+
}, u;
|
|
622
|
+
return r ? u = new Intl.NumberFormat(void 0, {
|
|
623
|
+
...l,
|
|
624
|
+
style: "percent"
|
|
625
|
+
}).format(n) : (u = new Intl.NumberFormat(void 0, l).format(n), a && (u = a + u)), u + "";
|
|
626
|
+
}
|
|
627
|
+
function d(e, t) {
|
|
628
|
+
let n;
|
|
629
|
+
if (e instanceof Date) n = e;
|
|
630
|
+
else if (typeof e == "string" || typeof e == "number") n = new Date(e);
|
|
631
|
+
else return String(e);
|
|
632
|
+
if (isNaN(n.getTime())) return String(e);
|
|
633
|
+
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");
|
|
634
|
+
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);
|
|
635
|
+
}
|
|
636
|
+
//#endregion
|
|
527
637
|
//#region src/renderers/cell-renderer.ts
|
|
528
|
-
function
|
|
529
|
-
return n.renderer ? n.renderer(e, t, n) :
|
|
638
|
+
function f(e, t, n) {
|
|
639
|
+
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
640
|
}
|
|
531
|
-
function
|
|
641
|
+
function p(e, t) {
|
|
532
642
|
if (e == null) return "";
|
|
533
643
|
switch (t.type) {
|
|
534
|
-
case "number": return
|
|
644
|
+
case "number": return h(e);
|
|
535
645
|
case "boolean": return n`<span class="ft-bool">${e ? "✔" : ""}</span>`;
|
|
536
|
-
case "date": return
|
|
537
|
-
case "datetime": return
|
|
538
|
-
case "select": return
|
|
646
|
+
case "date": return g(e);
|
|
647
|
+
case "datetime": return _(e);
|
|
648
|
+
case "select": return m(e, t);
|
|
539
649
|
default: return String(e);
|
|
540
650
|
}
|
|
541
651
|
}
|
|
542
|
-
function
|
|
652
|
+
function m(e, t) {
|
|
543
653
|
if (!t.options || t.options.length === 0 || typeof t.options[0] == "string") return e == null ? "" : String(e);
|
|
544
654
|
let n = t.options.find((t) => t.value === e);
|
|
545
655
|
return n ? n.label : e == null ? "" : String(e);
|
|
546
656
|
}
|
|
547
|
-
function
|
|
657
|
+
function h(e) {
|
|
548
658
|
return typeof e == "number" ? Number.isInteger(e) ? e.toLocaleString() : e.toLocaleString(void 0, { minimumFractionDigits: 1 }) : String(e);
|
|
549
659
|
}
|
|
550
|
-
function
|
|
660
|
+
function g(e) {
|
|
551
661
|
if (e instanceof Date) return e.toLocaleDateString();
|
|
552
662
|
if (typeof e == "string") {
|
|
553
663
|
let t = new Date(e);
|
|
@@ -555,7 +665,7 @@ function f(e) {
|
|
|
555
665
|
}
|
|
556
666
|
return String(e);
|
|
557
667
|
}
|
|
558
|
-
function
|
|
668
|
+
function _(e) {
|
|
559
669
|
if (e instanceof Date) return e.toLocaleString();
|
|
560
670
|
if (typeof e == "string") {
|
|
561
671
|
let t = new Date(e);
|
|
@@ -565,7 +675,7 @@ function p(e) {
|
|
|
565
675
|
}
|
|
566
676
|
//#endregion
|
|
567
677
|
//#region src/core/selection.ts
|
|
568
|
-
function
|
|
678
|
+
function v(e) {
|
|
569
679
|
return {
|
|
570
680
|
startRow: Math.min(e.startRow, e.endRow),
|
|
571
681
|
startCol: Math.min(e.startCol, e.endCol),
|
|
@@ -573,7 +683,7 @@ function m(e) {
|
|
|
573
683
|
endCol: Math.max(e.startCol, e.endCol)
|
|
574
684
|
};
|
|
575
685
|
}
|
|
576
|
-
var
|
|
686
|
+
var y = class {
|
|
577
687
|
constructor() {
|
|
578
688
|
this.activeCell = null, this.rangeAnchor = null, this.range = null, this.extraRanges = [], this._rowCount = 0, this._colCount = 0;
|
|
579
689
|
}
|
|
@@ -600,7 +710,7 @@ var h = class {
|
|
|
600
710
|
return e < 0 || e >= this._rowCount || t < 0 || t >= this._colCount ? this.activeCell : (!this.rangeAnchor && this.activeCell && (this.rangeAnchor = { ...this.activeCell }), this.activeCell = {
|
|
601
711
|
row: e,
|
|
602
712
|
col: t
|
|
603
|
-
}, this.rangeAnchor && (this.range =
|
|
713
|
+
}, this.rangeAnchor && (this.range = v({
|
|
604
714
|
startRow: this.rangeAnchor.row,
|
|
605
715
|
startCol: this.rangeAnchor.col,
|
|
606
716
|
endRow: e,
|
|
@@ -671,7 +781,7 @@ var h = class {
|
|
|
671
781
|
shiftMoveRight() {
|
|
672
782
|
return this.activeCell ? this.setActiveWithRange(this.activeCell.row, this.activeCell.col + 1) : null;
|
|
673
783
|
}
|
|
674
|
-
},
|
|
784
|
+
}, b = class {
|
|
675
785
|
constructor() {
|
|
676
786
|
this.current = null;
|
|
677
787
|
}
|
|
@@ -692,7 +802,7 @@ var h = class {
|
|
|
692
802
|
let e = this.current;
|
|
693
803
|
return this.current = null, e;
|
|
694
804
|
}
|
|
695
|
-
},
|
|
805
|
+
}, x = class {
|
|
696
806
|
constructor() {
|
|
697
807
|
this._selected = /* @__PURE__ */ new Set(), this._mode = "multi", this._rowCount = 0;
|
|
698
808
|
}
|
|
@@ -745,7 +855,7 @@ var h = class {
|
|
|
745
855
|
};
|
|
746
856
|
//#endregion
|
|
747
857
|
//#region src/core/sorting.ts
|
|
748
|
-
function
|
|
858
|
+
function S(e, t, n) {
|
|
749
859
|
let r = Array.from({ length: e.length }, (e, t) => t);
|
|
750
860
|
if (t.length === 0) return r;
|
|
751
861
|
let i = /* @__PURE__ */ new Map();
|
|
@@ -756,13 +866,13 @@ function v(e, t, n) {
|
|
|
756
866
|
if (c && l) continue;
|
|
757
867
|
if (c) return 1;
|
|
758
868
|
if (l) return -1;
|
|
759
|
-
let u =
|
|
869
|
+
let u = C(t, s, i.get(a) ?? "text");
|
|
760
870
|
if (u !== 0) return o === "asc" ? u : -u;
|
|
761
871
|
}
|
|
762
872
|
return n - r;
|
|
763
873
|
}), r;
|
|
764
874
|
}
|
|
765
|
-
function
|
|
875
|
+
function C(e, t, n) {
|
|
766
876
|
switch (n) {
|
|
767
877
|
case "number": {
|
|
768
878
|
let n = Number(e), r = Number(t);
|
|
@@ -777,7 +887,7 @@ function y(e, t, n) {
|
|
|
777
887
|
default: return String(e).localeCompare(String(t));
|
|
778
888
|
}
|
|
779
889
|
}
|
|
780
|
-
function
|
|
890
|
+
function w(e, t, n) {
|
|
781
891
|
let r = e.find((e) => e.key === t);
|
|
782
892
|
return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
|
|
783
893
|
...e,
|
|
@@ -795,7 +905,7 @@ function b(e, t, n) {
|
|
|
795
905
|
}
|
|
796
906
|
//#endregion
|
|
797
907
|
//#region src/core/filtering.ts
|
|
798
|
-
function
|
|
908
|
+
function T(e, t, n) {
|
|
799
909
|
if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
|
|
800
910
|
let r = [];
|
|
801
911
|
for (let i = 0; i < e.length; i++) {
|
|
@@ -814,9 +924,9 @@ function x(e, t, n) {
|
|
|
814
924
|
}
|
|
815
925
|
//#endregion
|
|
816
926
|
//#region src/core/undo.ts
|
|
817
|
-
var
|
|
927
|
+
var E = 100, D = class {
|
|
818
928
|
constructor() {
|
|
819
|
-
this._undoStack = [], this._redoStack = [], this._maxSize =
|
|
929
|
+
this._undoStack = [], this._redoStack = [], this._maxSize = E;
|
|
820
930
|
}
|
|
821
931
|
get maxSize() {
|
|
822
932
|
return this._maxSize;
|
|
@@ -853,7 +963,7 @@ var S = 100, C = class {
|
|
|
853
963
|
};
|
|
854
964
|
//#endregion
|
|
855
965
|
//#region src/clipboard/clipboard.ts
|
|
856
|
-
function
|
|
966
|
+
function O(e, t, n) {
|
|
857
967
|
let r = [];
|
|
858
968
|
for (let i = n.startRow; i <= n.endRow; i++) {
|
|
859
969
|
let a = e[i], o = [];
|
|
@@ -865,7 +975,7 @@ function w(e, t, n) {
|
|
|
865
975
|
}
|
|
866
976
|
return r.join("\n");
|
|
867
977
|
}
|
|
868
|
-
function
|
|
978
|
+
function k(e) {
|
|
869
979
|
let t = e.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), n = [], r = [], i = 0, a = t.length;
|
|
870
980
|
for (; i <= a;) {
|
|
871
981
|
if (i === a) {
|
|
@@ -894,7 +1004,7 @@ function T(e) {
|
|
|
894
1004
|
}
|
|
895
1005
|
return n;
|
|
896
1006
|
}
|
|
897
|
-
function
|
|
1007
|
+
function A(e, t) {
|
|
898
1008
|
if (e === "") return null;
|
|
899
1009
|
switch (t.type) {
|
|
900
1010
|
case "number": {
|
|
@@ -907,23 +1017,23 @@ function E(e, t) {
|
|
|
907
1017
|
}
|
|
908
1018
|
//#endregion
|
|
909
1019
|
//#region src/export/export.ts
|
|
910
|
-
function
|
|
1020
|
+
function j(e, t, n) {
|
|
911
1021
|
switch (n) {
|
|
912
|
-
case "csv": return
|
|
913
|
-
case "tsv": return
|
|
914
|
-
case "json": return
|
|
1022
|
+
case "csv": return N(e, t, ",");
|
|
1023
|
+
case "tsv": return N(e, t, " ");
|
|
1024
|
+
case "json": return F(e, t);
|
|
915
1025
|
}
|
|
916
1026
|
}
|
|
917
|
-
function
|
|
1027
|
+
function M(e, t) {
|
|
918
1028
|
return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
|
|
919
1029
|
}
|
|
920
|
-
function
|
|
921
|
-
return [t.map((e) =>
|
|
1030
|
+
function N(e, t, n) {
|
|
1031
|
+
return [t.map((e) => P(e.header, n)).join(n), ...e.map((e) => t.map((t) => P(M(e[t.key], t), n)).join(n))].join("\n");
|
|
922
1032
|
}
|
|
923
|
-
function
|
|
1033
|
+
function P(e, t) {
|
|
924
1034
|
return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
|
|
925
1035
|
}
|
|
926
|
-
function
|
|
1036
|
+
function F(e, t) {
|
|
927
1037
|
let n = e.map((e) => {
|
|
928
1038
|
let n = {};
|
|
929
1039
|
for (let r of t) {
|
|
@@ -934,28 +1044,28 @@ function j(e, t) {
|
|
|
934
1044
|
});
|
|
935
1045
|
return JSON.stringify(n, null, 2);
|
|
936
1046
|
}
|
|
937
|
-
function
|
|
1047
|
+
function I(e, t, n) {
|
|
938
1048
|
let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
|
|
939
1049
|
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
1050
|
}
|
|
941
|
-
var
|
|
1051
|
+
var L = {
|
|
942
1052
|
csv: "text/csv;charset=utf-8",
|
|
943
1053
|
tsv: "text/tab-separated-values;charset=utf-8",
|
|
944
1054
|
json: "application/json;charset=utf-8"
|
|
945
|
-
},
|
|
1055
|
+
}, R = {
|
|
946
1056
|
csv: ".csv",
|
|
947
1057
|
tsv: ".tsv",
|
|
948
1058
|
json: ".json"
|
|
949
1059
|
};
|
|
950
|
-
function
|
|
951
|
-
return
|
|
1060
|
+
function z(e) {
|
|
1061
|
+
return L[e];
|
|
952
1062
|
}
|
|
953
|
-
function
|
|
954
|
-
return
|
|
1063
|
+
function B(e) {
|
|
1064
|
+
return R[e];
|
|
955
1065
|
}
|
|
956
1066
|
//#endregion
|
|
957
1067
|
//#region \0@oxc-project+runtime@0.130.0/helpers/decorate.js
|
|
958
|
-
function
|
|
1068
|
+
function V(e, t, n, r) {
|
|
959
1069
|
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
960
1070
|
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
961
1071
|
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 +1073,9 @@ function L(e, t, n, r) {
|
|
|
963
1073
|
}
|
|
964
1074
|
//#endregion
|
|
965
1075
|
//#region src/flex-table.ts
|
|
966
|
-
var
|
|
1076
|
+
var H = 120, U = 40, W = 32, G = 5, K = class extends e {
|
|
967
1077
|
constructor(...e) {
|
|
968
|
-
super(...e), this.columns = [], this.data = [], this.rowHeight =
|
|
1078
|
+
super(...e), this.columns = [], this.data = [], this.rowHeight = W, 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 y(), this._editing = new b(), this._rowSelection = new x(), this._undo = new D(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._autocompleteState = null, this._headerMenu = 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
1079
|
}
|
|
970
1080
|
static {
|
|
971
1081
|
this.styles = s;
|
|
@@ -1149,6 +1259,29 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1149
1259
|
composed: !0
|
|
1150
1260
|
})), this._dispatchUndoStateEvent();
|
|
1151
1261
|
}
|
|
1262
|
+
hideColumn(e) {
|
|
1263
|
+
this._setColumnHidden(e, !0);
|
|
1264
|
+
}
|
|
1265
|
+
showColumn(e) {
|
|
1266
|
+
this._setColumnHidden(e, !1);
|
|
1267
|
+
}
|
|
1268
|
+
_setColumnHidden(e, t) {
|
|
1269
|
+
let n = this.columns.findIndex((t) => t.key === e);
|
|
1270
|
+
n !== -1 && (this.columns = this.columns.map((e, r) => r === n ? {
|
|
1271
|
+
...e,
|
|
1272
|
+
hidden: t
|
|
1273
|
+
} : e), this.dispatchEvent(new CustomEvent("column-visibility-change", {
|
|
1274
|
+
detail: {
|
|
1275
|
+
key: e,
|
|
1276
|
+
hidden: t
|
|
1277
|
+
},
|
|
1278
|
+
bubbles: !0,
|
|
1279
|
+
composed: !0
|
|
1280
|
+
})));
|
|
1281
|
+
}
|
|
1282
|
+
getHiddenColumns() {
|
|
1283
|
+
return this.columns.filter((e) => e.hidden);
|
|
1284
|
+
}
|
|
1152
1285
|
addRow(e, t) {
|
|
1153
1286
|
if (this.maxRows > 0 && this.data.length >= this.maxRows) return null;
|
|
1154
1287
|
let n = e ?? this._createEmptyRow(), r = t ?? this.data.length;
|
|
@@ -1251,12 +1384,12 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1251
1384
|
if (!t) return "";
|
|
1252
1385
|
let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
|
|
1253
1386
|
for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
|
|
1254
|
-
return
|
|
1387
|
+
return j(r, n, e);
|
|
1255
1388
|
}
|
|
1256
|
-
return
|
|
1389
|
+
return j(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
|
|
1257
1390
|
}
|
|
1258
1391
|
exportToFile(e, t) {
|
|
1259
|
-
|
|
1392
|
+
I(this.exportToString(e), t ?? `export${B(e)}`, z(e));
|
|
1260
1393
|
}
|
|
1261
1394
|
_getSelectedDataRows() {
|
|
1262
1395
|
let e = this._selection.getEffectiveRange();
|
|
@@ -1269,8 +1402,8 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1269
1402
|
return this._columnWidths.get(e);
|
|
1270
1403
|
}
|
|
1271
1404
|
_getColWidth(e) {
|
|
1272
|
-
let t = this._columnWidths.get(e.key) ?? e.width ??
|
|
1273
|
-
return Math.max(t, e.minWidth ??
|
|
1405
|
+
let t = this._columnWidths.get(e.key) ?? e.width ?? H;
|
|
1406
|
+
return Math.max(t, e.minWidth ?? U);
|
|
1274
1407
|
}
|
|
1275
1408
|
get headerHeight() {
|
|
1276
1409
|
return this.rowHeight + 8;
|
|
@@ -1282,10 +1415,10 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1282
1415
|
return this._visibleRowCount * this.rowHeight;
|
|
1283
1416
|
}
|
|
1284
1417
|
get visibleRange() {
|
|
1285
|
-
let e = Math.max(0, this._scrollTop - this.headerHeight), t = Math.max(0, Math.floor(e / this.rowHeight) -
|
|
1418
|
+
let e = Math.max(0, this._scrollTop - this.headerHeight), t = Math.max(0, Math.floor(e / this.rowHeight) - G), n = Math.ceil(this._viewportHeight / this.rowHeight);
|
|
1286
1419
|
return {
|
|
1287
1420
|
start: t,
|
|
1288
|
-
end: Math.min(this._visibleRowCount, Math.floor(e / this.rowHeight) + n +
|
|
1421
|
+
end: Math.min(this._visibleRowCount, Math.floor(e / this.rowHeight) + n + G)
|
|
1289
1422
|
};
|
|
1290
1423
|
}
|
|
1291
1424
|
connectedCallback() {
|
|
@@ -1318,13 +1451,13 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1318
1451
|
i = r;
|
|
1319
1452
|
break;
|
|
1320
1453
|
}
|
|
1321
|
-
i = Math.max(0, i -
|
|
1454
|
+
i = Math.max(0, i - G);
|
|
1322
1455
|
let a = e.length;
|
|
1323
1456
|
for (let e = i; e < t.length; e++) if (t[e] > r) {
|
|
1324
1457
|
a = e;
|
|
1325
1458
|
break;
|
|
1326
1459
|
}
|
|
1327
|
-
return a = Math.min(e.length, a +
|
|
1460
|
+
return a = Math.min(e.length, a + G), {
|
|
1328
1461
|
start: i,
|
|
1329
1462
|
end: a
|
|
1330
1463
|
};
|
|
@@ -1340,7 +1473,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1340
1473
|
this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
|
|
1341
1474
|
return;
|
|
1342
1475
|
}
|
|
1343
|
-
if (this._filteredIndices =
|
|
1476
|
+
if (this._filteredIndices = T(this.data, this._filters, (e, t, n) => {
|
|
1344
1477
|
this.dispatchEvent(new CustomEvent("filter-error", {
|
|
1345
1478
|
detail: {
|
|
1346
1479
|
error: e,
|
|
@@ -1353,7 +1486,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1353
1486
|
}), this._filters.length === 0 && this._sortCriteria.length === 0) this._sortedIndices = Array.from({ length: this.data.length }, (e, t) => t);
|
|
1354
1487
|
else if (this._sortCriteria.length === 0) this._sortedIndices = [...this._filteredIndices];
|
|
1355
1488
|
else {
|
|
1356
|
-
let e =
|
|
1489
|
+
let e = S(this._filteredIndices.map((e) => this.data[e]), this._sortCriteria, this.visibleColumns);
|
|
1357
1490
|
this._sortedIndices = e.map((e) => this._filteredIndices[e]);
|
|
1358
1491
|
}
|
|
1359
1492
|
}
|
|
@@ -1373,7 +1506,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1373
1506
|
this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
|
|
1374
1507
|
}
|
|
1375
1508
|
_onDocumentClick() {
|
|
1376
|
-
this._openFilterKey &&= null;
|
|
1509
|
+
this._openFilterKey &&= null, this._headerMenu &&= null;
|
|
1377
1510
|
}
|
|
1378
1511
|
_onContextMenu(e) {
|
|
1379
1512
|
let t = e.composedPath().find((e) => e instanceof HTMLElement && e.classList.contains("ft-cell"));
|
|
@@ -1467,14 +1600,30 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1467
1600
|
}
|
|
1468
1601
|
let t = this.shadowRoot?.querySelector(".ft-editor");
|
|
1469
1602
|
if (t) {
|
|
1470
|
-
let n =
|
|
1603
|
+
let n = A(t.value, e);
|
|
1471
1604
|
this._applyEdit(n);
|
|
1472
1605
|
} else this._cancelEdit();
|
|
1473
1606
|
}
|
|
1474
1607
|
_applyEdit(e) {
|
|
1608
|
+
this._autocompleteState = null;
|
|
1475
1609
|
let t = this._editing.commit();
|
|
1476
1610
|
if (this._editingCell = null, !t) return;
|
|
1477
1611
|
let { row: n, col: r } = t.position, i = this._toDataIndex(n), a = this.visibleColumns[r], o = t.originalValue;
|
|
1612
|
+
if (a.autocomplete === "strict" && e != null && e !== "" && !this._getAutocompleteCandidates(a, "").includes(String(e))) {
|
|
1613
|
+
let t = "Value must be from the existing list";
|
|
1614
|
+
this._markCellInvalid(n, r, t), this.dispatchEvent(new CustomEvent("validation-error", {
|
|
1615
|
+
detail: {
|
|
1616
|
+
row: i,
|
|
1617
|
+
col: r,
|
|
1618
|
+
key: a.key,
|
|
1619
|
+
value: e,
|
|
1620
|
+
error: t
|
|
1621
|
+
},
|
|
1622
|
+
bubbles: !0,
|
|
1623
|
+
composed: !0
|
|
1624
|
+
}));
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1478
1627
|
if (a.validator) {
|
|
1479
1628
|
let t = a.validator(e, this.data[i], a);
|
|
1480
1629
|
if (t) {
|
|
@@ -1513,6 +1662,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1513
1662
|
})), this._dispatchUndoStateEvent();
|
|
1514
1663
|
}
|
|
1515
1664
|
_cancelEdit() {
|
|
1665
|
+
this._autocompleteState = null;
|
|
1516
1666
|
let e = this._editing.cancel();
|
|
1517
1667
|
this._editingCell = null, e && this.dispatchEvent(new CustomEvent("cell-edit-cancel", {
|
|
1518
1668
|
detail: {
|
|
@@ -1524,8 +1674,56 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1524
1674
|
}));
|
|
1525
1675
|
}
|
|
1526
1676
|
_onEditorKeyDown(e) {
|
|
1677
|
+
if (this._autocompleteState && this._autocompleteState.candidates.length > 0) {
|
|
1678
|
+
if (e.key === "ArrowDown") {
|
|
1679
|
+
e.preventDefault(), e.stopPropagation();
|
|
1680
|
+
let t = this._autocompleteState.candidates.length;
|
|
1681
|
+
this._autocompleteState = {
|
|
1682
|
+
...this._autocompleteState,
|
|
1683
|
+
activeIndex: Math.min(this._autocompleteState.activeIndex + 1, t - 1)
|
|
1684
|
+
};
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
if (e.key === "ArrowUp") {
|
|
1688
|
+
e.preventDefault(), e.stopPropagation(), this._autocompleteState = {
|
|
1689
|
+
...this._autocompleteState,
|
|
1690
|
+
activeIndex: Math.max(this._autocompleteState.activeIndex - 1, -1)
|
|
1691
|
+
};
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
if (e.key === "Enter" && this._autocompleteState.activeIndex >= 0) {
|
|
1695
|
+
e.preventDefault(), e.stopPropagation();
|
|
1696
|
+
let t = this._autocompleteState.candidates[this._autocompleteState.activeIndex];
|
|
1697
|
+
this._selectAutocompleteCandidate(t);
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
if (e.key === "Escape") {
|
|
1701
|
+
e.preventDefault(), e.stopPropagation(), this._autocompleteState = null;
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1527
1705
|
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
1706
|
}
|
|
1707
|
+
_getAutocompleteCandidates(e, t) {
|
|
1708
|
+
let n = t.toLowerCase(), r = /* @__PURE__ */ new Set(), i = [];
|
|
1709
|
+
for (let a of this.data) {
|
|
1710
|
+
let o = a[e.key];
|
|
1711
|
+
if (o == null) continue;
|
|
1712
|
+
let s = String(o);
|
|
1713
|
+
if (!r.has(s) && (t === "" || s.toLowerCase().includes(n)) && (r.add(s), i.push(s), i.length >= 20)) break;
|
|
1714
|
+
}
|
|
1715
|
+
return i;
|
|
1716
|
+
}
|
|
1717
|
+
_onAutocompleteInput(e, t) {
|
|
1718
|
+
let n = e.target.value, r = this._getAutocompleteCandidates(t, n).filter((e) => e !== n);
|
|
1719
|
+
this._autocompleteState = r.length > 0 ? {
|
|
1720
|
+
candidates: r,
|
|
1721
|
+
activeIndex: -1
|
|
1722
|
+
} : null;
|
|
1723
|
+
}
|
|
1724
|
+
_selectAutocompleteCandidate(e) {
|
|
1725
|
+
this._autocompleteState = null, this._applyEdit(e), this._selection.moveDown(), this._syncActiveCell();
|
|
1726
|
+
}
|
|
1529
1727
|
_syncActiveCell() {
|
|
1530
1728
|
this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._scrollToActiveCell(), this._dispatchSelectionEvent();
|
|
1531
1729
|
}
|
|
@@ -1595,7 +1793,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1595
1793
|
e.preventDefault();
|
|
1596
1794
|
let n = t[this._activeCell.col];
|
|
1597
1795
|
if (!n) return !0;
|
|
1598
|
-
let r = this._columnWidths.get(n.key) ?? n.width ??
|
|
1796
|
+
let r = this._columnWidths.get(n.key) ?? n.width ?? H, i = e.key === "ArrowRight" ? 20 : -20, a = n.minWidth ?? U, o = Math.max(a, r + i);
|
|
1599
1797
|
return this._columnWidths.set(n.key, o), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
|
|
1600
1798
|
detail: {
|
|
1601
1799
|
key: n.key,
|
|
@@ -1624,7 +1822,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1624
1822
|
async _handleCopy(e) {
|
|
1625
1823
|
let t = this._selection.getEffectiveRange();
|
|
1626
1824
|
if (!t) return;
|
|
1627
|
-
let n = this.visibleColumns, r =
|
|
1825
|
+
let n = this.visibleColumns, r = O(this._sortedIndices.map((e) => this.data[e]), n, t);
|
|
1628
1826
|
try {
|
|
1629
1827
|
await navigator.clipboard.writeText(r);
|
|
1630
1828
|
} catch (e) {
|
|
@@ -1650,7 +1848,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1650
1848
|
if (!this._activeCell) return;
|
|
1651
1849
|
let e = await this._readClipboardText();
|
|
1652
1850
|
if (e == null) return;
|
|
1653
|
-
let t =
|
|
1851
|
+
let t = k(e);
|
|
1654
1852
|
if (t.length === 0) return;
|
|
1655
1853
|
let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
|
|
1656
1854
|
if (r.length > 0 || n.length > 0) {
|
|
@@ -1708,7 +1906,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1708
1906
|
for (let a = 0; a < t[i].length; a++) {
|
|
1709
1907
|
let s = e.col + a;
|
|
1710
1908
|
if (s >= n.length) break;
|
|
1711
|
-
let c = n[s], l = this.data[o][c.key], u =
|
|
1909
|
+
let c = n[s], l = this.data[o][c.key], u = A(t[i][a], c);
|
|
1712
1910
|
this.data[o][c.key] = u, r.push({
|
|
1713
1911
|
row: o,
|
|
1714
1912
|
col: s,
|
|
@@ -1773,7 +1971,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1773
1971
|
for (let r = e.startCol + 1; r <= e.endCol; r++) {
|
|
1774
1972
|
let e = t[r];
|
|
1775
1973
|
if (!e || !this._isCellEditable(e)) continue;
|
|
1776
|
-
let a =
|
|
1974
|
+
let a = A(o == null ? "" : String(o), e);
|
|
1777
1975
|
n.push({
|
|
1778
1976
|
row: i,
|
|
1779
1977
|
key: e.key,
|
|
@@ -1864,7 +2062,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1864
2062
|
this._selectColumn(n);
|
|
1865
2063
|
return;
|
|
1866
2064
|
}
|
|
1867
|
-
t.sortable !== !1 && (this._sortCriteria =
|
|
2065
|
+
t.sortable !== !1 && (this._sortCriteria = w(this._sortCriteria, t.key, e.shiftKey), this.dataMode !== "server" && this._recomputeView(), this.requestUpdate(), this.dispatchEvent(new CustomEvent("sort-change", {
|
|
1868
2066
|
detail: { criteria: [...this._sortCriteria] },
|
|
1869
2067
|
bubbles: !0,
|
|
1870
2068
|
composed: !0
|
|
@@ -1906,15 +2104,25 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1906
2104
|
c || l ? "ft-pinned" : ""
|
|
1907
2105
|
].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
2106
|
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;
|
|
2107
|
+
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 = [];
|
|
2108
|
+
if (y > 0) for (let e = y - 1; e >= 0 && v[e].hidden; e--) b.push(v[e]);
|
|
2109
|
+
let x = b.length > 0;
|
|
1910
2110
|
return n`
|
|
1911
|
-
<div class=${
|
|
2111
|
+
<div class=${_}
|
|
1912
2112
|
role="columnheader"
|
|
1913
2113
|
data-col-index=${t}
|
|
1914
2114
|
style=${h}
|
|
1915
2115
|
aria-sort=${d ?? r}
|
|
2116
|
+
@contextmenu=${(t) => this._onHeaderContextMenu(t, e)}
|
|
1916
2117
|
@mousedown=${(n) => this._onHeaderMouseDown(n, e, t)}
|
|
1917
2118
|
@click=${i ? (t) => this._onHeaderClick(t, e) : void 0}>
|
|
2119
|
+
${x ? n`
|
|
2120
|
+
<button class="ft-hidden-col-indicator"
|
|
2121
|
+
title="Show hidden column(s)"
|
|
2122
|
+
@click=${(t) => {
|
|
2123
|
+
t.stopPropagation(), this._showHiddenBefore(e);
|
|
2124
|
+
}}>❯</button>
|
|
2125
|
+
` : ""}
|
|
1918
2126
|
<span>${e.header}</span>
|
|
1919
2127
|
${a ? n`<span class="ft-sort-indicator">${a.direction === "asc" ? "▲" : "▼"}</span>` : ""}
|
|
1920
2128
|
${o >= 0 ? n`<span class="ft-sort-order">${o + 1}</span>` : ""}
|
|
@@ -1935,6 +2143,56 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
1935
2143
|
</div>
|
|
1936
2144
|
${this._openFilterKey === e.key ? this._renderFilterDropdown(e) : ""}
|
|
1937
2145
|
`;
|
|
2146
|
+
}
|
|
2147
|
+
_onHeaderContextMenu(e, t) {
|
|
2148
|
+
e.preventDefault();
|
|
2149
|
+
let n = this.columns, r = n.findIndex((e) => e.key === t.key), i = [];
|
|
2150
|
+
for (let e = r - 1; e >= 0 && n[e].hidden; e--) i.push(n[e]);
|
|
2151
|
+
for (let e = r + 1; e < n.length && n[e].hidden; e++) i.push(n[e]);
|
|
2152
|
+
this._headerMenu = {
|
|
2153
|
+
key: t.key,
|
|
2154
|
+
x: e.clientX,
|
|
2155
|
+
y: e.clientY,
|
|
2156
|
+
hiddenNeighbors: i
|
|
2157
|
+
}, this.dispatchEvent(new CustomEvent("header-context-menu", {
|
|
2158
|
+
detail: {
|
|
2159
|
+
key: t.key,
|
|
2160
|
+
header: t.header,
|
|
2161
|
+
x: e.clientX,
|
|
2162
|
+
y: e.clientY
|
|
2163
|
+
},
|
|
2164
|
+
bubbles: !0,
|
|
2165
|
+
composed: !0
|
|
2166
|
+
})), requestAnimationFrame(() => {
|
|
2167
|
+
document.addEventListener("click", this._onDocumentClick, { once: !0 });
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
_showHiddenBefore(e) {
|
|
2171
|
+
let t = this.columns, n = t.findIndex((t) => t.key === e.key);
|
|
2172
|
+
for (let e = n - 1; e >= 0 && t[e].hidden; e--) this._setColumnHidden(t[e].key, !1);
|
|
2173
|
+
}
|
|
2174
|
+
_renderHeaderContextMenu() {
|
|
2175
|
+
if (!this._headerMenu) return r;
|
|
2176
|
+
let { key: e, x: t, y: i, hiddenNeighbors: a } = this._headerMenu;
|
|
2177
|
+
return this.columns.find((t) => t.key === e) ? n`
|
|
2178
|
+
<div class="ft-header-menu" style="position: fixed; left: ${t}px; top: ${i}px; z-index: 200;"
|
|
2179
|
+
@mousedown=${(e) => e.stopPropagation()}>
|
|
2180
|
+
<div class="ft-header-menu-item"
|
|
2181
|
+
@click=${() => {
|
|
2182
|
+
this._setColumnHidden(e, !0), this._headerMenu = null;
|
|
2183
|
+
}}>
|
|
2184
|
+
Hide column
|
|
2185
|
+
</div>
|
|
2186
|
+
${a.map((e) => n`
|
|
2187
|
+
<div class="ft-header-menu-item"
|
|
2188
|
+
@click=${() => {
|
|
2189
|
+
this._setColumnHidden(e.key, !1), this._headerMenu = null;
|
|
2190
|
+
}}>
|
|
2191
|
+
Show: ${e.header}
|
|
2192
|
+
</div>
|
|
2193
|
+
`)}
|
|
2194
|
+
</div>
|
|
2195
|
+
` : r;
|
|
1938
2196
|
}
|
|
1939
2197
|
_adjustFilterDropdown() {
|
|
1940
2198
|
if (!this._openFilterKey) return;
|
|
@@ -2076,7 +2334,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2076
2334
|
if (!n) return;
|
|
2077
2335
|
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
2336
|
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 ??
|
|
2337
|
+
let o = n.minWidth ?? U, s = Math.max(o, i + 8);
|
|
2080
2338
|
this._columnWidths.set(n.key, s), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
|
|
2081
2339
|
detail: {
|
|
2082
2340
|
key: n.key,
|
|
@@ -2089,7 +2347,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2089
2347
|
}
|
|
2090
2348
|
_onResizeStart(e, t) {
|
|
2091
2349
|
e.preventDefault(), e.stopPropagation();
|
|
2092
|
-
let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ??
|
|
2350
|
+
let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? H;
|
|
2093
2351
|
this._resizing = {
|
|
2094
2352
|
colIndex: t,
|
|
2095
2353
|
startX: e.clientX,
|
|
@@ -2097,13 +2355,13 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2097
2355
|
};
|
|
2098
2356
|
let i = (e) => {
|
|
2099
2357
|
if (!this._resizing) return;
|
|
2100
|
-
let t = e.clientX - this._resizing.startX, r = n.minWidth ??
|
|
2358
|
+
let t = e.clientX - this._resizing.startX, r = n.minWidth ?? U, i = Math.max(r, this._resizing.startWidth + t);
|
|
2101
2359
|
this._columnWidths.set(n.key, i), this.requestUpdate();
|
|
2102
2360
|
}, a = () => {
|
|
2103
2361
|
document.removeEventListener("mousemove", i), document.removeEventListener("mouseup", o), this._resizeCleanup = null;
|
|
2104
2362
|
}, o = () => {
|
|
2105
2363
|
if (a(), this._resizing) {
|
|
2106
|
-
let e = this._columnWidths.get(n.key) ??
|
|
2364
|
+
let e = this._columnWidths.get(n.key) ?? H;
|
|
2107
2365
|
this.dispatchEvent(new CustomEvent("column-resize", {
|
|
2108
2366
|
detail: {
|
|
2109
2367
|
key: n.key,
|
|
@@ -2553,6 +2811,7 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2553
2811
|
${this.footerData ? this._renderFooter(i, a, o) : ""}
|
|
2554
2812
|
${_}
|
|
2555
2813
|
${g}
|
|
2814
|
+
${this._renderHeaderContextMenu()}
|
|
2556
2815
|
`;
|
|
2557
2816
|
}
|
|
2558
2817
|
_onSelectAllChange(e) {
|
|
@@ -2616,11 +2875,17 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2616
2875
|
`;
|
|
2617
2876
|
}
|
|
2618
2877
|
_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,
|
|
2620
|
-
g =
|
|
2878
|
+
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;
|
|
2879
|
+
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
2880
|
let _ = !this._isCellEditable(t);
|
|
2881
|
+
if (t.conditionalRules && t.conditionalRules.length > 0) {
|
|
2882
|
+
let n = e[t.key], r = {};
|
|
2883
|
+
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));
|
|
2884
|
+
let i = Object.entries(r).map(([e, t]) => `${e}: ${t}`).join("; ");
|
|
2885
|
+
i && (g += " " + i + ";");
|
|
2886
|
+
}
|
|
2622
2887
|
if (s) return n`
|
|
2623
|
-
<div class="ft-cell ft-editing ft-active ${
|
|
2888
|
+
<div class="ft-cell ft-editing ft-active ${d ? "ft-pinned" : ""}" role="gridcell"
|
|
2624
2889
|
data-col-index=${a}
|
|
2625
2890
|
aria-selected="true"
|
|
2626
2891
|
aria-readonly=${_ ? "true" : r}
|
|
@@ -2628,14 +2893,14 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2628
2893
|
${this._renderEditor(e, t)}
|
|
2629
2894
|
</div>
|
|
2630
2895
|
`;
|
|
2631
|
-
let v = o ||
|
|
2896
|
+
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
2897
|
return n`
|
|
2633
2898
|
<div class=${[
|
|
2634
2899
|
"ft-cell",
|
|
2635
2900
|
`ft-type-${t.type ?? "text"}`,
|
|
2636
2901
|
o ? "ft-active" : "",
|
|
2637
|
-
|
|
2638
|
-
|
|
2902
|
+
c ? "ft-selected" : "",
|
|
2903
|
+
d ? "ft-pinned" : "",
|
|
2639
2904
|
y ? "ft-invalid" : "",
|
|
2640
2905
|
S ? "ft-find-current" : x ? "ft-find-match" : ""
|
|
2641
2906
|
].filter(Boolean).join(" ")}
|
|
@@ -2650,45 +2915,67 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2650
2915
|
@mouseenter=${() => this._onCellMouseEnter(i, a)}
|
|
2651
2916
|
@click=${(e) => this._onCellClickEvent(e, i, a)}
|
|
2652
2917
|
@dblclick=${() => this._onCellDblClick(i, a)}>
|
|
2653
|
-
${
|
|
2918
|
+
${f(e[t.key], e, t)}
|
|
2654
2919
|
</div>
|
|
2655
2920
|
`;
|
|
2656
2921
|
}
|
|
2657
2922
|
_renderEditor(e, t) {
|
|
2658
2923
|
if (t.editor) return t.editor(e[t.key], e, t);
|
|
2659
|
-
let
|
|
2924
|
+
let i = e[t.key], a = i == null ? "" : String(i);
|
|
2660
2925
|
if (t.type === "number") return n`
|
|
2661
2926
|
<input class="ft-editor ft-editor-number" type="number"
|
|
2662
|
-
.value=${
|
|
2927
|
+
.value=${a}
|
|
2663
2928
|
@keydown=${this._onEditorKeyDown}
|
|
2664
2929
|
@blur=${() => this._commitEdit()}>
|
|
2665
2930
|
`;
|
|
2666
2931
|
if (t.type === "date") return n`
|
|
2667
2932
|
<input class="ft-editor" type="date"
|
|
2668
|
-
.value=${this._toDateInputValue(
|
|
2933
|
+
.value=${this._toDateInputValue(i)}
|
|
2669
2934
|
@keydown=${this._onEditorKeyDown}
|
|
2670
2935
|
@blur=${() => this._commitEdit()}>
|
|
2671
2936
|
`;
|
|
2672
2937
|
if (t.type === "datetime") return n`
|
|
2673
2938
|
<input class="ft-editor" type="datetime-local"
|
|
2674
|
-
.value=${this._toDateTimeInputValue(
|
|
2939
|
+
.value=${this._toDateTimeInputValue(i)}
|
|
2675
2940
|
@keydown=${this._onEditorKeyDown}
|
|
2676
2941
|
@blur=${() => this._commitEdit()}>
|
|
2677
2942
|
`;
|
|
2678
2943
|
if (t.type === "select" && t.options && t.options.length > 0) {
|
|
2679
|
-
let e = t.options,
|
|
2944
|
+
let e = t.options, r = typeof e[0] == "string";
|
|
2680
2945
|
return n`
|
|
2681
2946
|
<select class="ft-editor"
|
|
2682
2947
|
@keydown=${this._onEditorKeyDown}
|
|
2683
2948
|
@blur=${() => this._commitEdit()}
|
|
2684
2949
|
@change=${() => this._commitEdit()}>
|
|
2685
|
-
${
|
|
2950
|
+
${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
2951
|
</select>
|
|
2952
|
+
`;
|
|
2953
|
+
}
|
|
2954
|
+
if (t.autocomplete) {
|
|
2955
|
+
let e = this._autocompleteState?.candidates ?? [], i = this._autocompleteState?.activeIndex ?? -1;
|
|
2956
|
+
return n`
|
|
2957
|
+
<input class="ft-editor" type="text"
|
|
2958
|
+
.value=${a}
|
|
2959
|
+
@input=${(e) => this._onAutocompleteInput(e, t)}
|
|
2960
|
+
@keydown=${this._onEditorKeyDown}
|
|
2961
|
+
@blur=${() => this._commitEdit()}>
|
|
2962
|
+
${e.length > 0 ? n`
|
|
2963
|
+
<div class="ft-autocomplete-dropdown">
|
|
2964
|
+
${e.map((e, t) => n`
|
|
2965
|
+
<div class="ft-autocomplete-item ${t === i ? "ft-autocomplete-active" : ""}"
|
|
2966
|
+
@mousedown=${(t) => {
|
|
2967
|
+
t.preventDefault(), this._selectAutocompleteCandidate(e);
|
|
2968
|
+
}}>
|
|
2969
|
+
${e}
|
|
2970
|
+
</div>
|
|
2971
|
+
`)}
|
|
2972
|
+
</div>
|
|
2973
|
+
` : r}
|
|
2687
2974
|
`;
|
|
2688
2975
|
}
|
|
2689
2976
|
return n`
|
|
2690
2977
|
<input class="ft-editor" type="text"
|
|
2691
|
-
.value=${
|
|
2978
|
+
.value=${a}
|
|
2692
2979
|
@keydown=${this._onEditorKeyDown}
|
|
2693
2980
|
@blur=${() => this._commitEdit()}>
|
|
2694
2981
|
`;
|
|
@@ -2704,36 +2991,36 @@ var R = 120, z = 40, B = 32, V = 5, H = class extends e {
|
|
|
2704
2991
|
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
2992
|
}
|
|
2706
2993
|
};
|
|
2707
|
-
|
|
2994
|
+
V([a({ type: Array })], K.prototype, "columns", void 0), V([a({
|
|
2708
2995
|
type: Array,
|
|
2709
2996
|
hasChanged: () => !0
|
|
2710
|
-
})],
|
|
2997
|
+
})], K.prototype, "data", void 0), V([a({
|
|
2711
2998
|
type: Number,
|
|
2712
2999
|
attribute: "row-height"
|
|
2713
|
-
})],
|
|
3000
|
+
})], K.prototype, "rowHeight", void 0), V([a({
|
|
2714
3001
|
type: Boolean,
|
|
2715
3002
|
attribute: "show-row-numbers"
|
|
2716
|
-
})],
|
|
3003
|
+
})], K.prototype, "showRowNumbers", void 0), V([a({
|
|
2717
3004
|
type: String,
|
|
2718
3005
|
reflect: !0
|
|
2719
|
-
})],
|
|
3006
|
+
})], K.prototype, "theme", void 0), V([a({
|
|
2720
3007
|
type: Number,
|
|
2721
3008
|
attribute: "max-rows"
|
|
2722
|
-
})],
|
|
3009
|
+
})], K.prototype, "maxRows", void 0), V([a({ type: Boolean })], K.prototype, "editable", void 0), V([a({
|
|
2723
3010
|
type: Boolean,
|
|
2724
3011
|
attribute: "show-filters"
|
|
2725
|
-
})],
|
|
3012
|
+
})], K.prototype, "showFilters", void 0), V([a({ type: Boolean })], K.prototype, "selectable", void 0), V([a({
|
|
2726
3013
|
type: String,
|
|
2727
3014
|
attribute: "selection-mode"
|
|
2728
|
-
})],
|
|
3015
|
+
})], K.prototype, "selectionMode", null), V([a({
|
|
2729
3016
|
type: String,
|
|
2730
3017
|
attribute: "data-mode"
|
|
2731
|
-
})],
|
|
3018
|
+
})], K.prototype, "dataMode", void 0), V([a({
|
|
2732
3019
|
type: Object,
|
|
2733
3020
|
attribute: "footer-data"
|
|
2734
|
-
})],
|
|
3021
|
+
})], K.prototype, "footerData", void 0), V([a({
|
|
2735
3022
|
type: Number,
|
|
2736
3023
|
attribute: "max-undo-size"
|
|
2737
|
-
})],
|
|
3024
|
+
})], K.prototype, "maxUndoSize", null), V([o()], K.prototype, "_scrollTop", void 0), V([o()], K.prototype, "_scrollLeft", void 0), V([o()], K.prototype, "_viewportHeight", void 0), V([o()], K.prototype, "_viewportWidth", void 0), V([o()], K.prototype, "_activeCell", void 0), V([o()], K.prototype, "_editingCell", void 0), V([o()], K.prototype, "_sortCriteria", void 0), V([o()], K.prototype, "_openFilterKey", void 0), V([o()], K.prototype, "_rowSelectionVersion", void 0), V([o()], K.prototype, "_autocompleteState", void 0), V([o()], K.prototype, "_headerMenu", void 0), K = V([i("flex-table")], K);
|
|
2738
3025
|
//#endregion
|
|
2739
|
-
export {
|
|
3026
|
+
export { f as a, x as i, j as n, D as r, K as t };
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ export declare class FlexTable extends LitElement {
|
|
|
44
44
|
private _sortedIndices;
|
|
45
45
|
private _openFilterKey;
|
|
46
46
|
private _rowSelectionVersion;
|
|
47
|
+
private _autocompleteState;
|
|
48
|
+
private _headerMenu;
|
|
47
49
|
private _viewDirty;
|
|
48
50
|
private _isDragging;
|
|
49
51
|
private _wasDrag;
|
|
@@ -117,6 +119,13 @@ export declare class FlexTable extends LitElement {
|
|
|
117
119
|
* @param newIndex Target index in the columns array.
|
|
118
120
|
*/
|
|
119
121
|
moveColumn(key: string, newIndex: number): void;
|
|
122
|
+
/** Hide a column by its key. Fires `column-visibility-change` event. */
|
|
123
|
+
hideColumn(key: string): void;
|
|
124
|
+
/** Show a previously hidden column by its key. Fires `column-visibility-change` event. */
|
|
125
|
+
showColumn(key: string): void;
|
|
126
|
+
private _setColumnHidden;
|
|
127
|
+
/** Returns all columns marked as hidden. */
|
|
128
|
+
getHiddenColumns(): ColumnDefinition[];
|
|
120
129
|
/**
|
|
121
130
|
* Add a row at the specified index (default: end).
|
|
122
131
|
* Returns the new row.
|
|
@@ -187,6 +196,9 @@ export declare class FlexTable extends LitElement {
|
|
|
187
196
|
private _applyEdit;
|
|
188
197
|
private _cancelEdit;
|
|
189
198
|
private _onEditorKeyDown;
|
|
199
|
+
private _getAutocompleteCandidates;
|
|
200
|
+
private _onAutocompleteInput;
|
|
201
|
+
private _selectAutocompleteCandidate;
|
|
190
202
|
private _syncActiveCell;
|
|
191
203
|
private _onKeyDown;
|
|
192
204
|
private _handleCtrlKey;
|
|
@@ -213,6 +225,9 @@ export declare class FlexTable extends LitElement {
|
|
|
213
225
|
/** Calculate cumulative right offset for a right-pinned column */
|
|
214
226
|
private _getPinnedRight;
|
|
215
227
|
private _renderHeaderCell;
|
|
228
|
+
private _onHeaderContextMenu;
|
|
229
|
+
private _showHiddenBefore;
|
|
230
|
+
private _renderHeaderContextMenu;
|
|
216
231
|
private _adjustFilterDropdown;
|
|
217
232
|
private _onFilterBtnClick;
|
|
218
233
|
private _renderFilterDropdown;
|
package/dist/flex-table.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, r, t as i } from "./flex-table-
|
|
1
|
+
import { a as e, i as t, n, r, t as i } from "./flex-table-zJST_6sy.js";
|
|
2
2
|
export { i as FlexTable, t as RowSelectionState, r as UndoStack, n as exportData, e as renderCell };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { FlexTable } from './flex-table.js';
|
|
2
|
-
export type { ColumnDefinition, ColumnType, DataRow, CellRenderer, CellEditor, CellValidator, SelectionMode, DataMode } from './models/types.js';
|
|
2
|
+
export type { ColumnDefinition, ColumnType, DataRow, CellRenderer, CellEditor, CellValidator, SelectionMode, DataMode, CellStyle, ConditionalRule } from './models/types.js';
|
|
3
3
|
export type { CellPosition, CellRange } from './core/selection.js';
|
|
4
4
|
export type { SortCriteria, SortDirection } from './core/sorting.js';
|
|
5
5
|
export type { ColumnFilter, FilterPredicate, FilterErrorCallback } from './core/filtering.js';
|
package/dist/models/types.d.ts
CHANGED
|
@@ -65,6 +65,33 @@ export interface ColumnDefinition {
|
|
|
65
65
|
validator?: CellValidator;
|
|
66
66
|
/** Allowed values for select columns (strings or label/value pairs) */
|
|
67
67
|
options?: string[] | SelectOption[];
|
|
68
|
+
/**
|
|
69
|
+
* Autocomplete for text editing.
|
|
70
|
+
* - true: show suggestions from existing column values
|
|
71
|
+
* - 'strict': same as true, but rejects values not in the list
|
|
72
|
+
*/
|
|
73
|
+
autocomplete?: boolean | 'strict';
|
|
74
|
+
/**
|
|
75
|
+
* Display format for cell values. Applied during rendering; raw value is preserved.
|
|
76
|
+
* - String: number format pattern (e.g. '#,##0.00', '0.00%', '$#,##0') or date pattern (e.g. 'yyyy-MM-dd')
|
|
77
|
+
* - Function: custom formatter receiving (value, row, col)
|
|
78
|
+
*/
|
|
79
|
+
format?: string | ((value: unknown, row: DataRow, col: ColumnDefinition) => string);
|
|
80
|
+
/** Per-column conditional formatting rules applied during cell rendering */
|
|
81
|
+
conditionalRules?: ConditionalRule[];
|
|
82
|
+
}
|
|
83
|
+
/** Style applied to a cell by a conditional formatting rule */
|
|
84
|
+
export interface CellStyle {
|
|
85
|
+
background?: string;
|
|
86
|
+
color?: string;
|
|
87
|
+
fontWeight?: 'bold' | 'normal';
|
|
88
|
+
fontStyle?: 'italic' | 'normal';
|
|
89
|
+
}
|
|
90
|
+
/** A single conditional formatting rule */
|
|
91
|
+
export interface ConditionalRule {
|
|
92
|
+
/** Returns true when this rule's style should be applied */
|
|
93
|
+
when: (value: unknown, row: DataRow, col: ColumnDefinition) => boolean;
|
|
94
|
+
style: CellStyle;
|
|
68
95
|
}
|
|
69
96
|
/**
|
|
70
97
|
* A single data row — schema-agnostic key-value map.
|
package/dist/react.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cell value formatting: number and date patterns.
|
|
3
|
+
* Patterns follow Excel-like conventions.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Apply a format string or function to a cell value.
|
|
7
|
+
* Returns empty string for null/undefined.
|
|
8
|
+
*/
|
|
9
|
+
export declare function applyFormat(value: unknown, format: string | ((value: unknown) => string)): string;
|
|
10
|
+
/**
|
|
11
|
+
* Parse an Excel-style number format string and apply it.
|
|
12
|
+
* Supported patterns: '#,##0', '#,##0.00', '0.00%', '$#,##0.00', '#,##0.00%'
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatNumberValue(value: unknown, fmt: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Format a Date or ISO string value using a pattern.
|
|
17
|
+
* Tokens: yyyy, yy, MM, dd, HH, hh, mm, ss
|
|
18
|
+
*/
|
|
19
|
+
export declare function formatDateValue(value: unknown, fmt: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|