@ixfx/components 0.6.2 → 0.7.1
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 +1918 -835
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +22137 -16840
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/ac-text.js +3 -2
- package/dist/ac-text.js.map +1 -1
- package/dist/{ac-token-BAa6ke09.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
- package/dist/{ac-token-BAa6ke09.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/ac-token.js +3 -2
- package/dist/ac-token.js.map +1 -1
- package/dist/{button-Bn0BuLpO.js → button-DsFbV4XD.js} +5 -4
- package/dist/button-DsFbV4XD.js.map +1 -0
- package/dist/button.d.ts.map +1 -1
- package/dist/button.js +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/{colour-picker-0stHB90J.js → colour-picker-Ddsk-7E_.js} +4 -3
- package/dist/{colour-picker-0stHB90J.js.map → colour-picker-Ddsk-7E_.js.map} +1 -1
- package/dist/colour-picker.js +1 -1
- package/dist/crumbs.d.ts +1 -1
- package/dist/crumbs.js +4 -2
- package/dist/crumbs.js.map +1 -1
- package/dist/data-display.js +1 -1
- package/dist/{data-grid-C8qIo1-u.d.ts → data-grid-Bh4YrQGK.d.ts} +2 -2
- package/dist/{data-grid-C8qIo1-u.d.ts.map → data-grid-Bh4YrQGK.d.ts.map} +1 -1
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +4 -2
- package/dist/data-grid.js.map +1 -1
- package/dist/{defaults-BCiDhZbF.js → defaults-BJwDsMH4.js} +27 -20
- package/dist/defaults-BJwDsMH4.js.map +1 -0
- package/dist/editable-label-rzXkjf1H.d.ts +75 -0
- package/dist/editable-label-rzXkjf1H.d.ts.map +1 -0
- package/dist/editable-label.d.ts +2 -75
- package/dist/editable-label.js +2 -1
- package/dist/editable-label.js.map +1 -1
- package/dist/{fallbacks-DEE1nCTt.js → fallbacks-DNI9xt0F.js} +2 -2
- package/dist/{fallbacks-DEE1nCTt.js.map → fallbacks-DNI9xt0F.js.map} +1 -1
- package/dist/{grouped-item-lister-_pMDwIo1.d.ts → grouped-item-lister-DnWB-eFT.d.ts} +2 -2
- package/dist/{grouped-item-lister-_pMDwIo1.d.ts.map → grouped-item-lister-DnWB-eFT.d.ts.map} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{hex-editor-Bk6rxhfg.js → hex-editor-BiRfwTz1.js} +2 -2
- package/dist/{hex-editor-Bk6rxhfg.js.map → hex-editor-BiRfwTz1.js.map} +1 -1
- package/dist/hex.js +1 -1
- package/dist/{icon-DpA9x2Ve.d.ts → icon-CDGprSdE.d.ts} +1 -12
- package/dist/icon-CDGprSdE.d.ts.map +1 -0
- package/dist/{icons-Bm2ByQ3s.js → icon-DcEEGQa_.js} +38 -12
- package/dist/icon-DcEEGQa_.js.map +1 -0
- package/dist/icons.d.ts +3 -3
- package/dist/icons.js +9 -3
- package/dist/icons.js.map +1 -0
- package/dist/{index-CKtLhgYj.d.ts → index-9AhaHIT2.d.ts} +3 -3
- package/dist/{index-CKtLhgYj.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
- package/dist/index-CG2vIgPv.d.ts +101 -0
- package/dist/index-CG2vIgPv.d.ts.map +1 -0
- package/dist/{index-BtGFYfaK.d.ts → index-CS9yM8L-.d.ts} +14 -4
- package/dist/index-CS9yM8L-.d.ts.map +1 -0
- package/dist/index.d.ts +861 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4257 -931
- package/dist/index.js.map +1 -1
- package/dist/interaction-D5XdKzbR.js +2 -0
- package/dist/labelled-radial-input.js +2 -1
- package/dist/labelled-radial-input.js.map +1 -1
- package/dist/labelled-slider-input-DzigjMwP.js +808 -0
- package/dist/labelled-slider-input-DzigjMwP.js.map +1 -0
- package/dist/labelled-slider-input.d.ts +2 -0
- package/dist/labelled-slider-input.js +2 -0
- package/dist/{types-DlVNJez_.d.ts → list-selection-types-DSuRNWpx.d.ts} +10 -2
- package/dist/list-selection-types-DSuRNWpx.d.ts.map +1 -0
- package/dist/menu-CXDFJxNm.js +825 -0
- package/dist/menu-CXDFJxNm.js.map +1 -0
- package/dist/{menu-item-Bs2MYyHq.d.ts → menu-item-CZi9vy5O.d.ts} +4 -2
- package/dist/menu-item-CZi9vy5O.d.ts.map +1 -0
- package/dist/menu-item-D2S4i8u1.js +809 -0
- package/dist/menu-item-D2S4i8u1.js.map +1 -0
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -1
- package/dist/miller.d.ts +1 -1
- package/dist/miller.js +3 -2
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.js +4 -2
- package/dist/narrowed-text.js.map +1 -1
- package/dist/notification-pill-DyZydXoZ.d.ts.map +1 -1
- package/dist/notifier.js +4 -3
- package/dist/notifier.js.map +1 -1
- package/dist/panel.d.ts +13 -13
- package/dist/panel.d.ts.map +1 -1
- package/dist/panel.js +37 -253
- package/dist/panel.js.map +1 -1
- package/dist/plots.js +1 -1
- package/dist/polar-pad.js +1 -1
- package/dist/{radial-input-Dk8Wydp5.js → radial-input-Dp5qz0ly.js} +2 -2
- package/dist/{radial-input-Dk8Wydp5.js.map → radial-input-Dp5qz0ly.js.map} +1 -1
- package/dist/radial-input.js +1 -1
- package/dist/range-input.js +1 -1
- package/dist/range.js +1 -1
- package/dist/registry-BEtb8_wB.js +46 -0
- package/dist/registry-BEtb8_wB.js.map +1 -0
- package/dist/select-horiz.js +3 -2
- package/dist/select-horiz.js.map +1 -1
- package/dist/{slider-input-XppH3vcy.d.ts → slider-input-BfRUW2ZB.d.ts} +16 -3
- package/dist/slider-input-BfRUW2ZB.d.ts.map +1 -0
- package/dist/{slider-input-CT4gcF-o.js → slider-input-De4eoT11.js} +382 -67
- package/dist/slider-input-De4eoT11.js.map +1 -0
- package/dist/slider-input.d.ts +1 -1
- package/dist/slider-input.js +1 -1
- package/dist/snackbar.js +1 -1
- package/dist/split-layout-BFSbUZQv.js +969 -0
- package/dist/split-layout-BFSbUZQv.js.map +1 -0
- package/dist/split-layout-JK3xWVX2.d.ts +179 -0
- package/dist/split-layout-JK3xWVX2.d.ts.map +1 -0
- package/dist/split-layout.d.ts +2 -60
- package/dist/split-layout.js +1 -617
- package/dist/style.css +1 -1
- package/dist/swipe.js +1 -1
- package/dist/{tab-list-D_1cYhB_.d.ts → tab-list-CGyPt07Z.d.ts} +10 -2
- package/dist/tab-list-CGyPt07Z.d.ts.map +1 -0
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +128 -27
- package/dist/tabs.js.map +1 -1
- package/dist/{tickled-controller-BtevrRLV.d.ts → tickled-controller-CRzdIEjJ.d.ts} +7 -1
- package/dist/tickled-controller-CRzdIEjJ.d.ts.map +1 -0
- package/dist/{tickled-controller-DkAU-0qL.js → tickled-controller-h9GmJ_bU.js} +8 -2
- package/dist/tickled-controller-h9GmJ_bU.js.map +1 -0
- package/dist/titlebar-Bj5pfdw_.d.ts +50 -0
- package/dist/titlebar-Bj5pfdw_.d.ts.map +1 -0
- package/dist/titlebar.d.ts +2 -0
- package/dist/titlebar.js +324 -0
- package/dist/titlebar.js.map +1 -0
- package/dist/tooltip-BlvBUQxx.d.ts.map +1 -1
- package/dist/{tree-BO6BXI2b.js → tree-Ch4W8qXQ.js} +4 -3
- package/dist/{tree-BO6BXI2b.js.map → tree-Ch4W8qXQ.js.map} +1 -1
- package/dist/tree.d.ts +1 -1
- package/dist/tree.js +1 -1
- package/dist/vertical-list-ClnqTkF3.js +814 -0
- package/dist/vertical-list-ClnqTkF3.js.map +1 -0
- package/dist/vertical-list.d.ts +8 -9
- package/dist/vertical-list.d.ts.map +1 -1
- package/dist/vertical-list.js +1 -736
- package/dist/{xy-axis-B6yMjckW.js → xy-axis-DWizs0bt.js} +109 -3
- package/dist/xy-axis-DWizs0bt.js.map +1 -0
- package/dist/xy-pad.js +1 -1
- package/docs-user/README.md +5 -0
- package/docs-user/detail-list.md +398 -0
- package/docs-user/dock.md +461 -0
- package/docs-user/icons.md +4 -0
- package/docs-user/index.json +28 -3
- package/docs-user/labelled-slider-input.md +198 -0
- package/docs-user/llms.txt +6 -1
- package/docs-user/panel.md +20 -1
- package/docs-user/slider-input.md +55 -15
- package/docs-user/split-layout.md +136 -170
- package/docs-user/tabs.md +54 -0
- package/docs-user/titlebar.md +102 -0
- package/docs-user/toolbar.md +95 -22
- package/docs-user/twosplit-layout.md +254 -0
- package/docs-user/user-catalog.md +8 -1
- package/docs-user/user-theming.md +109 -0
- package/llms.txt +6 -1
- package/package.json +1 -2
- package/dist/button-Bn0BuLpO.js.map +0 -1
- package/dist/defaults-BCiDhZbF.js.map +0 -1
- package/dist/editable-label.d.ts.map +0 -1
- package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
- package/dist/icons-Bm2ByQ3s.js.map +0 -1
- package/dist/index-BtGFYfaK.d.ts.map +0 -1
- package/dist/menu-DIfU70AA.js +0 -1609
- package/dist/menu-DIfU70AA.js.map +0 -1
- package/dist/menu-item-Bs2MYyHq.d.ts.map +0 -1
- package/dist/slider-input-CT4gcF-o.js.map +0 -1
- package/dist/slider-input-XppH3vcy.d.ts.map +0 -1
- package/dist/split-layout.d.ts.map +0 -1
- package/dist/split-layout.js.map +0 -1
- package/dist/tab-list-D_1cYhB_.d.ts.map +0 -1
- package/dist/tickled-controller-BtevrRLV.d.ts.map +0 -1
- package/dist/tickled-controller-DkAU-0qL.js.map +0 -1
- package/dist/types-DlVNJez_.d.ts.map +0 -1
- package/dist/vertical-list.js.map +0 -1
- package/dist/xy-axis-B6yMjckW.js.map +0 -1
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
# `ixfx-detail-list`
|
|
2
|
+
|
|
3
|
+
A list that scales horizontally, not vertically. Items are laid out in equal-width columns; they flow top→bottom down a column, then wrap to the top of the next column to the right. The component has a fixed vertical extent and scrolls horizontally.
|
|
4
|
+
|
|
5
|
+
Selection semantics match `ixfx-vertical-list` — same modes, same `list-*` events, same keyboard gestures — but navigation is a 2-D grid (Up/Down move within a column, Left/Right jump columns).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
1. [Quick start](#quick-start)
|
|
12
|
+
2. [Item types](#item-types)
|
|
13
|
+
3. [Properties](#properties)
|
|
14
|
+
4. [Selection](#selection)
|
|
15
|
+
5. [Interaction modes](#interaction-modes)
|
|
16
|
+
6. [Custom checkbox](#custom-checkbox)
|
|
17
|
+
7. [Events](#events)
|
|
18
|
+
8. [Keyboard navigation](#keyboard-navigation)
|
|
19
|
+
9. [Incremental search](#incremental-search)
|
|
20
|
+
10. [Filter predicate](#filter-predicate)
|
|
21
|
+
11. [Sorting](#sorting)
|
|
22
|
+
12. [Asynchronous data](#asynchronous-data)
|
|
23
|
+
13. [CSS variables](#css-variables)
|
|
24
|
+
14. [CSS parts](#css-parts)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
### Declarative HTML items
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<ixfx-detail-list id="my-list" selection-mode="single">
|
|
34
|
+
<li>Alpha</li>
|
|
35
|
+
<li>Bravo</li>
|
|
36
|
+
<li>Charlie</li>
|
|
37
|
+
</ixfx-detail-list>
|
|
38
|
+
|
|
39
|
+
<script type="module">
|
|
40
|
+
import '@ixfx/components';
|
|
41
|
+
|
|
42
|
+
const list = document.querySelector('#my-list');
|
|
43
|
+
list.addEventListener('list-select', ({ detail }) => {
|
|
44
|
+
const [item] = detail.selected;
|
|
45
|
+
console.log('selected:', item?.textContent);
|
|
46
|
+
});
|
|
47
|
+
</script>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Items flow down columns (vertically) then wrap to the next column:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Alpha Golf November Uniform
|
|
54
|
+
Bravo Hotel Oscar Victor
|
|
55
|
+
Charlie India Papa Whiskey
|
|
56
|
+
Delta Juliett Quebec X-ray
|
|
57
|
+
Echo Kilo Romeo Yankee
|
|
58
|
+
Foxtrot Lima Sierra Zulu
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Programmatic items
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import type { DetailListElement } from '@ixfx/components';
|
|
65
|
+
|
|
66
|
+
const list = document.querySelector<DetailListElement>('ixfx-detail-list')!;
|
|
67
|
+
|
|
68
|
+
list.addItem('Document A');
|
|
69
|
+
list.addItem('Image 01.png');
|
|
70
|
+
|
|
71
|
+
// Or pass an element directly
|
|
72
|
+
const li = document.createElement('li');
|
|
73
|
+
li.textContent = 'Custom item';
|
|
74
|
+
list.addItem(li);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Item types
|
|
80
|
+
|
|
81
|
+
### Plain `<li>` elements
|
|
82
|
+
|
|
83
|
+
The simplest item type. Items are positioned by CSS flexbox into columns.
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<ixfx-detail-list>
|
|
87
|
+
<li>Item one</li>
|
|
88
|
+
<li>Item two</li>
|
|
89
|
+
</ixfx-detail-list>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Attributes supported on `<li>`:**
|
|
93
|
+
|
|
94
|
+
| Attribute | Description |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `data-search-label` | Override searchable text (defaults to `textContent`) |
|
|
97
|
+
| `data-key` | Stable identity for selection persistence across sort/rebuild |
|
|
98
|
+
| `data-value` | Alternative to `data-key` |
|
|
99
|
+
| `data-icon` | Icon name to display (injects `<ixfx-icon>`) |
|
|
100
|
+
| `not-checked` | In `checked` mode, renders without a checkbox and cannot be checked |
|
|
101
|
+
| `hidden` | Hides the item from view and navigation |
|
|
102
|
+
|
|
103
|
+
### Object items
|
|
104
|
+
|
|
105
|
+
Pass an array of objects and configure how to display them:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const files = [
|
|
109
|
+
{ name: 'Report Q1.pdf', size: 220, kind: 'doc' },
|
|
110
|
+
{ name: 'Photo 01.png', size: 1400, kind: 'img' },
|
|
111
|
+
{ name: 'Notes.txt', size: 3, kind: 'doc' },
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
list.items = files;
|
|
115
|
+
list.displayProperty = 'name';
|
|
116
|
+
list.keyProperty = 'name'; // Preserves selection across rebuilds
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Object-related properties:**
|
|
120
|
+
|
|
121
|
+
| Property | Type | Description |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `items` | `readonly unknown[]` | Array of objects to render |
|
|
124
|
+
| `displayProperty` | `string` | Property name to use as label |
|
|
125
|
+
| `keyProperty` | `string` | Property name for stable identity |
|
|
126
|
+
| `iconProperty` | `string` | Property name for icon name |
|
|
127
|
+
| `formatter` | `(item: unknown, index: number) => string \| Node` | Custom renderer |
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
list.formatter = (item, index) => {
|
|
131
|
+
const file = item as { name: string; size: number };
|
|
132
|
+
return `${file.name} (${file.size} KB)`;
|
|
133
|
+
};
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Retrieve the original data for an element:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const data = list.getItemData(liElement);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Properties
|
|
145
|
+
|
|
146
|
+
| Property | Attribute | Type | Default | Description |
|
|
147
|
+
|---|---|---|---|---|
|
|
148
|
+
| `selectionMode` | `selection-mode` | `'single' \| 'multiple' \| 'none'` | `'single'` | How selection works |
|
|
149
|
+
| `interactionMode` | `interaction-mode` | `'implicit' \| 'standard' \| 'manual' \| 'checked' \| 'sticky' \| 'vscode'` | `'standard'` | Click/keyboard behavior |
|
|
150
|
+
| `sort` | `sort` | `'none' \| 'ascending' \| 'descending'` | `'none'` | Sort direction |
|
|
151
|
+
| `sortBy` | `sort-by` | `string` | — | Object property to sort by |
|
|
152
|
+
| `sortComparator` | — | `(a, b) => number` | — | Custom sort function |
|
|
153
|
+
| `filterPredicate` | — | `(el: Element) => boolean` | — | Filter visible items |
|
|
154
|
+
| `itemWrap` | `item-wrap` | `'stop' \| 'wrap'` | `'stop'` | Keyboard wrap behavior |
|
|
155
|
+
| `provider` | — | `IDataProvider` | — | Async data source |
|
|
156
|
+
| `checkboxRenderer` | — | `function \| object` | — | Custom checkbox |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Selection
|
|
161
|
+
|
|
162
|
+
### Getters
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const selected = list.selectedItem; // First selected element or undefined
|
|
166
|
+
const allSelected = list.selectedItems; // Array of all selected elements
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Methods
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
list.select(item); // Select an item
|
|
173
|
+
list.deselect(item); // Deselect an item
|
|
174
|
+
list.selectMany([item1, item2]); // Select multiple
|
|
175
|
+
list.clearSelection(); // Clear all selections
|
|
176
|
+
list.selectAll(); // Select all visible items (if permitted)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Interaction modes
|
|
182
|
+
|
|
183
|
+
| Mode | Description |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `standard` | Click replaces selection. Ctrl+click toggles. Shift+click creates range. Cmd+A selects all. |
|
|
186
|
+
| `implicit` | Click always replaces selection (no modifier support). |
|
|
187
|
+
| `checked` | Checkbox column toggles selection; rows marked `not-checked` have no checkbox. |
|
|
188
|
+
| `sticky` | Every click toggles. Cmd+A selects all. |
|
|
189
|
+
| `vscode` | Like `standard`, but Shift+Arrow extends selection range. |
|
|
190
|
+
| `manual` | No auto-selection; drive state via `select()` / `deselect()` programmatically. |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Custom checkbox
|
|
195
|
+
|
|
196
|
+
In `checked` mode, provide a custom checkbox renderer:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
list.checkboxRenderer = (checked) => checked
|
|
200
|
+
? html`<span>✓</span>`
|
|
201
|
+
: html``;
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Or use the shorthand object form:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
list.checkboxRenderer = { checked: '✓', unchecked: '' };
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Events
|
|
213
|
+
|
|
214
|
+
| Event | Detail | Description |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| `list-select` | `{ selected: Element[] }` | Selection changed |
|
|
217
|
+
| `list-tickle` | `{ item: Element }` | Hover/focus cursor moved |
|
|
218
|
+
| `list-activate` | `{ item: Element }` | Item activated (Enter/double-click) |
|
|
219
|
+
| `list-item-click` | `{ item: Element }` | Item clicked |
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
list.addEventListener('list-select', (e) => {
|
|
223
|
+
console.log('Selected:', [...e.detail.selected].map(el => el.textContent));
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Keyboard navigation
|
|
230
|
+
|
|
231
|
+
The list must have focus for keyboard navigation. Click an item to focus, or set `tabindex="0"` on the element.
|
|
232
|
+
|
|
233
|
+
| Key | Action |
|
|
234
|
+
|---|---|
|
|
235
|
+
| ↑ / ↓ | Move up/down within the current column |
|
|
236
|
+
| ← / → | Jump to previous/next column (same row) |
|
|
237
|
+
| Home | Jump to first item |
|
|
238
|
+
| End | Jump to last item |
|
|
239
|
+
| Enter | Activate item (fires `list-activate`) |
|
|
240
|
+
| Space | Toggle selection (in modes that support it) |
|
|
241
|
+
| Escape | Clear selection / close search |
|
|
242
|
+
| Ctrl+F | Open incremental search |
|
|
243
|
+
| Ctrl+A | Select all (in modes that support it) |
|
|
244
|
+
|
|
245
|
+
### Wrapping
|
|
246
|
+
|
|
247
|
+
Set `item-wrap="wrap"` to enable wraparound navigation:
|
|
248
|
+
|
|
249
|
+
```html
|
|
250
|
+
<ixfx-detail-list item-wrap="wrap">...</ixfx-detail-list>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
With wrapping:
|
|
254
|
+
- Down from last row → first row of next column (or first column if at end)
|
|
255
|
+
- Up from first row → last row of previous column (or last column if at start)
|
|
256
|
+
- Right from last column → first column
|
|
257
|
+
- Left from first column → last column
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Incremental search
|
|
262
|
+
|
|
263
|
+
Press Ctrl+F (or Cmd+F on Mac) to open the search overlay. Type to filter items in real-time using fuzzy matching.
|
|
264
|
+
|
|
265
|
+
Search matches against `data-search-label` (or `textContent` as fallback). Use `data-search-label` to match against a different string than what's displayed:
|
|
266
|
+
|
|
267
|
+
```html
|
|
268
|
+
<li data-search-label="document a alpha">Document A</li>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Highlight styling
|
|
272
|
+
|
|
273
|
+
Matched characters are highlighted with the `detail-list-search` highlight key. Style matches with:
|
|
274
|
+
|
|
275
|
+
```css
|
|
276
|
+
::highlight(detail-list-search) {
|
|
277
|
+
background: yellow;
|
|
278
|
+
color: black;
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Filter predicate
|
|
285
|
+
|
|
286
|
+
Use `filterPredicate` to programmatically hide items:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// Show only .doc files
|
|
290
|
+
list.filterPredicate = (el) => el.getAttribute('data-kind') === 'doc';
|
|
291
|
+
|
|
292
|
+
// Clear filter
|
|
293
|
+
list.filterPredicate = undefined;
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Filtered items are hidden from view, keyboard navigation, and selection.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Sorting
|
|
301
|
+
|
|
302
|
+
### Simple sort
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
list.sort = 'ascending'; // or 'descending'
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Sort by property
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
list.sortBy = 'size'; // Sort by 'size' property
|
|
312
|
+
list.sort = 'ascending';
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Custom comparator
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
list.sortComparator = (a, b) => {
|
|
319
|
+
// Sort by kind first, then by label
|
|
320
|
+
const kindCompare = a.data.kind.localeCompare(b.data.kind);
|
|
321
|
+
if (kindCompare !== 0) return kindCompare;
|
|
322
|
+
return a.label.localeCompare(b.label);
|
|
323
|
+
};
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
The comparator receives `{ element, data, label }` where:
|
|
327
|
+
- `element` — the `<li>` DOM element
|
|
328
|
+
- `data` — the original object from `items` array
|
|
329
|
+
- `label` — the display string
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Asynchronous data
|
|
334
|
+
|
|
335
|
+
Use a `provider` for async data loading:
|
|
336
|
+
|
|
337
|
+
### Promise provider
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
list.provider = async () => {
|
|
341
|
+
const response = await fetch('/api/items');
|
|
342
|
+
return response.json();
|
|
343
|
+
};
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Streaming provider
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
list.provider = async function*() {
|
|
350
|
+
for (let i = 0; i < 100; i++) {
|
|
351
|
+
yield [{ id: i, name: `Item ${i}` }];
|
|
352
|
+
await delay(100);
|
|
353
|
+
}
|
|
354
|
+
}();
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
The provider function can return:
|
|
358
|
+
- A promise that resolves to an array
|
|
359
|
+
- An async iterable that yields arrays (streaming)
|
|
360
|
+
|
|
361
|
+
Streaming providers extend columns to the right as batches arrive.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## CSS variables
|
|
366
|
+
|
|
367
|
+
| Variable | Default | Description |
|
|
368
|
+
|---|---|---|
|
|
369
|
+
| `--detail-list-bg` | `surface-3` | Background color |
|
|
370
|
+
| `--detail-list-text` | `surface-3-text` | Text color |
|
|
371
|
+
| `--detail-list-border` | `border` | Border color |
|
|
372
|
+
| `--detail-list-radius` | `radius-s` | Border radius |
|
|
373
|
+
| `--detail-list-column-width` | `220px` | Width of each column |
|
|
374
|
+
| `--detail-list-column-gap` | `8px` | Gap between columns |
|
|
375
|
+
| `--detail-list-item-height` | `28px` | Height of each item |
|
|
376
|
+
| `--detail-list-item-padding` | `0 var(--space-m)` | Item padding |
|
|
377
|
+
| `--detail-list-scrollbar-width` | `auto` | Scrollbar width |
|
|
378
|
+
| `--detail-list-scrollbar-gutter` | `auto` | Scrollbar gutter |
|
|
379
|
+
| `--detail-list-scrollbar-color` | `auto` | Scrollbar color |
|
|
380
|
+
|
|
381
|
+
Plus all `--item-bg-*`, `--item-text-*` variables from the theme for selection/tickle states.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## CSS parts
|
|
386
|
+
|
|
387
|
+
| Part | Description |
|
|
388
|
+
|---|---|
|
|
389
|
+
| `list` | The `<ul>` container |
|
|
390
|
+
| `search-overlay` | The Ctrl+F search overlay |
|
|
391
|
+
| `checkbox` | The checkbox element (in `checked` mode) |
|
|
392
|
+
| `loading` | The loading indicator |
|
|
393
|
+
|
|
394
|
+
```css
|
|
395
|
+
ixfx-detail-list::part(search-overlay) {
|
|
396
|
+
background: rgba(0, 0, 0, 0.8);
|
|
397
|
+
}
|
|
398
|
+
```
|