@iyulab/flex-table 0.13.0 → 0.15.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.
@@ -1,12 +1,13 @@
1
1
  import type { ColumnDefinition, DataRow } from '../models/types.js';
2
- export type ExportFormat = 'csv' | 'tsv' | 'json';
2
+ export type ExportFormat = 'csv' | 'tsv' | 'json' | 'xlsx';
3
3
  /**
4
4
  * Export data to the specified format.
5
+ * Returns string for text formats (csv/tsv/json) or Uint8Array for xlsx.
5
6
  */
6
- export declare function exportData(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat): string;
7
+ export declare function exportData(data: DataRow[], columns: ColumnDefinition[], format: ExportFormat): string | Uint8Array;
7
8
  /**
8
9
  * Trigger a file download in the browser.
9
10
  */
10
- export declare function downloadFile(content: string, filename: string, mimeType: string): void;
11
+ export declare function downloadFile(content: string | Uint8Array, filename: string, mimeType: string): void;
11
12
  export declare function getExportMimeType(format: ExportFormat): string;
12
13
  export declare function getExportExtension(format: ExportFormat): string;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Minimal XLSX writer — no external dependencies.
3
+ * Generates OOXML (.xlsx) files using ZIP STORE method (no compression).
4
+ * Supports string, number, boolean, and date cell types.
5
+ */
6
+ import type { ColumnDefinition, DataRow } from '../models/types.js';
7
+ /**
8
+ * Build an XLSX file as a Uint8Array.
9
+ */
10
+ export declare function buildXlsx(data: DataRow[], columns: ColumnDefinition[]): Uint8Array;
@@ -174,6 +174,14 @@ var s = t`
174
174
 
175
175
  .ft-body { position: relative; }
176
176
 
177
+ .ft-frozen-rows {
178
+ display: block;
179
+ position: sticky;
180
+ z-index: 3;
181
+ border-bottom: 2px solid var(--ft-active-color);
182
+ background: var(--ft-bg);
183
+ }
184
+
177
185
  .ft-row {
178
186
  display: block;
179
187
  position: absolute;
@@ -353,7 +361,7 @@ var s = t`
353
361
  position: absolute;
354
362
  top: 100%;
355
363
  left: 0;
356
- min-width: 160px;
364
+ min-width: 200px;
357
365
  background: var(--ft-bg);
358
366
  border: 1px solid var(--ft-border-color);
359
367
  border-radius: 4px;
@@ -407,6 +415,51 @@ var s = t`
407
415
  color: var(--ft-text-color);
408
416
  }
409
417
 
418
+ .ft-filter-mode-row {
419
+ display: flex;
420
+ gap: 4px;
421
+ margin-bottom: 4px;
422
+ }
423
+
424
+ .ft-filter-mode-select {
425
+ flex: 1;
426
+ padding: 3px 6px;
427
+ font: inherit;
428
+ font-size: 12px;
429
+ border: 1px solid var(--ft-border-color);
430
+ border-radius: 3px;
431
+ color: var(--ft-text-color);
432
+ background: var(--ft-editor-bg);
433
+ cursor: pointer;
434
+ }
435
+
436
+ .ft-num-cond-row {
437
+ display: flex;
438
+ gap: 4px;
439
+ margin-bottom: 4px;
440
+ }
441
+
442
+ .ft-num-op-select {
443
+ flex: 0 0 44px;
444
+ }
445
+
446
+ .ft-num-cond-input {
447
+ flex: 1;
448
+ }
449
+
450
+ .ft-filter-empty-row {
451
+ margin-top: 6px;
452
+ padding-top: 6px;
453
+ border-top: 1px solid var(--ft-border-color);
454
+ }
455
+
456
+ .ft-filter-empty-row label {
457
+ display: block;
458
+ font-size: 11px;
459
+ color: var(--ft-sort-indicator-color);
460
+ margin-bottom: 3px;
461
+ }
462
+
410
463
  /* --- Row Selection (Checkbox) --- */
411
464
 
412
465
  .ft-checkbox-header,
@@ -519,6 +572,42 @@ var s = t`
519
572
  color: white;
520
573
  }
521
574
 
575
+ /* Body context menu */
576
+ .ft-body-context-menu {
577
+ background: var(--ft-editor-bg, #fff);
578
+ border: 1px solid var(--ft-border-color);
579
+ box-shadow: 0 2px 8px rgba(0,0,0,0.16);
580
+ min-width: 180px;
581
+ border-radius: 4px;
582
+ overflow: hidden;
583
+ padding: 4px 0;
584
+ }
585
+
586
+ .ft-context-menu-item {
587
+ padding: 6px 14px;
588
+ cursor: pointer;
589
+ font-size: var(--ft-font-size, 14px);
590
+ color: var(--ft-text-color);
591
+ white-space: nowrap;
592
+ user-select: none;
593
+ }
594
+
595
+ .ft-context-menu-item:hover {
596
+ background: var(--ft-selection-bg);
597
+ color: var(--ft-active-color);
598
+ }
599
+
600
+ .ft-context-menu-item.ft-context-menu-danger:hover {
601
+ background: #fdd;
602
+ color: #c0392b;
603
+ }
604
+
605
+ .ft-context-menu-separator {
606
+ height: 1px;
607
+ background: var(--ft-border-color);
608
+ margin: 4px 0;
609
+ }
610
+
522
611
  /* Find / Replace panel */
523
612
  .ft-find-panel {
524
613
  position: sticky;
@@ -866,13 +955,13 @@ function S(e, t, n) {
866
955
  if (c && l) continue;
867
956
  if (c) return 1;
868
957
  if (l) return -1;
869
- let u = C(t, s, i.get(a) ?? "text");
958
+ let u = ee(t, s, i.get(a) ?? "text");
870
959
  if (u !== 0) return o === "asc" ? u : -u;
871
960
  }
872
961
  return n - r;
873
962
  }), r;
874
963
  }
875
- function C(e, t, n) {
964
+ function ee(e, t, n) {
876
965
  switch (n) {
877
966
  case "number": {
878
967
  let n = Number(e), r = Number(t);
@@ -887,7 +976,7 @@ function C(e, t, n) {
887
976
  default: return String(e).localeCompare(String(t));
888
977
  }
889
978
  }
890
- function w(e, t, n) {
979
+ function te(e, t, n) {
891
980
  let r = e.find((e) => e.key === t);
892
981
  return n ? r ? r.direction === "asc" ? e.map((e) => e.key === t ? {
893
982
  ...e,
@@ -905,7 +994,7 @@ function w(e, t, n) {
905
994
  }
906
995
  //#endregion
907
996
  //#region src/core/filtering.ts
908
- function T(e, t, n) {
997
+ function ne(e, t, n) {
909
998
  if (t.length === 0) return Array.from({ length: e.length }, (e, t) => t);
910
999
  let r = [];
911
1000
  for (let i = 0; i < e.length; i++) {
@@ -924,9 +1013,9 @@ function T(e, t, n) {
924
1013
  }
925
1014
  //#endregion
926
1015
  //#region src/core/undo.ts
927
- var E = 100, D = class {
1016
+ var C = 100, w = class {
928
1017
  constructor() {
929
- this._undoStack = [], this._redoStack = [], this._maxSize = E;
1018
+ this._undoStack = [], this._redoStack = [], this._maxSize = C;
930
1019
  }
931
1020
  get maxSize() {
932
1021
  return this._maxSize;
@@ -963,7 +1052,7 @@ var E = 100, D = class {
963
1052
  };
964
1053
  //#endregion
965
1054
  //#region src/clipboard/clipboard.ts
966
- function O(e, t, n) {
1055
+ function T(e, t, n) {
967
1056
  let r = [];
968
1057
  for (let i = n.startRow; i <= n.endRow; i++) {
969
1058
  let a = e[i], o = [];
@@ -975,7 +1064,7 @@ function O(e, t, n) {
975
1064
  }
976
1065
  return r.join("\n");
977
1066
  }
978
- function k(e) {
1067
+ function E(e) {
979
1068
  let t = e.replace(/\r\n/g, "\n").replace(/\r/g, "\n"), n = [], r = [], i = 0, a = t.length;
980
1069
  for (; i <= a;) {
981
1070
  if (i === a) {
@@ -1004,7 +1093,7 @@ function k(e) {
1004
1093
  }
1005
1094
  return n;
1006
1095
  }
1007
- function A(e, t) {
1096
+ function D(e, t) {
1008
1097
  if (e === "") return null;
1009
1098
  switch (t.type) {
1010
1099
  case "number": {
@@ -1016,24 +1105,122 @@ function A(e, t) {
1016
1105
  }
1017
1106
  }
1018
1107
  //#endregion
1108
+ //#region src/export/xlsx-writer.ts
1109
+ var re = (() => {
1110
+ let e = new Uint32Array(256);
1111
+ for (let t = 0; t < 256; t++) {
1112
+ let n = t;
1113
+ for (let e = 0; e < 8; e++) n = n & 1 ? 3988292384 ^ n >>> 1 : n >>> 1;
1114
+ e[t] = n;
1115
+ }
1116
+ return e;
1117
+ })();
1118
+ function ie(e) {
1119
+ let t = 4294967295;
1120
+ for (let n = 0; n < e.length; n++) t = re[(t ^ e[n]) & 255] ^ t >>> 8;
1121
+ return (t ^ 4294967295) >>> 0;
1122
+ }
1123
+ var O = new TextEncoder();
1124
+ function k(e) {
1125
+ let t = [], n = [], r = 0;
1126
+ for (let i of e) {
1127
+ let e = O.encode(i.name), a = ie(i.data), o = i.data.length, s = new ArrayBuffer(30 + e.length), c = new DataView(s);
1128
+ 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);
1129
+ let l = new ArrayBuffer(46 + e.length), u = new DataView(l);
1130
+ 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;
1131
+ }
1132
+ let i = A(n), a = /* @__PURE__ */ new ArrayBuffer(22), o = new DataView(a);
1133
+ 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), A([
1134
+ ...t,
1135
+ i,
1136
+ new Uint8Array(a)
1137
+ ]);
1138
+ }
1139
+ function A(e) {
1140
+ let t = e.reduce((e, t) => e + t.length, 0), n = new Uint8Array(t), r = 0;
1141
+ for (let t of e) n.set(t, r), r += t.length;
1142
+ return n;
1143
+ }
1144
+ function j(e) {
1145
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1146
+ }
1147
+ function ae(e) {
1148
+ let t = "";
1149
+ for (e++; e > 0;) t = String.fromCharCode(64 + (e % 26 || 26)) + t, e = Math.floor((e - 1) / 26);
1150
+ return t;
1151
+ }
1152
+ function M(e, t) {
1153
+ return ae(t) + (e + 1);
1154
+ }
1155
+ function N(e) {
1156
+ let t = Date.UTC(1899, 11, 30);
1157
+ return (e.getTime() - t) / 864e5;
1158
+ }
1159
+ var P = "<?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>", F = "<?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>", I = "<?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>", 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/worksheet\" Target=\"worksheets/sheet1.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n</Relationships>", R = "<?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>";
1160
+ function z(e, t) {
1161
+ let n = [], r = t.map((e, t) => `<c r="${M(0, t)}" t="str" s="2"><v>${j(e.header)}</v></c>`);
1162
+ return n.push(`<row r="1">${r.join("")}</row>`), e.forEach((e, r) => {
1163
+ let i = t.map((t, n) => {
1164
+ let i = M(r + 1, n), a = e[t.key];
1165
+ if (a == null) return `<c r="${i}" t="str"><v></v></c>`;
1166
+ let o = t.type ?? "text";
1167
+ 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>${N(a).toFixed(6)}</v></c>` : o === "boolean" ? `<c r="${i}" t="b"><v>${+!!a}</v></c>` : `<c r="${i}" t="str"><v>${j(String(a))}</v></c>`;
1168
+ });
1169
+ n.push(`<row r="${r + 2}">${i.join("")}</row>`);
1170
+ }), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1171
+ <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
1172
+ <sheetData>${n.join("")}</sheetData>
1173
+ </worksheet>`;
1174
+ }
1175
+ function B(e, t) {
1176
+ let n = z(e, t);
1177
+ return k([
1178
+ {
1179
+ name: "[Content_Types].xml",
1180
+ data: O.encode(P)
1181
+ },
1182
+ {
1183
+ name: "_rels/.rels",
1184
+ data: O.encode(F)
1185
+ },
1186
+ {
1187
+ name: "xl/workbook.xml",
1188
+ data: O.encode(I)
1189
+ },
1190
+ {
1191
+ name: "xl/_rels/workbook.xml.rels",
1192
+ data: O.encode(L)
1193
+ },
1194
+ {
1195
+ name: "xl/worksheets/sheet1.xml",
1196
+ data: O.encode(n)
1197
+ },
1198
+ {
1199
+ name: "xl/styles.xml",
1200
+ data: O.encode(R)
1201
+ }
1202
+ ]);
1203
+ }
1204
+ //#endregion
1019
1205
  //#region src/export/export.ts
1020
- function j(e, t, n) {
1206
+ function V(e, t, n) {
1021
1207
  switch (n) {
1022
- case "csv": return N(e, t, ",");
1023
- case "tsv": return N(e, t, " ");
1024
- case "json": return F(e, t);
1208
+ case "csv": return U(e, t, ",");
1209
+ case "tsv": return U(e, t, " ");
1210
+ case "json": return G(e, t);
1211
+ case "xlsx": return B(e, t);
1025
1212
  }
1026
1213
  }
1027
- function M(e, t) {
1214
+ function H(e, t) {
1028
1215
  return e == null ? "" : (t.type === "date" || t.type === "datetime") && e instanceof Date ? e.toISOString() : String(e);
1029
1216
  }
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");
1217
+ function U(e, t, n) {
1218
+ return [t.map((e) => W(e.header, n)).join(n), ...e.map((e) => t.map((t) => W(H(e[t.key], t), n)).join(n))].join("\n");
1032
1219
  }
1033
- function P(e, t) {
1220
+ function W(e, t) {
1034
1221
  return e.includes(t) || e.includes("\"") || e.includes("\n") || e.includes("\r") ? "\"" + e.replace(/"/g, "\"\"") + "\"" : e;
1035
1222
  }
1036
- function F(e, t) {
1223
+ function G(e, t) {
1037
1224
  let n = e.map((e) => {
1038
1225
  let n = {};
1039
1226
  for (let r of t) {
@@ -1044,28 +1231,30 @@ function F(e, t) {
1044
1231
  });
1045
1232
  return JSON.stringify(n, null, 2);
1046
1233
  }
1047
- function I(e, t, n) {
1234
+ function K(e, t, n) {
1048
1235
  let r = new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
1049
1236
  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);
1050
1237
  }
1051
- var L = {
1238
+ var q = {
1052
1239
  csv: "text/csv;charset=utf-8",
1053
1240
  tsv: "text/tab-separated-values;charset=utf-8",
1054
- json: "application/json;charset=utf-8"
1055
- }, R = {
1241
+ json: "application/json;charset=utf-8",
1242
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1243
+ }, oe = {
1056
1244
  csv: ".csv",
1057
1245
  tsv: ".tsv",
1058
- json: ".json"
1246
+ json: ".json",
1247
+ xlsx: ".xlsx"
1059
1248
  };
1060
- function z(e) {
1061
- return L[e];
1249
+ function se(e) {
1250
+ return q[e];
1062
1251
  }
1063
- function B(e) {
1064
- return R[e];
1252
+ function ce(e) {
1253
+ return oe[e];
1065
1254
  }
1066
1255
  //#endregion
1067
1256
  //#region \0@oxc-project+runtime@0.130.0/helpers/decorate.js
1068
- function V(e, t, n, r) {
1257
+ function J(e, t, n, r) {
1069
1258
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
1070
1259
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
1071
1260
  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);
@@ -1073,9 +1262,16 @@ function V(e, t, n, r) {
1073
1262
  }
1074
1263
  //#endregion
1075
1264
  //#region src/flex-table.ts
1076
- var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1265
+ var Y = {
1266
+ eq: "=",
1267
+ neq: "≠",
1268
+ gt: ">",
1269
+ lt: "<",
1270
+ gte: "≥",
1271
+ lte: "≤"
1272
+ }, X = 120, Z = 40, le = 32, Q = 5, $ = class extends e {
1077
1273
  constructor(...e) {
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();
1274
+ super(...e), this.columns = [], this.data = [], this.rowHeight = le, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, 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 w(), 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(), this._emptyFilterState = /* @__PURE__ */ new Map();
1079
1275
  }
1080
1276
  static {
1081
1277
  this.styles = s;
@@ -1384,12 +1580,12 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1384
1580
  if (!t) return "";
1385
1581
  let n = this.visibleColumns.slice(t.startCol, t.endCol + 1), r = [];
1386
1582
  for (let e = t.startRow; e <= t.endRow; e++) r.push(this.data[this._toDataIndex(e)]);
1387
- return j(r, n, e);
1583
+ return V(r, n, e);
1388
1584
  }
1389
- return j(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
1585
+ return V(this._sortedIndices.map((e) => this.data[e]), this.visibleColumns, e);
1390
1586
  }
1391
1587
  exportToFile(e, t) {
1392
- I(this.exportToString(e), t ?? `export${B(e)}`, z(e));
1588
+ K(this.exportToString(e), t ?? `export${ce(e)}`, se(e));
1393
1589
  }
1394
1590
  _getSelectedDataRows() {
1395
1591
  let e = this._selection.getEffectiveRange();
@@ -1402,8 +1598,8 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1402
1598
  return this._columnWidths.get(e);
1403
1599
  }
1404
1600
  _getColWidth(e) {
1405
- let t = this._columnWidths.get(e.key) ?? e.width ?? H;
1406
- return Math.max(t, e.minWidth ?? U);
1601
+ let t = this._columnWidths.get(e.key) ?? e.width ?? X;
1602
+ return Math.max(t, e.minWidth ?? Z);
1407
1603
  }
1408
1604
  get headerHeight() {
1409
1605
  return this.rowHeight + 8;
@@ -1411,14 +1607,20 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1411
1607
  get _visibleRowCount() {
1412
1608
  return this._sortedIndices.length;
1413
1609
  }
1610
+ get _frozenRowCount() {
1611
+ return Math.min(this.frozenRows, this._visibleRowCount);
1612
+ }
1613
+ get frozenRowsHeight() {
1614
+ return this._frozenRowCount * this.rowHeight;
1615
+ }
1414
1616
  get totalBodyHeight() {
1415
- return this._visibleRowCount * this.rowHeight;
1617
+ return Math.max(0, this._visibleRowCount - this._frozenRowCount) * this.rowHeight;
1416
1618
  }
1417
1619
  get visibleRange() {
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);
1620
+ let e = this._frozenRowCount, t = Math.max(0, this._scrollTop - this.headerHeight - this.frozenRowsHeight), n = e + Math.floor(t / this.rowHeight), r = Math.max(e, n - Q), i = Math.ceil(this._viewportHeight / this.rowHeight);
1419
1621
  return {
1420
- start: t,
1421
- end: Math.min(this._visibleRowCount, Math.floor(e / this.rowHeight) + n + G)
1622
+ start: r,
1623
+ end: Math.min(this._visibleRowCount, n + i + Q)
1422
1624
  };
1423
1625
  }
1424
1626
  connectedCallback() {
@@ -1451,13 +1653,13 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1451
1653
  i = r;
1452
1654
  break;
1453
1655
  }
1454
- i = Math.max(0, i - G);
1656
+ i = Math.max(0, i - Q);
1455
1657
  let a = e.length;
1456
1658
  for (let e = i; e < t.length; e++) if (t[e] > r) {
1457
1659
  a = e;
1458
1660
  break;
1459
1661
  }
1460
- return a = Math.min(e.length, a + G), {
1662
+ return a = Math.min(e.length, a + Q), {
1461
1663
  start: i,
1462
1664
  end: a
1463
1665
  };
@@ -1473,7 +1675,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1473
1675
  this._filteredIndices = Array.from({ length: this.data.length }, (e, t) => t), this._sortedIndices = this._filteredIndices;
1474
1676
  return;
1475
1677
  }
1476
- if (this._filteredIndices = T(this.data, this._filters, (e, t, n) => {
1678
+ if (this._filteredIndices = ne(this.data, this._filters, (e, t, n) => {
1477
1679
  this.dispatchEvent(new CustomEvent("filter-error", {
1478
1680
  detail: {
1479
1681
  error: e,
@@ -1506,17 +1708,19 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1506
1708
  this._scrollTop = this.scrollTop, this._scrollLeft = this.scrollLeft;
1507
1709
  }
1508
1710
  _onDocumentClick() {
1509
- this._openFilterKey &&= null, this._headerMenu &&= null;
1711
+ this._openFilterKey &&= null, this._headerMenu &&= null, this._bodyContextMenu &&= null;
1510
1712
  }
1511
1713
  _onContextMenu(e) {
1512
1714
  let t = e.composedPath().find((e) => e instanceof HTMLElement && e.classList.contains("ft-cell"));
1513
1715
  if (!t) return;
1716
+ e.preventDefault();
1514
1717
  let n = t.parentElement;
1515
1718
  if (!n || !n.classList.contains("ft-row")) return;
1516
1719
  let r = parseInt(t.dataset.colIndex ?? "-1", 10), i = n.style.top, a = Math.round(parseInt(i, 10) / this.rowHeight);
1517
1720
  if (r < 0 || a < 0) return;
1518
1721
  let o = this._toDataIndex(a), s = this.visibleColumns[r];
1519
- s && this.dispatchEvent(new CustomEvent("context-menu", {
1722
+ if (!s) return;
1723
+ let c = new CustomEvent("context-menu", {
1520
1724
  detail: {
1521
1725
  x: e.clientX,
1522
1726
  y: e.clientY,
@@ -1527,7 +1731,17 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1527
1731
  rowData: this.data[o]
1528
1732
  },
1529
1733
  bubbles: !0,
1530
- composed: !0
1734
+ composed: !0,
1735
+ cancelable: !0
1736
+ });
1737
+ this.dispatchEvent(c), this.showContextMenu && !c.defaultPrevented && (this._bodyContextMenu = {
1738
+ rowIndex: a,
1739
+ colIndex: r,
1740
+ dataIndex: o,
1741
+ x: e.clientX,
1742
+ y: e.clientY
1743
+ }, requestAnimationFrame(() => {
1744
+ document.addEventListener("click", this._onDocumentClick, { once: !0 });
1531
1745
  }));
1532
1746
  }
1533
1747
  _onCellClickEvent(e, t, n) {
@@ -1600,7 +1814,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1600
1814
  }
1601
1815
  let t = this.shadowRoot?.querySelector(".ft-editor");
1602
1816
  if (t) {
1603
- let n = A(t.value, e);
1817
+ let n = D(t.value, e);
1604
1818
  this._applyEdit(n);
1605
1819
  } else this._cancelEdit();
1606
1820
  }
@@ -1793,7 +2007,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1793
2007
  e.preventDefault();
1794
2008
  let n = t[this._activeCell.col];
1795
2009
  if (!n) return !0;
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);
2010
+ 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);
1797
2011
  return this._columnWidths.set(n.key, o), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
1798
2012
  detail: {
1799
2013
  key: n.key,
@@ -1822,7 +2036,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1822
2036
  async _handleCopy(e) {
1823
2037
  let t = this._selection.getEffectiveRange();
1824
2038
  if (!t) return;
1825
- let n = this.visibleColumns, r = O(this._sortedIndices.map((e) => this.data[e]), n, t);
2039
+ let n = this.visibleColumns, r = T(this._sortedIndices.map((e) => this.data[e]), n, t);
1826
2040
  try {
1827
2041
  await navigator.clipboard.writeText(r);
1828
2042
  } catch (e) {
@@ -1848,7 +2062,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1848
2062
  if (!this._activeCell) return;
1849
2063
  let e = await this._readClipboardText();
1850
2064
  if (e == null) return;
1851
- let t = k(e);
2065
+ let t = E(e);
1852
2066
  if (t.length === 0) return;
1853
2067
  let n = this._expandRowsForPaste(this._activeCell.row, t.length), r = this._applyPasteData(this._activeCell, t);
1854
2068
  if (r.length > 0 || n.length > 0) {
@@ -1906,7 +2120,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1906
2120
  for (let a = 0; a < t[i].length; a++) {
1907
2121
  let s = e.col + a;
1908
2122
  if (s >= n.length) break;
1909
- let c = n[s], l = this.data[o][c.key], u = A(t[i][a], c);
2123
+ let c = n[s], l = this.data[o][c.key], u = D(t[i][a], c);
1910
2124
  this.data[o][c.key] = u, r.push({
1911
2125
  row: o,
1912
2126
  col: s,
@@ -1971,7 +2185,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
1971
2185
  for (let r = e.startCol + 1; r <= e.endCol; r++) {
1972
2186
  let e = t[r];
1973
2187
  if (!e || !this._isCellEditable(e)) continue;
1974
- let a = A(o == null ? "" : String(o), e);
2188
+ let a = D(o == null ? "" : String(o), e);
1975
2189
  n.push({
1976
2190
  row: i,
1977
2191
  key: e.key,
@@ -2045,7 +2259,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2045
2259
  _scrollToActiveCell() {
2046
2260
  if (!this._activeCell) return;
2047
2261
  let e = this._activeCell.row * this.rowHeight + this.headerHeight, t = e + this.rowHeight;
2048
- e < this.scrollTop + this.headerHeight ? this.scrollTop = e - this.headerHeight : t > this.scrollTop + this.clientHeight && (this.scrollTop = t - this.clientHeight);
2262
+ this._activeCell.row < this._frozenRowCount || (e < this.scrollTop + this.headerHeight + this.frozenRowsHeight ? this.scrollTop = e - this.headerHeight - this.frozenRowsHeight : t > this.scrollTop + this.clientHeight && (this.scrollTop = t - this.clientHeight));
2049
2263
  let n = this.visibleColumns, r = this._activeCell.col, i = this._colLeftOffsets[r] ?? 0, a = i + this._getColWidth(n[r]);
2050
2264
  i < this.scrollLeft ? this.scrollLeft = i : a > this.scrollLeft + this.clientWidth && (this.scrollLeft = a - this.clientWidth);
2051
2265
  }
@@ -2062,7 +2276,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2062
2276
  this._selectColumn(n);
2063
2277
  return;
2064
2278
  }
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", {
2279
+ t.sortable !== !1 && (this._sortCriteria = te(this._sortCriteria, t.key, e.shiftKey), this.dataMode !== "server" && this._recomputeView(), this.requestUpdate(), this.dispatchEvent(new CustomEvent("sort-change", {
2066
2280
  detail: { criteria: [...this._sortCriteria] },
2067
2281
  bubbles: !0,
2068
2282
  composed: !0
@@ -2194,6 +2408,89 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2194
2408
  </div>
2195
2409
  ` : r;
2196
2410
  }
2411
+ _renderBodyContextMenu() {
2412
+ if (!this._bodyContextMenu) return r;
2413
+ let { colIndex: e, dataIndex: t, x: i, y: a } = this._bodyContextMenu, o = this.visibleColumns[e];
2414
+ if (!o) return r;
2415
+ let s = this.data[t]?.[o.key], c = this._filters.some((e) => e.key === o.key), l = () => {
2416
+ this._bodyContextMenu = null;
2417
+ };
2418
+ return n`
2419
+ <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;"
2420
+ @mousedown=${(e) => e.stopPropagation()}>
2421
+ <div class="ft-context-menu-item"
2422
+ @click=${() => {
2423
+ this._handleCopy(!1), l();
2424
+ }}>
2425
+ Copy
2426
+ </div>
2427
+ <div class="ft-context-menu-separator"></div>
2428
+ <div class="ft-context-menu-item"
2429
+ @click=${() => {
2430
+ this.addRow(void 0, t), l();
2431
+ }}>
2432
+ Insert row above
2433
+ </div>
2434
+ <div class="ft-context-menu-item"
2435
+ @click=${() => {
2436
+ this.addRow(void 0, t + 1), l();
2437
+ }}>
2438
+ Insert row below
2439
+ </div>
2440
+ <div class="ft-context-menu-item ft-context-menu-danger"
2441
+ @click=${() => {
2442
+ this.deleteRows([t]), l();
2443
+ }}>
2444
+ Delete row
2445
+ </div>
2446
+ <div class="ft-context-menu-separator"></div>
2447
+ <div class="ft-context-menu-item"
2448
+ @click=${() => {
2449
+ this._setColumnHidden(o.key, !0), l();
2450
+ }}>
2451
+ Hide column
2452
+ </div>
2453
+ <div class="ft-context-menu-separator"></div>
2454
+ <div class="ft-context-menu-item"
2455
+ @click=${() => {
2456
+ this._applySortFromMenu(o.key, "asc"), l();
2457
+ }}>
2458
+ Sort ascending ↑
2459
+ </div>
2460
+ <div class="ft-context-menu-item"
2461
+ @click=${() => {
2462
+ this._applySortFromMenu(o.key, "desc"), l();
2463
+ }}>
2464
+ Sort descending ↓
2465
+ </div>
2466
+ <div class="ft-context-menu-separator"></div>
2467
+ <div class="ft-context-menu-item"
2468
+ @click=${() => {
2469
+ this.setFilter(o.key, (e) => e === s), l();
2470
+ }}>
2471
+ Filter by this value
2472
+ </div>
2473
+ ${c ? n`
2474
+ <div class="ft-context-menu-item"
2475
+ @click=${() => {
2476
+ this.removeFilter(o.key), l();
2477
+ }}>
2478
+ Clear filter
2479
+ </div>
2480
+ ` : ""}
2481
+ </div>
2482
+ `;
2483
+ }
2484
+ _applySortFromMenu(e, t) {
2485
+ this.columns.find((t) => t.key === e) && (this._sortCriteria = [{
2486
+ key: e,
2487
+ direction: t
2488
+ }], this._sortedIndices = S(this.data, this._sortCriteria, this.columns), this.dispatchEvent(new CustomEvent("sort-change", {
2489
+ detail: { sortCriteria: [...this._sortCriteria] },
2490
+ bubbles: !0,
2491
+ composed: !0
2492
+ })), this.requestUpdate());
2493
+ }
2197
2494
  _adjustFilterDropdown() {
2198
2495
  if (!this._openFilterKey) return;
2199
2496
  let e = this.shadowRoot?.querySelector(".ft-filter-dropdown");
@@ -2220,36 +2517,215 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2220
2517
  </div>
2221
2518
  `;
2222
2519
  }
2520
+ _buildTextPredicate(e, t) {
2521
+ let n = e.toLowerCase();
2522
+ switch (t) {
2523
+ case "starts": return (e) => String(e ?? "").toLowerCase().startsWith(n);
2524
+ case "ends": return (e) => String(e ?? "").toLowerCase().endsWith(n);
2525
+ case "wildcard": {
2526
+ let e = n.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, "."), t = RegExp("^" + e + "$", "i");
2527
+ return (e) => t.test(String(e ?? ""));
2528
+ }
2529
+ default: return (e) => String(e ?? "").toLowerCase().includes(n);
2530
+ }
2531
+ }
2532
+ _applyTextFilter(e) {
2533
+ let t = this._emptyFilterState.get(e);
2534
+ if (t) {
2535
+ this.setFilter(e, this._buildEmptyPredicate(t));
2536
+ return;
2537
+ }
2538
+ let n = this._textFilterState.get(e);
2539
+ n?.value ? this.setFilter(e, this._buildTextPredicate(n.value, n.mode)) : this.removeFilter(e);
2540
+ }
2541
+ _buildEmptyPredicate(e) {
2542
+ return e === "empty" ? (e) => e == null || e === "" : (e) => e != null && e !== "";
2543
+ }
2544
+ _renderEmptyFilterRow(e, t) {
2545
+ return n`
2546
+ <div class="ft-filter-empty-row">
2547
+ <label>Blank cells</label>
2548
+ <select class="ft-filter-mode-select"
2549
+ .value=${this._emptyFilterState.get(e) ?? ""}
2550
+ @change=${(n) => {
2551
+ let r = n.target.value;
2552
+ (r === "" || r === "empty" || r === "non-empty") && (r ? this._emptyFilterState.set(e, r) : this._emptyFilterState.delete(e), t?.(), this._applyFilterForKey(e));
2553
+ }}
2554
+ @keydown=${(e) => {
2555
+ e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2556
+ }}>
2557
+ <option value="">— All —</option>
2558
+ <option value="empty">Empty only</option>
2559
+ <option value="non-empty">Non-empty only</option>
2560
+ </select>
2561
+ </div>
2562
+ `;
2563
+ }
2564
+ _evalNumCond(e, t) {
2565
+ let n = t.value;
2566
+ switch (t.op) {
2567
+ case "eq": return e === n;
2568
+ case "neq": return e !== n;
2569
+ case "gt": return e > n;
2570
+ case "lt": return e < n;
2571
+ case "gte": return e >= n;
2572
+ case "lte": return e <= n;
2573
+ }
2574
+ }
2575
+ _buildNumberPredicate(e) {
2576
+ let t = e.cond1.value != null, n = e.cond2.value != null;
2577
+ return !t && !n ? null : (r) => {
2578
+ let i = Number(r);
2579
+ if (isNaN(i)) return !1;
2580
+ if (t && !n) return this._evalNumCond(i, e.cond1);
2581
+ if (!t && n) return this._evalNumCond(i, e.cond2);
2582
+ let a = this._evalNumCond(i, e.cond1), o = this._evalNumCond(i, e.cond2);
2583
+ return e.join === "or" ? a || o : a && o;
2584
+ };
2585
+ }
2586
+ _buildDatePredicate(e) {
2587
+ return e.from == null && e.to == null ? null : (t) => {
2588
+ if (t == null || t === "") return !1;
2589
+ let n = t instanceof Date ? t : new Date(String(t));
2590
+ if (isNaN(n.getTime()) || e.from && n < new Date(e.from)) return !1;
2591
+ if (e.to) {
2592
+ let t = new Date(e.to);
2593
+ if (e.to.length === 10 && t.setHours(23, 59, 59, 999), n > t) return !1;
2594
+ }
2595
+ return !0;
2596
+ };
2597
+ }
2598
+ _applyFilterForKey(e) {
2599
+ let t = this._emptyFilterState.get(e);
2600
+ if (t) {
2601
+ this.setFilter(e, this._buildEmptyPredicate(t));
2602
+ return;
2603
+ }
2604
+ if (this._textFilterState.has(e)) this._applyTextFilter(e);
2605
+ else if (this._numberFilterState.has(e)) {
2606
+ let t = this._buildNumberPredicate(this._numberFilterState.get(e));
2607
+ t ? this.setFilter(e, t) : this.removeFilter(e);
2608
+ } else if (this._dateFilterState.has(e)) {
2609
+ let t = this._buildDatePredicate(this._dateFilterState.get(e));
2610
+ t ? this.setFilter(e, t) : this.removeFilter(e);
2611
+ } else this.removeFilter(e);
2612
+ }
2223
2613
  _renderTextFilter(e) {
2614
+ let t = this._textFilterState.get(e.key) ?? {
2615
+ value: "",
2616
+ mode: "contains"
2617
+ };
2224
2618
  return n`
2619
+ <div class="ft-filter-mode-row">
2620
+ <select class="ft-filter-mode-select"
2621
+ .value=${t.mode}
2622
+ @change=${(t) => {
2623
+ let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
2624
+ value: "",
2625
+ mode: "contains"
2626
+ };
2627
+ this._textFilterState.set(e.key, {
2628
+ ...r,
2629
+ mode: n
2630
+ }), this._applyTextFilter(e.key);
2631
+ }}
2632
+ @keydown=${(e) => {
2633
+ e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2634
+ }}>
2635
+ <option value="contains">Contains</option>
2636
+ <option value="starts">Starts with</option>
2637
+ <option value="ends">Ends with</option>
2638
+ <option value="wildcard">Wildcard</option>
2639
+ </select>
2640
+ </div>
2225
2641
  <input class="ft-filter-input" type="text" placeholder="Search..."
2226
- .value=${this._textFilterState.get(e.key) ?? ""}
2642
+ .value=${t.value}
2227
2643
  @input=${(t) => {
2228
- let n = t.target.value;
2229
- this._textFilterState.set(e.key, n), n ? this.setFilter(e.key, (e) => String(e ?? "").toLowerCase().includes(n.toLowerCase())) : this.removeFilter(e.key);
2644
+ let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
2645
+ value: "",
2646
+ mode: "contains"
2647
+ };
2648
+ this._textFilterState.set(e.key, {
2649
+ ...r,
2650
+ value: n
2651
+ }), this._emptyFilterState.delete(e.key), this._applyTextFilter(e.key);
2230
2652
  }}
2231
2653
  @keydown=${(e) => {
2232
2654
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2233
2655
  }}>
2656
+ ${this._renderEmptyFilterRow(e.key, () => {
2657
+ this._textFilterState.delete(e.key);
2658
+ })}
2234
2659
  `;
2235
2660
  }
2236
- _renderNumberFilter(e) {
2237
- let t = this._numberFilterState.get(e.key) ?? {};
2661
+ _defaultNumState() {
2662
+ return {
2663
+ cond1: {
2664
+ op: "gte",
2665
+ value: null
2666
+ },
2667
+ join: "and",
2668
+ cond2: {
2669
+ op: "lte",
2670
+ value: null
2671
+ }
2672
+ };
2673
+ }
2674
+ _renderNumCondRow(e, t) {
2675
+ let r = (this._numberFilterState.get(e) ?? this._defaultNumState())[t];
2238
2676
  return n`
2239
- <div class="ft-filter-range">
2240
- <input class="ft-filter-input" type="number" placeholder="Min"
2241
- .value=${t.min == null ? "" : String(t.min)}
2242
- @input=${(t) => this._applyNumberFilter(e.key, t, "min")}
2677
+ <div class="ft-num-cond-row">
2678
+ <select class="ft-filter-mode-select ft-num-op-select"
2679
+ .value=${r.op}
2680
+ @change=${(n) => {
2681
+ let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
2682
+ i[t] = {
2683
+ ...i[t],
2684
+ op: r
2685
+ }, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
2686
+ }}
2243
2687
  @keydown=${(e) => {
2244
2688
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2245
2689
  }}>
2246
- <input class="ft-filter-input" type="number" placeholder="Max"
2247
- .value=${t.max == null ? "" : String(t.max)}
2248
- @input=${(t) => this._applyNumberFilter(e.key, t, "max")}
2690
+ ${Object.keys(Y).map((e) => n`<option value=${e}>${Y[e]}</option>`)}
2691
+ </select>
2692
+ <input class="ft-filter-input ft-num-cond-input" type="number" placeholder="Value"
2693
+ .value=${r.value == null ? "" : String(r.value)}
2694
+ @input=${(n) => {
2695
+ let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
2696
+ i[t] = {
2697
+ ...i[t],
2698
+ value: r === "" ? null : Number(r)
2699
+ }, this._numberFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
2700
+ }}
2701
+ @keydown=${(e) => {
2702
+ e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2703
+ }}>
2704
+ </div>
2705
+ `;
2706
+ }
2707
+ _renderNumberFilter(e) {
2708
+ let t = this._numberFilterState.get(e.key) ?? this._defaultNumState();
2709
+ return n`
2710
+ ${this._renderNumCondRow(e.key, "cond1")}
2711
+ <div class="ft-filter-mode-row">
2712
+ <select class="ft-filter-mode-select"
2713
+ .value=${t.join}
2714
+ @change=${(t) => {
2715
+ let n = t.target.value, r = this._numberFilterState.get(e.key) ?? this._defaultNumState();
2716
+ r.join = n, this._numberFilterState.set(e.key, r), this._emptyFilterState.delete(e.key), this._applyFilterForKey(e.key);
2717
+ }}
2249
2718
  @keydown=${(e) => {
2250
2719
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2251
2720
  }}>
2721
+ <option value="and">AND</option>
2722
+ <option value="or">OR</option>
2723
+ </select>
2252
2724
  </div>
2725
+ ${this._renderNumCondRow(e.key, "cond2")}
2726
+ ${this._renderEmptyFilterRow(e.key, () => {
2727
+ this._numberFilterState.delete(e.key);
2728
+ })}
2253
2729
  `;
2254
2730
  }
2255
2731
  _cellKey(e, t) {
@@ -2270,13 +2746,6 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2270
2746
  let n = this._invalidCells.get(this._cellKey(e, t));
2271
2747
  return n ? n.error : null;
2272
2748
  }
2273
- _applyNumberFilter(e, t, n) {
2274
- let r = t.target.value, i = this._numberFilterState.get(e) ?? {};
2275
- r === "" ? delete i[n] : i[n] = Number(r), this._numberFilterState.set(e, i), i.min == null && i.max == null ? this.removeFilter(e) : this.setFilter(e, (e) => {
2276
- let t = Number(e);
2277
- return !(isNaN(t) || i.min != null && t < i.min || i.max != null && t > i.max);
2278
- });
2279
- }
2280
2749
  _renderDateFilter(e) {
2281
2750
  let t = e.type === "datetime" ? "datetime-local" : "date", r = this._dateFilterState.get(e.key) ?? {};
2282
2751
  return n`
@@ -2294,20 +2763,14 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2294
2763
  e.key === "Escape" && (this._openFilterKey = null), e.stopPropagation();
2295
2764
  }}>
2296
2765
  </div>
2766
+ ${this._renderEmptyFilterRow(e.key, () => {
2767
+ this._dateFilterState.delete(e.key);
2768
+ })}
2297
2769
  `;
2298
2770
  }
2299
2771
  _applyDateFilter(e, t, n) {
2300
2772
  let r = t.target.value, i = this._dateFilterState.get(e) ?? {};
2301
- r === "" ? delete i[n] : i[n] = r, this._dateFilterState.set(e, i), i.from == null && i.to == null ? this.removeFilter(e) : this.setFilter(e, (e) => {
2302
- if (e == null || e === "") return !1;
2303
- let t = e instanceof Date ? e : new Date(String(e));
2304
- if (isNaN(t.getTime()) || i.from && t < new Date(i.from)) return !1;
2305
- if (i.to) {
2306
- let e = new Date(i.to);
2307
- if (i.to.length === 10 && e.setHours(23, 59, 59, 999), t > e) return !1;
2308
- }
2309
- return !0;
2310
- });
2773
+ r === "" ? delete i[n] : i[n] = r, this._dateFilterState.set(e, i), this._emptyFilterState.delete(e), this._applyFilterForKey(e);
2311
2774
  }
2312
2775
  _renderBooleanFilter(e) {
2313
2776
  return n`
@@ -2323,10 +2786,11 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2323
2786
  <option value="true">\u2714 True</option>
2324
2787
  <option value="false">\u2718 False</option>
2325
2788
  </select>
2789
+ ${this._renderEmptyFilterRow(e.key)}
2326
2790
  `;
2327
2791
  }
2328
2792
  _clearColumnFilter(e) {
2329
- this.removeFilter(e), this._textFilterState.delete(e), this._numberFilterState.delete(e), this._dateFilterState.delete(e), this._openFilterKey = null;
2793
+ this.removeFilter(e), this._textFilterState.delete(e), this._numberFilterState.delete(e), this._dateFilterState.delete(e), this._emptyFilterState.delete(e), this._openFilterKey = null;
2330
2794
  }
2331
2795
  _onResizeAutoFit(e, t) {
2332
2796
  e.preventDefault(), e.stopPropagation();
@@ -2334,7 +2798,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2334
2798
  if (!n) return;
2335
2799
  let r = this.shadowRoot?.querySelectorAll(`.ft-cell[data-col-index="${t}"]`), i = 0, a = this.shadowRoot?.querySelector(`.ft-header-cell[data-col-index="${t}"]`);
2336
2800
  if (a && (i = Math.max(i, a.scrollWidth)), r) for (let e of r) i = Math.max(i, e.scrollWidth);
2337
- let o = n.minWidth ?? U, s = Math.max(o, i + 8);
2801
+ let o = n.minWidth ?? Z, s = Math.max(o, i + 8);
2338
2802
  this._columnWidths.set(n.key, s), this.requestUpdate(), this.dispatchEvent(new CustomEvent("column-resize", {
2339
2803
  detail: {
2340
2804
  key: n.key,
@@ -2347,7 +2811,7 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2347
2811
  }
2348
2812
  _onResizeStart(e, t) {
2349
2813
  e.preventDefault(), e.stopPropagation();
2350
- let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? H;
2814
+ let n = this.visibleColumns[t], r = this._columnWidths.get(n.key) ?? n.width ?? X;
2351
2815
  this._resizing = {
2352
2816
  colIndex: t,
2353
2817
  startX: e.clientX,
@@ -2355,13 +2819,13 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2355
2819
  };
2356
2820
  let i = (e) => {
2357
2821
  if (!this._resizing) return;
2358
- let t = e.clientX - this._resizing.startX, r = n.minWidth ?? U, i = Math.max(r, this._resizing.startWidth + t);
2822
+ let t = e.clientX - this._resizing.startX, r = n.minWidth ?? Z, i = Math.max(r, this._resizing.startWidth + t);
2359
2823
  this._columnWidths.set(n.key, i), this.requestUpdate();
2360
2824
  }, a = () => {
2361
2825
  document.removeEventListener("mousemove", i), document.removeEventListener("mouseup", o), this._resizeCleanup = null;
2362
2826
  }, o = () => {
2363
2827
  if (a(), this._resizing) {
2364
- let e = this._columnWidths.get(n.key) ?? H;
2828
+ let e = this._columnWidths.get(n.key) ?? X;
2365
2829
  this.dispatchEvent(new CustomEvent("column-resize", {
2366
2830
  detail: {
2367
2831
  key: n.key,
@@ -2795,9 +3259,9 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2795
3259
  </div>
2796
3260
  <div class="ft-empty">${this.data.length === 0 ? "No data" : "No matching data"}</div>
2797
3261
  `;
2798
- let { start: p, end: m } = this.visibleRange, h = [];
2799
- for (let e = p; e < m; e++) h.push(this._renderRow(e, i, a, o));
2800
- let g = this._renderFillHandle(), _ = this._rowDragIndicatorY == null ? "" : n`<div class="ft-row-drop-indicator" style="top:${this._rowDragIndicatorY}px;width:${r + this._prefixWidth}px;"></div>`;
3262
+ let { start: p, end: m } = this.visibleRange, h = this._frozenRowCount, g = [];
3263
+ for (let e = p; e < m; e++) g.push(this._renderRow(e, i, a, o, (e - h) * this.rowHeight));
3264
+ let _ = this._renderFillHandle(), v = this._rowDragIndicatorY == null ? "" : n`<div class="ft-row-drop-indicator" style="top:${this._rowDragIndicatorY}px;width:${r + this._prefixWidth}px;"></div>`;
2801
3265
  return n`
2802
3266
  ${this._renderFindPanel()}
2803
3267
  <div class="ft-header" role="row" style="width: ${r}px; height: ${t}px;">
@@ -2805,13 +3269,15 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2805
3269
  ${d}
2806
3270
  ${f}
2807
3271
  </div>
3272
+ ${this._renderFrozenRows(i, a, o)}
2808
3273
  <div class="ft-body" style="height: ${this.totalBodyHeight}px; width: ${r}px;">
2809
- ${h}
3274
+ ${g}
2810
3275
  </div>
2811
3276
  ${this.footerData ? this._renderFooter(i, a, o) : ""}
3277
+ ${v}
2812
3278
  ${_}
2813
- ${g}
2814
3279
  ${this._renderHeaderContextMenu()}
3280
+ ${this._renderBodyContextMenu()}
2815
3281
  `;
2816
3282
  }
2817
3283
  _onSelectAllChange(e) {
@@ -2820,6 +3286,17 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2820
3286
  _onRowCheckboxChange(e, t) {
2821
3287
  e.stopPropagation(), this._rowSelection.toggle(t), this._rowSelectionVersion++, this._dispatchRowSelectionEvent();
2822
3288
  }
3289
+ _renderFrozenRows(e, t, i) {
3290
+ let a = this._frozenRowCount;
3291
+ if (a === 0) return r;
3292
+ let o = this._totalRowWidth, s = [];
3293
+ for (let n = 0; n < a; n++) s.push(this._renderRow(n, e, t, i, n * this.rowHeight));
3294
+ return n`
3295
+ <div class="ft-frozen-rows" style="top: ${this.headerHeight}px; height: ${this.frozenRowsHeight}px; width: ${o}px;">
3296
+ ${s}
3297
+ </div>
3298
+ `;
3299
+ }
2823
3300
  _renderFooter(e, t, r) {
2824
3301
  if (!this.footerData) return "";
2825
3302
  let i = this.visibleColumns, a = this.rowHeight, o = this._totalRowWidth, s = this._scrollLeft, c = 0, l = this.selectable ? n`<div class="ft-footer-cell ft-checkbox-cell"
@@ -2848,29 +3325,29 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2848
3325
  </div>
2849
3326
  `;
2850
3327
  }
2851
- _renderRow(e, t, r, i) {
2852
- let a = this.visibleColumns, o = this._toDataIndex(e), s = this.data[o], c = e * this.rowHeight, l = this.rowHeight, u = this._totalRowWidth, d = e % 2 == 0 ? "ft-row-even" : "ft-row-odd", f = this.selectable && this._rowSelection.isSelected(e), p = this._scrollLeft, m = 0, h = this.selectable ? n`
3328
+ _renderRow(e, t, r, i, a) {
3329
+ let o = this.visibleColumns, s = this._toDataIndex(e), c = this.data[s], l = a ?? e * this.rowHeight, u = this.rowHeight, d = this._totalRowWidth, f = e % 2 == 0 ? "ft-row-even" : "ft-row-odd", p = this.selectable && this._rowSelection.isSelected(e), m = this._scrollLeft, h = 0, g = this.selectable ? n`
2853
3330
  <div class="ft-checkbox-cell"
2854
- style="position: absolute; top: 0; left: ${p + m}px; width: 36px; height: ${l}px; z-index: 2;">
3331
+ style="position: absolute; top: 0; left: ${m + h}px; width: 36px; height: ${u}px; z-index: 2;">
2855
3332
  <input type="checkbox"
2856
- .checked=${f}
3333
+ .checked=${p}
2857
3334
  @change=${(t) => this._onRowCheckboxChange(t, e)}>
2858
3335
  </div>
2859
3336
  ` : "";
2860
- this.selectable && (m += 36);
2861
- let g = this._rowDrag?.active && this._rowDrag.rowIndex === e, _ = this.showRowNumbers ? n`
2862
- <div class="ft-row-num ${g ? "ft-col-dragging" : ""}"
2863
- style="position: absolute; top: 0; left: ${p + m}px; width: 48px; height: ${l}px; z-index: 2; cursor: grab;"
3337
+ this.selectable && (h += 36);
3338
+ let _ = this._rowDrag?.active && this._rowDrag.rowIndex === e, v = this.showRowNumbers ? n`
3339
+ <div class="ft-row-num ${_ ? "ft-col-dragging" : ""}"
3340
+ style="position: absolute; top: 0; left: ${m + h}px; width: 48px; height: ${u}px; z-index: 2; cursor: grab;"
2864
3341
  @mousedown=${(t) => this._onRowNumMouseDown(t, e)}
2865
- @click=${() => this._onRowNumberClick(e)}>${o + 1}</div>
2866
- ` : "", v = [];
2867
- for (let t of i) v.push(this._renderCell(s, a[t], e, t));
2868
- for (let n = t; n < r; n++) v.push(this._renderCell(s, a[n], e, n));
3342
+ @click=${() => this._onRowNumberClick(e)}>${s + 1}</div>
3343
+ ` : "", y = [];
3344
+ for (let t of i) y.push(this._renderCell(c, o[t], e, t));
3345
+ for (let n = t; n < r; n++) y.push(this._renderCell(c, o[n], e, n));
2869
3346
  return n`
2870
- <div class="ft-row ${d} ${f ? "ft-row-selected" : ""}" role="row"
2871
- style="top: ${c}px; height: ${l}px; width: ${u}px;">
2872
- ${h}${_}
2873
- ${v}
3347
+ <div class="ft-row ${f} ${p ? "ft-row-selected" : ""}" role="row"
3348
+ style="top: ${l}px; height: ${u}px; width: ${d}px;">
3349
+ ${g}${v}
3350
+ ${y}
2874
3351
  </div>
2875
3352
  `;
2876
3353
  }
@@ -2991,36 +3468,42 @@ var H = 120, U = 40, W = 32, G = 5, K = class extends e {
2991
3468
  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")}`;
2992
3469
  }
2993
3470
  };
2994
- V([a({ type: Array })], K.prototype, "columns", void 0), V([a({
3471
+ J([a({ type: Array })], $.prototype, "columns", void 0), J([a({
2995
3472
  type: Array,
2996
3473
  hasChanged: () => !0
2997
- })], K.prototype, "data", void 0), V([a({
3474
+ })], $.prototype, "data", void 0), J([a({
2998
3475
  type: Number,
2999
3476
  attribute: "row-height"
3000
- })], K.prototype, "rowHeight", void 0), V([a({
3477
+ })], $.prototype, "rowHeight", void 0), J([a({
3001
3478
  type: Boolean,
3002
3479
  attribute: "show-row-numbers"
3003
- })], K.prototype, "showRowNumbers", void 0), V([a({
3480
+ })], $.prototype, "showRowNumbers", void 0), J([a({
3004
3481
  type: String,
3005
3482
  reflect: !0
3006
- })], K.prototype, "theme", void 0), V([a({
3483
+ })], $.prototype, "theme", void 0), J([a({
3007
3484
  type: Number,
3008
3485
  attribute: "max-rows"
3009
- })], K.prototype, "maxRows", void 0), V([a({ type: Boolean })], K.prototype, "editable", void 0), V([a({
3486
+ })], $.prototype, "maxRows", void 0), J([a({ type: Boolean })], $.prototype, "editable", void 0), J([a({
3010
3487
  type: Boolean,
3011
3488
  attribute: "show-filters"
3012
- })], K.prototype, "showFilters", void 0), V([a({ type: Boolean })], K.prototype, "selectable", void 0), V([a({
3489
+ })], $.prototype, "showFilters", void 0), J([a({
3490
+ type: Boolean,
3491
+ attribute: "show-context-menu"
3492
+ })], $.prototype, "showContextMenu", void 0), J([a({
3493
+ type: Number,
3494
+ attribute: "frozen-rows"
3495
+ })], $.prototype, "frozenRows", void 0), J([a({ type: Boolean })], $.prototype, "selectable", void 0), J([a({
3013
3496
  type: String,
3014
3497
  attribute: "selection-mode"
3015
- })], K.prototype, "selectionMode", null), V([a({
3498
+ })], $.prototype, "selectionMode", null), J([a({
3016
3499
  type: String,
3017
3500
  attribute: "data-mode"
3018
- })], K.prototype, "dataMode", void 0), V([a({
3501
+ })], $.prototype, "dataMode", void 0), J([a({
3019
3502
  type: Object,
3020
3503
  attribute: "footer-data"
3021
- })], K.prototype, "footerData", void 0), V([a({
3504
+ })], $.prototype, "footerData", void 0), J([a({
3022
3505
  type: Number,
3023
3506
  attribute: "max-undo-size"
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);
3507
+ })], $.prototype, "maxUndoSize", null), J([o()], $.prototype, "_scrollTop", void 0), J([o()], $.prototype, "_scrollLeft", void 0), J([o()], $.prototype, "_viewportHeight", void 0), J([o()], $.prototype, "_viewportWidth", void 0), J([o()], $.prototype, "_activeCell", void 0), J([o()], $.prototype, "_editingCell", void 0), J([o()], $.prototype, "_sortCriteria", void 0), J([o()], $.prototype, "_openFilterKey", void 0), J([o()], $.prototype, "_rowSelectionVersion", void 0), J([o()], $.prototype, "_autocompleteState", void 0), J([o()], $.prototype, "_headerMenu", void 0), J([o()], $.prototype, "_bodyContextMenu", void 0), $ = J([i("flex-table")], $);
3025
3508
  //#endregion
3026
- export { f as a, x as i, j as n, D as r, K as t };
3509
+ export { f as a, x as i, V as n, w as r, $ as t };
@@ -15,6 +15,10 @@ export declare class FlexTable extends LitElement {
15
15
  maxRows: number;
16
16
  editable: boolean;
17
17
  showFilters: boolean;
18
+ /** Enable built-in context menu on cell right-click. */
19
+ showContextMenu: boolean;
20
+ /** Number of rows to freeze at the top (always visible during vertical scroll). */
21
+ frozenRows: number;
18
22
  /** Enable row-level checkbox selection. */
19
23
  selectable: boolean;
20
24
  /** Row selection mode: 'single' or 'multi' (default: 'multi'). */
@@ -46,6 +50,7 @@ export declare class FlexTable extends LitElement {
46
50
  private _rowSelectionVersion;
47
51
  private _autocompleteState;
48
52
  private _headerMenu;
53
+ private _bodyContextMenu;
49
54
  private _viewDirty;
50
55
  private _isDragging;
51
56
  private _wasDrag;
@@ -152,7 +157,7 @@ export declare class FlexTable extends LitElement {
152
157
  */
153
158
  exportToString(format: ExportFormat, options?: {
154
159
  selectionOnly?: boolean;
155
- }): string;
160
+ }): string | Uint8Array;
156
161
  /**
157
162
  * Export table data and trigger file download.
158
163
  */
@@ -166,6 +171,8 @@ export declare class FlexTable extends LitElement {
166
171
  private get headerHeight();
167
172
  /** Number of rows visible after filter + sort. */
168
173
  private get _visibleRowCount();
174
+ private get _frozenRowCount();
175
+ private get frozenRowsHeight();
169
176
  private get totalBodyHeight();
170
177
  private get visibleRange();
171
178
  connectedCallback(): void;
@@ -228,10 +235,22 @@ export declare class FlexTable extends LitElement {
228
235
  private _onHeaderContextMenu;
229
236
  private _showHiddenBefore;
230
237
  private _renderHeaderContextMenu;
238
+ private _renderBodyContextMenu;
239
+ private _applySortFromMenu;
231
240
  private _adjustFilterDropdown;
232
241
  private _onFilterBtnClick;
233
242
  private _renderFilterDropdown;
243
+ private _buildTextPredicate;
244
+ private _applyTextFilter;
245
+ private _buildEmptyPredicate;
246
+ private _renderEmptyFilterRow;
247
+ private _evalNumCond;
248
+ private _buildNumberPredicate;
249
+ private _buildDatePredicate;
250
+ private _applyFilterForKey;
234
251
  private _renderTextFilter;
252
+ private _defaultNumState;
253
+ private _renderNumCondRow;
235
254
  private _renderNumberFilter;
236
255
  private _invalidCells;
237
256
  private _cellKey;
@@ -240,7 +259,7 @@ export declare class FlexTable extends LitElement {
240
259
  private _textFilterState;
241
260
  private _numberFilterState;
242
261
  private _dateFilterState;
243
- private _applyNumberFilter;
262
+ private _emptyFilterState;
244
263
  private _renderDateFilter;
245
264
  private _applyDateFilter;
246
265
  private _renderBooleanFilter;
@@ -274,6 +293,7 @@ export declare class FlexTable extends LitElement {
274
293
  render(): TemplateResult<1>;
275
294
  private _onSelectAllChange;
276
295
  private _onRowCheckboxChange;
296
+ private _renderFrozenRows;
277
297
  private _renderFooter;
278
298
  private _renderRow;
279
299
  private _renderCell;
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r, t as i } from "./flex-table-zJST_6sy.js";
1
+ import { a as e, i as t, n, r, t as i } from "./flex-table-BVzjrFBP.js";
2
2
  export { i as FlexTable, t as RowSelectionState, r as UndoStack, n as exportData, e as renderCell };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-zJST_6sy.js";
1
+ import { t as e } from "./flex-table-BVzjrFBP.js";
2
2
  import t from "react";
3
3
  import { createComponent as n } from "@lit/react";
4
4
  //#region src/react.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",