@design.estate/dees-catalog 3.69.0 → 3.70.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.
@@ -163904,6 +163904,69 @@ var demoFunc29 = /* @__PURE__ */ __name(() => b2`
163904
163904
  ]}
163905
163905
  ></dees-table>
163906
163906
  </div>
163907
+
163908
+ <dees-demowrapper .runAfterRender=${async (elementArg) => {
163909
+ const tableEl = elementArg.querySelector("#demoLiveFlash");
163910
+ if (!tableEl) return;
163911
+ if (tableEl.__liveFlashTimerId) {
163912
+ window.clearInterval(tableEl.__liveFlashTimerId);
163913
+ }
163914
+ const tick = /* @__PURE__ */ __name(() => {
163915
+ if (!Array.isArray(tableEl.data) || tableEl.data.length === 0) return;
163916
+ const next2 = tableEl.data.map((r11) => ({ ...r11 }));
163917
+ const count2 = 1 + Math.floor(Math.random() * 3);
163918
+ for (let i11 = 0; i11 < count2; i11++) {
163919
+ const idx = Math.floor(Math.random() * next2.length);
163920
+ const delta = +((Math.random() * 2 - 1) * 3).toFixed(2);
163921
+ const newPrice = Math.max(1, +(next2[idx].price + delta).toFixed(2));
163922
+ next2[idx] = {
163923
+ ...next2[idx],
163924
+ price: newPrice,
163925
+ change: delta,
163926
+ updatedAt: (/* @__PURE__ */ new Date()).toLocaleTimeString()
163927
+ };
163928
+ }
163929
+ tableEl.data = next2;
163930
+ }, "tick");
163931
+ tableEl.__liveFlashTimerId = window.setInterval(tick, 1500);
163932
+ }}>
163933
+ <div class="demo-section">
163934
+ <h2 class="demo-title">Live Updates with Flash Highlighting</h2>
163935
+ <p class="demo-description">
163936
+ Opt-in cell-flash via <code>highlight-updates="flash"</code>. The ticker below mutates
163937
+ random rows every 1.5s and reassigns <code>.data</code>. Updated cells briefly flash
163938
+ amber and fade out. Requires <code>rowKey</code> (here <code>"symbol"</code>). Honors
163939
+ <code>prefers-reduced-motion</code>. Row selection persists across updates — click a
163940
+ row, then watch it stay selected as the data churns.
163941
+ </p>
163942
+ <dees-table
163943
+ id="demoLiveFlash"
163944
+ .rowKey=${"symbol"}
163945
+ highlight-updates="flash"
163946
+ .selectionMode=${"multi"}
163947
+ heading1="Live Market Feed"
163948
+ heading2="Flashing cells indicate updated values"
163949
+ .columns=${[
163950
+ { key: "symbol", header: "Symbol", sortable: true },
163951
+ { key: "price", header: "Price", sortable: true },
163952
+ { key: "change", header: "\u0394", sortable: true },
163953
+ { key: "updatedAt", header: "Updated" }
163954
+ ]}
163955
+ .data=${[
163956
+ { symbol: "AAPL", price: 182.52, change: 0, updatedAt: "\u2014" },
163957
+ { symbol: "MSFT", price: 414.18, change: 0, updatedAt: "\u2014" },
163958
+ { symbol: "GOOG", price: 168.74, change: 0, updatedAt: "\u2014" },
163959
+ { symbol: "AMZN", price: 186.13, change: 0, updatedAt: "\u2014" },
163960
+ { symbol: "TSLA", price: 248.5, change: 0, updatedAt: "\u2014" },
163961
+ { symbol: "NVDA", price: 877.35, change: 0, updatedAt: "\u2014" },
163962
+ { symbol: "META", price: 492.96, change: 0, updatedAt: "\u2014" },
163963
+ { symbol: "NFLX", price: 605.88, change: 0, updatedAt: "\u2014" },
163964
+ { symbol: "AMD", price: 165.24, change: 0, updatedAt: "\u2014" },
163965
+ { symbol: "INTC", price: 42.15, change: 0, updatedAt: "\u2014" }
163966
+ ]}
163967
+ ></dees-table>
163968
+ </div>
163969
+ </dees-demowrapper>
163907
163970
  </div>
163908
163971
  </div>
163909
163972
  `, "demoFunc");
@@ -164282,6 +164345,72 @@ var tableStyles = [
164282
164345
  line-height: 24px;
164283
164346
  }
164284
164347
 
164348
+ /* ---- Cell flash highlighting (opt-in via highlight-updates="flash") ----
164349
+ Bloomberg/TradingView-style: the text itself briefly takes an accent
164350
+ color then fades back to the default. No background tint, no layout
164351
+ shift, no weight change. Readable, modern, subtle.
164352
+ Consumers can override per instance:
164353
+ dees-table#myTable { --dees-table-flash-color: hsl(142 76% 40%); }
164354
+ */
164355
+ :host {
164356
+ --dees-table-flash-color: ${cssManager.bdTheme(
164357
+ "hsl(32 95% 44%)",
164358
+ "hsl(45 93% 62%)"
164359
+ )};
164360
+ --dees-table-flash-easing: cubic-bezier(0.22, 0.61, 0.36, 1);
164361
+ }
164362
+
164363
+ .innerCellContainer.flashing {
164364
+ animation: dees-table-cell-flash
164365
+ var(--dees-table-flash-duration, 900ms)
164366
+ var(--dees-table-flash-easing);
164367
+ }
164368
+
164369
+ /* Hold the accent color briefly, then fade back to the theme's default
164370
+ text color. Inherits to child text and to SVG icons that use
164371
+ currentColor. Cells with explicit color overrides in renderers are
164372
+ intentionally unaffected. */
164373
+ @keyframes dees-table-cell-flash {
164374
+ 0%,
164375
+ 35% { color: var(--dees-table-flash-color); }
164376
+ 100% { color: var(--dees-color-text-primary); }
164377
+ }
164378
+
164379
+ @media (prefers-reduced-motion: reduce) {
164380
+ .innerCellContainer.flashing {
164381
+ animation: none;
164382
+ color: var(--dees-table-flash-color);
164383
+ }
164384
+ }
164385
+
164386
+ /* Dev-time warning banner shown when highlight-updates="flash" but
164387
+ rowKey is missing. Consumers should never ship this to production. */
164388
+ .flashConfigWarning {
164389
+ display: flex;
164390
+ align-items: center;
164391
+ gap: 8px;
164392
+ margin: 8px 16px 0;
164393
+ padding: 8px 12px;
164394
+ border-left: 3px solid ${cssManager.bdTheme("hsl(38 92% 50%)", "hsl(48 96% 63%)")};
164395
+ background: ${cssManager.bdTheme("hsl(48 96% 89% / 0.6)", "hsl(48 96% 30% / 0.15)")};
164396
+ color: ${cssManager.bdTheme("hsl(32 81% 29%)", "hsl(48 96% 80%)")};
164397
+ font-size: 12px;
164398
+ line-height: 1.4;
164399
+ border-radius: 4px;
164400
+ }
164401
+ .flashConfigWarning dees-icon {
164402
+ width: 14px;
164403
+ height: 14px;
164404
+ flex: 0 0 auto;
164405
+ }
164406
+ .flashConfigWarning code {
164407
+ padding: 1px 4px;
164408
+ border-radius: 3px;
164409
+ background: ${cssManager.bdTheme("hsl(0 0% 100% / 0.6)", "hsl(0 0% 0% / 0.3)")};
164410
+ font-family: ${cssGeistFontFamily};
164411
+ font-size: 11px;
164412
+ }
164413
+
164285
164414
  /* Editable cell affordances */
164286
164415
  td.editable {
164287
164416
  cursor: text;
@@ -164664,7 +164793,7 @@ __name(compileLucenePredicate, "compileLucenePredicate");
164664
164793
  init_dist_ts30();
164665
164794
  init_dist_ts29();
164666
164795
  init_theme();
164667
- 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;
164796
+ 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;
164668
164797
  function ordinalLabel(n12) {
164669
164798
  const s10 = ["th", "st", "nd", "rd"];
164670
164799
  const v5 = n12 % 100;
@@ -164711,7 +164840,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164711
164840
  type: Boolean,
164712
164841
  reflect: true,
164713
164842
  attribute: "show-grid"
164714
- })], _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) {
164843
+ })], _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) {
164715
164844
  constructor() {
164716
164845
  super();
164717
164846
  __privateAdd(this, _heading1, __runInitializers(_init39, 8, this, "heading 1")), __runInitializers(_init39, 11, this);
@@ -164744,12 +164873,14 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164744
164873
  __privateAdd(this, _showSelectionCheckbox, __runInitializers(_init39, 100, this, false)), __runInitializers(_init39, 103, this);
164745
164874
  __privateAdd(this, _virtualized, __runInitializers(_init39, 104, this, false)), __runInitializers(_init39, 107, this);
164746
164875
  __privateAdd(this, _virtualOverscan, __runInitializers(_init39, 108, this, 8)), __runInitializers(_init39, 111, this);
164747
- __privateAdd(this, _fixedHeight, __runInitializers(_init39, 112, this, false)), __runInitializers(_init39, 115, this);
164748
- __privateAdd(this, _searchMode, __runInitializers(_init39, 116, this, "table")), __runInitializers(_init39, 119, this);
164876
+ __privateAdd(this, _highlightUpdates, __runInitializers(_init39, 112, this, "none")), __runInitializers(_init39, 115, this);
164877
+ __privateAdd(this, _highlightDuration, __runInitializers(_init39, 116, this, 900)), __runInitializers(_init39, 119, this);
164878
+ __privateAdd(this, _fixedHeight, __runInitializers(_init39, 120, this, false)), __runInitializers(_init39, 123, this);
164879
+ __privateAdd(this, _searchMode, __runInitializers(_init39, 124, this, "table")), __runInitializers(_init39, 127, this);
164749
164880
  __publicField(this, "__searchTextSub");
164750
164881
  __publicField(this, "__searchModeSub");
164751
- __privateAdd(this, _selectionMode, __runInitializers(_init39, 120, this, "none")), __runInitializers(_init39, 123, this);
164752
- __privateAdd(this, _selectedIds, __runInitializers(_init39, 124, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 127, this);
164882
+ __privateAdd(this, _selectionMode, __runInitializers(_init39, 128, this, "none")), __runInitializers(_init39, 131, this);
164883
+ __privateAdd(this, _selectedIds, __runInitializers(_init39, 132, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 135, this);
164753
164884
  __publicField(this, "_rowIdMap", /* @__PURE__ */ new WeakMap());
164754
164885
  __publicField(this, "_rowIdCounter", 0);
164755
164886
  /**
@@ -164758,9 +164889,18 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164758
164889
  * can compute a contiguous range from this anchor.
164759
164890
  */
164760
164891
  __publicField(this, "__selectionAnchorId");
164761
- __privateAdd(this, ___focusedCell, __runInitializers(_init39, 128, this)), __runInitializers(_init39, 131, this);
164762
- __privateAdd(this, ___editingCell, __runInitializers(_init39, 132, this)), __runInitializers(_init39, 135, this);
164763
- __privateAdd(this, ___floatingActive, __runInitializers(_init39, 136, this, false)), __runInitializers(_init39, 139, this);
164892
+ __privateAdd(this, ___focusedCell, __runInitializers(_init39, 136, this)), __runInitializers(_init39, 139, this);
164893
+ __privateAdd(this, ___editingCell, __runInitializers(_init39, 140, this)), __runInitializers(_init39, 143, this);
164894
+ __privateAdd(this, ___floatingActive, __runInitializers(_init39, 144, this, false)), __runInitializers(_init39, 147, this);
164895
+ __privateAdd(this, ___flashingCells, __runInitializers(_init39, 148, this, /* @__PURE__ */ new Map())), __runInitializers(_init39, 151, this);
164896
+ /** rowId → (colKey → last-seen resolved cell value). Populated per diff pass. */
164897
+ __publicField(this, "__prevSnapshot");
164898
+ /** Single shared timer that clears __flashingCells after highlightDuration ms. */
164899
+ __publicField(this, "__flashClearTimer");
164900
+ /** Monotonic counter bumped each flash batch so directives.keyed recreates the cell node and restarts the animation. */
164901
+ __publicField(this, "__flashTick", 0);
164902
+ /** One-shot console.warn gate for missing rowKey in flash mode. */
164903
+ __publicField(this, "__flashWarnedNoRowKey", false);
164764
164904
  // ─── Render memoization ──────────────────────────────────────────────
164765
164905
  // These caches let render() short-circuit when the relevant inputs
164766
164906
  // (by reference) haven't changed. They are NOT @state — mutating them
@@ -164774,7 +164914,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
164774
164914
  __publicField(this, "__rowHeight", 36);
164775
164915
  /** True once we've measured `__rowHeight` from a real DOM row. */
164776
164916
  __publicField(this, "__rowHeightMeasured", false);
164777
- __privateAdd(this, ___virtualRange, __runInitializers(_init39, 140, this, { start: 0, end: 0 })), __runInitializers(_init39, 143, this);
164917
+ __privateAdd(this, ___virtualRange, __runInitializers(_init39, 152, this, { start: 0, end: 0 })), __runInitializers(_init39, 155, this);
164778
164918
  /**
164779
164919
  * Ctrl/Cmd+C copies the currently selected rows as a JSON array. Falls
164780
164920
  * back to copying the focused-row (`selectedDataRow`) if no multi
@@ -165099,6 +165239,13 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165099
165239
  </div>
165100
165240
  </div>
165101
165241
  <div class="headingSeparation"></div>
165242
+ ${this.highlightUpdates === "flash" && !this.rowKey ? b2`<div class="flashConfigWarning" role="alert">
165243
+ <dees-icon .icon=${"lucide:triangleAlert"}></dees-icon>
165244
+ <span>
165245
+ <code>highlight-updates="flash"</code> requires
165246
+ <code>rowKey</code> to be set. Flash is disabled.
165247
+ </span>
165248
+ </div>` : b2``}
165102
165249
  <div class="searchGrid hidden">
165103
165250
  <dees-input-text
165104
165251
  .label=${"lucene syntax search"}
@@ -165145,10 +165292,14 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165145
165292
  @drop=${this.__onTbodyDrop}
165146
165293
  >
165147
165294
  ${useVirtual && topSpacerHeight > 0 ? b2`<tr aria-hidden="true" style="height:${topSpacerHeight}px"><td></td></tr>` : b2``}
165148
- ${renderRows.map((itemArg, sliceIdx) => {
165149
- const rowIndex = renderStart + sliceIdx;
165150
- const rowId = this.getRowId(itemArg);
165151
- return b2`
165295
+ ${directives_exports.repeat(
165296
+ renderRows,
165297
+ (itemArg, sliceIdx) => `${this.getRowId(itemArg)}::${renderStart + sliceIdx}`,
165298
+ (itemArg, sliceIdx) => {
165299
+ const rowIndex = renderStart + sliceIdx;
165300
+ const rowId = this.getRowId(itemArg);
165301
+ const flashSet = this.__flashingCells.get(rowId);
165302
+ return b2`
165152
165303
  <tr
165153
165304
  data-row-idx=${rowIndex}
165154
165305
  class="${itemArg === this.selectedDataRow || this.isRowSelected(itemArg) ? "selected" : ""}"
@@ -165157,59 +165308,67 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165157
165308
  <dees-input-checkbox
165158
165309
  .value=${this.isRowSelected(itemArg)}
165159
165310
  @newValue=${(e11) => {
165160
- e11.stopPropagation();
165161
- this.setRowSelected(itemArg, e11.detail === true);
165162
- }}
165311
+ e11.stopPropagation();
165312
+ this.setRowSelected(itemArg, e11.detail === true);
165313
+ }}
165163
165314
  ></dees-input-checkbox>
165164
165315
  </td>` : b2``}
165165
165316
  ${effectiveColumns.filter((c11) => !c11.hidden).map((col, colIndex) => {
165166
- const value2 = getCellValue(itemArg, col, this.displayFunction);
165167
- const content3 = col.renderer ? col.renderer(value2, itemArg, { rowIndex, colIndex, column: col }) : value2;
165168
- const editKey = String(col.key);
165169
- const isEditable = !!(col.editable || col.editor);
165170
- const isFocused = this.__focusedCell?.rowId === rowId && this.__focusedCell?.colKey === editKey;
165171
- const isEditing = this.__editingCell?.rowId === rowId && this.__editingCell?.colKey === editKey;
165172
- const cellClasses = [
165173
- isEditable ? "editable" : "",
165174
- isFocused && !isEditing ? "focused" : "",
165175
- isEditing ? "editingCell" : ""
165176
- ].filter(Boolean).join(" ");
165177
- return b2`
165317
+ const value2 = getCellValue(itemArg, col, this.displayFunction);
165318
+ const content3 = col.renderer ? col.renderer(value2, itemArg, { rowIndex, colIndex, column: col }) : value2;
165319
+ const editKey = String(col.key);
165320
+ const isEditable = !!(col.editable || col.editor);
165321
+ const isFocused = this.__focusedCell?.rowId === rowId && this.__focusedCell?.colKey === editKey;
165322
+ const isEditing = this.__editingCell?.rowId === rowId && this.__editingCell?.colKey === editKey;
165323
+ const isFlashing = !!flashSet?.has(editKey);
165324
+ const cellClasses = [
165325
+ isEditable ? "editable" : "",
165326
+ isFocused && !isEditing ? "focused" : "",
165327
+ isEditing ? "editingCell" : ""
165328
+ ].filter(Boolean).join(" ");
165329
+ const innerHtml = b2`<div
165330
+ class=${isFlashing ? "innerCellContainer flashing" : "innerCellContainer"}
165331
+ >
165332
+ ${isEditing ? this.renderCellEditor(itemArg, col) : content3}
165333
+ </div>`;
165334
+ return b2`
165178
165335
  <td
165179
165336
  class=${cellClasses}
165180
165337
  data-col-key=${editKey}
165181
165338
  >
165182
- <div class="innerCellContainer">
165183
- ${isEditing ? this.renderCellEditor(itemArg, col) : content3}
165184
- </div>
165339
+ ${isFlashing ? directives_exports.keyed(
165340
+ `${rowId}:${editKey}:${this.__flashTick}`,
165341
+ innerHtml
165342
+ ) : innerHtml}
165185
165343
  </td>
165186
165344
  `;
165187
- })}
165345
+ })}
165188
165346
  ${(() => {
165189
- if (this.dataActions && this.dataActions.length > 0) {
165190
- return b2`
165347
+ if (this.dataActions && this.dataActions.length > 0) {
165348
+ return b2`
165191
165349
  <td class="actionsCol">
165192
165350
  <div class="actionsContainer">
165193
165351
  ${this.getActionsForType("inRow").map(
165194
- (actionArg) => b2`
165352
+ (actionArg) => b2`
165195
165353
  <div
165196
165354
  class="action"
165197
165355
  @click=${() => actionArg.actionFunc({
165198
- item: itemArg,
165199
- table: this
165200
- })}
165356
+ item: itemArg,
165357
+ table: this
165358
+ })}
165201
165359
  >
165202
165360
  ${actionArg.iconName ? b2` <dees-icon .icon=${actionArg.iconName}></dees-icon> ` : actionArg.name}
165203
165361
  </div>
165204
165362
  `
165205
- )}
165363
+ )}
165206
165364
  </div>
165207
165365
  </td>
165208
165366
  `;
165209
- }
165210
- })()}
165367
+ }
165368
+ })()}
165211
165369
  </tr>`;
165212
- })}
165370
+ }
165371
+ )}
165213
165372
  ${useVirtual && bottomSpacerHeight > 0 ? b2`<tr aria-hidden="true" style="height:${bottomSpacerHeight}px"><td></td></tr>` : b2``}
165214
165373
  </tbody>
165215
165374
  </table>
@@ -165300,7 +165459,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165300
165459
  const key2 = String(col.key);
165301
165460
  if (col.filterable === false) return b2`<th></th>`;
165302
165461
  return b2`<th>
165303
- <input type="text" placeholder="Filter..." .value=${this.columnFilters[key2] || ""}
165462
+ <input type="text" placeholder="Filter..." data-col-key=${key2} .value=${this.columnFilters[key2] || ""}
165304
165463
  @input=${(e11) => this.setColumnFilter(key2, e11.target.value)} />
165305
165464
  </th>`;
165306
165465
  })}
@@ -165422,6 +165581,79 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165422
165581
  const fh = this.__floatingHeaderEl;
165423
165582
  if (fh) fh.classList.remove("active");
165424
165583
  }
165584
+ /**
165585
+ * If a filter `<input>` inside the floating-header clone currently has
165586
+ * focus, copy its value, caret, and selection range onto the matching
165587
+ * input in the real header, then focus that real input. This lets the
165588
+ * user keep typing uninterrupted when filter input causes the table to
165589
+ * shrink below the viewport stick line and the floating header has to
165590
+ * unmount.
165591
+ *
165592
+ * Safe to call at any time — it is a no-op unless an input inside the
165593
+ * floating header is focused and has a `data-col-key` attribute that
165594
+ * matches a real-header input.
165595
+ */
165596
+ __transferFocusToRealHeader() {
165597
+ const fh = this.__floatingHeaderEl;
165598
+ if (!fh) return;
165599
+ const active = this.shadowRoot?.activeElement;
165600
+ if (!active || !fh.contains(active)) return;
165601
+ const colKey = active.getAttribute("data-col-key");
165602
+ if (!colKey) return;
165603
+ const fromInput = active;
165604
+ const real = this.shadowRoot?.querySelector(
165605
+ `.tableScroll > table > thead input[data-col-key="${CSS.escape(colKey)}"]`
165606
+ );
165607
+ if (!real || real === fromInput) return;
165608
+ const selStart = fromInput.selectionStart;
165609
+ const selEnd = fromInput.selectionEnd;
165610
+ const selDir = fromInput.selectionDirection;
165611
+ real.focus({ preventScroll: true });
165612
+ try {
165613
+ if (selStart != null && selEnd != null) {
165614
+ real.setSelectionRange(selStart, selEnd, selDir || void 0);
165615
+ }
165616
+ } catch {
165617
+ }
165618
+ }
165619
+ /**
165620
+ * Symmetric counterpart to `__transferFocusToRealHeader`. When the
165621
+ * floating header has just activated and a real-header filter input
165622
+ * was focused (and is now scrolled off-screen behind the floating
165623
+ * clone), move focus to the clone's matching input so the user keeps
165624
+ * typing in the visible one.
165625
+ *
165626
+ * Called from `__syncFloatingHeader` inside the post-activation
165627
+ * `updateComplete` callback — by then the clone subtree exists in the
165628
+ * DOM and can receive focus.
165629
+ */
165630
+ __transferFocusToFloatingHeader() {
165631
+ const fh = this.__floatingHeaderEl;
165632
+ if (!fh || !this.__floatingActive) return;
165633
+ const active = this.shadowRoot?.activeElement;
165634
+ if (!active) return;
165635
+ const realThead = this.shadowRoot?.querySelector(
165636
+ ".tableScroll > table > thead"
165637
+ );
165638
+ if (!realThead || !realThead.contains(active)) return;
165639
+ const colKey = active.getAttribute("data-col-key");
165640
+ if (!colKey) return;
165641
+ const fromInput = active;
165642
+ const clone = fh.querySelector(
165643
+ `input[data-col-key="${CSS.escape(colKey)}"]`
165644
+ );
165645
+ if (!clone || clone === fromInput) return;
165646
+ const selStart = fromInput.selectionStart;
165647
+ const selEnd = fromInput.selectionEnd;
165648
+ const selDir = fromInput.selectionDirection;
165649
+ clone.focus({ preventScroll: true });
165650
+ try {
165651
+ if (selStart != null && selEnd != null) {
165652
+ clone.setSelectionRange(selStart, selEnd, selDir || void 0);
165653
+ }
165654
+ } catch {
165655
+ }
165656
+ }
165425
165657
  // ─── Virtualization ─────────────────────────────────────────────────
165426
165658
  /**
165427
165659
  * Computes the visible row range based on the table's position in its
@@ -165509,6 +165741,9 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165509
165741
  const distance = tableRect.bottom - stick.top;
165510
165742
  const shouldBeActive = tableRect.top < stick.top && distance > 0;
165511
165743
  if (shouldBeActive !== this.__floatingActive) {
165744
+ if (!shouldBeActive) {
165745
+ this.__transferFocusToRealHeader();
165746
+ }
165512
165747
  this.__floatingActive = shouldBeActive;
165513
165748
  fh.classList.toggle("active", shouldBeActive);
165514
165749
  if (!shouldBeActive) {
@@ -165517,7 +165752,10 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165517
165752
  if (ft) ft.style.transform = "";
165518
165753
  }
165519
165754
  if (shouldBeActive) {
165520
- this.updateComplete.then(() => this.__syncFloatingHeader());
165755
+ this.updateComplete.then(() => {
165756
+ this.__syncFloatingHeader();
165757
+ this.__transferFocusToFloatingHeader();
165758
+ });
165521
165759
  return;
165522
165760
  }
165523
165761
  }
@@ -165554,11 +165792,121 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
165554
165792
  async disconnectedCallback() {
165555
165793
  super.disconnectedCallback();
165556
165794
  this.teardownFloatingHeader();
165795
+ if (this.__flashClearTimer) {
165796
+ clearTimeout(this.__flashClearTimer);
165797
+ this.__flashClearTimer = void 0;
165798
+ }
165557
165799
  }
165558
165800
  async firstUpdated() {
165559
165801
  }
165802
+ /**
165803
+ * Runs before each render. Drives two independent concerns:
165804
+ *
165805
+ * 1. **Selection rebind** — when `data` is reassigned to a fresh array
165806
+ * (typical live-data pattern), `selectedDataRow` still points at the
165807
+ * stale row object from the old array. We re-resolve it by rowKey so
165808
+ * consumers of `selectedDataRow` (footer indicator, header/footer
165809
+ * actions, copy fallback) see the live reference. `selectedIds`,
165810
+ * `__focusedCell`, `__editingCell`, `__selectionAnchorId` are all
165811
+ * keyed by string rowId and persist automatically — no change needed.
165812
+ * This runs regardless of `highlightUpdates` — it is a baseline
165813
+ * correctness fix for live data.
165814
+ *
165815
+ * 2. **Flash diff** — when `highlightUpdates === 'flash'`, diff the new
165816
+ * data against `__prevSnapshot` and populate `__flashingCells` with
165817
+ * the (rowId, colKey) pairs whose resolved cell value changed. A
165818
+ * single shared timer clears `__flashingCells` after
165819
+ * `highlightDuration` ms. Skipped if `rowKey` is missing (with a
165820
+ * one-shot console.warn; the render surface also shows a warning
165821
+ * banner).
165822
+ */
165823
+ willUpdate(changedProperties) {
165824
+ if (changedProperties.has("data") && this.selectedDataRow && this.rowKey) {
165825
+ const prevId = this.getRowId(this.selectedDataRow);
165826
+ let found2;
165827
+ for (const row of this.data) {
165828
+ if (this.getRowId(row) === prevId) {
165829
+ found2 = row;
165830
+ break;
165831
+ }
165832
+ }
165833
+ if (found2) {
165834
+ if (found2 !== this.selectedDataRow) this.selectedDataRow = found2;
165835
+ } else {
165836
+ this.selectedDataRow = void 0;
165837
+ }
165838
+ }
165839
+ if (this.highlightUpdates !== "flash") {
165840
+ if (this.__prevSnapshot || this.__flashingCells.size > 0) {
165841
+ this.__prevSnapshot = void 0;
165842
+ if (this.__flashingCells.size > 0) this.__flashingCells = /* @__PURE__ */ new Map();
165843
+ if (this.__flashClearTimer) {
165844
+ clearTimeout(this.__flashClearTimer);
165845
+ this.__flashClearTimer = void 0;
165846
+ }
165847
+ }
165848
+ return;
165849
+ }
165850
+ if (!this.rowKey) {
165851
+ if (!this.__flashWarnedNoRowKey) {
165852
+ this.__flashWarnedNoRowKey = true;
165853
+ console.warn(
165854
+ '[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"`).'
165855
+ );
165856
+ }
165857
+ return;
165858
+ }
165859
+ if (!changedProperties.has("data")) return;
165860
+ const effectiveColumns = this.__getEffectiveColumns();
165861
+ const visibleCols = effectiveColumns.filter((c11) => !c11.hidden);
165862
+ const nextSnapshot = /* @__PURE__ */ new Map();
165863
+ const newlyFlashing = /* @__PURE__ */ new Map();
165864
+ for (const row of this.data) {
165865
+ const rowId = this.getRowId(row);
165866
+ const cellMap = /* @__PURE__ */ new Map();
165867
+ for (const col of visibleCols) {
165868
+ cellMap.set(String(col.key), getCellValue(row, col, this.displayFunction));
165869
+ }
165870
+ nextSnapshot.set(rowId, cellMap);
165871
+ const prevCells = this.__prevSnapshot?.get(rowId);
165872
+ if (!prevCells) continue;
165873
+ for (const [colKey, nextVal] of cellMap) {
165874
+ if (prevCells.get(colKey) !== nextVal) {
165875
+ if (this.__editingCell && this.__editingCell.rowId === rowId && this.__editingCell.colKey === colKey) continue;
165876
+ let set3 = newlyFlashing.get(rowId);
165877
+ if (!set3) {
165878
+ set3 = /* @__PURE__ */ new Set();
165879
+ newlyFlashing.set(rowId, set3);
165880
+ }
165881
+ set3.add(colKey);
165882
+ }
165883
+ }
165884
+ }
165885
+ const hadPrev = !!this.__prevSnapshot;
165886
+ this.__prevSnapshot = nextSnapshot;
165887
+ if (!hadPrev) return;
165888
+ if (newlyFlashing.size === 0) return;
165889
+ for (const [rowId, cols] of newlyFlashing) {
165890
+ const existing = this.__flashingCells.get(rowId);
165891
+ if (existing) {
165892
+ for (const c11 of cols) existing.add(c11);
165893
+ } else {
165894
+ this.__flashingCells.set(rowId, cols);
165895
+ }
165896
+ }
165897
+ this.__flashTick++;
165898
+ this.__flashingCells = new Map(this.__flashingCells);
165899
+ if (this.__flashClearTimer) clearTimeout(this.__flashClearTimer);
165900
+ this.__flashClearTimer = setTimeout(() => {
165901
+ this.__flashingCells = /* @__PURE__ */ new Map();
165902
+ this.__flashClearTimer = void 0;
165903
+ }, Math.max(0, this.highlightDuration));
165904
+ }
165560
165905
  async updated(changedProperties) {
165561
165906
  super.updated(changedProperties);
165907
+ if (changedProperties.has("highlightDuration")) {
165908
+ this.style.setProperty("--dees-table-flash-duration", `${this.highlightDuration}ms`);
165909
+ }
165562
165910
  const dataOrColsChanged = !this.__columnsSizedFor || this.__columnsSizedFor.data !== this.data || this.__columnsSizedFor.columns !== this.columns;
165563
165911
  if (dataOrColsChanged) {
165564
165912
  this.__columnsSizedFor = { data: this.data, columns: this.columns };
@@ -166268,6 +166616,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
166268
166616
  }
166269
166617
  if (parsed !== oldValue) {
166270
166618
  item[col.key] = parsed;
166619
+ this.__recordCellInSnapshot(item, col);
166271
166620
  this.dispatchEvent(
166272
166621
  new CustomEvent("cellEdit", {
166273
166622
  detail: { row: item, key: key2, oldValue, newValue: parsed },
@@ -166280,6 +166629,23 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
166280
166629
  this.__editingCell = void 0;
166281
166630
  this.requestUpdate();
166282
166631
  }
166632
+ /**
166633
+ * Updates the flash diff snapshot for a single cell to match its current
166634
+ * resolved value. Called from `commitCellEdit` so a user-initiated edit
166635
+ * does not register as an external change on the next diff pass.
166636
+ * No-op when flash mode is off or no snapshot exists yet.
166637
+ */
166638
+ __recordCellInSnapshot(item, col) {
166639
+ if (this.highlightUpdates !== "flash" || !this.__prevSnapshot) return;
166640
+ if (!this.rowKey) return;
166641
+ const rowId = this.getRowId(item);
166642
+ let cellMap = this.__prevSnapshot.get(rowId);
166643
+ if (!cellMap) {
166644
+ cellMap = /* @__PURE__ */ new Map();
166645
+ this.__prevSnapshot.set(rowId, cellMap);
166646
+ }
166647
+ cellMap.set(String(col.key), getCellValue(item, col, this.displayFunction));
166648
+ }
166283
166649
  /** Renders the appropriate dees-input-* component for this column. */
166284
166650
  renderCellEditor(item, col) {
166285
166651
  const raw2 = item[col.key];
@@ -166433,6 +166799,8 @@ _showColumnFilters = new WeakMap();
166433
166799
  _showSelectionCheckbox = new WeakMap();
166434
166800
  _virtualized = new WeakMap();
166435
166801
  _virtualOverscan = new WeakMap();
166802
+ _highlightUpdates = new WeakMap();
166803
+ _highlightDuration = new WeakMap();
166436
166804
  _fixedHeight = new WeakMap();
166437
166805
  _searchMode = new WeakMap();
166438
166806
  _selectionMode = new WeakMap();
@@ -166440,6 +166808,7 @@ _selectedIds = new WeakMap();
166440
166808
  ___focusedCell = new WeakMap();
166441
166809
  ___editingCell = new WeakMap();
166442
166810
  ___floatingActive = new WeakMap();
166811
+ ___flashingCells = new WeakMap();
166443
166812
  ___virtualRange = new WeakMap();
166444
166813
  __decorateElement(_init39, 4, "heading1", _heading1_dec, _DeesTable, _heading1);
166445
166814
  __decorateElement(_init39, 4, "heading2", _heading2_dec, _DeesTable, _heading22);
@@ -166467,6 +166836,8 @@ __decorateElement(_init39, 4, "showColumnFilters", _showColumnFilters_dec, _Dees
166467
166836
  __decorateElement(_init39, 4, "showSelectionCheckbox", _showSelectionCheckbox_dec, _DeesTable, _showSelectionCheckbox);
166468
166837
  __decorateElement(_init39, 4, "virtualized", _virtualized_dec, _DeesTable, _virtualized);
166469
166838
  __decorateElement(_init39, 4, "virtualOverscan", _virtualOverscan_dec, _DeesTable, _virtualOverscan);
166839
+ __decorateElement(_init39, 4, "highlightUpdates", _highlightUpdates_dec, _DeesTable, _highlightUpdates);
166840
+ __decorateElement(_init39, 4, "highlightDuration", _highlightDuration_dec, _DeesTable, _highlightDuration);
166470
166841
  __decorateElement(_init39, 4, "fixedHeight", _fixedHeight_dec, _DeesTable, _fixedHeight);
166471
166842
  __decorateElement(_init39, 4, "searchMode", _searchMode_dec, _DeesTable, _searchMode);
166472
166843
  __decorateElement(_init39, 4, "selectionMode", _selectionMode_dec, _DeesTable, _selectionMode);
@@ -166474,6 +166845,7 @@ __decorateElement(_init39, 4, "selectedIds", _selectedIds_dec, _DeesTable, _sele
166474
166845
  __decorateElement(_init39, 4, "__focusedCell", ___focusedCell_dec, _DeesTable, ___focusedCell);
166475
166846
  __decorateElement(_init39, 4, "__editingCell", ___editingCell_dec, _DeesTable, ___editingCell);
166476
166847
  __decorateElement(_init39, 4, "__floatingActive", ___floatingActive_dec, _DeesTable, ___floatingActive);
166848
+ __decorateElement(_init39, 4, "__flashingCells", ___flashingCells_dec, _DeesTable, ___flashingCells);
166477
166849
  __decorateElement(_init39, 4, "__virtualRange", ___virtualRange_dec, _DeesTable, ___virtualRange);
166478
166850
  _DeesTable = __decorateElement(_init39, 0, "DeesTable", _DeesTable_decorators, _DeesTable);
166479
166851
  __name(_DeesTable, "DeesTable");
@@ -186398,17 +186770,30 @@ __publicField(_DeesHeading, "styles", [
186398
186770
  display: block;
186399
186771
  }
186400
186772
 
186401
- /* Heading styles */
186773
+ /* Heading styles.
186774
+ * Color hierarchy: h1-h2 stay prominent with text-primary; h3-h6 step
186775
+ * down to text-secondary so they read as subheadings instead of
186776
+ * mini-h1s. Keeps the visual loudness out of smaller headings. */
186402
186777
  h1, h2, h3, h4, h5, h6 {
186403
186778
  font-weight: 600;
186779
+ }
186780
+ h1, h2 {
186404
186781
  color: var(--dees-color-text-primary);
186405
186782
  }
186783
+ h3, h4, h5, h6 {
186784
+ color: var(--dees-color-text-secondary);
186785
+ }
186406
186786
 
186407
186787
  /* Per-level typography + spacing.
186408
186788
  * Margin scales with importance: h1 gets the most breathing room,
186409
186789
  * h6 the least. Top margin > bottom margin so headings group with
186410
186790
  * the content that follows them. */
186411
186791
  h1 {
186792
+ /* h1 uses weight 500, not 600: the Cal Sans display font is
186793
+ * already stylized enough that bold + max contrast + 32px stacks
186794
+ * too much emphasis. 500 keeps the typographic impact without
186795
+ * shouting. */
186796
+ font-weight: 500;
186412
186797
  font-size: 32px;
186413
186798
  font-family: ${cssCalSansFontFamily};
186414
186799
  letter-spacing: 0.025em;
@@ -194069,26 +194454,31 @@ var _DeesSimpleAppDash = class _DeesSimpleAppDash extends (_a97 = DeesElement, _
194069
194454
  <dees-icon class="chevron" .icon="${"lucide:chevronDown"}"></dees-icon>
194070
194455
  ` : ""}
194071
194456
  </div>
194072
- ${hasSubs && groupActive ? b2`
194073
- <div class="subViews">
194074
- ${view.subViews.map(
194457
+ ${hasSubs ? b2`
194458
+ <div
194459
+ class="subViews ${groupActive ? "expanded" : ""}"
194460
+ ?inert=${!groupActive}
194461
+ >
194462
+ <div class="subViews-inner">
194463
+ ${view.subViews.map(
194075
194464
  (sub2) => b2`
194076
- <div
194077
- class="viewTab sub ${this.selectedView === sub2 ? "selected" : ""}"
194078
- @click=${(e11) => {
194465
+ <div
194466
+ class="viewTab sub ${this.selectedView === sub2 ? "selected" : ""}"
194467
+ @click=${(e11) => {
194079
194468
  e11.stopPropagation();
194080
194469
  this.loadView(sub2);
194081
194470
  }}
194082
- >
194083
- ${sub2.iconName ? b2`
194084
- <dees-icon .icon="${sub2.iconName.includes(":") ? sub2.iconName : `lucide:${sub2.iconName}`}"></dees-icon>
194085
- ` : b2`
194086
- <dees-icon .icon="${"lucide:dot"}"></dees-icon>
194087
- `}
194088
- <span>${sub2.name}</span>
194089
- </div>
194090
- `
194471
+ >
194472
+ ${sub2.iconName ? b2`
194473
+ <dees-icon .icon="${sub2.iconName.includes(":") ? sub2.iconName : `lucide:${sub2.iconName}`}"></dees-icon>
194474
+ ` : b2`
194475
+ <dees-icon .icon="${"lucide:dot"}"></dees-icon>
194476
+ `}
194477
+ <span>${sub2.name}</span>
194478
+ </div>
194479
+ `
194091
194480
  )}
194481
+ </div>
194092
194482
  </div>
194093
194483
  ` : ""}
194094
194484
  `;
@@ -194502,12 +194892,20 @@ __publicField(_DeesSimpleAppDash, "styles", [
194502
194892
  }
194503
194893
 
194504
194894
  .subViews {
194505
- display: flex;
194506
- flex-direction: column;
194507
- gap: 2px;
194508
- margin: 2px 0 4px 12px;
194509
- padding-left: 12px;
194895
+ display: grid;
194896
+ grid-template-rows: 0fr;
194897
+ margin-left: 12px;
194510
194898
  position: relative;
194899
+ transition:
194900
+ grid-template-rows 0.25s cubic-bezier(0.4, 0, 0.2, 1),
194901
+ margin-top 0.25s cubic-bezier(0.4, 0, 0.2, 1),
194902
+ margin-bottom 0.25s cubic-bezier(0.4, 0, 0.2, 1);
194903
+ }
194904
+
194905
+ .subViews.expanded {
194906
+ grid-template-rows: 1fr;
194907
+ margin-top: 2px;
194908
+ margin-bottom: 4px;
194511
194909
  }
194512
194910
 
194513
194911
  .subViews::before {
@@ -194518,6 +194916,21 @@ __publicField(_DeesSimpleAppDash, "styles", [
194518
194916
  bottom: 4px;
194519
194917
  width: 1px;
194520
194918
  background: var(--dees-color-border-default);
194919
+ opacity: 0;
194920
+ transition: opacity 0.2s ease;
194921
+ }
194922
+
194923
+ .subViews.expanded::before {
194924
+ opacity: 1;
194925
+ }
194926
+
194927
+ .subViews-inner {
194928
+ min-height: 0;
194929
+ overflow: hidden;
194930
+ display: flex;
194931
+ flex-direction: column;
194932
+ gap: 2px;
194933
+ padding-left: 12px;
194521
194934
  }
194522
194935
 
194523
194936
  .viewTab.sub {
@@ -200456,7 +200869,7 @@ init_group_runtime();
200456
200869
  // ts_web/00_commitinfo_data.ts
200457
200870
  var commitinfo = {
200458
200871
  name: "@design.estate/dees-catalog",
200459
- version: "3.69.0",
200872
+ version: "3.70.0",
200460
200873
  description: "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript."
200461
200874
  };
200462
200875
  export {
@@ -202429,4 +202842,4 @@ ibantools/jsnext/ibantools.js:
202429
202842
  * @preferred
202430
202843
  *)
202431
202844
  */
202432
- //# sourceMappingURL=bundle-1775638700514.js.map
202845
+ //# sourceMappingURL=bundle-1775659924128.js.map