@ixfx/components 0.15.4 → 0.15.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/bundle/index.d.ts +307 -5
  2. package/bundle/index.js +283 -114
  3. package/dist/ac-text.d.ts +1 -1
  4. package/dist/{ac-token-Cq7lsYf-.d.ts → ac-token-qEs3FsQv.d.ts} +1 -1
  5. package/dist/ac-token.d.ts +1 -1
  6. package/dist/colour-picker.d.ts +1 -1
  7. package/dist/crumbs.d.ts +1 -1
  8. package/dist/{data-grid-Dx3l3dxw.js → data-grid-C1sZX6n9.js} +37 -9
  9. package/dist/{data-grid-CbiubdG2.d.ts → data-grid-D7qzmMMp.d.ts} +14 -7
  10. package/dist/data-grid.d.ts +1 -1
  11. package/dist/data-grid.js +1 -1
  12. package/dist/{detail-list-ClkMV0SN.d.ts → detail-list-CKIKlszv.d.ts} +3 -3
  13. package/dist/detail-list.d.ts +2 -2
  14. package/dist/{flat-list-0xTZdXzh.d.ts → flat-list-DXMyDiSH.d.ts} +2 -2
  15. package/dist/flat-list.d.ts +1 -1
  16. package/dist/{grid-list-BnWJUIBC.d.ts → grid-list-0e7snW6t.d.ts} +1 -1
  17. package/dist/grid-list.d.ts +1 -1
  18. package/dist/{grouped-item-lister-Bhyo-dkH.d.ts → grouped-item-lister-DETte0Dh.d.ts} +1 -1
  19. package/dist/grouped-item-lister.d.ts +1 -1
  20. package/dist/{icon-DR_3rSyZ.d.ts → icon-CDGprSdE.d.ts} +1 -1
  21. package/dist/icons.d.ts +2 -2
  22. package/dist/incr-search.d.ts +1 -1
  23. package/dist/{index-garxxqgV.d.ts → index-CYndvTWH.d.ts} +1 -1
  24. package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +1 -1
  25. package/dist/{index-BAuqR9El.d.ts → index-DEVyVIn8.d.ts} +1 -1
  26. package/dist/{index-Bz3loIAf.d.ts → index-DN2BWctP.d.ts} +1 -1
  27. package/dist/{index-cnaRPQPp.d.ts → index-DxyyVqzA.d.ts} +2 -2
  28. package/dist/{index-BPTuCRGb.d.ts → index-KN2MW_xD.d.ts} +1 -1
  29. package/dist/{index-CJ5fshD3.d.ts → index-UvnoZUAo.d.ts} +1 -1
  30. package/dist/index.d.ts +56 -20
  31. package/dist/index.js +3 -2
  32. package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +1 -1
  33. package/dist/labelled-radial-input.d.ts +2 -2
  34. package/dist/labelled-range-input.d.ts +1 -1
  35. package/dist/labelled-slider-input.d.ts +1 -1
  36. package/dist/list-group-header.d.ts +1 -1
  37. package/dist/{menu-item-B0zqw2xp.d.ts → menu-item-bF6narIz.d.ts} +1 -1
  38. package/dist/menu.d.ts +2 -2
  39. package/dist/miller.d.ts +1 -1
  40. package/dist/panel.d.ts +1 -1
  41. package/dist/{split-layout-C5SYbDrq.d.ts → split-layout-JK3xWVX2.d.ts} +1 -1
  42. package/dist/split-layout.d.ts +1 -1
  43. package/dist/sunburst-tree.d.ts +2 -0
  44. package/dist/sunburst-tree.js +2 -0
  45. package/dist/sunbursttree-list--Z0uyh8O.d.ts +266 -0
  46. package/dist/sunbursttree-list-yXwS-uEI.js +1337 -0
  47. package/dist/{tab-list-wC0xNz1b.d.ts → tab-list-Df371rqw.d.ts} +1 -1
  48. package/dist/tabs.d.ts +1 -1
  49. package/dist/{titlebar-B5zSTZnF.d.ts → titlebar-Tqu-VvMU.d.ts} +1 -1
  50. package/dist/titlebar.d.ts +1 -1
  51. package/dist/tree.d.ts +1 -1
  52. package/dist/{vertical-list-B8FoU-pU.d.ts → vertical-list-D8MksoTp.d.ts} +1 -1
  53. package/dist/vertical-list.d.ts +1 -1
  54. package/docs-user/README.md +1 -0
  55. package/docs-user/data-grid.md +11 -4
  56. package/docs-user/index.json +7 -2
  57. package/docs-user/llms.txt +1 -0
  58. package/docs-user/sunburst-tree.md +193 -0
  59. package/docs-user/tree.md +1 -1
  60. package/llms.txt +1 -0
  61. package/package.json +5 -1
@@ -1,4 +1,4 @@
1
- import "./icon-DR_3rSyZ.js";
1
+ import "./icon-CDGprSdE.js";
2
2
  import { LitElement, PropertyValues } from "lit";
3
3
  import { CommandRegistry } from "@clinth/ui-commands";
4
4
  //#region src/tabs/tab-list-item.d.ts
package/dist/tabs.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as TabListReorderDetail, i as TabListElement, n as TabListChangeEvent, o as TabListReorderEvent, r as TabListDragMode, t as TabListChangeDetail } from "./tab-list-wC0xNz1b.js";
1
+ import { a as TabListReorderDetail, i as TabListElement, n as TabListChangeEvent, o as TabListReorderEvent, r as TabListDragMode, t as TabListChangeDetail } from "./tab-list-Df371rqw.js";
2
2
  export { TabListChangeDetail, TabListChangeEvent, TabListDragMode, TabListElement, TabListReorderDetail, TabListReorderEvent };
@@ -1,4 +1,4 @@
1
- import "./icon-DR_3rSyZ.js";
1
+ import "./icon-CDGprSdE.js";
2
2
  import { LitElement } from "lit";
3
3
  //#region src/titlebar/titlebar.d.ts
4
4
  type TitlebarOrientation = `horizontal` | `vertical`;
@@ -1,2 +1,2 @@
1
- import { a as TitlebarToggleDetail, c as TitlebarVariant, i as TitlebarOrientation, n as TitlebarElement, o as TitlebarToggleEvent, r as TitlebarElementEventMap, s as TitlebarToggleInteraction, t as TitlebarCloseEvent } from "./titlebar-B5zSTZnF.js";
1
+ import { a as TitlebarToggleDetail, c as TitlebarVariant, i as TitlebarOrientation, n as TitlebarElement, o as TitlebarToggleEvent, r as TitlebarElementEventMap, s as TitlebarToggleInteraction, t as TitlebarCloseEvent } from "./titlebar-Tqu-VvMU.js";
2
2
  export { TitlebarCloseEvent, TitlebarElement, TitlebarElementEventMap, TitlebarOrientation, TitlebarToggleDetail, TitlebarToggleEvent, TitlebarToggleInteraction, TitlebarVariant };
package/dist/tree.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import { A as TreeTickleEvent, D as TreeSelectDetail, M as TreeDataModelOptions, O as TreeSelectEvent, T as TreeRevealMode, _ as TreeDropTarget, b as TreeItemClickDetail, c as TreeDragContext, d as TreeDragStartEvent, g as TreeDropPosition, h as TreeDropEvent, i as TreeCollapseEvent, j as TreeDataModel, k as TreeTickleDetail, l as TreeDragEndEvent, m as TreeDropDetail, n as TreeActivateEvent, o as TreeComponentEventMap, p as TreeDropContext, r as TreeCollapseDetail, s as TreeDndMode, t as TreeActivateDetail, u as TreeDragOverEvent, v as TreeExpandDetail, w as TreeNavigateOptions, x as TreeItemClickEvent, y as TreeExpandEvent } from "./tree-component-C6UHO-w9.js";
2
2
  import { a as TreeItem, n as TreeExclusivity, o as TreeNode, r as TreeFilterPredicate, s as TreeSelectionFilter, t as LoadChildrenCallback } from "./types-Jky6oNAp.js";
3
- import { a as TreeDropVisibleRow, c as TreeListElement, d as TreeBaseElement, f as TreeBaseElementEventMap, i as TreeDropRowInfo, l as TreeCheckboxState, m as TreeConfig, n as TreeDropControllerConfig, o as TreeController, p as TreeVirtualize, r as TreeDropResolvedDrag, s as TreeControllerOptions, t as TreeDropController, u as TreeAnimation } from "./index-BAuqR9El.js";
3
+ import { a as TreeDropVisibleRow, c as TreeListElement, d as TreeBaseElement, f as TreeBaseElementEventMap, i as TreeDropRowInfo, l as TreeCheckboxState, m as TreeConfig, n as TreeDropControllerConfig, o as TreeController, p as TreeVirtualize, r as TreeDropResolvedDrag, s as TreeControllerOptions, t as TreeDropController, u as TreeAnimation } from "./index-DEVyVIn8.js";
4
4
  export { type LoadChildrenCallback, type TreeActivateDetail, type TreeActivateEvent, TreeAnimation, TreeBaseElement, TreeBaseElementEventMap, type TreeCheckboxState, type TreeCollapseDetail, type TreeCollapseEvent, type TreeComponentEventMap, TreeConfig, TreeController, TreeControllerOptions, TreeDataModel, type TreeDataModelOptions, type TreeDndMode, type TreeDragContext, type TreeDragEndEvent, type TreeDragOverEvent, type TreeDragStartEvent, type TreeDropContext, TreeDropController, TreeDropControllerConfig, type TreeDropDetail, type TreeDropEvent, type TreeDropPosition, TreeDropResolvedDrag, TreeDropRowInfo, type TreeDropTarget, TreeDropVisibleRow, type TreeExclusivity, type TreeExpandDetail, type TreeExpandEvent, type TreeFilterPredicate, type TreeItem, type TreeItemClickDetail, type TreeItemClickEvent, TreeListElement, type TreeNavigateOptions, type TreeNode, type TreeRevealMode, type TreeSelectDetail, type TreeSelectEvent, type TreeSelectionFilter, type TreeTickleDetail, type TreeTickleEvent, TreeVirtualize };
@@ -1,6 +1,6 @@
1
1
  import { B as ListNativeDragStartEvent, I as ListDragPreviewRenderer, L as ListDragPreviewSourceResolver } from "./tree-component-C6UHO-w9.js";
2
2
  import { n as ListViewportChangeEvent } from "./list-viewport-types-BRZsLcvp.js";
3
- import { S as ListSearchController } from "./index-BPTuCRGb.js";
3
+ import { S as ListSearchController } from "./index-KN2MW_xD.js";
4
4
  import { i as ListInteractionMode, l as ListSelectionMode, r as ListElementEventMap } from "./list-selection-types-PjKdhF-a.js";
5
5
  import "./editable-label-rzXkjf1H.js";
6
6
  import { LitElement, PropertyValues } from "lit";
@@ -1,5 +1,5 @@
1
1
  import { B as ListNativeDragStartEvent, F as ListDragPreviewContext, I as ListDragPreviewRenderer, N as ListDragEntry, P as ListDragPreview, R as ListDragSource, z as ListNativeDragStartDetail } from "./tree-component-C6UHO-w9.js";
2
2
  import { n as ListViewportChangeEvent, t as ListViewportChangeDetail } from "./list-viewport-types-BRZsLcvp.js";
3
3
  import { a as ListItemClickDetail, c as ListSelectEvent, d as ListTickleEvent, i as ListInteractionMode, l as ListSelectionMode, n as ListActivateEvent, o as ListItemClickEvent, r as ListElementEventMap, s as ListSelectDetail, t as ListActivateDetail, u as ListTickleDetail } from "./list-selection-types-PjKdhF-a.js";
4
- import { a as ListContextMenuDetail, c as ListDragLeaveEvent, d as ListDropEvent, f as ListEditCancelDetail, h as ListEditCommitEvent, i as VerticalListElementEventMap, l as ListDragOverEvent, m as ListEditCommitDetail, n as CustomCheckboxOptions, o as ListContextMenuEvent, p as ListEditCancelEvent, r as VerticalListElement, s as ListDragLeaveDetail, t as AddItemOptions, u as ListDropDetail } from "./vertical-list-B8FoU-pU.js";
4
+ import { a as ListContextMenuDetail, c as ListDragLeaveEvent, d as ListDropEvent, f as ListEditCancelDetail, h as ListEditCommitEvent, i as VerticalListElementEventMap, l as ListDragOverEvent, m as ListEditCommitDetail, n as CustomCheckboxOptions, o as ListContextMenuEvent, p as ListEditCancelEvent, r as VerticalListElement, s as ListDragLeaveDetail, t as AddItemOptions, u as ListDropDetail } from "./vertical-list-D8MksoTp.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 };
@@ -49,6 +49,7 @@ This directory contains documentation for each component and some architectural
49
49
  - [snackbar](./snackbar.md)
50
50
  - [snap-container](./snap-container.md)
51
51
  - [split-layout](./split-layout.md)
52
+ - [sunburst-tree](./sunburst-tree.md)
52
53
  - [swipe](./swipe.md)
53
54
  - [tabs](./tabs.md)
54
55
  - [text-shimmer](./text-shimmer.md)
@@ -306,9 +306,12 @@ for plain text columns. It returns `false` and does nothing for:
306
306
 
307
307
  - an unknown column key,
308
308
  - a column with `resizable: false`,
309
- - a column with a `renderer` — its rendered output (icons, badges, custom
310
- markup, etc.) can't be reliably measured from the raw value, so sizing to
311
- it would be a guess.
309
+ - a column with a `renderer` that gives no hint of its size — its rendered
310
+ output (icons, badges, custom markup, etc.) can't be reliably measured from
311
+ the raw value. Opt in with either:
312
+ - `fixedExtraWidth: n` — pixels added to the measured text width (e.g. a
313
+ thumbnail beside the text), or
314
+ - `measure: (row, col) => px` — your own content-width measure per row.
312
315
 
313
316
  `--data-grid-column-resize-duration` (default `180ms`) controls the
314
317
  transition speed.
@@ -459,6 +462,10 @@ Demo: `Score` is random float `0–100` with 0–3 decimals, `align:'right'`, `f
459
462
 
460
463
  Gear menu (`ixfx-menu-trigger` placement `bottom-end`, `inset-area: block-end span-inline-end`) lists `Columns` (check-items) and `Group by` (radio). Toggle visibility via `col.visible=false` or menu. Event: `datagrid-column-visibility` `{key, visible}`.
461
464
 
465
+ Set `col.group` to a heading (e.g. the facet a column came from) and the menu
466
+ lists columns sharing that group in one submenu; ungrouped columns stay at the
467
+ top level.
468
+
462
469
  `column-menu` attribute: `none` (default) hides the gear menu; `auto` opts in to
463
470
  rendering it. `col.visible` + `datagrid-column-visibility` give full external
464
471
  control, so a host can own the column-visibility UI.
@@ -542,7 +549,7 @@ still shadow-internal.
542
549
  | `appendRows` | `(rows)` | Add rows without a full re-sort/rebuild — for streaming |
543
550
  | `selectKeys` / `set selectedKeys` | `(keys)` | Replace the selection by row key |
544
551
  | `tickleRow` | `(key)` | Move the row cursor and scroll it into view |
545
- | `autoSizeColumn` | `(key)=>boolean` | Resize a column to fit its contents, animating the width. Returns `false` (no-op) for an unknown column, `resizable: false`, or a column with a `renderer` — see [Auto-sizing a column](#auto-sizing-a-column). |
552
+ | `autoSizeColumn` | `(key)=>boolean` | Resize a column to fit its contents, animating the width. Returns `false` (no-op) for an unknown column, `resizable: false`, or a `renderer` column without `measure`/`fixedExtraWidth` — see [Auto-sizing a column](#auto-sizing-a-column). |
546
553
 
547
554
  | Getter | Type | |
548
555
  |---|---|---|
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
- "version": "0.15.4",
4
- "generated": "2026-10-19T01:39:50.334Z",
3
+ "version": "0.15.5",
4
+ "generated": "2026-10-23T07:10:01.881Z",
5
5
  "components": [
6
6
  {
7
7
  "name": "ac-text",
@@ -228,6 +228,11 @@
228
228
  "summary": "A Lit web component that lays out any number of panels along one axis with draggable gutters between them.",
229
229
  "path": "docs-user/split-layout.md"
230
230
  },
231
+ {
232
+ "name": "sunburst-tree",
233
+ "summary": "`<ixfx-sunbursttree-list>` — a zoomable sunburst over weighted tree data. The zoom node is the centre disc; each ring outward is one generation, and each arc's angle is its share of its parent's value",
234
+ "path": "docs-user/sunburst-tree.md"
235
+ },
231
236
  {
232
237
  "name": "swipe",
233
238
  "summary": "A touch-friendly swipe/nudge component. User taps and drags to generate a value in range [-1, 1]. Value is emitted only on pointer release.",
@@ -56,6 +56,7 @@ import '@ixfx/components/data-grid';
56
56
  - [snackbar](docs-user/snackbar.md): A small floating toolbar anchored in visual proximity to another element on the page (the "target"), built on the native Popover and CSS Anchor Positioning APIs.
57
57
  - [snap-container](docs-user/snap-container.md): A container that positions its child element at configurable snap positions along an axis. The child can be dragged, clicked to snap, or controlled via keyboard.
58
58
  - [split-layout](docs-user/split-layout.md): A Lit web component that lays out any number of panels along one axis with draggable gutters between them.
59
+ - [sunburst-tree](docs-user/sunburst-tree.md): `<ixfx-sunbursttree-list>` — a zoomable sunburst over weighted tree data. The zoom node is the centre disc; each ring outward is one generation, and each arc's angle is its share of its parent's value
59
60
  - [swipe](docs-user/swipe.md): A touch-friendly swipe/nudge component. User taps and drags to generate a value in range [-1, 1]. Value is emitted only on pointer release.
60
61
  - [tabs](docs-user/tabs.md): A complete tabbed interface system using several coordinated components:
61
62
  - [text-shimmer](docs-user/text-shimmer.md): A label with a sweeping highlight band across the text. Useful as a lightweight "still working…" or "loading…" indicator.
@@ -0,0 +1,193 @@
1
+ # Sunburst Tree
2
+
3
+ `<ixfx-sunbursttree-list>` — a zoomable sunburst over weighted tree data. The zoom node is the centre disc; each ring outward is one generation, and each arc's angle is its share of its parent's value. Every change — data arriving, a different weighting, a zoom — animates from what's on screen to the new layout.
4
+
5
+ It implements the shared `TreeComponent` interface (see [`src/tree/README.md`](../tree/README.md)), so `TreeDataModel`, `IncrSearchTreeController`, and `TreeComponent`-typed code work unmodified. Geometrically it is a polar [icicle](../icicle-tree/), and shares its API shape.
6
+
7
+ ---
8
+
9
+ ## Contents
10
+
11
+ 1. [Differences from `ixfx-tree-list`](#differences-from-ixfx-tree-list)
12
+ 2. [Data model](#data-model)
13
+ 3. [Values and weighting](#values-and-weighting)
14
+ 4. [Progressive data](#progressive-data)
15
+ 5. [Colour](#colour)
16
+ 6. [Properties](#properties)
17
+ 7. [Zoom, selection, navigation](#zoom-selection-navigation)
18
+ 8. [Events](#events)
19
+ 9. [Keyboard / pointer interaction](#keyboard--pointer-interaction)
20
+ 10. [CSS variables and parts](#css-variables-and-parts)
21
+
22
+ ---
23
+
24
+ ## Differences from `ixfx-tree-list`
25
+
26
+ - **Expand/collapse is reinterpreted as zoom.** `expand` fires on zoom-in, `collapse` on zoom-out.
27
+ - **`interactionMode` drops `'checked'`**; **`exclusivity` is accepted but ignored**.
28
+ - **`filterPredicate` dims** non-matching arcs instead of hiding them.
29
+ - **Reassigning `root` keeps zoom and selection** wherever the same key paths still exist (the icicle and treemap reset instead). See [Progressive data](#progressive-data).
30
+ - Drag-and-drop is out of scope.
31
+
32
+ ## Data model
33
+
34
+ Same `TreeNode` / `TreeItem` shapes as the rest of the tree family, including `root`, `model` and `loadChildren` for lazy loading (children are fetched for every visible arc).
35
+
36
+ Keys only need to be unique **among siblings**: arcs are identified by their key *path* from the root, so file-system data — where `readme.md` recurs in many folders — works. Lookups that only have a bare key (`revealKey`) match the first node, depth-first, carrying it.
37
+
38
+ ## Values and weighting
39
+
40
+ Every node — branches included — has a value. A child's arc is its share of its parent's:
41
+
42
+ ```
43
+ childAngle = parentAngle × child / max(parent, Σ siblings)
44
+ ```
45
+
46
+ - Children summing to **less** than their parent leave an unfilled gap — "unaccounted for" space (unscanned disk, an unknown remainder).
47
+ - Children summing to **more** are scaled down to fit.
48
+
49
+ Give values as a plain number on `item.weight` (the default accessor reads it), or as a function:
50
+
51
+ ```typescript
52
+ el.root = {
53
+ item: { key: 'hd', label: 'Disk', weight: 500e9 },
54
+ children: [
55
+ { item: { key: 'apps', label: 'Applications', weight: 120e9 }, children: [] },
56
+ { item: { key: 'users', label: 'Users', weight: 300e9 }, children: [] },
57
+ ],
58
+ };
59
+
60
+ // Swap weighting scheme: no DOM is rebuilt, the chart animates to the new layout.
61
+ el.valueAccessor = (item, node) => (item.data as Stats).fileCount;
62
+ ```
63
+
64
+ `valueAccessor` is `(item, node) => number | undefined`. When it returns `undefined` (or a negative / non-finite number) the node falls back to the **sum of its loaded children**, or `1` for a leaf or not-yet-loaded node. So unweighted data shows descendant counts, and an accessor can value only leaves and let branches sum:
65
+
66
+ ```typescript
67
+ el.valueAccessor = (item, node) => node.children ? undefined : Math.log2(bytes(item) + 1);
68
+ ```
69
+
70
+ `valueFormatter` (`(value, node) => string`) formats the value in the centre readout:
71
+
72
+ ```typescript
73
+ el.valueFormatter = v => `${(v / 1e9).toFixed(1)} GB`;
74
+ ```
75
+
76
+ ## Progressive data
77
+
78
+ Any update re-lays out and animates: new arcs grow from zero width, removed ones shrink away, the rest slide to their new angles. An update arriving mid-animation retargets from wherever things currently are.
79
+
80
+ Either rebuild the tree immutably and reassign it:
81
+
82
+ ```typescript
83
+ el.root = snapshotOfScanSoFar(); // zoom + selection carry over by key path
84
+ ```
85
+
86
+ or mutate in place and nudge the element — or let a `TreeDataModel` notify it:
87
+
88
+ ```typescript
89
+ folder.children.push(newFile);
90
+ el.requestUpdate();
91
+ ```
92
+
93
+ ## Colour
94
+
95
+ Hue is set by the ring around the centre: each first-ring arc takes the hue at its angular midpoint (so the ring spans the colour wheel), and every descendant takes a tone of that hue — lighter and less saturated each ring out, with a small per-sibling shift so neighbours stay distinct. Zooming re-anchors hues to the new first ring, cross-fading as it goes. The centre disc mixes towards `--sunbursttree-center-color`.
96
+
97
+ All of it is computed in CSS from per-arc custom properties, so the palette is themeable:
98
+
99
+ | Per-arc property | Value |
100
+ |---|---|
101
+ | `--arc-hue` | Degrees, added to `--sunbursttree-hue-start` |
102
+ | `--arc-depth` | Ring index from the centre (`0` = first ring) |
103
+ | `--arc-shade` | Sibling-position offset, `-0.5..0.5` |
104
+ | `--arc-centre` | `0..1`, how far the arc has become the centre disc |
105
+
106
+ ## Properties
107
+
108
+ | Property (attribute) | Type | Default | Description |
109
+ |---|---|---|---|
110
+ | `root` | `TreeNode \| undefined` | `undefined` | Root node of the tree |
111
+ | `model` | `TreeDataModel \| undefined` | `undefined` | Shared data model; takes precedence over `loadChildren` |
112
+ | `loadChildren` | `LoadChildrenCallback \| undefined` | `undefined` | Callback for lazy child loading |
113
+ | `valueAccessor` | `SunburstValueAccessor` | `item => item.weight` | Node value. See [Values and weighting](#values-and-weighting) |
114
+ | `valueFormatter` | `SunburstValueFormatter` | locale number | Formats the centre readout's value |
115
+ | `interactionMode` (`interaction-mode`) | `'implicit' \| 'standard' \| 'manual'` | `'standard'` | Gesture mapping |
116
+ | `selectionFilter` (`selection-filter`) | `'none' \| 'leaf' \| 'branch' \| 'all'` | `'all'` | Which node kinds can be selected |
117
+ | `maxDepth` (`max-depth`) | `number` | `5` | Rings drawn around the centre |
118
+ | `centerRatio` (`center-ratio`) | `number` | `0.22` | Centre disc radius as a fraction of the overall radius |
119
+ | `minArcLength` (`min-arc-length`) | `number` | `1.5` | Arcs whose outer edge is shorter than this (px) aren't drawn — bounds DOM size for big trees |
120
+ | `disableLabels` (`disable-labels`) | `boolean` | `false` | Hide in-arc labels (the centre readout remains) |
121
+ | `curvedLabels` (`curved-labels`) | `boolean` | `false` | Curve labels along their ring instead of drawing them straight. See below |
122
+ | `animationDuration` (`animation-duration`) | `number` | `600` | Transition length in ms; `0` snaps. Respects `prefers-reduced-motion` |
123
+ | `filterPredicate` | `TreeFilterPredicate \| undefined` | `undefined` | Non-matching arcs (with no matching descendant) are dimmed |
124
+ | `disableKeyboardNavigation` (`disable-keyboard-navigation`) | `boolean` | `false` | Turn off keyboard handling |
125
+ | `searchModes` (`search-modes`) | `string \| undefined` | `undefined` | Subset of `navigate select filter` — see [`docs/infra-incremental.md`](../../docs/infra-incremental.md) |
126
+ | `exclusivity` | `TreeExclusivity` | `'none'` | Accepted for interface compatibility, ignored |
127
+ | `selectedNode` / `selectedNodes` | | | Same contract as `ixfx-tree-list` |
128
+ | `focusedNode` | `TreeNode \| undefined` (read-only) | `undefined` | Current zoom node; `undefined` when showing the full tree |
129
+
130
+ In-arc labels run along the ring when the arc is long enough, otherwise radially (truncated to the ring width); both flip to stay upright. With `curved-labels`, ring-following labels bend to the arc (an SVG `<textPath>` along the ring's middle, reversed in the bottom half so it reads upright). Since the whole arc length is usable, long labels are truncated with `…` rather than dropped; arcs too narrow for a few characters still fall back to straight radial text. Arcs too thin for either are unlabelled — hover or keyboard-cursor them and the centre readout shows their label, value and share of the centre.
131
+
132
+ ## Zoom, selection, navigation
133
+
134
+ ```typescript
135
+ el.zoomTo(node); // node becomes the centre
136
+ el.zoomUp(); // centre's parent becomes the centre
137
+ el.zoomOut(); // back to the full tree
138
+
139
+ el.select(node); el.deselect(node); el.clearSelection(); el.selectAll(); el.deselectAll();
140
+
141
+ // Zooms so the target sits in the first ring (its parent at the centre), then selects it.
142
+ el.navigateTo(['users', 'me', 'photos']);
143
+ el.navigateToNode(n => n.item.key === 'photos');
144
+
145
+ el.getNodes(); // visible arcs (centre excluded), ring-major
146
+ ```
147
+
148
+ ## Events
149
+
150
+ All events **bubble** and are **composed**. `depth` counts from the root's children (`0`).
151
+
152
+ | Event | Detail | When |
153
+ |---|---|---|
154
+ | `zoom` | `SunburstZoomDetail` — `{ node: TreeNode \| undefined; depth }` | Zoom node changes (`node` undefined = full tree) |
155
+ | `expand` / `collapse` | `{ node; depth }` | Zoomed into a descendant / out of the previous centre |
156
+ | `select` | `TreeSelectDetail` | Selection changes |
157
+ | `tickle` | `TreeTickleDetail` | Pointer or keyboard cursor enters an arc |
158
+ | `activate` | `TreeActivateDetail` | Enter or double-click |
159
+ | `item-click` / `item-dblclick` | `{ node; depth }` | Raw pointer clicks on an arc |
160
+
161
+ ## Keyboard / pointer interaction
162
+
163
+ | Input | Action |
164
+ |---|---|
165
+ | Click an arc | Select (per `interactionMode`) and zoom in, if it has children |
166
+ | Ctrl/⌘-click, Shift-click | Toggle / range-select (`standard` mode), without zooming |
167
+ | Click the centre | Zoom up one level |
168
+ | `←` / `→` | Previous / next sibling (wraps) |
169
+ | `↑` / `↓` | Parent (inward) / first child (outward) |
170
+ | `Home` / `End` | First / last visible arc |
171
+ | `Enter` | Select, activate and zoom in |
172
+ | `Escape` / `Backspace` | Zoom up one level |
173
+
174
+ ## CSS variables and parts
175
+
176
+ | Variable | Default | Description |
177
+ |---|---|---|
178
+ | `--sunbursttree-hue-start` | `250` | Hue at 12 o'clock |
179
+ | `--sunbursttree-chroma` | `0.14` | First-ring chroma |
180
+ | `--sunbursttree-chroma-step` | `0.015` | Chroma lost per ring outward |
181
+ | `--sunbursttree-lightness` | `60%` | First-ring lightness |
182
+ | `--sunbursttree-lightness-step` | `5%` | Lightness gained per ring outward |
183
+ | `--sunbursttree-shade-step` | `10%` | Lightness spread across siblings |
184
+ | `--sunbursttree-center-color` | `var(--surface-4)` | Centre disc fill |
185
+ | `--sunbursttree-center-text` | `var(--surface-4-text)` | Centre readout text |
186
+ | `--sunbursttree-gap-color` | `var(--surface-2)` | Stroke between arcs — match it to the background |
187
+ | `--sunbursttree-gap` | `1px` | Width of that stroke |
188
+ | `--sunbursttree-font-size` | `11px` | Label size (px; read for label fitting) |
189
+ | `--sunbursttree-label-lightness` | `22%` | Label lightness (hue follows the arc) |
190
+
191
+ Parts: `arc`, `center`, `label`, `center-readout`.
192
+
193
+ The host defaults to `aspect-ratio: 1` with a `200px` minimum height; give it a width (or both dimensions) to size it.
package/docs-user/tree.md CHANGED
@@ -37,7 +37,7 @@ type TreeItem = {
37
37
  icon?: string; // Icon name (passed to <ixfx-icon>)
38
38
  tooltip?: string; // Tooltip content
39
39
  value?: string; // Optional machine-readable value
40
- weight?: number; // Relative importance/magnitude; only ixfx-hyperbolictree-list uses it today
40
+ weight?: number; // Relative importance/magnitude; used by ixfx-hyperbolictree-list and ixfx-sunbursttree-list
41
41
  };
42
42
 
43
43
  type TreeNode = {
package/llms.txt CHANGED
@@ -56,6 +56,7 @@ import '@ixfx/components/data-grid';
56
56
  - [snackbar](docs-user/snackbar.md): A small floating toolbar anchored in visual proximity to another element on the page (the "target"), built on the native Popover and CSS Anchor Positioning APIs.
57
57
  - [snap-container](docs-user/snap-container.md): A container that positions its child element at configurable snap positions along an axis. The child can be dragged, clicked to snap, or controlled via keyboard.
58
58
  - [split-layout](docs-user/split-layout.md): A Lit web component that lays out any number of panels along one axis with draggable gutters between them.
59
+ - [sunburst-tree](docs-user/sunburst-tree.md): `<ixfx-sunbursttree-list>` — a zoomable sunburst over weighted tree data. The zoom node is the centre disc; each ring outward is one generation, and each arc's angle is its share of its parent's value
59
60
  - [swipe](docs-user/swipe.md): A touch-friendly swipe/nudge component. User taps and drags to generate a value in range [-1, 1]. Value is emitted only on pointer release.
60
61
  - [tabs](docs-user/tabs.md): A complete tabbed interface system using several coordinated components:
61
62
  - [text-shimmer](docs-user/text-shimmer.md): A label with a sweeping highlight band across the text. Useful as a lightweight "still working…" or "loading…" indicator.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
3
  "type": "module",
4
- "version": "0.15.4",
4
+ "version": "0.15.5",
5
5
  "packageManager": "pnpm@10.0.0",
6
6
  "description": "Web components for ixfx — Lit-based UI toolkit",
7
7
  "author": "Clint Heyer",
@@ -141,6 +141,10 @@
141
141
  "types": "./dist/tabs.d.ts",
142
142
  "import": "./dist/tabs.js"
143
143
  },
144
+ "./sunburst-tree": {
145
+ "types": "./dist/sunburst-tree.d.ts",
146
+ "import": "./dist/sunburst-tree.js"
147
+ },
144
148
  "./timeline": {
145
149
  "types": "./dist/timeline.d.ts",
146
150
  "import": "./dist/timeline.js"