@ixfx/components 0.17.1 → 0.18.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.
Files changed (76) hide show
  1. package/bundle/index.d.ts +351 -11
  2. package/bundle/index.js +402 -361
  3. package/dist/ac-text.js +1 -1
  4. package/dist/ac-token.js +2 -2
  5. package/dist/{checked-select-BmwqpgGr.js → checked-select-CC-qSO1P.js} +2 -2
  6. package/dist/checked-select.js +1 -1
  7. package/dist/{crumb-navigation-D7dAC0H-.js → crumb-navigation-C78edQGt.js} +3 -3
  8. package/dist/{crumb-navigation-Tm4fnsvN.d.ts → crumb-navigation-DOfOS7li.d.ts} +1 -1
  9. package/dist/crumbs.d.ts +1 -1
  10. package/dist/crumbs.js +1 -1
  11. package/dist/{data-grid-vasJtjFP.d.ts → data-grid-BYMZZbNc.d.ts} +32 -3
  12. package/dist/{data-grid-BcO3SMac.js → data-grid-CJrbLzLr.js} +80 -18
  13. package/dist/data-grid.d.ts +2 -2
  14. package/dist/data-grid.js +1 -1
  15. package/dist/{detail-list-E9WdMVbE.d.ts → detail-list-CBgnKkEm.d.ts} +35 -3
  16. package/dist/{detail-list-vPVwE1CP.js → detail-list-Dk9oSvAZ.js} +75 -10
  17. package/dist/detail-list.d.ts +3 -3
  18. package/dist/detail-list.js +1 -1
  19. package/dist/{flat-list-CfutGqKY.d.ts → flat-list-D5glF_vD.d.ts} +5 -3
  20. package/dist/flat-list.d.ts +1 -1
  21. package/dist/flat-list.js +5 -3
  22. package/dist/{grid-list-D2hinM64.js → grid-list-0wC2xGBS.js} +104 -14
  23. package/dist/{grid-list-OCdjuhng.d.ts → grid-list-B3T_2N0N.d.ts} +34 -4
  24. package/dist/grid-list.d.ts +2 -2
  25. package/dist/grid-list.js +1 -1
  26. package/dist/{incr-search-C5114RxZ.js → incr-search-Bk4acsCM.js} +14 -6
  27. package/dist/incr-search.d.ts +1 -1
  28. package/dist/incr-search.js +1 -1
  29. package/dist/{index-88ra6YHP.d.ts → index-BIv_Hu7C.d.ts} +4 -4
  30. package/dist/{index-CRLTVAyt.d.ts → index-BuvySJEc.d.ts} +5 -1
  31. package/dist/{index-CzhYJJsx.d.ts → index-fhZCKSY6.d.ts} +3 -3
  32. package/dist/index.d.ts +134 -26
  33. package/dist/index.js +479 -130
  34. package/dist/interaction-DNuFnTm0.js +3 -0
  35. package/dist/item-tags-Dz-jQq-4.d.ts +65 -0
  36. package/dist/{list-native-drag-controller-ByftBooJ.js → list-native-drag-controller-B_INa6_G.js} +109 -1
  37. package/dist/{list-native-drag-controller-CgXKdmjr.d.ts → list-native-drag-controller-Cs-Tmtaa.d.ts} +1 -1
  38. package/dist/{menu-C3DhTjHx.js → menu-CgT60B3-.js} +3 -3
  39. package/dist/{menu-item-BSxhlWnW.js → menu-item-CbywH4Xo.js} +3 -3
  40. package/dist/menu.js +2 -2
  41. package/dist/{miller-DqDEaXqT.js → miller-Dyv4UM7k.js} +3 -3
  42. package/dist/miller.d.ts +2 -2
  43. package/dist/miller.js +1 -1
  44. package/dist/narrowed-text.js +3 -3
  45. package/dist/{node-graph-DqEGv5QR.js → node-graph-yrbOLbYo.js} +1 -1
  46. package/dist/node-graph.js +1 -1
  47. package/dist/{notification-pill-BiHEJk-o.d.ts → notification-pill-BJonE_wo.d.ts} +14 -1
  48. package/dist/notifier.d.ts +1 -1
  49. package/dist/select-horiz.js +2 -2
  50. package/dist/sunburst-tree.d.ts +1 -1
  51. package/dist/sunburst-tree.js +1 -1
  52. package/dist/{sunbursttree-list-C-FuZB5z.js → sunbursttree-list-CJdznPzN.js} +2 -2
  53. package/dist/{sunbursttree-list-CsrmVSB8.d.ts → sunbursttree-list-CmydFG66.d.ts} +2 -2
  54. package/dist/{tickled-controller-BVhGKzjZ.js → tickled-controller-BsFFr_1N.js} +1 -1
  55. package/dist/{tickled-controller-DSPoG551.d.ts → tickled-controller-Dz0UqwlQ.d.ts} +5 -0
  56. package/dist/{tree-BP5fxvEX.js → tree-C3rgEEmm.js} +4 -4
  57. package/dist/{tree-component-DNuzfo6R.d.ts → tree-component-BE7OEIiH.d.ts} +7 -1
  58. package/dist/tree.d.ts +2 -2
  59. package/dist/tree.js +1 -1
  60. package/dist/{vertical-list-B9z1lbjM.js → vertical-list-By-yuhkw.js} +61 -6
  61. package/dist/{vertical-list-BzeXehBt.d.ts → vertical-list-C4z3La0C.d.ts} +26 -2
  62. package/dist/vertical-list.d.ts +2 -2
  63. package/dist/vertical-list.js +1 -1
  64. package/docs-user/README.md +1 -0
  65. package/docs-user/button.md +31 -1
  66. package/docs-user/data-grid.md +3 -0
  67. package/docs-user/detail-list.md +3 -0
  68. package/docs-user/grid-list.md +8 -0
  69. package/docs-user/index.json +6 -2
  70. package/docs-user/llms.txt +1 -0
  71. package/docs-user/multicol-list.md +3 -0
  72. package/docs-user/notifier.md +28 -0
  73. package/docs-user/user-item-tags.md +68 -0
  74. package/llms.txt +1 -0
  75. package/package.json +3 -3
  76. package/dist/interaction-8Kbbf6xN.js +0 -3
@@ -1,9 +1,10 @@
1
- import { L as ListDragPreviewRenderer, R as ListDragPreviewSourceResolver, V as ListNativeDragStartEvent } from "./tree-component-DNuzfo6R.js";
1
+ import { i as ItemTagKeys, n as ItemTagBehaviour } from "./item-tags-Dz-jQq-4.js";
2
2
  import { a as ViewStateBase, t as GetViewStateOptions } from "./types-16GC5k1z.js";
3
+ import { H as ListNativeDragStartEvent, P as ListDragDataTransferWriter, R as ListDragPreviewRenderer, z as ListDragPreviewSourceResolver } from "./tree-component-BE7OEIiH.js";
3
4
  import { h as ListSelectionMode, i as ListInteractionMode, r as ListElementEventMap } from "./list-selection-types-CKTt7Rrw.js";
4
5
  import { n as ListViewportChangeEvent } from "./list-viewport-types-BJ8c6qur.js";
5
6
  import "./index-Cdcek1Oj.js";
6
- import { S as ListSearchController } from "./index-CRLTVAyt.js";
7
+ import { S as ListSearchController } from "./index-BuvySJEc.js";
7
8
  import "./editable-label-CiHCDlhC.js";
8
9
  import { LitElement, PropertyValues } from "lit";
9
10
  import { CommandId, CommandRegistry } from "@clinth/ui-commands";
@@ -113,6 +114,12 @@ declare class VerticalListElement extends LitElement {
113
114
  * built-in HTML+canvas preview.
114
115
  */
115
116
  dragPreviewRenderer: ListDragPreviewRenderer<Element> | undefined;
117
+ /**
118
+ * Write an application payload onto the drag's `DataTransfer` (e.g. a custom
119
+ * MIME type). Called once per drag, synchronously inside `dragstart`, after a
120
+ * non-cancelled `list-native-drag-start`.
121
+ */
122
+ writeDataTransfer: ListDragDataTransferWriter<Element> | undefined;
116
123
  dragPreviewSource: ListDragPreviewSourceResolver<Element> | undefined;
117
124
  /**
118
125
  * Object/adapter item mode (mirrors `ixfx-detail-list`). When set, the list
@@ -257,6 +264,23 @@ declare class VerticalListElement extends LitElement {
257
264
  selectAll(): void;
258
265
  /** The selection as stable `data-key` / `data-value` strings. */
259
266
  get selectedKeys(): ReadonlySet<string>;
267
+ /**
268
+ * Tags assigned by key, apart from the item data (like {@link partialKeys}):
269
+ * tag name → keys carrying it. Each tag is mirrored on the row as `data-tags`
270
+ * (`li[data-tags~="foo"]`); `tagBehaviour` can switch off selection, focus,
271
+ * drag or search per tag.
272
+ */
273
+ get tagKeys(): ItemTagKeys | undefined;
274
+ set tagKeys(value: ItemTagKeys | undefined);
275
+ /**
276
+ * Interaction flags per tag name: `selectable`, `focusable`, `draggable`,
277
+ * `searchable` (`false` switches one off; omitted keeps the default). With
278
+ * several tags the most restrictive wins. Rows stay rendered.
279
+ */
280
+ get tagBehaviour(): ItemTagBehaviour | undefined;
281
+ set tagBehaviour(value: ItemTagBehaviour | undefined);
282
+ /** Re-apply `data-tags` to the rows and refresh drag state. Called automatically on change and after each update. */
283
+ refreshTags(): void;
260
284
  /**
261
285
  * Rows shown as *partially* selected (a part of the resource is selected):
262
286
  * `data-partial`, an indeterminate checkbox in `checked` mode, and an
@@ -1,5 +1,5 @@
1
- import { B as ListNativeDragStartDetail, F as ListDragPreview, I as ListDragPreviewContext, L as ListDragPreviewRenderer, P as ListDragEntry, V as ListNativeDragStartEvent, z as ListDragSource } from "./tree-component-DNuzfo6R.js";
1
+ import { B as ListDragSource, F as ListDragEntry, H as ListNativeDragStartEvent, I as ListDragPreview, L as ListDragPreviewContext, R as ListDragPreviewRenderer, V as ListNativeDragStartDetail } from "./tree-component-BE7OEIiH.js";
2
2
  import { n as ListViewportChangeEvent, t as ListViewportChangeDetail } from "./list-viewport-types-BJ8c6qur.js";
3
3
  import { _ as ListTickleEvent, a as ListItemClickDetail, c as ListSelectDetail, g as ListTickleDetail, h as ListSelectionMode, i as ListInteractionMode, l as ListSelectEvent, n as ListActivateEvent, o as ListItemClickEvent, r as ListElementEventMap, t as ListActivateDetail } from "./list-selection-types-CKTt7Rrw.js";
4
- import { a as VerticalListViewState, c as ListDragLeaveDetail, d as ListDropDetail, f as ListDropEvent, g as ListEditCommitEvent, h as ListEditCommitDetail, i as VerticalListElementEventMap, l as ListDragLeaveEvent, m as ListEditCancelEvent, n as CustomCheckboxOptions, o as ListContextMenuDetail, p as ListEditCancelDetail, r as VerticalListElement, s as ListContextMenuEvent, t as AddItemOptions, u as ListDragOverEvent } from "./vertical-list-BzeXehBt.js";
4
+ import { a as VerticalListViewState, c as ListDragLeaveDetail, d as ListDropDetail, f as ListDropEvent, g as ListEditCommitEvent, h as ListEditCommitDetail, i as VerticalListElementEventMap, l as ListDragLeaveEvent, m as ListEditCancelEvent, n as CustomCheckboxOptions, o as ListContextMenuDetail, p as ListEditCancelDetail, r as VerticalListElement, s as ListContextMenuEvent, t as AddItemOptions, u as ListDragOverEvent } from "./vertical-list-C4z3La0C.js";
5
5
  export { AddItemOptions, CustomCheckboxOptions, type ListActivateDetail, type ListActivateEvent, type ListContextMenuDetail, type ListContextMenuEvent, type ListDragEntry, type ListDragLeaveDetail, type ListDragLeaveEvent, type ListDragOverEvent, type ListDragPreview, type ListDragPreviewContext, type ListDragPreviewRenderer, type ListDragSource, type ListDropDetail, type ListDropEvent, type ListEditCancelDetail, type ListEditCancelEvent, type ListEditCommitDetail, type ListEditCommitEvent, type ListElementEventMap, type ListInteractionMode, type ListItemClickDetail, type ListItemClickEvent, type ListNativeDragStartDetail, type ListNativeDragStartEvent, type ListSelectDetail, type ListSelectEvent, type ListSelectionMode, type ListTickleDetail, type ListTickleEvent, type ListViewportChangeDetail, type ListViewportChangeEvent, VerticalListElement, VerticalListElementEventMap, type VerticalListViewState };
@@ -1 +1 @@
1
- export { t as VerticalListElement } from "./vertical-list-B9z1lbjM.js";
1
+ export { t as VerticalListElement } from "./vertical-list-By-yuhkw.js";
@@ -77,5 +77,6 @@ This directory contains documentation for each component and some architectural
77
77
  - [infra-view-state.md](infra-view-state.md)
78
78
  - [list-state.md](list-state.md)
79
79
  - [user-catalog.md](user-catalog.md)
80
+ - [user-item-tags.md](user-item-tags.md)
80
81
  - [user-selection-intents.md](user-selection-intents.md)
81
82
  - [user-theming.md](user-theming.md)
@@ -3,7 +3,7 @@
3
3
  Three related button components:
4
4
 
5
5
  - **`ixfx-button`** — a styled, icon-capable replacement for `<button>`
6
- - **`ixfx-split-button`** — a button paired with a dropdown caret; supports a static popup menu, a switcher mode, and programmatic item control
6
+ - **`ixfx-split-button`** — a button paired with a dropdown caret; supports a static popup menu, a switcher mode, a popover (slotted, by `popover-target`, or built just in time), and programmatic item control
7
7
  - **`ixfx-radio-group`** — a group of radio-style selectable items; also supports single toggle mode
8
8
 
9
9
  ---
@@ -246,6 +246,8 @@ Inherits all `ixfx-button` properties, plus:
246
246
  | `default-value` | string | `''` | Command to pre-select in switcher mode |
247
247
  | `items` | `PopupItem[]` | — | Directly set popup items (ignored when `itemsProvider` is set) |
248
248
  | `itemsProvider` | `() => PopupItem[] \| Promise<PopupItem[]>` | — | Called on each caret click; return value replaces all other item sources |
249
+ | `popover-target` | string | `''` | Id of a `popover` element the caret toggles instead of the menu (see [Popover](#popover-instead-of-a-menu)) |
250
+ | `popoverProvider` | `(popover: HTMLElement) => void \| Promise<void>` | — | Builds popover content just before each show |
249
251
  | `registry` | `CommandRegistry` | — | Optional command registry forwarded to `ixfx-menu-trigger` |
250
252
  | `keyboardManager` | `KeyboardManager` | — | Optional keyboard manager forwarded to `ixfx-menu-trigger` |
251
253
 
@@ -254,6 +256,7 @@ Inherits all `ixfx-button` properties, plus:
254
256
  | Slot | Description |
255
257
  |-----------|-------------------------------------------------------------------------------|
256
258
  | default | Primary button label |
259
+ | `popover` | Content of a popover the caret toggles instead of the menu |
257
260
  | `menu` | `<ixfx-menu-container>` + items for the popup (default mode); or `<ixfx-menu-item>` elements as the data source in switcher mode |
258
261
 
259
262
  ### Events
@@ -344,6 +347,33 @@ btn.itemsProvider = async () => {
344
347
 
345
348
  The popup shows a "Loading…" placeholder while the promise resolves. `itemsProvider` takes priority over `items` and declarative slot content.
346
349
 
350
+ #### Popover instead of a menu
351
+
352
+ The caret can toggle a native popover instead of the menu (works in both modes; the primary button is unaffected). Popover mode is on when any of these is present, and takes precedence over menu items:
353
+
354
+ ```html
355
+ <!-- 1. Slotted content: shown in a panel anchored under the caret (`part="popover"`) -->
356
+ <ixfx-split-button>
357
+ Share
358
+ <div slot="popover">Anyone with the link can view</div>
359
+ </ixfx-split-button>
360
+
361
+ <!-- 2. An existing popover element anywhere in the same tree -->
362
+ <ixfx-split-button popover-target="share-pop">Share</ixfx-split-button>
363
+ <div id="share-pop" popover>…</div>
364
+ ```
365
+
366
+ ```js
367
+ // 3. Build the content just in time. Runs each time the popover is about to show
368
+ // (awaited), with the panel — or the `popover-target` element — as the argument.
369
+ btn.popoverProvider = async (popover) => {
370
+ const people = await fetch('/api/people').then(r => r.json());
371
+ popover.replaceChildren(...people.map(p => Object.assign(document.createElement('div'), { textContent: p.name })));
372
+ };
373
+ ```
374
+
375
+ `popoverProvider` can be combined with either form; on its own it fills the built-in panel. The caret gets `aria-haspopup="dialog"` and `aria-expanded`, ArrowDown opens it, and clicking the caret again closes it. A `popover-target` element positions itself (the caret is passed as the popover `source`, so CSS anchor positioning can use it implicitly). Width of the built-in panel: `--ixfx-split-button-popover-max-width`.
376
+
347
377
  #### Change mode at runtime
348
378
 
349
379
  ```js
@@ -652,3 +652,6 @@ state.
652
652
 
653
653
  `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.
654
654
 
655
+
656
+ **Item tags:** `tags` hook / `tagKeys` → `data-tags` and `part="… tag-<name>"`; `tagBehaviour` switches off `selectable` / `focusable` / `draggable` / `searchable` per tag. See [Item tags](./user-item-tags.md).
657
+
@@ -759,3 +759,6 @@ compare runs against each other rather than against fixed budgets. The data
759
759
  grid has the same tooling (`pnpm bench:data-grid`); shared harness code is in
760
760
  `scripts/bench/`.
761
761
 
762
+
763
+ **Item tags:** `tags` hook / `tagKeys` → `data-tags` and `part="… tag-<name>"`; `tagBehaviour` switches off `selectable` / `focusable` / `draggable` / `searchable` per tag. See [Item tags](./user-item-tags.md).
764
+
@@ -278,6 +278,11 @@ Set `items-draggable` to make selectable cells draggable out of the grid. On
278
278
  for native hosts.
279
279
  - Assign `dragPreviewRenderer` for a custom synchronous preview returning
280
280
  `{ element, hotspot?, canvas?, dispose? }`.
281
+ - Assign `writeDataTransfer(dataTransfer, detail)` to put your own payload on
282
+ the drag (e.g. a custom MIME type). It is a public property on every list
283
+ (`ixfx-grid-list`, `ixfx-vertical-list`, `ixfx-detail-list`, `ixfx-data-grid`,
284
+ and forwarded by `ixfx-flat-list`), run synchronously in `dragstart` after a
285
+ non-cancelled `list-native-drag-start`.
281
286
  - `preventDefault()` on the event cancels the browser drag, but the sync
282
287
  listener still sees `preview` (incl. `canvas`) — what lets an Electron host
283
288
  rasterize it during the synchronous turn.
@@ -765,6 +770,9 @@ For finer control, style `::part(viewport)` directly (including
765
770
 
766
771
  ## Choosing a list component
767
772
 
773
+
774
+ **Item tags:** `tags` hook / `tagKeys` → `data-tags` and `part="… tag-<name>"`; `tagBehaviour` switches off `selectable` / `focusable` / `draggable` / `searchable` per tag. See [Item tags](./user-item-tags.md).
775
+
768
776
  - **Large lists** — prefer `ixfx-grid-list` with `orientation="column"` over
769
777
  `ixfx-vertical-list`. `vertical-list` renders every child; `grid-list` is
770
778
  windowed.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
- "version": "0.17.1",
4
- "generated": "2026-11-10T11:14:57.413Z",
3
+ "version": "0.18.1",
4
+ "generated": "2026-11-10T23:10:32.663Z",
5
5
  "components": [
6
6
  {
7
7
  "name": "ac-text",
@@ -348,6 +348,10 @@
348
348
  "name": "user-catalog.md",
349
349
  "path": "docs-user/user-catalog.md"
350
350
  },
351
+ {
352
+ "name": "user-item-tags.md",
353
+ "path": "docs-user/user-item-tags.md"
354
+ },
351
355
  {
352
356
  "name": "user-selection-intents.md",
353
357
  "path": "docs-user/user-selection-intents.md"
@@ -83,5 +83,6 @@ import '@ixfx/components/data-grid';
83
83
  - [infra-view-state.md](docs-user/infra-view-state.md)
84
84
  - [list-state.md](docs-user/list-state.md)
85
85
  - [user-catalog.md](docs-user/user-catalog.md)
86
+ - [user-item-tags.md](docs-user/user-item-tags.md)
86
87
  - [user-selection-intents.md](docs-user/user-selection-intents.md)
87
88
  - [user-theming.md](docs-user/user-theming.md)
@@ -178,4 +178,7 @@ el.addEventListener(`multicol-select`, (event) => {
178
178
  });
179
179
  ```
180
180
 
181
+
182
+ **Item tags:** `tags` hook / `tagKeys` → `data-tags` and `part="… tag-<name>"`; `tagBehaviour` switches off `selectable` / `focusable` / `draggable` / `searchable` per tag. See [Item tags](./user-item-tags.md).
183
+
181
184
  See `demo/multicol-list.html` for a full in-memory example with counts.
@@ -67,6 +67,34 @@ NotificationManager.configure({
67
67
 
68
68
  ---
69
69
 
70
+ ## Scoped managers, history and unread
71
+
72
+ `NotificationManager` is the default, app-wide instance. Every instance has its own queue, timers, renderer and options, so toasts can sit beside the component they concern:
73
+
74
+ ```typescript
75
+ import { createNotificationManager, NotificationManager } from '../src/index.js';
76
+
77
+ const lister = NotificationManager.scope('lister-1', { renderer: myAnchoredRenderer }); // get-or-create by name
78
+ // or, unregistered: const lister = createNotificationManager({ renderer: myAnchoredRenderer });
79
+ lister.notify({ type: 'info', message: 'Moved 3 items' });
80
+ NotificationManager.releaseScope('lister-1'); // on unmount: dismiss, detach, forget
81
+ ```
82
+
83
+ Each instance also keeps a bounded history (`historyLimit`, default 100; `0` disables):
84
+
85
+ | API | Description |
86
+ |---|---|
87
+ | `getHistory()` | Snapshot of `{ ...Notification, read, dismissedAt? }`, oldest first; includes toasts no longer visible |
88
+ | `unreadCount` | Entries not yet read — drive a bell indicator |
89
+ | `markRead(id)` / `markAllRead()` | Mark read. Tapping a toast also marks it read |
90
+ | `clearHistory()` | Drop history |
91
+ | `subscribe(listener)` | Called with the history on every change; returns an unsubscribe function |
92
+ | `destroy()` | Dismiss all, drop history/listeners, detach renderer |
93
+
94
+ Scoped instances with no `renderer` fall back to the default top-right pill renderer, which is viewport-anchored — give anchored scopes a custom renderer.
95
+
96
+ ---
97
+
70
98
  ## Queueing model
71
99
 
72
100
  - **`queue: false`** — a message is always shown alone, for the full `timeout`/`timeoutError`. A new `notify()` call immediately replaces whatever is showing.
@@ -0,0 +1,68 @@
1
+ # Item tags
2
+
3
+ Tag list items with names that mean something to your app, then style them and
4
+ change how they react to input. The components never interpret a tag: they only
5
+ expose it and apply the generic interaction flags you declare for it.
6
+
7
+ Works the same on `ixfx-grid-list`, `ixfx-detail-list`, `ixfx-data-grid` and
8
+ `ixfx-multicol-list` (and on `ixfx-vertical-list`, which `ixfx-multicol-list` uses for its columns).
9
+
10
+ ## 1. Assigning tags
11
+
12
+ Two forms, which can be combined (tags are merged, de-duplicated):
13
+
14
+ | Form | Where |
15
+ | --- | --- |
16
+ | Hook returning `readonly string[] \| undefined` | `ixfx-grid-list`: `itemAdapter.tags(item, index)`. `ixfx-detail-list` / `ixfx-data-grid`: `list.tags(item, index)`. `ixfx-multicol-list`: `list.tags(item, columnId)` |
17
+ | Key sets: `tagKeys: ReadonlyMap<tag, ReadonlySet<key>>` | all of them (`ixfx-vertical-list` too). For tags kept apart from the item data, like `partialKeys`. Works for light-DOM / element-mode items |
18
+
19
+ ```ts
20
+ grid.itemAdapter = { key, render, tags: row => row.willBeRemoved ? [`leaving`] : undefined };
21
+ grid.tagKeys = new Map([[`arriving`, new Set([`k1`, `k2`])]]);
22
+ ```
23
+
24
+ Tags are re-read on every render, so `updateItem` / `updateItems` (grid-list) and
25
+ assigning `items` / `rows` pick up changes without rebuilding the adapter. If a hook reads
26
+ state outside the items, call `refreshTags()` (detail-list, data-grid, multicol-list).
27
+ Empty names and names containing whitespace are ignored.
28
+
29
+ ## 2. Styling
30
+
31
+ Each tag is exposed on the item:
32
+
33
+ - `data-tags` (space separated): `[data-tags~="leaving"]`. Always present.
34
+ - a `part` token `tag-<name>` on shadow-DOM items: `::part(item tag-leaving)`.
35
+
36
+ The prefix keeps a caller tag called `selected` from colliding with the built-in state.
37
+
38
+ Which element carries what:
39
+
40
+ | Component | Item element (background, `part="item …"`) | Content |
41
+ | --- | --- | --- |
42
+ | `ixfx-grid-list` | `.cell` — `part="item"` | `part="content"` inside it |
43
+ | `ixfx-data-grid` | `.row` — `part="item"` | the `.cell` children (`part="cell"`-style cells) |
44
+ | `ixfx-detail-list` | the light-DOM `<li>` (`data-tags` only — it is not in a shadow tree, so no `part`) | the `<li>`'s children |
45
+ | `ixfx-multicol-list` / `ixfx-vertical-list` | the light-DOM `<li>` (`data-tags` only) | the `<li>`'s children |
46
+
47
+ ```css
48
+ ixfx-grid-list::part(item tag-leaving) { opacity: 0.5; text-decoration: line-through; }
49
+ ixfx-detail-list li[data-tags~="arriving"] { background: color-mix(in srgb, green 15%, transparent); }
50
+ ```
51
+
52
+ ## 3. Behaviour
53
+
54
+ ```ts
55
+ list.tagBehaviour = {
56
+ leaving: { selectable: false, focusable: false, draggable: false, searchable: false },
57
+ };
58
+ ```
59
+
60
+ - Flags left out keep the default. A tag with no declaration only styles.
61
+ - Several tags: the most restrictive wins (any `false` beats `true`).
62
+ - `selectable: false` — no selection or tickle, no `list-select-intent`; range, marquee and select-all skip the item.
63
+ - `focusable: false` — keyboard cursor movement skips the item (hover can still tickle it).
64
+ - `draggable: false` — no drag starts from the item.
65
+ - `searchable: false` — left out of incremental search.
66
+ - The item is always still rendered and still counts for layout and scroll position.
67
+
68
+ `ixfx-grid-list`'s `disabled` adapter hook is unchanged and combines with these flags.
package/llms.txt CHANGED
@@ -83,5 +83,6 @@ import '@ixfx/components/data-grid';
83
83
  - [infra-view-state.md](docs-user/infra-view-state.md)
84
84
  - [list-state.md](docs-user/list-state.md)
85
85
  - [user-catalog.md](docs-user/user-catalog.md)
86
+ - [user-item-tags.md](docs-user/user-item-tags.md)
86
87
  - [user-selection-intents.md](docs-user/user-selection-intents.md)
87
88
  - [user-theming.md](docs-user/user-theming.md)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
3
  "type": "module",
4
- "version": "0.17.1",
4
+ "version": "0.18.1",
5
5
  "packageManager": "pnpm@10.0.0",
6
6
  "description": "Web components for ixfx — Lit-based UI toolkit",
7
7
  "author": "Clint Heyer",
@@ -268,7 +268,7 @@
268
268
  }
269
269
  },
270
270
  "dependencies": {
271
- "@clinth/ui-commands": "1.1.2",
271
+ "@clinth/ui-commands": "1.2.0",
272
272
  "@clinth/vcanvas": "0.0.6",
273
273
  "@ixfx/arrays": "0.56.21",
274
274
  "@ixfx/collections": "0.56.21",
@@ -290,7 +290,7 @@
290
290
  "eslint-plugin-format": "2.0.1",
291
291
  "globals": "17.14.0",
292
292
  "happy-dom": "^21.0.4",
293
- "knip": "6.44.2",
293
+ "knip": "6.45.0",
294
294
  "libavoid-js": "0.5.0-beta.5",
295
295
  "lit": "3.3.3",
296
296
  "tsdown": "0.23.7",
@@ -1,3 +0,0 @@
1
- import "./list-native-drag-controller-ByftBooJ.js";
2
- import "./tickled-controller-BVhGKzjZ.js";
3
- import "./tickled-styles-pnieYweS.js";