@ixfx/components 0.10.6 → 0.10.7

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.
Files changed (85) hide show
  1. package/bundle/index.d.ts +8 -2
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +132 -6
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +1 -1
  6. package/dist/{ac-token--_vCHXWw.d.ts → ac-token-TCLAZeVg.d.ts} +2 -2
  7. package/dist/{ac-token--_vCHXWw.d.ts.map → ac-token-TCLAZeVg.d.ts.map} +1 -1
  8. package/dist/ac-token.d.ts +1 -1
  9. package/dist/{button-BYuf72aR.d.ts → button-CTL45aBl.d.ts} +2 -2
  10. package/dist/{button-BYuf72aR.d.ts.map → button-CTL45aBl.d.ts.map} +1 -1
  11. package/dist/button.d.ts +1 -1
  12. package/dist/colour-picker.d.ts +1 -1
  13. package/dist/crumbs.d.ts +1 -1
  14. package/dist/{data-grid-DE1_gZNk.d.ts → data-grid-BDNjQv3Q.d.ts} +8 -6
  15. package/dist/data-grid-BDNjQv3Q.d.ts.map +1 -0
  16. package/dist/data-grid.d.ts +2 -2
  17. package/dist/data-grid.js +10 -5
  18. package/dist/data-grid.js.map +1 -1
  19. package/dist/{detail-list-CaStSzYN.d.ts → detail-list-BdLuOwQj.d.ts} +4 -4
  20. package/dist/{detail-list-CaStSzYN.d.ts.map → detail-list-BdLuOwQj.d.ts.map} +1 -1
  21. package/dist/detail-list.d.ts +2 -2
  22. package/dist/detail-list.js +49 -1
  23. package/dist/detail-list.js.map +1 -1
  24. package/dist/{grid-list-BJDxBL0x.d.ts → grid-list-DyphX9Fv.d.ts} +2 -2
  25. package/dist/{grid-list-BJDxBL0x.d.ts.map → grid-list-DyphX9Fv.d.ts.map} +1 -1
  26. package/dist/{grid-list-CaMcdpFJ.js → grid-list-k89JpiNy.js} +18 -1
  27. package/dist/grid-list-k89JpiNy.js.map +1 -0
  28. package/dist/grid-list.d.ts +1 -1
  29. package/dist/grid-list.js +1 -1
  30. package/dist/{grouped-item-lister-DETte0Dh.d.ts → grouped-item-lister-Bhyo-dkH.d.ts} +2 -2
  31. package/dist/{grouped-item-lister-DETte0Dh.d.ts.map → grouped-item-lister-Bhyo-dkH.d.ts.map} +1 -1
  32. package/dist/grouped-item-lister.d.ts +1 -1
  33. package/dist/{icon-CDGprSdE.d.ts → icon-DR_3rSyZ.d.ts} +2 -2
  34. package/dist/icon-DR_3rSyZ.d.ts.map +1 -0
  35. package/dist/icons.d.ts +2 -2
  36. package/dist/incr-search.d.ts +1 -1
  37. package/dist/{index-tq6f8007.d.ts → index-BOUaDIW-.d.ts} +2 -2
  38. package/dist/{index-tq6f8007.d.ts.map → index-BOUaDIW-.d.ts.map} +1 -1
  39. package/dist/{index-CoqtMSd9.d.ts → index-BUB5SICW.d.ts} +2 -2
  40. package/dist/{index-CoqtMSd9.d.ts.map → index-BUB5SICW.d.ts.map} +1 -1
  41. package/dist/{index-CsaQwNkz.d.ts → index-BXafRK-_.d.ts} +2 -2
  42. package/dist/{index-CsaQwNkz.d.ts.map → index-BXafRK-_.d.ts.map} +1 -1
  43. package/dist/{index-9AhaHIT2.d.ts → index-C59-JEPl.d.ts} +3 -3
  44. package/dist/{index-9AhaHIT2.d.ts.map → index-C59-JEPl.d.ts.map} +1 -1
  45. package/dist/{index-UvnoZUAo.d.ts → index-CJ5fshD3.d.ts} +2 -2
  46. package/dist/{index-UvnoZUAo.d.ts.map → index-CJ5fshD3.d.ts.map} +1 -1
  47. package/dist/{index-CYndvTWH.d.ts → index-garxxqgV.d.ts} +2 -2
  48. package/dist/{index-CYndvTWH.d.ts.map → index-garxxqgV.d.ts.map} +1 -1
  49. package/dist/index.d.ts +23 -19
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +57 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/{labelled-input-base-DiTme1JO.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +2 -2
  54. package/dist/{labelled-input-base-DiTme1JO.d.ts.map → labelled-input-base-Dp_9KP0G.d.ts.map} +1 -1
  55. package/dist/labelled-radial-input.d.ts +2 -2
  56. package/dist/labelled-radial-input.d.ts.map +1 -1
  57. package/dist/labelled-range-input.d.ts +1 -1
  58. package/dist/labelled-slider-input.d.ts +1 -1
  59. package/dist/{menu-item-CZi9vy5O.d.ts → menu-item-ZmkXNjek.d.ts} +2 -2
  60. package/dist/{menu-item-CZi9vy5O.d.ts.map → menu-item-ZmkXNjek.d.ts.map} +1 -1
  61. package/dist/menu.d.ts +2 -2
  62. package/dist/miller.d.ts +1 -1
  63. package/dist/panel.d.ts +1 -1
  64. package/dist/{split-layout-JK3xWVX2.d.ts → split-layout-C5SYbDrq.d.ts} +2 -2
  65. package/dist/{split-layout-JK3xWVX2.d.ts.map → split-layout-C5SYbDrq.d.ts.map} +1 -1
  66. package/dist/split-layout.d.ts +1 -1
  67. package/dist/{tab-list-pqfKaVAE.d.ts → tab-list-v8mKX7Fu.d.ts} +2 -2
  68. package/dist/{tab-list-pqfKaVAE.d.ts.map → tab-list-v8mKX7Fu.d.ts.map} +1 -1
  69. package/dist/tabs.d.ts +1 -1
  70. package/dist/{titlebar-Tqu-VvMU.d.ts → titlebar-B5zSTZnF.d.ts} +2 -2
  71. package/dist/{titlebar-Tqu-VvMU.d.ts.map → titlebar-B5zSTZnF.d.ts.map} +1 -1
  72. package/dist/titlebar.d.ts +1 -1
  73. package/dist/tree.d.ts +1 -1
  74. package/dist/{vertical-list-DfcNsa4p.d.ts → vertical-list-C03PN6lx.d.ts} +2 -2
  75. package/dist/{vertical-list-DfcNsa4p.d.ts.map → vertical-list-C03PN6lx.d.ts.map} +1 -1
  76. package/dist/vertical-list.d.ts +1 -1
  77. package/docs-user/data-grid.md +2 -1
  78. package/docs-user/detail-list.md +31 -3
  79. package/docs-user/grid-list.md +4 -2
  80. package/docs-user/index.json +2 -2
  81. package/docs-user/multicol-list.md +4 -0
  82. package/package.json +1 -1
  83. package/dist/data-grid-DE1_gZNk.d.ts.map +0 -1
  84. package/dist/grid-list-CaMcdpFJ.js.map +0 -1
  85. package/dist/icon-CDGprSdE.d.ts.map +0 -1
package/bundle/index.js CHANGED
@@ -14907,7 +14907,7 @@ let DataGridElement = class DataGridElement extends i {
14907
14907
  }
14908
14908
  case ` `: {
14909
14909
  if (this._editing) {
14910
- if (this.columns.find((c) => c.key === this._editing.colKey)?.editor === `boolean`) {
14910
+ if ((this.columns.find((c) => c.key === this._editing.colKey)?.dataType ?? `text`) === `boolean`) {
14911
14911
  e.preventDefault();
14912
14912
  const isImmediate = this.editability === `immediate`;
14913
14913
  const rowKey = this._editing.rowKey;
@@ -15424,11 +15424,13 @@ let DataGridElement = class DataGridElement extends i {
15424
15424
  if (!col) return rows;
15425
15425
  const dir = this.sortState.direction === `asc` ? 1 : -1;
15426
15426
  if (col.sortFn) return rows.sort((a, b) => dir * col.sortFn(a, b));
15427
+ const dataType = col.dataType ?? `text`;
15427
15428
  return rows.sort((a, b) => {
15428
15429
  const av = a[col.key];
15429
15430
  const bv = b[col.key];
15430
15431
  if (av === bv) return 0;
15431
- if (typeof av === `number` && typeof bv === `number`) return dir * (av - bv);
15432
+ if (dataType === `number`) return dir * (av - bv);
15433
+ if (dataType === `boolean`) return dir * (Boolean(av) === Boolean(bv) ? 0 : av ? 1 : -1);
15432
15434
  return dir * String(av).localeCompare(String(bv));
15433
15435
  });
15434
15436
  }
@@ -15805,7 +15807,7 @@ let DataGridElement = class DataGridElement extends i {
15805
15807
  }
15806
15808
  _isTextEditor(col) {
15807
15809
  const e = col.editor;
15808
- return !e || e === `text` || e === `number`;
15810
+ return !e || e === `auto`;
15809
15811
  }
15810
15812
  _isCellEditing(rowKey, colKey) {
15811
15813
  if (this.editability === `immediate` && this._isEditable(this._sortedRows.find((r, i) => this.getRowKey(r, i) === rowKey) ?? {}, this.columns.find((c) => c.key === colKey))) return true;
@@ -16247,7 +16249,8 @@ let DataGridElement = class DataGridElement extends i {
16247
16249
  if (this._isCellEditing(rowKey, col.key)) {
16248
16250
  const immediate = this.editability === `immediate` || this._editingRow === rowKey;
16249
16251
  const curVal = immediate ? val : this._editValue ?? val;
16250
- if (col.editor === `boolean` || col.editor === `boolean`) return b`<div class="cell" data-col=${col.key} style="width:${col.width ?? 150}px;justify-content:center;align-items:center"><input type="checkbox" .checked=${Boolean(curVal)} @change=${(e) => {
16252
+ const effectiveDataType = col.dataType ?? `text`;
16253
+ if (effectiveDataType === `boolean` && (col.editor === `auto` || col.editor === `select` || !col.editor)) return b`<div class="cell" data-col=${col.key} style="width:${col.width ?? 150}px;justify-content:center;align-items:center"><input type="checkbox" .checked=${Boolean(curVal)} @change=${(e) => {
16251
16254
  const v = e.target.checked;
16252
16255
  if (immediate) this._commitImmediate(rowKey, col.key, v);
16253
16256
  else {
@@ -16305,7 +16308,9 @@ let DataGridElement = class DataGridElement extends i {
16305
16308
  };
16306
16309
  return b`<div class="cell" data-col=${col.key} style="width:${col.width ?? 150}px">${factory(ctx)}</div>`;
16307
16310
  }
16308
- return b`<div class="cell" data-col=${col.key} style="width:${col.width ?? 150}px"><input .value=${String(curVal ?? ``)} @input=${(e) => this._editValue = e.target.value} @keydown=${(e) => {
16311
+ const inputType = effectiveDataType === `number` ? `number` : `text`;
16312
+ const inputValue = effectiveDataType === `number` ? String(curVal ?? ``) : String(curVal ?? ``);
16313
+ return b`<div class="cell" data-col=${col.key} style="width:${col.width ?? 150}px"><input type=${inputType} .value=${inputValue} @input=${(e) => this._editValue = e.target.value} @keydown=${(e) => {
16309
16314
  if (e.key === `Enter`) this._commitEdit();
16310
16315
  if (e.key === `Escape`) {
16311
16316
  this._editing = null;
@@ -16709,6 +16714,23 @@ DataTableElement = __decorate([safeCustomElement(`ixfx-data-table`)], DataTableE
16709
16714
  const ITEM_SELECTOR$3 = `:scope > li`;
16710
16715
  const SEARCH_HIGHLIGHT_KEY = `detail-list-search`;
16711
16716
  const LABEL_SPAN_CSS = `overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0`;
16717
+ function pointInRect(x, y, rect) {
16718
+ return rect.width > 0 && rect.height > 0 && x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom;
16719
+ }
16720
+ /** Hit-test the painted content, not a layout wrapper that may fill the row. */
16721
+ function contentAtPoint(node, x, y) {
16722
+ if (node instanceof Text) {
16723
+ if (!node.textContent?.trim()) return false;
16724
+ const range = document.createRange();
16725
+ range.selectNodeContents(node);
16726
+ return Array.from(range.getClientRects()).some((rect) => pointInRect(x, y, rect));
16727
+ }
16728
+ if (!(node instanceof Element)) return false;
16729
+ if (node.hasAttribute(`data-drag-select-blank`)) return false;
16730
+ if (node.hasAttribute(`data-drag-select-content`)) return pointInRect(x, y, node.getBoundingClientRect());
16731
+ if (Array.from(node.childNodes).some((child) => contentAtPoint(child, x, y))) return true;
16732
+ return node.childNodes.length === 0 && pointInRect(x, y, node.getBoundingClientRect());
16733
+ }
16712
16734
  /** Shallow key-array equality, treating `undefined` (never dispatched) as different. */
16713
16735
  function sameKeys$2(a, b) {
16714
16736
  if (a === void 0 || a.length !== b.length) return false;
@@ -16769,6 +16791,10 @@ let DetailListElement = class DetailListElement extends i {
16769
16791
  });
16770
16792
  this.#nativeDragging = false;
16771
16793
  this.#postDragSuppressTimer = 0;
16794
+ this.#blankItemPressPending = false;
16795
+ this.#clearBlankItemPress = () => {
16796
+ this.#blankItemPressPending = false;
16797
+ };
16772
16798
  this.#nativeDrag = new ListNativeDragController(this, {
16773
16799
  source: `detail-list`,
16774
16800
  isEnabled: () => this.itemsDraggable && this.selectionMode !== `none` && this._getVisibleItems().length > 0,
@@ -16800,7 +16826,8 @@ let DetailListElement = class DetailListElement extends i {
16800
16826
  for (const el of this.querySelectorAll(`li`)) el.removeAttribute(`data-drag-origin`);
16801
16827
  this.#startPostDragSuppressTimer();
16802
16828
  },
16803
- syncLightDomDraggable: () => this._syncNativeDraggable()
16829
+ syncLightDomDraggable: () => this._syncNativeDraggable(),
16830
+ shouldStart: () => !this.#blankItemPressPending
16804
16831
  });
16805
16832
  this.#dragSelect = new ListDragSelectController(this, {
16806
16833
  getSurface: () => this.renderRoot.querySelector(`.container`),
@@ -16820,6 +16847,10 @@ let DetailListElement = class DetailListElement extends i {
16820
16847
  },
16821
16848
  autoScroll: (dx, _dy) => {
16822
16849
  if (this._listEl) this._listEl.scrollLeft += dx;
16850
+ },
16851
+ shouldStart: (event) => {
16852
+ this.#blankItemPressPending = this.itemsDraggable && this.#isBlankItemPress(event);
16853
+ return !this.itemsDraggable || this.#blankItemPressPending;
16823
16854
  }
16824
16855
  });
16825
16856
  this.search = new ListSearchController(this, { adapter: createElementListSearchAdapter(this, {
@@ -16938,6 +16969,8 @@ let DetailListElement = class DetailListElement extends i {
16938
16969
  #data;
16939
16970
  #nativeDragging;
16940
16971
  #postDragSuppressTimer;
16972
+ #blankItemPressPending;
16973
+ #clearBlankItemPress;
16941
16974
  #nativeDrag;
16942
16975
  #prepareNativeDrag(originKey) {
16943
16976
  const visible = this._getVisibleItems();
@@ -16975,6 +17008,21 @@ let DetailListElement = class DetailListElement extends i {
16975
17008
  /** Live drag-select preview rect (surface-relative); the covered items carry `data-marquee`. */
16976
17009
  #marqueeRect;
16977
17010
  #dragSelect;
17011
+ /** A row's padding/empty area may start marquee; its actual content may drag out. */
17012
+ #isBlankItemPress(event) {
17013
+ const path = event.composedPath();
17014
+ const item = this._findListItem(path);
17015
+ if (!item) return false;
17016
+ for (const node of path) {
17017
+ if (node === item) break;
17018
+ if (node instanceof Element) {
17019
+ if (node.matches(`input, button, a, select, textarea, [contenteditable], .ixfx-list-checkbox, [role="checkbox"]`)) return false;
17020
+ if (node.hasAttribute(`data-drag-select-blank`)) return true;
17021
+ if (node.hasAttribute(`data-drag-select-content`)) return false;
17022
+ }
17023
+ }
17024
+ return !Array.from(item.childNodes).some((node) => contentAtPoint(node, event.clientX, event.clientY));
17025
+ }
16978
17026
  /** Collect visible items whose surface-relative box intersects `rect`. */
16979
17027
  #marqueeHitTest(rect) {
16980
17028
  const surface = this.renderRoot.querySelector(`.container`);
@@ -17023,6 +17071,8 @@ let DetailListElement = class DetailListElement extends i {
17023
17071
  this.addEventListener(`click`, this._onClick);
17024
17072
  this.addEventListener(`dblclick`, this._onDblClick);
17025
17073
  this.addEventListener(`wheel`, this._onWheel);
17074
+ window.addEventListener(`pointerup`, this.#clearBlankItemPress);
17075
+ window.addEventListener(`pointercancel`, this.#clearBlankItemPress);
17026
17076
  this.#resizeObserver = new ResizeObserver(() => this.#scheduleGeometry());
17027
17077
  this.#resizeObserver.observe(this);
17028
17078
  this.#mutationObserver = new MutationObserver((records) => {
@@ -17067,6 +17117,9 @@ let DetailListElement = class DetailListElement extends i {
17067
17117
  this.removeEventListener(`click`, this._onClick);
17068
17118
  this.removeEventListener(`dblclick`, this._onDblClick);
17069
17119
  this.removeEventListener(`wheel`, this._onWheel);
17120
+ window.removeEventListener(`pointerup`, this.#clearBlankItemPress);
17121
+ window.removeEventListener(`pointercancel`, this.#clearBlankItemPress);
17122
+ this.#blankItemPressPending = false;
17070
17123
  cancelAnimationFrame(this.#sortRaf);
17071
17124
  cancelAnimationFrame(this.#viewportScrollRaf);
17072
17125
  this.#viewportScrollRaf = 0;
@@ -25263,6 +25316,7 @@ let GridListElement = class GridListElement extends i {
25263
25316
  data-input-mode=${this.tickled.inputMode}
25264
25317
  @scroll=${this.#onScroll}
25265
25318
  @wheel=${this.#onWheel}
25319
+ @click=${this.#onViewportClick}
25266
25320
  >
25267
25321
  <div class="spacer" style=${spacerStyle}>
25268
25322
  ${this.#source instanceof DataGridListSource ? this.#renderDataCells(win) : this.#renderElementCells(win)}
@@ -25495,6 +25549,22 @@ let GridListElement = class GridListElement extends i {
25495
25549
  this.selection.handleClick(key, e);
25496
25550
  this.#emitItemEvent(`list-item-click`, key);
25497
25551
  }
25552
+ /**
25553
+ * A click that lands on the viewport without touching a cell — the empty
25554
+ * space between/around items — clears the selection (Finder-style). The
25555
+ * guard mirrors `#onCellClick`: a trailing click after a marquee or native
25556
+ * drag is swallowed so it cannot undo the selection that drag just made.
25557
+ * In `manual` interaction mode the consumer owns selection, so nothing is
25558
+ * cleared. Cell clicks route through `#onCellClick` and are skipped here.
25559
+ */
25560
+ #onViewportClick(e) {
25561
+ const mode = this.interactionMode;
25562
+ if (mode === `manual`) return;
25563
+ if (this.selectionMode === `none` && mode !== `checked` && mode !== `sticky`) return;
25564
+ if (this.#dragSelect.isDragging || this.#nativeDragging || this.#nativeDrag.isDragging || this.#postDragSuppressTimer !== 0) return;
25565
+ for (const node of e.composedPath()) if (node instanceof Element && node.classList.contains(`cell`)) return;
25566
+ this.selection.clear();
25567
+ }
25498
25568
  #startPostDragSuppressTimer() {
25499
25569
  if (this.#postDragSuppressTimer) clearTimeout(this.#postDragSuppressTimer);
25500
25570
  this.#postDragSuppressTimer = window.setTimeout(() => {
@@ -38169,6 +38239,62 @@ let MulticolListElement = class MulticolListElement extends i {
38169
38239
  composed: true
38170
38240
  }));
38171
38241
  }
38242
+ async autoSizeColumns(options) {
38243
+ return new Promise((resolve) => {
38244
+ setTimeout(() => {
38245
+ const minWidth = options?.minWidth ?? MIN_COLUMN_WIDTH;
38246
+ const maxWidth = options?.maxWidth ?? MAX_COLUMN_WIDTH;
38247
+ const measure = (text) => {
38248
+ const span = document.createElement(`span`);
38249
+ span.style.position = `absolute`;
38250
+ span.style.visibility = `hidden`;
38251
+ span.style.whiteSpace = `nowrap`;
38252
+ span.style.font = getComputedStyle(this).font;
38253
+ span.textContent = text;
38254
+ document.body.appendChild(span);
38255
+ const w = span.getBoundingClientRect().width;
38256
+ document.body.removeChild(span);
38257
+ return w;
38258
+ };
38259
+ for (const col of this._columns) {
38260
+ const colEl = this.shadowRoot?.querySelector(`[data-col-id="${col.id}"]`);
38261
+ if (!colEl) continue;
38262
+ const headerEl = colEl.querySelector(`.column-header`);
38263
+ const listerHost = colEl.querySelector(`.lister-host`);
38264
+ let contentWidth = 0;
38265
+ if (listerHost) {
38266
+ const allLabel = listerHost.querySelector(`.all-label`);
38267
+ if (allLabel) contentWidth = Math.max(contentWidth, measure(allLabel.textContent ?? ``));
38268
+ const groupedLister = listerHost.querySelector(`ixfx-grouped-item-lister`);
38269
+ if (groupedLister) {
38270
+ const verticalLists = groupedLister.querySelectorAll(`ixfx-vertical-list`);
38271
+ for (const vl of verticalLists) {
38272
+ const itemEls = vl.querySelectorAll(`li`);
38273
+ for (const li of itemEls) {
38274
+ const labelEl = li.querySelector(`.item-label`);
38275
+ const countEl = li.querySelector(`.count`);
38276
+ const combinedText = (labelEl?.textContent ?? ``) + (countEl?.textContent ?? ``);
38277
+ contentWidth = Math.max(contentWidth, measure(combinedText));
38278
+ }
38279
+ }
38280
+ }
38281
+ }
38282
+ let headerWidth = 0;
38283
+ if (headerEl) {
38284
+ const labelBtn = headerEl.querySelector(`.column-label`);
38285
+ if (labelBtn) headerWidth = measure(labelBtn.textContent ?? ``);
38286
+ }
38287
+ const neededWidth = Math.max(headerWidth, contentWidth + 24 + 16);
38288
+ const clampedWidth = Math.max(minWidth, Math.min(maxWidth, Math.ceil(neededWidth)));
38289
+ col.setWidth(clampedWidth);
38290
+ }
38291
+ this._updateColOffsets();
38292
+ this._emitColumnsChange(`resize`);
38293
+ this.requestUpdate();
38294
+ resolve();
38295
+ }, 0);
38296
+ });
38297
+ }
38172
38298
  };
38173
38299
  __decorate([property({ attribute: false })], MulticolListElement.prototype, "categories", void 0);
38174
38300
  __decorate([property({ attribute: false })], MulticolListElement.prototype, "dataProvider", void 0);