@fusion.dev/helix-headless 0.145.0 → 0.147.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 (343) hide show
  1. package/custom-elements.json +12286 -4281
  2. package/dist/accordion/item/accordion-item.d.ts +51 -18
  3. package/dist/accordion/item/accordion-item.js +45 -13
  4. package/dist/accordion/root/accordion-root.d.ts +16 -7
  5. package/dist/accordion/root/accordion-root.js +3 -3
  6. package/dist/announcement/root/announcement-root.d.ts +16 -6
  7. package/dist/announcement/root/announcement-root.js +37 -7
  8. package/dist/app-header/root/app-header-root.d.ts +7 -2
  9. package/dist/app-header/root/app-header-root.js +9 -1
  10. package/dist/app-header/sectioning.d.ts +3 -1
  11. package/dist/app-header/sectioning.js +3 -2
  12. package/dist/area-chart/root/area-chart-root.d.ts +18 -1
  13. package/dist/area-chart/root/area-chart-root.js +11 -3
  14. package/dist/avatar/group/avatar-group.d.ts +20 -14
  15. package/dist/avatar/group/avatar-group.js +17 -19
  16. package/dist/avatar/root/avatar-root.d.ts +31 -1
  17. package/dist/avatar/root/avatar-root.js +11 -1
  18. package/dist/badge/root/badge-root.d.ts +60 -7
  19. package/dist/badge/root/badge-root.js +89 -6
  20. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  21. package/dist/bar-chart/root/bar-chart-root.js +48 -20
  22. package/dist/bar-chart/stack.d.ts +25 -0
  23. package/dist/bar-chart/stack.js +27 -0
  24. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
  25. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
  26. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  27. package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
  28. package/dist/button/root/button-root.d.ts +50 -38
  29. package/dist/button/root/button-root.js +42 -53
  30. package/dist/button/submitter.d.ts +27 -0
  31. package/dist/button/submitter.js +25 -0
  32. package/dist/button-group/root/button-group-root.d.ts +2 -1
  33. package/dist/button-group/root/button-group-root.js +5 -1
  34. package/dist/canvas/node/canvas-node.d.ts +4 -3
  35. package/dist/canvas/node/canvas-node.js +3 -2
  36. package/dist/canvas/root/canvas-root.js +2 -2
  37. package/dist/card/root/card-root.d.ts +36 -4
  38. package/dist/card/root/card-root.js +29 -10
  39. package/dist/carousel/root/carousel-root.d.ts +43 -4
  40. package/dist/carousel/root/carousel-root.js +40 -12
  41. package/dist/carousel/stops.d.ts +20 -0
  42. package/dist/carousel/stops.js +30 -0
  43. package/dist/chat/message/chat-message.js +5 -4
  44. package/dist/chat/naming.d.ts +5 -1
  45. package/dist/chat/naming.js +4 -2
  46. package/dist/chat/root/chat-root.d.ts +40 -4
  47. package/dist/chat/root/chat-root.js +32 -6
  48. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  49. package/dist/checkbox/root/checkbox-root.js +18 -7
  50. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  51. package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
  52. package/dist/checkbox-group/select-all.d.ts +21 -0
  53. package/dist/checkbox-group/select-all.js +7 -0
  54. package/dist/code-block/highlight.d.ts +15 -0
  55. package/dist/code-block/highlight.js +4 -0
  56. package/dist/code-block/root/code-block-root.d.ts +79 -10
  57. package/dist/code-block/root/code-block-root.js +74 -5
  58. package/dist/color-input/root/color-input-root.d.ts +14 -0
  59. package/dist/color-input/root/color-input-root.js +17 -7
  60. package/dist/color-picker/channels.js +1 -2
  61. package/dist/color-picker/root/color-picker-root.d.ts +53 -16
  62. package/dist/color-picker/root/color-picker-root.js +155 -46
  63. package/dist/color-picker/wheel.d.ts +17 -0
  64. package/dist/color-picker/wheel.js +6 -0
  65. package/dist/combobox/root/combobox-root.d.ts +56 -0
  66. package/dist/combobox/root/combobox-root.js +92 -15
  67. package/dist/command/root/command-root.d.ts +19 -2
  68. package/dist/command/root/command-root.js +24 -23
  69. package/dist/copy-button/root/copy-button-root.d.ts +21 -1
  70. package/dist/copy-button/root/copy-button-root.js +16 -4
  71. package/dist/data-table/index.d.ts +1 -1
  72. package/dist/data-table/index.js +1 -1
  73. package/dist/data-table/keys.d.ts +6 -0
  74. package/dist/data-table/keys.js +14 -0
  75. package/dist/data-table/root/data-table-root.d.ts +27 -18
  76. package/dist/data-table/root/data-table-root.js +31 -57
  77. package/dist/data-table/tree.d.ts +16 -1
  78. package/dist/data-table/tree.js +2 -3
  79. package/dist/date-input/root/date-input-root.d.ts +11 -2
  80. package/dist/date-input/root/date-input-root.js +26 -12
  81. package/dist/date-picker/root/date-picker-root.d.ts +14 -9
  82. package/dist/date-picker/root/date-picker-root.js +33 -22
  83. package/dist/description-list/item/description-list-item.d.ts +18 -4
  84. package/dist/description-list/item/description-list-item.js +8 -4
  85. package/dist/dialog/description.js +15 -1
  86. package/dist/dialog/root/dialog-root.d.ts +8 -2
  87. package/dist/dialog/root/dialog-root.js +16 -1
  88. package/dist/divider/root/divider-root.d.ts +3 -0
  89. package/dist/divider/root/divider-root.js +2 -1
  90. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  91. package/dist/donut-chart/root/donut-chart-root.js +55 -1
  92. package/dist/donut-chart/slice-label.d.ts +35 -0
  93. package/dist/donut-chart/slice-label.js +11 -0
  94. package/dist/drawer/reveal.d.ts +8 -0
  95. package/dist/drawer/reveal.js +1 -0
  96. package/dist/drawer/root/drawer-root.d.ts +63 -2
  97. package/dist/drawer/root/drawer-root.js +75 -4
  98. package/dist/drilldown/item/drilldown-item.d.ts +21 -1
  99. package/dist/drilldown/item/drilldown-item.js +40 -5
  100. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  101. package/dist/drilldown/root/drilldown-root.js +22 -3
  102. package/dist/element-events.generated.js +35 -6
  103. package/dist/empty/root/empty-root.d.ts +34 -2
  104. package/dist/empty/root/empty-root.js +26 -4
  105. package/dist/file-input/root/file-input-root.d.ts +99 -8
  106. package/dist/file-input/root/file-input-root.js +120 -22
  107. package/dist/file-input/screen.d.ts +2 -1
  108. package/dist/file-input/status.d.ts +24 -0
  109. package/dist/file-input/status.js +10 -0
  110. package/dist/filter-input/chip/filter-chip.d.ts +23 -0
  111. package/dist/filter-input/chip/filter-chip.js +11 -2
  112. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  113. package/dist/filter-input/menu/filter-menu.js +12 -4
  114. package/dist/filter-input/root/filter-input-root.d.ts +38 -6
  115. package/dist/filter-input/root/filter-input-root.js +18 -28
  116. package/dist/filter-input/suggest.d.ts +28 -3
  117. package/dist/filter-input/suggest.js +18 -8
  118. package/dist/format-date/options.d.ts +3 -4
  119. package/dist/format-date/options.js +2 -2
  120. package/dist/format-date/root/format-date-root.d.ts +27 -17
  121. package/dist/format-date/root/format-date-root.js +27 -48
  122. package/dist/heatmap/root/buckets.d.ts +21 -0
  123. package/dist/heatmap/root/buckets.js +34 -0
  124. package/dist/heatmap/root/heatmap-root.d.ts +83 -11
  125. package/dist/heatmap/root/heatmap-root.js +104 -12
  126. package/dist/icon/index.d.ts +1 -1
  127. package/dist/icon/index.js +1 -1
  128. package/dist/icon/registry.d.ts +26 -1
  129. package/dist/icon/registry.js +12 -1
  130. package/dist/icon/root/icon-root.d.ts +25 -1
  131. package/dist/icon/root/icon-root.js +44 -12
  132. package/dist/icon/root/index.d.ts +1 -1
  133. package/dist/icon/root/index.js +1 -1
  134. package/dist/icon/settle.d.ts +7 -0
  135. package/dist/icon/settle.js +10 -0
  136. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  137. package/dist/image/root/image-root.d.ts +14 -1
  138. package/dist/image/root/image-root.js +7 -2
  139. package/dist/input/root/input-root.d.ts +34 -3
  140. package/dist/input/root/input-root.js +17 -4
  141. package/dist/kbd/keys.d.ts +29 -0
  142. package/dist/kbd/keys.js +52 -0
  143. package/dist/kbd/root/kbd-root.d.ts +52 -1
  144. package/dist/kbd/root/kbd-root.js +40 -47
  145. package/dist/legend/hidden-series.d.ts +10 -2
  146. package/dist/legend/hidden-series.js +5 -2
  147. package/dist/legend/root/legend-root.d.ts +77 -12
  148. package/dist/legend/root/legend-root.js +71 -17
  149. package/dist/lightbox/root/lightbox-root.d.ts +98 -10
  150. package/dist/lightbox/root/lightbox-root.js +153 -18
  151. package/dist/lightbox/zoom-controller.d.ts +59 -0
  152. package/dist/lightbox/zoom-controller.js +128 -0
  153. package/dist/lightbox/zoom.d.ts +24 -0
  154. package/dist/lightbox/zoom.js +18 -0
  155. package/dist/line-chart/root/line-chart-root.d.ts +38 -1
  156. package/dist/line-chart/root/line-chart-root.js +31 -3
  157. package/dist/list/item/list-item.d.ts +2 -0
  158. package/dist/list/item/list-item.js +11 -2
  159. package/dist/list/root/list-root.d.ts +70 -13
  160. package/dist/list/root/list-root.js +91 -13
  161. package/dist/list/selection.d.ts +54 -7
  162. package/dist/list/selection.js +32 -7
  163. package/dist/listbox/root/listbox-root.d.ts +44 -4
  164. package/dist/listbox/root/listbox-root.js +72 -34
  165. package/dist/loader/busy.d.ts +10 -0
  166. package/dist/loader/busy.js +11 -0
  167. package/dist/loader/root/loader-root.d.ts +9 -2
  168. package/dist/loader/root/loader-root.js +23 -3
  169. package/dist/megamenu/hand-over.d.ts +75 -0
  170. package/dist/megamenu/hand-over.js +67 -0
  171. package/dist/megamenu/root/megamenu-root.d.ts +80 -15
  172. package/dist/megamenu/root/megamenu-root.js +76 -19
  173. package/dist/menu/item/menu-item.d.ts +51 -2
  174. package/dist/menu/item/menu-item.js +50 -26
  175. package/dist/menu/root/menu-root.d.ts +17 -0
  176. package/dist/menu/root/menu-root.js +2 -2
  177. package/dist/meter/root/meter-root.d.ts +62 -1
  178. package/dist/meter/root/meter-root.js +38 -16
  179. package/dist/navigation/root/navigation-root.d.ts +2 -1
  180. package/dist/navigation/root/navigation-root.js +2 -2
  181. package/dist/notifications/root/notifications-root.d.ts +20 -4
  182. package/dist/notifications/root/notifications-root.js +30 -8
  183. package/dist/number-input/grain.d.ts +28 -0
  184. package/dist/number-input/grain.js +14 -0
  185. package/dist/number-input/root/number-input-root.d.ts +34 -9
  186. package/dist/number-input/root/number-input-root.js +31 -25
  187. package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
  188. package/dist/object-inspector/root/object-inspector-root.js +134 -92
  189. package/dist/object-inspector/rows.d.ts +18 -0
  190. package/dist/object-inspector/rows.js +33 -0
  191. package/dist/option/index.d.ts +1 -0
  192. package/dist/option/index.js +1 -0
  193. package/dist/option/root/option-root.d.ts +5 -3
  194. package/dist/option/separator/option-separator.d.ts +30 -0
  195. package/dist/option/separator/option-separator.js +21 -0
  196. package/dist/outline/root/outline-root.d.ts +30 -0
  197. package/dist/outline/root/outline-root.js +17 -13
  198. package/dist/pagination/size/pagination-size.d.ts +6 -0
  199. package/dist/pagination/size/pagination-size.js +5 -3
  200. package/dist/pin-input/code.d.ts +37 -0
  201. package/dist/pin-input/code.js +25 -0
  202. package/dist/pin-input/root/pin-input-root.d.ts +116 -115
  203. package/dist/pin-input/root/pin-input-root.js +163 -155
  204. package/dist/popover/hide-outside.d.ts +14 -0
  205. package/dist/popover/hide-outside.js +34 -0
  206. package/dist/popover/root/popover-root.d.ts +64 -8
  207. package/dist/popover/root/popover-root.js +67 -4
  208. package/dist/progress/root/progress-root.d.ts +47 -0
  209. package/dist/progress/root/progress-root.js +34 -16
  210. package/dist/qr-code/export.d.ts +45 -1
  211. package/dist/qr-code/export.js +28 -0
  212. package/dist/qr-code/name.d.ts +11 -0
  213. package/dist/qr-code/name.js +7 -0
  214. package/dist/qr-code/root/qr-code-root.d.ts +36 -11
  215. package/dist/qr-code/root/qr-code-root.js +58 -11
  216. package/dist/quote/marks.d.ts +8 -0
  217. package/dist/quote/marks.js +5 -0
  218. package/dist/quote/root/quote-root.d.ts +14 -2
  219. package/dist/quote/root/quote-root.js +23 -1
  220. package/dist/radio/group/radio-group.d.ts +15 -0
  221. package/dist/radio/root/radio-root.d.ts +6 -2
  222. package/dist/radio/root/radio-root.js +7 -2
  223. package/dist/rating/root/rating-root.d.ts +30 -12
  224. package/dist/rating/root/rating-root.js +27 -27
  225. package/dist/scatter-chart/fit.d.ts +15 -0
  226. package/dist/scatter-chart/fit.js +35 -0
  227. package/dist/scatter-chart/root/scatter-chart-root.d.ts +51 -1
  228. package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
  229. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  230. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  231. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  232. package/dist/scroll-area/scrollbar-controller.js +172 -0
  233. package/dist/scroll-area/scrollbar.d.ts +27 -8
  234. package/dist/scroll-area/scrollbar.js +10 -1
  235. package/dist/select/align.d.ts +47 -0
  236. package/dist/select/align.js +7 -0
  237. package/dist/select/root/select-root.d.ts +71 -0
  238. package/dist/select/root/select-root.js +78 -6
  239. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  240. package/dist/skeleton/root/skeleton-root.js +4 -2
  241. package/dist/skip-link/root/skip-link-root.js +2 -2
  242. package/dist/slider/root/slider-root.d.ts +59 -5
  243. package/dist/slider/root/slider-root.js +45 -3
  244. package/dist/sparkline/readings.d.ts +36 -0
  245. package/dist/sparkline/readings.js +36 -0
  246. package/dist/sparkline/root/sparkline-root.d.ts +121 -7
  247. package/dist/sparkline/root/sparkline-root.js +160 -26
  248. package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
  249. package/dist/speed-dial/item/speed-dial-item.js +2 -2
  250. package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
  251. package/dist/speed-dial/root/speed-dial-root.js +11 -3
  252. package/dist/splitter/root/splitter-root.d.ts +10 -12
  253. package/dist/splitter/root/splitter-root.js +211 -204
  254. package/dist/stat/root/stat-root.d.ts +14 -5
  255. package/dist/stat/root/stat-root.js +21 -5
  256. package/dist/steps/reach.d.ts +5 -0
  257. package/dist/steps/reach.js +3 -0
  258. package/dist/steps/root/steps-root.d.ts +56 -3
  259. package/dist/steps/root/steps-root.js +50 -6
  260. package/dist/steps/step/step.d.ts +8 -0
  261. package/dist/steps/step/step.js +8 -3
  262. package/dist/switch/root/switch-root.d.ts +10 -0
  263. package/dist/table/column/table-column.d.ts +6 -10
  264. package/dist/table/column/table-column.js +8 -20
  265. package/dist/table/root/table-root.d.ts +31 -10
  266. package/dist/table/root/table-root.js +14 -18
  267. package/dist/table/row/table-row.d.ts +24 -0
  268. package/dist/table/row/table-row.js +37 -1
  269. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  270. package/dist/tabs/panel/tab-panel.js +34 -5
  271. package/dist/tabs/root/tabs-root.d.ts +17 -3
  272. package/dist/tabs/root/tabs-root.js +1 -1
  273. package/dist/tabs/tab/tab.d.ts +5 -0
  274. package/dist/tabs/tab/tab.js +5 -2
  275. package/dist/tag/group/tag-group.d.ts +44 -5
  276. package/dist/tag/group/tag-group.js +60 -9
  277. package/dist/tag/root/tag-root.js +9 -2
  278. package/dist/textarea/root/textarea-root.d.ts +41 -2
  279. package/dist/textarea/root/textarea-root.js +39 -1
  280. package/dist/time-input/root/time-input-root.d.ts +10 -2
  281. package/dist/time-input/root/time-input-root.js +24 -13
  282. package/dist/time-picker/root/time-picker-root.d.ts +28 -17
  283. package/dist/time-picker/root/time-picker-root.js +18 -29
  284. package/dist/time-picker/wheel-name.d.ts +9 -0
  285. package/dist/time-picker/wheel-name.js +15 -0
  286. package/dist/timeline/group/timeline-group.js +2 -2
  287. package/dist/toast/item/toast-item.d.ts +16 -3
  288. package/dist/toast/item/toast-item.js +22 -6
  289. package/dist/toast/root/toast-root.d.ts +34 -4
  290. package/dist/toast/root/toast-root.js +74 -13
  291. package/dist/toast/words.d.ts +12 -0
  292. package/dist/toast/words.js +25 -0
  293. package/dist/toggle/group/toggle-group.d.ts +52 -7
  294. package/dist/toggle/group/toggle-group.js +58 -44
  295. package/dist/toggle/root/toggle-root.js +2 -4
  296. package/dist/toolbar/root/toolbar-root.d.ts +21 -5
  297. package/dist/toolbar/root/toolbar-root.js +52 -8
  298. package/dist/tooltip/root/tooltip-root.d.ts +20 -3
  299. package/dist/tooltip/root/tooltip-root.js +18 -1
  300. package/dist/tour/back.d.ts +10 -0
  301. package/dist/tour/back.js +8 -0
  302. package/dist/tour/root/tour-root.d.ts +45 -2
  303. package/dist/tour/root/tour-root.js +53 -8
  304. package/dist/tour/stop/tour-stop.d.ts +3 -0
  305. package/dist/tour/stop/tour-stop.js +3 -3
  306. package/dist/tree/item/tree-item.d.ts +7 -3
  307. package/dist/tree/item/tree-item.js +3 -0
  308. package/dist/tree/root/tree-root.d.ts +24 -3
  309. package/dist/tree/root/tree-root.js +32 -13
  310. package/dist/tree/selection.js +2 -15
  311. package/dist/trend/figure.d.ts +16 -0
  312. package/dist/trend/figure.js +8 -0
  313. package/dist/trend/root/trend-root.d.ts +83 -19
  314. package/dist/trend/root/trend-root.js +59 -8
  315. package/dist/video/media-events.d.ts +13 -18
  316. package/dist/video/media-events.js +1 -5
  317. package/dist/video/root/extra-controls.d.ts +12 -0
  318. package/dist/video/root/extra-controls.js +6 -2
  319. package/dist/video/root/video-root.d.ts +23 -6
  320. package/dist/video/root/video-root.js +19 -10
  321. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  322. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  323. package/dist/video-playlist/root/video-playlist-root.d.ts +17 -1
  324. package/dist/video-playlist/root/video-playlist-root.js +3 -0
  325. package/dist/virtual-list/fill.d.ts +11 -8
  326. package/dist/virtual-list/fill.js +10 -17
  327. package/dist/virtual-list/keys.d.ts +16 -7
  328. package/dist/virtual-list/keys.js +17 -6
  329. package/dist/virtual-list/plan.d.ts +65 -0
  330. package/dist/virtual-list/plan.js +27 -0
  331. package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
  332. package/dist/virtual-list/root/virtual-list-root.js +218 -51
  333. package/lint.json +1 -1
  334. package/package.json +8 -8
  335. package/types/jsx.d.ts +7441 -1458
  336. package/types/svelte.d.ts +1 -0
  337. package/types/vue.d.ts +1501 -326
  338. package/dist/chat/relative-clock.d.ts +0 -39
  339. package/dist/chat/relative-clock.js +0 -31
  340. package/dist/data-table/root/order.d.ts +0 -141
  341. package/dist/data-table/root/order.js +0 -76
  342. package/dist/tag/selection.d.ts +0 -10
  343. package/dist/tag/selection.js +0 -12
@@ -0,0 +1,21 @@
1
+ /** What the select-all helper reads from one box in the set. */
2
+ export interface SetBox {
3
+ /** Whether the box is checked. */
4
+ readonly checked: boolean;
5
+ /** Whether the box refuses a press, so select-all leaves it as it is. */
6
+ readonly disabled: boolean;
7
+ /** What the box submits when checked. */
8
+ readonly value: string;
9
+ }
10
+ /**
11
+ * What the select-all box shows: checked while every enabled box is checked,
12
+ * mixed while only some are, and clear while none is.
13
+ *
14
+ * A disabled box counts for nothing, because a press leaves it as it is. A
15
+ * set whose every box is disabled reads every box, so the select-all box still
16
+ * shows what the set holds.
17
+ */
18
+ export declare const selectAllState: (boxes: readonly SetBox[]) => {
19
+ checked: boolean;
20
+ indeterminate: boolean;
21
+ };
@@ -0,0 +1,7 @@
1
+ export const selectAllState = (boxes) => {
2
+ const enabled = boxes.filter((box) => !box.disabled);
3
+ const counted = enabled.length > 0 ? enabled : boxes;
4
+ const ticked = counted.filter((box) => box.checked).length;
5
+ const checked = counted.length > 0 && ticked === counted.length;
6
+ return { checked, indeterminate: ticked > 0 && !checked };
7
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The highlighted lines out of what a highlighter returned, without the
3
+ * `<pre>` and `<code>` around them that some highlighters write.
4
+ *
5
+ * Shiki's `codeToHtml` returns a whole block, `<pre class="shiki" tabindex="0"
6
+ * style="…"><code>…</code></pre>`. Drawn as given inside the block's own
7
+ * `<pre>`, that second `<pre>` sat 13px below the gutter's first number, and
8
+ * its `tabindex` was a second tab stop inside the block's scroller. Prism's
9
+ * `highlight` and highlight.js return the lines alone, which pass through
10
+ * unchanged.
11
+ *
12
+ * Only a wrapper around the whole markup is taken off, and only one. The block draws its own
13
+ * box and colors, so the wrapper's `style` and `class` go with it.
14
+ */
15
+ export declare const highlightedLines: (markup: string) => string;
@@ -0,0 +1,4 @@
1
+ export const highlightedLines = (markup) => {
2
+ const lines = /^\s*<pre\b[^>]*>\s*<code\b[^>]*>([\s\S]*)<\/code>\s*<\/pre>\s*$/i.exec(markup)?.[1];
3
+ return lines === undefined || /<\/?pre\b/i.test(lines) ? markup : lines;
4
+ };
@@ -17,8 +17,17 @@ import '../../copy-button/index.js';
17
17
  * Set `line-numbers` to number the lines in a gutter beside the code, hidden
18
18
  * from the accessibility tree and left out of a copy. Set `highlight` to a
19
19
  * function that turns the code into highlighted markup, such as one wrapping
20
- * Shiki or Prism, and the block draws what it returns; the code stays in the
21
- * slot, so the copy button and the page's own text are the code as written.
20
+ * Shiki or Prism, and the block draws what it returns; it is handed the
21
+ * block's `language`, so one function serves every block. The code stays in
22
+ * the slot, so the copy button and the page's own text are the code as
23
+ * written.
24
+ *
25
+ * Set `expandable` on a block whose height is capped, such as by
26
+ * `--code-block-max-block-size`, and a button under it shows every line and
27
+ * then fewer again, as a docs site's long example does. The button is drawn
28
+ * only while the cap hides something, says whether the block is expanded with
29
+ * `aria-expanded`, names the block it opens with `aria-controls`, and the block
30
+ * carries `:state(expanded)` while it is.
22
31
  *
23
32
  * Set `diff` to show a change. Put a unified diff, the output of `git diff` or
24
33
  * `diff -u`, in the same slot, and the block draws the lines it added and
@@ -50,6 +59,7 @@ import '../../copy-button/index.js';
50
59
  * @csspart copy-button - The inner button.
51
60
  * @csspart copy-live - The copy button's live region, which speaks while the button is pending.
52
61
  * @csspart copy-mark - The clipboard icon, and the check mark that replaces it after a copy.
62
+ * @csspart copy-spinner - The ring the copy button turns while it is pending.
53
63
  * @csspart copy-text - The words on that button, trimmed to their capitals and baseline.
54
64
  * @csspart copy-tooltip - The copy button's tooltip.
55
65
  * @csspart copy-tooltip-arrow - The tooltip's arrow, which points at the copy button.
@@ -61,6 +71,7 @@ import '../../copy-button/index.js';
61
71
  * @csspart copy-tooltip-left - The tooltip while it is left of the copy button. Applied with `copy-tooltip`.
62
72
  * @csspart copy-tooltip-right - The tooltip while it is right of the copy button. Applied with `copy-tooltip`.
63
73
  * @csspart copy-tooltip-top - The tooltip while it is above the copy button. Applied with `copy-tooltip`.
74
+ * @csspart expand - The button under a capped block that shows every line, and fewer again. Drawn when `expandable` is set and the cap hides something.
64
75
  * @csspart file - In a diff, one file's header and block.
65
76
  * @csspart filler - In a split diff, the empty row opposite a line the other side does not have.
66
77
  * @csspart frame - The code, and the copy button beside it where there is no header.
@@ -75,8 +86,14 @@ import '../../copy-button/index.js';
75
86
  * @csspart removed - In a diff, a line only the old version has, a `<del>`.
76
87
  * @csspart split - In a split diff, the two versions side by side.
77
88
  * @csspart text - In a diff, a line's code.
89
+ *
90
+ * @cssstate expanded - The expand button has shown every line of a capped block.
78
91
  */
79
92
  export declare class HelixHeadlessCodeBlock extends HelixElement {
93
+ /**
94
+ * The expand button's words while the block shows every line.
95
+ */
96
+ collapseLabel: string;
80
97
  /**
81
98
  * The copy button's name and tooltip text after a copy.
82
99
  */
@@ -96,19 +113,43 @@ export declare class HelixHeadlessCodeBlock extends HelixElement {
96
113
  * `false` reflects as no attribute at all.
97
114
  */
98
115
  diff: boolean;
116
+ /**
117
+ * Whether a block whose height is capped takes a button that shows every
118
+ * line, and fewer again.
119
+ *
120
+ * The cap is the page's, `--code-block-max-block-size` on the styled tier;
121
+ * the button is drawn only while the cap hides something, measured as the
122
+ * block lays out. Not for a diff, whose files each scroll on their own.
123
+ */
124
+ expandable: boolean;
125
+ /**
126
+ * The expand button's words while the cap hides lines.
127
+ */
128
+ expandLabel: string;
99
129
  /**
100
130
  * Turns the code into highlighted markup, which the block draws in place of
101
131
  * the plain text.
102
132
  *
103
- * Called with the code as written and returning HTML, such as the output of
104
- * Shiki's `codeToHtml` or Prism's `highlight`. **The markup is drawn as
105
- * given**, so it has to escape the code it was handed, which those
106
- * highlighters do. Bind the language in the function you pass. The code
107
- * stays in the slot, so the copy button copies it as written and a reader
108
- * without the script still has it. Not called on a server, which has no code
109
- * to read, nor for a diff.
133
+ * Called with the code as written and the block's `language`, and returning
134
+ * HTML, such as the output of Shiki's `codeToHtml` or Prism's `highlight`.
135
+ * One function serves every block on a page, each block saying its own
136
+ * language:
137
+ *
138
+ * ```js
139
+ * for (const block of document.querySelectorAll('helix-code-block')) {
140
+ * block.highlight = (code, lang) => codeToHtml(code, { lang, theme: 'github-light' })
141
+ * }
142
+ * ```
143
+ *
144
+ * **The markup is drawn as given**, so it has to escape the code it was
145
+ * handed, which those highlighters do. A `<pre>` and `<code>` around the
146
+ * whole of it, which Shiki writes, are taken off, so the lines sit level
147
+ * with the gutter's numbers and the block keeps one tab stop. The code stays
148
+ * in the slot, so the copy button copies it as written and a reader without
149
+ * the script still has it. Not called on a server, which has no code to
150
+ * read, nor for a diff.
110
151
  */
111
- highlight?: (code: string) => string;
152
+ highlight?: (code: string, language: string) => string;
112
153
  /**
113
154
  * The block's name, usually a file name or a language.
114
155
  *
@@ -116,6 +157,14 @@ export declare class HelixHeadlessCodeBlock extends HelixElement {
116
157
  * carries no name of its own.
117
158
  */
118
159
  label: string;
160
+ /**
161
+ * The language the code is written in, such as `ts` or `css`, handed to
162
+ * `highlight` as its second argument.
163
+ *
164
+ * Absent hands it an empty string. It draws nothing of its own: the block's
165
+ * name is `label`.
166
+ */
167
+ language: string;
119
168
  /**
120
169
  * Whether the lines are numbered in a gutter beside the code.
121
170
  *
@@ -184,10 +233,30 @@ export declare class HelixHeadlessCodeBlock extends HelixElement {
184
233
  * was not redrawn.
185
234
  */
186
235
  private observer;
236
+ /** Whether the cap hides lines, measured from the drawn block. */
237
+ private capped;
238
+ /** Whether the expand button has shown every line. */
239
+ private expanded;
240
+ /** Watches the block's size, while it is expandable. */
241
+ private sizes;
242
+ /**
243
+ * Reads whether the cap hides lines: the scroller is taller inside than it
244
+ * is drawn. The styled tier caps the `<code>`, and a page may cap the
245
+ * `<pre>`, so both are asked. Left as it was while expanded, which shows
246
+ * everything.
247
+ */
248
+ private readonly measure;
249
+ protected updated(changed: PropertyValues): void;
187
250
  connectedCallback(): void;
188
251
  disconnectedCallback(): void;
189
252
  protected firstUpdated(changed: PropertyValues): void;
190
253
  protected render(): TemplateResult;
254
+ /**
255
+ * The button that shows every line of a capped block, and fewer again, or
256
+ * nothing while the cap hides nothing. Not on a server, which cannot
257
+ * measure, so a served block draws none and the client adds it.
258
+ */
259
+ private renderExpand;
191
260
  /**
192
261
  * The name with the copy button beside it, or nothing when there is no name.
193
262
  *
@@ -6,22 +6,37 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { customElement, HelixElement } from '@fusion.dev/helix-core';
8
8
  import { nothing } from 'lit';
9
- import { property } from 'lit/decorators.js';
9
+ import { property, state } from 'lit/decorators.js';
10
10
  import { unsafeHTML } from 'lit/directives/unsafe-html.js';
11
11
  import { html } from 'lit/static-html.js';
12
12
  import '../../copy-button/index.js';
13
+ import { highlightedLines } from '../highlight.js';
13
14
  import { gutterNumbers, lineCount } from '../lines.js';
14
15
  import { pairLines, parsePatch } from '../patch.js';
15
16
  let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
16
17
  constructor() {
17
18
  super(...arguments);
19
+ this.collapseLabel = 'Show fewer lines';
18
20
  this.copiedLabel = 'Copied';
19
21
  this.copyLabel = 'Copy code';
20
22
  this.diff = false;
23
+ this.expandable = false;
24
+ this.expandLabel = 'Show all lines';
21
25
  this.label = '';
26
+ this.language = '';
22
27
  this.lineNumbers = false;
23
28
  this.noCopy = false;
24
29
  this.parsed = { files: [], text: '' };
30
+ this.capped = false;
31
+ this.expanded = false;
32
+ this.measure = () => {
33
+ if (!this.expanded) {
34
+ this.capped =
35
+ this.expandable &&
36
+ !this.diff &&
37
+ [...this.renderRoot.querySelectorAll('[part="block"], [part="code"]')].some((box) => box.scrollHeight > box.clientHeight + 1);
38
+ }
39
+ };
25
40
  }
26
41
  get files() {
27
42
  if (!this.diff) {
@@ -43,6 +58,14 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
43
58
  .map((node) => node.textContent ?? '')
44
59
  .join('');
45
60
  }
61
+ updated(changed) {
62
+ super.updated(changed);
63
+ if (this.expandable && typeof ResizeObserver !== 'undefined') {
64
+ this.sizes ??= new ResizeObserver(this.measure);
65
+ this.sizes.observe(this);
66
+ }
67
+ this.measure();
68
+ }
46
69
  connectedCallback() {
47
70
  super.connectedCallback();
48
71
  if (typeof MutationObserver !== 'undefined') {
@@ -52,6 +75,8 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
52
75
  }
53
76
  disconnectedCallback() {
54
77
  super.disconnectedCallback();
78
+ this.sizes?.disconnect();
79
+ this.sizes = undefined;
55
80
  this.observer?.disconnect();
56
81
  }
57
82
  firstUpdated(changed) {
@@ -64,7 +89,16 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
64
89
  return this.renderDiff(files);
65
90
  }
66
91
  const text = this.text;
67
- const highlighted = this.highlight && text !== '' ? this.highlight(text) : undefined;
92
+ let highlighted;
93
+ try {
94
+ highlighted =
95
+ this.highlight && text !== ''
96
+ ? highlightedLines(this.highlight(text, this.language))
97
+ : undefined;
98
+ }
99
+ catch (error) {
100
+ globalThis.reportError?.(error);
101
+ }
68
102
  const code = highlighted === undefined
69
103
  ? html `<code part="code"><slot @slotchange=${() => this.requestUpdate()}></slot></code>`
70
104
  : html `<code part="code">${unsafeHTML(highlighted)}</code><slot
@@ -77,9 +111,26 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
77
111
  : nothing;
78
112
  return html `${this.renderHeader(this.label)}
79
113
  <div part="frame">
80
- <pre part="block">${gutter}${code}</pre>
114
+ <pre id="block" part="block">${gutter}${code}</pre>
81
115
  ${this.label ? nothing : this.renderCopy()}
82
- </div>`;
116
+ </div>${this.renderExpand()}`;
117
+ }
118
+ renderExpand() {
119
+ if (!this.expandable || !(this.capped || this.expanded)) {
120
+ return nothing;
121
+ }
122
+ return html `<button
123
+ aria-controls="block"
124
+ aria-expanded=${this.expanded ? 'true' : 'false'}
125
+ part="expand"
126
+ type="button"
127
+ @click=${() => {
128
+ this.expanded = !this.expanded;
129
+ this.toggleState('expanded', this.expanded);
130
+ }}
131
+ >
132
+ ${this.expanded ? this.collapseLabel : this.expandLabel}
133
+ </button>`;
83
134
  }
84
135
  renderHeader(name, value) {
85
136
  return name
@@ -92,7 +143,7 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
92
143
  renderCopyButton(value = this.text, name = this.label) {
93
144
  return html `<${this.tag('copy-button')}
94
145
  part="copy"
95
- exportparts="button: copy-button, text: copy-text, mark: copy-mark, live: copy-live, tooltip: copy-tooltip,
146
+ exportparts="button: copy-button, text: copy-text, mark: copy-mark, live: copy-live, spinner: copy-spinner, tooltip: copy-tooltip,
96
147
  tooltip-arrow: copy-tooltip-arrow, tooltip-arrow-bottom: copy-tooltip-arrow-bottom,
97
148
  tooltip-arrow-left: copy-tooltip-arrow-left, tooltip-arrow-right: copy-tooltip-arrow-right,
98
149
  tooltip-arrow-top: copy-tooltip-arrow-top, tooltip-bottom: copy-tooltip-bottom,
@@ -150,6 +201,9 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
150
201
  })}<slot hidden @slotchange=${() => this.requestUpdate()}></slot>`;
151
202
  }
152
203
  };
204
+ __decorate([
205
+ property({ attribute: 'collapse-label' })
206
+ ], HelixHeadlessCodeBlock.prototype, "collapseLabel", void 0);
153
207
  __decorate([
154
208
  property({ attribute: 'copied-label' })
155
209
  ], HelixHeadlessCodeBlock.prototype, "copiedLabel", void 0);
@@ -159,12 +213,21 @@ __decorate([
159
213
  __decorate([
160
214
  property({ reflect: true, type: Boolean })
161
215
  ], HelixHeadlessCodeBlock.prototype, "diff", void 0);
216
+ __decorate([
217
+ property({ type: Boolean })
218
+ ], HelixHeadlessCodeBlock.prototype, "expandable", void 0);
219
+ __decorate([
220
+ property({ attribute: 'expand-label' })
221
+ ], HelixHeadlessCodeBlock.prototype, "expandLabel", void 0);
162
222
  __decorate([
163
223
  property({ attribute: false })
164
224
  ], HelixHeadlessCodeBlock.prototype, "highlight", void 0);
165
225
  __decorate([
166
226
  property()
167
227
  ], HelixHeadlessCodeBlock.prototype, "label", void 0);
228
+ __decorate([
229
+ property()
230
+ ], HelixHeadlessCodeBlock.prototype, "language", void 0);
168
231
  __decorate([
169
232
  property({ attribute: 'line-numbers', reflect: true, type: Boolean })
170
233
  ], HelixHeadlessCodeBlock.prototype, "lineNumbers", void 0);
@@ -174,6 +237,12 @@ __decorate([
174
237
  __decorate([
175
238
  property({ reflect: true })
176
239
  ], HelixHeadlessCodeBlock.prototype, "variant", void 0);
240
+ __decorate([
241
+ state()
242
+ ], HelixHeadlessCodeBlock.prototype, "capped", void 0);
243
+ __decorate([
244
+ state()
245
+ ], HelixHeadlessCodeBlock.prototype, "expanded", void 0);
177
246
  HelixHeadlessCodeBlock = __decorate([
178
247
  customElement('helix-headless-code-block')
179
248
  ], HelixHeadlessCodeBlock);
@@ -45,6 +45,8 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
45
45
  * @slot end - Content at the trailing end, before the trigger.
46
46
  * @slot feedback - The message that says what is wrong with the value.
47
47
  * @slot hint - Help text under the field.
48
+ * @slot panel-footer - Content in the panel under the picker, such as a note or an action.
49
+ * @slot panel-header - Content in the panel above the picker, such as a heading or a shortcut.
48
50
  * @slot start - Content at the leading end of the field, inside its border.
49
51
  * @slot trigger - The icon on the trigger, which shows that the field opens a panel.
50
52
  *
@@ -72,12 +74,16 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
72
74
  * @csspart picker-channel-marker-label - The value a mark stands at, when `marker-labels` is set.
73
75
  * @csspart picker-channel-markers - The row of marks along the track.
74
76
  * @csspart picker-channel-output - The current value, shown beside the track.
77
+ * @csspart picker-channel-tooltip - A ramp's value in a bubble, where a ramp shows one.
78
+ * @csspart picker-channel-tooltips - The layer over a ramp's track that holds its bubble.
75
79
  * @csspart picker-channels - The channel sliders beside the sample.
76
80
  * @csspart picker-controls - The row under the square.
77
81
  * @csspart picker-eyedropper - The control that samples a color from the screen.
78
82
  * @csspart picker-eyedropper-button - The button inside `picker-eyedropper`.
79
83
  * @csspart picker-eyedropper-live - The live region of the button inside `picker-eyedropper`, which says its pending label.
84
+ * @csspart picker-eyedropper-spinner - The ring the eyedropper button turns while it is pending.
80
85
  * @csspart picker-eyedropper-text - The words on the button inside `picker-eyedropper`.
86
+ * @csspart picker-feedback - The field's message inside the open panel, under the picker, where the panel covers the one under the field.
81
87
  * @csspart picker-field - One channel's number field with its label, in `channel-fields`.
82
88
  * @csspart picker-field-input - The number input in a channel's field.
83
89
  * @csspart picker-field-label - The name above a channel's number input.
@@ -86,6 +92,7 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
86
92
  * @csspart picker-format - The control that changes the syntax the value is written in.
87
93
  * @csspart picker-format-button - The button inside `picker-format`.
88
94
  * @csspart picker-format-live - The live region of the button inside `picker-format`, which says its pending label.
95
+ * @csspart picker-format-spinner - The ring the syntax button turns while it is pending.
89
96
  * @csspart picker-format-text - The words on the button inside `picker-format`.
90
97
  * @csspart picker-grid - The saturation and brightness square.
91
98
  * @csspart picker-grid-brightness - The range input for the square's vertical axis.
@@ -96,6 +103,8 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
96
103
  * @csspart picker-swatch - One preset.
97
104
  * @csspart picker-swatches - The row of presets.
98
105
  * @csspart picker-value - The text field that holds the color. It accepts a typed or pasted color.
106
+ * @csspart picker-wheel - The hue ring round the square, with `wheel`.
107
+ * @csspart picker-wheel-hue - The range input behind the hue ring.
99
108
  * @csspart preview - The chip showing the color, inside the trigger.
100
109
  * @csspart surface - The floating panel.
101
110
  * @csspart trigger - The control that opens the panel.
@@ -193,6 +202,11 @@ export declare class HelixHeadlessColorInput extends HelixHeadlessColorInput_bas
193
202
  * where the color is the answer rather than a setting.
194
203
  */
195
204
  variant?: 'swatch';
205
+ /**
206
+ * Draws the panel's hue as a wheel around the square, in place of the hue
207
+ * ramp. See Color Picker's `wheel`.
208
+ */
209
+ wheel: boolean;
196
210
  /**
197
211
  * The last value that was a color.
198
212
  *
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, colorName, customElement, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerField, parseColor, toCss, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, colorName, customElement, HelixFormElement, localeOf, MixinControllerOpen, MixinControllerValue, MixinField, MixinPickerField, parseColor, toCss, wordsConverter, } from '@fusion.dev/helix-core';
8
8
  import { nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { html } from 'lit/static-html.js';
@@ -25,6 +25,7 @@ let HelixHeadlessColorInput = class HelixHeadlessColorInput extends MixinPickerF
25
25
  this.announcesInput = true;
26
26
  this.swatches = '';
27
27
  this.triggerLabel = 'Choose a color';
28
+ this.wheel = false;
28
29
  this.settled = '';
29
30
  this.handleInput = (event) => {
30
31
  event.stopPropagation();
@@ -77,7 +78,7 @@ let HelixHeadlessColorInput = class HelixHeadlessColorInput extends MixinPickerF
77
78
  if (!parsed) {
78
79
  return this.value || this.triggerLabel;
79
80
  }
80
- return `${colorName(parsed, this.colorWords, this.lang)} ${this.value}`;
81
+ return `${colorName(parsed, this.colorWords, localeOf(this))} ${this.value}`;
81
82
  }
82
83
  get painted() {
83
84
  const parsed = parseColor(this.value);
@@ -115,16 +116,20 @@ let HelixHeadlessColorInput = class HelixHeadlessColorInput extends MixinPickerF
115
116
  channel-hint: picker-channel-hint, channel-label: picker-channel-label,
116
117
  channel-marker: picker-channel-marker, channel-marker-label: picker-channel-marker-label,
117
118
  channel-markers: picker-channel-markers, channel-output: picker-channel-output,
119
+ channel-tooltip: picker-channel-tooltip, channel-tooltips: picker-channel-tooltips,
118
120
  channels: picker-channels, controls: picker-controls, eyedropper: picker-eyedropper,
119
- eyedropper-button: picker-eyedropper-button, eyedropper-live: picker-eyedropper-live, eyedropper-text: picker-eyedropper-text,
120
- field: picker-field, field-input: picker-field-input, field-label: picker-field-label,
121
+ eyedropper-button: picker-eyedropper-button, eyedropper-live: picker-eyedropper-live, eyedropper-spinner: picker-eyedropper-spinner, eyedropper-text: picker-eyedropper-text,
122
+ feedback: picker-feedback, field: picker-field, field-input: picker-field-input, field-label: picker-field-label,
121
123
  fields: picker-fields, footer: picker-footer, format: picker-format,
122
- format-button: picker-format-button, format-live: picker-format-live, format-text: picker-format-text, grid: picker-grid,
124
+ format-button: picker-format-button, format-live: picker-format-live, format-spinner: picker-format-spinner, format-text: picker-format-text, grid: picker-grid,
123
125
  grid-brightness: picker-grid-brightness, grid-handle: picker-grid-handle,
124
126
  grid-saturation: picker-grid-saturation, icon: picker-icon, sample: picker-sample,
125
- swatch: picker-swatch, swatches: picker-swatches, value: picker-value"
127
+ swatch: picker-swatch, swatches: picker-swatches, value: picker-value,
128
+ wheel: picker-wheel, wheel-hue: picker-wheel-hue"
126
129
  ?invalid=${this.resolvedFeedback !== ''}
130
+ .feedback=${this.resolvedFeedback}
127
131
  ?alpha=${this.alpha}
132
+ ?wheel=${this.wheel}
128
133
  ?channel-fields=${this.channelFields}
129
134
  ?no-format=${this.noFormat}
130
135
  ?no-value=${this.variant !== 'swatch'}
@@ -209,7 +214,9 @@ let HelixHeadlessColorInput = class HelixHeadlessColorInput extends MixinPickerF
209
214
  popover="manual"
210
215
  ?hidden=${!this.open}
211
216
  >
217
+ <slot name="panel-header"></slot>
212
218
  ${this.renderPicker()}
219
+ <slot name="panel-footer"></slot>
213
220
  </div>
214
221
  ${this.renderHint()}${this.renderFeedback()}`;
215
222
  }
@@ -224,7 +231,7 @@ __decorate([
224
231
  property({ attribute: 'channel-fields', type: Boolean })
225
232
  ], HelixHeadlessColorInput.prototype, "channelFields", void 0);
226
233
  __decorate([
227
- property({ attribute: 'color-words', type: Object })
234
+ property({ attribute: 'color-words', converter: wordsConverter })
228
235
  ], HelixHeadlessColorInput.prototype, "colorWords", void 0);
229
236
  __decorate([
230
237
  property({ reflect: true })
@@ -247,6 +254,9 @@ __decorate([
247
254
  __decorate([
248
255
  property({ reflect: true })
249
256
  ], HelixHeadlessColorInput.prototype, "variant", void 0);
257
+ __decorate([
258
+ property({ reflect: true, type: Boolean })
259
+ ], HelixHeadlessColorInput.prototype, "wheel", void 0);
250
260
  HelixHeadlessColorInput = __decorate([
251
261
  customElement('helix-headless-color-input')
252
262
  ], HelixHeadlessColorInput);
@@ -1,5 +1,4 @@
1
- import { toHsl, toRgb } from '@fusion.dev/helix-core';
2
- const clamp = (value, low, high) => Math.min(high, Math.max(low, value));
1
+ import { clamp, toHsl, toRgb } from '@fusion.dev/helix-core';
3
2
  const percent = (token) => {
4
3
  if (token === undefined) {
5
4
  return 100;
@@ -1,9 +1,9 @@
1
- import { type Color, type ColorFormat, type ColorWords, HelixFormElement } from '@fusion.dev/helix-core';
1
+ import { type Color, type ColorFormat, type ColorWords, HelixFormElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../button/index.js';
4
4
  import '../../button-group/index.js';
5
5
  import '../../slider/index.js';
6
- declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & typeof HelixFormElement;
6
+ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinPickerFeedbackInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & typeof HelixFormElement;
7
7
  /**
8
8
  * @summary A color picker made of a square and two ramps.
9
9
  *
@@ -29,8 +29,12 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
29
29
  *
30
30
  * A screen reader hears the color's name, such as "vibrant red", after the two
31
31
  * numbers on the square and after the number on the hue ramp, and each preset
32
- * is named by its color. Set `color-words` to speak the names in another
33
- * language.
32
+ * is named by its color. The opacity ramp is heard as a percentage. Set
33
+ * `color-words` to speak the names in another language.
34
+ *
35
+ * The presets are a listbox with the current color selected, and one tab
36
+ * stop. The arrow keys move between them, Home and End go to the ends, and
37
+ * Enter, Space or a press chooses one.
34
38
  *
35
39
  * @since 0.1.0
36
40
  * @status stable
@@ -58,12 +62,16 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
58
62
  * @csspart channel-marker-label - The value a mark stands at, when `marker-labels` is set.
59
63
  * @csspart channel-markers - The row of marks along the track.
60
64
  * @csspart channel-output - The current value, shown beside the track.
65
+ * @csspart channel-tooltip - A ramp's value in a bubble, where a ramp shows one.
66
+ * @csspart channel-tooltips - The layer over a ramp's track that holds its bubble.
61
67
  * @csspart channels - The ramps beside the sample.
62
68
  * @csspart controls - The row under the square.
63
69
  * @csspart eyedropper - The control that samples a color from the screen.
64
70
  * @csspart eyedropper-button - The button inside `eyedropper`.
65
71
  * @csspart eyedropper-live - The live region of the button inside `eyedropper`, which says its pending label.
72
+ * @csspart eyedropper-spinner - The ring the eyedropper button turns while it is pending.
66
73
  * @csspart eyedropper-text - The words on the button inside `eyedropper`, trimmed to their capitals and baseline.
74
+ * @csspart feedback - The message under the picker, while `feedback` is set.
67
75
  * @csspart field - One channel's number field with its label, in `channel-fields`.
68
76
  * @csspart field-input - The number input in a channel's field.
69
77
  * @csspart field-label - The name above a channel's number input.
@@ -72,6 +80,7 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
72
80
  * @csspart format - The control that changes the syntax the value is written in.
73
81
  * @csspart format-button - The button inside `format`.
74
82
  * @csspart format-live - The live region of the button inside `format`, which says its pending label.
83
+ * @csspart format-spinner - The ring the syntax button turns while it is pending.
75
84
  * @csspart format-text - The words on the button inside `format`, trimmed to their capitals and baseline.
76
85
  * @csspart grid - The saturation and brightness square. Draw the mark that shows
77
86
  * where the color sits with `::part(grid)::after` in your stylesheet. The
@@ -80,14 +89,18 @@ declare const HelixHeadlessColorPicker_base: (new (...args: any[]) => import("@f
80
89
  * @csspart grid-brightness - The range input for the square's vertical axis.
81
90
  * @csspart grid-saturation - The range input for the square's horizontal axis.
82
91
  * @csspart sample - A chip of the current color. Pressing it copies the value.
83
- * @csspart swatch - One preset.
84
- * @csspart swatches - The row of presets.
92
+ * @csspart swatch - One preset, an option in the `swatches` listbox.
93
+ * @csspart swatches - The row of presets, a listbox.
85
94
  * @csspart value - The text field that holds the color. It accepts a typed or pasted color.
95
+ * @csspart wheel - The hue ring round the square, with `wheel`. Draw the ring and its mark from `--color-picker-hue`.
96
+ * @csspart wheel-hue - The range input behind the ring, which a reader turns with the keys.
86
97
  *
87
98
  * @cssproperty --color-picker-brightness - The chosen brightness, 0 to 100, as a percentage.
88
99
  * @cssproperty --color-picker-hue - The chosen hue, 0 to 360, unitless.
89
100
  * @cssproperty --color-picker-saturation - The chosen saturation, 0 to 100, as a percentage.
90
101
  * @cssproperty --color-picker-swatch - The color a chip shows: the current color on the sample, and the preset's color on each preset.
102
+ *
103
+ * @cssstate invalid - While `invalid` is set or `feedback` says what is wrong.
91
104
  */
92
105
  export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_base {
93
106
  /**
@@ -179,16 +192,6 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
179
192
  * What the hue channel is called.
180
193
  */
181
194
  hueLabel: string;
182
- /**
183
- * Whether the current selection fails validation.
184
- *
185
- * A flag rather than a message, the split Date Picker also draws. A flat
186
- * picker has no room of its own for a sentence: the field that wraps one owns
187
- * the label, the hint and the feedback, and a second message inside the panel
188
- * would be the same error said twice. What is left for the picker is the one
189
- * thing the field cannot draw from outside, the mark on the answer itself.
190
- */
191
- invalid: boolean;
192
195
  /**
193
196
  * What the lightness channel's field is called, in `channel-fields` with
194
197
  * hsl.
@@ -305,6 +308,16 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
305
308
  * speaks it. Absent is the control's own sentence, in English.
306
309
  */
307
310
  valueMissingMessage?: string;
311
+ /**
312
+ * Draws the hue as a wheel around the square, in place of the hue ramp, as
313
+ * React Aria's ColorWheel sits round its ColorArea.
314
+ *
315
+ * The ring is one stop, a slider a reader turns with the arrow keys, Home
316
+ * and End, the same way round in either writing direction, and a press or a
317
+ * drag on it takes the hue in that direction. Off, the picker keeps its
318
+ * ramp.
319
+ */
320
+ wheel: boolean;
308
321
  /**
309
322
  * The color the reader has moved to, or nothing while they have moved none.
310
323
  *
@@ -322,6 +335,8 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
322
335
  * server's markup, which was rendered without it.
323
336
  */
324
337
  private sampling;
338
+ /** The preset the reader was last on, which holds the row's one tab stop. */
339
+ private swatchAt;
325
340
  /**
326
341
  * Whether the value on this element was produced here.
327
342
  *
@@ -393,6 +408,17 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
393
408
  private readonly copier;
394
409
  /** Takes a preset, in this picker's syntax rather than as the preset spelled it. */
395
410
  private readonly handleSwatch;
411
+ /**
412
+ * The arrows, Home and End in the presets: focus moves, and nothing is
413
+ * chosen until Enter, Space or a press, as in React Aria's swatch picker.
414
+ *
415
+ * Core's roving set, as Legend's toggles are: the arrows follow the line of
416
+ * text, so the row reverses in a right-to-left page, Up and Down are the
417
+ * previous and the next since the row wraps onto lines, and focus stops at
418
+ * the ends, since a row of colors is no ring. A press from anywhere else in
419
+ * the picker is not the row's to move.
420
+ */
421
+ protected readonly swatchKeys: KeyboardNavigationController;
396
422
  /** Walks the format on, and rewrites the value in it. */
397
423
  private readonly handleFormat;
398
424
  /**
@@ -415,6 +441,11 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
415
441
  * reaches a corner, and without it the handle stops wherever the pointer left.
416
442
  */
417
443
  private readonly handleGridPointer;
444
+ /**
445
+ * A press or a drag on the hue wheel: the hue in that direction from its
446
+ * center. A press in the square inside it is the square's.
447
+ */
448
+ private readonly handleWheelPointer;
418
449
  protected firstUpdated(changed: import('lit').PropertyValues): void;
419
450
  /**
420
451
  * Reports the color to the form.
@@ -557,6 +588,12 @@ export declare class HelixHeadlessColorPicker extends HelixHeadlessColorPicker_b
557
588
  * tiers.
558
589
  */
559
590
  protected renderTools(): TemplateResult;
591
+ /**
592
+ * The presets, as a listbox of colors with the current one selected, which
593
+ * is React Aria's ColorSwatchPicker: one tab stop, held by the preset the
594
+ * reader was last on, then the selected one, then the first.
595
+ */
596
+ private renderSwatches;
560
597
  protected render(): TemplateResult;
561
598
  }
562
599
  declare global {