@ixfx/components 0.11.4 → 0.11.6
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 +451 -120
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +2267 -540
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +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/{button-CTL45aBl.d.ts → button-BYuf72aR.d.ts} +2 -2
- package/dist/{button-CTL45aBl.d.ts.map → button-BYuf72aR.d.ts.map} +1 -1
- package/dist/button.d.ts +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/crumbs.d.ts +3 -3
- package/dist/crumbs.js +1 -1
- package/dist/{data-grid-CfiaBqTA.d.ts → data-grid-C6EjCe5O.d.ts} +48 -6
- package/dist/data-grid-C6EjCe5O.d.ts.map +1 -0
- package/dist/data-grid.d.ts +3 -3
- package/dist/data-grid.js +67 -3
- package/dist/data-grid.js.map +1 -1
- package/dist/{detail-list-DxQZkK-C.d.ts → detail-list-CmdCxddo.d.ts} +22 -5
- package/dist/detail-list-CmdCxddo.d.ts.map +1 -0
- package/dist/detail-list.d.ts +3 -3
- package/dist/detail-list.js +67 -4
- package/dist/detail-list.js.map +1 -1
- package/dist/{grid-list-k89JpiNy.js → grid-list-3fGhdaFA.js} +92 -7
- package/dist/grid-list-3fGhdaFA.js.map +1 -0
- package/dist/{grid-list-ChgYpUUq.d.ts → grid-list-D6AfWfwn.d.ts} +27 -4
- package/dist/grid-list-D6AfWfwn.d.ts.map +1 -0
- package/dist/grid-list.d.ts +2 -2
- package/dist/grid-list.js +1 -1
- package/dist/{grouped-item-lister-Bhyo-dkH.d.ts → grouped-item-lister-DETte0Dh.d.ts} +2 -2
- package/dist/{grouped-item-lister-Bhyo-dkH.d.ts.map → grouped-item-lister-DETte0Dh.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.d.ts +1 -1
- package/dist/{index-CHbuPyLL.d.ts → index-CMsmZ6Or.d.ts} +4 -4
- package/dist/{index-CHbuPyLL.d.ts.map → index-CMsmZ6Or.d.ts.map} +1 -1
- package/dist/{index-garxxqgV.d.ts → index-CYndvTWH.d.ts} +2 -2
- package/dist/{index-garxxqgV.d.ts.map → index-CYndvTWH.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-CDllxjVG.d.ts → index-DyTSt9OK.d.ts} +4 -4
- package/dist/{index-CDllxjVG.d.ts.map → index-DyTSt9OK.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 +337 -140
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2038 -646
- package/dist/index.js.map +1 -1
- package/dist/item-appearance-BjcMyauw.js +31 -0
- package/dist/item-appearance-BjcMyauw.js.map +1 -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-native-drag-controller-B9reY4uM.d.ts → list-native-drag-controller-CllsHLxw.d.ts} +2 -2
- package/dist/{list-native-drag-controller-B9reY4uM.d.ts.map → list-native-drag-controller-CllsHLxw.d.ts.map} +1 -1
- package/dist/{menu-BHT6HRND.js → menu-CsBUyUuS.js} +2 -2
- package/dist/{menu-BHT6HRND.js.map → menu-CsBUyUuS.js.map} +1 -1
- package/dist/{menu-item-DlxAb0Xr.d.ts → menu-item-BbgdcwBX.d.ts} +11 -2
- package/dist/menu-item-BbgdcwBX.d.ts.map +1 -0
- package/dist/{menu-item-JcpHCyF0.js → menu-item-CfndBGO8.js} +38 -3
- package/dist/menu-item-CfndBGO8.js.map +1 -0
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -2
- package/dist/miller.d.ts +3 -3
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +18 -2
- package/dist/miller.js.map +1 -1
- package/dist/panel.d.ts +1 -1
- 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-v8mKX7Fu.d.ts → tab-list-pqfKaVAE.d.ts} +2 -2
- package/dist/{tab-list-v8mKX7Fu.d.ts.map → tab-list-pqfKaVAE.d.ts.map} +1 -1
- package/dist/tabs.d.ts +1 -1
- package/dist/{titlebar-B5zSTZnF.d.ts → titlebar-Tqu-VvMU.d.ts} +2 -2
- package/dist/{titlebar-B5zSTZnF.d.ts.map → titlebar-Tqu-VvMU.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/{tree-component-CMGeqyjZ.d.ts → tree-component-DukLqesg.d.ts} +2 -2
- package/dist/{tree-component-CMGeqyjZ.d.ts.map → tree-component-DukLqesg.d.ts.map} +1 -1
- package/dist/tree.d.ts +4 -4
- package/dist/{types-3Jfcaxvo.d.ts → types-D-kYF16b.d.ts} +21 -1
- package/dist/types-D-kYF16b.d.ts.map +1 -0
- package/dist/{vertical-list-R25WqAVO.d.ts → vertical-list-DTp-UIUE.d.ts} +26 -3
- package/dist/vertical-list-DTp-UIUE.d.ts.map +1 -0
- package/dist/vertical-list.d.ts +2 -2
- package/dist/vertical-list.js +53 -4
- package/dist/vertical-list.js.map +1 -1
- package/docs-user/data-grid.md +51 -1
- package/docs-user/detail-list.md +46 -0
- package/docs-user/grid-list.md +49 -2
- package/docs-user/hyperbolic-tree.md +98 -18
- package/docs-user/index.json +2 -2
- package/docs-user/menu.md +30 -9
- package/docs-user/miller.md +52 -7
- package/docs-user/vertical-list.md +63 -0
- package/package.json +1 -1
- package/dist/data-grid-CfiaBqTA.d.ts.map +0 -1
- package/dist/detail-list-DxQZkK-C.d.ts.map +0 -1
- package/dist/grid-list-ChgYpUUq.d.ts.map +0 -1
- package/dist/grid-list-k89JpiNy.js.map +0 -1
- package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
- package/dist/menu-item-DlxAb0Xr.d.ts.map +0 -1
- package/dist/menu-item-JcpHCyF0.js.map +0 -1
- package/dist/types-3Jfcaxvo.d.ts.map +0 -1
- package/dist/vertical-list-R25WqAVO.d.ts.map +0 -1
package/docs-user/detail-list.md
CHANGED
|
@@ -155,6 +155,9 @@ list.keyProperty = 'name'; // Preserves selection across rebuilds
|
|
|
155
155
|
| `displayProperty` | `string` | Property name to use as label |
|
|
156
156
|
| `keyProperty` | `string` | Property name for stable identity |
|
|
157
157
|
| `iconProperty` | `string` | Property name for icon name |
|
|
158
|
+
| `iconColorProperty` | `string` | Property name for the icon's CSS colour |
|
|
159
|
+
| `textColorProperty` | `string` | Property name for the caption's CSS colour |
|
|
160
|
+
| `badgeProperty` | `string` | Property name for a Finder-style badge |
|
|
158
161
|
| `formatter` | `(item: unknown, index: number) => string \| Node` | Custom renderer |
|
|
159
162
|
|
|
160
163
|
```typescript
|
|
@@ -170,6 +173,49 @@ Retrieve the original data for an element:
|
|
|
170
173
|
const data = list.getItemData(liElement);
|
|
171
174
|
```
|
|
172
175
|
|
|
176
|
+
### Per-item icon colour, text colour and badges
|
|
177
|
+
|
|
178
|
+
Three more property-name lookups, in the same idiom as `iconProperty`: each
|
|
179
|
+
names the property on the item object that carries the value.
|
|
180
|
+
|
|
181
|
+
| Property | Applies to | Value |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `icon-color-property` | the injected `<ixfx-icon>` | a CSS colour string |
|
|
184
|
+
| `text-color-property` | the caption | a CSS colour string |
|
|
185
|
+
| `badge-property` | a right-justified slot after the caption | anything Lit can render, or a DOM `Node` |
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
list.displayProperty = `name`;
|
|
189
|
+
list.iconProperty = `icon`;
|
|
190
|
+
list.iconColorProperty = `iconColor`;
|
|
191
|
+
list.textColorProperty = `textColor`;
|
|
192
|
+
list.badgeProperty = `badge`;
|
|
193
|
+
list.items = [
|
|
194
|
+
{ name: `Report.pdf`, icon: `file`, badge: tagChip(`orange`) },
|
|
195
|
+
{ name: `Overdue.txt`, textColor: `crimson` },
|
|
196
|
+
];
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Icons paint from `currentColor`, so `iconColor` recolours the glyph. Both
|
|
200
|
+
colours are applied inline, which means they also win over the selected /
|
|
201
|
+
tickled text colours — pick something legible against both, or leave them off
|
|
202
|
+
and let the component's theming handle selection contrast.
|
|
203
|
+
|
|
204
|
+
`undefined`, `null`, `''` and `false` all count as "not supplied", so a badge
|
|
205
|
+
can be made conditional without rebuilding the collection:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
list.badgeProperty = `badge`; // rows without a tag simply have no badge
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Changing any of these properties (or `items`, `formatter`, `displayProperty`,
|
|
212
|
+
`iconProperty`, `keyProperty`) rebuilds the rows.
|
|
213
|
+
|
|
214
|
+
The badge lands as a `<span class="item-badge">` in the row's light DOM, with
|
|
215
|
+
its layout applied as inline styles — a `::slotted()` rule can't reach inside a
|
|
216
|
+
slotted `<li>`. Drive it from `--detail-list-badge-gap` (or override with
|
|
217
|
+
`!important`). The icon's own gap is `--detail-list-icon-gap`.
|
|
218
|
+
|
|
173
219
|
---
|
|
174
220
|
|
|
175
221
|
## Properties
|
package/docs-user/grid-list.md
CHANGED
|
@@ -340,6 +340,10 @@ grid.itemAdapter = {
|
|
|
340
340
|
render: f => html`<img src=${f.thumb} loading="lazy" decoding="async">`,
|
|
341
341
|
disabled: f => f.locked, // optional — not selectable / tickle-able
|
|
342
342
|
searchableText: f => `${f.name} ${f.ext}`, // optional — search haystack
|
|
343
|
+
icon: f => fileIcon(f.ext), // optional — above the cell content
|
|
344
|
+
iconColor: f => f.tint, // optional — CSS colour for that icon
|
|
345
|
+
textColor: f => f.textTint, // optional — CSS colour for the caption
|
|
346
|
+
badge: f => f.tag && tagChip(f.tag), // optional — inline, before the name
|
|
343
347
|
};
|
|
344
348
|
grid.items = files; // readonly FileRecord[]
|
|
345
349
|
```
|
|
@@ -353,6 +357,45 @@ don't rebuild it each host render. Assigning a new `itemAdapter` reference makes
|
|
|
353
357
|
the grid reconstruct its data source, which is wasteful for a streaming
|
|
354
358
|
collection.
|
|
355
359
|
|
|
360
|
+
#### Per-item icon, colours and badges
|
|
361
|
+
|
|
362
|
+
The four optional appearance functions are the Finder-style per-item hooks:
|
|
363
|
+
|
|
364
|
+
| Function | Renders |
|
|
365
|
+
|---|---|
|
|
366
|
+
| `icon(item, index)` | Inside a sized, centred slot **above** the cell's content. Anything Lit can render. |
|
|
367
|
+
| `iconColor(item, index)` | `color` on that slot. Glyphs painting from `currentColor` are recoloured. |
|
|
368
|
+
| `textColor(item, index)` | `color` on the cell's caption. |
|
|
369
|
+
| `badge(item, index)` | A Finder-style badge, **inline at the head of the caption**, before the filename. |
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { html } from 'lit';
|
|
373
|
+
import { tagChip, stackedTagChips } from './my-tags.js';
|
|
374
|
+
|
|
375
|
+
grid.itemAdapter = {
|
|
376
|
+
key: f => f.path,
|
|
377
|
+
label: f => f.name,
|
|
378
|
+
render: f => html`<img src=${f.thumb} loading="lazy">`,
|
|
379
|
+
icon: f => html`<ixfx-icon name="file" style="width:100%;height:100%"></ixfx-icon>`,
|
|
380
|
+
iconColor: f => f.tint,
|
|
381
|
+
textColor: f => (f.overdue ? 'crimson' : undefined),
|
|
382
|
+
badge: f => (f.tags.length > 1 ? stackedTagChips(f.tags) : tagChip(f.tags[0])),
|
|
383
|
+
};
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
`undefined`, `null`, `''` and `false` all count as "not supplied", so a hook
|
|
387
|
+
can be made conditional without touching the collection. Both colours are
|
|
388
|
+
applied inline, which means they also win over the selected / tickled caption
|
|
389
|
+
colours — pick something legible against both, or leave them off and let the
|
|
390
|
+
component's theming handle selection contrast.
|
|
391
|
+
|
|
392
|
+
Element mode needs none of this: you own the light-DOM markup, so set the
|
|
393
|
+
colours yourself and put the badge markup wherever you want it.
|
|
394
|
+
|
|
395
|
+
CSS: `--grid-list-icon-size`, `--grid-list-icon-gap`, `--grid-list-badge-gap`.
|
|
396
|
+
|
|
397
|
+
Parts: `part="icon"` and `part="badge"` on the wrappers this adds.
|
|
398
|
+
|
|
356
399
|
| Method | Effect |
|
|
357
400
|
|---|---|
|
|
358
401
|
| `setItems(items)` | Replace the collection. Selection / cursor keep any key still present. |
|
|
@@ -425,11 +468,15 @@ it's suppressed under `prefers-reduced-motion: reduce`. Duration:
|
|
|
425
468
|
| `content` | The rendered content wrapper (data mode) |
|
|
426
469
|
| `thumb` | The square holding the slotted content (element mode) |
|
|
427
470
|
| `caption` | The caption element (absent for `caption-style="hidden"`) |
|
|
471
|
+
| `icon` | The per-item icon wrapper (data mode, when the adapter's `icon` returns something) |
|
|
472
|
+
| `badge` | The per-item badge wrapper (data mode, when the adapter's `badge` returns something) |
|
|
428
473
|
|
|
429
474
|
Host CSS custom properties: `--grid-list-item-bg`, `--grid-list-radius`,
|
|
430
475
|
`--grid-list-gap`, `--grid-list-item-move-duration` (insertion animation,
|
|
431
|
-
default `200ms`), `--scroll-fade-width` (edge fade reach, default `30px`),
|
|
432
|
-
|
|
476
|
+
default `200ms`), `--scroll-fade-width` (edge fade reach, default `30px`),
|
|
477
|
+
`--grid-list-icon-size` / `--grid-list-icon-gap` / `--grid-list-badge-gap`
|
|
478
|
+
(per-item appearance, data mode), plus the shared `--item-bg-*` / `--accent`
|
|
479
|
+
theme tokens.
|
|
433
480
|
|
|
434
481
|
### Thumbnail well (Finder-style selection)
|
|
435
482
|
|
|
@@ -11,15 +11,16 @@ It implements the shared `TreeComponent` interface (see [`src/tree/README.md`](.
|
|
|
11
11
|
1. [Differences from `ixfx-tree-list`](#differences-from-ixfx-tree-list)
|
|
12
12
|
2. [Data model](#data-model)
|
|
13
13
|
3. [Properties](#properties)
|
|
14
|
-
4. [
|
|
15
|
-
5. [
|
|
16
|
-
6. [
|
|
17
|
-
7. [
|
|
18
|
-
8. [
|
|
19
|
-
9. [
|
|
20
|
-
10. [
|
|
21
|
-
11. [
|
|
22
|
-
12. [
|
|
14
|
+
4. [Node shapes](#node-shapes)
|
|
15
|
+
5. [Zoom vs. curvature](#zoom-vs-curvature)
|
|
16
|
+
6. [Weighting](#weighting)
|
|
17
|
+
7. [Targeting a specific node or edge](#targeting-a-specific-node-or-edge)
|
|
18
|
+
8. [Custom edge rendering](#custom-edge-rendering)
|
|
19
|
+
9. [Focus, selection, navigation](#focus-selection-navigation)
|
|
20
|
+
10. [Events](#events)
|
|
21
|
+
11. [Keyboard / pointer interaction](#keyboard--pointer-interaction)
|
|
22
|
+
12. [CSS variables and parts](#css-variables-and-parts)
|
|
23
|
+
13. [Types reference](#types-reference)
|
|
23
24
|
|
|
24
25
|
---
|
|
25
26
|
|
|
@@ -36,6 +37,8 @@ It implements the shared `TreeComponent` interface (see [`src/tree/README.md`](.
|
|
|
36
37
|
|
|
37
38
|
Same `TreeNode` / `TreeItem` shapes as the rest of the tree family (see [`src/tree/README.md`](../tree/README.md#data-model)), including `root`, `model` (`TreeDataModel`), and `loadChildren` for lazy loading.
|
|
38
39
|
|
|
40
|
+
Keys only need to be unique **among siblings**: internally each node is identified by its key *path* from the root (`HyperbolicLayoutNode.id`), so data like a file system — where `readme.md` recurs in many folders — lays out and focuses correctly. Key-based lookups that can't know the path (`focusedKey` when given a bare key, `revealKey`, `::part(node-<key>)`) match the first node, depth-first, carrying that key.
|
|
41
|
+
|
|
39
42
|
```typescript
|
|
40
43
|
el.root = {
|
|
41
44
|
item: { key: 'root', label: 'My Files' },
|
|
@@ -58,12 +61,20 @@ el.root = {
|
|
|
58
61
|
| `exclusivity` | `TreeExclusivity` | `'none'` | Accepted for interface compatibility, ignored |
|
|
59
62
|
| `filterPredicate` | `TreeFilterPredicate \| undefined` | `undefined` | Non-matching nodes (and branches with no matching descendant) are dimmed, not hidden |
|
|
60
63
|
| `maxRadius` (`max-radius`) | `number` | `4` | Tree-graph steps from the focus to lay out and render |
|
|
61
|
-
| `
|
|
64
|
+
| `nodeShape` (`node-shape`) | `'dot' \| 'box'` | `'dot'` | How nodes are drawn. See [Node shapes](#node-shapes) |
|
|
65
|
+
| `boxMaxChars` (`box-max-chars`) | `number` | `24` | `box` mode: truncate longer labels with `…` (`0` disables) |
|
|
66
|
+
| `minLabelSize` (`min-label-size`) | `number` | `9` | `box` mode: smallest on-screen label size (CSS px) worth drawing; smaller labels become markers |
|
|
67
|
+
| `colorByBranch` (`color-by-branch`) | `boolean` | `false` | Tint each top-level branch (each child of the root, and its subtree) its own hue. See [Branch colours](#branch-colours) |
|
|
68
|
+
| `nodeRadius` (`node-radius`) | `number` | `0.05` | Base node dot radius at the disk center, as a fraction of the disk radius. Shrinks by the disk's conformal factor `1 − \|z\|²` away from the focus, and is capped to stay clear of the nearest neighbouring node |
|
|
62
69
|
| `minNodeRadius` (`min-node-radius`) | `number` | `0.015` | Nodes whose scaled radius falls below this render without a label |
|
|
63
70
|
| `minWeightScale` (`min-weight-scale`) | `number` | `0.6` | Radius multiplier for a node with `weight` at the low end of the currently-visible range |
|
|
64
71
|
| `maxWeightScale` (`max-weight-scale`) | `number` | `1.6` | Radius multiplier for a node with `weight` at the high end of the currently-visible range |
|
|
65
|
-
| `zoom` | `number` | `1` | Post-layout
|
|
72
|
+
| `zoom` | `number` | `1` | Post-layout (Euclidean) magnification; updated by zoom gestures. See [Zoom vs. curvature](#zoom-vs-curvature) |
|
|
66
73
|
| `curvature` | `number` | `1` | Hyperbolic distance placed between generations — how curved the space itself is. See [Zoom vs. curvature](#zoom-vs-curvature) |
|
|
74
|
+
| `disableZoomGestures` (`disable-zoom-gestures`) | `boolean` | `false` | Turn off zoom gestures — see [Zoom gestures](#zoom-gestures) |
|
|
75
|
+
| `disableRadialLabels` (`disable-radial-labels`) | `boolean` | `false` | Turn off radial labels — every label horizontal. See [Label legibility](#label-legibility) |
|
|
76
|
+
| `disableChildPreview` (`disable-child-preview`) | `boolean` | `false` | Turn off the hover preview of a crowded node's children — see [Child preview](#child-preview) |
|
|
77
|
+
| `siblingSpacing` (`sibling-spacing`) | `number` | `0.5` | Minimum hyperbolic distance between adjacent siblings — see [Crowded fans](#crowded-fans). `0` disables |
|
|
67
78
|
| `focusAnimationDuration` (`focus-animation-duration`) | `number` | `400` | Duration (ms) of the animated re-center on focus change; `0` snaps instantly. Respects `prefers-reduced-motion` |
|
|
68
79
|
| `edgeRenderer` | `HyperbolicEdgeRenderer \| undefined` | `undefined` | Custom renderer for edges, in place of the default geodesic-arc path |
|
|
69
80
|
| `disableKeyboardNavigation` (`disable-keyboard-navigation`) | `boolean` | `false` | Disables the keyboard handlers below |
|
|
@@ -74,6 +85,60 @@ el.root = {
|
|
|
74
85
|
|
|
75
86
|
---
|
|
76
87
|
|
|
88
|
+
## Node shapes
|
|
89
|
+
|
|
90
|
+
| `nodeShape` | Rendering |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `'dot'` (default) | A filled circle with the label beside it. Labels are greedily thinned where nodes crowd together |
|
|
93
|
+
| `'box'` | A rectangle containing the label, centered on the node. The box scales with the disk's conformal factor (`1 − \|z\|²`), floored at 45% so nearby rings stay readable |
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<ixfx-hyperbolictree-list node-shape="box"></ixfx-hyperbolictree-list>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Label legibility
|
|
100
|
+
|
|
101
|
+
Both shapes place labels greedily: the focus first, then selected nodes, then larger (nearer-the-center) nodes. A label is dropped if it would overlap an already-placed one by more than 3% of its area, or — in `box` mode — if it would render below `minLabelSize` px. A box without a label is drawn as a small marker. Hovering (or keyboard-tickling) any node always shows its label, drawn on top, and every node has its full label as a native tooltip.
|
|
102
|
+
|
|
103
|
+
`--hyperbolictree-font-size` is in **screen px**: the component converts it using its own rendered size, so text is the same size however large the element is. It also stays constant under `zoom`, so zooming in spreads crowded labels apart until they fit, rather than magnifying the overlap.
|
|
104
|
+
|
|
105
|
+
**Radial labels** (on by default; `disable-radial-labels` turns them off): each label runs along its node's incoming edge, from the neighbour one step nearer the focus. A fan of siblings then only needs room for each label's *height*, not its width, so far more of a crowd stays labelled. Labels on the left half are turned 180° so text never reads upside-down. The focus itself stays horizontal.
|
|
106
|
+
|
|
107
|
+
### Zoom gestures
|
|
108
|
+
|
|
109
|
+
On by default; `disable-zoom-gestures` turns them all off. Each one zooms around the pointer, like a map, and updates `zoom`:
|
|
110
|
+
|
|
111
|
+
| Gesture | When |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Trackpad pinch / Ctrl-⌘-scroll | Whenever the pointer is over the tree |
|
|
114
|
+
| Plain scroll | Only once the tree has keyboard focus (click it first), so scrolling the page past it isn't hijacked. This follows the library's focus-gated wheel convention |
|
|
115
|
+
| Two-finger touch pinch | On empty disk space |
|
|
116
|
+
|
|
117
|
+
Labels keep their on-screen size while zooming, so zooming in spreads a crowd apart. Boxes that were shrunk towards the edge grow back towards full size, until their labels are legible. Focusing a node pans a zoomed view back so the new focus lands in the middle of the element.
|
|
118
|
+
|
|
119
|
+
### Child preview
|
|
120
|
+
|
|
121
|
+
On by default; `disable-child-preview` turns it off. Hovering or keyboard-tickling a node whose children aren't all legible opens a popover listing them. That means some children had their labels culled, or sit beyond `maxRadius`. It shows up to 12 children, then "+N more". Clicking an entry focuses that child and selects it, per `interactionMode`. The popover stays open while the pointer moves onto it, and Escape closes it. Style it with `::part(child-preview)`. Nodes that can show a preview drop their native `<title>` tooltip so the two don't stack. With the preview disabled, every node keeps its tooltip.
|
|
122
|
+
|
|
123
|
+
### Crowded fans
|
|
124
|
+
|
|
125
|
+
Panning is a hyperbolic *isometry*: it moves nodes to where the disk magnifies more, but it can never change the hyperbolic distance between them. So if a bushy node's children were laid out nearly on top of each other, no amount of dragging would separate them.
|
|
126
|
+
|
|
127
|
+
`siblingSpacing` guarantees a minimum hyperbolic distance between adjacent siblings. A child with a thin angular slice is placed further from its parent: `sinh(L) = sinh(spacing/2) / sin(slice/2)`, never less than `curvature`. In the overview, a crowd sits further out, as a neat fan of markers rather than a pile. Dragging it towards the center always spreads it out until the labels fit. Raise `siblingSpacing` if your labels are long and still collide when centered. Lower it to keep crowds closer in the overview.
|
|
128
|
+
|
|
129
|
+
### Branch colours
|
|
130
|
+
|
|
131
|
+
`color-by-branch` spreads hues evenly around the colour wheel, one per child of the root, and mixes each into the normal node, box and edge colours. Mixing rather than replacing keeps it in step with the theme, and selected/tickled states still override it. Each node and edge carries `--branch-index` and `--branch-count` (unset on the root) for custom CSS, and these knobs tune the palette:
|
|
132
|
+
|
|
133
|
+
| Variable | Default |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `--hyperbolictree-branch-hue-start` | `250` |
|
|
136
|
+
| `--hyperbolictree-branch-chroma` | `0.13` |
|
|
137
|
+
| `--hyperbolictree-branch-lightness` | `62%` |
|
|
138
|
+
| `--hyperbolictree-branch-mix` | `55%` |
|
|
139
|
+
|
|
140
|
+
Style boxes via `--hyperbolictree-box-color` / `--hyperbolictree-box-text` / `--hyperbolictree-box-border`, or `::part(box)` directly.
|
|
141
|
+
|
|
77
142
|
## Zoom vs. curvature
|
|
78
143
|
|
|
79
144
|
Two independent knobs affect how much of the tree is visible and how it's magnified — neither mutates `root`:
|
|
@@ -81,7 +146,7 @@ Two independent knobs affect how much of the tree is visible and how it's magnif
|
|
|
81
146
|
| | What it changes | Effect |
|
|
82
147
|
|---|---|---|
|
|
83
148
|
| `zoom` | A post-layout SVG `scale()`, applied after everything else | Uniformly magnifies/shrinks the rendered disk around the focus. Node positions relative to each other are unchanged — it's a camera zoom, not a re-layout. |
|
|
84
|
-
| `curvature` | The hyperbolic distance placed between each generation (default `1`, matching the standard Poincaré-disk layout) | Raising it pushes each generation further out in hyperbolic terms, so the disk's own `tanh` compression crowds distant generations toward the boundary faster — a stronger fisheye. This *reshapes* the layout (relative sizes/spacing of near vs. far nodes change), which is why increasing it reads as "zooming in" on the focus even at `zoom: 1`. Lowering it spreads generations out more evenly, flattening the view toward a Euclidean-feeling layout. |
|
|
149
|
+
| `curvature` | The minimum hyperbolic distance placed between each generation (default `1`, matching the standard Poincaré-disk layout; bushy nodes' children go further — see `siblingSpacing`) | Raising it pushes each generation further out in hyperbolic terms, so the disk's own `tanh` compression crowds distant generations toward the boundary faster — a stronger fisheye. This *reshapes* the layout (relative sizes/spacing of near vs. far nodes change), which is why increasing it reads as "zooming in" on the focus even at `zoom: 1`. Lowering it spreads generations out more evenly, flattening the view toward a Euclidean-feeling layout. |
|
|
85
150
|
| `maxRadius` | How many tree-graph rings are laid out at all | Independent of both — a window over the tree, not a projection change. |
|
|
86
151
|
|
|
87
152
|
```html
|
|
@@ -204,7 +269,7 @@ All events **bubble** and are **composed**.
|
|
|
204
269
|
|
|
205
270
|
## Keyboard / pointer interaction
|
|
206
271
|
|
|
207
|
-
The element must be focused before keyboard navigation works (`disableKeyboardNavigation` turns it off entirely).
|
|
272
|
+
The element must be focused before keyboard navigation works (`disableKeyboardNavigation` turns it off entirely). Any pointer interaction — pressing a node, or starting a pan — moves keyboard focus to the tree, so you can follow a click or drag straight away with the arrow keys.
|
|
208
273
|
|
|
209
274
|
| Key | Action |
|
|
210
275
|
|---|---|
|
|
@@ -214,7 +279,11 @@ The element must be focused before keyboard navigation works (`disableKeyboardNa
|
|
|
214
279
|
| `Enter` | Select (unless `interactionMode="manual"`) and activate the focused node |
|
|
215
280
|
| `Escape` | Return focus to the root |
|
|
216
281
|
|
|
217
|
-
Pointer: click a node to focus (and select, per `interactionMode`) it; drag empty disk space to pan.
|
|
282
|
+
Pointer: click a node to focus (and select, per `interactionMode`) it; drag empty disk space to pan. Panning is a true hyperbolic translation — the grabbed point tracks the pointer and the tree never distorts. Focusing a node animates it to the center along the geodesic, keeping the current orientation (no spin).
|
|
283
|
+
|
|
284
|
+
Any pointer interaction also moves keyboard focus to the tree — see [Keyboard / pointer interaction](#keyboard--pointer-interaction). Ctrl/⌘-scroll or pinch zooms; see [Zoom gestures](#zoom-gestures).
|
|
285
|
+
|
|
286
|
+
Positions are always computed outward from the focus, one parent→child hop at a time, never from root-anchored coordinates. Root-anchored coordinates run out of floating-point precision about 14 hyperbolic units from the root (depth 5 at `curvature` 3), where whole subtrees would collapse onto one point. Focus-relative positions stay exact however deep you browse.
|
|
218
287
|
|
|
219
288
|
## CSS variables and parts
|
|
220
289
|
|
|
@@ -224,7 +293,10 @@ Pointer: click a node to focus (and select, per `interactionMode`) it; drag empt
|
|
|
224
293
|
| `--hyperbolictree-node-text` | `var(--surface-3-text)` | Label text colour |
|
|
225
294
|
| `--hyperbolictree-edge-color` | `var(--surface-6)` | Edge stroke colour |
|
|
226
295
|
| `--hyperbolictree-boundary-color` | `var(--border-subtle)` | Disk boundary stroke colour |
|
|
227
|
-
| `--hyperbolictree-font-size` | `
|
|
296
|
+
| `--hyperbolictree-font-size` | `13px` | Label font size in screen px (in `box` mode, the size at the focus) |
|
|
297
|
+
| `--hyperbolictree-box-color` | `var(--hyperbolictree-node-color)` | `box` mode fill |
|
|
298
|
+
| `--hyperbolictree-box-text` | `var(--surface-4-text)` | `box` mode label colour. Selected/tickled boxes use `--item-text-selected` / `--item-text-tickled`, paired with their `--item-bg-*` fills |
|
|
299
|
+
| `--hyperbolictree-box-border` | `var(--surface-2)` | `box` mode border |
|
|
228
300
|
| `--node-weight` / `--node-weight-raw` | — | See [Weighting](#weighting) |
|
|
229
301
|
| `--edge-weight` | — | See [Weighting](#weighting) |
|
|
230
302
|
|
|
@@ -234,9 +306,11 @@ Pointer: click a node to focus (and select, per `interactionMode`) it; drag empt
|
|
|
234
306
|
| `edges` / `nodes` | Group wrappers | |
|
|
235
307
|
| `edge`, `edge-to-<key>`, `edge-from-<key>` | Each edge `<path>` | See [Targeting a specific node or edge](#targeting-a-specific-node-or-edge) |
|
|
236
308
|
| `node`, `node-<key>` | Each node `<g>` | |
|
|
237
|
-
| `hit` | Invisible larger hit-target circle per node | |
|
|
238
|
-
| `dot` | The visible node circle | |
|
|
309
|
+
| `hit` | Invisible larger hit-target circle per node | `dot` mode only |
|
|
310
|
+
| `dot` | The visible node circle | `dot` mode only |
|
|
311
|
+
| `box` | The node rectangle | `box` mode only |
|
|
239
312
|
| `label` | Node label `<text>` | |
|
|
313
|
+
| `child-preview` | The hover popover listing a crowded node's children | See [Child preview](#child-preview) |
|
|
240
314
|
|
|
241
315
|
---
|
|
242
316
|
|
|
@@ -245,6 +319,8 @@ Pointer: click a node to focus (and select, per `interactionMode`) it; drag empt
|
|
|
245
319
|
```typescript
|
|
246
320
|
type HyperbolicInteractionMode = 'implicit' | 'standard' | 'manual';
|
|
247
321
|
|
|
322
|
+
type HyperbolicNodeShape = 'dot' | 'box';
|
|
323
|
+
|
|
248
324
|
type HyperbolicFocusDetail = {
|
|
249
325
|
readonly node: TreeNode;
|
|
250
326
|
readonly previous: TreeNode | undefined;
|
|
@@ -260,10 +336,12 @@ type HyperbolicEdgeRenderer = (context: HyperbolicEdgeRenderContext) => unknown;
|
|
|
260
336
|
|
|
261
337
|
type HyperbolicLayoutNode = {
|
|
262
338
|
readonly node: TreeNode;
|
|
263
|
-
readonly key: string;
|
|
339
|
+
readonly key: string; // node.item.key — may repeat across branches
|
|
340
|
+
readonly id: string; // key-path id, unique across the tree
|
|
264
341
|
readonly depth: number; // absolute depth from the true root
|
|
265
342
|
readonly ring: number; // tree-graph steps from the focus (0 = focus itself)
|
|
266
343
|
readonly parentKey: string | undefined;
|
|
344
|
+
readonly parentId: string | undefined;
|
|
267
345
|
readonly position: Point; // Poincaré-disk position, focus projected to the origin
|
|
268
346
|
readonly angularShare: number; // angular width (radians) allocated by the parent's partition
|
|
269
347
|
readonly weight: number | undefined;
|
|
@@ -273,6 +351,8 @@ type HyperbolicLayoutNode = {
|
|
|
273
351
|
type HyperbolicLayoutEdge = {
|
|
274
352
|
readonly fromKey: string;
|
|
275
353
|
readonly toKey: string;
|
|
354
|
+
readonly fromId: string;
|
|
355
|
+
readonly toId: string;
|
|
276
356
|
readonly from: Point;
|
|
277
357
|
readonly to: Point;
|
|
278
358
|
readonly weightNormalized: number; // average of the two endpoints'
|
package/docs-user/index.json
CHANGED
package/docs-user/menu.md
CHANGED
|
@@ -176,18 +176,37 @@ Use `ixfx-menu-sub-trigger` with a nested `ixfx-menu-container` in its `submenu`
|
|
|
176
176
|
|
|
177
177
|
### Context Menu Mode
|
|
178
178
|
|
|
179
|
-
Set `mode="context"` on the trigger. The menu
|
|
179
|
+
Set `mode="context"` on the trigger. The menu opens at the cursor position when the user right-clicks. Put the surface that should respond to right-clicks (a list, canvas or whole panel) in the `context-target` slot. It replaces the `trigger` slot for this mode:
|
|
180
180
|
|
|
181
181
|
```html
|
|
182
|
-
<
|
|
183
|
-
<ixfx-menu-
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
182
|
+
<div class="panel"> <!-- e.g. display: flex; flex-direction: column; height: 300px -->
|
|
183
|
+
<ixfx-menu-trigger mode="context" @menu-command=${handleContextMenu}>
|
|
184
|
+
<ul slot="context-target" class="file-list"> <!-- e.g. overflow: auto -->
|
|
185
|
+
<li>…</li>
|
|
186
|
+
</ul>
|
|
187
|
+
<ixfx-menu-container slot="menu">
|
|
188
|
+
<ixfx-menu-item command="cut" label="Cut"></ixfx-menu-item>
|
|
189
|
+
<ixfx-menu-item command="copy" label="Copy"></ixfx-menu-item>
|
|
190
|
+
<ixfx-menu-item command="paste" label="Paste"></ixfx-menu-item>
|
|
191
|
+
</ixfx-menu-container>
|
|
192
|
+
</ixfx-menu-trigger>
|
|
193
|
+
</div>
|
|
189
194
|
```
|
|
190
195
|
|
|
196
|
+
How it behaves:
|
|
197
|
+
- **No extra button.** When a `context-target` is slotted, the default trigger button isn't rendered. A left click goes to your surface as normal and doesn't open the menu. If you slot only `menu`, a default button is still shown.
|
|
198
|
+
- **Layout.** When a `context-target` is slotted, the trigger's host and its inner wrapper both use `display: contents`. That makes the slotted surface the item in the parent's flex or grid layout, as if the trigger weren't there. In a height-constrained flex column, a surface with `overflow: auto` is clipped and scrolls on its own. You don't need extra CSS for this.
|
|
199
|
+
- **Focus.** Escape or Tab closes the menu and moves focus back to the element that had it when the menu opened, such as a row inside the surface.
|
|
200
|
+
- **Events.** `menu-trigger-open` and `menu-trigger-close` fire for context opens too.
|
|
201
|
+
|
|
202
|
+
To keep a real box instead (for example, a visible trigger mixed with a context target), use these properties:
|
|
203
|
+
|
|
204
|
+
| Variable | Default | Description |
|
|
205
|
+
|----------|---------|-------------|
|
|
206
|
+
| `--menu-trigger-display` | `contents` | `display` of the host when a `context-target` is slotted |
|
|
207
|
+
| `--menu-trigger-area-display` | `contents` | `display` of the inner trigger wrapper in context mode |
|
|
208
|
+
| `--menu-trigger-area-flex` | `initial` | `flex` of the inner trigger wrapper in context mode |
|
|
209
|
+
|
|
191
210
|
### Command Registry Integration
|
|
192
211
|
|
|
193
212
|
Pass a `CommandRegistry` to the trigger and/or container. Items resolve their label and icon from the registry if not explicitly set:
|
|
@@ -287,6 +306,8 @@ ixfx-menu-item[command="delete"] .item {
|
|
|
287
306
|
| `radio-change` | `{ name, value }` | Fired by `ixfx-menu-radio-group` when selection changes |
|
|
288
307
|
| `menu-command` | `{ command, args, checked }` | Bubbles up from `ixfx-menu-trigger`, re-dispatching a `command`/`checked` event's detail verbatim — `args` is always present, `checked` only from a check-item |
|
|
289
308
|
| `menu-command` | `{ command, value }` | Bubbles up from `ixfx-menu-trigger`, built from a `radio-change` event — `value` only appears on this radio-group path, never alongside `args`/`checked` |
|
|
309
|
+
| `menu-trigger-open` | — | Fired by `ixfx-menu-trigger` when its menu opens (any mode, including right-click in `context` mode) |
|
|
310
|
+
| `menu-trigger-close` | — | Fired by `ixfx-menu-trigger` when its menu closes |
|
|
290
311
|
|
|
291
312
|
## `ixfx-menu-command-controller`
|
|
292
313
|
|
|
@@ -309,7 +330,7 @@ ctrl.start();
|
|
|
309
330
|
|------|-----------------|
|
|
310
331
|
| `trigger` | Shows a button labeled with the `label` property |
|
|
311
332
|
| `dropdown` | No button shown; expects a custom trigger in the `trigger` slot |
|
|
312
|
-
| `context` | Opens at cursor position on right-click |
|
|
333
|
+
| `context` | Opens at cursor position on right-click. Put the right-clickable surface in the `context-target` slot |
|
|
313
334
|
|
|
314
335
|
## Placement
|
|
315
336
|
|
package/docs-user/miller.md
CHANGED
|
@@ -37,6 +37,8 @@ These can be overridden in your CSS:
|
|
|
37
37
|
| `--item-hover-bg` | `var(--item-bg-tickled)` | Background on item hover |
|
|
38
38
|
| `--item-selected-bg` | `var(--item-bg-selected)` | Background of selected item |
|
|
39
39
|
| `--item-selected-text` | `var(--item-text-selected)` | Text color of selected item |
|
|
40
|
+
| `--miller-list-badge-gap` | `0.5em` | Space between a per-item label and its right-justified badge |
|
|
41
|
+
| `--icon-size` / `--icon-spacing` | `1em` / `0.3em` | Per-item icon size and gap |
|
|
40
42
|
|
|
41
43
|
Inherited from theme:
|
|
42
44
|
- `--font-family` - Font family
|
|
@@ -165,13 +167,16 @@ el.clearSelection(): void
|
|
|
165
167
|
|
|
166
168
|
```typescript
|
|
167
169
|
type MillerItem = {
|
|
168
|
-
key: string;
|
|
169
|
-
label: string;
|
|
170
|
-
isLeaf?: boolean;
|
|
171
|
-
data?: unknown;
|
|
172
|
-
icon?: string;
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
key: string; // Unique identifier
|
|
171
|
+
label: string; // Display text
|
|
172
|
+
isLeaf?: boolean; // If true, clicking never fires 'expand'
|
|
173
|
+
data?: unknown; // Arbitrary user data
|
|
174
|
+
icon?: string; // Optional icon name
|
|
175
|
+
iconColor?: string; // Optional CSS colour for the icon
|
|
176
|
+
textColor?: string; // Optional CSS colour for the label
|
|
177
|
+
badge?: unknown; // Optional Finder-style badge (anything Lit can render)
|
|
178
|
+
tooltip?: string; // Optional tooltip text
|
|
179
|
+
value?: string; // Optional string value
|
|
175
180
|
};
|
|
176
181
|
|
|
177
182
|
type MillerNode = {
|
|
@@ -184,6 +189,46 @@ type MillerConfig = {
|
|
|
184
189
|
};
|
|
185
190
|
```
|
|
186
191
|
|
|
192
|
+
### Per-item icon colour, text colour and badges
|
|
193
|
+
|
|
194
|
+
`iconColor` and `textColor` are plain CSS colour strings; the icon paints from
|
|
195
|
+
`currentColor`, so `iconColor` recolours the glyph. `badge` is anything Lit
|
|
196
|
+
can render — a `TemplateResult`, a DOM `Node`, or a string — and shows up
|
|
197
|
+
right-justified on the row, after the name and before the expand caret, the
|
|
198
|
+
way Finder's list view shows colour tags.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { html } from 'lit';
|
|
202
|
+
import { tagChip, stackedTagChips } from './my-tags.js'; // your own SVGs
|
|
203
|
+
|
|
204
|
+
el.root = {
|
|
205
|
+
item: { key: 'root', label: 'Documents' },
|
|
206
|
+
children: [
|
|
207
|
+
{ item: { key: 'a', label: 'Archive.zip', icon: 'file', badge: tagChip('orange') } },
|
|
208
|
+
{
|
|
209
|
+
item: {
|
|
210
|
+
key: 'b',
|
|
211
|
+
label: 'Overdue.txt',
|
|
212
|
+
icon: 'file',
|
|
213
|
+
iconColor: 'var(--accent)',
|
|
214
|
+
textColor: 'crimson',
|
|
215
|
+
badge: stackedTagChips(['red', 'yellow']),
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Colours are applied inline, so they also win over the selected / tickled text
|
|
223
|
+
colours — pick something legible against both, or leave them off and let the
|
|
224
|
+
component's theming handle selection contrast. `undefined`, `null`, `''` and
|
|
225
|
+
`false` all count as "not supplied", so a badge can be made conditional.
|
|
226
|
+
|
|
227
|
+
The badge renders as `<span class="item-badge" part="badge">`, so
|
|
228
|
+
`::part(badge)` works from outside the component.
|
|
229
|
+
|
|
230
|
+
CSS: `--miller-list-badge-gap`.
|
|
231
|
+
|
|
187
232
|
---
|
|
188
233
|
|
|
189
234
|
## Basic Usage
|
|
@@ -122,9 +122,69 @@ To reflect selection state inside the custom element's shadow DOM, target the `:
|
|
|
122
122
|
| `itemHeight` / `item-height` | `number` | `0` | Fixed row height in px. Required for `virtualize` — every row must be exactly this tall |
|
|
123
123
|
| `filterPredicate` | `((el: Element) => boolean) \| undefined` | `undefined` | External filter; only items returning `true` are shown |
|
|
124
124
|
| `checkboxRenderer` | `((checked: boolean) => unknown) \| CustomCheckboxOptions \| undefined` | `undefined` | Custom content for the checkbox in `checked` mode. See [Custom checkbox](#custom-checkbox) |
|
|
125
|
+
| `formatter` | `((item: unknown, index: number) => unknown) \| undefined` | `undefined` | Renders one `items` entry into its row. See [Adapter items](#adapter-items) |
|
|
126
|
+
| `keyProperty` / `key-property` | `string` | `''` | Property on each `items` entry used for stable identity |
|
|
127
|
+
| `icon` | `((item, index) => unknown) \| undefined` | `undefined` | Per-item icon, prepended to the row |
|
|
128
|
+
| `iconColor` | `((item, index) => string \| undefined) \| undefined` | `undefined` | CSS colour for that icon |
|
|
129
|
+
| `textColor` | `((item, index) => string \| undefined) \| undefined` | `undefined` | CSS colour for the row's text |
|
|
130
|
+
| `badge` | `((item, index) => unknown) \| undefined` | `undefined` | Finder-style badge, right-justified on the row |
|
|
125
131
|
|
|
126
132
|
Switching `interactionMode` always clears the current selection.
|
|
127
133
|
|
|
134
|
+
### Adapter items
|
|
135
|
+
|
|
136
|
+
Set `items` and the list builds one `<li>` per entry, resolving each row
|
|
137
|
+
through the function-valued properties above. This is the only mode the
|
|
138
|
+
per-item appearance hooks apply to — declarative and programmatic elements
|
|
139
|
+
already own their own markup.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { html } from 'lit';
|
|
143
|
+
import { tagChip, stackedTagChips } from './my-tags.js'; // your own SVGs
|
|
144
|
+
|
|
145
|
+
list.keyProperty = 'name';
|
|
146
|
+
list.formatter = item => (item as File).name;
|
|
147
|
+
list.icon = item => fileIcon((item as File).ext);
|
|
148
|
+
list.iconColor = item => (item as File).tint;
|
|
149
|
+
list.textColor = item => (item as File).overdue ? 'crimson' : undefined;
|
|
150
|
+
list.badge = item => {
|
|
151
|
+
const { tags } = item as File;
|
|
152
|
+
return tags.length > 1 ? stackedTagChips(tags) : tagChip(tags[0]);
|
|
153
|
+
};
|
|
154
|
+
list.items = files;
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- `icon` is prepended to the row in a fixed-size slot; `iconColor` sets that
|
|
158
|
+
slot's `color`, so glyphs painting from `currentColor` are recoloured.
|
|
159
|
+
- `textColor` is applied to the row itself.
|
|
160
|
+
- `badge` is appended after the text; the row is already a flex row, so the
|
|
161
|
+
badge self-justifies to the trailing edge.
|
|
162
|
+
|
|
163
|
+
Both colours are applied inline, so they also win over the selected / tickled
|
|
164
|
+
text colours — pick something legible against both, or leave them off and let
|
|
165
|
+
the component's theming handle selection contrast. `undefined`, `null`, `''`
|
|
166
|
+
and `false` all count as "not supplied", so a hook can be made conditional
|
|
167
|
+
without touching `items`. Changing any of these rebuilds the rows.
|
|
168
|
+
|
|
169
|
+
All four hooks are skipped when `formatter` returns a full row element (an
|
|
170
|
+
`<li>`, a `[data-list-item]`, or a custom element) — that element owns its own
|
|
171
|
+
markup. See [Item types](#item-types).
|
|
172
|
+
|
|
173
|
+
The icon and badge land as `<span class="item-icon">` / `<span class="item-badge">`
|
|
174
|
+
in the row's light DOM. Their layout is applied as inline styles — a
|
|
175
|
+
`::slotted()` rule can't reach inside a slotted `<li>` — so override it with
|
|
176
|
+
`!important`, or (better) drive it from the CSS variables above:
|
|
177
|
+
|
|
178
|
+
```css
|
|
179
|
+
#list-look {
|
|
180
|
+
--list-item-icon-size: 18px;
|
|
181
|
+
--list-item-badge-gap: 12px;
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Parts: none for these two; they are light-DOM elements you can style with your
|
|
186
|
+
own selectors.
|
|
187
|
+
|
|
128
188
|
### `interactionMode`
|
|
129
189
|
|
|
130
190
|
| Value | Behaviour |
|
|
@@ -654,6 +714,9 @@ dispatch. Mirrors `ixfx-grid-list`'s `grid-list-viewport-change`.
|
|
|
654
714
|
| `--list-radius` | `var(--radius-s)` | Border radius |
|
|
655
715
|
| `--list-item-height` | `28px` | Minimum row height for `<li>` items; set it to match `item-height` when virtualizing |
|
|
656
716
|
| `--list-item-padding` | `4px var(--space-m, 8px)` | Padding for `<li>` items |
|
|
717
|
+
| `--list-item-icon-size` | `1em` | Size of the adapter-mode per-item icon |
|
|
718
|
+
| `--list-item-icon-gap` | `6px` | Space between the adapter-mode icon and the row text |
|
|
719
|
+
| `--list-item-badge-gap` | `8px` | Space between the row text and a right-justified adapter-mode badge |
|
|
657
720
|
| `--item-bg-tickled` | `rgba(0,0,0,0.06)` | Row background when cursor is on it |
|
|
658
721
|
| `--item-bg-selected` | `rgba(25,118,210,1)` | Selected row background |
|
|
659
722
|
| `--item-text-selected` | `#fff` | Selected row text colour |
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-grid-CfiaBqTA.d.ts","names":[],"sources":["../src/data-grid/types.ts","../src/data-grid/data-grid.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detail-list-DxQZkK-C.d.ts","names":[],"sources":["../src/detail-list/types.ts","../src/detail-list/detail-list.ts"],"mappings":";;;;;;;;;;;KACY;;KAGA;WACD,SAAS;WACT;WACA;;;KAIC,wBAAwB,GAAG,gBAAgB,GAAG;;KAG9C,mBAAmB,eAAe,2BAA2B;;;;;;;;;;;;;;;;;;;;cCqH5D,0BAA0B;;EAErC,eAAe;EAGf,iBAAiB;EAGjB,MAAM;EAGN;EAGA,gBAAgB;EAGhB;EAGA,UAAU;EAGV;EAGA,WAAW;EAGX;EAGA;EAGA,mBAAmB,IAAI;;;;;;EAQvB;;EAIA,oBAAoB,gCAAgC;;;;;;EAQpD;;;;;;EAQA;;;;;EAOA,qBAAqB,wBAAwB;EAG7C,mBAAmB,8BAA8B;UAGzC;mBAoBS;UAeT;UAyFA;;WAkGC,QAAM,qBAAA;;MAYX,YAAY;EAoBP;EA8DA;EA2BA;EASA,QAAQ,SAAS;;MA0CtB,gBAAgB;;MAKhB,iBAAiB,YAAY;;;;;;EASjC;EAIA,QAAQ,MAAM,kBAAkB,UAAU;;;;;EAuB1C,WAAW,MAAM,UAAU;;EAW3B,YAAY,OAAO,SAAS,WAAW;EAIvC;;;;;EAYA,SAAS,gBAAgB;;;;;EAgBzB,YAAY,MAAM;;;;;;;;;;EAalB;;;;;;EAsBA,SAAS,WAAW,WAAW,OAAO;EAItC,OAAO,MAAM;EAIb,WAAW,OAAO,SAAS;EAI3B,SAAS,MAAM;EAIf;EAIA;;MAQI,gBAAgB;;MAKhB;;EAMJ,WAAW,MAAM;;EAKjB,gBAAgB,MAAM;;EAKtB,mBAAmB,MAAM;;EAKzB,SAAS;EAgBP,eAAe,0CAA0C,UAAU;UA4a7D;;;;;;;;;EAkBF,kBAAkB;UAwBhB;UAMA;UAgCA;UAiBA;;;;;;;UA2DA;;UAoBA;UAcA;UAYA;UAQA;UA6DA;UAMA;UAIA;UA4EA;UAWA;UAMA;UAKA;SAUQ,sBAAM;EAiJb,wBAAM;;QAsBT;YACI;IACR,oBAAoB;;YAGZ,4BAA4B;;UAGvB,kCAAkC;EACjD,+BAA+B;EAC/B,0BAA0B,yBAAyB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grid-list-ChgYpUUq.d.ts","names":[],"sources":["../src/interaction/list-drag-select-controller.ts","../src/interaction/list-selection-controller.ts","../src/interaction/tree-keyboard-controller.ts","../src/grid-list/types.ts","../src/grid-list/grid-list.ts"],"mappings":"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"}
|