@ixfx/components 0.7.3 → 0.7.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 +1355 -526
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +3277 -384
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/ac-text.js +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/ac-token.js +2 -2
- package/dist/button.d.ts +1 -1
- package/dist/button.d.ts.map +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/crumbs.d.ts +6 -2
- package/dist/crumbs.d.ts.map +1 -1
- package/dist/crumbs.js +13 -3
- package/dist/crumbs.js.map +1 -1
- package/dist/{data-grid-Db4QpnII.d.ts → data-grid-CtJ35v8L.d.ts} +59 -2
- package/dist/data-grid-CtJ35v8L.d.ts.map +1 -0
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +268 -14
- package/dist/data-grid.js.map +1 -1
- package/dist/detail-list-BS5dRDda.d.ts +175 -0
- package/dist/detail-list-BS5dRDda.d.ts.map +1 -0
- package/dist/detail-list.d.ts +3 -0
- package/dist/detail-list.js +1031 -0
- package/dist/detail-list.js.map +1 -0
- package/dist/grid-list-D-GbghSH.d.ts +321 -0
- package/dist/grid-list-D-GbghSH.d.ts.map +1 -0
- package/dist/grid-list.d.ts +3 -0
- package/dist/grid-list.js +994 -0
- package/dist/grid-list.js.map +1 -0
- package/dist/{grouped-item-lister-BWlC9S4e.d.ts → grouped-item-lister-fdZHVxFM.d.ts} +3 -3
- package/dist/{grouped-item-lister-BWlC9S4e.d.ts.map → grouped-item-lister-fdZHVxFM.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-DpbSJtgj.js +962 -0
- package/dist/incr-search-DpbSJtgj.js.map +1 -0
- package/dist/incr-search.d.ts +2 -2
- package/dist/incr-search.js +2 -3
- 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-CBS4z1v-.d.ts +365 -0
- package/dist/index-CBS4z1v-.d.ts.map +1 -0
- package/dist/{index-DsjpDksO.d.ts → index-CS9yM8L-.d.ts} +2 -2
- package/dist/{index-DsjpDksO.d.ts.map → index-CS9yM8L-.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-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 +188 -243
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +376 -1004
- package/dist/index.js.map +1 -1
- package/dist/interaction-Cr13azbM.js +3 -0
- 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-item-animation-DuiwgN3l.js +112 -0
- package/dist/list-item-animation-DuiwgN3l.js.map +1 -0
- package/dist/list-selection-controller-DTFI40li.js +264 -0
- package/dist/list-selection-controller-DTFI40li.js.map +1 -0
- package/dist/{list-selection-types-DSuRNWpx.d.ts → list-selection-types-B5ioL-dG.d.ts} +6 -1
- package/dist/list-selection-types-B5ioL-dG.d.ts.map +1 -0
- package/dist/{menu-DMzjkVnK.js → menu-Bg90Qr0B.js} +3 -3
- package/dist/{menu-DMzjkVnK.js.map → menu-Bg90Qr0B.js.map} +1 -1
- package/dist/{menu-item-D2S4i8u1.js → menu-item-Bx-Fs7jq.js} +3 -3
- package/dist/{menu-item-D2S4i8u1.js.map → menu-item-Bx-Fs7jq.js.map} +1 -1
- 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/menu.js +2 -2
- package/dist/miller.d.ts +82 -4
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +329 -70
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.js +3 -4
- package/dist/narrowed-text.js.map +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/plots.js +1 -1
- package/dist/select-horiz.js +2 -2
- 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-CGyPt07Z.d.ts} +2 -2
- package/dist/{tab-list-DbMIL520.d.ts.map → tab-list-CGyPt07Z.d.ts.map} +1 -1
- package/dist/tabs.d.ts +1 -1
- package/dist/{tickled-controller-Ds1DMyG7.d.ts → tickled-controller-Bn3YdQsM.d.ts} +12 -1
- package/dist/{tickled-controller-Ds1DMyG7.d.ts.map → tickled-controller-Bn3YdQsM.d.ts.map} +1 -1
- package/dist/{tickled-controller-h9GmJ_bU.js → tickled-controller-C66DgJHl.js} +16 -1
- package/dist/tickled-controller-C66DgJHl.js.map +1 -0
- package/dist/{titlebar-B23MrIbI.d.ts → titlebar-Bj5pfdw_.d.ts} +2 -2
- package/dist/{titlebar-B23MrIbI.d.ts.map → titlebar-Bj5pfdw_.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/{tree-Ch4W8qXQ.js → tree-DAii2A1g.js} +190 -29
- package/dist/tree-DAii2A1g.js.map +1 -0
- package/dist/{tree-component-BvV4muxx.d.ts → tree-component-F6qZ0Gdv.d.ts} +9 -1
- package/dist/{tree-component-BvV4muxx.d.ts.map → tree-component-F6qZ0Gdv.d.ts.map} +1 -1
- package/dist/tree.d.ts +28 -4
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +1 -1
- package/dist/vertical-list-DwtCPy1b.d.ts +143 -0
- package/dist/vertical-list-DwtCPy1b.d.ts.map +1 -0
- package/dist/vertical-list.d.ts +3 -121
- package/dist/vertical-list.js +642 -1
- package/dist/vertical-list.js.map +1 -0
- package/dist/{xy-axis-DWizs0bt.js → xy-axis-VrX8dmvS.js} +2 -2
- package/dist/{xy-axis-DWizs0bt.js.map → xy-axis-VrX8dmvS.js.map} +1 -1
- package/docs-user/README.md +1 -0
- package/docs-user/data-grid.md +70 -2
- package/docs-user/detail-list.md +39 -1
- package/docs-user/grid-list.md +298 -0
- package/docs-user/incr-search.md +12 -2
- package/docs-user/index.json +7 -2
- package/docs-user/llms.txt +1 -0
- package/docs-user/tree.md +35 -1
- package/docs-user/vertical-list.md +58 -2
- package/llms.txt +1 -0
- package/package.json +17 -2
- package/dist/data-grid-Db4QpnII.d.ts.map +0 -1
- package/dist/element-search-Y8SRfPGM.js +0 -185
- package/dist/element-search-Y8SRfPGM.js.map +0 -1
- package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
- package/dist/incr-search-vCzuao-2.js +0 -137
- package/dist/incr-search-vCzuao-2.js.map +0 -1
- package/dist/index-Cu5i8zZY.d.ts +0 -160
- package/dist/index-Cu5i8zZY.d.ts.map +0 -1
- package/dist/interaction-D5XdKzbR.js +0 -2
- package/dist/list-selection-types-DSuRNWpx.d.ts.map +0 -1
- package/dist/tickled-controller-h9GmJ_bU.js.map +0 -1
- package/dist/tree-Ch4W8qXQ.js.map +0 -1
- package/dist/vertical-list-B4w_ksJk.js +0 -814
- package/dist/vertical-list-B4w_ksJk.js.map +0 -1
- package/dist/vertical-list.d.ts.map +0 -1
package/docs-user/data-grid.md
CHANGED
|
@@ -65,6 +65,30 @@ grid.getRowKey = (row, i) => row.key ?? row.id ?? String(i);
|
|
|
65
65
|
|
|
66
66
|
Reassign `rows` to update. Sorting is derived from `sortState`.
|
|
67
67
|
|
|
68
|
+
When the row set changes without a wholesale replace — rows spliced in, rows
|
|
69
|
+
filtered out — the new rows fade in and, for ~0.3s afterwards, every row slides
|
|
70
|
+
to its new position instead of snapping (so an inserted row's neighbours make
|
|
71
|
+
room and a removed row's gap closes). Skipped under `prefers-reduced-motion:
|
|
72
|
+
reduce`; timing is `--data-grid-row-move-duration` (default `200ms`).
|
|
73
|
+
|
|
74
|
+
### Streaming appends — `appendRows()`
|
|
75
|
+
|
|
76
|
+
Reassigning `rows` re-runs `_applySort([...rows])` + `_rebuildFlat()` every
|
|
77
|
+
time — O(n log n) per batch, quadratic over a full load. When feeding the grid
|
|
78
|
+
from a stream (paged fetch, incremental scan), use `appendRows()` instead:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
for await (const batch of stream) {
|
|
82
|
+
grid.appendRows(batch);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
It still sets `rows` to a new array reference (reactivity preserved) but
|
|
87
|
+
**bypasses the `rows` setter's full rebuild** — the derived arrays are extended
|
|
88
|
+
over the appended slice only. When a sort is active the new rows show unsorted
|
|
89
|
+
for one frame, then a single coalesced re-sort runs. Scroll position, selection
|
|
90
|
+
and cursor are preserved across the append.
|
|
91
|
+
|
|
68
92
|
---
|
|
69
93
|
|
|
70
94
|
## Selection & interaction
|
|
@@ -76,7 +100,19 @@ Reassign `rows` to update. Sorting is derived from `sortState`.
|
|
|
76
100
|
|
|
77
101
|
See `ixfx-vertical-list` README for mode table. Data-grid adds checkbox column in `checked` mode.
|
|
78
102
|
|
|
79
|
-
Programmatic
|
|
103
|
+
### Programmatic selection & cursor
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
grid.selectedKeys; // ReadonlySet<string> of selected row keys
|
|
107
|
+
grid.selectedKeys = ['r3', 'r7']; // replace (clamped to known rows, single-mode keeps the last)
|
|
108
|
+
grid.selectKeys(['r3', 'r7']); // alias of the setter
|
|
109
|
+
|
|
110
|
+
grid.tickleRow('r7'); // move the row cursor + scroll it into view
|
|
111
|
+
grid.tickledKey; // row key under the cursor, or undefined
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The setter fires `datagrid-select` `{ selectedKeys, previous }` only when the
|
|
115
|
+
selection actually changes.
|
|
80
116
|
|
|
81
117
|
---
|
|
82
118
|
|
|
@@ -194,6 +230,10 @@ Demo: `Score` is random float `0–100` with 0–3 decimals, `align:'right'`, `f
|
|
|
194
230
|
|
|
195
231
|
Gear menu (`ixfx-menu-trigger` placement `bottom-end`, `inset-area: block-end span-inline-end`) lists `Columns` (check-items) and `Group by` (radio). Toggle visibility via `col.visible=false` or menu. Event: `datagrid-column-visibility` `{key, visible}`.
|
|
196
232
|
|
|
233
|
+
`column-menu` attribute: `auto` (default) renders the gear menu; `none`
|
|
234
|
+
suppresses it entirely. `col.visible` + `datagrid-column-visibility` still give
|
|
235
|
+
full external control, so `none` lets a host own the column-visibility UI.
|
|
236
|
+
|
|
197
237
|
Other events: `datagrid-column-reorder` `{from,to,columns}`, `datagrid-column-resize` `{key,width}`, `datagrid-cell-click` `{rowKey,colKey,rowIndex,colIndex}`, `datagrid-cell-edit` `{rowKey,colKey,oldValue,newValue}`.
|
|
198
238
|
|
|
199
239
|
---
|
|
@@ -213,11 +253,31 @@ Grid is focusable (`tabindex=0`). When not editing:
|
|
|
213
253
|
|
|
214
254
|
---
|
|
215
255
|
|
|
256
|
+
## Incremental search
|
|
257
|
+
|
|
258
|
+
A built-in type-ahead popover with **navigate** (cursor + scroll to best match),
|
|
259
|
+
**select** (matching rows become the selection), and **filter** (non-matching
|
|
260
|
+
rows dropped from the flat list) modes. No default shortcut:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
grid.registry.invoke('list.search.filter'); // or .navigate / .select
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
A row is matched against `rowSearchText(row)` — by default its visible cells'
|
|
267
|
+
values joined by a space; override with the `rowSearchText` property. `select`
|
|
268
|
+
mode needs `selection-mode="multiple"` to hold more than one row. Character
|
|
269
|
+
highlights are not drawn (a match position spans multiple cells). `filterPredicate`
|
|
270
|
+
(a `(row) => boolean` property) filters rows directly. `search-modes` limits the
|
|
271
|
+
offered modes. Full model: [`docs/infra-incremental.md`](../../docs/infra-incremental.md).
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
216
275
|
## CSS variables & parts
|
|
217
276
|
|
|
218
277
|
| Variable | Default | Description |
|
|
219
278
|
|---|---|---|
|
|
220
279
|
| `--data-grid-row-height` | `28px` | Row height |
|
|
280
|
+
| `--data-grid-row-move-duration` | `200ms` | Insertion / removal animation duration |
|
|
221
281
|
| `--data-grid-header-height` | `32px` | Header height |
|
|
222
282
|
| `--data-grid-bg` | `var(--surface-3)` | Grid background |
|
|
223
283
|
| `--data-grid-header-bg` | `var(--surface-2)` | Header background |
|
|
@@ -239,10 +299,18 @@ No `::part` exports yet (header/row/cell are shadow-internal).
|
|
|
239
299
|
| `startRowEdit` | `(rowKey)` | Open row editors |
|
|
240
300
|
| `stopEdit` | `()` | Cancel editors |
|
|
241
301
|
| `getVisibleRange` | `()=>{startRow,endRow,startCol,endCol}` | Virtual window |
|
|
302
|
+
| `appendRows` | `(rows)` | Add rows without a full re-sort/rebuild — for streaming |
|
|
303
|
+
| `selectKeys` / `set selectedKeys` | `(keys)` | Replace the selection by row key |
|
|
304
|
+
| `tickleRow` | `(key)` | Move the row cursor and scroll it into view |
|
|
305
|
+
|
|
306
|
+
| Getter | Type | |
|
|
307
|
+
|---|---|---|
|
|
308
|
+
| `selectedKeys` | `ReadonlySet<string>` | Selected row keys |
|
|
309
|
+
| `tickledKey` | `string \| undefined` | Row key under the cursor |
|
|
242
310
|
|
|
243
311
|
---
|
|
244
312
|
|
|
245
313
|
## Demo
|
|
246
314
|
|
|
247
|
-
`demo/data-grid.html` + `demo/data-grid.ts`: 200 rows, `Department` random, `Score` float, `Name`/`Department` editable (`user` mode, slow double-click; `Tab`/`Up`/`Down` navigation; `Enter` from tickled row). Controls: Selection/Interaction/Group by/Editability + `Edit first row` (manual).
|
|
315
|
+
`demo/data-grid.html` + `demo/data-grid.ts`: 200 rows, `Department` random, `Score` float, `Name`/`Department` editable (`user` mode, slow double-click; `Tab`/`Up`/`Down` navigation; `Enter` from tickled row). Controls: Selection/Interaction/Group by/Editability/`column-menu` + `Edit first row` (manual), a `Stream +5,000 rows` button (`appendRows`), and `selectKeys` / `tickleRow` buttons.
|
|
248
316
|
|
package/docs-user/detail-list.md
CHANGED
|
@@ -87,8 +87,17 @@ list.addItem('Image 01.png');
|
|
|
87
87
|
const li = document.createElement('li');
|
|
88
88
|
li.textContent = 'Custom item';
|
|
89
89
|
list.addItem(li);
|
|
90
|
+
|
|
91
|
+
// removeItem / removeItems return a Promise that resolves once the row is gone
|
|
92
|
+
list.removeItems(list.selectedItems);
|
|
90
93
|
```
|
|
91
94
|
|
|
95
|
+
Rows added mid-list collapse + fade in; `removeItem` / `removeItems` collapse +
|
|
96
|
+
fade them out before detaching, so the rows around them slide to make or close
|
|
97
|
+
the gap. A bulk populate isn't animated, and it's all skipped under
|
|
98
|
+
`prefers-reduced-motion: reduce` (`--ixfx-list-item-move-duration`, default
|
|
99
|
+
`200ms`).
|
|
100
|
+
|
|
92
101
|
---
|
|
93
102
|
|
|
94
103
|
## Item types
|
|
@@ -191,6 +200,35 @@ list.clearSelection(); // Clear all selections
|
|
|
191
200
|
list.selectAll(); // Select all visible items (if permitted)
|
|
192
201
|
```
|
|
193
202
|
|
|
203
|
+
### Key-based selection
|
|
204
|
+
|
|
205
|
+
`Element` references die when the item set is rebuilt (re-fetch, re-sort,
|
|
206
|
+
filter). Drive selection by a stable **`data-key`** (or `data-value`) instead —
|
|
207
|
+
the Element API is unchanged, the key API is additive. Object items built from
|
|
208
|
+
`items` / a provider get their key stamped automatically from `keyProperty`.
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
list.selectKeys(['row-3', 'row-7']); // replace selection; unknown keys ignored
|
|
212
|
+
list.addSelectedKeys(['row-9']); // multi-select modes only
|
|
213
|
+
list.removeSelectedKeys(['row-3']);
|
|
214
|
+
list.selectedKeys; // ReadonlySet<string>
|
|
215
|
+
|
|
216
|
+
list.focusKey('row-7'); // move cursor to an item + scroll into view
|
|
217
|
+
list.tickledKey; // key under the cursor, or undefined
|
|
218
|
+
|
|
219
|
+
list.addEventListener('list-select', ({ detail }) => {
|
|
220
|
+
console.log([...detail.selectedKeys]); // carried alongside detail.selected
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Restore a selection across a data reload:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const keep = [...list.selectedKeys];
|
|
228
|
+
list.items = await fetchRows(); // Element refs are stale...
|
|
229
|
+
list.selectKeys(keep); // ...keys still resolve
|
|
230
|
+
```
|
|
231
|
+
|
|
194
232
|
---
|
|
195
233
|
|
|
196
234
|
## Interaction modes
|
|
@@ -275,7 +313,7 @@ With wrapping:
|
|
|
275
313
|
|
|
276
314
|
## Incremental search
|
|
277
315
|
|
|
278
|
-
|
|
316
|
+
A built-in type-ahead popover with **navigate** / **select** / **filter** modes — see [`docs/infra-incremental.md`](../../docs/infra-incremental.md). No default shortcut; open it with `list.registry.invoke('list.search.filter')` (or `.navigate` / `.select`). A filter change re-runs the column geometry automatically.
|
|
279
317
|
|
|
280
318
|
Search matches against `data-search-label` (or `textContent` as fallback). Use `data-search-label` to match against a different string than what's displayed:
|
|
281
319
|
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# `ixfx-grid-list`
|
|
2
|
+
|
|
3
|
+
A virtualised grid of items — thumbnails, cards, or arbitrary slotted markup —
|
|
4
|
+
with selection, keyboard navigation, and captions. Windowed rendering keeps the
|
|
5
|
+
DOM small regardless of item count; the same component does a wrapping grid, a
|
|
6
|
+
single vertical column, or a horizontally-scrolling strip.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Contents
|
|
11
|
+
|
|
12
|
+
1. [Quick start](#quick-start)
|
|
13
|
+
2. [Items & keys](#items--keys)
|
|
14
|
+
3. [Sizing & layout](#sizing--layout)
|
|
15
|
+
4. [Captions](#captions)
|
|
16
|
+
5. [Orientation](#orientation)
|
|
17
|
+
6. [Selection](#selection)
|
|
18
|
+
7. [Cursor](#cursor)
|
|
19
|
+
8. [Events](#events)
|
|
20
|
+
9. [Keyboard](#keyboard)
|
|
21
|
+
10. [Virtualisation](#virtualisation)
|
|
22
|
+
11. [CSS parts](#css-parts)
|
|
23
|
+
12. [Choosing a list component](#choosing-a-list-component)
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<ixfx-grid-list id="grid" selection-mode="single" item-size="120" gap="8">
|
|
31
|
+
<div class="tile" data-key="a" data-label="Apple">🍎</div>
|
|
32
|
+
<div class="tile" data-key="b" data-label="Banana">🍌</div>
|
|
33
|
+
<div class="tile" data-key="c" data-label="Cherry">🍒</div>
|
|
34
|
+
</ixfx-grid-list>
|
|
35
|
+
|
|
36
|
+
<script type="module">
|
|
37
|
+
import '@ixfx/components/grid-list';
|
|
38
|
+
|
|
39
|
+
const grid = document.querySelector('#grid');
|
|
40
|
+
grid.addEventListener('list-select', ({ detail }) => {
|
|
41
|
+
console.log([...detail.selectedKeys]);
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Items are **light-DOM children**. Each is projected into its own virtualised
|
|
47
|
+
cell via a named `<slot>`. Add or remove children at any time — a
|
|
48
|
+
`MutationObserver` picks the change up and re-renders.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import type { GridListElement } from '@ixfx/components/grid-list';
|
|
52
|
+
|
|
53
|
+
const grid = document.querySelector<GridListElement>('#grid')!;
|
|
54
|
+
for (const item of data) {
|
|
55
|
+
const el = document.createElement('div');
|
|
56
|
+
el.className = 'tile';
|
|
57
|
+
el.dataset.key = item.id;
|
|
58
|
+
el.dataset.label = item.name;
|
|
59
|
+
el.textContent = item.glyph;
|
|
60
|
+
grid.appendChild(el);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Items & keys
|
|
67
|
+
|
|
68
|
+
| Item attribute | Purpose |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `data-key` (or `data-value`) | Stable identity — for key-based selection, `focusKey`, and `visibleKeys()`. Recommended on every item. |
|
|
71
|
+
| `data-label` | Caption text (see [Captions](#captions)). Alternatively put the text in a `[data-grid-list-caption]` descendant. |
|
|
72
|
+
| `not-checked` | Item can't be tickled / checked (skipped by the cursor). |
|
|
73
|
+
| `hidden` | Item is excluded from layout and navigation. |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Sizing & layout
|
|
78
|
+
|
|
79
|
+
| Property / attribute | Default | Description |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `itemSize` / `item-size` | `160` | Cell width in px. Also the square's height for `separate` / `under` / `overlaid` / `hidden`. |
|
|
82
|
+
| `gap` | `8` | Gap between cells, px. |
|
|
83
|
+
| `captionHeight` / `caption-height` | `24` | Height reserved for the caption band in `separate` / `under`. |
|
|
84
|
+
|
|
85
|
+
Values are clamped and rounded. Changing `item-size` / `gap` re-anchors the
|
|
86
|
+
scroll on the item nearest the viewport centre (zoom stays put rather than
|
|
87
|
+
jumping to the top-left corner).
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Captions
|
|
92
|
+
|
|
93
|
+
`caption-style` — how the caption relates to the content:
|
|
94
|
+
|
|
95
|
+
| value | layout |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `hidden` | No caption. Cell height = `item-size`. |
|
|
98
|
+
| `separate` | Content in a square; caption a **detached** label below it. Square and caption highlight independently (macOS Finder icon view). |
|
|
99
|
+
| `under` (default) | One box: content on top, caption strip **inside** it below. One selection outline. |
|
|
100
|
+
| `overlaid` | Caption floats over the content. |
|
|
101
|
+
|
|
102
|
+
`caption-align` — `left` \| `middle` (default) \| `right`. Text alignment; also
|
|
103
|
+
positions the pill in `separate`.
|
|
104
|
+
|
|
105
|
+
`overlaid` only:
|
|
106
|
+
|
|
107
|
+
- `caption-position` — `top` \| `middle` \| `bottom` (default).
|
|
108
|
+
- `caption-backdrop` — `scrim` (default, flat translucent panel) \| `gradient`
|
|
109
|
+
(fades away from the caption edge) \| `blur` (frosted) \| `none` (text +
|
|
110
|
+
shadow, no panel).
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
<ixfx-grid-list caption-style="separate" caption-align="left"></ixfx-grid-list>
|
|
114
|
+
<ixfx-grid-list caption-style="overlaid" caption-position="top" caption-backdrop="gradient"></ixfx-grid-list>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Orientation
|
|
120
|
+
|
|
121
|
+
`orientation`:
|
|
122
|
+
|
|
123
|
+
| value | layout | scrolls |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `grid` (default) | wraps across as many columns as fit | vertically |
|
|
126
|
+
| `row` | a single row of items | **horizontally** |
|
|
127
|
+
| `column` | a single column of items | vertically |
|
|
128
|
+
|
|
129
|
+
`row` is the virtualised horizontal strip; `column` is the recommended
|
|
130
|
+
large-list replacement for `ixfx-vertical-list`.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Selection
|
|
135
|
+
|
|
136
|
+
`selection-mode` (`none` \| `single` \| `multiple`) and `interaction-mode`
|
|
137
|
+
(`standard` \| `implicit` \| `manual` \| `checked` \| `sticky` \| `vscode`) match
|
|
138
|
+
the other list components — see the `ixfx-vertical-list` README for the mode
|
|
139
|
+
table.
|
|
140
|
+
|
|
141
|
+
### Element API
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
grid.select(el); // replace with one item
|
|
145
|
+
grid.selectMany([a, b]); // selection-mode="multiple" only
|
|
146
|
+
grid.deselect(el);
|
|
147
|
+
grid.clearSelection();
|
|
148
|
+
grid.selectAll();
|
|
149
|
+
grid.selectedItems; // ReadonlySet<Element>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Key-based selection
|
|
153
|
+
|
|
154
|
+
`Element` references die when the item set is rebuilt. With a `data-key` on each
|
|
155
|
+
item, drive selection by key instead — additive, the Element API is unchanged.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
grid.selectKeys(['a', 'c']); // replace; unknown keys ignored
|
|
159
|
+
grid.addSelectedKeys(['b']); // multi-select modes only
|
|
160
|
+
grid.removeSelectedKeys(['a']);
|
|
161
|
+
grid.selectedKeys; // ReadonlySet<string>
|
|
162
|
+
|
|
163
|
+
grid.addEventListener('list-select', ({ detail }) => {
|
|
164
|
+
console.log([...detail.selectedKeys]); // alongside detail.selected
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Restore across a reload:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const keep = [...grid.selectedKeys];
|
|
172
|
+
grid.replaceChildren(...(await fetchTiles()));
|
|
173
|
+
grid.selectKeys(keep);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Cursor
|
|
179
|
+
|
|
180
|
+
The "tickled" cursor follows hover (mouse) or arrow keys (keyboard).
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
grid.focusKey('b'); // move the cursor to an item and scroll it into view
|
|
184
|
+
grid.tickledKey; // key under the cursor, or undefined
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Events
|
|
190
|
+
|
|
191
|
+
All bubble and are `composed`.
|
|
192
|
+
|
|
193
|
+
| Event | Detail | When |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| `list-select` | `{ selected, previous, selectedKeys }` | Selection changes by any means |
|
|
196
|
+
| `list-activate` | `{ item }` | Double-click or `Enter` on an item |
|
|
197
|
+
| `list-item-click` | `{ item }` | Single click / `Enter` |
|
|
198
|
+
| `list-tickle` | `{ item }` | Cursor moves onto an item |
|
|
199
|
+
| `grid-list-viewport-change` | `{ visibleKeys }` | Scroll, resize, or content change — the rendered window moved |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Keyboard
|
|
204
|
+
|
|
205
|
+
| Key | `grid` | `row` / `column` |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `ArrowLeft` / `ArrowRight` | ∓1 item | ∓1 item |
|
|
208
|
+
| `ArrowUp` / `ArrowDown` | ∓/± one row | ∓1 item |
|
|
209
|
+
| `Home` / `End` | first / last | first / last |
|
|
210
|
+
| `PageUp` / `PageDown` | ± one screen of rows | ± one screen of items |
|
|
211
|
+
| `Enter` | activate | activate |
|
|
212
|
+
| `Space` | toggle selection | toggle selection |
|
|
213
|
+
| `Escape` | clear selection | clear selection |
|
|
214
|
+
| `Ctrl` / `Cmd` + `A` | select all (multi modes) | select all (multi modes) |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Incremental search
|
|
219
|
+
|
|
220
|
+
A built-in type-ahead popover with **navigate** / **select** / **filter** modes.
|
|
221
|
+
No default shortcut — open it via a command on `grid.registry`:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
grid.registry.invoke('list.search.filter'); // or .navigate / .select
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Search matches `data-label` (or `[data-grid-list-caption]` text, then
|
|
228
|
+
`data-search-label`, then `textContent`). Filter mode genuinely removes items
|
|
229
|
+
from the virtualised layout. Add a page-level highlight rule to see matched
|
|
230
|
+
characters:
|
|
231
|
+
|
|
232
|
+
```css
|
|
233
|
+
::highlight(grid-list-search) { background: var(--accent); color: var(--accent-text); }
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`filterPredicate` (an `(el: Element) => boolean` property) filters items directly,
|
|
237
|
+
independent of search. Limit modes with `search-modes="navigate filter"`. Full
|
|
238
|
+
model: [`docs/infra-incremental.md`](../../docs/infra-incremental.md).
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Virtualisation
|
|
243
|
+
|
|
244
|
+
Only the cells in (or near) the viewport are in the DOM.
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
grid.count; // total items
|
|
248
|
+
grid.renderedCount; // cells currently in the shadow DOM
|
|
249
|
+
grid.visibleKeys(); // data-key of items in the current window
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`grid-list` handles tens of thousands of children in every orientation.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Scroll fade & insertion animation
|
|
257
|
+
|
|
258
|
+
The scrollable edge is fade-masked whenever there's more content that way — a
|
|
259
|
+
zero-JS `scroll-timeline` mask (`scroll-fade-y` for `grid` / `column`,
|
|
260
|
+
`scroll-fade-x` for `row`). See `docs/infra-theming.md` → *Scroll Fade*; tune the
|
|
261
|
+
reach with `--scroll-fade-width` (default `30px`).
|
|
262
|
+
|
|
263
|
+
When the child list changes **mid-list** (not a first populate or a wholesale
|
|
264
|
+
`replaceChildren`), the cells slide to their new position rather than snapping —
|
|
265
|
+
so an inserted item's neighbours make room and a removed item's gap closes — and
|
|
266
|
+
a freshly inserted cell also fades in. The transition is confined to a short
|
|
267
|
+
window after the mutation, so it never fires during scroll virtualisation, and
|
|
268
|
+
it's suppressed under `prefers-reduced-motion: reduce`. Duration:
|
|
269
|
+
`--grid-list-item-move-duration` (default `200ms`).
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## CSS parts
|
|
274
|
+
|
|
275
|
+
| Part | Element |
|
|
276
|
+
|---|---|
|
|
277
|
+
| `viewport` | The scroll container |
|
|
278
|
+
| `item` | A cell |
|
|
279
|
+
| `thumb` | The square holding the slotted content |
|
|
280
|
+
| `caption` | The caption element (absent for `caption-style="hidden"`) |
|
|
281
|
+
|
|
282
|
+
Host CSS custom properties: `--grid-list-item-bg`, `--grid-list-radius`,
|
|
283
|
+
`--grid-list-gap`, `--grid-list-item-move-duration` (insertion animation,
|
|
284
|
+
default `200ms`), `--scroll-fade-width` (edge fade reach, default `30px`), plus
|
|
285
|
+
the shared `--item-bg-*` / `--accent` theme tokens.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Choosing a list component
|
|
290
|
+
|
|
291
|
+
- **Large lists** — prefer `ixfx-grid-list` with `orientation="column"` over
|
|
292
|
+
`ixfx-vertical-list`. `vertical-list` renders every child; `grid-list` is
|
|
293
|
+
windowed.
|
|
294
|
+
- **Small, declarative, richly-slotted lists** — `ixfx-vertical-list` stays the
|
|
295
|
+
simpler choice.
|
|
296
|
+
- **Horizontal virtualised strip** — `ixfx-grid-list` with `orientation="row"`.
|
|
297
|
+
- **Tabular data with columns / sort / grouping / inline edit** —
|
|
298
|
+
`ixfx-data-grid`.
|
package/docs-user/incr-search.md
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
# Incremental Search
|
|
2
2
|
|
|
3
3
|
Utilities for incremental (type-ahead) search over data collections or DOM-backed lists.
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
- **`ListSearchController`** — the shared brain behind the built-in search
|
|
6
|
+
popover in `ixfx-grid-list` / `ixfx-vertical-list` / `ixfx-detail-list` /
|
|
7
|
+
`ixfx-data-grid` / `ixfx-tree-list` / `ixfx-miller-list`. Three modes
|
|
8
|
+
(navigate / select / filter), driven by `list.search.*` commands. See
|
|
9
|
+
[`docs/infra-incremental.md`](../../docs/infra-incremental.md) — start there
|
|
10
|
+
for anything component-facing.
|
|
11
|
+
- **`createIncrSearch`** — the low-level fuzzy engine (fzf) both the controller
|
|
12
|
+
and the helpers below are built on.
|
|
13
|
+
- **`createElementIncrSearch`** / **`IncrSearchTreeController`** — *deprecated*
|
|
14
|
+
filter-only controllers driven by an external `<input>`. Kept for standalone
|
|
15
|
+
use; components now use `ListSearchController`.
|
|
6
16
|
|
|
7
17
|
## Plain UL list
|
|
8
18
|
|
package/docs-user/index.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixfx/components",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"generated": "2026-09-
|
|
3
|
+
"version": "0.7.5",
|
|
4
|
+
"generated": "2026-09-08T18:17:07.322Z",
|
|
5
5
|
"components": [
|
|
6
6
|
{
|
|
7
7
|
"name": "ac-text",
|
|
@@ -63,6 +63,11 @@
|
|
|
63
63
|
"summary": "Primitives for typical form layout with responsive label positioning and data binding.",
|
|
64
64
|
"path": "docs-user/form.md"
|
|
65
65
|
},
|
|
66
|
+
{
|
|
67
|
+
"name": "grid-list",
|
|
68
|
+
"summary": "A virtualised grid of items — thumbnails, cards, or arbitrary slotted markup —",
|
|
69
|
+
"path": "docs-user/grid-list.md"
|
|
70
|
+
},
|
|
66
71
|
{
|
|
67
72
|
"name": "grouped-item-lister",
|
|
68
73
|
"summary": "A meta-component that renders a typed item list using any sub-component you supply. Items can be displayed in a single sub-component (_ungrouped_ mode) or split into labelled groups, each with its own",
|
package/docs-user/llms.txt
CHANGED
|
@@ -23,6 +23,7 @@ import '@ixfx/components/data-grid';
|
|
|
23
23
|
- [dock](docs-user/dock.md): Dockable, movable panels like VS Code / Photoshop. Drag a panel by its
|
|
24
24
|
- [editable-label](docs-user/editable-label.md): Inline editable text components. `ixfx-editable-number` extends `ixfx-editable-label` with drag-to-adjust and fill-bar visualization.
|
|
25
25
|
- [form](docs-user/form.md): Primitives for typical form layout with responsive label positioning and data binding.
|
|
26
|
+
- [grid-list](docs-user/grid-list.md): A virtualised grid of items — thumbnails, cards, or arbitrary slotted markup —
|
|
26
27
|
- [grouped-item-lister](docs-user/grouped-item-lister.md): A meta-component that renders a typed item list using any sub-component you supply. Items can be displayed in a single sub-component (_ungrouped_ mode) or split into labelled groups, each with its own
|
|
27
28
|
- [icons](docs-user/icons.md): A centralized SVG icon system for `@ixfx/components`. Icons are stored by name, can be overridden globally, and all components that use a given icon re-render automatically when it changes.
|
|
28
29
|
- [incr-search](docs-user/incr-search.md): Utilities for incremental (type-ahead) search over data collections or DOM-backed lists.
|
package/docs-user/tree.md
CHANGED
|
@@ -367,7 +367,28 @@ Keyboard navigation follows the crumb path. Arrow keys move between breadcrumb s
|
|
|
367
367
|
|
|
368
368
|
## Incremental search
|
|
369
369
|
|
|
370
|
-
|
|
370
|
+
`ixfx-tree-list` and `ixfx-miller-list` have a **built-in type-ahead popover**
|
|
371
|
+
with three modes:
|
|
372
|
+
|
|
373
|
+
- **navigate** — expands the match's ancestors and moves the cursor to it; ↑/↓
|
|
374
|
+
cycle between matches; Enter activates and closes.
|
|
375
|
+
- **select** — the selection becomes the set of matching nodes.
|
|
376
|
+
- **filter** — non-matching nodes (and branches with no matching descendant) are
|
|
377
|
+
hidden; branches with a match auto-expand so the match is visible.
|
|
378
|
+
|
|
379
|
+
No default shortcut — open it via a command on `el.registry`:
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
el.registry.invoke('list.search.navigate'); // or .select / .filter
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Limit the offered modes with the `search-modes` attribute
|
|
386
|
+
(`search-modes="navigate filter"`). Full model: [`docs/infra-incremental.md`](../../docs/infra-incremental.md).
|
|
387
|
+
|
|
388
|
+
### Deprecated: `IncrSearchTreeController`
|
|
389
|
+
|
|
390
|
+
The external-`<input>` filter-only controller still works but is superseded by
|
|
391
|
+
the built-in popover.
|
|
371
392
|
|
|
372
393
|
```typescript
|
|
373
394
|
import { IncrSearchTreeController } from '@ixfx/components';
|
|
@@ -463,6 +484,18 @@ Each column is a separate `role="listbox"` with `aria-label` showing the parent
|
|
|
463
484
|
|
|
464
485
|
---
|
|
465
486
|
|
|
487
|
+
## Row animation
|
|
488
|
+
|
|
489
|
+
Rows that appear — a branch expanded, a node added to `root` / the model —
|
|
490
|
+
collapse + fade in, and the rows below slide down to make room. Rows that
|
|
491
|
+
disappear — a branch collapsed, a node removed — are kept as fading "ghost" rows
|
|
492
|
+
until they've collapsed out, so the gap closes smoothly. Above ~50 rows changing
|
|
493
|
+
at once the animation is skipped, as it is entirely under
|
|
494
|
+
`prefers-reduced-motion: reduce`. Duration: `--ixfx-list-item-move-duration`
|
|
495
|
+
(default `200ms`).
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
466
499
|
## CSS variables
|
|
467
500
|
|
|
468
501
|
### Shared / themed
|
|
@@ -493,6 +526,7 @@ These are set by the global theme and inherited by all tree components.
|
|
|
493
526
|
| `--tree-indent` | `20px` | Indentation per depth level |
|
|
494
527
|
| `--tree-item-height` | `28px` | Height of each row |
|
|
495
528
|
| `--tree-caret-size` | `10px` | Expand/collapse caret size |
|
|
529
|
+
| `--ixfx-list-item-move-duration` | `200ms` | Row enter / leave animation duration |
|
|
496
530
|
|
|
497
531
|
### `ixfx-miller-list` specific
|
|
498
532
|
|
|
@@ -313,13 +313,21 @@ list.addItem(myElement);
|
|
|
313
313
|
// In checked mode, add a row that shows no checkbox and can't be checked
|
|
314
314
|
list.addItem('Header', { notChecked: true });
|
|
315
315
|
|
|
316
|
-
// Remove a specific element
|
|
316
|
+
// Remove a specific element (returns a Promise that resolves once it's gone)
|
|
317
317
|
list.removeItem(element);
|
|
318
|
+
list.removeItems(list.selectedItems);
|
|
318
319
|
|
|
319
320
|
// Remove all items and clear selection
|
|
320
321
|
list.clearItems();
|
|
321
322
|
```
|
|
322
323
|
|
|
324
|
+
Items added mid-list — via `addItem`, a direct `appendChild`, or a framework
|
|
325
|
+
binding — collapse + fade in, and the rows below slide down to make room.
|
|
326
|
+
`removeItem` / `removeItems` play the reverse (collapse + fade out) and then
|
|
327
|
+
detach, so the gap closes smoothly. A bulk populate isn't animated, and
|
|
328
|
+
everything is skipped under `prefers-reduced-motion: reduce`. Tune the timing
|
|
329
|
+
with the `--ixfx-list-item-move-duration` custom property (default `200ms`).
|
|
330
|
+
|
|
323
331
|
### Reading the selection
|
|
324
332
|
|
|
325
333
|
```typescript
|
|
@@ -341,6 +349,48 @@ list.addEventListener('list-select', ({ detail }) => {
|
|
|
341
349
|
});
|
|
342
350
|
```
|
|
343
351
|
|
|
352
|
+
### Key-based selection
|
|
353
|
+
|
|
354
|
+
`Element` references die the moment you rebuild the item set (re-fetch, external
|
|
355
|
+
re-sort, filter). Give each item a **`data-key`** (or `data-value`) and drive
|
|
356
|
+
selection by that stable string instead. The Element API keeps working
|
|
357
|
+
unchanged — the key API is additive.
|
|
358
|
+
|
|
359
|
+
```html
|
|
360
|
+
<ixfx-vertical-list selection-mode="multiple">
|
|
361
|
+
<li data-key="a">Apple</li>
|
|
362
|
+
<li data-key="b">Banana</li>
|
|
363
|
+
<li data-key="c">Cherry</li>
|
|
364
|
+
</ixfx-vertical-list>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
list.selectKeys(['a', 'c']); // replace selection; unknown keys ignored
|
|
369
|
+
list.addSelectedKeys(['b']); // multi-select modes only
|
|
370
|
+
list.removeSelectedKeys(['a']);
|
|
371
|
+
list.selectedKeys; // ReadonlySet<string>, e.g. Set { 'b', 'c' }
|
|
372
|
+
|
|
373
|
+
list.focusKey('b'); // move the cursor to an item + scroll it into view
|
|
374
|
+
list.tickledKey; // key under the cursor, or undefined
|
|
375
|
+
|
|
376
|
+
// list-select carries keys too
|
|
377
|
+
list.addEventListener('list-select', ({ detail }) => {
|
|
378
|
+
console.log([...detail.selectedKeys]);
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Restore a selection across a data reload:
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
const keep = [...list.selectedKeys];
|
|
386
|
+
list.setItems(await fetchRows()); // Element refs are now stale
|
|
387
|
+
list.selectKeys(keep); // ...but the keys still resolve
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
The `data-key` requirement is documented, not enforced: items without a key
|
|
391
|
+
simply never appear in `selectedKeys` and can't be targeted by `selectKeys` /
|
|
392
|
+
`focusKey`.
|
|
393
|
+
|
|
344
394
|
### Filtering by state
|
|
345
395
|
|
|
346
396
|
Use `selectedFilter()` to iterate over items based on their selection or checked state. Pass `'selected'`, `'checked'`, or `'either'` to filter accordingly:
|
|
@@ -454,7 +504,13 @@ The element must be focused (click it or tab to it) before keyboard navigation w
|
|
|
454
504
|
|
|
455
505
|
## Incremental search
|
|
456
506
|
|
|
457
|
-
|
|
507
|
+
A built-in type-ahead popover with three modes — **navigate** (cursor jumps to the best match, ↑/↓ cycle), **select** (matches become the selection), **filter** (non-matches hidden). See [`docs/infra-incremental.md`](../../docs/infra-incremental.md) for the full model, conversions between modes, and the `search-modes` attribute.
|
|
508
|
+
|
|
509
|
+
There is **no default shortcut**. Open it by invoking one of the commands on `list.registry`:
|
|
510
|
+
|
|
511
|
+
```typescript
|
|
512
|
+
list.registry.invoke('list.search.filter'); // or .navigate / .select
|
|
513
|
+
```
|
|
458
514
|
|
|
459
515
|
### Adding the page-level highlight rule
|
|
460
516
|
|
package/llms.txt
CHANGED
|
@@ -23,6 +23,7 @@ import '@ixfx/components/data-grid';
|
|
|
23
23
|
- [dock](docs-user/dock.md): Dockable, movable panels like VS Code / Photoshop. Drag a panel by its
|
|
24
24
|
- [editable-label](docs-user/editable-label.md): Inline editable text components. `ixfx-editable-number` extends `ixfx-editable-label` with drag-to-adjust and fill-bar visualization.
|
|
25
25
|
- [form](docs-user/form.md): Primitives for typical form layout with responsive label positioning and data binding.
|
|
26
|
+
- [grid-list](docs-user/grid-list.md): A virtualised grid of items — thumbnails, cards, or arbitrary slotted markup —
|
|
26
27
|
- [grouped-item-lister](docs-user/grouped-item-lister.md): A meta-component that renders a typed item list using any sub-component you supply. Items can be displayed in a single sub-component (_ungrouped_ mode) or split into labelled groups, each with its own
|
|
27
28
|
- [icons](docs-user/icons.md): A centralized SVG icon system for `@ixfx/components`. Icons are stored by name, can be overridden globally, and all components that use a given icon re-render automatically when it changes.
|
|
28
29
|
- [incr-search](docs-user/incr-search.md): Utilities for incremental (type-ahead) search over data collections or DOM-backed lists.
|