@design.estate/dees-catalog 3.69.1 → 3.70.1

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.
@@ -145391,9 +145391,7 @@ __publicField(_DeesModal, "styles", [
145391
145391
  }
145392
145392
 
145393
145393
  .heading .header-button dees-icon {
145394
- width: 14px;
145395
- height: 14px;
145396
- display: block;
145394
+ font-size: 14px;
145397
145395
  }
145398
145396
 
145399
145397
  .content {
@@ -169250,6 +169248,69 @@ var demoFunc29 = /* @__PURE__ */ __name(() => b2`
169250
169248
  ]}
169251
169249
  ></dees-table>
169252
169250
  </div>
169251
+
169252
+ <dees-demowrapper .runAfterRender=${async (elementArg) => {
169253
+ const tableEl = elementArg.querySelector("#demoLiveFlash");
169254
+ if (!tableEl) return;
169255
+ if (tableEl.__liveFlashTimerId) {
169256
+ window.clearInterval(tableEl.__liveFlashTimerId);
169257
+ }
169258
+ const tick = /* @__PURE__ */ __name(() => {
169259
+ if (!Array.isArray(tableEl.data) || tableEl.data.length === 0) return;
169260
+ const next2 = tableEl.data.map((r11) => ({ ...r11 }));
169261
+ const count2 = 1 + Math.floor(Math.random() * 3);
169262
+ for (let i11 = 0; i11 < count2; i11++) {
169263
+ const idx = Math.floor(Math.random() * next2.length);
169264
+ const delta = +((Math.random() * 2 - 1) * 3).toFixed(2);
169265
+ const newPrice = Math.max(1, +(next2[idx].price + delta).toFixed(2));
169266
+ next2[idx] = {
169267
+ ...next2[idx],
169268
+ price: newPrice,
169269
+ change: delta,
169270
+ updatedAt: (/* @__PURE__ */ new Date()).toLocaleTimeString()
169271
+ };
169272
+ }
169273
+ tableEl.data = next2;
169274
+ }, "tick");
169275
+ tableEl.__liveFlashTimerId = window.setInterval(tick, 1500);
169276
+ }}>
169277
+ <div class="demo-section">
169278
+ <h2 class="demo-title">Live Updates with Flash Highlighting</h2>
169279
+ <p class="demo-description">
169280
+ Opt-in cell-flash via <code>highlight-updates="flash"</code>. The ticker below mutates
169281
+ random rows every 1.5s and reassigns <code>.data</code>. Updated cells briefly flash
169282
+ amber and fade out. Requires <code>rowKey</code> (here <code>"symbol"</code>). Honors
169283
+ <code>prefers-reduced-motion</code>. Row selection persists across updates — click a
169284
+ row, then watch it stay selected as the data churns.
169285
+ </p>
169286
+ <dees-table
169287
+ id="demoLiveFlash"
169288
+ .rowKey=${"symbol"}
169289
+ highlight-updates="flash"
169290
+ .selectionMode=${"multi"}
169291
+ heading1="Live Market Feed"
169292
+ heading2="Flashing cells indicate updated values"
169293
+ .columns=${[
169294
+ { key: "symbol", header: "Symbol", sortable: true },
169295
+ { key: "price", header: "Price", sortable: true },
169296
+ { key: "change", header: "\u0394", sortable: true },
169297
+ { key: "updatedAt", header: "Updated" }
169298
+ ]}
169299
+ .data=${[
169300
+ { symbol: "AAPL", price: 182.52, change: 0, updatedAt: "\u2014" },
169301
+ { symbol: "MSFT", price: 414.18, change: 0, updatedAt: "\u2014" },
169302
+ { symbol: "GOOG", price: 168.74, change: 0, updatedAt: "\u2014" },
169303
+ { symbol: "AMZN", price: 186.13, change: 0, updatedAt: "\u2014" },
169304
+ { symbol: "TSLA", price: 248.5, change: 0, updatedAt: "\u2014" },
169305
+ { symbol: "NVDA", price: 877.35, change: 0, updatedAt: "\u2014" },
169306
+ { symbol: "META", price: 492.96, change: 0, updatedAt: "\u2014" },
169307
+ { symbol: "NFLX", price: 605.88, change: 0, updatedAt: "\u2014" },
169308
+ { symbol: "AMD", price: 165.24, change: 0, updatedAt: "\u2014" },
169309
+ { symbol: "INTC", price: 42.15, change: 0, updatedAt: "\u2014" }
169310
+ ]}
169311
+ ></dees-table>
169312
+ </div>
169313
+ </dees-demowrapper>
169253
169314
  </div>
169254
169315
  </div>
169255
169316
  `, "demoFunc");
@@ -169628,6 +169689,72 @@ var tableStyles = [
169628
169689
  line-height: 24px;
169629
169690
  }
169630
169691
 
169692
+ /* ---- Cell flash highlighting (opt-in via highlight-updates="flash") ----
169693
+ Bloomberg/TradingView-style: the text itself briefly takes an accent
169694
+ color then fades back to the default. No background tint, no layout
169695
+ shift, no weight change. Readable, modern, subtle.
169696
+ Consumers can override per instance:
169697
+ dees-table#myTable { --dees-table-flash-color: hsl(142 76% 40%); }
169698
+ */
169699
+ :host {
169700
+ --dees-table-flash-color: ${cssManager.bdTheme(
169701
+ "hsl(32 95% 44%)",
169702
+ "hsl(45 93% 62%)"
169703
+ )};
169704
+ --dees-table-flash-easing: cubic-bezier(0.22, 0.61, 0.36, 1);
169705
+ }
169706
+
169707
+ .innerCellContainer.flashing {
169708
+ animation: dees-table-cell-flash
169709
+ var(--dees-table-flash-duration, 900ms)
169710
+ var(--dees-table-flash-easing);
169711
+ }
169712
+
169713
+ /* Hold the accent color briefly, then fade back to the theme's default
169714
+ text color. Inherits to child text and to SVG icons that use
169715
+ currentColor. Cells with explicit color overrides in renderers are
169716
+ intentionally unaffected. */
169717
+ @keyframes dees-table-cell-flash {
169718
+ 0%,
169719
+ 35% { color: var(--dees-table-flash-color); }
169720
+ 100% { color: var(--dees-color-text-primary); }
169721
+ }
169722
+
169723
+ @media (prefers-reduced-motion: reduce) {
169724
+ .innerCellContainer.flashing {
169725
+ animation: none;
169726
+ color: var(--dees-table-flash-color);
169727
+ }
169728
+ }
169729
+
169730
+ /* Dev-time warning banner shown when highlight-updates="flash" but
169731
+ rowKey is missing. Consumers should never ship this to production. */
169732
+ .flashConfigWarning {
169733
+ display: flex;
169734
+ align-items: center;
169735
+ gap: 8px;
169736
+ margin: 8px 16px 0;
169737
+ padding: 8px 12px;
169738
+ border-left: 3px solid ${cssManager.bdTheme("hsl(38 92% 50%)", "hsl(48 96% 63%)")};
169739
+ background: ${cssManager.bdTheme("hsl(48 96% 89% / 0.6)", "hsl(48 96% 30% / 0.15)")};
169740
+ color: ${cssManager.bdTheme("hsl(32 81% 29%)", "hsl(48 96% 80%)")};
169741
+ font-size: 12px;
169742
+ line-height: 1.4;
169743
+ border-radius: 4px;
169744
+ }
169745
+ .flashConfigWarning dees-icon {
169746
+ width: 14px;
169747
+ height: 14px;
169748
+ flex: 0 0 auto;
169749
+ }
169750
+ .flashConfigWarning code {
169751
+ padding: 1px 4px;
169752
+ border-radius: 3px;
169753
+ background: ${cssManager.bdTheme("hsl(0 0% 100% / 0.6)", "hsl(0 0% 0% / 0.3)")};
169754
+ font-family: ${cssGeistFontFamily};
169755
+ font-size: 11px;
169756
+ }
169757
+
169631
169758
  /* Editable cell affordances */
169632
169759
  td.editable {
169633
169760
  cursor: text;
@@ -170010,7 +170137,7 @@ __name(compileLucenePredicate, "compileLucenePredicate");
170010
170137
  init_dist_ts30();
170011
170138
  init_dist_ts29();
170012
170139
  init_theme();
170013
- 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;
170140
+ var ___virtualRange_dec, ___flashingCells_dec, ___floatingActive_dec, ___editingCell_dec, ___focusedCell_dec, _selectedIds_dec, _selectionMode_dec, _searchMode_dec, _fixedHeight_dec, _highlightDuration_dec, _highlightUpdates_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, _highlightUpdates, _highlightDuration, _fixedHeight, _searchMode, _selectionMode, _selectedIds, ___focusedCell, ___editingCell, ___floatingActive, ___flashingCells, ___virtualRange;
170014
170141
  function ordinalLabel(n12) {
170015
170142
  const s10 = ["th", "st", "nd", "rd"];
170016
170143
  const v5 = n12 % 100;
@@ -170057,7 +170184,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170057
170184
  type: Boolean,
170058
170185
  reflect: true,
170059
170186
  attribute: "show-grid"
170060
- })], _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) {
170187
+ })], _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" })], _highlightUpdates_dec = [n5({ type: String, attribute: "highlight-updates" })], _highlightDuration_dec = [n5({ type: Number, attribute: "highlight-duration" })], _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()], ___flashingCells_dec = [r5()], ___virtualRange_dec = [r5()], _a42) {
170061
170188
  constructor() {
170062
170189
  super();
170063
170190
  __privateAdd(this, _heading1, __runInitializers(_init39, 8, this, "heading 1")), __runInitializers(_init39, 11, this);
@@ -170090,12 +170217,14 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170090
170217
  __privateAdd(this, _showSelectionCheckbox, __runInitializers(_init39, 100, this, false)), __runInitializers(_init39, 103, this);
170091
170218
  __privateAdd(this, _virtualized, __runInitializers(_init39, 104, this, false)), __runInitializers(_init39, 107, this);
170092
170219
  __privateAdd(this, _virtualOverscan, __runInitializers(_init39, 108, this, 8)), __runInitializers(_init39, 111, this);
170093
- __privateAdd(this, _fixedHeight, __runInitializers(_init39, 112, this, false)), __runInitializers(_init39, 115, this);
170094
- __privateAdd(this, _searchMode, __runInitializers(_init39, 116, this, "table")), __runInitializers(_init39, 119, this);
170220
+ __privateAdd(this, _highlightUpdates, __runInitializers(_init39, 112, this, "none")), __runInitializers(_init39, 115, this);
170221
+ __privateAdd(this, _highlightDuration, __runInitializers(_init39, 116, this, 900)), __runInitializers(_init39, 119, this);
170222
+ __privateAdd(this, _fixedHeight, __runInitializers(_init39, 120, this, false)), __runInitializers(_init39, 123, this);
170223
+ __privateAdd(this, _searchMode, __runInitializers(_init39, 124, this, "table")), __runInitializers(_init39, 127, this);
170095
170224
  __publicField(this, "__searchTextSub");
170096
170225
  __publicField(this, "__searchModeSub");
170097
- __privateAdd(this, _selectionMode, __runInitializers(_init39, 120, this, "none")), __runInitializers(_init39, 123, this);
170098
- __privateAdd(this, _selectedIds, __runInitializers(_init39, 124, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 127, this);
170226
+ __privateAdd(this, _selectionMode, __runInitializers(_init39, 128, this, "none")), __runInitializers(_init39, 131, this);
170227
+ __privateAdd(this, _selectedIds, __runInitializers(_init39, 132, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 135, this);
170099
170228
  __publicField(this, "_rowIdMap", /* @__PURE__ */ new WeakMap());
170100
170229
  __publicField(this, "_rowIdCounter", 0);
170101
170230
  /**
@@ -170104,9 +170233,18 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170104
170233
  * can compute a contiguous range from this anchor.
170105
170234
  */
170106
170235
  __publicField(this, "__selectionAnchorId");
170107
- __privateAdd(this, ___focusedCell, __runInitializers(_init39, 128, this)), __runInitializers(_init39, 131, this);
170108
- __privateAdd(this, ___editingCell, __runInitializers(_init39, 132, this)), __runInitializers(_init39, 135, this);
170109
- __privateAdd(this, ___floatingActive, __runInitializers(_init39, 136, this, false)), __runInitializers(_init39, 139, this);
170236
+ __privateAdd(this, ___focusedCell, __runInitializers(_init39, 136, this)), __runInitializers(_init39, 139, this);
170237
+ __privateAdd(this, ___editingCell, __runInitializers(_init39, 140, this)), __runInitializers(_init39, 143, this);
170238
+ __privateAdd(this, ___floatingActive, __runInitializers(_init39, 144, this, false)), __runInitializers(_init39, 147, this);
170239
+ __privateAdd(this, ___flashingCells, __runInitializers(_init39, 148, this, /* @__PURE__ */ new Map())), __runInitializers(_init39, 151, this);
170240
+ /** rowId → (colKey → last-seen resolved cell value). Populated per diff pass. */
170241
+ __publicField(this, "__prevSnapshot");
170242
+ /** Single shared timer that clears __flashingCells after highlightDuration ms. */
170243
+ __publicField(this, "__flashClearTimer");
170244
+ /** Monotonic counter bumped each flash batch so directives.keyed recreates the cell node and restarts the animation. */
170245
+ __publicField(this, "__flashTick", 0);
170246
+ /** One-shot console.warn gate for missing rowKey in flash mode. */
170247
+ __publicField(this, "__flashWarnedNoRowKey", false);
170110
170248
  // ─── Render memoization ──────────────────────────────────────────────
170111
170249
  // These caches let render() short-circuit when the relevant inputs
170112
170250
  // (by reference) haven't changed. They are NOT @state — mutating them
@@ -170120,7 +170258,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170120
170258
  __publicField(this, "__rowHeight", 36);
170121
170259
  /** True once we've measured `__rowHeight` from a real DOM row. */
170122
170260
  __publicField(this, "__rowHeightMeasured", false);
170123
- __privateAdd(this, ___virtualRange, __runInitializers(_init39, 140, this, { start: 0, end: 0 })), __runInitializers(_init39, 143, this);
170261
+ __privateAdd(this, ___virtualRange, __runInitializers(_init39, 152, this, { start: 0, end: 0 })), __runInitializers(_init39, 155, this);
170124
170262
  /**
170125
170263
  * Ctrl/Cmd+C copies the currently selected rows as a JSON array. Falls
170126
170264
  * back to copying the focused-row (`selectedDataRow`) if no multi
@@ -170445,6 +170583,13 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170445
170583
  </div>
170446
170584
  </div>
170447
170585
  <div class="headingSeparation"></div>
170586
+ ${this.highlightUpdates === "flash" && !this.rowKey ? b2`<div class="flashConfigWarning" role="alert">
170587
+ <dees-icon .icon=${"lucide:triangleAlert"}></dees-icon>
170588
+ <span>
170589
+ <code>highlight-updates="flash"</code> requires
170590
+ <code>rowKey</code> to be set. Flash is disabled.
170591
+ </span>
170592
+ </div>` : b2``}
170448
170593
  <div class="searchGrid hidden">
170449
170594
  <dees-input-text
170450
170595
  .label=${"lucene syntax search"}
@@ -170491,10 +170636,14 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170491
170636
  @drop=${this.__onTbodyDrop}
170492
170637
  >
170493
170638
  ${useVirtual && topSpacerHeight > 0 ? b2`<tr aria-hidden="true" style="height:${topSpacerHeight}px"><td></td></tr>` : b2``}
170494
- ${renderRows.map((itemArg, sliceIdx) => {
170495
- const rowIndex = renderStart + sliceIdx;
170496
- const rowId = this.getRowId(itemArg);
170497
- return b2`
170639
+ ${directives_exports.repeat(
170640
+ renderRows,
170641
+ (itemArg, sliceIdx) => `${this.getRowId(itemArg)}::${renderStart + sliceIdx}`,
170642
+ (itemArg, sliceIdx) => {
170643
+ const rowIndex = renderStart + sliceIdx;
170644
+ const rowId = this.getRowId(itemArg);
170645
+ const flashSet = this.__flashingCells.get(rowId);
170646
+ return b2`
170498
170647
  <tr
170499
170648
  data-row-idx=${rowIndex}
170500
170649
  class="${itemArg === this.selectedDataRow || this.isRowSelected(itemArg) ? "selected" : ""}"
@@ -170503,59 +170652,67 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170503
170652
  <dees-input-checkbox
170504
170653
  .value=${this.isRowSelected(itemArg)}
170505
170654
  @newValue=${(e11) => {
170506
- e11.stopPropagation();
170507
- this.setRowSelected(itemArg, e11.detail === true);
170508
- }}
170655
+ e11.stopPropagation();
170656
+ this.setRowSelected(itemArg, e11.detail === true);
170657
+ }}
170509
170658
  ></dees-input-checkbox>
170510
170659
  </td>` : b2``}
170511
170660
  ${effectiveColumns.filter((c11) => !c11.hidden).map((col, colIndex) => {
170512
- const value2 = getCellValue(itemArg, col, this.displayFunction);
170513
- const content3 = col.renderer ? col.renderer(value2, itemArg, { rowIndex, colIndex, column: col }) : value2;
170514
- const editKey = String(col.key);
170515
- const isEditable = !!(col.editable || col.editor);
170516
- const isFocused = this.__focusedCell?.rowId === rowId && this.__focusedCell?.colKey === editKey;
170517
- const isEditing = this.__editingCell?.rowId === rowId && this.__editingCell?.colKey === editKey;
170518
- const cellClasses = [
170519
- isEditable ? "editable" : "",
170520
- isFocused && !isEditing ? "focused" : "",
170521
- isEditing ? "editingCell" : ""
170522
- ].filter(Boolean).join(" ");
170523
- return b2`
170661
+ const value2 = getCellValue(itemArg, col, this.displayFunction);
170662
+ const content3 = col.renderer ? col.renderer(value2, itemArg, { rowIndex, colIndex, column: col }) : value2;
170663
+ const editKey = String(col.key);
170664
+ const isEditable = !!(col.editable || col.editor);
170665
+ const isFocused = this.__focusedCell?.rowId === rowId && this.__focusedCell?.colKey === editKey;
170666
+ const isEditing = this.__editingCell?.rowId === rowId && this.__editingCell?.colKey === editKey;
170667
+ const isFlashing = !!flashSet?.has(editKey);
170668
+ const cellClasses = [
170669
+ isEditable ? "editable" : "",
170670
+ isFocused && !isEditing ? "focused" : "",
170671
+ isEditing ? "editingCell" : ""
170672
+ ].filter(Boolean).join(" ");
170673
+ const innerHtml = b2`<div
170674
+ class=${isFlashing ? "innerCellContainer flashing" : "innerCellContainer"}
170675
+ >
170676
+ ${isEditing ? this.renderCellEditor(itemArg, col) : content3}
170677
+ </div>`;
170678
+ return b2`
170524
170679
  <td
170525
170680
  class=${cellClasses}
170526
170681
  data-col-key=${editKey}
170527
170682
  >
170528
- <div class="innerCellContainer">
170529
- ${isEditing ? this.renderCellEditor(itemArg, col) : content3}
170530
- </div>
170683
+ ${isFlashing ? directives_exports.keyed(
170684
+ `${rowId}:${editKey}:${this.__flashTick}`,
170685
+ innerHtml
170686
+ ) : innerHtml}
170531
170687
  </td>
170532
170688
  `;
170533
- })}
170689
+ })}
170534
170690
  ${(() => {
170535
- if (this.dataActions && this.dataActions.length > 0) {
170536
- return b2`
170691
+ if (this.dataActions && this.dataActions.length > 0) {
170692
+ return b2`
170537
170693
  <td class="actionsCol">
170538
170694
  <div class="actionsContainer">
170539
170695
  ${this.getActionsForType("inRow").map(
170540
- (actionArg) => b2`
170696
+ (actionArg) => b2`
170541
170697
  <div
170542
170698
  class="action"
170543
170699
  @click=${() => actionArg.actionFunc({
170544
- item: itemArg,
170545
- table: this
170546
- })}
170700
+ item: itemArg,
170701
+ table: this
170702
+ })}
170547
170703
  >
170548
170704
  ${actionArg.iconName ? b2` <dees-icon .icon=${actionArg.iconName}></dees-icon> ` : actionArg.name}
170549
170705
  </div>
170550
170706
  `
170551
- )}
170707
+ )}
170552
170708
  </div>
170553
170709
  </td>
170554
170710
  `;
170555
- }
170556
- })()}
170711
+ }
170712
+ })()}
170557
170713
  </tr>`;
170558
- })}
170714
+ }
170715
+ )}
170559
170716
  ${useVirtual && bottomSpacerHeight > 0 ? b2`<tr aria-hidden="true" style="height:${bottomSpacerHeight}px"><td></td></tr>` : b2``}
170560
170717
  </tbody>
170561
170718
  </table>
@@ -170646,7 +170803,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170646
170803
  const key2 = String(col.key);
170647
170804
  if (col.filterable === false) return b2`<th></th>`;
170648
170805
  return b2`<th>
170649
- <input type="text" placeholder="Filter..." .value=${this.columnFilters[key2] || ""}
170806
+ <input type="text" placeholder="Filter..." data-col-key=${key2} .value=${this.columnFilters[key2] || ""}
170650
170807
  @input=${(e11) => this.setColumnFilter(key2, e11.target.value)} />
170651
170808
  </th>`;
170652
170809
  })}
@@ -170768,6 +170925,79 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170768
170925
  const fh = this.__floatingHeaderEl;
170769
170926
  if (fh) fh.classList.remove("active");
170770
170927
  }
170928
+ /**
170929
+ * If a filter `<input>` inside the floating-header clone currently has
170930
+ * focus, copy its value, caret, and selection range onto the matching
170931
+ * input in the real header, then focus that real input. This lets the
170932
+ * user keep typing uninterrupted when filter input causes the table to
170933
+ * shrink below the viewport stick line and the floating header has to
170934
+ * unmount.
170935
+ *
170936
+ * Safe to call at any time — it is a no-op unless an input inside the
170937
+ * floating header is focused and has a `data-col-key` attribute that
170938
+ * matches a real-header input.
170939
+ */
170940
+ __transferFocusToRealHeader() {
170941
+ const fh = this.__floatingHeaderEl;
170942
+ if (!fh) return;
170943
+ const active = this.shadowRoot?.activeElement;
170944
+ if (!active || !fh.contains(active)) return;
170945
+ const colKey = active.getAttribute("data-col-key");
170946
+ if (!colKey) return;
170947
+ const fromInput = active;
170948
+ const real = this.shadowRoot?.querySelector(
170949
+ `.tableScroll > table > thead input[data-col-key="${CSS.escape(colKey)}"]`
170950
+ );
170951
+ if (!real || real === fromInput) return;
170952
+ const selStart = fromInput.selectionStart;
170953
+ const selEnd = fromInput.selectionEnd;
170954
+ const selDir = fromInput.selectionDirection;
170955
+ real.focus({ preventScroll: true });
170956
+ try {
170957
+ if (selStart != null && selEnd != null) {
170958
+ real.setSelectionRange(selStart, selEnd, selDir || void 0);
170959
+ }
170960
+ } catch {
170961
+ }
170962
+ }
170963
+ /**
170964
+ * Symmetric counterpart to `__transferFocusToRealHeader`. When the
170965
+ * floating header has just activated and a real-header filter input
170966
+ * was focused (and is now scrolled off-screen behind the floating
170967
+ * clone), move focus to the clone's matching input so the user keeps
170968
+ * typing in the visible one.
170969
+ *
170970
+ * Called from `__syncFloatingHeader` inside the post-activation
170971
+ * `updateComplete` callback — by then the clone subtree exists in the
170972
+ * DOM and can receive focus.
170973
+ */
170974
+ __transferFocusToFloatingHeader() {
170975
+ const fh = this.__floatingHeaderEl;
170976
+ if (!fh || !this.__floatingActive) return;
170977
+ const active = this.shadowRoot?.activeElement;
170978
+ if (!active) return;
170979
+ const realThead = this.shadowRoot?.querySelector(
170980
+ ".tableScroll > table > thead"
170981
+ );
170982
+ if (!realThead || !realThead.contains(active)) return;
170983
+ const colKey = active.getAttribute("data-col-key");
170984
+ if (!colKey) return;
170985
+ const fromInput = active;
170986
+ const clone = fh.querySelector(
170987
+ `input[data-col-key="${CSS.escape(colKey)}"]`
170988
+ );
170989
+ if (!clone || clone === fromInput) return;
170990
+ const selStart = fromInput.selectionStart;
170991
+ const selEnd = fromInput.selectionEnd;
170992
+ const selDir = fromInput.selectionDirection;
170993
+ clone.focus({ preventScroll: true });
170994
+ try {
170995
+ if (selStart != null && selEnd != null) {
170996
+ clone.setSelectionRange(selStart, selEnd, selDir || void 0);
170997
+ }
170998
+ } catch {
170999
+ }
171000
+ }
170771
171001
  // ─── Virtualization ─────────────────────────────────────────────────
170772
171002
  /**
170773
171003
  * Computes the visible row range based on the table's position in its
@@ -170855,6 +171085,9 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170855
171085
  const distance = tableRect.bottom - stick.top;
170856
171086
  const shouldBeActive = tableRect.top < stick.top && distance > 0;
170857
171087
  if (shouldBeActive !== this.__floatingActive) {
171088
+ if (!shouldBeActive) {
171089
+ this.__transferFocusToRealHeader();
171090
+ }
170858
171091
  this.__floatingActive = shouldBeActive;
170859
171092
  fh.classList.toggle("active", shouldBeActive);
170860
171093
  if (!shouldBeActive) {
@@ -170863,7 +171096,10 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170863
171096
  if (ft) ft.style.transform = "";
170864
171097
  }
170865
171098
  if (shouldBeActive) {
170866
- this.updateComplete.then(() => this.__syncFloatingHeader());
171099
+ this.updateComplete.then(() => {
171100
+ this.__syncFloatingHeader();
171101
+ this.__transferFocusToFloatingHeader();
171102
+ });
170867
171103
  return;
170868
171104
  }
170869
171105
  }
@@ -170900,11 +171136,121 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
170900
171136
  async disconnectedCallback() {
170901
171137
  super.disconnectedCallback();
170902
171138
  this.teardownFloatingHeader();
171139
+ if (this.__flashClearTimer) {
171140
+ clearTimeout(this.__flashClearTimer);
171141
+ this.__flashClearTimer = void 0;
171142
+ }
170903
171143
  }
170904
171144
  async firstUpdated() {
170905
171145
  }
171146
+ /**
171147
+ * Runs before each render. Drives two independent concerns:
171148
+ *
171149
+ * 1. **Selection rebind** — when `data` is reassigned to a fresh array
171150
+ * (typical live-data pattern), `selectedDataRow` still points at the
171151
+ * stale row object from the old array. We re-resolve it by rowKey so
171152
+ * consumers of `selectedDataRow` (footer indicator, header/footer
171153
+ * actions, copy fallback) see the live reference. `selectedIds`,
171154
+ * `__focusedCell`, `__editingCell`, `__selectionAnchorId` are all
171155
+ * keyed by string rowId and persist automatically — no change needed.
171156
+ * This runs regardless of `highlightUpdates` — it is a baseline
171157
+ * correctness fix for live data.
171158
+ *
171159
+ * 2. **Flash diff** — when `highlightUpdates === 'flash'`, diff the new
171160
+ * data against `__prevSnapshot` and populate `__flashingCells` with
171161
+ * the (rowId, colKey) pairs whose resolved cell value changed. A
171162
+ * single shared timer clears `__flashingCells` after
171163
+ * `highlightDuration` ms. Skipped if `rowKey` is missing (with a
171164
+ * one-shot console.warn; the render surface also shows a warning
171165
+ * banner).
171166
+ */
171167
+ willUpdate(changedProperties) {
171168
+ if (changedProperties.has("data") && this.selectedDataRow && this.rowKey) {
171169
+ const prevId = this.getRowId(this.selectedDataRow);
171170
+ let found2;
171171
+ for (const row of this.data) {
171172
+ if (this.getRowId(row) === prevId) {
171173
+ found2 = row;
171174
+ break;
171175
+ }
171176
+ }
171177
+ if (found2) {
171178
+ if (found2 !== this.selectedDataRow) this.selectedDataRow = found2;
171179
+ } else {
171180
+ this.selectedDataRow = void 0;
171181
+ }
171182
+ }
171183
+ if (this.highlightUpdates !== "flash") {
171184
+ if (this.__prevSnapshot || this.__flashingCells.size > 0) {
171185
+ this.__prevSnapshot = void 0;
171186
+ if (this.__flashingCells.size > 0) this.__flashingCells = /* @__PURE__ */ new Map();
171187
+ if (this.__flashClearTimer) {
171188
+ clearTimeout(this.__flashClearTimer);
171189
+ this.__flashClearTimer = void 0;
171190
+ }
171191
+ }
171192
+ return;
171193
+ }
171194
+ if (!this.rowKey) {
171195
+ if (!this.__flashWarnedNoRowKey) {
171196
+ this.__flashWarnedNoRowKey = true;
171197
+ console.warn(
171198
+ '[dees-table] highlightUpdates="flash" requires `rowKey` to be set. Flash is disabled. Set the rowKey property/attribute to a stable identifier on your row data (e.g. `rowKey="id"`).'
171199
+ );
171200
+ }
171201
+ return;
171202
+ }
171203
+ if (!changedProperties.has("data")) return;
171204
+ const effectiveColumns = this.__getEffectiveColumns();
171205
+ const visibleCols = effectiveColumns.filter((c11) => !c11.hidden);
171206
+ const nextSnapshot = /* @__PURE__ */ new Map();
171207
+ const newlyFlashing = /* @__PURE__ */ new Map();
171208
+ for (const row of this.data) {
171209
+ const rowId = this.getRowId(row);
171210
+ const cellMap = /* @__PURE__ */ new Map();
171211
+ for (const col of visibleCols) {
171212
+ cellMap.set(String(col.key), getCellValue(row, col, this.displayFunction));
171213
+ }
171214
+ nextSnapshot.set(rowId, cellMap);
171215
+ const prevCells = this.__prevSnapshot?.get(rowId);
171216
+ if (!prevCells) continue;
171217
+ for (const [colKey, nextVal] of cellMap) {
171218
+ if (prevCells.get(colKey) !== nextVal) {
171219
+ if (this.__editingCell && this.__editingCell.rowId === rowId && this.__editingCell.colKey === colKey) continue;
171220
+ let set3 = newlyFlashing.get(rowId);
171221
+ if (!set3) {
171222
+ set3 = /* @__PURE__ */ new Set();
171223
+ newlyFlashing.set(rowId, set3);
171224
+ }
171225
+ set3.add(colKey);
171226
+ }
171227
+ }
171228
+ }
171229
+ const hadPrev = !!this.__prevSnapshot;
171230
+ this.__prevSnapshot = nextSnapshot;
171231
+ if (!hadPrev) return;
171232
+ if (newlyFlashing.size === 0) return;
171233
+ for (const [rowId, cols] of newlyFlashing) {
171234
+ const existing = this.__flashingCells.get(rowId);
171235
+ if (existing) {
171236
+ for (const c11 of cols) existing.add(c11);
171237
+ } else {
171238
+ this.__flashingCells.set(rowId, cols);
171239
+ }
171240
+ }
171241
+ this.__flashTick++;
171242
+ this.__flashingCells = new Map(this.__flashingCells);
171243
+ if (this.__flashClearTimer) clearTimeout(this.__flashClearTimer);
171244
+ this.__flashClearTimer = setTimeout(() => {
171245
+ this.__flashingCells = /* @__PURE__ */ new Map();
171246
+ this.__flashClearTimer = void 0;
171247
+ }, Math.max(0, this.highlightDuration));
171248
+ }
170906
171249
  async updated(changedProperties) {
170907
171250
  super.updated(changedProperties);
171251
+ if (changedProperties.has("highlightDuration")) {
171252
+ this.style.setProperty("--dees-table-flash-duration", `${this.highlightDuration}ms`);
171253
+ }
170908
171254
  const dataOrColsChanged = !this.__columnsSizedFor || this.__columnsSizedFor.data !== this.data || this.__columnsSizedFor.columns !== this.columns;
170909
171255
  if (dataOrColsChanged) {
170910
171256
  this.__columnsSizedFor = { data: this.data, columns: this.columns };
@@ -171614,6 +171960,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
171614
171960
  }
171615
171961
  if (parsed !== oldValue) {
171616
171962
  item[col.key] = parsed;
171963
+ this.__recordCellInSnapshot(item, col);
171617
171964
  this.dispatchEvent(
171618
171965
  new CustomEvent("cellEdit", {
171619
171966
  detail: { row: item, key: key2, oldValue, newValue: parsed },
@@ -171626,6 +171973,23 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
171626
171973
  this.__editingCell = void 0;
171627
171974
  this.requestUpdate();
171628
171975
  }
171976
+ /**
171977
+ * Updates the flash diff snapshot for a single cell to match its current
171978
+ * resolved value. Called from `commitCellEdit` so a user-initiated edit
171979
+ * does not register as an external change on the next diff pass.
171980
+ * No-op when flash mode is off or no snapshot exists yet.
171981
+ */
171982
+ __recordCellInSnapshot(item, col) {
171983
+ if (this.highlightUpdates !== "flash" || !this.__prevSnapshot) return;
171984
+ if (!this.rowKey) return;
171985
+ const rowId = this.getRowId(item);
171986
+ let cellMap = this.__prevSnapshot.get(rowId);
171987
+ if (!cellMap) {
171988
+ cellMap = /* @__PURE__ */ new Map();
171989
+ this.__prevSnapshot.set(rowId, cellMap);
171990
+ }
171991
+ cellMap.set(String(col.key), getCellValue(item, col, this.displayFunction));
171992
+ }
171629
171993
  /** Renders the appropriate dees-input-* component for this column. */
171630
171994
  renderCellEditor(item, col) {
171631
171995
  const raw2 = item[col.key];
@@ -171779,6 +172143,8 @@ _showColumnFilters = new WeakMap();
171779
172143
  _showSelectionCheckbox = new WeakMap();
171780
172144
  _virtualized = new WeakMap();
171781
172145
  _virtualOverscan = new WeakMap();
172146
+ _highlightUpdates = new WeakMap();
172147
+ _highlightDuration = new WeakMap();
171782
172148
  _fixedHeight = new WeakMap();
171783
172149
  _searchMode = new WeakMap();
171784
172150
  _selectionMode = new WeakMap();
@@ -171786,6 +172152,7 @@ _selectedIds = new WeakMap();
171786
172152
  ___focusedCell = new WeakMap();
171787
172153
  ___editingCell = new WeakMap();
171788
172154
  ___floatingActive = new WeakMap();
172155
+ ___flashingCells = new WeakMap();
171789
172156
  ___virtualRange = new WeakMap();
171790
172157
  __decorateElement(_init39, 4, "heading1", _heading1_dec, _DeesTable, _heading1);
171791
172158
  __decorateElement(_init39, 4, "heading2", _heading2_dec, _DeesTable, _heading22);
@@ -171813,6 +172180,8 @@ __decorateElement(_init39, 4, "showColumnFilters", _showColumnFilters_dec, _Dees
171813
172180
  __decorateElement(_init39, 4, "showSelectionCheckbox", _showSelectionCheckbox_dec, _DeesTable, _showSelectionCheckbox);
171814
172181
  __decorateElement(_init39, 4, "virtualized", _virtualized_dec, _DeesTable, _virtualized);
171815
172182
  __decorateElement(_init39, 4, "virtualOverscan", _virtualOverscan_dec, _DeesTable, _virtualOverscan);
172183
+ __decorateElement(_init39, 4, "highlightUpdates", _highlightUpdates_dec, _DeesTable, _highlightUpdates);
172184
+ __decorateElement(_init39, 4, "highlightDuration", _highlightDuration_dec, _DeesTable, _highlightDuration);
171816
172185
  __decorateElement(_init39, 4, "fixedHeight", _fixedHeight_dec, _DeesTable, _fixedHeight);
171817
172186
  __decorateElement(_init39, 4, "searchMode", _searchMode_dec, _DeesTable, _searchMode);
171818
172187
  __decorateElement(_init39, 4, "selectionMode", _selectionMode_dec, _DeesTable, _selectionMode);
@@ -171820,6 +172189,7 @@ __decorateElement(_init39, 4, "selectedIds", _selectedIds_dec, _DeesTable, _sele
171820
172189
  __decorateElement(_init39, 4, "__focusedCell", ___focusedCell_dec, _DeesTable, ___focusedCell);
171821
172190
  __decorateElement(_init39, 4, "__editingCell", ___editingCell_dec, _DeesTable, ___editingCell);
171822
172191
  __decorateElement(_init39, 4, "__floatingActive", ___floatingActive_dec, _DeesTable, ___floatingActive);
172192
+ __decorateElement(_init39, 4, "__flashingCells", ___flashingCells_dec, _DeesTable, ___flashingCells);
171823
172193
  __decorateElement(_init39, 4, "__virtualRange", ___virtualRange_dec, _DeesTable, ___virtualRange);
171824
172194
  _DeesTable = __decorateElement(_init39, 0, "DeesTable", _DeesTable_decorators, _DeesTable);
171825
172195
  __name(_DeesTable, "DeesTable");