@iyulab/flex-table 0.17.0 → 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,7 +1480,9 @@ 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._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._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;
@@ -1946,7 +2012,7 @@ var Y = {
1946
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));
1947
2013
  }
1948
2014
  disconnectedCallback() {
1949
- 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);
1950
2016
  }
1951
2017
  firstUpdated() {
1952
2018
  this._measureViewport();
@@ -1986,8 +2052,11 @@ var Y = {
1986
2052
  willUpdate(e) {
1987
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);
1988
2054
  }
1989
- updated() {
1990
- 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
+ }
1991
2060
  }
1992
2061
  _recomputeView() {
1993
2062
  if (this.dataMode === "server") {
@@ -2053,7 +2122,7 @@ var Y = {
2053
2122
  composed: !0,
2054
2123
  cancelable: !0
2055
2124
  });
2056
- this.dispatchEvent(c), this.showContextMenu && !c.defaultPrevented && (this._bodyContextMenu = {
2125
+ this.dispatchEvent(c), this._cancelCommentPopup(), this.showContextMenu && !c.defaultPrevented && (this._bodyContextMenu = {
2057
2126
  rowIndex: a,
2058
2127
  colIndex: r,
2059
2128
  dataIndex: o,
@@ -2797,6 +2866,60 @@ var Y = {
2797
2866
  Clear filter
2798
2867
  </div>
2799
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>
2800
2923
  </div>
2801
2924
  `;
2802
2925
  }
@@ -3598,6 +3721,7 @@ var Y = {
3598
3721
  ${y}
3599
3722
  ${this._renderHeaderContextMenu()}
3600
3723
  ${this._renderBodyContextMenu()}
3724
+ ${this._renderCommentPopup()}
3601
3725
  `;
3602
3726
  }
3603
3727
  _onSelectAllChange(e) {
@@ -3831,6 +3955,6 @@ J([a({ type: Array })], $.prototype, "columns", void 0), J([a({
3831
3955
  })], $.prototype, "footerData", void 0), J([a({
3832
3956
  type: Number,
3833
3957
  attribute: "max-undo-size"
3834
- })], $.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")], $);
3835
3959
  //#endregion
3836
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';
@@ -67,6 +67,7 @@ export declare class FlexTable extends LitElement {
67
67
  private _autocompleteState;
68
68
  private _headerMenu;
69
69
  private _bodyContextMenu;
70
+ private _commentPopup;
70
71
  private _viewDirty;
71
72
  private _isDragging;
72
73
  private _wasDrag;
@@ -240,7 +241,7 @@ export declare class FlexTable extends LitElement {
240
241
  private _updateColOffsets;
241
242
  private get visibleColRange();
242
243
  protected willUpdate(changedProperties: Map<string, unknown>): void;
243
- protected updated(): void;
244
+ protected updated(changedProps: PropertyValues): void;
244
245
  /** Recompute filter → sort pipeline. */
245
246
  private _recomputeView;
246
247
  /** Map visual row index to data row index */
@@ -295,6 +296,11 @@ export declare class FlexTable extends LitElement {
295
296
  private _showHiddenBefore;
296
297
  private _renderHeaderContextMenu;
297
298
  private _renderBodyContextMenu;
299
+ private _openCommentPopup;
300
+ private _onCommentPopupOutsideClick;
301
+ private _commitCommentPopup;
302
+ private _cancelCommentPopup;
303
+ private _renderCommentPopup;
298
304
  private _applySortFromMenu;
299
305
  private _adjustFilterDropdown;
300
306
  private _onFilterBtnClick;
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r, t as i } from "./flex-table-Dwdo2HpR.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-Dwdo2HpR.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.17.0",
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",