@ixfx/components 0.10.3 → 0.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.d.ts +106 -28
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +335 -22
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/{ac-token-TCLAZeVg.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
- package/dist/{ac-token-TCLAZeVg.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/{button-DsFbV4XD.js → button-B7mgqtxR.js} +36 -2
- package/dist/button-B7mgqtxR.js.map +1 -0
- package/dist/button-BYuf72aR.d.ts +63 -0
- package/dist/button-BYuf72aR.d.ts.map +1 -0
- package/dist/button.d.ts +2 -21
- package/dist/button.js +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/{data-grid-f9W2uzaR.d.ts → data-grid-DE1_gZNk.d.ts} +10 -5
- package/dist/data-grid-DE1_gZNk.d.ts.map +1 -0
- package/dist/data-grid.d.ts +2 -2
- package/dist/data-grid.js +56 -0
- package/dist/data-grid.js.map +1 -1
- package/dist/{detail-list-C3tozzBT.d.ts → detail-list-CaStSzYN.d.ts} +7 -5
- package/dist/detail-list-CaStSzYN.d.ts.map +1 -0
- package/dist/detail-list.d.ts +4 -3
- package/dist/detail-list.js +61 -1
- package/dist/detail-list.js.map +1 -1
- package/dist/{grid-list-CM1XhTaW.d.ts → grid-list-BJDxBL0x.d.ts} +3 -3
- package/dist/{grid-list-CM1XhTaW.d.ts.map → grid-list-BJDxBL0x.d.ts.map} +1 -1
- package/dist/{grid-list-WE92nfX5.js → grid-list-CaMcdpFJ.js} +22 -3
- package/dist/grid-list-CaMcdpFJ.js.map +1 -0
- package/dist/grid-list.d.ts +2 -2
- package/dist/grid-list.js +1 -1
- package/dist/{grouped-item-lister-CEZ72VOs.d.ts → grouped-item-lister-DETte0Dh.d.ts} +3 -3
- package/dist/{grouped-item-lister-CEZ72VOs.d.ts.map → grouped-item-lister-DETte0Dh.d.ts.map} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{icon-DR_3rSyZ.d.ts → icon-CDGprSdE.d.ts} +2 -2
- package/dist/icon-CDGprSdE.d.ts.map +1 -0
- package/dist/icons.d.ts +2 -2
- package/dist/incr-search.d.ts +1 -1
- package/dist/{index-C59-JEPl.d.ts → index-9AhaHIT2.d.ts} +3 -3
- package/dist/{index-C59-JEPl.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
- package/dist/{index-garxxqgV.d.ts → index-CYndvTWH.d.ts} +2 -2
- package/dist/{index-garxxqgV.d.ts.map → index-CYndvTWH.d.ts.map} +1 -1
- package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +2 -2
- package/dist/{index-BUB5SICW.d.ts.map → index-CoqtMSd9.d.ts.map} +1 -1
- package/dist/{index-BXafRK-_.d.ts → index-CsaQwNkz.d.ts} +2 -2
- package/dist/{index-BXafRK-_.d.ts.map → index-CsaQwNkz.d.ts.map} +1 -1
- package/dist/{index-CJ5fshD3.d.ts → index-UvnoZUAo.d.ts} +2 -2
- package/dist/{index-CJ5fshD3.d.ts.map → index-UvnoZUAo.d.ts.map} +1 -1
- package/dist/{index-BOUaDIW-.d.ts → index-tq6f8007.d.ts} +2 -2
- package/dist/{index-BOUaDIW-.d.ts.map → index-tq6f8007.d.ts.map} +1 -1
- package/dist/index.d.ts +22 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -14
- package/dist/index.js.map +1 -1
- package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +2 -2
- package/dist/{labelled-input-base-Dp_9KP0G.d.ts.map → labelled-input-base-DiTme1JO.d.ts.map} +1 -1
- package/dist/labelled-radial-input.d.ts +2 -2
- package/dist/labelled-radial-input.d.ts.map +1 -1
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-slider-input.d.ts +1 -1
- package/dist/{list-selection-types-B5ioL-dG.d.ts → list-selection-types-PjKdhF-a.d.ts} +1 -9
- package/dist/list-selection-types-PjKdhF-a.d.ts.map +1 -0
- package/dist/list-viewport-types-BRZsLcvp.d.ts +23 -0
- package/dist/list-viewport-types-BRZsLcvp.d.ts.map +1 -0
- package/dist/{menu-item-ZmkXNjek.d.ts → menu-item-CZi9vy5O.d.ts} +2 -2
- package/dist/{menu-item-ZmkXNjek.d.ts.map → menu-item-CZi9vy5O.d.ts.map} +1 -1
- package/dist/menu.d.ts +2 -2
- package/dist/miller.d.ts +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/{split-layout-C5SYbDrq.d.ts → split-layout-JK3xWVX2.d.ts} +2 -2
- package/dist/{split-layout-C5SYbDrq.d.ts.map → split-layout-JK3xWVX2.d.ts.map} +1 -1
- package/dist/split-layout.d.ts +1 -1
- package/dist/{tab-list-DbMIL520.d.ts → tab-list-pqfKaVAE.d.ts} +31 -2
- package/dist/tab-list-pqfKaVAE.d.ts.map +1 -0
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +24 -5
- package/dist/tabs.js.map +1 -1
- package/dist/{titlebar-B5zSTZnF.d.ts → titlebar-Tqu-VvMU.d.ts} +2 -2
- package/dist/{titlebar-B5zSTZnF.d.ts.map → titlebar-Tqu-VvMU.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/{vertical-list-DdaYcvHQ.d.ts → vertical-list-DfcNsa4p.d.ts} +11 -3
- package/dist/vertical-list-DfcNsa4p.d.ts.map +1 -0
- package/dist/vertical-list.d.ts +4 -3
- package/dist/vertical-list.js +47 -1
- package/dist/vertical-list.js.map +1 -1
- package/docs-user/data-grid.md +9 -0
- package/docs-user/detail-list.md +8 -0
- package/docs-user/grid-list.md +1 -1
- package/docs-user/index.json +2 -2
- package/docs-user/vertical-list.md +7 -0
- package/package.json +1 -1
- package/dist/button-DsFbV4XD.js.map +0 -1
- package/dist/button.d.ts.map +0 -1
- package/dist/data-grid-f9W2uzaR.d.ts.map +0 -1
- package/dist/detail-list-C3tozzBT.d.ts.map +0 -1
- package/dist/grid-list-WE92nfX5.js.map +0 -1
- package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
- package/dist/list-selection-types-B5ioL-dG.d.ts.map +0 -1
- package/dist/tab-list-DbMIL520.d.ts.map +0 -1
- package/dist/vertical-list-DdaYcvHQ.d.ts.map +0 -1
package/bundle/index.js
CHANGED
|
@@ -5715,6 +5715,20 @@ const buttonStyles = i$3`
|
|
|
5715
5715
|
:host([subtle]) button:focus-visible:not(:disabled) {
|
|
5716
5716
|
background: color-mix(in oklch, var(--surface-4, #ccc) 70%, transparent);
|
|
5717
5717
|
}
|
|
5718
|
+
|
|
5719
|
+
:host([toggleable]) button:not(:disabled) {
|
|
5720
|
+
opacity: 0.7;
|
|
5721
|
+
}
|
|
5722
|
+
|
|
5723
|
+
:host([toggleable]) button:hover:not(:disabled) {
|
|
5724
|
+
opacity: 0.85;
|
|
5725
|
+
}
|
|
5726
|
+
|
|
5727
|
+
:host([toggleable][value]) button:not(:disabled) {
|
|
5728
|
+
opacity: 1;
|
|
5729
|
+
outline: var(--ixfx-button-toggle-outline-width, 2px) solid var(--ixfx-button-toggle-outline-color, oklch(from var(--accent, #666) l c calc(h + 130)));
|
|
5730
|
+
outline-offset: var(--ixfx-button-toggle-outline-offset, 2px);
|
|
5731
|
+
}
|
|
5718
5732
|
`;
|
|
5719
5733
|
//#endregion
|
|
5720
5734
|
//#region src/button/button.ts
|
|
@@ -5726,7 +5740,19 @@ let ButtonElement = class ButtonElement extends i {
|
|
|
5726
5740
|
this.hideLabel = false;
|
|
5727
5741
|
this.hasIcon = false;
|
|
5728
5742
|
this.subtle = false;
|
|
5743
|
+
this.toggleable = false;
|
|
5744
|
+
this.value = false;
|
|
5745
|
+
this.#handleClick = () => {
|
|
5746
|
+
if (!this.toggleable || this.disabled) return;
|
|
5747
|
+
this.value = !this.value;
|
|
5748
|
+
this.dispatchEvent(new CustomEvent(`toggle`, {
|
|
5749
|
+
detail: { value: this.value },
|
|
5750
|
+
bubbles: true,
|
|
5751
|
+
composed: true
|
|
5752
|
+
}));
|
|
5753
|
+
};
|
|
5729
5754
|
}
|
|
5755
|
+
#handleClick;
|
|
5730
5756
|
_renderIcon() {
|
|
5731
5757
|
if (this.hideIcon || !this.icon) return A;
|
|
5732
5758
|
if (this.icon.startsWith(`<svg`)) return b`<span class="button-icon">${unsafeHTML(this.icon)}</span>`;
|
|
@@ -5736,7 +5762,7 @@ let ButtonElement = class ButtonElement extends i {
|
|
|
5736
5762
|
render() {
|
|
5737
5763
|
this.hasIcon = !this.hideIcon && !!this.icon;
|
|
5738
5764
|
const label = this.hideLabel ? A : b`<span class="button-label"><slot></slot></span>`;
|
|
5739
|
-
return b`<button ?disabled=${this.disabled}>${this._renderIcon()}${label}</button>`;
|
|
5765
|
+
return b`<button ?disabled=${this.disabled} @click=${this.#handleClick}>${this._renderIcon()}${label}</button>`;
|
|
5740
5766
|
}
|
|
5741
5767
|
static {
|
|
5742
5768
|
this.styles = [prominenceStyles, buttonStyles];
|
|
@@ -5763,6 +5789,14 @@ __decorate([property({
|
|
|
5763
5789
|
type: Boolean,
|
|
5764
5790
|
reflect: true
|
|
5765
5791
|
})], ButtonElement.prototype, "subtle", void 0);
|
|
5792
|
+
__decorate([property({
|
|
5793
|
+
type: Boolean,
|
|
5794
|
+
reflect: true
|
|
5795
|
+
})], ButtonElement.prototype, "toggleable", void 0);
|
|
5796
|
+
__decorate([property({
|
|
5797
|
+
type: Boolean,
|
|
5798
|
+
reflect: true
|
|
5799
|
+
})], ButtonElement.prototype, "value", void 0);
|
|
5766
5800
|
ButtonElement = __decorate([safeCustomElement(`ixfx-button`)], ButtonElement);
|
|
5767
5801
|
//#endregion
|
|
5768
5802
|
//#region src/button/radio-group.ts
|
|
@@ -14627,6 +14661,12 @@ __decorate([query(`.text`)], PanTextElement.prototype, "_textEl", void 0);
|
|
|
14627
14661
|
PanTextElement = __decorate([safeCustomElement(`ixfx-pan-text`)], PanTextElement);
|
|
14628
14662
|
//#endregion
|
|
14629
14663
|
//#region src/data-grid/data-grid.ts
|
|
14664
|
+
/** Shallow key-array equality, treating `undefined` (never dispatched) as different. */
|
|
14665
|
+
function sameKeys$3(a, b) {
|
|
14666
|
+
if (a === void 0 || a.length !== b.length) return false;
|
|
14667
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
14668
|
+
return true;
|
|
14669
|
+
}
|
|
14630
14670
|
let DataGridElement = class DataGridElement extends i {
|
|
14631
14671
|
constructor(..._args) {
|
|
14632
14672
|
super(..._args);
|
|
@@ -14719,6 +14759,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14719
14759
|
this._colOffsets = [];
|
|
14720
14760
|
this._colWidthSum = 0;
|
|
14721
14761
|
this._raf = 0;
|
|
14762
|
+
this.#viewportChangeRaf = 0;
|
|
14722
14763
|
this.#appendInProgress = false;
|
|
14723
14764
|
this.#resortRaf = 0;
|
|
14724
14765
|
this._drag = null;
|
|
@@ -14740,6 +14781,9 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
14740
14781
|
this._scrollLeft = el.scrollLeft;
|
|
14741
14782
|
if (this._headerScrollEl) this._headerScrollEl.scrollLeft = el.scrollLeft;
|
|
14742
14783
|
this.requestUpdate();
|
|
14784
|
+
cancelAnimationFrame(this.#viewportChangeRaf);
|
|
14785
|
+
this.#viewportChangeRaf = 0;
|
|
14786
|
+
this.#emitViewportChangeIfChanged();
|
|
14743
14787
|
});
|
|
14744
14788
|
};
|
|
14745
14789
|
this._onKeyDown = (e) => {
|
|
@@ -15173,6 +15217,10 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15173
15217
|
#enteringRowKeys;
|
|
15174
15218
|
#rowReflowTimer;
|
|
15175
15219
|
#dataGridRenderedOnce;
|
|
15220
|
+
#viewportChangeRaf;
|
|
15221
|
+
/** Key sets as of the last `datagrid-viewport-change` dispatch, for dedupe. */
|
|
15222
|
+
#lastViewportRenderedKeys;
|
|
15223
|
+
#lastViewportVisibleKeys;
|
|
15176
15224
|
#appendInProgress;
|
|
15177
15225
|
#resortRaf;
|
|
15178
15226
|
connectedCallback() {
|
|
@@ -15188,6 +15236,8 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15188
15236
|
this.removeEventListener(`keydown`, this._onKeyDown);
|
|
15189
15237
|
this.removeEventListener(`focusout`, this._onFocusOut);
|
|
15190
15238
|
cancelAnimationFrame(this._raf);
|
|
15239
|
+
cancelAnimationFrame(this.#viewportChangeRaf);
|
|
15240
|
+
this.#viewportChangeRaf = 0;
|
|
15191
15241
|
this.#unregisterSearchCommands?.();
|
|
15192
15242
|
this.#unregisterSearchCommands = void 0;
|
|
15193
15243
|
this.#searchRegistry = void 0;
|
|
@@ -15228,6 +15278,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15228
15278
|
if (w === this._viewportW && h === this._viewportH) return;
|
|
15229
15279
|
this._viewportW = w;
|
|
15230
15280
|
this._viewportH = h;
|
|
15281
|
+
this.#scheduleViewportChangeEmit();
|
|
15231
15282
|
}
|
|
15232
15283
|
/**
|
|
15233
15284
|
* Force a fresh re-measure of the viewport and re-render. Normally
|
|
@@ -15242,6 +15293,7 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
15242
15293
|
}
|
|
15243
15294
|
updated(changed) {
|
|
15244
15295
|
super.updated(changed);
|
|
15296
|
+
if (changed.has(`rows`) || changed.has(`sortState`) || changed.has(`columns`) || changed.has(`groupBy`) || changed.has(`groupLabel`) || changed.has(`filterPredicate`) || changed.has(`rowHeight`)) this.#scheduleViewportChangeEmit();
|
|
15245
15297
|
if (changed.has(`_editing`) || changed.has(`_editingRow`)) requestAnimationFrame(() => {
|
|
15246
15298
|
let sel = null;
|
|
15247
15299
|
if (this._editing) sel = `.row[data-key="${this._editing.rowKey}"] .cell[data-col="${this._editing.colKey}"] input, .row[data-key="${this._editing.rowKey}"] .cell[data-col="${this._editing.colKey}"] select`;
|
|
@@ -16021,6 +16073,44 @@ let DataGridElement = class DataGridElement extends i {
|
|
|
16021
16073
|
const { startRow, endRow } = this.getVisibleRange();
|
|
16022
16074
|
return this._flat.slice(startRow, endRow).filter((f) => f.type === `row`).map((f) => f.key);
|
|
16023
16075
|
}
|
|
16076
|
+
/**
|
|
16077
|
+
* Row keys strictly intersecting the viewport (no overscan), mirroring
|
|
16078
|
+
* `ixfx-grid-list.visibleKeys()` for the `datagrid-viewport-change` detail.
|
|
16079
|
+
*/
|
|
16080
|
+
#visibleKeys() {
|
|
16081
|
+
const rh = this.rowHeight;
|
|
16082
|
+
const startRow = Math.max(0, Math.floor(this._scrollTop / rh));
|
|
16083
|
+
const endRow = Math.min(this._flat.length, Math.ceil((this._scrollTop + this._viewportH) / rh));
|
|
16084
|
+
return this._flat.slice(startRow, endRow).filter((f) => f.type === `row`).map((f) => f.key);
|
|
16085
|
+
}
|
|
16086
|
+
/** Coalesce viewport-change dispatches to at most one per animation frame. */
|
|
16087
|
+
#scheduleViewportChangeEmit() {
|
|
16088
|
+
if (this.#viewportChangeRaf !== 0) return;
|
|
16089
|
+
this.#viewportChangeRaf = requestAnimationFrame(() => {
|
|
16090
|
+
this.#viewportChangeRaf = 0;
|
|
16091
|
+
this.#emitViewportChangeIfChanged();
|
|
16092
|
+
});
|
|
16093
|
+
}
|
|
16094
|
+
/**
|
|
16095
|
+
* Dispatch `datagrid-viewport-change` with the current key sets — unless
|
|
16096
|
+
* neither set changed since the last dispatch, so coalesced frames and
|
|
16097
|
+
* no-op scrolls stay silent.
|
|
16098
|
+
*/
|
|
16099
|
+
#emitViewportChangeIfChanged() {
|
|
16100
|
+
const renderedKeys = this.renderedKeys();
|
|
16101
|
+
const visibleKeys = this.#visibleKeys();
|
|
16102
|
+
if (sameKeys$3(this.#lastViewportRenderedKeys, renderedKeys) && sameKeys$3(this.#lastViewportVisibleKeys, visibleKeys)) return;
|
|
16103
|
+
this.#lastViewportRenderedKeys = renderedKeys;
|
|
16104
|
+
this.#lastViewportVisibleKeys = visibleKeys;
|
|
16105
|
+
this.dispatchEvent(new CustomEvent(`datagrid-viewport-change`, {
|
|
16106
|
+
detail: {
|
|
16107
|
+
renderedKeys,
|
|
16108
|
+
visibleKeys
|
|
16109
|
+
},
|
|
16110
|
+
bubbles: true,
|
|
16111
|
+
composed: true
|
|
16112
|
+
}));
|
|
16113
|
+
}
|
|
16024
16114
|
_findFirstVisibleCol(scrollLeft) {
|
|
16025
16115
|
let lo = 0;
|
|
16026
16116
|
let hi = this._colOffsets.length - 1;
|
|
@@ -16619,6 +16709,12 @@ DataTableElement = __decorate([safeCustomElement(`ixfx-data-table`)], DataTableE
|
|
|
16619
16709
|
const ITEM_SELECTOR$3 = `:scope > li`;
|
|
16620
16710
|
const SEARCH_HIGHLIGHT_KEY = `detail-list-search`;
|
|
16621
16711
|
const LABEL_SPAN_CSS = `overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0`;
|
|
16712
|
+
/** Shallow key-array equality, treating `undefined` (never dispatched) as different. */
|
|
16713
|
+
function sameKeys$2(a, b) {
|
|
16714
|
+
if (a === void 0 || a.length !== b.length) return false;
|
|
16715
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
16716
|
+
return true;
|
|
16717
|
+
}
|
|
16622
16718
|
let DetailListElement = class DetailListElement extends i {
|
|
16623
16719
|
constructor(..._args) {
|
|
16624
16720
|
super(..._args);
|
|
@@ -16637,6 +16733,7 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
16637
16733
|
this.#positions = /* @__PURE__ */ new Map();
|
|
16638
16734
|
this.#geometryScheduled = false;
|
|
16639
16735
|
this.#sortRaf = 0;
|
|
16736
|
+
this.#viewportScrollRaf = 0;
|
|
16640
16737
|
this.#animatedItems = /* @__PURE__ */ new WeakSet();
|
|
16641
16738
|
this.#builtFromProvider = [];
|
|
16642
16739
|
this.#providerBuilt = 0;
|
|
@@ -16730,6 +16827,13 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
16730
16827
|
getLabel: (el) => el.getAttribute(`data-search-label`) ?? el.textContent?.trim() ?? ``,
|
|
16731
16828
|
highlightKey: SEARCH_HIGHLIGHT_KEY
|
|
16732
16829
|
}) });
|
|
16830
|
+
this.#onListScroll = () => {
|
|
16831
|
+
if (this.#viewportScrollRaf !== 0) return;
|
|
16832
|
+
this.#viewportScrollRaf = requestAnimationFrame(() => {
|
|
16833
|
+
this.#viewportScrollRaf = 0;
|
|
16834
|
+
this.#emitViewportChangeIfChanged();
|
|
16835
|
+
});
|
|
16836
|
+
};
|
|
16733
16837
|
this._onPointerOver = (e) => {
|
|
16734
16838
|
const item = this._findListItem(e.composedPath());
|
|
16735
16839
|
if (item) this.tickled.handlePointerEnter(item);
|
|
@@ -16821,6 +16925,10 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
16821
16925
|
#positions;
|
|
16822
16926
|
#geometryScheduled;
|
|
16823
16927
|
#sortRaf;
|
|
16928
|
+
#viewportScrollRaf;
|
|
16929
|
+
/** Key sets as of the last viewport-change dispatch, for dedupe. */
|
|
16930
|
+
#lastViewportRenderedKeys;
|
|
16931
|
+
#lastViewportVisibleKeys;
|
|
16824
16932
|
#resizeObserver;
|
|
16825
16933
|
#mutationObserver;
|
|
16826
16934
|
/** Items that have already played (or been skipped for) their enter animation. */
|
|
@@ -16960,6 +17068,8 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
16960
17068
|
this.removeEventListener(`dblclick`, this._onDblClick);
|
|
16961
17069
|
this.removeEventListener(`wheel`, this._onWheel);
|
|
16962
17070
|
cancelAnimationFrame(this.#sortRaf);
|
|
17071
|
+
cancelAnimationFrame(this.#viewportScrollRaf);
|
|
17072
|
+
this.#viewportScrollRaf = 0;
|
|
16963
17073
|
this.#resizeObserver?.disconnect();
|
|
16964
17074
|
this.#resizeObserver = void 0;
|
|
16965
17075
|
this.#mutationObserver?.disconnect();
|
|
@@ -17312,6 +17422,7 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
17312
17422
|
col: colIdx,
|
|
17313
17423
|
row: rowIdx
|
|
17314
17424
|
})));
|
|
17425
|
+
this.#scheduleViewportChangeEmit();
|
|
17315
17426
|
}
|
|
17316
17427
|
#positionOf(el) {
|
|
17317
17428
|
let pos = this.#positions.get(el);
|
|
@@ -17603,6 +17714,45 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
17603
17714
|
cancelable: true
|
|
17604
17715
|
}));
|
|
17605
17716
|
}
|
|
17717
|
+
/** Scroll on the `part="list"` element — rAF-coalesced viewport-change check. */
|
|
17718
|
+
#onListScroll;
|
|
17719
|
+
/** Coalesce non-scroll viewport checks to at most one per animation frame. */
|
|
17720
|
+
#scheduleViewportChangeEmit() {
|
|
17721
|
+
if (this.#viewportScrollRaf !== 0) return;
|
|
17722
|
+
this.#viewportScrollRaf = requestAnimationFrame(() => {
|
|
17723
|
+
this.#viewportScrollRaf = 0;
|
|
17724
|
+
this.#emitViewportChangeIfChanged();
|
|
17725
|
+
});
|
|
17726
|
+
}
|
|
17727
|
+
/**
|
|
17728
|
+
* Keys of everything currently rendered. The list has no virtual window —
|
|
17729
|
+
* every non-hidden item is in the DOM — so this is all keyed items, mirroring
|
|
17730
|
+
* `ixfx-vertical-list.renderedKeys()` in its non-virtualized mode.
|
|
17731
|
+
*/
|
|
17732
|
+
#renderedKeys() {
|
|
17733
|
+
const out = [];
|
|
17734
|
+
for (const el of this._getVisibleItems()) {
|
|
17735
|
+
const key = keyForElement(el);
|
|
17736
|
+
if (key !== void 0) out.push(key);
|
|
17737
|
+
}
|
|
17738
|
+
return out;
|
|
17739
|
+
}
|
|
17740
|
+
/**
|
|
17741
|
+
* Dispatch `detail-list-viewport-change` with the current key sets — unless
|
|
17742
|
+
* neither set changed since the last dispatch, so coalesced frames and
|
|
17743
|
+
* no-op scrolls stay silent.
|
|
17744
|
+
*/
|
|
17745
|
+
#emitViewportChangeIfChanged() {
|
|
17746
|
+
const renderedKeys = this.#renderedKeys();
|
|
17747
|
+
const visibleKeys = this.visibleKeys();
|
|
17748
|
+
if (sameKeys$2(this.#lastViewportRenderedKeys, renderedKeys) && sameKeys$2(this.#lastViewportVisibleKeys, visibleKeys)) return;
|
|
17749
|
+
this.#lastViewportRenderedKeys = renderedKeys;
|
|
17750
|
+
this.#lastViewportVisibleKeys = visibleKeys;
|
|
17751
|
+
this._dispatch(`detail-list-viewport-change`, {
|
|
17752
|
+
renderedKeys,
|
|
17753
|
+
visibleKeys
|
|
17754
|
+
});
|
|
17755
|
+
}
|
|
17606
17756
|
_activateItem(item) {
|
|
17607
17757
|
if (this.interactionMode !== `manual`) this.selection.replace(item);
|
|
17608
17758
|
this._dispatch(`list-activate`, { item });
|
|
@@ -17761,7 +17911,7 @@ let DetailListElement = class DetailListElement extends i {
|
|
|
17761
17911
|
const progress = this.#data.progress;
|
|
17762
17912
|
return b`
|
|
17763
17913
|
<div class="container">
|
|
17764
|
-
<ul part="list" class="scroll-fade-x">
|
|
17914
|
+
<ul part="list" class="scroll-fade-x" @scroll=${this.#onListScroll}>
|
|
17765
17915
|
<slot></slot>
|
|
17766
17916
|
</ul>
|
|
17767
17917
|
${this.#marqueeRect ? b`<div class="marquee" part="marquee" style=${this.#marqueeStyle(this.#marqueeRect)}></div>` : ``}
|
|
@@ -19573,6 +19723,7 @@ let TabListElement = class TabListElement extends i {
|
|
|
19573
19723
|
this.flip = false;
|
|
19574
19724
|
this.scrollable = false;
|
|
19575
19725
|
this.hideLabels = false;
|
|
19726
|
+
this.labelNogrow = false;
|
|
19576
19727
|
this.shrink = false;
|
|
19577
19728
|
this.dragMode = `off`;
|
|
19578
19729
|
this.#items = [];
|
|
@@ -19580,9 +19731,10 @@ let TabListElement = class TabListElement extends i {
|
|
|
19580
19731
|
this.#suppressNextClick = false;
|
|
19581
19732
|
this.#onSlotChange = () => {
|
|
19582
19733
|
this.updateComplete.then(() => {
|
|
19583
|
-
this.#
|
|
19734
|
+
this.#refreshItems();
|
|
19584
19735
|
this.#syncIndicatorColors();
|
|
19585
19736
|
this.#syncHideLabels();
|
|
19737
|
+
this.#syncLabelNogrow();
|
|
19586
19738
|
});
|
|
19587
19739
|
};
|
|
19588
19740
|
this.#onToolbarSlotChange = () => {
|
|
@@ -19741,13 +19893,21 @@ let TabListElement = class TabListElement extends i {
|
|
|
19741
19893
|
</div>`;
|
|
19742
19894
|
}
|
|
19743
19895
|
#onSlotChange;
|
|
19896
|
+
/**
|
|
19897
|
+
* Re-read the assigned tab items. Some environments do not fire slotchange
|
|
19898
|
+
* for a slot's initial assignment, so firstUpdated also calls this before
|
|
19899
|
+
* syncing item attributes.
|
|
19900
|
+
*/
|
|
19901
|
+
#refreshItems() {
|
|
19902
|
+
this.#items = (this.shadowRoot?.querySelector(`slot:not([name])`))?.assignedElements({ flatten: true }) ?? [];
|
|
19903
|
+
}
|
|
19744
19904
|
#onToolbarSlotChange;
|
|
19745
19905
|
firstUpdated() {
|
|
19746
19906
|
this.updateComplete.then(() => {
|
|
19747
|
-
|
|
19748
|
-
|
|
19749
|
-
|
|
19750
|
-
|
|
19907
|
+
this.#refreshItems();
|
|
19908
|
+
this.#syncIndicatorColors();
|
|
19909
|
+
this.#syncHideLabels();
|
|
19910
|
+
this.#syncLabelNogrow();
|
|
19751
19911
|
this.#onToolbarSlotChange();
|
|
19752
19912
|
});
|
|
19753
19913
|
}
|
|
@@ -19756,11 +19916,16 @@ let TabListElement = class TabListElement extends i {
|
|
|
19756
19916
|
this.classList.toggle(`scrollable`, this.scrollable);
|
|
19757
19917
|
if (changedProperties.has(`dragMode`)) this.toggleAttribute(`drag-mode`, this.dragMode !== `off`);
|
|
19758
19918
|
if (changedProperties.has(`hideLabels`)) this.#syncHideLabels();
|
|
19919
|
+
if (changedProperties.has(`labelNogrow`)) this.#syncLabelNogrow();
|
|
19759
19920
|
}
|
|
19760
19921
|
#syncHideLabels() {
|
|
19761
19922
|
for (const item of this.#items) if (this.hideLabels) item.setAttribute(`hide-labels`, ``);
|
|
19762
19923
|
else item.removeAttribute(`hide-labels`);
|
|
19763
19924
|
}
|
|
19925
|
+
#syncLabelNogrow() {
|
|
19926
|
+
for (const item of this.#items) if (this.labelNogrow) item.setAttribute(`label-nogrow`, ``);
|
|
19927
|
+
else item.removeAttribute(`label-nogrow`);
|
|
19928
|
+
}
|
|
19764
19929
|
#syncIndicatorColors() {
|
|
19765
19930
|
for (const item of this.#items) {
|
|
19766
19931
|
item.style.setProperty(`--indicator-color-bottom`, `transparent`);
|
|
@@ -20179,6 +20344,10 @@ __decorate([property({
|
|
|
20179
20344
|
type: Boolean,
|
|
20180
20345
|
attribute: `hide-labels`
|
|
20181
20346
|
})], TabListElement.prototype, "hideLabels", void 0);
|
|
20347
|
+
__decorate([property({
|
|
20348
|
+
type: Boolean,
|
|
20349
|
+
attribute: `label-nogrow`
|
|
20350
|
+
})], TabListElement.prototype, "labelNogrow", void 0);
|
|
20182
20351
|
__decorate([property({
|
|
20183
20352
|
type: Boolean,
|
|
20184
20353
|
reflect: true
|
|
@@ -20195,16 +20364,21 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20195
20364
|
super(..._args);
|
|
20196
20365
|
this.closeable = false;
|
|
20197
20366
|
this.hideLabels = false;
|
|
20367
|
+
this.labelNogrow = false;
|
|
20198
20368
|
this.iconName = void 0;
|
|
20199
20369
|
this.description = void 0;
|
|
20200
20370
|
this.commandActive = void 0;
|
|
20201
20371
|
this.registry = void 0;
|
|
20202
20372
|
this._compact = false;
|
|
20203
20373
|
this._hasToolbarContent = false;
|
|
20374
|
+
this._hasStatusContent = false;
|
|
20204
20375
|
this._labelObserver = null;
|
|
20205
20376
|
this._onToolbarSlotChange = () => {
|
|
20206
20377
|
this._updateToolbarContent();
|
|
20207
20378
|
};
|
|
20379
|
+
this._onStatusSlotChange = () => {
|
|
20380
|
+
this._updateStatusContent();
|
|
20381
|
+
};
|
|
20208
20382
|
this._onLabelSlotChange = () => {
|
|
20209
20383
|
this._syncLabelSizer();
|
|
20210
20384
|
};
|
|
@@ -20215,13 +20389,18 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20215
20389
|
this._compact = entry.contentRect.width < 64;
|
|
20216
20390
|
});
|
|
20217
20391
|
this._resizeObserver.observe(this);
|
|
20218
|
-
|
|
20219
|
-
|
|
20220
|
-
|
|
20392
|
+
this._wireSlotListeners();
|
|
20393
|
+
this._labelObserver = new MutationObserver(() => {
|
|
20394
|
+
this._syncLabelSizer();
|
|
20395
|
+
this._updateToolbarContent();
|
|
20396
|
+
this._updateStatusContent();
|
|
20397
|
+
});
|
|
20221
20398
|
this._labelObserver.observe(this, {
|
|
20222
20399
|
childList: true,
|
|
20223
20400
|
characterData: true,
|
|
20224
|
-
subtree: true
|
|
20401
|
+
subtree: true,
|
|
20402
|
+
attributes: true,
|
|
20403
|
+
attributeFilter: [`slot`]
|
|
20225
20404
|
});
|
|
20226
20405
|
}
|
|
20227
20406
|
disconnectedCallback() {
|
|
@@ -20232,8 +20411,7 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20232
20411
|
this._commandCleanup = void 0;
|
|
20233
20412
|
this._labelObserver?.disconnect();
|
|
20234
20413
|
this._labelObserver = null;
|
|
20235
|
-
|
|
20236
|
-
(this.shadowRoot?.querySelector(`slot:not([name])`))?.removeEventListener(`slotchange`, this._onLabelSlotChange);
|
|
20414
|
+
this._unwireSlotListeners();
|
|
20237
20415
|
}
|
|
20238
20416
|
updated(changed) {
|
|
20239
20417
|
super.updated(changed);
|
|
@@ -20257,6 +20435,22 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20257
20435
|
});
|
|
20258
20436
|
}
|
|
20259
20437
|
/**
|
|
20438
|
+
* Attach slotchange listeners. The shadow root is empty during the first
|
|
20439
|
+
* connectedCallback (the template only exists once rendered), so this is
|
|
20440
|
+
* called again from firstUpdated. addEventListener dedupes identical
|
|
20441
|
+
* listener registrations, so double-wiring is harmless.
|
|
20442
|
+
*/
|
|
20443
|
+
_wireSlotListeners() {
|
|
20444
|
+
(this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.addEventListener(`slotchange`, this._onToolbarSlotChange);
|
|
20445
|
+
(this.shadowRoot?.querySelector(`slot[name="status"]`))?.addEventListener(`slotchange`, this._onStatusSlotChange);
|
|
20446
|
+
(this.shadowRoot?.querySelector(`slot:not([name])`))?.addEventListener(`slotchange`, this._onLabelSlotChange);
|
|
20447
|
+
}
|
|
20448
|
+
_unwireSlotListeners() {
|
|
20449
|
+
(this.shadowRoot?.querySelector(`slot[name="toolbar"]`))?.removeEventListener(`slotchange`, this._onToolbarSlotChange);
|
|
20450
|
+
(this.shadowRoot?.querySelector(`slot[name="status"]`))?.removeEventListener(`slotchange`, this._onStatusSlotChange);
|
|
20451
|
+
(this.shadowRoot?.querySelector(`slot:not([name])`))?.removeEventListener(`slotchange`, this._onLabelSlotChange);
|
|
20452
|
+
}
|
|
20453
|
+
/**
|
|
20260
20454
|
* Mirror the default-slot text into `.label[data-label]` for the `::after`
|
|
20261
20455
|
* width sizer. Slotted toolbar content is excluded.
|
|
20262
20456
|
*/
|
|
@@ -20269,11 +20463,20 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20269
20463
|
else label.removeAttribute(`data-label`);
|
|
20270
20464
|
}
|
|
20271
20465
|
_updateToolbarContent() {
|
|
20272
|
-
|
|
20273
|
-
|
|
20466
|
+
this._hasToolbarContent = Array.from(this.children).some((child) => child.getAttribute(`slot`) === `toolbar`);
|
|
20467
|
+
}
|
|
20468
|
+
/**
|
|
20469
|
+
* Named slots only render once content has been detected, so reading
|
|
20470
|
+
* assignedElements() cannot bootstrap detection. Direct light-DOM children
|
|
20471
|
+
* are exactly what a slot assigns, so scan those instead.
|
|
20472
|
+
*/
|
|
20473
|
+
_updateStatusContent() {
|
|
20474
|
+
this._hasStatusContent = Array.from(this.children).some((child) => child.getAttribute(`slot`) === `status`);
|
|
20274
20475
|
}
|
|
20275
20476
|
firstUpdated() {
|
|
20477
|
+
this._wireSlotListeners();
|
|
20276
20478
|
this._updateToolbarContent();
|
|
20479
|
+
this._updateStatusContent();
|
|
20277
20480
|
this._syncLabelSizer();
|
|
20278
20481
|
}
|
|
20279
20482
|
render() {
|
|
@@ -20283,6 +20486,7 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20283
20486
|
<div>
|
|
20284
20487
|
${this.iconName ? b`<ixfx-icon name="${this.iconName}"></ixfx-icon>` : A}
|
|
20285
20488
|
${showLabel ? b`<span class="label"><slot></slot></span>` : A}
|
|
20489
|
+
${this._hasStatusContent ? b`<div class="status"><slot name="status"></slot></div>` : A}
|
|
20286
20490
|
${hasActions ? b`
|
|
20287
20491
|
<div class="actions">
|
|
20288
20492
|
<div class="toolbar"><slot name="toolbar"></slot></div>
|
|
@@ -20435,6 +20639,28 @@ let TabListItemElement = class TabListItemElement extends i {
|
|
|
20435
20639
|
display: contents;
|
|
20436
20640
|
}
|
|
20437
20641
|
|
|
20642
|
+
/* Persistent status slot (e.g. an ixfx-led). Unlike .toolbar it is
|
|
20643
|
+
always visible, selection or not, and keeps its own size however
|
|
20644
|
+
much the label truncates. --size inherits through slotted content,
|
|
20645
|
+
so bare and button-wrapped LEDs both render smaller; consumers can
|
|
20646
|
+
override per element. */
|
|
20647
|
+
.status {
|
|
20648
|
+
display: flex;
|
|
20649
|
+
align-items: center;
|
|
20650
|
+
flex-shrink: 0;
|
|
20651
|
+
--size: 0.75ex;
|
|
20652
|
+
}
|
|
20653
|
+
|
|
20654
|
+
slot[name="status"] {
|
|
20655
|
+
display: contents;
|
|
20656
|
+
}
|
|
20657
|
+
|
|
20658
|
+
/* With label-nogrow, the label keeps its intrinsic width so status
|
|
20659
|
+
content lands next to the label text instead of the far edge. */
|
|
20660
|
+
:host([label-nogrow]) .label {
|
|
20661
|
+
flex: 0 0 auto;
|
|
20662
|
+
}
|
|
20663
|
+
|
|
20438
20664
|
/* Slotted buttons inherit these through the shadow boundary; keeps a
|
|
20439
20665
|
toolbar button from inflating the strip height. */
|
|
20440
20666
|
.toolbar ::slotted(ixfx-button) {
|
|
@@ -20478,6 +20704,10 @@ __decorate([property({
|
|
|
20478
20704
|
type: Boolean,
|
|
20479
20705
|
attribute: `hide-labels`
|
|
20480
20706
|
})], TabListItemElement.prototype, "hideLabels", void 0);
|
|
20707
|
+
__decorate([property({
|
|
20708
|
+
type: Boolean,
|
|
20709
|
+
attribute: `label-nogrow`
|
|
20710
|
+
})], TabListItemElement.prototype, "labelNogrow", void 0);
|
|
20481
20711
|
__decorate([property({
|
|
20482
20712
|
type: String,
|
|
20483
20713
|
attribute: `icon-name`
|
|
@@ -20490,6 +20720,7 @@ __decorate([property({
|
|
|
20490
20720
|
__decorate([property({ attribute: false })], TabListItemElement.prototype, "registry", void 0);
|
|
20491
20721
|
__decorate([state()], TabListItemElement.prototype, "_compact", void 0);
|
|
20492
20722
|
__decorate([state()], TabListItemElement.prototype, "_hasToolbarContent", void 0);
|
|
20723
|
+
__decorate([state()], TabListItemElement.prototype, "_hasStatusContent", void 0);
|
|
20493
20724
|
TabListItemElement = __decorate([safeCustomElement(`ixfx-tab-list-item`)], TabListItemElement);
|
|
20494
20725
|
//#endregion
|
|
20495
20726
|
//#region src/dock/dock-panel.ts
|
|
@@ -23629,6 +23860,12 @@ function columnOf(index, cols) {
|
|
|
23629
23860
|
function rowOf(index, cols) {
|
|
23630
23861
|
return cols <= 1 ? index : Math.floor(index / cols);
|
|
23631
23862
|
}
|
|
23863
|
+
/** Shallow key-array equality, treating `undefined` (never dispatched) as different. */
|
|
23864
|
+
function sameKeys$1(a, b) {
|
|
23865
|
+
if (a === void 0 || a.length !== b.length) return false;
|
|
23866
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
23867
|
+
return true;
|
|
23868
|
+
}
|
|
23632
23869
|
let GridListElement = class GridListElement extends i {
|
|
23633
23870
|
constructor(..._args) {
|
|
23634
23871
|
super(..._args);
|
|
@@ -24523,10 +24760,23 @@ let GridListElement = class GridListElement extends i {
|
|
|
24523
24760
|
this.requestUpdate();
|
|
24524
24761
|
}, REFLOW_WINDOW_MS);
|
|
24525
24762
|
}
|
|
24763
|
+
/** Key sets as of the last `grid-list-viewport-change` dispatch, for dedupe. */
|
|
24764
|
+
#lastViewportRenderedKeys;
|
|
24765
|
+
#lastViewportVisibleKeys;
|
|
24766
|
+
/**
|
|
24767
|
+
* Dispatch `grid-list-viewport-change` with the current key sets — unless
|
|
24768
|
+
* neither set changed since the last dispatch, so coalesced frames and
|
|
24769
|
+
* no-op scrolls stay silent.
|
|
24770
|
+
*/
|
|
24526
24771
|
#emitViewportChange() {
|
|
24772
|
+
const renderedKeys = this.renderedKeys();
|
|
24773
|
+
const visibleKeys = this.visibleKeys();
|
|
24774
|
+
if (sameKeys$1(this.#lastViewportRenderedKeys, renderedKeys) && sameKeys$1(this.#lastViewportVisibleKeys, visibleKeys)) return;
|
|
24775
|
+
this.#lastViewportRenderedKeys = renderedKeys;
|
|
24776
|
+
this.#lastViewportVisibleKeys = visibleKeys;
|
|
24527
24777
|
this._dispatch(`grid-list-viewport-change`, {
|
|
24528
|
-
renderedKeys
|
|
24529
|
-
visibleKeys
|
|
24778
|
+
renderedKeys,
|
|
24779
|
+
visibleKeys
|
|
24530
24780
|
});
|
|
24531
24781
|
}
|
|
24532
24782
|
firstUpdated() {
|
|
@@ -28257,6 +28507,12 @@ const ITEM_SELECTOR = `li:not([data-virtual-spacer]), [data-list-item]:not([data
|
|
|
28257
28507
|
* vertical rows are shorter relative to the viewport, so 3.
|
|
28258
28508
|
*/
|
|
28259
28509
|
const VIRTUAL_OVERSCAN = 3;
|
|
28510
|
+
/** Shallow key-array equality, treating `undefined` (never dispatched) as different. */
|
|
28511
|
+
function sameKeys(a, b) {
|
|
28512
|
+
if (a === void 0 || a.length !== b.length) return false;
|
|
28513
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
28514
|
+
return true;
|
|
28515
|
+
}
|
|
28260
28516
|
let VerticalListElement = class VerticalListElement extends i {
|
|
28261
28517
|
constructor(..._args) {
|
|
28262
28518
|
super(..._args);
|
|
@@ -28371,11 +28627,11 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
28371
28627
|
highlightKey: `vertical-list-search`
|
|
28372
28628
|
}) });
|
|
28373
28629
|
this.#onScroll = () => {
|
|
28374
|
-
if (!this.#virtualActive()) return;
|
|
28375
28630
|
if (this.#scrollRaf !== 0) return;
|
|
28376
28631
|
this.#scrollRaf = requestAnimationFrame(() => {
|
|
28377
28632
|
this.#scrollRaf = 0;
|
|
28378
28633
|
this.#syncVirtualWindow();
|
|
28634
|
+
this.#emitViewportChangeIfChanged();
|
|
28379
28635
|
});
|
|
28380
28636
|
};
|
|
28381
28637
|
this._onPointerOver = (e) => {
|
|
@@ -28468,6 +28724,9 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
28468
28724
|
#suspendAdapterRebuild;
|
|
28469
28725
|
#scrollRaf;
|
|
28470
28726
|
#resizeObserver;
|
|
28727
|
+
/** Key sets as of the last viewport-change dispatch, for dedupe. */
|
|
28728
|
+
#lastViewportRenderedKeys;
|
|
28729
|
+
#lastViewportVisibleKeys;
|
|
28471
28730
|
#topSpacer;
|
|
28472
28731
|
#bottomSpacer;
|
|
28473
28732
|
/** Last measured viewport height — kept so a 0 read can't collapse the window. */
|
|
@@ -28595,6 +28854,14 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
28595
28854
|
}
|
|
28596
28855
|
}
|
|
28597
28856
|
/**
|
|
28857
|
+
* The shadow scroll list only exists after the first render; start
|
|
28858
|
+
* watching it so resizes move the window (virtualized) and the visible
|
|
28859
|
+
* set (plain) too.
|
|
28860
|
+
*/
|
|
28861
|
+
firstUpdated() {
|
|
28862
|
+
this.#ensureResizeObserved();
|
|
28863
|
+
}
|
|
28864
|
+
/**
|
|
28598
28865
|
* Animate in items appended to the light DOM (however they got there —
|
|
28599
28866
|
* {@link addItem}, direct `appendChild`, a framework binding). A bulk populate
|
|
28600
28867
|
* (roughly everything at once) is left alone, as are the wrapper `<li>`s the
|
|
@@ -28604,6 +28871,7 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
28604
28871
|
if (!this.isConnected) return;
|
|
28605
28872
|
if (this.#virtualActive()) {
|
|
28606
28873
|
this.#syncVirtualWindow(this.#reconcileRecords(records));
|
|
28874
|
+
this.#scheduleViewportChangeEmit();
|
|
28607
28875
|
return;
|
|
28608
28876
|
}
|
|
28609
28877
|
const fresh = [];
|
|
@@ -28614,6 +28882,7 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
28614
28882
|
this.#animatedItems.add(node);
|
|
28615
28883
|
fresh.push(node);
|
|
28616
28884
|
}
|
|
28885
|
+
this.#scheduleViewportChangeEmit();
|
|
28617
28886
|
if (fresh.length === 0) return;
|
|
28618
28887
|
if (this.#isBulkPopulate(fresh.length)) return;
|
|
28619
28888
|
for (const el of fresh) animateListItemIn(el);
|
|
@@ -29167,6 +29436,7 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
29167
29436
|
if (!ul) return;
|
|
29168
29437
|
this.#resizeObserver ??= new ResizeObserver(() => {
|
|
29169
29438
|
this.#syncVirtualWindow();
|
|
29439
|
+
this.#scheduleViewportChangeEmit();
|
|
29170
29440
|
});
|
|
29171
29441
|
this.#resizeObserver.observe(ul);
|
|
29172
29442
|
}
|
|
@@ -29246,6 +29516,32 @@ let VerticalListElement = class VerticalListElement extends i {
|
|
|
29246
29516
|
this._syncItemStates();
|
|
29247
29517
|
this._syncNativeDraggable();
|
|
29248
29518
|
this.#nativeDrag.refreshDraggable();
|
|
29519
|
+
this.#scheduleViewportChangeEmit();
|
|
29520
|
+
}
|
|
29521
|
+
/** Coalesce content/layout viewport checks to at most one animation frame. */
|
|
29522
|
+
#scheduleViewportChangeEmit() {
|
|
29523
|
+
if (this.#scrollRaf !== 0) return;
|
|
29524
|
+
this.#scrollRaf = requestAnimationFrame(() => {
|
|
29525
|
+
this.#scrollRaf = 0;
|
|
29526
|
+
this.#syncVirtualWindow();
|
|
29527
|
+
this.#emitViewportChangeIfChanged();
|
|
29528
|
+
});
|
|
29529
|
+
}
|
|
29530
|
+
/**
|
|
29531
|
+
* Dispatch `vertical-list-viewport-change` with the current key sets — unless
|
|
29532
|
+
* neither set changed since the last dispatch, so coalesced frames and
|
|
29533
|
+
* no-op scrolls stay silent.
|
|
29534
|
+
*/
|
|
29535
|
+
#emitViewportChangeIfChanged() {
|
|
29536
|
+
const renderedKeys = this.renderedKeys();
|
|
29537
|
+
const visibleKeys = this.visibleKeys();
|
|
29538
|
+
if (sameKeys(this.#lastViewportRenderedKeys, renderedKeys) && sameKeys(this.#lastViewportVisibleKeys, visibleKeys)) return;
|
|
29539
|
+
this.#lastViewportRenderedKeys = renderedKeys;
|
|
29540
|
+
this.#lastViewportVisibleKeys = visibleKeys;
|
|
29541
|
+
this._dispatch(`vertical-list-viewport-change`, {
|
|
29542
|
+
renderedKeys,
|
|
29543
|
+
visibleKeys
|
|
29544
|
+
});
|
|
29249
29545
|
}
|
|
29250
29546
|
_getVisibleItems() {
|
|
29251
29547
|
return Array.from(this.querySelectorAll(ITEM_SELECTOR)).filter((el) => {
|
|
@@ -46598,6 +46894,7 @@ let ToolbarElement = class ToolbarElement extends i {
|
|
|
46598
46894
|
this.invisibleGroups = false;
|
|
46599
46895
|
this.allowReorder = false;
|
|
46600
46896
|
this._overflowCount = 0;
|
|
46897
|
+
this._popoverOpen = false;
|
|
46601
46898
|
this._ro = null;
|
|
46602
46899
|
this._anchor = `--toolbar-${_ToolbarElement._cnt++}`;
|
|
46603
46900
|
this._sizes = /* @__PURE__ */ new WeakMap();
|
|
@@ -46723,11 +47020,11 @@ let ToolbarElement = class ToolbarElement extends i {
|
|
|
46723
47020
|
.overflow-btn[hidden] { display: none; }
|
|
46724
47021
|
.overflow-popover {
|
|
46725
47022
|
position: fixed;
|
|
46726
|
-
|
|
46727
|
-
|
|
47023
|
+
inset: auto;
|
|
47024
|
+
margin: 0;
|
|
46728
47025
|
position-anchor: var(--anchor-name);
|
|
46729
47026
|
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
|
|
46730
|
-
|
|
47027
|
+
position-visibility: anchors-visible;
|
|
46731
47028
|
max-height: min(60vh, 400px);
|
|
46732
47029
|
max-width: min(90vw, 320px);
|
|
46733
47030
|
overflow: auto;
|
|
@@ -46737,6 +47034,18 @@ let ToolbarElement = class ToolbarElement extends i {
|
|
|
46737
47034
|
flex-direction: column;
|
|
46738
47035
|
gap: var(--space-s);
|
|
46739
47036
|
}
|
|
47037
|
+
:host([orientation="horizontal"]) .overflow-popover {
|
|
47038
|
+
position-area: bottom span-left;
|
|
47039
|
+
margin-top: var(--toolbar-overflow-gap, 8px);
|
|
47040
|
+
}
|
|
47041
|
+
:host([orientation="vertical-left"]) .overflow-popover {
|
|
47042
|
+
position-area: right span-bottom;
|
|
47043
|
+
margin-left: var(--toolbar-overflow-gap, 8px);
|
|
47044
|
+
}
|
|
47045
|
+
:host([orientation="vertical-right"]) .overflow-popover {
|
|
47046
|
+
position-area: left span-bottom;
|
|
47047
|
+
margin-right: var(--toolbar-overflow-gap, 8px);
|
|
47048
|
+
}
|
|
46740
47049
|
.overflow-popover:popover-open { display: flex; }
|
|
46741
47050
|
.overflow-popover ::slotted(*) { writing-mode: horizontal-tb; text-orientation: mixed; }
|
|
46742
47051
|
|
|
@@ -46775,6 +47084,9 @@ let ToolbarElement = class ToolbarElement extends i {
|
|
|
46775
47084
|
});
|
|
46776
47085
|
this._ro = new ResizeObserver(() => this._scheduleMeasure());
|
|
46777
47086
|
this._ro.observe(this._inner);
|
|
47087
|
+
this._popover.addEventListener(`toggle`, () => {
|
|
47088
|
+
this._popoverOpen = this._popover.matches(`:popover-open`);
|
|
47089
|
+
});
|
|
46778
47090
|
this._scheduleMeasure();
|
|
46779
47091
|
this._updateGroups();
|
|
46780
47092
|
}
|
|
@@ -47115,7 +47427,7 @@ let ToolbarElement = class ToolbarElement extends i {
|
|
|
47115
47427
|
return b`
|
|
47116
47428
|
<div class="inner" role="toolbar" aria-orientation=${this.orientation}>
|
|
47117
47429
|
<slot @pointerdown=${this._onPointerDown} @keydown=${this._onKeyDown}></slot>
|
|
47118
|
-
<ixfx-button class="overflow-btn" ?hidden=${!hasOverflow} @click=${this._toggleOverflow} aria-label="More" aria-haspopup="true" aria-expanded=${this.
|
|
47430
|
+
<ixfx-button class="overflow-btn" ?hidden=${!hasOverflow} @click=${this._toggleOverflow} aria-label="More" aria-haspopup="true" aria-expanded=${this._popoverOpen}>⋯</ixfx-button>
|
|
47119
47431
|
</div>
|
|
47120
47432
|
<div class="overflow-popover popup-surface" popover="auto" @click=${(e) => e.stopPropagation()}>
|
|
47121
47433
|
<slot name="overflow"></slot>
|
|
@@ -47158,6 +47470,7 @@ __decorate([property({
|
|
|
47158
47470
|
reflect: true
|
|
47159
47471
|
})], ToolbarElement.prototype, "allowReorder", void 0);
|
|
47160
47472
|
__decorate([state()], ToolbarElement.prototype, "_overflowCount", void 0);
|
|
47473
|
+
__decorate([state()], ToolbarElement.prototype, "_popoverOpen", void 0);
|
|
47161
47474
|
__decorate([query(`.inner`)], ToolbarElement.prototype, "_inner", void 0);
|
|
47162
47475
|
__decorate([query(`.overflow-popover`)], ToolbarElement.prototype, "_popover", void 0);
|
|
47163
47476
|
__decorate([query(`slot`)], ToolbarElement.prototype, "_slot", void 0);
|