@ixfx/components 0.16.1 → 0.16.3
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 +272 -58
- package/bundle/index.js +400 -337
- package/dist/ac-token.js +1 -1
- package/dist/{crumb-navigation-YnFVFqrx.js → crumb-navigation-D3ndPgFg.js} +2 -2
- package/dist/crumbs.js +1 -1
- package/dist/{data-grid-Cqxuwgbb.js → data-grid-8TsiF2ES.js} +142 -60
- package/dist/{data-grid-Csh5EJW9.d.ts → data-grid-CslzF16R.d.ts} +21 -3
- package/dist/data-grid.d.ts +2 -2
- package/dist/data-grid.js +1 -1
- package/dist/{detail-list-DSZ1DDor.d.ts → detail-list-n1MbNbhF.d.ts} +11 -3
- package/dist/{detail-list-Bo5ze3SN.js → detail-list-w3GXKO2k.js} +71 -19
- package/dist/detail-list.d.ts +2 -2
- package/dist/detail-list.js +1 -1
- package/dist/{flat-list-CT9kX3TQ.d.ts → flat-list-D_4y3wgn.d.ts} +7 -2
- package/dist/flat-list.d.ts +1 -1
- package/dist/flat-list.js +5 -2
- package/dist/{grid-list-DDLrWRxm.d.ts → grid-list-CqYS28NY.d.ts} +60 -14
- package/dist/{grid-list-D0dJNVEF.js → grid-list-Cz2tKcNZ.js} +55 -17
- 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-CS4yInuw.d.ts} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{incr-search-CgbL-OlS.js → incr-search-Dc6gYpJG.js} +34 -5
- package/dist/incr-search.d.ts +1 -1
- package/dist/incr-search.js +1 -1
- package/dist/{index-CUErGhCg.d.ts → index-Bm9a9S3_.d.ts} +2 -1
- package/dist/{index-Bnm-kKGC.d.ts → index-DyaHA9Kk.d.ts} +20 -1
- package/dist/{index-D-lZNlHa.d.ts → index-VAs9akt4.d.ts} +18 -2
- package/dist/{index-DxyyVqzA.d.ts → index-ZaA90u09.d.ts} +1 -0
- package/dist/index.d.ts +45 -14
- package/dist/index.js +93 -17
- package/dist/{list-selection-controller-5L0Nj9tR.js → list-selection-controller-D4iIrvJH.js} +199 -57
- package/dist/list-selection-types-Dnamh2Lu.d.ts +109 -0
- package/dist/{menu-CU9KAm8s.js → menu-BX1FHxY8.js} +16 -1
- package/dist/{menu-item-BUv8An2k.js → menu-item-oxU1VKiJ.js} +34 -9
- package/dist/menu.d.ts +1 -1
- package/dist/menu.js +2 -2
- package/dist/{miller-DUqiUAWQ.js → miller-Be7x4ufN.js} +142 -10
- package/dist/miller.d.ts +1 -1
- package/dist/miller.js +1 -1
- package/dist/narrowed-text.js +1 -1
- package/dist/partial-keys-Ck6CiprB.js +32 -0
- package/dist/sunburst-tree.d.ts +1 -1
- package/dist/sunburst-tree.js +1 -1
- package/dist/{sunbursttree-list-DePuFYlU.d.ts → sunbursttree-list-Bk20giTF.d.ts} +1 -1
- package/dist/{sunbursttree-list-B_M0YTEA.js → sunbursttree-list-DQF6DcsS.js} +1 -1
- package/dist/timeline.d.ts +1 -1
- package/dist/{tree-DAlgvaHB.js → tree-BaXYyt5U.js} +185 -69
- package/dist/tree.d.ts +1 -1
- package/dist/tree.js +1 -1
- package/dist/{vertical-list-SAx56U-l.d.ts → vertical-list-DtHX26JO.d.ts} +11 -2
- package/dist/{vertical-list-DyKPKGxK.js → vertical-list-o5hfqH87.js} +54 -19
- package/dist/vertical-list.d.ts +2 -2
- package/dist/vertical-list.js +1 -1
- package/docs-user/README.md +1 -0
- package/docs-user/data-grid.md +10 -3
- package/docs-user/detail-list.md +1 -1
- package/docs-user/grid-list.md +4 -1
- package/docs-user/index.json +6 -2
- package/docs-user/llms.txt +1 -0
- package/docs-user/menu.md +11 -1
- package/docs-user/miller.md +4 -0
- package/docs-user/multicol-list.md +6 -0
- package/docs-user/select-horiz.md +1 -1
- package/docs-user/tree.md +6 -0
- package/docs-user/user-selection-intents.md +86 -0
- package/docs-user/vertical-list.md +9 -1
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/dist/list-selection-types-PjKdhF-a.d.ts +0 -45
- /package/dist/{index-DV3iaUBW.d.ts → index-DV3iaUBW2.d.ts} +0 -0
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-o5hfqH87.js";
|
|
2
2
|
export { VerticalListElement };
|
package/docs-user/README.md
CHANGED
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](./user-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
|
|
package/docs-user/detail-list.md
CHANGED
|
@@ -310,7 +310,7 @@ the Element API is unchanged, the key API is additive. Object items built from
|
|
|
310
310
|
`items` / a provider get their key stamped automatically from `keyProperty`.
|
|
311
311
|
|
|
312
312
|
```typescript
|
|
313
|
-
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
|
|
314
314
|
list.addSelectedKeys(['row-9']); // multi-select modes only
|
|
315
315
|
list.removeSelectedKeys(['row-3']);
|
|
316
316
|
list.selectedKeys; // ReadonlySet<string>
|
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](./user-selection-intents.md): `list-select-intent`, `partialKeys`, and keys that arrive later.
|
|
198
|
+
|
|
196
199
|
Restore across a reload:
|
|
197
200
|
|
|
198
201
|
```typescript
|
package/docs-user/index.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixfx/components",
|
|
3
|
-
"version": "0.16.
|
|
4
|
-
"generated": "2026-
|
|
3
|
+
"version": "0.16.3",
|
|
4
|
+
"generated": "2026-11-02T20:40:41.501Z",
|
|
5
5
|
"components": [
|
|
6
6
|
{
|
|
7
7
|
"name": "ac-text",
|
|
@@ -313,6 +313,10 @@
|
|
|
313
313
|
"name": "user-catalog.md",
|
|
314
314
|
"path": "docs-user/user-catalog.md"
|
|
315
315
|
},
|
|
316
|
+
{
|
|
317
|
+
"name": "user-selection-intents.md",
|
|
318
|
+
"path": "docs-user/user-selection-intents.md"
|
|
319
|
+
},
|
|
316
320
|
{
|
|
317
321
|
"name": "user-theming.md",
|
|
318
322
|
"path": "docs-user/user-theming.md"
|
package/docs-user/llms.txt
CHANGED
|
@@ -75,4 +75,5 @@ import '@ixfx/components/data-grid';
|
|
|
75
75
|
## Overviews
|
|
76
76
|
- [infra-tickled.md](docs-user/infra-tickled.md)
|
|
77
77
|
- [user-catalog.md](docs-user/user-catalog.md)
|
|
78
|
+
- [user-selection-intents.md](docs-user/user-selection-intents.md)
|
|
78
79
|
- [user-theming.md](docs-user/user-theming.md)
|
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 |
|
package/docs-user/miller.md
CHANGED
|
@@ -149,6 +149,10 @@ The `change` event is fired on the component after every checkbox toggle.
|
|
|
149
149
|
|
|
150
150
|
---
|
|
151
151
|
|
|
152
|
+
## Selection intents and partial rows
|
|
153
|
+
|
|
154
|
+
`ixfx-miller-list` fires a cancelable `list-select-intent` before a click (all interaction modes, including `manual`), a checkbox toggle or a Shift+Arrow range changes the selection; `preventDefault()` means "I'll apply it". Navigation (opening the node's column) still happens. It also fires `list-select` `{ selectedKeys, previousKeys, previous }` next to `select`, and supports `partialKeys` (indeterminate checkbox in `checked` mode, `.partial` otherwise; selected wins; in `checked` mode it overrides the state derived from loaded descendants). In `checked` mode the checkbox intent is for the node only: the cascade to loaded descendants is the caller's call. See [Selection intents, partial rows, unloaded keys](./user-selection-intents.md).
|
|
155
|
+
|
|
152
156
|
## Selection API
|
|
153
157
|
|
|
154
158
|
```typescript
|
|
@@ -62,6 +62,12 @@ one column (the first category) once `categories` is assigned.
|
|
|
62
62
|
|
|
63
63
|
---
|
|
64
64
|
|
|
65
|
+
## Selection intents and partial rows
|
|
66
|
+
|
|
67
|
+
Gestures in a column (click, Space, Enter, Shift+Arrow, Cmd/Ctrl+A, marquee, the column's incremental search, the "All" row) fire a cancelable `list-select-intent` on the multicol host with `columnId` set; `keys` are that column's item keys. Going back to "All" is a `clear` intent. `preventDefault()` leaves the column alone.
|
|
68
|
+
|
|
69
|
+
`partialKeys` marks items as partially selected in every column that has an item with that key; `setColumnPartialKeys(columnId, keys)` adds keys for one column only. Selected wins. See [Selection intents, partial rows, unloaded keys](./user-selection-intents.md).
|
|
70
|
+
|
|
65
71
|
## Data flow
|
|
66
72
|
|
|
67
73
|
1. A selection change in column *i* re-queries **every other** column; column *i*'s list
|
|
@@ -98,7 +98,7 @@ Click an item (or Tab to the element) to focus it first — a focus ring appears
|
|
|
98
98
|
| `--select-horiz-spacer-width` | `10%` | Width of the leading/trailing spacer that lets the first/last item scroll to center |
|
|
99
99
|
| `--scroll-fade-width` | `30px` | Width of the edge fade and the inner horizontal padding (shared with `scrollFadeStyles`) |
|
|
100
100
|
|
|
101
|
-
Items are styled with the standard `--item-*` theming tokens (see [`docs/user-theming.md`](
|
|
101
|
+
Items are styled with the standard `--item-*` theming tokens (see [`docs/user-theming.md`](./user-theming.md)):
|
|
102
102
|
|
|
103
103
|
| Property | State |
|
|
104
104
|
|---|---|
|
package/docs-user/tree.md
CHANGED
|
@@ -424,6 +424,12 @@ el.addEventListener('select', ({ detail }) => {
|
|
|
424
424
|
|
|
425
425
|
---
|
|
426
426
|
|
|
427
|
+
### Selection intents and partial rows (`ixfx-tree-list`)
|
|
428
|
+
|
|
429
|
+
A cancelable `list-select-intent` fires before a click, Space, Enter, Shift+Arrow, Ctrl/Cmd+A, a checkbox or `selectAll()` changes the selection (in every interaction mode, including `manual`); `preventDefault()` means "I'll apply it". Expansion and the cursor still behave normally. Checking a branch in `checked` mode is one `toggle` intent with `descendants: true` and `checked` (the state it is being set to): `keys` lists the loaded selectable nodes under it, but the caller can express it as a rule ("this folder and everything under it"). `list-select` `{ selectedKeys, previousKeys, previous }` fires next to `select`.
|
|
430
|
+
|
|
431
|
+
`partialKeys` marks nodes as partially selected: in `checked` mode the checkbox is indeterminate if either the loaded descendants or `partialKeys` say so (selected wins over partial); otherwise `data-partial` and an accessible description. Incremental search in `select` mode fires a `match` intent first (see below). See [Selection intents, partial rows, unloaded keys](./user-selection-intents.md).
|
|
432
|
+
|
|
427
433
|
## Expansion
|
|
428
434
|
|
|
429
435
|
### Programmatic expansion
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Selection intents, partial rows, unloaded keys
|
|
2
|
+
|
|
3
|
+
Shared by every list-like component: `ixfx-vertical-list`, `ixfx-flat-list`, `ixfx-detail-list`, `ixfx-grid-list`, `ixfx-data-grid`, `ixfx-miller-list`, `ixfx-tree-list` and `ixfx-multicol-list`. For a caller that owns the selection itself (e.g. a selection that is an expression or a set of rules, not a key set), so a list shows what it is given and reports what the user did.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `list-select-intent` (cancelable)
|
|
8
|
+
|
|
9
|
+
Fired **before** a component changes its selection, in every interaction mode (including `manual`, where nothing is selected by default). `preventDefault()` means "I apply this myself": the component changes nothing. Without it, behaviour is unchanged.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
type ListSelectIntentDetail = {
|
|
13
|
+
readonly kind:
|
|
14
|
+
| `replace` // plain click / Enter: select only `keys`
|
|
15
|
+
| `toggle` // Cmd/Ctrl-click, Space, sticky tap, checkbox: flip `keys`
|
|
16
|
+
| `extend` // Shift-click / Shift+Arrow: range from `anchorKey` to `targetKey`
|
|
17
|
+
| `all` // Cmd/Ctrl+A or selectAll(): "everything in this view", not a key list
|
|
18
|
+
| `marquee` // drag-select: `keys` covered; `mode` says how they combine with the selection
|
|
19
|
+
| `match` // incremental search in `select` mode / "Select matches"
|
|
20
|
+
| `clear`; // Escape / click on empty space / back to "All" in a multicol column
|
|
21
|
+
readonly keys: readonly string[]; // keys directly affected (empty for `all` / `clear`)
|
|
22
|
+
readonly anchorKey?: string; // `extend`
|
|
23
|
+
readonly targetKey?: string; // `extend`
|
|
24
|
+
readonly mode?: `replace` | `add` | `toggle`; // `marquee`
|
|
25
|
+
readonly additive?: boolean; // `marquee`: `mode` is not `replace`
|
|
26
|
+
readonly query?: string; // `match`: the search text
|
|
27
|
+
readonly groupKey?: string | null; // `all`: the group the select-all is confined to
|
|
28
|
+
readonly descendants?: boolean; // `toggle` on a tree branch checkbox: node + loaded descendants
|
|
29
|
+
readonly checked?: boolean; // ...and the state it is being set to
|
|
30
|
+
readonly columnId?: string; // multicol-list: the column
|
|
31
|
+
readonly source: `pointer` | `keyboard` | `touch` | `api`;
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
list.addEventListener('list-select-intent', (e) => {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
const { kind, keys, anchorKey, targetKey } = e.detail;
|
|
39
|
+
// ...compute the new selection from your own model, then:
|
|
40
|
+
list.selectKeys(newKeys);
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- **`extend` gives endpoints.** `keys` also holds the range as loaded here, but rows in between may not be loaded (virtualised / progressive listings): compute the range from your own order using `anchorKey` / `targetKey`.
|
|
45
|
+
- **`all` is a meaning, not a list.** Turn it into your own scope rule instead of enumerating keys. In grouped lists with `cross-group-selection` off, select-all is confined to one group (the anchor's group, else the cursor's): `groupKey` names it, so a caller that takes over does the same. It is absent when select-all is not confined.
|
|
46
|
+
- **`marquee` `mode`.** `replace`: the selection becomes the covered `keys` (plain drag). `add`: covered keys are added (Shift-drag). `toggle`: each covered key flips, so a Cmd/Ctrl-drag can deselect. `additive` is just `mode !== 'replace'`; use `mode`.
|
|
47
|
+
- **`match` is a search.** Incremental search in `select` mode (typing, and `selectMatches()` / the "Select matches" button) reports `{ kind: 'match', query, keys }` — `keys` are the current matches, a convenience; `query` is what to keep as a live rule. Cancelling it leaves the selection untouched while the popover keeps showing the matches. Source is `keyboard` while typing, `pointer` for the button, `api` for `selectMatches()`.
|
|
48
|
+
- **Tree branch checkboxes.** In `ixfx-tree-list` `checked` mode, checking a branch is one `toggle` with `descendants: true` and `checked` (the state the branch is being set to); `keys` lists the loaded selectable nodes under it, but express it as a rule.
|
|
49
|
+
- **Cursor and anchor keep moving when cancelled.** They are view state, not selection; the next `extend` still has its `anchorKey`.
|
|
50
|
+
- **Who fires it.** Gestures (click, Space, Enter, double-click, checkbox, Shift+Arrow, Cmd/Ctrl+A, marquee, Escape, click on empty space) and `selectAll()`. The imperative `select()` / `selectKeys()` / `clearSelection()` family never fires it, so applying your decision through them cannot re-enter your handler.
|
|
51
|
+
- **`manual` mode.** The intent is reported and nothing else happens, so the caller never re-implements modifier handling. (`ixfx-data-grid` keeps Space toggling in `manual`, as before.)
|
|
52
|
+
- **Not covered.** Right-click auto-select and the drag-origin auto-select of native drag-out still apply directly. `ixfx-miller-list` reports click / checkbox / Shift+Arrow; it has no select-all, and Escape navigates rather than clears. In `checked` mode a miller checkbox intent is for the node only; the descendant cascade is the caller's decision.
|
|
53
|
+
|
|
54
|
+
## `list-select` (consistent)
|
|
55
|
+
|
|
56
|
+
Every list-like component fires `list-select` with the same key-based detail:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
{ selectedKeys: ReadonlySet<string>, previousKeys: ReadonlySet<string> /* , plus component-specific extras */ }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Vertical-list, detail-list and grid-list keep their element-based `selected` / `previous`; data-grid keeps `datagrid-select` (and adds `list-select` with `previous` as keys); miller keeps `select` (and adds `list-select`). One adapter can read any of them through `selectedKeys` / `previousKeys`. Miller now also fires for Cmd-click and Shift-click selection changes.
|
|
63
|
+
|
|
64
|
+
## `partialKeys`
|
|
65
|
+
|
|
66
|
+
A row whose resource is only partly selected (a time range of an audio file, a region of an image):
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
list.partialKeys = ['k1', 'k2']; // ReadonlySet<string> getter; replace-on-set
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- Independent of `selectedKeys`; a key in both counts as selected.
|
|
73
|
+
- Light-DOM lists (vertical, detail): `data-partial` on the row; grid-list cell and data-grid row: `data-partial` plus `.partial` (`part="item partial"` on grid-list); miller: `.partial`.
|
|
74
|
+
- Accessibility: in `checked` mode the checkbox is indeterminate with `aria-checked="mixed"`; otherwise the row gets `aria-description="Partially selected"` (an author-set `aria-description` is never overwritten).
|
|
75
|
+
- Style hooks: `--item-bg-partial`, `--item-border-partial` (`--grid-list-partial-outline` on grid-list).
|
|
76
|
+
- `ixfx-flat-list` forwards `partialKeys` to its inner list. Miller's `checked` mode still derives indeterminate from loaded descendants; `partialKeys` overrides that for the keys you set.
|
|
77
|
+
|
|
78
|
+
## Selected keys that aren't loaded yet
|
|
79
|
+
|
|
80
|
+
`selectKeys()` on vertical-list, flat-list (`flat.list`), detail-list and grid-list keeps keys with no row yet as *pending* and selects them when the row appears (`selectedKeys` lists only present rows). `addSelectedKeys()` does the same; `removeSelectedKeys()` also drops pending keys. Any explicit gesture-driven selection change supersedes pending keys, in single-select only the last unresolved key is kept, and pending keys are capped (2000, oldest dropped). `ixfx-data-grid` already behaved this way. A key that is selected and then leaves the data is reselected if it returns (view-state pending).
|
|
81
|
+
|
|
82
|
+
## Per-component notes
|
|
83
|
+
|
|
84
|
+
- **`ixfx-tree-list`** — also fires `list-select` next to `select`. `partialKeys` combines with the checkbox state derived from loaded descendants: indeterminate if either says so; selected wins.
|
|
85
|
+
- **`ixfx-multicol-list`** — the intent is re-fired on the host with `columnId`; the "All" row is a `clear`. `partialKeys` applies to every column with a matching item key; `setColumnPartialKeys(columnId, keys)` targets one column.
|
|
86
|
+
- **`ixfx-miller-list`** — see above; `checked` mode checkbox intents are for the node only.
|
|
@@ -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](./user-selection-intents.md): `list-select-intent`, `partialKeys`, and keys that arrive later.
|
|
541
|
+
|
|
534
542
|
### Usage example
|
|
535
543
|
|
|
536
544
|
```typescript
|
package/llms.txt
CHANGED
|
@@ -75,4 +75,5 @@ import '@ixfx/components/data-grid';
|
|
|
75
75
|
## Overviews
|
|
76
76
|
- [infra-tickled.md](docs-user/infra-tickled.md)
|
|
77
77
|
- [user-catalog.md](docs-user/user-catalog.md)
|
|
78
|
+
- [user-selection-intents.md](docs-user/user-selection-intents.md)
|
|
78
79
|
- [user-theming.md](docs-user/user-theming.md)
|
package/package.json
CHANGED
|
@@ -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 };
|
|
File without changes
|