@iyulab/flex-table 0.31.1 → 0.31.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.31.5] - 2026-09-04
4
+
5
+ ### Fixed
6
+
7
+ - **`0.31.3` and `0.31.4` both failed to reach npm for the same reason**: the
8
+ publish and demo-deploy workflows pinned Node 22, and npm's dependency
9
+ resolver crashes with a null-pointer error during a lockfile-less install
10
+ on that runner (this repo doesn't commit a `package-lock.json`) — the CI
11
+ workflow, which already runs Node 24, never hit it. Both workflows now run
12
+ Node 24 to match CI. No package code changed; this release exists to get
13
+ `0.31.3`'s content onto the registry with a working pipeline.
14
+
15
+ ## [0.31.4] - 2026-09-04
16
+
17
+ ### Fixed
18
+
19
+ - **`0.31.3`'s release pipeline never actually published to npm** — the
20
+ publish step's `npm install` crashed with a null-pointer error inside
21
+ npm's own dependency-resolution engine, unrelated to this package's
22
+ dependency graph (the lockfile is byte-for-byte unchanged from the prior,
23
+ successfully published `0.31.2`, and two separate retries reproduced the
24
+ identical crash). No package code changed; this release exists to get
25
+ `0.31.3`'s content onto the registry with a working pipeline.
26
+
27
+ ## [0.31.3] - 2026-09-04
28
+
29
+ ### Fixed
30
+
31
+ - **Header resize/reorder drag and row-number drag reorder could spuriously
32
+ toggle column sort or extend row selection on drop.** A native `click`
33
+ event the browser synthesizes after `mouseup` bubbles to the header
34
+ cell's own sort listener (or the row-number cell's select listener)
35
+ even though `stopPropagation()` on the drag handle's `mousedown` had
36
+ already fired — that call only blocks the `mousedown` itself, not the
37
+ separate `click` that follows. Both interactions now track whether the
38
+ gesture that just ended was a genuine resize/drag and skip the next
39
+ click when it was.
40
+
41
+ ## [0.31.2] - 2026-09-02
42
+
43
+ ### Fixed
44
+
45
+ - **`ColumnDefinition`'s README reference was missing three real, shipped
46
+ fields**: `headerAlign` (per-column header alignment, added in a later
47
+ commit than the rest of the snippet), `options`/`autocomplete` (select-type
48
+ columns and autocomplete editing, since `0.13.0`). The `select` value of
49
+ `ColumnType` was also missing from its inline comment. None of these had
50
+ any mention anywhere in the README — a consumer had no way to discover
51
+ select columns or autocomplete existed short of reading the source.
52
+
3
53
  ## [0.31.1] - 2026-09-01
4
54
 
5
55
  ### Fixed
package/README.md CHANGED
@@ -107,13 +107,16 @@ npm install @iyulab/flex-table
107
107
  interface ColumnDefinition {
108
108
  key: string; // Unique key matching data property names
109
109
  header: string; // Display header text
110
- type?: ColumnType; // 'text' | 'number' | 'boolean' | 'date' | 'datetime'
111
- width?: number; // Column width in pixels (default: 120)
110
+ type?: ColumnType; // 'text' | 'number' | 'boolean' | 'date' | 'datetime' | 'select' (any other string falls back to 'text')
111
+ width?: number; // Column width in pixels (default: auto)
112
112
  minWidth?: number; // Minimum width in pixels (default: 40, enforced in rendering)
113
113
  hidden?: boolean; // Hide column from view
114
114
  sortable?: boolean; // Enable sorting (default: true)
115
+ headerAlign?: 'start' | 'center' | 'end'; // Header label alignment (default: 'start'), independent of cell content alignment
115
116
  editable?: boolean; // Per-column edit control (follows global editable)
116
117
  pinned?: 'left' | 'right'; // Freeze column during horizontal scroll
118
+ options?: string[] | SelectOption[]; // Allowed values for type: 'select' (SelectOption = { label, value })
119
+ autocomplete?: boolean | 'strict'; // Suggest existing column values while editing; 'strict' rejects values not in the list
117
120
  format?: string | ((value, row, col) => string); // Display format, see "format vs renderer" below
118
121
  renderer?: CellRenderer; // Custom cell render: (value, row, col) => TemplateResult | string
119
122
  editor?: CellEditor; // Custom cell editor: (value, row, col) => TemplateResult
@@ -1497,7 +1497,7 @@ async function K(e) {
1497
1497
  };
1498
1498
  }
1499
1499
  //#endregion
1500
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/decorate.js
1500
+ //#region \0@oxc-project+runtime@0.148.0/helpers/esm/decorate.js
1501
1501
  function q(e, t, n, r) {
1502
1502
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
1503
1503
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
@@ -1515,7 +1515,7 @@ var J = {
1515
1515
  lte: "≤"
1516
1516
  }, Y = 120, X = 40, Z = 32, Q = 5, $ = class extends n {
1517
1517
  constructor(...e) {
1518
- super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new x(), this._editing = new S(), this._rowSelection = new C(), this._undo = new E(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, 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 = () => {
1518
+ super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = Z, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new x(), this._editing = new S(), this._rowSelection = new C(), this._undo = new E(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, 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._wasHeaderDrag = !1, this._wasRowDrag = !1, 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 = () => {
1519
1519
  this._commitCommentPopup();
1520
1520
  }, 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();
1521
1521
  }
@@ -2069,7 +2069,7 @@ var J = {
2069
2069
  this._readDensityTokens(), this._measureViewport(), this.shadowRoot && Array.isArray(this.shadowRoot.adoptedStyleSheets) && (this._baseStyleSheets = [...this.shadowRoot.adoptedStyleSheets]), this._syncStylesheets();
2070
2070
  }
2071
2071
  _syncStylesheets() {
2072
- !this.shadowRoot || !Array.isArray(this.shadowRoot.adoptedStyleSheets) || (this.shadowRoot.adoptedStyleSheets = [...this._baseStyleSheets, ...this.stylesheets]);
2072
+ this.shadowRoot && Array.isArray(this.shadowRoot.adoptedStyleSheets) && (this.shadowRoot.adoptedStyleSheets = [...this._baseStyleSheets, ...this.stylesheets]);
2073
2073
  }
2074
2074
  _readDensityTokens() {
2075
2075
  let e = getComputedStyle(this).getPropertyValue("--ft-row-height").trim();
@@ -2222,6 +2222,10 @@ var J = {
2222
2222
  this._isDragging && (this._wasDrag = !0, this._selection.setActiveWithRange(e, t), this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._dispatchSelectionEvent(), this.requestUpdate());
2223
2223
  }
2224
2224
  _onRowNumberClick(e) {
2225
+ if (this._wasRowDrag) {
2226
+ this._wasRowDrag = !1;
2227
+ return;
2228
+ }
2225
2229
  this._editing.current && this._commitEdit();
2226
2230
  let t = this.visibleColumns.length - 1;
2227
2231
  this._selection.setActive(e, 0), this._selection.setActiveWithRange(e, t), this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._dispatchSelectionEvent(), this.requestUpdate();
@@ -2739,6 +2743,10 @@ var J = {
2739
2743
  }));
2740
2744
  }
2741
2745
  _onHeaderClick(t, n) {
2746
+ if (this._wasHeaderDrag) {
2747
+ this._wasHeaderDrag = !1;
2748
+ return;
2749
+ }
2742
2750
  let r = this.visibleColumns.indexOf(n);
2743
2751
  if (t.ctrlKey || t.metaKey) {
2744
2752
  this._selectColumn(r);
@@ -2821,7 +2829,7 @@ var J = {
2821
2829
  ` : ""}
2822
2830
  <div class="ft-resize-handle"
2823
2831
  @mousedown=${(e) => {
2824
- e.stopPropagation(), this._onResizeStart(e, t);
2832
+ e.stopPropagation(), this._wasHeaderDrag = !0, this._onResizeStart(e, t);
2825
2833
  }}
2826
2834
  @dblclick=${(e) => this._onResizeAutoFit(e, t)}></div>
2827
2835
  </div>
@@ -3379,7 +3387,7 @@ var J = {
3379
3387
  let t = Math.abs(e.clientX - this._colDrag.startX);
3380
3388
  !this._colDrag.active && t > 5 && (this._colDrag.active = !0, this._startColumnGhost(e), this.requestUpdate()), this._colDrag.active && this._updateColumnDrag(e);
3381
3389
  }, i = (e) => {
3382
- document.removeEventListener("mousemove", r), document.removeEventListener("mouseup", i), this._colDrag?.active && this._finishColumnDrag(), this._colDrag?.ghost && this._colDrag.ghost.remove(), this._colDrag = null, this._colDragIndicatorLeft = null, this.requestUpdate();
3390
+ document.removeEventListener("mousemove", r), document.removeEventListener("mouseup", i), this._colDrag?.active && (this._wasHeaderDrag = !0, this._finishColumnDrag()), this._colDrag?.ghost && this._colDrag.ghost.remove(), this._colDrag = null, this._colDragIndicatorLeft = null, this.requestUpdate();
3383
3391
  };
3384
3392
  document.addEventListener("mousemove", r), document.addEventListener("mouseup", i);
3385
3393
  }
@@ -3546,7 +3554,7 @@ var J = {
3546
3554
  let n = Math.abs(e.clientY - this._rowDrag.startY);
3547
3555
  !this._rowDrag.active && n > 5 && (this._rowDrag.active = !0, this._startRowGhost(e, t), this.requestUpdate()), this._rowDrag.active && this._updateRowDrag(e);
3548
3556
  }, r = () => {
3549
- document.removeEventListener("mousemove", n), document.removeEventListener("mouseup", r), this._rowDrag?.active && this._finishRowDrag(), this._rowDrag?.ghost && this._rowDrag.ghost.remove(), this._rowDrag = null, this._rowDragIndicatorY = null, this.requestUpdate();
3557
+ document.removeEventListener("mousemove", n), document.removeEventListener("mouseup", r), this._rowDrag?.active && (this._wasRowDrag = !0, this._finishRowDrag()), this._rowDrag?.ghost && this._rowDrag.ghost.remove(), this._rowDrag = null, this._rowDragIndicatorY = null, this.requestUpdate();
3550
3558
  };
3551
3559
  document.addEventListener("mousemove", n), document.addEventListener("mouseup", r);
3552
3560
  }
@@ -128,6 +128,13 @@ export declare class FlexTable extends LitElement {
128
128
  private _wasDrag;
129
129
  private _resizing;
130
130
  private _resizeCleanup;
131
+ /** Set by a resize or a real column-drag reorder; consumed once by the next header `click` to
132
+ * suppress the browser's synthetic click that follows mouseup (same pattern as `_wasDrag` for
133
+ * cell-selection drags below). */
134
+ private _wasHeaderDrag;
135
+ /** Same as `_wasHeaderDrag`, for the row-number gutter's real row-drag reorder vs. its own
136
+ * `click`-to-select-row listener. */
137
+ private _wasRowDrag;
131
138
  private _colDrag;
132
139
  private _colDragIndicatorLeft;
133
140
  private _fillDrag;
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r, t as i } from "./flex-table-BH1lOINr.js";
1
+ import { a as e, i as t, n, r, t as i } from "./flex-table-D4W1C_QA.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-BH1lOINr.js";
1
+ import { t as e } from "./flex-table-D4W1C_QA.js";
2
2
  import t from "react";
3
3
  import { createComponent as n } from "@lit/react";
4
4
  var r = n({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.31.1",
3
+ "version": "0.31.5",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",