@ixfx/components 0.16.0 → 0.16.2
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 +290 -66
- package/bundle/index.js +412 -327
- package/dist/ac-text.d.ts +1 -1
- package/dist/{ac-token-qEs3FsQv.d.ts → ac-token-Cq7lsYf-.d.ts} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/ac-token.js +1 -1
- package/dist/{button-N92DKoWb.d.ts → button-D1sPDUCM.d.ts} +1 -1
- package/dist/button.d.ts +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/{crumb-navigation-YnFVFqrx.js → crumb-navigation-D3ndPgFg.js} +2 -2
- package/dist/{crumb-navigation-BbqfmkYs.d.ts → crumb-navigation-nnr881n-.d.ts} +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/crumbs.js +1 -1
- package/dist/{data-grid-CIG2DVip.d.ts → data-grid-BAEpfTkb.d.ts} +32 -5
- package/dist/{data-grid-rMkLX2qo.js → data-grid-CaPLWt5E.js} +159 -60
- package/dist/data-grid.d.ts +2 -2
- package/dist/data-grid.js +1 -1
- package/dist/{detail-list-C4pDSoI8.js → detail-list-C3XKTRmE.js} +86 -21
- package/dist/{detail-list-6iMTNP4N.d.ts → detail-list-DK49TsJd.d.ts} +26 -4
- package/dist/detail-list.d.ts +2 -2
- package/dist/detail-list.js +1 -1
- package/dist/{flat-list-JPgQSmLW.d.ts → flat-list-Bv4-qfjp.d.ts} +9 -4
- package/dist/flat-list.d.ts +1 -1
- package/dist/flat-list.js +6 -3
- package/dist/{grid-list-CdEkScn-.js → grid-list-51XsR2X2.js} +56 -18
- package/dist/{grid-list-D6n7WH8l.d.ts → grid-list-DaeSHv9P.d.ts} +58 -14
- package/dist/grid-list.d.ts +2 -2
- package/dist/grid-list.js +1 -1
- package/dist/{grouped-item-lister-DETte0Dh.d.ts → grouped-item-lister-DZIjo9nO.d.ts} +2 -2
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{icon-CDGprSdE.d.ts → icon-DR_3rSyZ.d.ts} +1 -1
- package/dist/icons.d.ts +2 -2
- package/dist/{incr-search-JIhwB49y.js → incr-search-2YaxUUA9.js} +150 -11
- package/dist/incr-search.d.ts +1 -1
- package/dist/incr-search.js +1 -1
- package/dist/{index-CoqtMSd9.d.ts → index-BUB5SICW.d.ts} +1 -1
- package/dist/{index-Dr80Zdl6.d.ts → index-BjRoPrwj.d.ts} +31 -4
- package/dist/{index-DN2BWctP.d.ts → index-Bz3loIAf.d.ts} +1 -1
- package/dist/{index-UvnoZUAo.d.ts → index-CJ5fshD3.d.ts} +1 -1
- package/dist/{index-DxyyVqzA.d.ts → index-DM9OLgTH.d.ts} +3 -2
- package/dist/{index-CYRc6Dah.d.ts → index-DXDz60XH.d.ts} +20 -1
- package/dist/{index-CYndvTWH.d.ts → index-garxxqgV.d.ts} +1 -1
- package/dist/{index-Bx0BXPxI.d.ts → index-vdbbGE7N.d.ts} +1 -1
- package/dist/index.d.ts +57 -28
- package/dist/index.js +58 -35
- package/dist/item-appearance-Bl6rMIID.js +60 -0
- package/dist/{labelled-input-base-DiTme1JO.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +1 -1
- package/dist/labelled-radial-input.d.ts +2 -2
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-slider-input.d.ts +1 -1
- package/dist/list-group-header.d.ts +1 -1
- package/dist/{list-selection-controller-5L0Nj9tR.js → list-selection-controller-CJDdjH7E.js} +192 -54
- package/dist/list-selection-types-hj9Njei3.d.ts +83 -0
- package/dist/{menu-CU9KAm8s.js → menu-BX1FHxY8.js} +16 -1
- package/dist/{menu-item-bF6narIz.d.ts → menu-item-B0zqw2xp.d.ts} +1 -1
- package/dist/{menu-item-BUv8An2k.js → menu-item-oxU1VKiJ.js} +34 -9
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -2
- package/dist/{miller-BFRfn0ve.js → miller-BfrTcujx.js} +142 -18
- package/dist/miller.d.ts +1 -1
- package/dist/miller.js +1 -1
- package/dist/narrowed-text.js +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/{split-layout-CophkNeU.d.ts → split-layout-ChZ0Glrs.d.ts} +1 -1
- package/dist/split-layout.d.ts +1 -1
- package/dist/sunburst-tree.d.ts +1 -1
- package/dist/sunburst-tree.js +1 -1
- package/dist/{sunbursttree-list-B_VxOHlo.js → sunbursttree-list-906G33ME.js} +1 -1
- package/dist/{sunbursttree-list-D6j5BxVQ.d.ts → sunbursttree-list-BAS0KrDG.d.ts} +1 -1
- package/dist/{tab-list-Df371rqw.d.ts → tab-list-wC0xNz1b.d.ts} +1 -1
- package/dist/tabs.d.ts +1 -1
- package/dist/{titlebar-Tqu-VvMU.d.ts → titlebar-B5zSTZnF.d.ts} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/{tree-Crdpl4nc.js → tree-C_H1COTf.js} +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/tree.js +1 -1
- package/dist/{vertical-list-BPDmZx6T.d.ts → vertical-list-od4050Bo.d.ts} +11 -2
- package/dist/{vertical-list-1V1Vg2O5.js → vertical-list-qMRIxZIT.js} +54 -20
- package/dist/vertical-list.d.ts +2 -2
- package/dist/vertical-list.js +1 -1
- package/docs-user/data-grid.md +23 -7
- package/docs-user/detail-list.md +16 -1
- package/docs-user/dock.md +12 -3
- package/docs-user/grid-list.md +9 -3
- package/docs-user/index.json +2 -2
- package/docs-user/menu.md +11 -1
- package/docs-user/vertical-list.md +9 -1
- package/package.json +2 -2
- package/dist/item-appearance-BjcMyauw.js +0 -29
- package/dist/list-selection-types-PjKdhF-a.d.ts +0 -45
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as TickledController } from "./tickled-controller-D-HZymaZ.js";
|
|
2
2
|
import { t as themeFallbacks } from "./fallbacks-DQ_5OsmR.js";
|
|
3
3
|
import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
|
|
4
|
-
import { c as createElementListSearchAdapter, i as ListSearchController, n as listSearchStyles, o as registerListSearchCommands, r as LIST_SEARCH_MODES, u as keyForElement } from "./incr-search-
|
|
4
|
+
import { c as createElementListSearchAdapter, d as keysOfElements, i as ListSearchController, n as listSearchStyles, o as registerListSearchCommands, r as LIST_SEARCH_MODES, u as keyForElement } from "./incr-search-2YaxUUA9.js";
|
|
5
5
|
import { i as animateListItemOut, r as animateListItemIn, t as ListNativeDragController } from "./list-native-drag-controller-CcXoS0YX.js";
|
|
6
|
-
import {
|
|
6
|
+
import { i as ListDragSelectController, n as gestureOf, t as ListSelectionController } from "./list-selection-controller-CJDdjH7E.js";
|
|
7
7
|
import { l as keysToArray } from "./pending-BGidHppL.js";
|
|
8
|
-
import { a as
|
|
8
|
+
import { a as isPartialKey, i as applyPartialAttributes, n as appearanceColor, o as sameKeySet, t as appearanceAbsent } from "./item-appearance-Bl6rMIID.js";
|
|
9
9
|
import { t as scrollFadeStyles } from "./scroll-fade-Xx28D7mH.js";
|
|
10
|
-
import { n as
|
|
10
|
+
import { a as restoreElementScroll, n as anchorFromRow, o as scrollToOffset, r as captureElementScroll, t as ViewStateController } from "./view-state-controller-BdyXWUUM.js";
|
|
11
11
|
import "./editable-label.js";
|
|
12
12
|
import { LitElement, css, html, render } from "lit";
|
|
13
13
|
import { property } from "lit/decorators.js";
|
|
@@ -153,13 +153,15 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
153
153
|
interactionMode: this.interactionMode
|
|
154
154
|
}),
|
|
155
155
|
getKey: keyForElement,
|
|
156
|
+
onIntent: (intent) => this._dispatchCancelable(`list-select-intent`, intent) === false,
|
|
156
157
|
onChange: (selected, previous) => {
|
|
157
158
|
this._syncItemStates();
|
|
158
159
|
this.#viewState.notify();
|
|
159
160
|
this._dispatch(`list-select`, {
|
|
160
161
|
selected,
|
|
161
162
|
previous,
|
|
162
|
-
selectedKeys: this.selection.selectedKeys
|
|
163
|
+
selectedKeys: this.selection.selectedKeys,
|
|
164
|
+
previousKeys: keysOfElements(previous)
|
|
163
165
|
});
|
|
164
166
|
}
|
|
165
167
|
});
|
|
@@ -245,6 +247,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
245
247
|
getAllItems: () => this.#selectionOrder(),
|
|
246
248
|
observeContainer: false
|
|
247
249
|
}) });
|
|
250
|
+
this.#partialKeys = /* @__PURE__ */ new Set();
|
|
248
251
|
this.#onScroll = () => {
|
|
249
252
|
if (!this.#viewState.pendingScroll) this.#viewState.notify();
|
|
250
253
|
if (this.#scrollRaf !== 0) return;
|
|
@@ -275,7 +278,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
275
278
|
if ((e.ctrlKey || e.metaKey) && e.key === `a`) {
|
|
276
279
|
if (this.selection.canSelectAll()) {
|
|
277
280
|
e.preventDefault();
|
|
278
|
-
this.selection.selectAll();
|
|
281
|
+
this.selection.selectAll(`keyboard`);
|
|
279
282
|
}
|
|
280
283
|
return;
|
|
281
284
|
}
|
|
@@ -284,18 +287,18 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
284
287
|
e.preventDefault();
|
|
285
288
|
this.tickled.handleKeyboardNavigation(`next`);
|
|
286
289
|
this.#revealCursor();
|
|
287
|
-
if (e.shiftKey && this.interactionMode === `vscode`) {
|
|
290
|
+
if (e.shiftKey && (this.interactionMode === `vscode` || this.interactionMode === `manual`)) {
|
|
288
291
|
const cur = this.tickled.tickledId;
|
|
289
|
-
if (cur) this.selection.
|
|
292
|
+
if (cur) this.selection.handleExtend(cur);
|
|
290
293
|
}
|
|
291
294
|
break;
|
|
292
295
|
case `ArrowUp`:
|
|
293
296
|
e.preventDefault();
|
|
294
297
|
this.tickled.handleKeyboardNavigation(`previous`);
|
|
295
298
|
this.#revealCursor();
|
|
296
|
-
if (e.shiftKey && this.interactionMode === `vscode`) {
|
|
299
|
+
if (e.shiftKey && (this.interactionMode === `vscode` || this.interactionMode === `manual`)) {
|
|
297
300
|
const cur = this.tickled.tickledId;
|
|
298
|
-
if (cur) this.selection.
|
|
301
|
+
if (cur) this.selection.handleExtend(cur);
|
|
299
302
|
}
|
|
300
303
|
break;
|
|
301
304
|
case `Home`:
|
|
@@ -321,7 +324,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
321
324
|
if (id) {
|
|
322
325
|
e.preventDefault();
|
|
323
326
|
this._dispatch(`list-item-click`, { item: id });
|
|
324
|
-
this._activateItem(id);
|
|
327
|
+
this._activateItem(id, `keyboard`);
|
|
325
328
|
}
|
|
326
329
|
break;
|
|
327
330
|
}
|
|
@@ -333,7 +336,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
333
336
|
}
|
|
334
337
|
break;
|
|
335
338
|
}
|
|
336
|
-
case `Escape`: this.selection.
|
|
339
|
+
case `Escape`: this.selection.handleClear(`keyboard`);
|
|
337
340
|
}
|
|
338
341
|
};
|
|
339
342
|
this._onClick = (e) => {
|
|
@@ -342,7 +345,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
342
345
|
const item = this._findListItem(e.composedPath());
|
|
343
346
|
if (!item) return;
|
|
344
347
|
this._dispatch(`list-item-click`, { item });
|
|
345
|
-
this.selection.handleClick(item, e);
|
|
348
|
+
this.selection.handleClick(item, gestureOf(e));
|
|
346
349
|
};
|
|
347
350
|
this._onDblClick = (e) => {
|
|
348
351
|
if (this.#isEditEvent(e)) return;
|
|
@@ -773,6 +776,23 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
773
776
|
get selectedKeys() {
|
|
774
777
|
return this.selection.selectedKeys;
|
|
775
778
|
}
|
|
779
|
+
#partialKeys;
|
|
780
|
+
/**
|
|
781
|
+
* Rows shown as *partially* selected (a part of the resource is selected):
|
|
782
|
+
* `data-partial`, an indeterminate checkbox in `checked` mode, and an
|
|
783
|
+
* accessible description. Independent of `selectedKeys` — a key in both
|
|
784
|
+
* counts as selected. Replace-on-set; keys without a row are kept for when
|
|
785
|
+
* the row appears.
|
|
786
|
+
*/
|
|
787
|
+
get partialKeys() {
|
|
788
|
+
return this.#partialKeys;
|
|
789
|
+
}
|
|
790
|
+
set partialKeys(keys) {
|
|
791
|
+
const next = new Set(keys);
|
|
792
|
+
if (sameKeySet(next, this.#partialKeys)) return;
|
|
793
|
+
this.#partialKeys = next;
|
|
794
|
+
this._syncItemStates();
|
|
795
|
+
}
|
|
776
796
|
/** The key of the item under the cursor, or `undefined`. */
|
|
777
797
|
get tickledKey() {
|
|
778
798
|
const id = this.tickled.tickledId;
|
|
@@ -1468,6 +1488,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1468
1488
|
const item = this.#customWrappers.get(el) ?? el;
|
|
1469
1489
|
el.toggleAttribute(`data-tickled`, this.tickled.isTickled(el));
|
|
1470
1490
|
el.toggleAttribute(`data-selected`, this.selection.selected.has(el));
|
|
1491
|
+
applyPartialAttributes(el, isPartialKey(keyForElement(el), this.#partialKeys, this.selection.selected.has(el)));
|
|
1471
1492
|
if (el.hasAttribute(`data-aria-role`)) el.setAttribute(`aria-selected`, String(this.selection.selected.has(el)));
|
|
1472
1493
|
if (this.interactionMode === `checked`) el.toggleAttribute(`data-checked`, !item.hasAttribute(`not-checked`) && this.selection.selected.has(el));
|
|
1473
1494
|
else el.removeAttribute(`data-checked`);
|
|
@@ -1532,16 +1553,22 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1532
1553
|
el.prepend(cb);
|
|
1533
1554
|
}
|
|
1534
1555
|
const checked = this.selection.selected.has(el);
|
|
1556
|
+
const partial = isPartialKey(keyForElement(el), this.#partialKeys, checked);
|
|
1535
1557
|
if (wantsCustom) {
|
|
1536
|
-
cb.setAttribute(`aria-checked`, String(checked));
|
|
1558
|
+
cb.setAttribute(`aria-checked`, partial ? `mixed` : String(checked));
|
|
1537
1559
|
cb.toggleAttribute(`data-checked`, checked);
|
|
1560
|
+
cb.toggleAttribute(`data-partial`, partial);
|
|
1538
1561
|
if (this.checkboxRenderer) {
|
|
1539
1562
|
const renderer = typeof this.checkboxRenderer === `function` ? this.checkboxRenderer : this.checkboxRenderer.renderer;
|
|
1540
1563
|
render(renderer(checked), cb);
|
|
1541
1564
|
}
|
|
1542
1565
|
} else {
|
|
1543
1566
|
const input = cb.querySelector(`input.ixfx-list-checkbox`);
|
|
1544
|
-
if (input)
|
|
1567
|
+
if (input) {
|
|
1568
|
+
input.checked = checked;
|
|
1569
|
+
input.indeterminate = partial;
|
|
1570
|
+
}
|
|
1571
|
+
cb.setAttribute(`aria-checked`, partial ? `mixed` : String(checked));
|
|
1545
1572
|
}
|
|
1546
1573
|
}
|
|
1547
1574
|
}
|
|
@@ -1560,7 +1587,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1560
1587
|
cell.setAttribute(`part`, `checkbox`);
|
|
1561
1588
|
cell.addEventListener(`click`, (e) => {
|
|
1562
1589
|
e.stopPropagation();
|
|
1563
|
-
this.selection.
|
|
1590
|
+
this.selection.handleCheckbox(el);
|
|
1564
1591
|
});
|
|
1565
1592
|
const input = document.createElement(`input`);
|
|
1566
1593
|
input.type = `checkbox`;
|
|
@@ -1582,7 +1609,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1582
1609
|
span.setAttribute(`part`, `checkbox`);
|
|
1583
1610
|
span.addEventListener(`click`, (e) => {
|
|
1584
1611
|
e.stopPropagation();
|
|
1585
|
-
this.selection.
|
|
1612
|
+
this.selection.handleCheckbox(el);
|
|
1586
1613
|
});
|
|
1587
1614
|
return span;
|
|
1588
1615
|
}
|
|
@@ -1608,13 +1635,13 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1608
1635
|
cancelable: true
|
|
1609
1636
|
}));
|
|
1610
1637
|
}
|
|
1611
|
-
_activateItem(item) {
|
|
1612
|
-
|
|
1638
|
+
_activateItem(item, source = `pointer`) {
|
|
1639
|
+
this.selection.handleReplace(item, source);
|
|
1613
1640
|
this._dispatch(`list-activate`, { item });
|
|
1614
1641
|
}
|
|
1615
1642
|
activateKey(key) {
|
|
1616
1643
|
const item = this.#itemForKey(key);
|
|
1617
|
-
if (item) this._activateItem(item);
|
|
1644
|
+
if (item) this._activateItem(item, `api`);
|
|
1618
1645
|
}
|
|
1619
1646
|
/** The row (or `undefined` for empty space) the last `list-drag-over` was fired for. */
|
|
1620
1647
|
#dragOver;
|
|
@@ -1862,6 +1889,13 @@ let VerticalListElement = class VerticalListElement extends LitElement {
|
|
|
1862
1889
|
outline: 1px solid transparent;
|
|
1863
1890
|
}
|
|
1864
1891
|
|
|
1892
|
+
/* Partially selected: a dashed edge, lighter than a full selection. Hook: --item-bg-partial. */
|
|
1893
|
+
::slotted([data-partial]) {
|
|
1894
|
+
background: var(--item-bg-partial, color-mix(in srgb, var(--item-bg-selected) 35%, transparent));
|
|
1895
|
+
outline: 1px dashed var(--item-border-partial, var(--border));
|
|
1896
|
+
outline-offset: -1px;
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1865
1899
|
::slotted([data-selected][data-tickled]) {
|
|
1866
1900
|
background: var(--item-bg-selected-tickled);
|
|
1867
1901
|
outline: 2px dashed var(--surface-3);
|
package/dist/vertical-list.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { B as ListNativeDragStartDetail, F as ListDragPreview, I as ListDragPreviewContext, L as ListDragPreviewRenderer, P as ListDragEntry, V as ListNativeDragStartEvent, z as ListDragSource } from "./tree-component-DgfkxmVY.js";
|
|
2
2
|
import { n as ListViewportChangeEvent, t as ListViewportChangeDetail } from "./list-viewport-types-BRZsLcvp.js";
|
|
3
|
-
import { a as ListItemClickDetail, c as ListSelectEvent,
|
|
4
|
-
import { a as VerticalListViewState, c as ListDragLeaveDetail, d as ListDropDetail, f as ListDropEvent, g as ListEditCommitEvent, h as ListEditCommitDetail, i as VerticalListElementEventMap, l as ListDragLeaveEvent, m as ListEditCancelEvent, n as CustomCheckboxOptions, o as ListContextMenuDetail, p as ListEditCancelDetail, r as VerticalListElement, s as ListContextMenuEvent, t as AddItemOptions, u as ListDragOverEvent } from "./vertical-list-
|
|
3
|
+
import { a as ListItemClickDetail, c as ListSelectEvent, g as ListTickleEvent, h as ListTickleDetail, i as ListInteractionMode, m as ListSelectionMode, n as ListActivateEvent, o as ListItemClickEvent, r as ListElementEventMap, s as ListSelectDetail, t as ListActivateDetail } from "./list-selection-types-hj9Njei3.js";
|
|
4
|
+
import { a as VerticalListViewState, c as ListDragLeaveDetail, d as ListDropDetail, f as ListDropEvent, g as ListEditCommitEvent, h as ListEditCommitDetail, i as VerticalListElementEventMap, l as ListDragLeaveEvent, m as ListEditCancelEvent, n as CustomCheckboxOptions, o as ListContextMenuDetail, p as ListEditCancelDetail, r as VerticalListElement, s as ListContextMenuEvent, t as AddItemOptions, u as ListDragOverEvent } from "./vertical-list-od4050Bo.js";
|
|
5
5
|
export { AddItemOptions, CustomCheckboxOptions, type ListActivateDetail, type ListActivateEvent, type ListContextMenuDetail, type ListContextMenuEvent, type ListDragEntry, type ListDragLeaveDetail, type ListDragLeaveEvent, type ListDragOverEvent, type ListDragPreview, type ListDragPreviewContext, type ListDragPreviewRenderer, type ListDragSource, type ListDropDetail, type ListDropEvent, type ListEditCancelDetail, type ListEditCancelEvent, type ListEditCommitDetail, type ListEditCommitEvent, type ListElementEventMap, type ListInteractionMode, type ListItemClickDetail, type ListItemClickEvent, type ListNativeDragStartDetail, type ListNativeDragStartEvent, type ListSelectDetail, type ListSelectEvent, type ListSelectionMode, type ListTickleDetail, type ListTickleEvent, type ListViewportChangeDetail, type ListViewportChangeEvent, VerticalListElement, VerticalListElementEventMap, type VerticalListViewState };
|
package/dist/vertical-list.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as VerticalListElement } from "./vertical-list-
|
|
1
|
+
import { t as VerticalListElement } from "./vertical-list-qMRIxZIT.js";
|
|
2
2
|
export { VerticalListElement };
|
package/docs-user/data-grid.md
CHANGED
|
@@ -222,9 +222,16 @@ grid.tickleRow('r7'); // move the row cursor + scroll it into view
|
|
|
222
222
|
grid.tickledKey; // row key under the cursor, or undefined
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
-
The setter fires `datagrid-select` `{ selectedKeys, previous }`
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
The setter fires `datagrid-select` `{ selectedKeys, previous }` (and `list-select`
|
|
226
|
+
`{ selectedKeys, previousKeys, previous }`, the name the other list components use)
|
|
227
|
+
only when the selection actually changes. A cancelable `list-select-intent` fires
|
|
228
|
+
before every selection gesture, and `partialKeys` marks partially selected rows
|
|
229
|
+
(`data-partial`, indeterminate checkbox in `checked` mode).
|
|
230
|
+
See [Selection intents, partial rows, unloaded keys](../../docs/infra-selection-intents.md): `list-select-intent`, `partialKeys`, and keys that arrive later.
|
|
231
|
+
|
|
232
|
+
Selected rows that leave `rows` are deselected silently, and reselected if they
|
|
233
|
+
return. See [View state](#view-state). In `checked` mode the row checkbox toggles
|
|
234
|
+
the row.
|
|
228
235
|
|
|
229
236
|
---
|
|
230
237
|
|
|
@@ -506,10 +513,19 @@ rows dropped from the flat list) modes. No default shortcut:
|
|
|
506
513
|
grid.registry.invoke('list.search.filter'); // or .navigate / .select
|
|
507
514
|
```
|
|
508
515
|
|
|
509
|
-
A row is matched against
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
516
|
+
A row is matched against the displayed (formatted) text of one column: the
|
|
517
|
+
`search-column` attribute (`searchColumn` property) names it, defaulting to the
|
|
518
|
+
first visible column. Searching every column makes dates and sizes match
|
|
519
|
+
queries like `12`, which is rarely what Find is for. Set the `rowSearchText`
|
|
520
|
+
property, `(row) => string`, to match against something else, e.g. several
|
|
521
|
+
columns joined. `select` mode needs `selection-mode="multiple"` to hold more
|
|
522
|
+
than one row.
|
|
523
|
+
|
|
524
|
+
Matched characters in the search column are highlighted under the
|
|
525
|
+
`data-grid-search` key, coloured by `--search-highlight-bg` /
|
|
526
|
+
`--search-highlight-color` (default `--accent` / `--accent-text`). Matches
|
|
527
|
+
against a custom `rowSearchText` aren't highlighted, since they can't be
|
|
528
|
+
mapped onto a cell, and neither are cells drawn by a column `renderer`. `filterPredicate`
|
|
513
529
|
(a `(row) => boolean` property) filters rows directly. `search-modes` limits the
|
|
514
530
|
offered modes. Full model: [`docs/infra-incremental.md`](../../docs/infra-incremental.md).
|
|
515
531
|
|
package/docs-user/detail-list.md
CHANGED
|
@@ -162,6 +162,7 @@ list.keyProperty = 'name'; // Preserves selection across rebuilds
|
|
|
162
162
|
| `textColorProperty` | `string` | Property name for the caption's CSS colour |
|
|
163
163
|
| `badgeProperty` | `string` | Property name for a Finder-style badge |
|
|
164
164
|
| `formatter` | `(item: unknown, index: number) => string \| Node` | Custom renderer |
|
|
165
|
+
| `searchText` | `(item: unknown, index: number) => string` | Text incremental search matches (default: the caption if a string, else the row's whole text) |
|
|
165
166
|
|
|
166
167
|
```typescript
|
|
167
168
|
list.formatter = (item, index) => {
|
|
@@ -177,6 +178,18 @@ put, and the new row animates in like `addItem()`. Pass new objects (or change
|
|
|
177
178
|
`displayProperty`, `formatter`, …) to rebuild rows. With a `formatter`, a row
|
|
178
179
|
is only kept at the same index, since the formatter receives the index.
|
|
179
180
|
|
|
181
|
+
Because reused rows aren't re-run through the `formatter`, state it reads from
|
|
182
|
+
outside the item (sizes, fit mode, …) doesn't reach existing rows when the same
|
|
183
|
+
objects are reassigned. Call `list.reformat()` to rebuild every row, or assign a
|
|
184
|
+
new `formatter` function (a new identity counts as a shape change).
|
|
185
|
+
|
|
186
|
+
When `formatter` returns a `Node`, search falls back to the row's whole text
|
|
187
|
+
(sublines, sizes, dates). Set `searchText` to match on just the name:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
list.searchText = item => (item as { name: string }).name;
|
|
191
|
+
```
|
|
192
|
+
|
|
180
193
|
Retrieve the original data for an element:
|
|
181
194
|
|
|
182
195
|
```typescript
|
|
@@ -297,7 +310,7 @@ the Element API is unchanged, the key API is additive. Object items built from
|
|
|
297
310
|
`items` / a provider get their key stamped automatically from `keyProperty`.
|
|
298
311
|
|
|
299
312
|
```typescript
|
|
300
|
-
list.selectKeys(['row-3', 'row-7']); // replace selection;
|
|
313
|
+
list.selectKeys(['row-3', 'row-7']); // replace selection; keys with no row yet apply when the row appears
|
|
301
314
|
list.addSelectedKeys(['row-9']); // multi-select modes only
|
|
302
315
|
list.removeSelectedKeys(['row-3']);
|
|
303
316
|
list.selectedKeys; // ReadonlySet<string>
|
|
@@ -459,6 +472,8 @@ Search matches against `data-search-label` (or `textContent` as fallback). Use `
|
|
|
459
472
|
<li data-search-label="document a alpha">Document A</li>
|
|
460
473
|
```
|
|
461
474
|
|
|
475
|
+
For object items, `searchText` sets `data-search-label` per row (see [Object items](#object-items)).
|
|
476
|
+
|
|
462
477
|
### Highlight styling
|
|
463
478
|
|
|
464
479
|
Matched characters are highlighted with the `detail-list-search` highlight key. Style matches with:
|
package/docs-user/dock.md
CHANGED
|
@@ -228,7 +228,9 @@ The host consumes `ixfx-split-layout` events: `ixfx-split-resize` /
|
|
|
228
228
|
```ts
|
|
229
229
|
getViewState(options?): DockHostViewState // { v, kind: 'dock-host', layout }; folds live split weights
|
|
230
230
|
setViewState(state: Partial<DockHostViewState>): void
|
|
231
|
-
clearPendingViewState(): void //
|
|
231
|
+
clearPendingViewState(): void // drops placeholders (panels the host doesn't hold)
|
|
232
|
+
saveLayout(): DockLayout // deprecated alias of getViewState().layout
|
|
233
|
+
loadLayout(layout: DockLayout): void // deprecated alias of setViewState({ layout })
|
|
232
234
|
addPanel(panel: DockPanelElement | DockPanelInit, target?: DockAddPanelTarget): boolean
|
|
233
235
|
type DockAddPanelTarget = {
|
|
234
236
|
container?: string; // named stack leaf — takes precedence over `stack`
|
|
@@ -259,6 +261,7 @@ getNeighbours(leaf: DockLeafRef): DockNeighbours | null
|
|
|
259
261
|
moveLeaf(leaf: DockLeafRef, direction: 'up' | 'down' | 'left' | 'right'): boolean
|
|
260
262
|
moveLeafToEdge(leaf: DockLeafRef, edge: 'top' | 'bottom' | 'left' | 'right'): boolean
|
|
261
263
|
canAccept?: (panelId: string, op: DockOperation) => boolean
|
|
264
|
+
placeholderLabel?: (panelId: string) => string // tab label for placeholders (default: the id)
|
|
262
265
|
|
|
263
266
|
// Cross-window hooks (serializable in/out; no element handoff)
|
|
264
267
|
getPanelSnapshot(panelId: string): DockPanelSnapshot | null
|
|
@@ -456,13 +459,19 @@ The dock layout is close to structure, so the saved state *is* the tree
|
|
|
456
459
|
a save → drag → save round-trip preserves user adjustments.
|
|
457
460
|
- **Panels not in the host yet.** `setViewState()` keeps every panel id the
|
|
458
461
|
layout names, held or not. One the host doesn't hold is a *placeholder*:
|
|
459
|
-
it keeps its place in the tree (shown as a tab labelled
|
|
462
|
+
it keeps its place in the tree (shown as a tab labelled by the
|
|
463
|
+
`placeholderLabel(panelId)` property, or its id when unset) and
|
|
460
464
|
the panel slots into that place when it arrives — appended as a light-DOM
|
|
461
465
|
child, `addPanel()` **without** a target, `acceptExternalPanel()` without
|
|
462
466
|
`at`, or a cross-host adoption. An explicit `addPanel()` target still wins.
|
|
463
467
|
Placeholders are saved by `getViewState()`; `includePending: false` leaves
|
|
464
468
|
them out (stacks they empty are dropped unless named). Remove one with
|
|
465
|
-
`removePanel(id)
|
|
469
|
+
`removePanel(id)`, or all of them with `clearPendingViewState()`.
|
|
470
|
+
- **Persisting with the default keeps stale ids.** A placeholder for a panel
|
|
471
|
+
that no longer exists is saved again on every `getViewState()`, so it never
|
|
472
|
+
goes away. Apps whose panels can disappear between save and restore should
|
|
473
|
+
call `clearPendingViewState()` once they have added the panels they hold,
|
|
474
|
+
or save with `includePending: false`.
|
|
466
475
|
- Pooled panels the layout doesn't name are appended to the first stack
|
|
467
476
|
admitting their kind.
|
|
468
477
|
- A panel that is closed / removed (`removePanel`, close button, removed from
|
package/docs-user/grid-list.md
CHANGED
|
@@ -183,7 +183,7 @@ See `docs-user/grid-list.md`.
|
|
|
183
183
|
item, drive selection by key instead — additive, the Element API is unchanged.
|
|
184
184
|
|
|
185
185
|
```typescript
|
|
186
|
-
grid.selectKeys(['a', 'c']); // replace;
|
|
186
|
+
grid.selectKeys(['a', 'c']); // replace; keys with no cell yet apply when the cell appears
|
|
187
187
|
grid.addSelectedKeys(['b']); // multi-select modes only
|
|
188
188
|
grid.removeSelectedKeys(['a']);
|
|
189
189
|
grid.selectedKeys; // ReadonlySet<string>
|
|
@@ -193,6 +193,9 @@ grid.addEventListener('list-select', ({ detail }) => {
|
|
|
193
193
|
});
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
+
Caller-owned selection: a cancelable `list-select-intent` fires before every gesture, and `partialKeys` marks partially selected cells (`data-partial`, `part="item partial"`).
|
|
197
|
+
See [Selection intents, partial rows, unloaded keys](../../docs/infra-selection-intents.md): `list-select-intent`, `partialKeys`, and keys that arrive later.
|
|
198
|
+
|
|
196
199
|
Restore across a reload:
|
|
197
200
|
|
|
198
201
|
```typescript
|
|
@@ -311,8 +314,11 @@ grid.registry.invoke('list.search.filter'); // or .navigate / .select
|
|
|
311
314
|
|
|
312
315
|
Search matches `data-label` (or `[data-grid-list-caption]` text, then
|
|
313
316
|
`data-search-label`, then `textContent`). Filter mode genuinely removes items
|
|
314
|
-
from the virtualised layout.
|
|
315
|
-
|
|
317
|
+
from the virtualised layout. Matched characters are highlighted under the
|
|
318
|
+
`grid-list-search` key. In data mode (`itemAdapter`) the captions live in the
|
|
319
|
+
shadow root and the grid styles them itself (`--search-highlight-bg` /
|
|
320
|
+
`--search-highlight-color`, default `--accent` / `--accent-text`). In element
|
|
321
|
+
mode the items are light DOM, so add a page-level rule:
|
|
316
322
|
|
|
317
323
|
```css
|
|
318
324
|
::highlight(grid-list-search) { background: var(--accent); color: var(--accent-text); }
|
package/docs-user/index.json
CHANGED
package/docs-user/menu.md
CHANGED
|
@@ -6,7 +6,7 @@ A custom menu system built on native HTML popovers with keyboard navigation, tic
|
|
|
6
6
|
|
|
7
7
|
| Component | Description |
|
|
8
8
|
|------------|-------------|
|
|
9
|
-
| `ixfx-menu-bar` | Horizontal container for menu triggers; handles arrow-key navigation between top-level menus |
|
|
9
|
+
| `ixfx-menu-bar` | Horizontal container for menu triggers; handles arrow-key navigation between top-level menus; while a menu is open, hovering another top-level trigger switches to its menu |
|
|
10
10
|
| `ixfx-menu-trigger` | Button or slot that opens a menu popover. Modes: `trigger` (button), `dropdown` (slot-only), `context` (right-click) |
|
|
11
11
|
| `ixfx-menu-container` | The popover panel holding menu items; manages keyboard focus and tickled state |
|
|
12
12
|
| `ixfx-menu-item` | Basic menu item that dispatches a `command` event |
|
|
@@ -254,6 +254,16 @@ The trigger button and menu bar additionally expose a couple of underscore-prefi
|
|
|
254
254
|
| `--_trigger-hover-bg` | `var(--surface-4)` | Trigger button hover background |
|
|
255
255
|
| `--_trigger-hover-opacity` | `1` | Trigger button hover opacity |
|
|
256
256
|
|
|
257
|
+
Public layout variables:
|
|
258
|
+
|
|
259
|
+
| Variable | Default | Description |
|
|
260
|
+
|----------|---------|-------------|
|
|
261
|
+
| `--ixfx-button-padding` | `var(--space-s) var(--space-m)` | Padding of the default trigger button |
|
|
262
|
+
| `--menu-max-height` | `min(60vh, 400px)` | Max height of a menu panel; taller menus scroll, with an edge fade |
|
|
263
|
+
| `--menu-popup-offset` | `var(--space-xs)` | Distance between a trigger and its menu popup |
|
|
264
|
+
| `--menu-bar-gap` | `var(--space-xs)` | Gap between top-level triggers in `ixfx-menu-bar` |
|
|
265
|
+
| `--menu-bar-padding` | `var(--space-xs)` | Padding around the items in `ixfx-menu-bar` |
|
|
266
|
+
|
|
257
267
|
The popup surface uses these from `popupSurfaceStyles`:
|
|
258
268
|
|
|
259
269
|
| Variable | Description |
|
|
@@ -441,7 +441,7 @@ unchanged — the key API is additive.
|
|
|
441
441
|
```
|
|
442
442
|
|
|
443
443
|
```typescript
|
|
444
|
-
list.selectKeys(['a', 'c']); // replace selection;
|
|
444
|
+
list.selectKeys(['a', 'c']); // replace selection; keys with no row yet apply when the row appears
|
|
445
445
|
list.addSelectedKeys(['b']); // multi-select modes only
|
|
446
446
|
list.removeSelectedKeys(['a']);
|
|
447
447
|
list.selectedKeys; // ReadonlySet<string>, e.g. Set { 'b', 'c' }
|
|
@@ -512,6 +512,7 @@ All events **bubble** and are **composed** (they cross shadow-DOM boundaries).
|
|
|
512
512
|
| Event | Detail type | When fired |
|
|
513
513
|
|---|---|---|
|
|
514
514
|
| `list-select` | `ListSelectDetail` | Selection changes by any means |
|
|
515
|
+
| `list-select-intent` | `ListSelectIntentDetail` | Cancelable; a gesture is about to change the selection (see below) |
|
|
515
516
|
| `list-tickle` | `ListTickleDetail` | An item enters cursor focus (hover or keyboard navigation) |
|
|
516
517
|
| `list-activate` | `ListActivateDetail` | User explicitly activates an item: Enter key or double-click |
|
|
517
518
|
| `list-item-click` | `ListItemClickDetail` | Raw click or Enter on any item |
|
|
@@ -524,6 +525,8 @@ All events **bubble** and are **composed** (they cross shadow-DOM boundaries).
|
|
|
524
525
|
type ListSelectDetail = {
|
|
525
526
|
readonly selected: ReadonlySet<Element>; // Current full selection
|
|
526
527
|
readonly previous: ReadonlySet<Element>; // Selection before this change
|
|
528
|
+
readonly selectedKeys: ReadonlySet<string>;
|
|
529
|
+
readonly previousKeys: ReadonlySet<string>;
|
|
527
530
|
};
|
|
528
531
|
|
|
529
532
|
type ListTickleDetail = { readonly item: Element };
|
|
@@ -531,6 +534,11 @@ type ListActivateDetail = { readonly item: Element };
|
|
|
531
534
|
type ListItemClickDetail = { readonly item: Element };
|
|
532
535
|
```
|
|
533
536
|
|
|
537
|
+
### Caller-owned selection: `list-select-intent` and `partialKeys`
|
|
538
|
+
|
|
539
|
+
`list-select-intent` is fired before any gesture changes the selection (in every `interactionMode`, including `manual`); `preventDefault()` means "I'll apply it". `partialKeys` marks rows as partially selected (`data-partial`, indeterminate checkbox in `checked` mode). Both are shared across the list-like components.
|
|
540
|
+
See [Selection intents, partial rows, unloaded keys](../../docs/infra-selection-intents.md): `list-select-intent`, `partialKeys`, and keys that arrive later.
|
|
541
|
+
|
|
534
542
|
### Usage example
|
|
535
543
|
|
|
536
544
|
```typescript
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixfx/components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.2",
|
|
5
5
|
"packageManager": "pnpm@10.0.0",
|
|
6
6
|
"description": "Web components for ixfx — Lit-based UI toolkit",
|
|
7
7
|
"author": "Clint Heyer",
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
"lit": { "optional": false }
|
|
248
248
|
},
|
|
249
249
|
"dependencies": {
|
|
250
|
-
"@clinth/ui-commands": "1.1.
|
|
250
|
+
"@clinth/ui-commands": "1.1.1",
|
|
251
251
|
"@clinth/vcanvas": "0.0.5",
|
|
252
252
|
"@ixfx/arrays": "0.56.14",
|
|
253
253
|
"@ixfx/collections": "0.56.14",
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
//#region src/common/item-appearance.ts
|
|
2
|
-
/**
|
|
3
|
-
* Shared helpers for the list components' per-item appearance hooks — the
|
|
4
|
-
* per-item icon colour / text colour / badge that miller-list, detail-list,
|
|
5
|
-
* grid-list, data-grid and vertical-list all accept.
|
|
6
|
-
*
|
|
7
|
-
* Every component takes these three features in its own idiom (plain fields
|
|
8
|
-
* on a `TreeItem`, a property-name lookup, an adapter function, a nominated
|
|
9
|
-
* column) but they all agree on what "not supplied" means, and on never
|
|
10
|
-
* emitting an empty slot for an absent value.
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* Whether a per-item appearance value counts as "not supplied". `false` and
|
|
14
|
-
* `''` are included so a consumer can clear a feature without rebuilding the
|
|
15
|
-
* collection — e.g. `badge: flags && tagChip(flags.colour)`.
|
|
16
|
-
*/
|
|
17
|
-
function appearanceAbsent(value) {
|
|
18
|
-
return value === void 0 || value === null || value === false || value === ``;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* A usable CSS colour from a per-item value, or `undefined`. Non-strings and
|
|
22
|
-
* empty strings are ignored rather than stringified, so a stray number or
|
|
23
|
-
* `0` never lands in a `style` attribute.
|
|
24
|
-
*/
|
|
25
|
-
function appearanceColor(value) {
|
|
26
|
-
return typeof value === `string` && value.length > 0 ? value : void 0;
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
|
-
export { appearanceColor as n, appearanceAbsent as t };
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
//#region src/interaction/list-selection-types.d.ts
|
|
2
|
-
type ListSelectionMode = `none` | `single` | `multiple`;
|
|
3
|
-
/**
|
|
4
|
-
* Controls how pointer and keyboard gestures map to selection changes.
|
|
5
|
-
*
|
|
6
|
-
* - `implicit` — click always replaces selection (no modifier support)
|
|
7
|
-
* - `standard` — click replaces; Ctrl/Cmd+click toggles; Shift+click range-selects (multiple only)
|
|
8
|
-
* - `manual` — no auto-selection; drive state via select()/deselect()/clearSelection()
|
|
9
|
-
* - `checked` — every click toggles; implies multiple selection regardless of selectionMode
|
|
10
|
-
* - `sticky` — every tap/click toggles (no checkbox column); implies multiple selection, for touchscreens
|
|
11
|
-
* - `vscode` — like standard for clicks; Shift+Arrow extends range from the keyboard anchor
|
|
12
|
-
*
|
|
13
|
-
* Switching interactionMode clears the current selection.
|
|
14
|
-
*/
|
|
15
|
-
type ListInteractionMode = `implicit` | `standard` | `manual` | `checked` | `sticky` | `vscode`;
|
|
16
|
-
type ListSelectDetail = {
|
|
17
|
-
readonly selected: ReadonlySet<Element>;
|
|
18
|
-
readonly previous: ReadonlySet<Element>;
|
|
19
|
-
/**
|
|
20
|
-
* The selection as stable key strings (`data-key` / `data-value`). Empty
|
|
21
|
-
* when items carry no key. Additive to `selected`.
|
|
22
|
-
*/
|
|
23
|
-
readonly selectedKeys: ReadonlySet<string>;
|
|
24
|
-
};
|
|
25
|
-
type ListTickleDetail = {
|
|
26
|
-
readonly item: Element;
|
|
27
|
-
};
|
|
28
|
-
type ListActivateDetail = {
|
|
29
|
-
readonly item: Element;
|
|
30
|
-
};
|
|
31
|
-
type ListItemClickDetail = {
|
|
32
|
-
readonly item: Element;
|
|
33
|
-
};
|
|
34
|
-
type ListSelectEvent = CustomEvent<ListSelectDetail>;
|
|
35
|
-
type ListTickleEvent = CustomEvent<ListTickleDetail>;
|
|
36
|
-
type ListActivateEvent = CustomEvent<ListActivateDetail>;
|
|
37
|
-
type ListItemClickEvent = CustomEvent<ListItemClickDetail>;
|
|
38
|
-
interface ListElementEventMap {
|
|
39
|
-
'list-select': ListSelectEvent;
|
|
40
|
-
'list-tickle': ListTickleEvent;
|
|
41
|
-
'list-activate': ListActivateEvent;
|
|
42
|
-
'list-item-click': ListItemClickEvent;
|
|
43
|
-
}
|
|
44
|
-
//#endregion
|
|
45
|
-
export { ListItemClickDetail as a, ListSelectEvent as c, ListTickleEvent as d, ListInteractionMode as i, ListSelectionMode as l, ListActivateEvent as n, ListItemClickEvent as o, ListElementEventMap as r, ListSelectDetail as s, ListActivateDetail as t, ListTickleDetail as u };
|