@ixfx/components 0.4.3 → 0.5.0

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 (239) hide show
  1. package/bundle/index.d.ts +518 -1176
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +4861 -17274
  4. package/bundle/index.js.map +1 -1
  5. package/bundle/style.css +1 -1
  6. package/dist/ac-text.d.ts +12 -7
  7. package/dist/ac-text.d.ts.map +1 -1
  8. package/dist/ac-text.js +2 -3
  9. package/dist/ac-text.js.map +1 -1
  10. package/dist/{button-C3fLMKUv.js → button-DxYee1ZH.js} +2 -2
  11. package/dist/{button-C3fLMKUv.js.map → button-DxYee1ZH.js.map} +1 -1
  12. package/dist/button.d.ts +1 -2
  13. package/dist/button.d.ts.map +1 -1
  14. package/dist/button.js +1 -2
  15. package/dist/checkbox.d.ts +0 -1
  16. package/dist/checkbox.d.ts.map +1 -1
  17. package/dist/checkbox.js +1 -1
  18. package/dist/checkbox.js.map +1 -1
  19. package/dist/{colour-picker-0sgAha1T.js → colour-picker-C3Ag4uh-.js} +15 -17
  20. package/dist/colour-picker-C3Ag4uh-.js.map +1 -0
  21. package/dist/colour-picker.d.ts +1 -1
  22. package/dist/colour-picker.js +1 -1
  23. package/dist/crumbs.d.ts +5 -2
  24. package/dist/crumbs.d.ts.map +1 -1
  25. package/dist/crumbs.js +45 -20
  26. package/dist/crumbs.js.map +1 -1
  27. package/dist/data-display.d.ts +1 -2
  28. package/dist/data-display.d.ts.map +1 -1
  29. package/dist/data-display.js +25 -23
  30. package/dist/data-display.js.map +1 -1
  31. package/dist/{data-provider-DgI909FP.js → data-provider-35TyWclX.js} +2 -2
  32. package/dist/data-provider-35TyWclX.js.map +1 -0
  33. package/dist/{decorate-DdjvVHS-.js → decorate-VRK8rslU.js} +2 -2
  34. package/dist/{decorate-DdjvVHS-.js.map → decorate-VRK8rslU.js.map} +1 -1
  35. package/dist/{defaults-C3b9OWJD.js → defaults-DcE8RQJc.js} +19 -1
  36. package/dist/defaults-DcE8RQJc.js.map +1 -0
  37. package/dist/editable-label.d.ts +1 -2
  38. package/dist/editable-label.d.ts.map +1 -1
  39. package/dist/editable-label.js +1 -1
  40. package/dist/editable-label.js.map +1 -1
  41. package/dist/{hex-editor-WZrjRtvL.js → hex-editor-Bk6rxhfg.js} +9 -11
  42. package/dist/hex-editor-Bk6rxhfg.js.map +1 -0
  43. package/dist/{hex-editor-CMIxtNgT.d.ts → hex-editor-Caq8vNQk.d.ts} +2 -3
  44. package/dist/hex-editor-Caq8vNQk.d.ts.map +1 -0
  45. package/dist/hex.d.ts +1 -1
  46. package/dist/hex.js +1 -1
  47. package/dist/highlight-B-eQrhhb.js.map +1 -1
  48. package/dist/{icon-Ndo40kNO.js → icon-B22XVlCt.js} +6 -4
  49. package/dist/{icon-Ndo40kNO.js.map → icon-B22XVlCt.js.map} +1 -1
  50. package/dist/{icon-Bd5BiU4b.d.ts → icon-DpA9x2Ve.d.ts} +2 -3
  51. package/dist/icon-DpA9x2Ve.d.ts.map +1 -0
  52. package/dist/icons.d.ts +2 -2
  53. package/dist/icons.js +2 -2
  54. package/dist/{incr-search-CeERfijK.js → incr-search-2pz21xtR.js} +9 -6
  55. package/dist/incr-search-2pz21xtR.js.map +1 -0
  56. package/dist/incr-search.d.ts +1 -1
  57. package/dist/incr-search.js +1 -1
  58. package/dist/{index-CowKi2mo.d.ts → index-BeuCXtiO.d.ts} +3 -4
  59. package/dist/index-BeuCXtiO.d.ts.map +1 -0
  60. package/dist/{index-D87kRcEs.d.ts → index-BtGFYfaK.d.ts} +2 -1
  61. package/dist/index-BtGFYfaK.d.ts.map +1 -0
  62. package/dist/{index-s_IhSnwc.d.ts → index-CoqtMSd9.d.ts} +6 -4
  63. package/dist/index-CoqtMSd9.d.ts.map +1 -0
  64. package/dist/{index-9fGVAg1d.d.ts → index-Cxwxtj6g.d.ts} +3 -3
  65. package/dist/index-Cxwxtj6g.d.ts.map +1 -0
  66. package/dist/index-D_ftz_IT.d.ts +184 -0
  67. package/dist/index-D_ftz_IT.d.ts.map +1 -0
  68. package/dist/{index-_RTQSKHi.d.ts → index-DfEkTGvT.d.ts} +11 -11
  69. package/dist/index-DfEkTGvT.d.ts.map +1 -0
  70. package/dist/index.d.ts +167 -29
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +712 -2970
  73. package/dist/index.js.map +1 -1
  74. package/dist/keyboard-B5xD7Fz-.js +36 -0
  75. package/dist/keyboard-B5xD7Fz-.js.map +1 -0
  76. package/dist/{labelled-input-base-ORb1rGq6.d.ts → labelled-input-base-DiTme1JO.d.ts} +1 -2
  77. package/dist/labelled-input-base-DiTme1JO.d.ts.map +1 -0
  78. package/dist/{labelled-input-base-9K_w3oLj.js → labelled-input-base-hoKGwyKT.js} +2 -2
  79. package/dist/{labelled-input-base-9K_w3oLj.js.map → labelled-input-base-hoKGwyKT.js.map} +1 -1
  80. package/dist/labelled-radial-input.d.ts +5 -4
  81. package/dist/labelled-radial-input.d.ts.map +1 -1
  82. package/dist/labelled-radial-input.js +7 -3
  83. package/dist/labelled-radial-input.js.map +1 -1
  84. package/dist/labelled-range-input.d.ts +1 -1
  85. package/dist/labelled-range-input.js +27 -3
  86. package/dist/labelled-range-input.js.map +1 -1
  87. package/dist/led.d.ts +1 -2
  88. package/dist/led.d.ts.map +1 -1
  89. package/dist/led.js +1 -1
  90. package/dist/led.js.map +1 -1
  91. package/dist/{menu-vjoiHZ13.js → menu-g6yd7ddN.js} +8 -9
  92. package/dist/menu-g6yd7ddN.js.map +1 -0
  93. package/dist/{menu-item-COx-Azgj.d.ts → menu-item-DSyf9f_L.d.ts} +4 -4
  94. package/dist/menu-item-DSyf9f_L.d.ts.map +1 -0
  95. package/dist/{menu-item-BrIuORYD.js → menu-item-NUKwJ4s5.js} +3 -4
  96. package/dist/{menu-item-BrIuORYD.js.map → menu-item-NUKwJ4s5.js.map} +1 -1
  97. package/dist/menu.d.ts +2 -2
  98. package/dist/menu.js +2 -2
  99. package/dist/miller.d.ts +8 -5
  100. package/dist/miller.d.ts.map +1 -1
  101. package/dist/miller.js +22 -24
  102. package/dist/miller.js.map +1 -1
  103. package/dist/narrowed-text.d.ts +7 -3
  104. package/dist/narrowed-text.d.ts.map +1 -1
  105. package/dist/narrowed-text.js +73 -47
  106. package/dist/narrowed-text.js.map +1 -1
  107. package/dist/panel.d.ts +1 -1
  108. package/dist/panel.d.ts.map +1 -1
  109. package/dist/panel.js +2 -2
  110. package/dist/panel.js.map +1 -1
  111. package/dist/plots.d.ts +2 -2
  112. package/dist/plots.js +1 -1
  113. package/dist/polar-pad.d.ts +15 -3
  114. package/dist/polar-pad.d.ts.map +1 -1
  115. package/dist/polar-pad.js +64 -11
  116. package/dist/polar-pad.js.map +1 -1
  117. package/dist/{radial-input-CpQPs1Mp.d.ts → radial-input-BhZeyyP-.d.ts} +6 -4
  118. package/dist/radial-input-BhZeyyP-.d.ts.map +1 -0
  119. package/dist/{radial-input-DZ7eQCcM.js → radial-input-DxCrt_NE.js} +41 -19
  120. package/dist/radial-input-DxCrt_NE.js.map +1 -0
  121. package/dist/radial-input.d.ts +1 -1
  122. package/dist/radial-input.js +1 -1
  123. package/dist/range-input.d.ts +15 -4
  124. package/dist/range-input.d.ts.map +1 -1
  125. package/dist/range-input.js +23 -2
  126. package/dist/range-input.js.map +1 -1
  127. package/dist/range.d.ts +15 -4
  128. package/dist/range.d.ts.map +1 -1
  129. package/dist/range.js +23 -2
  130. package/dist/range.js.map +1 -1
  131. package/dist/selecthorizontal.d.ts +1 -2
  132. package/dist/selecthorizontal.d.ts.map +1 -1
  133. package/dist/selecthorizontal.js +1 -1
  134. package/dist/selecthorizontal.js.map +1 -1
  135. package/dist/slider-input-DFpG23bS.js +1592 -0
  136. package/dist/slider-input-DFpG23bS.js.map +1 -0
  137. package/dist/slider-input-TidGhvXt.d.ts +160 -0
  138. package/dist/slider-input-TidGhvXt.d.ts.map +1 -0
  139. package/dist/slider-input.d.ts +2 -0
  140. package/dist/slider-input.js +2 -0
  141. package/dist/snap-container.d.ts +1 -2
  142. package/dist/snap-container.d.ts.map +1 -1
  143. package/dist/snap-container.js +6 -5
  144. package/dist/snap-container.js.map +1 -1
  145. package/dist/split-layout.d.ts +1 -2
  146. package/dist/split-layout.d.ts.map +1 -1
  147. package/dist/split-layout.js +6 -4
  148. package/dist/split-layout.js.map +1 -1
  149. package/dist/style.css +1 -1
  150. package/dist/swipe.d.ts +12 -2
  151. package/dist/swipe.d.ts.map +1 -1
  152. package/dist/swipe.js +22 -3
  153. package/dist/swipe.js.map +1 -1
  154. package/dist/{tab-list-DLzb-m-I.d.ts → tab-list-BohmbvqF.d.ts} +14 -5
  155. package/dist/tab-list-BohmbvqF.d.ts.map +1 -0
  156. package/dist/tab-list-DhkVhRQc.js +597 -0
  157. package/dist/tab-list-DhkVhRQc.js.map +1 -0
  158. package/dist/tabs.d.ts +2 -2
  159. package/dist/tabs.js +1 -208
  160. package/dist/{tickled-controller-BjYCzGrU.d.ts → tickled-controller-BF2Ea0DE.d.ts} +2 -31
  161. package/dist/tickled-controller-BF2Ea0DE.d.ts.map +1 -0
  162. package/dist/tickled-styles-fNDdqf6l.js.map +1 -1
  163. package/dist/{timeline-2OFtN4Ta.js → timeline-B2fgDL4U.js} +37 -1438
  164. package/dist/timeline-B2fgDL4U.js.map +1 -0
  165. package/dist/timeline.d.ts +1 -1
  166. package/dist/timeline.js +1 -1
  167. package/dist/{tooltip-RGVIwHrZ.d.ts → tooltip-BlvBUQxx.d.ts} +3 -3
  168. package/dist/tooltip-BlvBUQxx.d.ts.map +1 -0
  169. package/dist/{tree-D84RUgFC.js → tree-BnvzhsAw.js} +8 -9
  170. package/dist/tree-BnvzhsAw.js.map +1 -0
  171. package/dist/{tree-component-BaCSPWg1.d.ts → tree-component-DCmmKZ4j.d.ts} +8 -124
  172. package/dist/tree-component-DCmmKZ4j.d.ts.map +1 -0
  173. package/dist/tree.d.ts +10 -4
  174. package/dist/tree.d.ts.map +1 -1
  175. package/dist/tree.js +1 -1
  176. package/dist/types-DO3gt5vg.d.ts +130 -0
  177. package/dist/types-DO3gt5vg.d.ts.map +1 -0
  178. package/dist/wheel-nudge-BlSCe_hD.js +86 -0
  179. package/dist/wheel-nudge-BlSCe_hD.js.map +1 -0
  180. package/dist/wheel-nudge-DgMTRYlh.d.ts +29 -0
  181. package/dist/wheel-nudge-DgMTRYlh.d.ts.map +1 -0
  182. package/dist/{xy-axis-BeWRMmbo.d.ts → xy-axis-5KhVTNoX.d.ts} +30 -7
  183. package/dist/xy-axis-5KhVTNoX.d.ts.map +1 -0
  184. package/dist/xy-axis-CxHC8z5E.js +1849 -0
  185. package/dist/xy-axis-CxHC8z5E.js.map +1 -0
  186. package/dist/xy-pad.d.ts +13 -2
  187. package/dist/xy-pad.d.ts.map +1 -1
  188. package/dist/xy-pad.js +47 -6
  189. package/dist/xy-pad.js.map +1 -1
  190. package/docs-user/README.md +2 -0
  191. package/docs-user/button.md +48 -0
  192. package/docs-user/narrowed-text.md +33 -1
  193. package/docs-user/notifier.md +131 -0
  194. package/docs-user/plots.md +61 -1
  195. package/docs-user/radial-input.md +2 -2
  196. package/docs-user/slider-input.md +673 -0
  197. package/docs-user/tabs.md +12 -14
  198. package/docs-user/user-catalog.md +69 -4
  199. package/docs-user/vertical-list.md +75 -7
  200. package/package.json +23 -20
  201. package/dist/colour-C3MQIjFJ-vRCdr8W-.js +0 -3732
  202. package/dist/colour-C3MQIjFJ-vRCdr8W-.js.map +0 -1
  203. package/dist/colour-picker-0sgAha1T.js.map +0 -1
  204. package/dist/data-provider-DgI909FP.js.map +0 -1
  205. package/dist/defaults-C3b9OWJD.js.map +0 -1
  206. package/dist/dist-CA13FvMn.js +0 -980
  207. package/dist/dist-CA13FvMn.js.map +0 -1
  208. package/dist/hex-editor-CMIxtNgT.d.ts.map +0 -1
  209. package/dist/hex-editor-WZrjRtvL.js.map +0 -1
  210. package/dist/icon-Bd5BiU4b.d.ts.map +0 -1
  211. package/dist/incr-search-CeERfijK.js.map +0 -1
  212. package/dist/index-9fGVAg1d.d.ts.map +0 -1
  213. package/dist/index-CowKi2mo.d.ts.map +0 -1
  214. package/dist/index-D87kRcEs.d.ts.map +0 -1
  215. package/dist/index-DgXpCg_G.d.ts +0 -1244
  216. package/dist/index-DgXpCg_G.d.ts.map +0 -1
  217. package/dist/index-_RTQSKHi.d.ts.map +0 -1
  218. package/dist/index-s_IhSnwc.d.ts.map +0 -1
  219. package/dist/keyboard-CimiEskD.js +0 -20
  220. package/dist/keyboard-CimiEskD.js.map +0 -1
  221. package/dist/labelled-input-base-ORb1rGq6.d.ts.map +0 -1
  222. package/dist/menu-item-COx-Azgj.d.ts.map +0 -1
  223. package/dist/menu-vjoiHZ13.js.map +0 -1
  224. package/dist/radial-input-CpQPs1Mp.d.ts.map +0 -1
  225. package/dist/radial-input-DZ7eQCcM.js.map +0 -1
  226. package/dist/tab-list-DLzb-m-I.d.ts.map +0 -1
  227. package/dist/tabs.js.map +0 -1
  228. package/dist/tickled-controller-BjYCzGrU.d.ts.map +0 -1
  229. package/dist/timeline-2OFtN4Ta.js.map +0 -1
  230. package/dist/tooltip-RGVIwHrZ.d.ts.map +0 -1
  231. package/dist/tree-D84RUgFC.js.map +0 -1
  232. package/dist/tree-component-BaCSPWg1.d.ts.map +0 -1
  233. package/dist/types-DSfbtHs3.d.ts +0 -8
  234. package/dist/types-DSfbtHs3.d.ts.map +0 -1
  235. package/dist/xy-axis-BeWRMmbo.d.ts.map +0 -1
  236. package/dist/xy-axis-no0OL_O1.js +0 -7893
  237. package/dist/xy-axis-no0OL_O1.js.map +0 -1
  238. /package/bundle/{chunk-D7D4PA-g.js → rolldown-runtime-D7D4PA-g.js} +0 -0
  239. /package/dist/{chunk-D7D4PA-g.js → rolldown-runtime-D7D4PA-g.js} +0 -0
package/docs-user/tabs.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  A complete tabbed interface system using several coordinated components:
4
4
 
5
- - **`ixfx-tab-layout`** — Layout wrapper (minimal)
6
- - **`ixfx-tab-layout-item`** — Individual tab item within layout
7
5
  - **`ixfx-tab-list`** — Tab header bar with tab buttons
8
6
  - **`ixfx-tab-list-item`** — Individual tab button
9
7
  - **`ixfx-tab-panel`** — Content panel for a single tab
@@ -12,17 +10,15 @@ A complete tabbed interface system using several coordinated components:
12
10
  ## Basic usage
13
11
 
14
12
  ```html
15
- <ixfx-tab-layout>
16
- <ixfx-tab-list>
17
- <ixfx-tab-list-item id="tab-home" for="panel-home">Home</ixfx-tab-list-item>
18
- <ixfx-tab-list-item id="tab-profile" for="panel-profile">Profile</ixfx-tab-list-item>
19
- </ixfx-tab-list>
20
-
21
- <ixfx-tab-panels>
22
- <ixfx-tab-panel id="panel-home">Home content</ixfx-tab-panel>
23
- <ixfx-tab-panel id="panel-profile">Profile content</ixfx-tab-panel>
24
- </ixfx-tab-panels>
25
- </ixfx-tab-layout>
13
+ <ixfx-tab-list>
14
+ <ixfx-tab-list-item id="tab-home" for="panel-home">Home</ixfx-tab-list-item>
15
+ <ixfx-tab-list-item id="tab-profile" for="panel-profile">Profile</ixfx-tab-list-item>
16
+ </ixfx-tab-list>
17
+
18
+ <ixfx-tab-panels>
19
+ <ixfx-tab-panel id="panel-home">Home content</ixfx-tab-panel>
20
+ <ixfx-tab-panel id="panel-profile">Profile content</ixfx-tab-panel>
21
+ </ixfx-tab-panels>
26
22
  ```
27
23
 
28
24
  Wire them together:
@@ -47,13 +43,15 @@ Manages tab selection and keyboard navigation.
47
43
  |---------------------|-----------------------------------|----------------|----------------------------------|
48
44
  | `orientation` | `'horizontal' \| 'vertical-stack' \| 'vertical-side'` | `'horizontal'` | Layout direction |
49
45
  | `flip` | `boolean` | `false` | Flip indicator to opposite side |
50
- | `scrollable` | `boolean` | `false` | Enable scroll overflow |
46
+ | `scrollable` | `boolean` | `false` | Enable scroll overflow. When set, vertical mousewheel on horizontal lists scrolls horizontally (and vice-versa for vertical lists). |
47
+ | `drag-mode` | `'off' \| 'reorder'` | `'off'` | Pointer-driven reordering within the list (sets `grab` cursor on items) |
51
48
 
52
49
  ### Events
53
50
 
54
51
  | Event | Detail | Description |
55
52
  |----------|------------------------------------------------------|---------------------------|
56
53
  | `change` | `{ previous, selected, for }` | Tab selection changed |
54
+ | `reorder` | `{ id, fromIndex, toIndex }` | Tab reordered (only fired when `drag-mode="reorder"`). Fires after the DOM has been updated. Press <kbd>Esc</kbd> or receive a `pointercancel` while dragging to abort — no `reorder` event fires in that case. |
57
55
 
58
56
  ### Methods
59
57
 
@@ -30,12 +30,33 @@ A circular input control for selecting values in a rotational manner. Ideal for
30
30
  ### ixfx-ac-text
31
31
  An autocomplete text input that suggests options as the user type. Perfect for search boxes, tag entry, or any field where you want to assist users with predefined options.
32
32
 
33
+ ### ixfx-ac-token
34
+ A token/tag input with per-token autocomplete, where committed tokens appear as inline chips and a suggestion popup follows the typing cursor. Ideal for email recipient fields, tag pickers, or any multi-value entry with per-value suggestions.
35
+
33
36
  ### ixfx-narrowed-text
34
37
  A specialized text input that constrains input length and provides visual feedback about remaining capacity. Use for fields with strict character limits like tweet composition or SMS messages.
35
38
 
36
39
  ### ixfx-editable-label
37
40
  A label that becomes an inline editor when clicked or focused. Useful for in-place editing of list items, card titles, or any display text that users might need to modify.
38
41
 
42
+ ### ixfx-editable-number
43
+ A numeric label that combines inline text editing with pointer-drag-to-adjust (Ableton-style), optional min/max clamping, step snapping, and a fill-bar visualisation. Use for mixing-console-style numeric controls where both typing and dragging are appropriate.
44
+
45
+ ### ixfx-range-input
46
+ A label-free, fully styled range slider wrapping the native `<input type="range">`. Supports horizontal and vertical orientations, custom thumb shapes, gradient fills, and an optional value tooltip. Use as a drop-in replacement for native range inputs when you need consistent theming.
47
+
48
+ ### ixfx-slider-input
49
+ A linear SVG-based slider with horizontal/vertical orientations, single/dual/triple value modes, and triangle/needle/dot markers. Use for audio-mixer style multi-handle sliders, threshold selectors, or any interface requiring precise linear control.
50
+
51
+ ### ixfx-radial-input
52
+ A rotary dial input rendered as a flattened arc SVG, inspired by music production interfaces. Responds to drag and keyboard input. Use as a building block for custom rotary controls or combine with `ixfx-editable-label` via `ixfx-labelled-radial-input`.
53
+
54
+ ### ixfx-swipe
55
+ A touch-friendly swipe/nudge component that produces a value in [-1, 1] based on tap-and-drag distance, emitted only on pointer release. Use as a compact gesture control for audio scrubbing, video seeking, or any value where a spring-back gesture is appropriate.
56
+
57
+ ### ixfx-vertical-list
58
+ A scrollable vertical list of items with selection, keyboard navigation, and incremental search. Supports plain `<li>` items in HTML or rich custom elements added programmatically. Use wherever you need a list with first-class keyboard and selection support.
59
+
39
60
  ### ixfx-color-picker
40
61
  A comprehensive color selection tool with multiple modes (hue/saturation/lightness, red/green/blue, etc.) and support for saving custom colors. Use whenever users need to select or adjust colors.
41
62
 
@@ -53,9 +74,21 @@ A tabbed interface for organizing content into separate views. Use when you have
53
74
  ### ixfx-tab-panel
54
75
  Individual panels that work with the ixfx-tabs component to create tabbed interfaces.
55
76
 
77
+ ### ixfx-tab-panels
78
+ A container that manages a collection of `ixfx-tab-panel` children and exposes a `selectPanel()` method to switch between them. Pair with `ixfx-tab-list` for a complete tabbed interface.
79
+
80
+ ### ixfx-tab-list
81
+ The header bar of a tabbed interface, holding `ixfx-tab-list-item` buttons and emitting a `change` event when the active tab changes. Pair with `ixfx-tab-panels` for a complete tabbed interface.
82
+
83
+ ### ixfx-tab-list-item
84
+ Individual tab buttons used inside `ixfx-tab-list`. Use the `for` attribute to associate each button with the id of its corresponding `ixfx-tab-panel`.
85
+
56
86
  ### ixfx-data-display
57
87
  A flexible component for presenting various types of data with consistent formatting. Use for showing metrics, status information, or any structured data that benefits from standardized presentation.
58
88
 
89
+ ### ixfx-transitory-label
90
+ An inline text label that animates between values instead of changing instantly, with fade, slide-up, and other transition effects. Use for status readouts, mode indicators, or any text that benefits from smooth value transitions rather than abrupt updates.
91
+
59
92
  ## Navigation Components
60
93
 
61
94
  ### ixfx-menu
@@ -76,6 +109,15 @@ A hierarchical tree view component for displaying nested data structures. Perfec
76
109
  ### ixfx-crumb-navigation
77
110
  Similar to breadcrumb navigation but with a more compact representation focused on the immediate path context.
78
111
 
112
+ ### ixfx-crumb-path
113
+ A path-style breadcrumb (e.g. `/users/jane/projects`) with editable path segments and autocomplete dropdowns. Supports lazy-loaded sibling paths. Use for file paths, URL navigation, or any address-bar-style interface where segments can be edited inline.
114
+
115
+ ### ixfx-miller
116
+ A Miller column component that displays hierarchical data as multiple vertical columns (like macOS Finder or email clients). Each column shows the children of the selected item in the previous column. Use for navigating deeply nested data with persistent visibility of the path.
117
+
118
+ ### ixfx-grouped-item-lister
119
+ A meta-component that renders a typed item list using any sub-component you supply. Items can be displayed in a single sub-component (ungrouped mode) or split into labelled groups, each with its own sub-component (grouped mode). Use for categorised lists, filtered views, or any list that needs both grouping and rich item rendering.
120
+
79
121
  ## Layout Components
80
122
 
81
123
  ### ixfx-split-layout
@@ -110,6 +152,15 @@ A component for representing and manipulating numerical ranges with visual handl
110
152
  ### ixfx-range-multi
111
153
  An extension of the range component that allows multiple non-overlapping ranges to be selected simultaneously. Ideal for selecting multiple time segments or value ranges.
112
154
 
155
+ ### ixfx-plot-multi-axis
156
+ A multi-series plot that renders several named 1D data streams simultaneously with per-series colours. Use for comparing multiple sensor readings, multi-track audio visualisation, or any scenario where several signals need to share the same axes.
157
+
158
+ ### ixfx-plot-histogram
159
+ A histogram plot that bins buffered values into buckets over the observed (or fixed) data range, with no time or sequence axis. Use for value distributions, density estimation, or any scenario where the shape of a dataset matters more than its order.
160
+
161
+ ### ixfx-hex-editor
162
+ A hex editor for inspecting and editing binary data, with configurable columns, ASCII/Hex/Offset columns, byte-level selection, drag-to-edit values, undo/redo, and colour-scheme options. Use for binary file inspection, debuggers, or any tool that needs to view or modify raw bytes.
163
+
113
164
  ## Utility Components
114
165
 
115
166
  ### ixfx-icon
@@ -124,6 +175,9 @@ A simple indicator light component that can show on/off states or various colors
124
175
  ### ixfx-horizontal-selector
125
176
  A compact horizontal control for selecting from a set of options. Use when you need a more space-efficient alternative to radio groups or dropdowns.
126
177
 
178
+ ### ixfx-incr-search
179
+ Incremental (type-ahead) search utilities for filtering data collections or DOM-backed lists in real time. Provides controllers for plain lists, tree components, and Miller columns, with built-in highlighting and keyboard navigation. Use to add fast type-ahead filtering to any list, tree, or column-based interface.
180
+
127
181
  ## Component Selection Guidelines
128
182
 
129
183
  When choosing components for your application, consider these patterns:
@@ -131,22 +185,30 @@ When choosing components for your application, consider these patterns:
131
185
  ### For Forms and Settings
132
186
  - Use `ixfx-checkbox` for binary options
133
187
  - Use `ixfx-radio-group` for mutually exclusive choices
134
- - Use `ixfx-labelled-range-input` for numerical parameters
188
+ - Use `ixfx-labelled-range-input` for numerical parameters with labels
135
189
  - Use `ixfx-toggle-switch` for settings with clear on/off states
190
+ - Use `ixfx-range-input` or `ixfx-slider-input` for plain slider-style numeric entry
191
+ - Use `ixfx-editable-number` for values that benefit from both typing and dragging
136
192
  - Use `ixfx-panel` or `ixfx-panel-group` to organize related settings
137
193
 
138
194
  ### For Data Display
139
195
  - Use `ixfx-data-display` for consistent metric presentation
140
196
  - Use `ixfx-panel` as containers for grouped information
141
197
  - Use `ixfx-tabs` to separate different views of related data
142
- - Use visualization components (`ixfx-xy-pad`, `ixfx-single-axis`, etc.) for graphical data representation
198
+ - Use visualization components (`ixfx-xy-pad`, `ixfx-single-axis`, `ixfx-plot-multi-axis`, `ixfx-plot-histogram`, etc.) for graphical data representation
199
+ - Use `ixfx-transitory-label` for readouts that animate between values
143
200
 
144
201
  ### For Navigation and Selection
145
202
  - Use `ixfx-menu` for contextual actions
146
203
  - Use `ixfx-menu-bar` for primary application navigation
147
204
  - Use `ixfx-tree` for hierarchical data exploration
148
205
  - Use `ixfx-breadcrumb-navigation` to show location in hierarchies
149
- - Use `ixfx-ac-text` for assisted text entry with predefined options
206
+ - Use `ixfx-crumb-path` for path-style navigation with editable segments
207
+ - Use `ixfx-miller` for deeply nested data with persistent column visibility
208
+ - Use `ixfx-vertical-list` for selectable, keyboard-navigable lists
209
+ - Use `ixfx-grouped-item-lister` for typed, optionally grouped item lists
210
+ - Use `ixfx-ac-text` for assisted single-value entry with predefined options
211
+ - Use `ixfx-ac-token` for multi-value tag/recipient entry with per-token suggestions
150
212
 
151
213
  ### For Layout and Structure
152
214
  - Use `ixfx-split-layout` for adjustable panes
@@ -156,9 +218,12 @@ When choosing components for your application, consider these patterns:
156
218
 
157
219
  ### For Interactive Controls
158
220
  - Use `ixfx-xy-pad` for 2D parameter control
159
- - Use `ixfx-labelled-radial-input` for circular parameters
221
+ - Use `ixfx-labelled-radial-input` for labelled rotary parameters
222
+ - Use `ixfx-radial-input` for bare rotary dial controls
160
223
  - Use `ixfx-range` or `ixfx-range-multi` for value ranges
224
+ - Use `ixfx-swipe` for spring-back gesture controls
161
225
  - Use `ixfx-color-picker` for comprehensive color selection
226
+ - Use `ixfx-hex-editor` for inspecting or editing raw binary data
162
227
 
163
228
  This catalog represents the core components available in the ixfx library. Each component is designed to work together through a shared theming system and consistent interaction patterns, allowing you to build cohesive interfaces with minimal effort.
164
229
 
@@ -9,12 +9,13 @@ A scrollable vertical list of items with selection, keyboard navigation, and inc
9
9
  1. [Quick start](#quick-start)
10
10
  2. [Item types](#item-types)
11
11
  3. [Properties](#properties)
12
- 4. [Selection](#selection)
13
- 5. [Events](#events)
14
- 6. [Keyboard navigation](#keyboard-navigation)
15
- 7. [Incremental search](#incremental-search)
16
- 8. [CSS variables](#css-variables)
17
- 9. [CSS parts](#css-parts)
12
+ 4. [Custom checkbox](#custom-checkbox)
13
+ 5. [Selection](#selection)
14
+ 6. [Events](#events)
15
+ 7. [Keyboard navigation](#keyboard-navigation)
16
+ 8. [Incremental search](#incremental-search)
17
+ 9. [CSS variables](#css-variables)
18
+ 10. [CSS parts](#css-parts)
18
19
 
19
20
  ---
20
21
 
@@ -115,6 +116,7 @@ To reflect selection state inside the custom element's shadow DOM, target the `:
115
116
  | `selectionMode` / `selection-mode` | `'none' \| 'single' \| 'multiple'` | `'single'` | Which items can be selected simultaneously |
116
117
  | `interactionMode` / `interaction-mode` | `ListInteractionMode` | `'standard'` | How gestures map to selection changes (see table below) |
117
118
  | `filterPredicate` | `((el: Element) => boolean) \| undefined` | `undefined` | External filter; only items returning `true` are shown |
119
+ | `checkboxRenderer` | `((checked: boolean) => unknown) \| undefined` | `undefined` | Custom content for the checkbox in `checked` mode. See [Custom checkbox](#custom-checkbox) |
118
120
 
119
121
  Switching `interactionMode` always clears the current selection.
120
122
 
@@ -125,11 +127,63 @@ Switching `interactionMode` always clears the current selection.
125
127
  | `'implicit'` | Click always replaces selection. No modifier support. |
126
128
  | `'standard'` | Plain click replaces selection; Ctrl/Cmd+click toggles; Shift+click range-selects (multiple mode only); Cmd+A selects all |
127
129
  | `'vscode'` | Like `standard` for clicks; Shift+Arrow extends the range from the keyboard anchor |
128
- | `'checked'` | Checkboxes on every `<li>` row; checkbox click (or Space) toggles; body clicks do nothing. Custom elements show a left-border indicator instead of a checkbox |
130
+ | `'checked'` | Checkbox column on the left of every row; only that column is clickable and it spans the full row height so a tall card can still be toggled with a single click on the left; Space toggles the focused row. See [Custom checkbox](#custom-checkbox) for styling |
129
131
  | `'manual'` | No automatic selection; drive state entirely via `select()` / `deselect()` / `clearSelection()` |
130
132
 
131
133
  ---
132
134
 
135
+ ## Custom checkbox
136
+
137
+ In `checked` mode every row gets a checkbox column on the left. The column is always a **full-height click target** (the wrapper uses `align-self: stretch`), so a single click anywhere on the left side of a tall card toggles it — you never have to precisely hit a small checkbox. Clicks on the row body (the text or custom card content) do **not** toggle, and the cursor is `default` there so the affordance is clear.
138
+
139
+ By default the column contains a native `<input type="checkbox">`. The visible square is small, but the entire column (~20–24px wide, full row height) is clickable.
140
+
141
+ ### Subtle style — `checkboxRenderer`
142
+
143
+ Set `checkboxRenderer` to a function that returns a Lit template. The function receives the row's current `checked` state. This is what enables the *subtle* style: render an empty template when unchecked and a translucent mark when checked.
144
+
145
+ ```typescript
146
+ import { html } from 'lit';
147
+ import type { VerticalListElement } from '@ixfx/components';
148
+
149
+ const list = document.querySelector<VerticalListElement>('#my-list')!;
150
+ list.interactionMode = 'checked';
151
+
152
+ // Nothing when unchecked; a translucent tick when checked
153
+ list.checkboxRenderer = (checked) => checked
154
+ ? html`<svg viewBox="0 0 16 16" width="14" height="14"
155
+ fill="none" stroke="currentColor" stroke-width="2"
156
+ stroke-linecap="round" stroke-linejoin="round"
157
+ style="opacity:0.5">
158
+ <polyline points="3,8 7,12 13,4" />
159
+ </svg>`
160
+ : html``;
161
+ ```
162
+
163
+ Because the wrapper still spans the full row height and owns the click handler, the empty unchecked area is just as clickable as the visible tick — even though there is no border, background, or other visual indicator of where the column is.
164
+
165
+ ### How it works under the hood
166
+
167
+ In `checked` mode each row has a `<span class="ixfx-list-checkbox" role="checkbox" part="checkbox">` prepended as the first child:
168
+
169
+ - When `checkboxRenderer` is set, your template is rendered into the span (via lit's `render()`) and re-rendered on every state change.
170
+ - When `checkboxRenderer` is **not** set, the span contains a real `<input type="checkbox">` with `pointer-events: none` — the span owns the click so there is exactly one toggle per click.
171
+ - `aria-checked` and `data-checked` on the span reflect the current state.
172
+ - `align-self: stretch` makes the span fill the row's cross-axis, giving you the full-height click target.
173
+
174
+ The element is also exposed as the `checkbox` CSS part, so you can tune the wrapper from outside:
175
+
176
+ ```css
177
+ ixfx-vertical-list::part(checkbox) {
178
+ width: 32px; /* a wider column */
179
+ color: var(--accent); /* recolour your rendered content */
180
+ }
181
+ ```
182
+
183
+ You can change `checkboxRenderer` at any time (e.g., swap the subtle SVG for an animated check); the wrapper element swaps in place and the renderer is re-applied.
184
+
185
+ ---
186
+
133
187
  ## Selection
134
188
 
135
189
  ### Programmatic API
@@ -328,6 +382,19 @@ list.filterPredicate = undefined;
328
382
  | `--item-bg-selected-tickled` | `rgba(21,101,192,1)` | Selected + cursor row background |
329
383
  | `--accent` | — | Accent colour (focus ring, search highlight, checkbox) |
330
384
  | `--transition` | `0.1s ease-out` | Transition timing for hover/selection changes |
385
+ | `--list-scrollbar-width` | `auto` | Maps to the `scrollbar-width` CSS property on the scroll container (`auto`, `thin`, `none`) |
386
+ | `--list-scrollbar-gutter` | `auto` | Maps to the `scrollbar-gutter` CSS property on the scroll container (`auto`, `stable`, `stable both-edges`) |
387
+ | `--list-scrollbar-color` | `auto` | Maps to the `scrollbar-color` CSS property on the scroll container (`auto` or a two-colour `thumb track` pair) |
388
+
389
+ The three `--list-scrollbar-*` variables are consumed by the shadow-DOM `<ul>` scroll container, so they can be set on any ancestor:
390
+
391
+ ```css
392
+ ixfx-vertical-list {
393
+ --list-scrollbar-width: thin;
394
+ --list-scrollbar-gutter: stable;
395
+ --list-scrollbar-color: var(--accent) var(--surface-2);
396
+ }
397
+ ```
331
398
 
332
399
  ---
333
400
 
@@ -337,6 +404,7 @@ list.filterPredicate = undefined;
337
404
  |---|---|
338
405
  | `list` | The `<ul>` scroll container |
339
406
  | `search-overlay` | The floating search input overlay |
407
+ | `checkbox` | The per-row checkbox column wrapper in `checked` mode (always present; hosts the native `<input>` or the user-rendered content) |
340
408
 
341
409
  Use `::part()` to style these from outside the component's shadow DOM:
342
410
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ixfx/components",
3
3
  "type": "module",
4
- "version": "0.4.3",
4
+ "version": "0.5.0",
5
5
  "description": "",
6
6
  "author": "",
7
7
  "license": "ISC",
@@ -33,8 +33,10 @@
33
33
  "scripts": {
34
34
  "typecheck": "tsc --noEmit",
35
35
  "start": "vite serve",
36
+ "dev": "vite serve",
36
37
  "lint": "eslint",
37
38
  "lint:fix": "eslint --fix",
39
+ "build:md": "node ./scripts/collate-docs.ts",
38
40
  "build": "tsdown",
39
41
  "rebuild": "rm -rf dist bundle && pnpm run build",
40
42
  "publish-prepare": "pnpm run rebuild && pnpm run typecheck && pnpm run lint",
@@ -43,29 +45,30 @@
43
45
  },
44
46
  "dependencies": {
45
47
  "@clinth/ui-commands": "1.1.0",
48
+ "@clinth/vcanvas": "0.0.3",
49
+ "@ixfx/arrays": "0.56.14",
50
+ "@ixfx/collections": "0.56.14",
51
+ "@ixfx/core": "0.56.14",
52
+ "@ixfx/dom": "0.56.14",
53
+ "@ixfx/flow": "0.56.14",
54
+ "@ixfx/geometry": "0.56.14",
55
+ "@ixfx/modulation": "0.56.14",
56
+ "@ixfx/numbers": "0.56.14",
57
+ "@ixfx/visual": "0.56.14",
46
58
  "fzf": "0.5.2",
47
59
  "lit": "3.3.3"
48
60
  },
49
61
  "devDependencies": {
50
- "@antfu/eslint-config": "^9.0.0",
51
- "@clinth/vcanvas": "0.0.3",
52
- "@ixfx/arrays": "0.56.13",
53
- "@ixfx/collections": "0.56.13",
54
- "@ixfx/core": "0.56.13",
55
- "@ixfx/dom": "0.56.13",
56
- "@ixfx/flow": "0.56.13",
57
- "@ixfx/geometry": "0.56.13",
58
- "@ixfx/modulation": "0.56.13",
59
- "@ixfx/numbers": "0.56.13",
60
- "@ixfx/visual": "0.56.13",
61
- "@tsdown/css": "0.22.1",
62
- "eslint": "10.4.1",
62
+ "@antfu/eslint-config": "^9.3.0",
63
+ "@tsdown/css": "0.22.14",
64
+ "@typescript/native": "npm:typescript@^7.0.2",
65
+ "eslint": "10.8.1",
63
66
  "eslint-plugin-format": "2.0.1",
64
- "globals": "17.6.0",
65
- "knip": "6.14.2",
66
- "tsdown": "0.22.1",
67
- "typescript": "6.0.3",
68
- "typescript-eslint": "8.60.0",
69
- "vite": "8.0.14"
67
+ "globals": "17.9.0",
68
+ "knip": "6.32.0",
69
+ "tsdown": "0.22.14",
70
+ "typescript": "npm:@typescript/typescript6@6.0.2",
71
+ "typescript-eslint": "8.66.0",
72
+ "vite": "8.2.1"
70
73
  }
71
74
  }