@iyulab/flex-table 0.16.1 → 0.18.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.
@@ -641,6 +641,70 @@ var s = t`
641
641
  margin: 4px 0;
642
642
  }
643
643
 
644
+ /* Comment edit popup */
645
+ .ft-comment-popup {
646
+ background: var(--ft-editor-bg, #fff);
647
+ border: 1px solid var(--ft-border-color);
648
+ box-shadow: 0 2px 10px rgba(0,0,0,0.18);
649
+ border-radius: 4px;
650
+ padding: 8px;
651
+ display: flex;
652
+ flex-direction: column;
653
+ gap: 6px;
654
+ min-width: 220px;
655
+ }
656
+
657
+ .ft-comment-popup-textarea {
658
+ width: 100%;
659
+ box-sizing: border-box;
660
+ resize: vertical;
661
+ font-size: var(--ft-font-size, 14px);
662
+ font-family: inherit;
663
+ color: var(--ft-text-color);
664
+ background: var(--ft-editor-bg, #fff);
665
+ border: 1px solid var(--ft-border-color);
666
+ border-radius: 3px;
667
+ padding: 4px 6px;
668
+ outline: none;
669
+ min-height: 72px;
670
+ }
671
+
672
+ .ft-comment-popup-textarea:focus {
673
+ border-color: var(--ft-active-color, #3b82f6);
674
+ box-shadow: 0 0 0 2px rgba(59,130,246,0.2);
675
+ }
676
+
677
+ .ft-comment-popup-buttons {
678
+ display: flex;
679
+ justify-content: flex-end;
680
+ gap: 6px;
681
+ }
682
+
683
+ .ft-comment-popup-cancel,
684
+ .ft-comment-popup-save {
685
+ padding: 4px 12px;
686
+ font-size: var(--ft-font-size, 13px);
687
+ border-radius: 3px;
688
+ border: 1px solid var(--ft-border-color);
689
+ cursor: pointer;
690
+ background: var(--ft-editor-bg, #fff);
691
+ color: var(--ft-text-color);
692
+ }
693
+
694
+ .ft-comment-popup-save {
695
+ background: var(--ft-active-color, #3b82f6);
696
+ color: #fff;
697
+ border-color: transparent;
698
+ }
699
+
700
+ .ft-comment-popup-cancel:hover {
701
+ background: var(--ft-selection-bg);
702
+ }
703
+
704
+ .ft-comment-popup-save:hover {
705
+ opacity: 0.9;
706
+ }
707
+
644
708
  /* Find / Replace panel */
645
709
  .ft-find-panel {
646
710
  position: sticky;
@@ -1416,11 +1480,20 @@ var Y = {
1416
1480
  lte: "≤"
1417
1481
  }, X = 120, Z = 40, xe = 32, Q = 5, $ = class extends e {
1418
1482
  constructor(...e) {
1419
- super(...e), this.columns = [], this.data = [], this.rowHeight = xe, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.importEnabled = !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._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._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, 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();
1483
+ super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.rowHeight = xe, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.importEnabled = !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._bodyContextMenu = null, this._commentPopup = 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._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._onCommentPopupOutsideClick = () => {
1484
+ this._commitCommentPopup();
1485
+ }, 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();
1420
1486
  }
1421
1487
  static {
1422
1488
  this.styles = s;
1423
1489
  }
1490
+ get data() {
1491
+ return this._data;
1492
+ }
1493
+ set data(e) {
1494
+ let t = this._data;
1495
+ this._data = e, this.clearUndoOnDataChange && !this._inUndoRedo && this._undo.clear(), this.requestUpdate("data", t);
1496
+ }
1424
1497
  set selectionMode(e) {
1425
1498
  this._rowSelection.mode = e, this.requestUpdate();
1426
1499
  }
@@ -1501,6 +1574,15 @@ var Y = {
1501
1574
  refreshData() {
1502
1575
  this.requestUpdate("data");
1503
1576
  }
1577
+ undo() {
1578
+ this._inUndoRedo = !0, this._undo.undo(), this._inUndoRedo = !1, this.requestUpdate(), this._dispatchUndoStateEvent();
1579
+ }
1580
+ redo() {
1581
+ this._inUndoRedo = !0, this._undo.redo(), this._inUndoRedo = !1, this.requestUpdate(), this._dispatchUndoStateEvent();
1582
+ }
1583
+ clearUndoHistory() {
1584
+ this._undo.clear(), this._dispatchUndoStateEvent();
1585
+ }
1504
1586
  _dispatchUndoStateEvent() {
1505
1587
  this.dispatchEvent(new CustomEvent("undo-state-change", {
1506
1588
  detail: {
@@ -1601,10 +1683,32 @@ var Y = {
1601
1683
  })), this._dispatchUndoStateEvent();
1602
1684
  }
1603
1685
  hideColumn(e) {
1604
- this._setColumnHidden(e, !0);
1686
+ let t = this.columns.findIndex((t) => t.key === e);
1687
+ if (t === -1) return;
1688
+ let n = this.columns[t].hidden ?? !1;
1689
+ this._setColumnHidden(e, !0), this._undo.push({
1690
+ label: "column-visibility",
1691
+ undo: () => {
1692
+ this._setColumnHidden(e, n);
1693
+ },
1694
+ redo: () => {
1695
+ this._setColumnHidden(e, !0);
1696
+ }
1697
+ });
1605
1698
  }
1606
1699
  showColumn(e) {
1607
- this._setColumnHidden(e, !1);
1700
+ let t = this.columns.findIndex((t) => t.key === e);
1701
+ if (t === -1) return;
1702
+ let n = this.columns[t].hidden ?? !1;
1703
+ this._setColumnHidden(e, !1), this._undo.push({
1704
+ label: "column-visibility",
1705
+ undo: () => {
1706
+ this._setColumnHidden(e, n);
1707
+ },
1708
+ redo: () => {
1709
+ this._setColumnHidden(e, !1);
1710
+ }
1711
+ });
1608
1712
  }
1609
1713
  _setColumnHidden(e, t) {
1610
1714
  let n = this.columns.findIndex((t) => t.key === e);
@@ -1733,6 +1837,18 @@ var Y = {
1733
1837
  G(this.exportToString(e), t ?? `export${le(e)}`, ce(e));
1734
1838
  }
1735
1839
  setComment(e, t, n) {
1840
+ let r = this.getComment(e, t);
1841
+ this._applyComment(e, t, n), this._undo.push({
1842
+ label: "comment",
1843
+ undo: () => {
1844
+ this._applyComment(e, t, r);
1845
+ },
1846
+ redo: () => {
1847
+ this._applyComment(e, t, n);
1848
+ }
1849
+ });
1850
+ }
1851
+ _applyComment(e, t, n) {
1736
1852
  if (n) this._comments.has(e) || this._comments.set(e, /* @__PURE__ */ new Map()), this._comments.get(e).set(t, n);
1737
1853
  else {
1738
1854
  let n = this._comments.get(e);
@@ -1761,7 +1877,16 @@ var Y = {
1761
1877
  return e;
1762
1878
  }
1763
1879
  clearComments() {
1764
- this._comments.clear(), this.requestUpdate();
1880
+ let e = new Map([...this._comments].map(([e, t]) => [e, new Map(t)]));
1881
+ this._comments.clear(), this.requestUpdate(), this._undo.push({
1882
+ label: "clear-comments",
1883
+ undo: () => {
1884
+ this._comments = e, this.requestUpdate();
1885
+ },
1886
+ redo: () => {
1887
+ this._comments.clear(), this.requestUpdate();
1888
+ }
1889
+ });
1765
1890
  }
1766
1891
  async importFromFile(e) {
1767
1892
  let t = e.name.toLowerCase();
@@ -1782,8 +1907,16 @@ var Y = {
1782
1907
  let o = this.columns.find((e) => e.key === a);
1783
1908
  r[a] = o ? k(n[i] ?? "", o) : n[i] ?? null;
1784
1909
  }), r;
1785
- });
1786
- this.data = n, this.dispatchEvent(new CustomEvent("data-import", {
1910
+ }), r = [...this.data];
1911
+ this.data = n, this._undo.push({
1912
+ label: "import",
1913
+ undo: () => {
1914
+ this.data = r, this.requestUpdate();
1915
+ },
1916
+ redo: () => {
1917
+ this.data = n, this.requestUpdate();
1918
+ }
1919
+ }), this.dispatchEvent(new CustomEvent("data-import", {
1787
1920
  detail: { count: n.length },
1788
1921
  bubbles: !0,
1789
1922
  composed: !0
@@ -1799,8 +1932,16 @@ var Y = {
1799
1932
  let o = this.columns.find((e) => e.key === a);
1800
1933
  r[a] = o ? k(e[i] ?? "", o) : e[i] ?? null;
1801
1934
  }), r;
1802
- });
1803
- this.data = r, this.dispatchEvent(new CustomEvent("data-import", {
1935
+ }), i = [...this.data];
1936
+ this.data = r, this._undo.push({
1937
+ label: "import",
1938
+ undo: () => {
1939
+ this.data = i, this.requestUpdate();
1940
+ },
1941
+ redo: () => {
1942
+ this.data = r, this.requestUpdate();
1943
+ }
1944
+ }), this.dispatchEvent(new CustomEvent("data-import", {
1804
1945
  detail: { count: r.length },
1805
1946
  bubbles: !0,
1806
1947
  composed: !0
@@ -1871,7 +2012,7 @@ var Y = {
1871
2012
  super.connectedCallback(), this._onScroll = this._onScroll.bind(this), this._onKeyDown = this._onKeyDown.bind(this), this._onDocumentClick = this._onDocumentClick.bind(this), this._onContextMenu = this._onContextMenu.bind(this), this._onDragover = this._onDragover.bind(this), this._onDragleave = this._onDragleave.bind(this), this._onDrop = this._onDrop.bind(this), this.addEventListener("scroll", this._onScroll, { passive: !0 }), this.addEventListener("keydown", this._onKeyDown), this.addEventListener("contextmenu", this._onContextMenu), this.addEventListener("dragover", this._onDragover), this.addEventListener("dragleave", this._onDragleave), this.addEventListener("drop", this._onDrop), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "grid"), typeof ResizeObserver < "u" && (this._hostResizeObserver = new ResizeObserver(() => this._measureViewport()), this._hostResizeObserver.observe(this));
1872
2013
  }
1873
2014
  disconnectedCallback() {
1874
- super.disconnectedCallback(), this.removeEventListener("scroll", this._onScroll), this.removeEventListener("keydown", this._onKeyDown), this.removeEventListener("contextmenu", this._onContextMenu), this.removeEventListener("dragover", this._onDragover), this.removeEventListener("dragleave", this._onDragleave), this.removeEventListener("drop", this._onDrop), document.removeEventListener("click", this._onDocumentClick), this._isDragging = !1, this._wasDrag = !1, this._resizeCleanup &&= (this._resizeCleanup(), null), this._hostResizeObserver &&= (this._hostResizeObserver.disconnect(), null);
2015
+ super.disconnectedCallback(), this.removeEventListener("scroll", this._onScroll), this.removeEventListener("keydown", this._onKeyDown), this.removeEventListener("contextmenu", this._onContextMenu), this.removeEventListener("dragover", this._onDragover), this.removeEventListener("dragleave", this._onDragleave), this.removeEventListener("drop", this._onDrop), document.removeEventListener("click", this._onDocumentClick), document.removeEventListener("mousedown", this._onCommentPopupOutsideClick), this._isDragging = !1, this._wasDrag = !1, this._resizeCleanup &&= (this._resizeCleanup(), null), this._hostResizeObserver &&= (this._hostResizeObserver.disconnect(), null);
1875
2016
  }
1876
2017
  firstUpdated() {
1877
2018
  this._measureViewport();
@@ -1911,8 +2052,11 @@ var Y = {
1911
2052
  willUpdate(e) {
1912
2053
  (!(e.size <= 2 && !e.has("data") && !e.has("columns") && !e.has("_openFilterKey") && !e.has("_editingCell") && !e.has("_activeCell") && (e.has("_scrollTop") || e.has("_scrollLeft"))) || this._viewDirty) && (this._recomputeView(), this._viewDirty = !1), this._updateColOffsets(), this._selection.setDimensions(this._visibleRowCount, this.visibleColumns.length), this._rowSelection.setRowCount(this._visibleRowCount);
1913
2054
  }
1914
- updated() {
1915
- this._focusEditor(), this._adjustFilterDropdown(), this.setAttribute("aria-rowcount", String(this._visibleRowCount)), this.setAttribute("aria-colcount", String(this.visibleColumns.length));
2055
+ updated(e) {
2056
+ if (this._focusEditor(), this._adjustFilterDropdown(), this.setAttribute("aria-rowcount", String(this._visibleRowCount)), this.setAttribute("aria-colcount", String(this.visibleColumns.length)), e.has("_commentPopup") && this._commentPopup) {
2057
+ let e = this.shadowRoot?.querySelector(".ft-comment-popup textarea");
2058
+ e && (e.value = this.getComment(this._commentPopup.dataIndex, this._commentPopup.colKey) ?? "", e.focus(), e.select());
2059
+ }
1916
2060
  }
1917
2061
  _recomputeView() {
1918
2062
  if (this.dataMode === "server") {
@@ -1978,7 +2122,7 @@ var Y = {
1978
2122
  composed: !0,
1979
2123
  cancelable: !0
1980
2124
  });
1981
- this.dispatchEvent(c), this.showContextMenu && !c.defaultPrevented && (this._bodyContextMenu = {
2125
+ this.dispatchEvent(c), this._cancelCommentPopup(), this.showContextMenu && !c.defaultPrevented && (this._bodyContextMenu = {
1982
2126
  rowIndex: a,
1983
2127
  colIndex: r,
1984
2128
  dataIndex: o,
@@ -2234,8 +2378,8 @@ var Y = {
2234
2378
  _handleCtrlKey(e) {
2235
2379
  if (!(e.ctrlKey || e.metaKey) || e.altKey) return !1;
2236
2380
  switch (e.key.toLowerCase()) {
2237
- case "z": return e.preventDefault(), e.shiftKey ? this._undo.redo() : this._undo.undo(), this.requestUpdate(), this._dispatchUndoStateEvent(), !0;
2238
- case "y": return e.preventDefault(), this._undo.redo(), this.requestUpdate(), this._dispatchUndoStateEvent(), !0;
2381
+ case "z": return e.preventDefault(), e.shiftKey ? this.redo() : this.undo(), !0;
2382
+ case "y": return e.preventDefault(), this.redo(), !0;
2239
2383
  case "c": return e.preventDefault(), this._handleCopy(!1), !0;
2240
2384
  case "x": return e.preventDefault(), this._handleCopy(this.editable), !0;
2241
2385
  case "v": return e.preventDefault(), this.editable && this._handlePaste(), !0;
@@ -2722,6 +2866,60 @@ var Y = {
2722
2866
  Clear filter
2723
2867
  </div>
2724
2868
  ` : ""}
2869
+ <div class="ft-context-menu-separator"></div>
2870
+ <div class="ft-context-menu-item"
2871
+ @click=${() => {
2872
+ this._openCommentPopup(t, o.key, i, a), l();
2873
+ }}>
2874
+ ${this.getComment(t, o.key) ? "Edit Comment" : "Add Comment"}
2875
+ </div>
2876
+ ${this.getComment(t, o.key) ? n`
2877
+ <div class="ft-context-menu-item ft-context-menu-danger"
2878
+ @click=${() => {
2879
+ this.setComment(t, o.key, null), l();
2880
+ }}>
2881
+ Delete Comment
2882
+ </div>
2883
+ ` : ""}
2884
+ </div>
2885
+ `;
2886
+ }
2887
+ _openCommentPopup(e, t, n, r) {
2888
+ this._commentPopup = {
2889
+ dataIndex: e,
2890
+ colKey: t,
2891
+ x: n,
2892
+ y: r
2893
+ }, requestAnimationFrame(() => {
2894
+ document.addEventListener("mousedown", this._onCommentPopupOutsideClick);
2895
+ });
2896
+ }
2897
+ _commitCommentPopup() {
2898
+ if (!this._commentPopup) return;
2899
+ document.removeEventListener("mousedown", this._onCommentPopupOutsideClick);
2900
+ let e = (this.shadowRoot?.querySelector(".ft-comment-popup textarea"))?.value?.trim() || null;
2901
+ e !== this.getComment(this._commentPopup.dataIndex, this._commentPopup.colKey) && this.setComment(this._commentPopup.dataIndex, this._commentPopup.colKey, e), this._commentPopup = null;
2902
+ }
2903
+ _cancelCommentPopup() {
2904
+ this._commentPopup &&= (document.removeEventListener("mousedown", this._onCommentPopupOutsideClick), null);
2905
+ }
2906
+ _renderCommentPopup() {
2907
+ if (!this._commentPopup) return r;
2908
+ let { x: e, y: t } = this._commentPopup;
2909
+ return n`
2910
+ <div class="ft-comment-popup"
2911
+ style="position: fixed; left: ${e + 240 > window.innerWidth ? e - 240 : e}px; top: ${t + 150 > window.innerHeight ? t - 150 : t}px; z-index: 201;"
2912
+ @mousedown=${(e) => e.stopPropagation()}>
2913
+ <textarea class="ft-comment-popup-textarea"
2914
+ rows="4"
2915
+ placeholder="Add a comment… (Ctrl+Enter to save)"
2916
+ @keydown=${(e) => {
2917
+ e.key === "Escape" && (e.preventDefault(), this._cancelCommentPopup()), e.key === "Enter" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this._commitCommentPopup());
2918
+ }}></textarea>
2919
+ <div class="ft-comment-popup-buttons">
2920
+ <button class="ft-comment-popup-cancel" @click=${() => this._cancelCommentPopup()}>Cancel</button>
2921
+ <button class="ft-comment-popup-save" @click=${() => this._commitCommentPopup()}>Save</button>
2922
+ </div>
2725
2923
  </div>
2726
2924
  `;
2727
2925
  }
@@ -3523,6 +3721,7 @@ var Y = {
3523
3721
  ${y}
3524
3722
  ${this._renderHeaderContextMenu()}
3525
3723
  ${this._renderBodyContextMenu()}
3724
+ ${this._renderCommentPopup()}
3526
3725
  `;
3527
3726
  }
3528
3727
  _onSelectAllChange(e) {
@@ -3717,7 +3916,10 @@ var Y = {
3717
3916
  J([a({ type: Array })], $.prototype, "columns", void 0), J([a({
3718
3917
  type: Array,
3719
3918
  hasChanged: () => !0
3720
- })], $.prototype, "data", void 0), J([a({
3919
+ })], $.prototype, "data", null), J([a({
3920
+ type: Boolean,
3921
+ attribute: "clear-undo-on-data-change"
3922
+ })], $.prototype, "clearUndoOnDataChange", void 0), J([a({
3721
3923
  type: Number,
3722
3924
  attribute: "row-height"
3723
3925
  })], $.prototype, "rowHeight", void 0), J([a({
@@ -3753,6 +3955,6 @@ J([a({ type: Array })], $.prototype, "columns", void 0), J([a({
3753
3955
  })], $.prototype, "footerData", void 0), J([a({
3754
3956
  type: Number,
3755
3957
  attribute: "max-undo-size"
3756
- })], $.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([o()], $.prototype, "_isDragOver", void 0), $ = J([i("flex-table")], $);
3958
+ })], $.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([o()], $.prototype, "_commentPopup", void 0), J([o()], $.prototype, "_isDragOver", void 0), $ = J([i("flex-table")], $);
3757
3959
  //#endregion
3758
3960
  export { f as a, x as i, B as n, D as r, $ as t };
@@ -1,4 +1,4 @@
1
- import { LitElement } from 'lit';
1
+ import { LitElement, type PropertyValues } from 'lit';
2
2
  import type { ExportFormat } from './export/export.js';
3
3
  import type { CellPosition, CellRange } from './core/selection.js';
4
4
  import type { SortCriteria } from './core/sorting.js';
@@ -8,7 +8,21 @@ import type { TemplateResult } from 'lit';
8
8
  export declare class FlexTable extends LitElement {
9
9
  static styles: import("lit").CSSResult;
10
10
  columns: ColumnDefinition[];
11
- data: DataRow[];
11
+ private _data;
12
+ private _inUndoRedo;
13
+ /**
14
+ * The table data. When `clear-undo-on-data-change` is enabled, replacing this
15
+ * property externally (`table.data = newData`) will clear the undo/redo history.
16
+ * Internal undo/redo operations are exempt from this clearing.
17
+ * To manually clear history before data replacement, call `clearUndoHistory()`.
18
+ */
19
+ get data(): DataRow[];
20
+ set data(value: DataRow[]);
21
+ /**
22
+ * When true, replacing `data` externally automatically clears the undo/redo history.
23
+ * Default: false. Internal undo/redo operations are never affected.
24
+ */
25
+ clearUndoOnDataChange: boolean;
12
26
  rowHeight: number;
13
27
  showRowNumbers: boolean;
14
28
  theme: 'light' | 'dark' | undefined;
@@ -53,6 +67,7 @@ export declare class FlexTable extends LitElement {
53
67
  private _autocompleteState;
54
68
  private _headerMenu;
55
69
  private _bodyContextMenu;
70
+ private _commentPopup;
56
71
  private _viewDirty;
57
72
  private _isDragging;
58
73
  private _wasDrag;
@@ -111,6 +126,12 @@ export declare class FlexTable extends LitElement {
111
126
  * Useful when `data` array contents are mutated in-place without reassignment.
112
127
  */
113
128
  refreshData(): void;
129
+ /** Undo the most recent action. */
130
+ undo(): void;
131
+ /** Redo the most recently undone action. */
132
+ redo(): void;
133
+ /** Clear all undo/redo history. */
134
+ clearUndoHistory(): void;
114
135
  private _dispatchUndoStateEvent;
115
136
  private _dispatchFilterEvent;
116
137
  /**
@@ -172,6 +193,7 @@ export declare class FlexTable extends LitElement {
172
193
  * Pass an empty string or null to remove the comment.
173
194
  */
174
195
  setComment(dataIndex: number, colKey: string, text: string | null): void;
196
+ private _applyComment;
175
197
  /**
176
198
  * Get the comment for a cell (by data index and column key). Returns null if none.
177
199
  */
@@ -219,7 +241,7 @@ export declare class FlexTable extends LitElement {
219
241
  private _updateColOffsets;
220
242
  private get visibleColRange();
221
243
  protected willUpdate(changedProperties: Map<string, unknown>): void;
222
- protected updated(): void;
244
+ protected updated(changedProps: PropertyValues): void;
223
245
  /** Recompute filter → sort pipeline. */
224
246
  private _recomputeView;
225
247
  /** Map visual row index to data row index */
@@ -274,6 +296,11 @@ export declare class FlexTable extends LitElement {
274
296
  private _showHiddenBefore;
275
297
  private _renderHeaderContextMenu;
276
298
  private _renderBodyContextMenu;
299
+ private _openCommentPopup;
300
+ private _onCommentPopupOutsideClick;
301
+ private _commitCommentPopup;
302
+ private _cancelCommentPopup;
303
+ private _renderCommentPopup;
277
304
  private _applySortFromMenu;
278
305
  private _adjustFilterDropdown;
279
306
  private _onFilterBtnClick;
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r, t as i } from "./flex-table-C06mZOgA.js";
1
+ import { a as e, i as t, n, r, t as i } from "./flex-table-DPEaaiUQ.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-C06mZOgA.js";
1
+ import { t as e } from "./flex-table-DPEaaiUQ.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.16.1",
3
+ "version": "0.18.0",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",