@design.estate/dees-catalog 3.64.0 → 3.66.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.
@@ -163118,36 +163118,66 @@ var demoFunc29 = /* @__PURE__ */ __name(() => b2`
163118
163118
  <div class="demo-container">
163119
163119
  <div class="demo-section">
163120
163120
  <h2 class="demo-title">Basic Table with Actions</h2>
163121
- <p class="demo-description">A standard table with row actions, editable fields, and context menu support. Double-click on descriptions to edit. Grid lines are enabled by default.</p>
163121
+ <p class="demo-description">A standard table with row actions, editable cells, and context menu support. Double-click any cell to edit. Tab moves to the next editable cell, Enter to the row below, Esc cancels.</p>
163122
163122
  <dees-table
163123
163123
  heading1="Current Account Statement"
163124
163124
  heading2="Bunq - Payment Account 2 - April 2021"
163125
- .editableFields="${["description"]}"
163125
+ .columns=${[
163126
+ { key: "date", header: "Date", sortable: true, editable: true, editor: "date" },
163127
+ { key: "amount", header: "Amount", editable: true, editor: "text" },
163128
+ {
163129
+ key: "category",
163130
+ header: "Category",
163131
+ editable: true,
163132
+ editor: "dropdown",
163133
+ editorOptions: {
163134
+ options: [
163135
+ { option: "Office Supplies", key: "office" },
163136
+ { option: "Hardware", key: "hardware" },
163137
+ { option: "Software", key: "software" },
163138
+ { option: "Travel", key: "travel" }
163139
+ ]
163140
+ }
163141
+ },
163142
+ { key: "description", header: "Description", editable: true },
163143
+ { key: "reconciled", header: "OK", editable: true, editor: "checkbox" }
163144
+ ]}
163145
+ @cellEdit=${(e11) => console.log("cellEdit", e11.detail)}
163126
163146
  .data=${[
163127
163147
  {
163128
163148
  date: "2021-04-01",
163129
163149
  amount: "2464.65 \u20AC",
163130
- description: "Printing Paper (Office Supplies) - STAPLES BREMEN"
163150
+ category: "office",
163151
+ description: "Printing Paper - STAPLES BREMEN",
163152
+ reconciled: true
163131
163153
  },
163132
163154
  {
163133
163155
  date: "2021-04-02",
163134
163156
  amount: "165.65 \u20AC",
163135
- description: "Logitech Mouse (Hardware) - logi.com OnlineShop"
163157
+ category: "hardware",
163158
+ description: "Logitech Mouse - logi.com OnlineShop",
163159
+ reconciled: false
163136
163160
  },
163137
163161
  {
163138
163162
  date: "2021-04-03",
163139
163163
  amount: "2999,00 \u20AC",
163140
- description: "Macbook Pro 16inch (Hardware) - Apple.de OnlineShop"
163164
+ category: "hardware",
163165
+ description: "Macbook Pro 16inch - Apple.de OnlineShop",
163166
+ reconciled: false
163141
163167
  },
163142
163168
  {
163143
163169
  date: "2021-04-01",
163144
163170
  amount: "2464.65 \u20AC",
163145
- description: "Office-Supplies - STAPLES BREMEN"
163171
+ category: "office",
163172
+ description: "Office-Supplies - STAPLES BREMEN",
163173
+ reconciled: true
163146
163174
  },
163147
163175
  {
163148
163176
  date: "2021-04-01",
163149
163177
  amount: "2464.65 \u20AC",
163150
- description: "Office-Supplies - STAPLES BREMEN"
163178
+ category: "office",
163179
+ description: "Office-Supplies - STAPLES BREMEN",
163180
+ reconciled: true
163151
163181
  }
163152
163182
  ]}
163153
163183
  dataName="transactions"
@@ -163578,13 +163608,13 @@ var demoFunc29 = /* @__PURE__ */ __name(() => b2`
163578
163608
  <h2 class="demo-title">Column Filters + Sticky Header (New)</h2>
163579
163609
  <p class="demo-description">Per-column quick filters and sticky header with internal scroll. Try filtering the Name column. Uses --table-max-height var.</p>
163580
163610
  <style>
163581
- dees-table[sticky-header] { --table-max-height: 220px; }
163611
+ dees-table[fixed-height] { --table-max-height: 220px; }
163582
163612
  </style>
163583
163613
  <dees-table
163584
163614
  heading1="Employees"
163585
163615
  heading2="Quick filter per column + sticky header"
163586
163616
  .showColumnFilters=${true}
163587
- .stickyHeader=${true}
163617
+ .fixedHeight=${true}
163588
163618
  .columns=${[
163589
163619
  { key: "name", header: "Name", sortable: true },
163590
163620
  { key: "email", header: "Email", sortable: true },
@@ -163750,8 +163780,9 @@ var demoFunc29 = /* @__PURE__ */ __name(() => b2`
163750
163780
  </style>
163751
163781
  <dees-table
163752
163782
  id="scrollSmallHeight"
163753
- .stickyHeader=${true}
163754
- heading1="People Directory (Scrollable)"
163783
+ .fixedHeight=${true}
163784
+ .virtualized=${true}
163785
+ heading1="People Directory (Scrollable, Virtualized)"
163755
163786
  heading2="Forced scrolling with many items"
163756
163787
  .columns=${[
163757
163788
  { key: "id", header: "ID", sortable: true },
@@ -164172,32 +164203,32 @@ var tableStyles = [
164172
164203
  min-height: 24px;
164173
164204
  line-height: 24px;
164174
164205
  }
164175
- td input {
164176
- position: absolute;
164177
- top: 4px;
164178
- bottom: 4px;
164179
- left: 20px;
164180
- right: 20px;
164181
- width: calc(100% - 40px);
164182
- height: calc(100% - 8px);
164183
- padding: 0 12px;
164184
- outline: none;
164185
- border: 1px solid var(--dees-color-border-default);
164186
- border-radius: 6px;
164187
- background: ${cssManager.bdTheme("hsl(0 0% 100%)", "hsl(0 0% 9%)")};
164188
- color: var(--dees-color-text-primary);
164189
- font-family: inherit;
164190
- font-size: inherit;
164191
- font-weight: inherit;
164192
- transition: all 0.15s ease;
164193
- box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
164206
+
164207
+ /* Editable cell affordances */
164208
+ td.editable {
164209
+ cursor: text;
164194
164210
  }
164195
-
164196
- td input:focus {
164197
- border-color: ${cssManager.bdTheme("hsl(222.2 47.4% 51.2%)", "hsl(217.2 91.2% 59.8%)")};
164198
- outline: 2px solid transparent;
164199
- outline-offset: 2px;
164200
- box-shadow: 0 0 0 2px ${cssManager.bdTheme("hsl(222.2 47.4% 51.2% / 0.2)", "hsl(217.2 91.2% 59.8% / 0.2)")};
164211
+ td.focused {
164212
+ outline: 2px solid ${cssManager.bdTheme(
164213
+ "hsl(222.2 47.4% 51.2% / 0.6)",
164214
+ "hsl(217.2 91.2% 59.8% / 0.6)"
164215
+ )};
164216
+ outline-offset: -2px;
164217
+ }
164218
+ td.editingCell {
164219
+ padding: 0;
164220
+ }
164221
+ td.editingCell .innerCellContainer {
164222
+ padding: 0;
164223
+ line-height: normal;
164224
+ }
164225
+ td.editingCell dees-input-text,
164226
+ td.editingCell dees-input-checkbox,
164227
+ td.editingCell dees-input-dropdown,
164228
+ td.editingCell dees-input-datepicker,
164229
+ td.editingCell dees-input-tags {
164230
+ display: block;
164231
+ width: 100%;
164201
164232
  }
164202
164233
 
164203
164234
  /* filter row */
@@ -164550,7 +164581,7 @@ __name(compileLucenePredicate, "compileLucenePredicate");
164550
164581
  init_dist_ts30();
164551
164582
  init_dist_ts29();
164552
164583
  init_theme();
164553
- var _selectedIds_dec, _selectionMode_dec, _searchMode_dec, _fixedHeight_dec, _showSelectionCheckbox_dec, _showColumnFilters_dec, _columnFilters_dec, _filterText_dec, _sortBy_dec, _showGrid_dec, _showHorizontalLines_dec, _showVerticalLines_dec, _editableFields_dec, _selectedDataRow_dec, _reverseDisplayFunction_dec, _displayFunction_dec, _augmentFromDisplayFunction_dec, _rowKey_dec, _columns_dec, _dataActions_dec, _searchable_dec, _dataName_dec, _required_dec3, _disabled_dec3, _label_dec3, _key_dec2, _data_dec, _heading2_dec, _heading1_dec, _a42, _DeesTable_decorators, _init39, _heading1, _heading22, _data, _key2, _label3, _disabled3, _required3, _dataName, _searchable, _dataActions, _columns, _rowKey, _augmentFromDisplayFunction, _displayFunction, _reverseDisplayFunction, _selectedDataRow, _editableFields, _showVerticalLines, _showHorizontalLines, _showGrid, _sortBy, _filterText, _columnFilters, _showColumnFilters, _showSelectionCheckbox, _fixedHeight, _searchMode, _selectionMode, _selectedIds;
164584
+ var ___virtualRange_dec, ___floatingActive_dec, ___editingCell_dec, ___focusedCell_dec, _selectedIds_dec, _selectionMode_dec, _searchMode_dec, _fixedHeight_dec, _virtualOverscan_dec, _virtualized_dec, _showSelectionCheckbox_dec, _showColumnFilters_dec, _columnFilters_dec, _filterText_dec, _sortBy_dec, _showGrid_dec, _showHorizontalLines_dec, _showVerticalLines_dec, _selectedDataRow_dec, _reverseDisplayFunction_dec, _displayFunction_dec, _augmentFromDisplayFunction_dec, _rowKey_dec, _columns_dec, _dataActions_dec, _searchable_dec, _dataName_dec, _required_dec3, _disabled_dec3, _label_dec3, _key_dec2, _data_dec, _heading2_dec, _heading1_dec, _a42, _DeesTable_decorators, _init39, _heading1, _heading22, _data, _key2, _label3, _disabled3, _required3, _dataName, _searchable, _dataActions, _columns, _rowKey, _augmentFromDisplayFunction, _displayFunction, _reverseDisplayFunction, _selectedDataRow, _showVerticalLines, _showHorizontalLines, _showGrid, _sortBy, _filterText, _columnFilters, _showColumnFilters, _showSelectionCheckbox, _virtualized, _virtualOverscan, _fixedHeight, _searchMode, _selectionMode, _selectedIds, ___focusedCell, ___editingCell, ___floatingActive, ___virtualRange;
164554
164585
  function ordinalLabel(n12) {
164555
164586
  const s10 = ["th", "st", "nd", "rd"];
164556
164587
  const v5 = n12 % 100;
@@ -164585,8 +164616,6 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164585
164616
  attribute: false
164586
164617
  })], _selectedDataRow_dec = [n5({
164587
164618
  type: Object
164588
- })], _editableFields_dec = [n5({
164589
- type: Array
164590
164619
  })], _showVerticalLines_dec = [n5({
164591
164620
  type: Boolean,
164592
164621
  reflect: true,
@@ -164599,7 +164628,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164599
164628
  type: Boolean,
164600
164629
  reflect: true,
164601
164630
  attribute: "show-grid"
164602
- })], _sortBy_dec = [n5({ attribute: false })], _filterText_dec = [n5({ type: String })], _columnFilters_dec = [n5({ attribute: false })], _showColumnFilters_dec = [n5({ type: Boolean, attribute: "show-column-filters" })], _showSelectionCheckbox_dec = [n5({ type: Boolean, reflect: true, attribute: "show-selection-checkbox" })], _fixedHeight_dec = [n5({ type: Boolean, reflect: true, attribute: "fixed-height" })], _searchMode_dec = [n5({ type: String })], _selectionMode_dec = [n5({ type: String })], _selectedIds_dec = [n5({ attribute: false })], _a42) {
164631
+ })], _sortBy_dec = [n5({ attribute: false })], _filterText_dec = [n5({ type: String })], _columnFilters_dec = [n5({ attribute: false })], _showColumnFilters_dec = [n5({ type: Boolean, attribute: "show-column-filters" })], _showSelectionCheckbox_dec = [n5({ type: Boolean, reflect: true, attribute: "show-selection-checkbox" })], _virtualized_dec = [n5({ type: Boolean, reflect: true, attribute: "virtualized" })], _virtualOverscan_dec = [n5({ type: Number, attribute: "virtual-overscan" })], _fixedHeight_dec = [n5({ type: Boolean, reflect: true, attribute: "fixed-height" })], _searchMode_dec = [n5({ type: String })], _selectionMode_dec = [n5({ type: String })], _selectedIds_dec = [n5({ attribute: false })], ___focusedCell_dec = [r5()], ___editingCell_dec = [r5()], ___floatingActive_dec = [r5()], ___virtualRange_dec = [r5()], _a42) {
164603
164632
  constructor() {
164604
164633
  super();
164605
164634
  __privateAdd(this, _heading1, __runInitializers(_init39, 8, this, "heading 1")), __runInitializers(_init39, 11, this);
@@ -164619,24 +164648,25 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164619
164648
  __privateAdd(this, _displayFunction, __runInitializers(_init39, 60, this, /* @__PURE__ */ __name((itemArg) => itemArg, "displayFunction"))), __runInitializers(_init39, 63, this);
164620
164649
  __privateAdd(this, _reverseDisplayFunction, __runInitializers(_init39, 64, this, /* @__PURE__ */ __name((itemArg) => itemArg, "reverseDisplayFunction"))), __runInitializers(_init39, 67, this);
164621
164650
  __privateAdd(this, _selectedDataRow, __runInitializers(_init39, 68, this)), __runInitializers(_init39, 71, this);
164622
- __privateAdd(this, _editableFields, __runInitializers(_init39, 72, this, [])), __runInitializers(_init39, 75, this);
164623
- __privateAdd(this, _showVerticalLines, __runInitializers(_init39, 76, this, false)), __runInitializers(_init39, 79, this);
164624
- __privateAdd(this, _showHorizontalLines, __runInitializers(_init39, 80, this, false)), __runInitializers(_init39, 83, this);
164625
- __privateAdd(this, _showGrid, __runInitializers(_init39, 84, this, true)), __runInitializers(_init39, 87, this);
164651
+ __privateAdd(this, _showVerticalLines, __runInitializers(_init39, 72, this, false)), __runInitializers(_init39, 75, this);
164652
+ __privateAdd(this, _showHorizontalLines, __runInitializers(_init39, 76, this, false)), __runInitializers(_init39, 79, this);
164653
+ __privateAdd(this, _showGrid, __runInitializers(_init39, 80, this, true)), __runInitializers(_init39, 83, this);
164626
164654
  __publicField(this, "files", []);
164627
164655
  __publicField(this, "fileWeakMap", /* @__PURE__ */ new WeakMap());
164628
164656
  __publicField(this, "dataChangeSubject", new domtools_pluginexports_exports.smartrx.rxjs.Subject());
164629
- __privateAdd(this, _sortBy, __runInitializers(_init39, 88, this, [])), __runInitializers(_init39, 91, this);
164630
- __privateAdd(this, _filterText, __runInitializers(_init39, 92, this, "")), __runInitializers(_init39, 95, this);
164631
- __privateAdd(this, _columnFilters, __runInitializers(_init39, 96, this, {})), __runInitializers(_init39, 99, this);
164632
- __privateAdd(this, _showColumnFilters, __runInitializers(_init39, 100, this, false)), __runInitializers(_init39, 103, this);
164633
- __privateAdd(this, _showSelectionCheckbox, __runInitializers(_init39, 104, this, false)), __runInitializers(_init39, 107, this);
164634
- __privateAdd(this, _fixedHeight, __runInitializers(_init39, 108, this, false)), __runInitializers(_init39, 111, this);
164635
- __privateAdd(this, _searchMode, __runInitializers(_init39, 112, this, "table")), __runInitializers(_init39, 115, this);
164657
+ __privateAdd(this, _sortBy, __runInitializers(_init39, 84, this, [])), __runInitializers(_init39, 87, this);
164658
+ __privateAdd(this, _filterText, __runInitializers(_init39, 88, this, "")), __runInitializers(_init39, 91, this);
164659
+ __privateAdd(this, _columnFilters, __runInitializers(_init39, 92, this, {})), __runInitializers(_init39, 95, this);
164660
+ __privateAdd(this, _showColumnFilters, __runInitializers(_init39, 96, this, false)), __runInitializers(_init39, 99, this);
164661
+ __privateAdd(this, _showSelectionCheckbox, __runInitializers(_init39, 100, this, false)), __runInitializers(_init39, 103, this);
164662
+ __privateAdd(this, _virtualized, __runInitializers(_init39, 104, this, false)), __runInitializers(_init39, 107, this);
164663
+ __privateAdd(this, _virtualOverscan, __runInitializers(_init39, 108, this, 8)), __runInitializers(_init39, 111, this);
164664
+ __privateAdd(this, _fixedHeight, __runInitializers(_init39, 112, this, false)), __runInitializers(_init39, 115, this);
164665
+ __privateAdd(this, _searchMode, __runInitializers(_init39, 116, this, "table")), __runInitializers(_init39, 119, this);
164636
164666
  __publicField(this, "__searchTextSub");
164637
164667
  __publicField(this, "__searchModeSub");
164638
- __privateAdd(this, _selectionMode, __runInitializers(_init39, 116, this, "none")), __runInitializers(_init39, 119, this);
164639
- __privateAdd(this, _selectedIds, __runInitializers(_init39, 120, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 123, this);
164668
+ __privateAdd(this, _selectionMode, __runInitializers(_init39, 120, this, "none")), __runInitializers(_init39, 123, this);
164669
+ __privateAdd(this, _selectedIds, __runInitializers(_init39, 124, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 127, this);
164640
164670
  __publicField(this, "_rowIdMap", /* @__PURE__ */ new WeakMap());
164641
164671
  __publicField(this, "_rowIdCounter", 0);
164642
164672
  /**
@@ -164645,6 +164675,23 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164645
164675
  * can compute a contiguous range from this anchor.
164646
164676
  */
164647
164677
  __publicField(this, "__selectionAnchorId");
164678
+ __privateAdd(this, ___focusedCell, __runInitializers(_init39, 128, this)), __runInitializers(_init39, 131, this);
164679
+ __privateAdd(this, ___editingCell, __runInitializers(_init39, 132, this)), __runInitializers(_init39, 135, this);
164680
+ __privateAdd(this, ___floatingActive, __runInitializers(_init39, 136, this, false)), __runInitializers(_init39, 139, this);
164681
+ // ─── Render memoization ──────────────────────────────────────────────
164682
+ // These caches let render() short-circuit when the relevant inputs
164683
+ // (by reference) haven't changed. They are NOT @state — mutating them
164684
+ // must never trigger a re-render.
164685
+ __publicField(this, "__memoEffectiveCols");
164686
+ __publicField(this, "__memoViewData");
164687
+ /** Tracks the (data, columns) pair that `determineColumnWidths()` last sized for. */
164688
+ __publicField(this, "__columnsSizedFor");
164689
+ // ─── Virtualization state ────────────────────────────────────────────
164690
+ /** Estimated row height (px). Measured once from the first rendered row. */
164691
+ __publicField(this, "__rowHeight", 36);
164692
+ /** True once we've measured `__rowHeight` from a real DOM row. */
164693
+ __publicField(this, "__rowHeightMeasured", false);
164694
+ __privateAdd(this, ___virtualRange, __runInitializers(_init39, 140, this, { start: 0, end: 0 })), __runInitializers(_init39, 143, this);
164648
164695
  /**
164649
164696
  * Ctrl/Cmd+C copies the currently selected rows as a JSON array. Falls
164650
164697
  * back to copying the focused-row (`selectedDataRow`) if no multi
@@ -164652,30 +164699,182 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164652
164699
  * receive the copy.
164653
164700
  */
164654
164701
  __publicField(this, "__handleHostKeydown", /* @__PURE__ */ __name((eventArg) => {
164655
- const isCopy = (eventArg.metaKey || eventArg.ctrlKey) && (eventArg.key === "c" || eventArg.key === "C");
164656
- if (!isCopy) return;
164657
164702
  const path2 = eventArg.composedPath?.() || [];
164703
+ let inEditor = false;
164658
164704
  for (const t9 of path2) {
164659
164705
  const tag = t9?.tagName;
164660
- if (tag === "INPUT" || tag === "TEXTAREA") return;
164661
- if (t9?.isContentEditable) return;
164706
+ if (tag === "INPUT" || tag === "TEXTAREA" || t9?.isContentEditable) {
164707
+ inEditor = true;
164708
+ break;
164709
+ }
164662
164710
  }
164663
- const rows = [];
164664
- if (this.selectedIds.size > 0) {
164665
- for (const r11 of this.data) if (this.selectedIds.has(this.getRowId(r11))) rows.push(r11);
164666
- } else if (this.selectedDataRow) {
164667
- rows.push(this.selectedDataRow);
164711
+ const isCopy = (eventArg.metaKey || eventArg.ctrlKey) && (eventArg.key === "c" || eventArg.key === "C");
164712
+ if (isCopy) {
164713
+ if (inEditor) return;
164714
+ const rows = [];
164715
+ if (this.selectedIds.size > 0) {
164716
+ for (const r11 of this.data) if (this.selectedIds.has(this.getRowId(r11))) rows.push(r11);
164717
+ } else if (this.selectedDataRow) {
164718
+ rows.push(this.selectedDataRow);
164719
+ }
164720
+ if (rows.length === 0) return;
164721
+ eventArg.preventDefault();
164722
+ this.__writeRowsAsJson(rows);
164723
+ return;
164724
+ }
164725
+ if (inEditor || this.__editingCell) return;
164726
+ switch (eventArg.key) {
164727
+ case "ArrowLeft":
164728
+ eventArg.preventDefault();
164729
+ this.moveFocusedCell(-1, 0, false);
164730
+ return;
164731
+ case "ArrowRight":
164732
+ eventArg.preventDefault();
164733
+ this.moveFocusedCell(1, 0, false);
164734
+ return;
164735
+ case "ArrowUp":
164736
+ eventArg.preventDefault();
164737
+ this.moveFocusedCell(0, -1, false);
164738
+ return;
164739
+ case "ArrowDown":
164740
+ eventArg.preventDefault();
164741
+ this.moveFocusedCell(0, 1, false);
164742
+ return;
164743
+ case "Enter":
164744
+ case "F2": {
164745
+ if (!this.__focusedCell) return;
164746
+ const view = this._lastViewData ?? [];
164747
+ const item = view.find((r11) => this.getRowId(r11) === this.__focusedCell.rowId);
164748
+ if (!item) return;
164749
+ const allCols = Array.isArray(this.columns) && this.columns.length > 0 ? computeEffectiveColumns(
164750
+ this.columns,
164751
+ this.augmentFromDisplayFunction,
164752
+ this.displayFunction,
164753
+ this.data
164754
+ ) : computeColumnsFromDisplayFunction(this.displayFunction, this.data);
164755
+ const col = allCols.find((c11) => String(c11.key) === this.__focusedCell.colKey);
164756
+ if (!col || !this.__isColumnEditable(col)) return;
164757
+ eventArg.preventDefault();
164758
+ this.startEditing(item, col);
164759
+ return;
164760
+ }
164761
+ case "Escape":
164762
+ if (this.__focusedCell) {
164763
+ this.__focusedCell = void 0;
164764
+ this.requestUpdate();
164765
+ }
164766
+ return;
164767
+ default:
164768
+ return;
164668
164769
  }
164669
- if (rows.length === 0) return;
164670
- eventArg.preventDefault();
164671
- this.__writeRowsAsJson(rows);
164672
164770
  }, "__handleHostKeydown"));
164673
164771
  // ─── Floating header (page-sticky) lifecycle ─────────────────────────
164674
164772
  __publicField(this, "__floatingResizeObserver");
164675
164773
  __publicField(this, "__floatingScrollHandler");
164676
- __publicField(this, "__floatingActive", false);
164774
+ // __floatingActive is declared as a @state field above so its toggle
164775
+ // triggers re-rendering of the floating-header clone subtree.
164677
164776
  __publicField(this, "__scrollAncestors", []);
164678
164777
  __publicField(this, "__debounceTimer");
164778
+ __publicField(this, "__onTbodyClick", /* @__PURE__ */ __name((eventArg) => {
164779
+ if (this.__isInEditor(eventArg) || this.__isInActionsCol(eventArg)) return;
164780
+ const cell2 = this.__resolveCell(eventArg);
164781
+ if (!cell2) return;
164782
+ const view = this._lastViewData ?? [];
164783
+ if (cell2.col.editable || cell2.col.editor) {
164784
+ this.__focusedCell = {
164785
+ rowId: this.getRowId(cell2.item),
164786
+ colKey: String(cell2.col.key)
164787
+ };
164788
+ }
164789
+ this.handleRowClick(eventArg, cell2.item, cell2.rowIdx, view);
164790
+ }, "__onTbodyClick"));
164791
+ __publicField(this, "__onTbodyDblclick", /* @__PURE__ */ __name((eventArg) => {
164792
+ if (this.__isInEditor(eventArg) || this.__isInActionsCol(eventArg)) return;
164793
+ const cell2 = this.__resolveCell(eventArg);
164794
+ if (!cell2) return;
164795
+ const isEditable = !!(cell2.col.editable || cell2.col.editor);
164796
+ if (isEditable) {
164797
+ eventArg.stopPropagation();
164798
+ this.startEditing(cell2.item, cell2.col);
164799
+ return;
164800
+ }
164801
+ const dblAction = this.dataActions.find((a5) => a5.type?.includes("doubleClick"));
164802
+ if (dblAction) dblAction.actionFunc({ item: cell2.item, table: this });
164803
+ }, "__onTbodyDblclick"));
164804
+ __publicField(this, "__onTbodyMousedown", /* @__PURE__ */ __name((eventArg) => {
164805
+ if (eventArg.shiftKey && this.selectionMode !== "single") eventArg.preventDefault();
164806
+ }, "__onTbodyMousedown"));
164807
+ __publicField(this, "__onTbodyContextmenu", /* @__PURE__ */ __name((eventArg) => {
164808
+ if (this.__isInActionsCol(eventArg)) return;
164809
+ const row = this.__resolveRow(eventArg);
164810
+ if (!row) return;
164811
+ const item = row.item;
164812
+ if (!this.isRowSelected(item)) {
164813
+ this.selectedDataRow = item;
164814
+ this.selectedIds.clear();
164815
+ this.selectedIds.add(this.getRowId(item));
164816
+ this.__selectionAnchorId = this.getRowId(item);
164817
+ this.emitSelectionChange();
164818
+ this.requestUpdate();
164819
+ }
164820
+ const userItems = this.getActionsForType("contextmenu").map(
164821
+ (action) => ({
164822
+ name: action.name,
164823
+ iconName: action.iconName,
164824
+ action: /* @__PURE__ */ __name(async () => {
164825
+ await action.actionFunc({ item, table: this });
164826
+ return null;
164827
+ }, "action")
164828
+ })
164829
+ );
164830
+ const defaultItems = [
164831
+ {
164832
+ name: this.selectedIds.size > 1 ? `Copy ${this.selectedIds.size} rows as JSON` : "Copy row as JSON",
164833
+ iconName: "lucide:Copy",
164834
+ action: /* @__PURE__ */ __name(async () => {
164835
+ this.copySelectionAsJson(item);
164836
+ return null;
164837
+ }, "action")
164838
+ }
164839
+ ];
164840
+ DeesContextmenu.openContextMenuWithOptions(eventArg, [...userItems, ...defaultItems]);
164841
+ }, "__onTbodyContextmenu"));
164842
+ __publicField(this, "__onTbodyDragenter", /* @__PURE__ */ __name((eventArg) => {
164843
+ eventArg.preventDefault();
164844
+ eventArg.stopPropagation();
164845
+ const row = this.__resolveRow(eventArg);
164846
+ if (!row) return;
164847
+ const tr3 = (eventArg.composedPath?.() || []).find(
164848
+ (t9) => t9?.tagName === "TR"
164849
+ );
164850
+ if (tr3) setTimeout(() => tr3.classList.add("hasAttachment"), 0);
164851
+ }, "__onTbodyDragenter"));
164852
+ __publicField(this, "__onTbodyDragleave", /* @__PURE__ */ __name((eventArg) => {
164853
+ eventArg.preventDefault();
164854
+ eventArg.stopPropagation();
164855
+ const tr3 = (eventArg.composedPath?.() || []).find(
164856
+ (t9) => t9?.tagName === "TR"
164857
+ );
164858
+ if (tr3) tr3.classList.remove("hasAttachment");
164859
+ }, "__onTbodyDragleave"));
164860
+ __publicField(this, "__onTbodyDragover", /* @__PURE__ */ __name((eventArg) => {
164861
+ eventArg.preventDefault();
164862
+ }, "__onTbodyDragover"));
164863
+ __publicField(this, "__onTbodyDrop", /* @__PURE__ */ __name(async (eventArg) => {
164864
+ eventArg.preventDefault();
164865
+ const row = this.__resolveRow(eventArg);
164866
+ if (!row) return;
164867
+ const item = row.item;
164868
+ const newFiles = [];
164869
+ for (const file of Array.from(eventArg.dataTransfer.files)) {
164870
+ this.files.push(file);
164871
+ newFiles.push(file);
164872
+ this.requestUpdate();
164873
+ }
164874
+ const existing = this.fileWeakMap.get(item);
164875
+ if (!existing) this.fileWeakMap.set(item, newFiles);
164876
+ else existing.push(...newFiles);
164877
+ }, "__onTbodyDrop"));
164679
164878
  if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "0");
164680
164879
  this.addEventListener("keydown", this.__handleHostKeydown);
164681
164880
  }
@@ -164708,24 +164907,83 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164708
164907
  } catch {
164709
164908
  }
164710
164909
  }
164711
- render() {
164910
+ /**
164911
+ * Returns the effective column schema, memoized by reference of the inputs
164912
+ * that affect it. Avoids re-running `computeEffectiveColumnsFn` /
164913
+ * `computeColumnsFromDisplayFunctionFn` on every Lit update.
164914
+ */
164915
+ __getEffectiveColumns() {
164712
164916
  const usingColumns = Array.isArray(this.columns) && this.columns.length > 0;
164713
- const effectiveColumns = usingColumns ? computeEffectiveColumns(this.columns, this.augmentFromDisplayFunction, this.displayFunction, this.data) : computeColumnsFromDisplayFunction(this.displayFunction, this.data);
164714
- const lucenePred = compileLucenePredicate(
164715
- this.filterText,
164716
- this.searchMode === "data" ? "data" : "table",
164717
- effectiveColumns
164718
- );
164719
- const viewData = getViewData(
164917
+ const cache = this.__memoEffectiveCols;
164918
+ if (cache && cache.columns === this.columns && cache.augment === this.augmentFromDisplayFunction && cache.displayFunction === this.displayFunction && cache.data === this.data) {
164919
+ return cache.out;
164920
+ }
164921
+ const out = usingColumns ? computeEffectiveColumns(
164922
+ this.columns,
164923
+ this.augmentFromDisplayFunction,
164924
+ this.displayFunction,
164925
+ this.data
164926
+ ) : computeColumnsFromDisplayFunction(this.displayFunction, this.data);
164927
+ this.__memoEffectiveCols = {
164928
+ columns: this.columns,
164929
+ augment: this.augmentFromDisplayFunction,
164930
+ displayFunction: this.displayFunction,
164931
+ data: this.data,
164932
+ out
164933
+ };
164934
+ return out;
164935
+ }
164936
+ /**
164937
+ * Returns the sorted/filtered view of the data, memoized by reference of
164938
+ * everything that affects it. Avoids re-running the lucene compiler and
164939
+ * the sort/filter pipeline on every render.
164940
+ */
164941
+ __getViewData(effectiveColumns) {
164942
+ const searchMode = this.searchMode === "data" ? "data" : "table";
164943
+ const cache = this.__memoViewData;
164944
+ if (cache && cache.data === this.data && cache.sortBy === this.sortBy && cache.filterText === this.filterText && cache.columnFilters === this.columnFilters && cache.searchMode === searchMode && cache.effectiveColumns === effectiveColumns) {
164945
+ return cache.out;
164946
+ }
164947
+ const lucenePred = compileLucenePredicate(this.filterText, searchMode, effectiveColumns);
164948
+ const out = getViewData(
164720
164949
  this.data,
164721
164950
  effectiveColumns,
164722
164951
  this.sortBy,
164723
164952
  this.filterText,
164724
164953
  this.columnFilters,
164725
- this.searchMode === "data" ? "data" : "table",
164954
+ searchMode,
164726
164955
  lucenePred || void 0
164727
164956
  );
164957
+ this.__memoViewData = {
164958
+ data: this.data,
164959
+ sortBy: this.sortBy,
164960
+ filterText: this.filterText,
164961
+ columnFilters: this.columnFilters,
164962
+ searchMode,
164963
+ effectiveColumns,
164964
+ out
164965
+ };
164966
+ return out;
164967
+ }
164968
+ render() {
164969
+ const effectiveColumns = this.__getEffectiveColumns();
164970
+ const viewData = this.__getViewData(effectiveColumns);
164728
164971
  this._lastViewData = viewData;
164972
+ const useVirtual = this.virtualized && viewData.length > 0;
164973
+ let renderRows = viewData;
164974
+ let renderStart = 0;
164975
+ let topSpacerHeight = 0;
164976
+ let bottomSpacerHeight = 0;
164977
+ if (useVirtual) {
164978
+ const range2 = this.__virtualRange;
164979
+ const start = Math.max(0, range2.start);
164980
+ const end3 = Math.min(viewData.length, range2.end || 0);
164981
+ const initialEnd = end3 > 0 ? end3 : Math.min(viewData.length, this.virtualOverscan * 2 + 16);
164982
+ renderStart = start;
164983
+ renderRows = viewData.slice(start, initialEnd);
164984
+ topSpacerHeight = start * this.__rowHeight;
164985
+ bottomSpacerHeight = Math.max(0, viewData.length - initialEnd) * this.__rowHeight;
164986
+ }
164729
164987
  return b2`
164730
164988
  <dees-tile>
164731
164989
  <div slot="header" class="header">
@@ -164793,88 +165051,23 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164793
165051
  <thead>
164794
165052
  ${this.renderHeaderRows(effectiveColumns)}
164795
165053
  </thead>
164796
- <tbody>
164797
- ${viewData.map((itemArg, rowIndex) => {
164798
- const getTr = /* @__PURE__ */ __name((elementArg) => {
164799
- if (elementArg.tagName === "TR") {
164800
- return elementArg;
164801
- } else {
164802
- return getTr(elementArg.parentElement);
164803
- }
164804
- }, "getTr");
165054
+ <tbody
165055
+ @click=${this.__onTbodyClick}
165056
+ @dblclick=${this.__onTbodyDblclick}
165057
+ @mousedown=${this.__onTbodyMousedown}
165058
+ @contextmenu=${this.__onTbodyContextmenu}
165059
+ @dragenter=${this.__onTbodyDragenter}
165060
+ @dragleave=${this.__onTbodyDragleave}
165061
+ @dragover=${this.__onTbodyDragover}
165062
+ @drop=${this.__onTbodyDrop}
165063
+ >
165064
+ ${useVirtual && topSpacerHeight > 0 ? b2`<tr aria-hidden="true" style="height:${topSpacerHeight}px"><td></td></tr>` : b2``}
165065
+ ${renderRows.map((itemArg, sliceIdx) => {
165066
+ const rowIndex = renderStart + sliceIdx;
165067
+ const rowId = this.getRowId(itemArg);
164805
165068
  return b2`
164806
165069
  <tr
164807
- @click=${(e11) => this.handleRowClick(e11, itemArg, rowIndex, viewData)}
164808
- @mousedown=${(e11) => {
164809
- if (e11.shiftKey && this.selectionMode !== "single") e11.preventDefault();
164810
- }}
164811
- @dragenter=${async (eventArg) => {
164812
- eventArg.preventDefault();
164813
- eventArg.stopPropagation();
164814
- const realTarget = getTr(eventArg.target);
164815
- setTimeout(() => {
164816
- realTarget.classList.add("hasAttachment");
164817
- }, 0);
164818
- }}
164819
- @dragleave=${async (eventArg) => {
164820
- eventArg.preventDefault();
164821
- eventArg.stopPropagation();
164822
- const realTarget = getTr(eventArg.target);
164823
- realTarget.classList.remove("hasAttachment");
164824
- }}
164825
- @dragover=${async (eventArg) => {
164826
- eventArg.preventDefault();
164827
- }}
164828
- @drop=${async (eventArg) => {
164829
- eventArg.preventDefault();
164830
- const newFiles = [];
164831
- for (const file of Array.from(eventArg.dataTransfer.files)) {
164832
- this.files.push(file);
164833
- newFiles.push(file);
164834
- this.requestUpdate();
164835
- }
164836
- const result = this.fileWeakMap.get(itemArg);
164837
- if (!result) {
164838
- this.fileWeakMap.set(itemArg, newFiles);
164839
- } else {
164840
- result.push(...newFiles);
164841
- }
164842
- }}
164843
- @contextmenu=${async (eventArg) => {
164844
- if (!this.isRowSelected(itemArg)) {
164845
- this.selectedDataRow = itemArg;
164846
- this.selectedIds.clear();
164847
- this.selectedIds.add(this.getRowId(itemArg));
164848
- this.__selectionAnchorId = this.getRowId(itemArg);
164849
- this.emitSelectionChange();
164850
- this.requestUpdate();
164851
- }
164852
- const userItems = this.getActionsForType("contextmenu").map((action) => ({
164853
- name: action.name,
164854
- iconName: action.iconName,
164855
- action: /* @__PURE__ */ __name(async () => {
164856
- await action.actionFunc({
164857
- item: itemArg,
164858
- table: this
164859
- });
164860
- return null;
164861
- }, "action")
164862
- }));
164863
- const defaultItems = [
164864
- {
164865
- name: this.selectedIds.size > 1 ? `Copy ${this.selectedIds.size} rows as JSON` : "Copy row as JSON",
164866
- iconName: "lucide:Copy",
164867
- action: /* @__PURE__ */ __name(async () => {
164868
- this.copySelectionAsJson(itemArg);
164869
- return null;
164870
- }, "action")
164871
- }
164872
- ];
164873
- DeesContextmenu.openContextMenuWithOptions(eventArg, [
164874
- ...userItems,
164875
- ...defaultItems
164876
- ]);
164877
- }}
165070
+ data-row-idx=${rowIndex}
164878
165071
  class="${itemArg === this.selectedDataRow || this.isRowSelected(itemArg) ? "selected" : ""}"
164879
165072
  >
164880
165073
  ${this.showSelectionCheckbox ? b2`<td style="width:42px; text-align:center;">
@@ -164890,20 +165083,22 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164890
165083
  const value2 = getCellValue(itemArg, col, this.displayFunction);
164891
165084
  const content3 = col.renderer ? col.renderer(value2, itemArg, { rowIndex, colIndex, column: col }) : value2;
164892
165085
  const editKey = String(col.key);
165086
+ const isEditable = !!(col.editable || col.editor);
165087
+ const isFocused = this.__focusedCell?.rowId === rowId && this.__focusedCell?.colKey === editKey;
165088
+ const isEditing = this.__editingCell?.rowId === rowId && this.__editingCell?.colKey === editKey;
165089
+ const cellClasses = [
165090
+ isEditable ? "editable" : "",
165091
+ isFocused && !isEditing ? "focused" : "",
165092
+ isEditing ? "editingCell" : ""
165093
+ ].filter(Boolean).join(" ");
164893
165094
  return b2`
164894
165095
  <td
164895
- @dblclick=${(e11) => {
164896
- const dblAction = this.dataActions.find(
164897
- (actionArg) => actionArg.type?.includes("doubleClick")
164898
- );
164899
- if (this.editableFields.includes(editKey)) {
164900
- this.handleCellEditing(e11, itemArg, editKey);
164901
- } else if (dblAction) {
164902
- dblAction.actionFunc({ item: itemArg, table: this });
164903
- }
164904
- }}
165096
+ class=${cellClasses}
165097
+ data-col-key=${editKey}
164905
165098
  >
164906
- <div class="innerCellContainer">${content3}</div>
165099
+ <div class="innerCellContainer">
165100
+ ${isEditing ? this.renderCellEditor(itemArg, col) : content3}
165101
+ </div>
164907
165102
  </td>
164908
165103
  `;
164909
165104
  })}
@@ -164932,15 +165127,16 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164932
165127
  })()}
164933
165128
  </tr>`;
164934
165129
  })}
165130
+ ${useVirtual && bottomSpacerHeight > 0 ? b2`<tr aria-hidden="true" style="height:${bottomSpacerHeight}px"><td></td></tr>` : b2``}
164935
165131
  </tbody>
164936
165132
  </table>
164937
165133
  </div>
164938
165134
  <div class="floatingHeader" aria-hidden="true">
164939
- <table>
164940
- <thead>
164941
- ${this.renderHeaderRows(effectiveColumns)}
164942
- </thead>
164943
- </table>
165135
+ ${this.__floatingActive ? b2`<table>
165136
+ <thead>
165137
+ ${this.renderHeaderRows(effectiveColumns)}
165138
+ </thead>
165139
+ </table>` : b2``}
164944
165140
  </div>
164945
165141
  ` : b2` <div class="noDataSet">No data set!</div> `}
164946
165142
  <div slot="footer" class="footer">
@@ -165100,24 +165296,33 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165100
165296
  }
165101
165297
  setupFloatingHeader() {
165102
165298
  this.teardownFloatingHeader();
165103
- if (this.fixedHeight) return;
165299
+ if (this.fixedHeight && !this.virtualized) return;
165104
165300
  const realTable = this.__realTableEl;
165105
165301
  if (!realTable) return;
165106
165302
  this.__scrollAncestors = this.__collectScrollAncestors();
165107
165303
  const tableScrollEl = this.shadowRoot?.querySelector(".tableScroll");
165108
165304
  if (tableScrollEl) {
165109
- this.__scrollAncestors.unshift({ target: tableScrollEl, scrollsY: false, scrollsX: true });
165305
+ this.__scrollAncestors.unshift({
165306
+ target: tableScrollEl,
165307
+ scrollsY: this.fixedHeight,
165308
+ scrollsX: true
165309
+ });
165110
165310
  }
165111
165311
  this.__floatingResizeObserver = new ResizeObserver(() => {
165112
- this.__syncFloatingHeader();
165312
+ if (!this.fixedHeight) this.__syncFloatingHeader();
165313
+ if (this.virtualized) this.__computeVirtualRange();
165113
165314
  });
165114
165315
  this.__floatingResizeObserver.observe(realTable);
165115
- this.__floatingScrollHandler = () => this.__syncFloatingHeader();
165316
+ this.__floatingScrollHandler = () => {
165317
+ if (!this.fixedHeight) this.__syncFloatingHeader();
165318
+ if (this.virtualized) this.__computeVirtualRange();
165319
+ };
165116
165320
  for (const a5 of this.__scrollAncestors) {
165117
165321
  a5.target.addEventListener("scroll", this.__floatingScrollHandler, { passive: true });
165118
165322
  }
165119
165323
  window.addEventListener("resize", this.__floatingScrollHandler, { passive: true });
165120
- this.__syncFloatingHeader();
165324
+ if (!this.fixedHeight) this.__syncFloatingHeader();
165325
+ if (this.virtualized) this.__computeVirtualRange();
165121
165326
  }
165122
165327
  teardownFloatingHeader() {
165123
165328
  this.__floatingResizeObserver?.disconnect();
@@ -165134,24 +165339,106 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165134
165339
  const fh = this.__floatingHeaderEl;
165135
165340
  if (fh) fh.classList.remove("active");
165136
165341
  }
165342
+ // ─── Virtualization ─────────────────────────────────────────────────
165343
+ /**
165344
+ * Computes the visible row range based on the table's position in its
165345
+ * nearest vertical scroll ancestor (or the viewport). Updates
165346
+ * `__virtualRange` if it changed; that triggers a Lit re-render.
165347
+ */
165348
+ __computeVirtualRange() {
165349
+ if (!this.virtualized) return;
165350
+ const view = this._lastViewData ?? [];
165351
+ const total = view.length;
165352
+ if (total === 0) {
165353
+ if (this.__virtualRange.start !== 0 || this.__virtualRange.end !== 0) {
165354
+ this.__virtualRange = { start: 0, end: 0 };
165355
+ }
165356
+ return;
165357
+ }
165358
+ const realTable = this.__realTableEl;
165359
+ if (!realTable) return;
165360
+ const tableRect = realTable.getBoundingClientRect();
165361
+ let viewportTop = 0;
165362
+ let viewportBottom = window.innerHeight;
165363
+ for (const a5 of this.__scrollAncestors) {
165364
+ if (a5.target === window || !a5.scrollsY) continue;
165365
+ const r11 = a5.target.getBoundingClientRect();
165366
+ const cs = getComputedStyle(a5.target);
165367
+ const bt = parseFloat(cs.borderTopWidth) || 0;
165368
+ const bb = parseFloat(cs.borderBottomWidth) || 0;
165369
+ viewportTop = Math.max(viewportTop, r11.top + bt);
165370
+ viewportBottom = Math.min(viewportBottom, r11.bottom - bb);
165371
+ }
165372
+ const rowH = Math.max(1, this.__rowHeight);
165373
+ const headerHeight = realTable.tHead?.getBoundingClientRect().height ?? 0;
165374
+ const bodyTop = tableRect.top + headerHeight;
165375
+ const offsetIntoBody = Math.max(0, viewportTop - bodyTop);
165376
+ const visiblePx = Math.max(0, viewportBottom - Math.max(viewportTop, bodyTop));
165377
+ const startRaw = Math.floor(offsetIntoBody / rowH);
165378
+ const visibleCount = Math.ceil(visiblePx / rowH) + 1;
165379
+ const start = Math.max(0, startRaw - this.virtualOverscan);
165380
+ const end3 = Math.min(total, startRaw + visibleCount + this.virtualOverscan);
165381
+ if (start !== this.__virtualRange.start || end3 !== this.__virtualRange.end) {
165382
+ this.__virtualRange = { start, end: end3 };
165383
+ }
165384
+ }
165385
+ /**
165386
+ * Measures the height of the first rendered body row and stores it for
165387
+ * subsequent virtualization math. Idempotent — only measures once per
165388
+ * `data`/`columns` pair (cleared in `updated()` when those change).
165389
+ */
165390
+ __measureRowHeight() {
165391
+ if (!this.virtualized || this.__rowHeightMeasured) return;
165392
+ const tbody3 = this.shadowRoot?.querySelector("tbody");
165393
+ if (!tbody3) return;
165394
+ const firstRow = Array.from(tbody3.rows).find((r11) => r11.hasAttribute("data-row-idx"));
165395
+ if (!firstRow) return;
165396
+ const h8 = firstRow.getBoundingClientRect().height;
165397
+ if (h8 > 0) {
165398
+ this.__rowHeight = h8;
165399
+ this.__rowHeightMeasured = true;
165400
+ }
165401
+ }
165137
165402
  /**
165138
165403
  * Single function that drives both activation and geometry of the floating
165139
- * header. Called on scroll, resize, table-resize, and after each render.
165404
+ * header. Called on scroll, resize, table-resize, and after relevant
165405
+ * renders.
165406
+ *
165407
+ * Activation is decided from the *real* header geometry, so this function
165408
+ * works even when the clone subtree hasn't been rendered yet (it's only
165409
+ * rendered when `__floatingActive` is true). The first activation flips
165410
+ * `__floatingActive`; the next render materializes the clone; the next
165411
+ * call here mirrors widths and positions.
165140
165412
  */
165141
165413
  __syncFloatingHeader() {
165142
165414
  const fh = this.__floatingHeaderEl;
165143
165415
  const realTable = this.__realTableEl;
165144
- const floatTable = this.__floatingTableEl;
165145
- if (!fh || !realTable || !floatTable) return;
165416
+ if (!fh || !realTable) return;
165146
165417
  const tableRect = realTable.getBoundingClientRect();
165147
165418
  const stick = this.__getStickContext();
165148
- floatTable.style.tableLayout = realTable.style.tableLayout || "auto";
165149
165419
  const realHeadRows = realTable.tHead?.rows;
165150
- const floatHeadRows = floatTable.tHead?.rows;
165151
165420
  let headerHeight = 0;
165421
+ if (realHeadRows) {
165422
+ for (let r11 = 0; r11 < realHeadRows.length; r11++) {
165423
+ headerHeight += realHeadRows[r11].getBoundingClientRect().height;
165424
+ }
165425
+ }
165426
+ const shouldBeActive = tableRect.top < stick.top && tableRect.bottom > stick.top + Math.min(headerHeight, 1);
165427
+ if (shouldBeActive !== this.__floatingActive) {
165428
+ this.__floatingActive = shouldBeActive;
165429
+ fh.classList.toggle("active", shouldBeActive);
165430
+ if (shouldBeActive) {
165431
+ this.updateComplete.then(() => this.__syncFloatingHeader());
165432
+ return;
165433
+ }
165434
+ }
165435
+ if (!shouldBeActive) return;
165436
+ const floatTable = this.__floatingTableEl;
165437
+ if (!floatTable) return;
165438
+ floatTable.style.tableLayout = realTable.style.tableLayout || "auto";
165439
+ const floatHeadRows = floatTable.tHead?.rows;
165152
165440
  if (realHeadRows && floatHeadRows) {
165153
165441
  for (let r11 = 0; r11 < realHeadRows.length && r11 < floatHeadRows.length; r11++) {
165154
- headerHeight += realHeadRows[r11].getBoundingClientRect().height;
165155
165442
  const realCells = realHeadRows[r11].cells;
165156
165443
  const floatCells = floatHeadRows[r11].cells;
165157
165444
  for (let c11 = 0; c11 < realCells.length && c11 < floatCells.length; c11++) {
@@ -165162,12 +165449,6 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165162
165449
  }
165163
165450
  }
165164
165451
  }
165165
- const shouldBeActive = tableRect.top < stick.top && tableRect.bottom > stick.top + Math.min(headerHeight, 1);
165166
- if (shouldBeActive !== this.__floatingActive) {
165167
- this.__floatingActive = shouldBeActive;
165168
- fh.classList.toggle("active", shouldBeActive);
165169
- }
165170
- if (!shouldBeActive) return;
165171
165452
  const clipLeft = Math.max(tableRect.left, stick.left);
165172
165453
  const clipRight = Math.min(tableRect.right, stick.right);
165173
165454
  const clipWidth = Math.max(0, clipRight - clipLeft);
@@ -165185,15 +165466,25 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165185
165466
  }
165186
165467
  async updated(changedProperties) {
165187
165468
  super.updated(changedProperties);
165188
- this.determineColumnWidths();
165189
- if (changedProperties.has("fixedHeight") || changedProperties.has("data") || changedProperties.has("columns") || !this.__floatingScrollHandler) {
165190
- if (!this.fixedHeight && this.data.length > 0) {
165469
+ const dataOrColsChanged = !this.__columnsSizedFor || this.__columnsSizedFor.data !== this.data || this.__columnsSizedFor.columns !== this.columns;
165470
+ if (dataOrColsChanged) {
165471
+ this.__columnsSizedFor = { data: this.data, columns: this.columns };
165472
+ this.determineColumnWidths();
165473
+ this.__rowHeightMeasured = false;
165474
+ }
165475
+ if (this.virtualized) {
165476
+ this.__measureRowHeight();
165477
+ this.__computeVirtualRange();
165478
+ }
165479
+ if (changedProperties.has("fixedHeight") || changedProperties.has("virtualized") || changedProperties.has("data") || changedProperties.has("columns") || !this.__floatingScrollHandler) {
165480
+ const needsScrollWatchers = (!this.fixedHeight || this.virtualized) && this.data.length > 0;
165481
+ if (needsScrollWatchers) {
165191
165482
  this.setupFloatingHeader();
165192
165483
  } else {
165193
165484
  this.teardownFloatingHeader();
165194
165485
  }
165195
165486
  }
165196
- if (!this.fixedHeight && this.data.length > 0) {
165487
+ if (!this.fixedHeight && this.data.length > 0 && (this.__floatingActive || dataOrColsChanged)) {
165197
165488
  this.__syncFloatingHeader();
165198
165489
  }
165199
165490
  if (this.searchable) {
@@ -165640,6 +165931,65 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165640
165931
  this.emitSelectionChange();
165641
165932
  this.requestUpdate();
165642
165933
  }
165934
+ // ─── Delegated tbody event handlers ─────────────────────────────────
165935
+ // Hoisted from per-<tr> closures to a single set of handlers on <tbody>.
165936
+ // Cuts ~7 closure allocations per row per render. Each handler resolves
165937
+ // the source row via `data-row-idx` (and `data-col-key` for cell-level
165938
+ // events) using the latest `_lastViewData`.
165939
+ __resolveRow(eventArg) {
165940
+ const path2 = eventArg.composedPath?.() || [];
165941
+ let tr3 = null;
165942
+ for (const t9 of path2) {
165943
+ const el = t9;
165944
+ if (el?.tagName === "TR" && el.hasAttribute("data-row-idx")) {
165945
+ tr3 = el;
165946
+ break;
165947
+ }
165948
+ }
165949
+ if (!tr3) return null;
165950
+ const rowIdx = Number(tr3.getAttribute("data-row-idx"));
165951
+ const view = this._lastViewData ?? [];
165952
+ const item = view[rowIdx];
165953
+ if (!item) return null;
165954
+ return { item, rowIdx };
165955
+ }
165956
+ __resolveCell(eventArg) {
165957
+ const row = this.__resolveRow(eventArg);
165958
+ if (!row) return null;
165959
+ const path2 = eventArg.composedPath?.() || [];
165960
+ let td = null;
165961
+ for (const t9 of path2) {
165962
+ const el = t9;
165963
+ if (el?.tagName === "TD" && el.hasAttribute("data-col-key")) {
165964
+ td = el;
165965
+ break;
165966
+ }
165967
+ }
165968
+ if (!td) return null;
165969
+ const colKey = td.getAttribute("data-col-key");
165970
+ const cols = this.__getEffectiveColumns();
165971
+ const col = cols.find((c11) => String(c11.key) === colKey);
165972
+ if (!col) return null;
165973
+ return { item: row.item, rowIdx: row.rowIdx, col };
165974
+ }
165975
+ __isInActionsCol(eventArg) {
165976
+ const path2 = eventArg.composedPath?.() || [];
165977
+ for (const t9 of path2) {
165978
+ const el = t9;
165979
+ if (el?.classList?.contains("actionsCol")) return true;
165980
+ }
165981
+ return false;
165982
+ }
165983
+ __isInEditor(eventArg) {
165984
+ const path2 = eventArg.composedPath?.() || [];
165985
+ for (const t9 of path2) {
165986
+ const el = t9;
165987
+ const tag = el?.tagName;
165988
+ if (tag === "INPUT" || tag === "TEXTAREA" || el?.isContentEditable) return true;
165989
+ if (tag && tag.startsWith("DEES-INPUT-")) return true;
165990
+ }
165991
+ return false;
165992
+ }
165643
165993
  /**
165644
165994
  * Handles row clicks with file-manager style selection semantics:
165645
165995
  * - plain click: select only this row, set anchor
@@ -165755,38 +166105,193 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165755
166105
  }
165756
166106
  return actions;
165757
166107
  }
165758
- async handleCellEditing(event, itemArg, key2) {
165759
- await this.domtoolsPromise;
165760
- const target = event.target;
165761
- const originalColor = target.style.color;
165762
- target.style.color = "transparent";
165763
- const transformedItem = this.displayFunction(itemArg);
165764
- const initialValue = transformedItem[key2] ?? itemArg[key2] ?? "";
165765
- const input = document.createElement("input");
165766
- input.type = "text";
165767
- input.value = initialValue;
165768
- const blurInput = /* @__PURE__ */ __name(async (blurArg = true, saveArg = false) => {
165769
- if (blurArg) {
165770
- input.blur();
165771
- }
165772
- if (saveArg) {
165773
- itemArg[key2] = input.value;
165774
- this.changeSubject.next(this);
165775
- }
165776
- input.remove();
165777
- target.style.color = originalColor;
165778
- this.requestUpdate();
165779
- }, "blurInput");
165780
- input.addEventListener("blur", () => {
165781
- blurInput(false, false);
166108
+ // ─── Cell editing ─────────────────────────────────────────────────────
166109
+ /** True if the column has any in-cell editor configured. */
166110
+ __isColumnEditable(col) {
166111
+ return !!(col.editable || col.editor);
166112
+ }
166113
+ /** Effective columns filtered to those that can be edited (visible only). */
166114
+ __editableColumns(effectiveColumns) {
166115
+ return effectiveColumns.filter((c11) => !c11.hidden && this.__isColumnEditable(c11));
166116
+ }
166117
+ /**
166118
+ * Opens the editor on the given cell. Sets focus + editing state and
166119
+ * focuses the freshly rendered editor on the next frame.
166120
+ */
166121
+ startEditing(item, col) {
166122
+ if (!this.__isColumnEditable(col)) return;
166123
+ const rowId = this.getRowId(item);
166124
+ const colKey = String(col.key);
166125
+ this.__focusedCell = { rowId, colKey };
166126
+ this.__editingCell = { rowId, colKey };
166127
+ this.requestUpdate();
166128
+ this.updateComplete.then(() => {
166129
+ const el = this.shadowRoot?.querySelector(
166130
+ ".editingCell dees-input-text, .editingCell dees-input-checkbox, .editingCell dees-input-dropdown, .editingCell dees-input-datepicker, .editingCell dees-input-tags"
166131
+ );
166132
+ el?.focus?.();
165782
166133
  });
165783
- input.addEventListener("keydown", (e11) => {
165784
- if (e11.key === "Enter") {
165785
- blurInput(true, true);
166134
+ }
166135
+ /** Closes the editor without committing. */
166136
+ cancelCellEdit() {
166137
+ this.__editingCell = void 0;
166138
+ this.requestUpdate();
166139
+ }
166140
+ /**
166141
+ * Commits an editor value to the row. Runs `parse` then `validate`. On
166142
+ * validation failure, fires `cellEditError` and leaves the editor open.
166143
+ * On success, mutates `data` in place, fires `cellEdit`, and closes the
166144
+ * editor.
166145
+ */
166146
+ commitCellEdit(item, col, editorValue) {
166147
+ const key2 = String(col.key);
166148
+ const oldValue = item[col.key];
166149
+ const parsed = col.parse ? col.parse(editorValue, item) : editorValue;
166150
+ if (col.validate) {
166151
+ const result = col.validate(parsed, item);
166152
+ if (typeof result === "string") {
166153
+ this.dispatchEvent(
166154
+ new CustomEvent("cellEditError", {
166155
+ detail: { row: item, key: key2, value: parsed, message: result },
166156
+ bubbles: true,
166157
+ composed: true
166158
+ })
166159
+ );
166160
+ return;
165786
166161
  }
165787
- });
165788
- target.appendChild(input);
165789
- input.focus();
166162
+ }
166163
+ if (parsed !== oldValue) {
166164
+ item[col.key] = parsed;
166165
+ this.dispatchEvent(
166166
+ new CustomEvent("cellEdit", {
166167
+ detail: { row: item, key: key2, oldValue, newValue: parsed },
166168
+ bubbles: true,
166169
+ composed: true
166170
+ })
166171
+ );
166172
+ this.changeSubject.next(this);
166173
+ }
166174
+ this.__editingCell = void 0;
166175
+ this.requestUpdate();
166176
+ }
166177
+ /** Renders the appropriate dees-input-* component for this column. */
166178
+ renderCellEditor(item, col) {
166179
+ const raw2 = item[col.key];
166180
+ const value2 = col.format ? col.format(raw2, item) : raw2;
166181
+ const editorType = col.editor ?? "text";
166182
+ const onTextCommit = /* @__PURE__ */ __name((target) => this.commitCellEdit(item, col, target.value), "onTextCommit");
166183
+ switch (editorType) {
166184
+ case "checkbox":
166185
+ return b2`<dees-input-checkbox
166186
+ .value=${!!value2}
166187
+ @newValue=${(e11) => {
166188
+ e11.stopPropagation();
166189
+ this.commitCellEdit(item, col, e11.detail);
166190
+ }}
166191
+ ></dees-input-checkbox>`;
166192
+ case "dropdown": {
166193
+ const options2 = col.editorOptions?.options ?? [];
166194
+ const selected = options2.find((o13) => (o13?.option ?? o13?.key ?? o13) === value2) ?? null;
166195
+ return b2`<dees-input-dropdown
166196
+ .options=${options2}
166197
+ .selectedOption=${selected}
166198
+ @selectedOption=${(e11) => {
166199
+ e11.stopPropagation();
166200
+ const detail = e11.detail;
166201
+ const newRaw = detail?.option ?? detail?.key ?? detail;
166202
+ this.commitCellEdit(item, col, newRaw);
166203
+ }}
166204
+ ></dees-input-dropdown>`;
166205
+ }
166206
+ case "date":
166207
+ return b2`<dees-input-datepicker
166208
+ .value=${value2}
166209
+ @focusout=${(e11) => onTextCommit(e11.target)}
166210
+ @keydown=${(e11) => this.__handleEditorKey(e11, item, col)}
166211
+ ></dees-input-datepicker>`;
166212
+ case "tags":
166213
+ return b2`<dees-input-tags
166214
+ .value=${value2 ?? []}
166215
+ @focusout=${(e11) => onTextCommit(e11.target)}
166216
+ @keydown=${(e11) => this.__handleEditorKey(e11, item, col)}
166217
+ ></dees-input-tags>`;
166218
+ case "number":
166219
+ case "text":
166220
+ default:
166221
+ return b2`<dees-input-text
166222
+ .value=${value2 == null ? "" : String(value2)}
166223
+ @focusout=${(e11) => onTextCommit(e11.target)}
166224
+ @keydown=${(e11) => this.__handleEditorKey(e11, item, col)}
166225
+ ></dees-input-text>`;
166226
+ }
166227
+ }
166228
+ /**
166229
+ * Centralized keydown handler for text-style editors. Handles Esc (cancel),
166230
+ * Enter (commit + move down) and Tab/Shift+Tab (commit + move horizontally).
166231
+ */
166232
+ __handleEditorKey(eventArg, item, col) {
166233
+ if (eventArg.key === "Escape") {
166234
+ eventArg.preventDefault();
166235
+ eventArg.stopPropagation();
166236
+ this.cancelCellEdit();
166237
+ this.focus();
166238
+ } else if (eventArg.key === "Enter") {
166239
+ eventArg.preventDefault();
166240
+ eventArg.stopPropagation();
166241
+ const target = eventArg.target;
166242
+ this.commitCellEdit(item, col, target.value);
166243
+ this.moveFocusedCell(0, 1, true);
166244
+ } else if (eventArg.key === "Tab") {
166245
+ eventArg.preventDefault();
166246
+ eventArg.stopPropagation();
166247
+ const target = eventArg.target;
166248
+ this.commitCellEdit(item, col, target.value);
166249
+ this.moveFocusedCell(eventArg.shiftKey ? -1 : 1, 0, true);
166250
+ }
166251
+ }
166252
+ /**
166253
+ * Moves the focused cell by `dx` columns and `dy` rows along the editable
166254
+ * grid. Wraps row-end → next row when moving horizontally. If
166255
+ * `andStartEditing` is true, opens the editor on the new cell.
166256
+ */
166257
+ moveFocusedCell(dx, dy, andStartEditing) {
166258
+ const view = this._lastViewData ?? [];
166259
+ if (view.length === 0) return;
166260
+ const allCols = Array.isArray(this.columns) && this.columns.length > 0 ? computeEffectiveColumns(this.columns, this.augmentFromDisplayFunction, this.displayFunction, this.data) : computeColumnsFromDisplayFunction(this.displayFunction, this.data);
166261
+ const editableCols = this.__editableColumns(allCols);
166262
+ if (editableCols.length === 0) return;
166263
+ let rowIdx = 0;
166264
+ let colIdx = 0;
166265
+ if (this.__focusedCell) {
166266
+ rowIdx = view.findIndex((r11) => this.getRowId(r11) === this.__focusedCell.rowId);
166267
+ colIdx = editableCols.findIndex((c11) => String(c11.key) === this.__focusedCell.colKey);
166268
+ if (rowIdx < 0) rowIdx = 0;
166269
+ if (colIdx < 0) colIdx = 0;
166270
+ }
166271
+ if (dx !== 0) {
166272
+ colIdx += dx;
166273
+ while (colIdx >= editableCols.length) {
166274
+ colIdx -= editableCols.length;
166275
+ rowIdx += 1;
166276
+ }
166277
+ while (colIdx < 0) {
166278
+ colIdx += editableCols.length;
166279
+ rowIdx -= 1;
166280
+ }
166281
+ }
166282
+ if (dy !== 0) rowIdx += dy;
166283
+ if (rowIdx < 0 || rowIdx >= view.length) {
166284
+ this.cancelCellEdit();
166285
+ return;
166286
+ }
166287
+ const item = view[rowIdx];
166288
+ const col = editableCols[colIdx];
166289
+ this.__focusedCell = { rowId: this.getRowId(item), colKey: String(col.key) };
166290
+ if (andStartEditing) {
166291
+ this.startEditing(item, col);
166292
+ } else {
166293
+ this.requestUpdate();
166294
+ }
165790
166295
  }
165791
166296
  };
165792
166297
  _init39 = __decoratorStart(_a42);
@@ -165806,7 +166311,6 @@ _augmentFromDisplayFunction = new WeakMap();
165806
166311
  _displayFunction = new WeakMap();
165807
166312
  _reverseDisplayFunction = new WeakMap();
165808
166313
  _selectedDataRow = new WeakMap();
165809
- _editableFields = new WeakMap();
165810
166314
  _showVerticalLines = new WeakMap();
165811
166315
  _showHorizontalLines = new WeakMap();
165812
166316
  _showGrid = new WeakMap();
@@ -165815,10 +166319,16 @@ _filterText = new WeakMap();
165815
166319
  _columnFilters = new WeakMap();
165816
166320
  _showColumnFilters = new WeakMap();
165817
166321
  _showSelectionCheckbox = new WeakMap();
166322
+ _virtualized = new WeakMap();
166323
+ _virtualOverscan = new WeakMap();
165818
166324
  _fixedHeight = new WeakMap();
165819
166325
  _searchMode = new WeakMap();
165820
166326
  _selectionMode = new WeakMap();
165821
166327
  _selectedIds = new WeakMap();
166328
+ ___focusedCell = new WeakMap();
166329
+ ___editingCell = new WeakMap();
166330
+ ___floatingActive = new WeakMap();
166331
+ ___virtualRange = new WeakMap();
165822
166332
  __decorateElement(_init39, 4, "heading1", _heading1_dec, _DeesTable, _heading1);
165823
166333
  __decorateElement(_init39, 4, "heading2", _heading2_dec, _DeesTable, _heading22);
165824
166334
  __decorateElement(_init39, 4, "data", _data_dec, _DeesTable, _data);
@@ -165835,7 +166345,6 @@ __decorateElement(_init39, 4, "augmentFromDisplayFunction", _augmentFromDisplayF
165835
166345
  __decorateElement(_init39, 4, "displayFunction", _displayFunction_dec, _DeesTable, _displayFunction);
165836
166346
  __decorateElement(_init39, 4, "reverseDisplayFunction", _reverseDisplayFunction_dec, _DeesTable, _reverseDisplayFunction);
165837
166347
  __decorateElement(_init39, 4, "selectedDataRow", _selectedDataRow_dec, _DeesTable, _selectedDataRow);
165838
- __decorateElement(_init39, 4, "editableFields", _editableFields_dec, _DeesTable, _editableFields);
165839
166348
  __decorateElement(_init39, 4, "showVerticalLines", _showVerticalLines_dec, _DeesTable, _showVerticalLines);
165840
166349
  __decorateElement(_init39, 4, "showHorizontalLines", _showHorizontalLines_dec, _DeesTable, _showHorizontalLines);
165841
166350
  __decorateElement(_init39, 4, "showGrid", _showGrid_dec, _DeesTable, _showGrid);
@@ -165844,10 +166353,16 @@ __decorateElement(_init39, 4, "filterText", _filterText_dec, _DeesTable, _filter
165844
166353
  __decorateElement(_init39, 4, "columnFilters", _columnFilters_dec, _DeesTable, _columnFilters);
165845
166354
  __decorateElement(_init39, 4, "showColumnFilters", _showColumnFilters_dec, _DeesTable, _showColumnFilters);
165846
166355
  __decorateElement(_init39, 4, "showSelectionCheckbox", _showSelectionCheckbox_dec, _DeesTable, _showSelectionCheckbox);
166356
+ __decorateElement(_init39, 4, "virtualized", _virtualized_dec, _DeesTable, _virtualized);
166357
+ __decorateElement(_init39, 4, "virtualOverscan", _virtualOverscan_dec, _DeesTable, _virtualOverscan);
165847
166358
  __decorateElement(_init39, 4, "fixedHeight", _fixedHeight_dec, _DeesTable, _fixedHeight);
165848
166359
  __decorateElement(_init39, 4, "searchMode", _searchMode_dec, _DeesTable, _searchMode);
165849
166360
  __decorateElement(_init39, 4, "selectionMode", _selectionMode_dec, _DeesTable, _selectionMode);
165850
166361
  __decorateElement(_init39, 4, "selectedIds", _selectedIds_dec, _DeesTable, _selectedIds);
166362
+ __decorateElement(_init39, 4, "__focusedCell", ___focusedCell_dec, _DeesTable, ___focusedCell);
166363
+ __decorateElement(_init39, 4, "__editingCell", ___editingCell_dec, _DeesTable, ___editingCell);
166364
+ __decorateElement(_init39, 4, "__floatingActive", ___floatingActive_dec, _DeesTable, ___floatingActive);
166365
+ __decorateElement(_init39, 4, "__virtualRange", ___virtualRange_dec, _DeesTable, ___virtualRange);
165851
166366
  _DeesTable = __decorateElement(_init39, 0, "DeesTable", _DeesTable_decorators, _DeesTable);
165852
166367
  __name(_DeesTable, "DeesTable");
165853
166368
  __publicField(_DeesTable, "demo", demoFunc29);
@@ -199694,7 +200209,7 @@ init_group_runtime();
199694
200209
  // ts_web/00_commitinfo_data.ts
199695
200210
  var commitinfo = {
199696
200211
  name: "@design.estate/dees-catalog",
199697
- version: "3.64.0",
200212
+ version: "3.66.0",
199698
200213
  description: "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript."
199699
200214
  };
199700
200215
  export {
@@ -201667,4 +202182,4 @@ ibantools/jsnext/ibantools.js:
201667
202182
  * @preferred
201668
202183
  *)
201669
202184
  */
201670
- //# sourceMappingURL=bundle-1775572474370.js.map
202185
+ //# sourceMappingURL=bundle-1775577430289.js.map