@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
@@ -4,15 +4,19 @@ 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 { customElement, deepActiveElement, deepContains, FocusScopeController, fillTemplate, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
7
+ import { customElement, DelayController, deepActiveElement, deepContains, FocusScopeController, fillTemplate, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
- import { property } from 'lit/decorators.js';
9
+ import { property, state } from 'lit/decorators.js';
10
10
  import { matchesHotkey, parseHotkey } from '../hotkey.js';
11
+ import { messageWords } from '../words.js';
11
12
  let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
12
13
  constructor() {
13
14
  super(...arguments);
14
15
  this.hotkey = 'F8';
15
16
  this.label = 'Notifications ({hotkey})';
17
+ this.said = '';
18
+ this.urgent = '';
19
+ this.hush = new DelayController(this, { renders: false });
16
20
  this.scope = new FocusScopeController(this, {
17
21
  contents: () => this.showing.flatMap((one) => {
18
22
  const target = focusTarget(one);
@@ -85,14 +89,59 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
85
89
  label: fillTemplate(this.label, { hotkey: this.hotkey }),
86
90
  role: 'region',
87
91
  });
88
- this.internals.ariaLive = 'polite';
89
- this.internals.ariaRelevant = 'additions';
90
- this.internals.ariaAtomic = 'false';
92
+ }
93
+ announce(arrived) {
94
+ const urgent = arrived.filter(isDanger).map(messageWords).join(' ');
95
+ const said = arrived
96
+ .filter((one) => !isDanger(one))
97
+ .map(messageWords)
98
+ .join(' ');
99
+ if (said.trim() === '' && urgent.trim() === '') {
100
+ return;
101
+ }
102
+ this.said = '';
103
+ this.urgent = '';
104
+ const fill = () => {
105
+ this.said = said;
106
+ this.urgent = urgent;
107
+ this.hush.start(1000, () => {
108
+ this.said = '';
109
+ this.urgent = '';
110
+ });
111
+ };
112
+ if (typeof requestAnimationFrame === 'function') {
113
+ requestAnimationFrame(fill);
114
+ }
115
+ else {
116
+ fill();
117
+ }
118
+ }
119
+ tell(added) {
120
+ const showing = this.showing;
121
+ const arrived = added.filter((one) => one instanceof HTMLElement && showing.includes(one));
122
+ if (arrived.length === 0) {
123
+ return;
124
+ }
125
+ if (this.blocked()) {
126
+ this.notify(arrived);
127
+ }
128
+ else {
129
+ this.announce(arrived);
130
+ }
91
131
  }
92
132
  add(message, options = {}) {
93
133
  const tier = this.constructor.tier;
94
134
  const item = document.createElement(`${tier}toast-item`);
95
- item.textContent = message;
135
+ if (options.heading === undefined) {
136
+ item.textContent = message;
137
+ }
138
+ else {
139
+ item.append(slotted('heading', options.heading), slotted('description', message));
140
+ }
141
+ if (options.action) {
142
+ options.action.setAttribute('slot', 'actions');
143
+ item.append(options.action);
144
+ }
96
145
  if (options.tone) {
97
146
  item.setAttribute('tone', options.tone);
98
147
  }
@@ -143,9 +192,6 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
143
192
  if (!open || blocked) {
144
193
  region.showPopover();
145
194
  }
146
- if (blocked) {
147
- this.notify(arrived);
148
- }
149
195
  }
150
196
  lowerWhenStill(region) {
151
197
  const running = typeof this.getAnimations === 'function' ? this.getAnimations({ subtree: true }) : [];
@@ -173,9 +219,9 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
173
219
  return;
174
220
  }
175
221
  for (const one of arrived) {
176
- const words = (one.textContent ?? '').replace(/\s+/gu, ' ').trim();
222
+ const words = messageWords(one);
177
223
  if (words !== '') {
178
- speaker.ariaNotify(words);
224
+ speaker.ariaNotify(words, { priority: isDanger(one) ? 'high' : 'normal' });
179
225
  }
180
226
  }
181
227
  }
@@ -185,7 +231,9 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
185
231
  this.addEventListener('helix-dismiss', this.handleDismiss);
186
232
  document.addEventListener('keydown', this.handleHotkey);
187
233
  this.watcher = new MutationObserver((records) => {
188
- this.place(records.flatMap((record) => [...record.addedNodes]));
234
+ const added = records.flatMap((record) => [...record.addedNodes]);
235
+ this.place(added);
236
+ this.tell(added);
189
237
  this.sweep();
190
238
  });
191
239
  this.watcher.observe(this, {
@@ -211,7 +259,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
211
259
  this.place();
212
260
  }
213
261
  render() {
214
- return html `<div part="region" popover="manual" tabindex="-1"><slot></slot></div>`;
262
+ return html `<div part="region" popover="manual" tabindex="-1"><slot></slot><span part="live" role="status">${this.said}</span><span part="live" role="alert">${this.urgent}</span></div>`;
215
263
  }
216
264
  };
217
265
  __decorate([
@@ -223,10 +271,17 @@ __decorate([
223
271
  __decorate([
224
272
  property({ reflect: true })
225
273
  ], HelixHeadlessToast.prototype, "placement", void 0);
274
+ __decorate([
275
+ state()
276
+ ], HelixHeadlessToast.prototype, "said", void 0);
277
+ __decorate([
278
+ state()
279
+ ], HelixHeadlessToast.prototype, "urgent", void 0);
226
280
  HelixHeadlessToast = __decorate([
227
281
  customElement('helix-headless-toast')
228
282
  ], HelixHeadlessToast);
229
283
  export { HelixHeadlessToast };
284
+ const isDanger = (item) => (item.tone ?? item.getAttribute('tone')) === 'danger';
230
285
  const popoverOpen = (region) => {
231
286
  try {
232
287
  return region.matches(':popover-open');
@@ -238,3 +293,9 @@ const popoverOpen = (region) => {
238
293
  const focusTarget = (item) => item.shadowRoot?.querySelector('[part="dismiss"]') ??
239
294
  focusableElements(item)[0] ??
240
295
  null;
296
+ const slotted = (slot, words) => {
297
+ const element = document.createElement('div');
298
+ element.slot = slot;
299
+ element.textContent = words;
300
+ return element;
301
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Pieces of a message joined into one line a screen reader says, with a full
3
+ * stop between two where the first does not already end a sentence, so a
4
+ * heading and its detail are heard as two sentences and not run together.
5
+ */
6
+ export declare const joinSaid: (pieces: readonly string[]) => string;
7
+ /**
8
+ * What a message says as it arrives: the word for its tone, then its heading,
9
+ * its description and its text, and never its actions or its dismiss control,
10
+ * which a reader finds by moving into the message.
11
+ */
12
+ export declare const messageWords: (item: Element) => string;
@@ -0,0 +1,25 @@
1
+ import { toneMark } from '@fusion.dev/helix-core';
2
+ const UNSAID = new Set(['actions', 'dismiss-icon', 'icon']);
3
+ export const joinSaid = (pieces) => pieces
4
+ .map((piece) => piece.replace(/\s+/gu, ' ').trim())
5
+ .filter((piece) => piece !== '')
6
+ .reduce((line, piece) => line === '' ? piece : `${line}${/[.!?:;]$/u.test(line) ? '' : '.'} ${piece}`, '');
7
+ export const messageWords = (item) => {
8
+ const tone = item.tone ?? item.getAttribute('tone') ?? undefined;
9
+ const label = toneMark(tone)?.label;
10
+ const heading = [];
11
+ const rest = [];
12
+ for (const node of item.childNodes) {
13
+ if (node instanceof Element) {
14
+ const slot = node.getAttribute('slot') ?? '';
15
+ if (!UNSAID.has(slot)) {
16
+ ;
17
+ (slot === 'heading' ? heading : rest).push(node.textContent ?? '');
18
+ }
19
+ }
20
+ else if (node.nodeType === 3) {
21
+ rest.push(node.textContent ?? '');
22
+ }
23
+ }
24
+ return joinSaid([...(label ? [label] : []), ...heading, ...rest]);
25
+ };
@@ -18,13 +18,33 @@ declare const HelixHeadlessToggleGroup_base: (new (...args: any[]) => import("@f
18
18
  * say whether they are pressed with `aria-pressed`, as React Aria's
19
19
  * ToggleButtonGroup and Radix's ToggleGroup do. A press presses or releases
20
20
  * one item, the arrow keys move focus without pressing, and `value` is the
21
- * pressed values, comma separated, which `values` also gives as a list. The
22
- * form receives one entry per pressed value. The indicator stays hidden, and
23
- * each pressed item is marked with `:state(pressed)`.
21
+ * pressed values, comma separated, which `values` also gives as a list. Use
22
+ * `values` where an item's value holds a comma. The form receives one entry
23
+ * per pressed value, and a page the browser brings back presses the same
24
+ * items again. The indicator stays hidden, and each pressed item is marked
25
+ * with `:state(pressed)`. Inside a toolbar it is a named group of that
26
+ * toolbar's controls instead, so a reader meets one toolbar.
24
27
  *
25
28
  * `orientation="vertical"` runs the items down a column, says so to the
26
29
  * accessibility tree, and the up and down arrows move between them.
27
30
  *
31
+ * **Keyboard.** The group is one tab stop: the chosen item, or the first that
32
+ * can be chosen, as in a radio group, and in a multiple group the item focus
33
+ * was last on.
34
+ *
35
+ * | Key | What it does |
36
+ * |---|---|
37
+ * | Right, Down | Moves to the next item, from the last back to the first. In a single group, chooses it. |
38
+ * | Left, Up | Moves to the item before, from the first round to the last. In a single group, chooses it. |
39
+ * | Home, End | Moves to the first or the last item. In a single group, chooses it. |
40
+ * | Space, Enter | Chooses the focused item, or presses or releases it in a multiple group. |
41
+ *
42
+ * Left and Right swap on a right-to-left page, and a disabled item is passed
43
+ * over. A single group is a `radiogroup` of items with `role="radio"` and
44
+ * `aria-checked`. A multiple group is a `toolbar` of buttons with
45
+ * `aria-pressed`, or a `group` inside a toolbar. The group is named by
46
+ * `label` and carries `aria-orientation` under `orientation`.
47
+ *
28
48
  * @since 0.1.0
29
49
  * @status stable
30
50
  * @aliases SegmentedControl, Segmented, Navigation, Switcher
@@ -112,6 +132,11 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
112
132
  /** The item focus was last on, in a toolbar, which holds its tab stop. */
113
133
  private lastFocused;
114
134
  private readonly noteFocus;
135
+ /**
136
+ * The item whose value is the group's, in a single group: the exact match,
137
+ * so nothing chosen marks nothing. A multiple group has none.
138
+ */
139
+ private get chosenItem();
115
140
  /** Whether several items can be pressed at once. */
116
141
  private get multiple();
117
142
  /**
@@ -178,12 +203,17 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
178
203
  disconnectedCallback(): void;
179
204
  protected firstUpdated(changed: PropertyValues): void;
180
205
  protected updated(changed: PropertyValues): void;
181
- protected willUpdate(changed: PropertyValues): void;
182
206
  /**
183
- * What the form receives: the value, or under `selection-mode="multiple"`
184
- * one entry per pressed value, as a native `<select multiple>` sends.
207
+ * The group's role: a radio group, a toolbar of pressed buttons, or, for
208
+ * pressed buttons inside a toolbar, a group.
209
+ *
210
+ * **A toolbar inside a toolbar is a reader's dead end**, so inside one the
211
+ * pressed buttons are a named group of the outer toolbar, as React Aria's
212
+ * ToggleButtonGroup demotes itself. Read by tag and by role, since the
213
+ * outer toolbar is a Helix one or the page's own `role="toolbar"`.
185
214
  */
186
- private formValue;
215
+ private get groupRole();
216
+ protected willUpdate(changed: PropertyValues): void;
187
217
  /**
188
218
  * The verdict on the answer `required` asks for.
189
219
  *
@@ -203,6 +233,14 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
203
233
  */
204
234
  get values(): string[];
205
235
  set values(next: string[]);
236
+ /** The pressed values as a list last written, which `values` reads. */
237
+ private chosen;
238
+ /**
239
+ * Presses the items a page the browser brings back held. Under
240
+ * `selection-mode="multiple"` the saved state is the form's entries, one per
241
+ * pressed value, which the shared restore leaves alone.
242
+ */
243
+ formStateRestoreCallback(state: string | File | FormData | null): void;
206
244
  /**
207
245
  * The row the track sits in, so something can sit beside it.
208
246
  *
@@ -217,6 +255,13 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
217
255
  * in it.
218
256
  */
219
257
  protected render(): TemplateResult;
258
+ /**
259
+ * Items that arrive after the first render, which is every item on a page
260
+ * the parser is still reading. Outside an update here, so taking the
261
+ * declaration schedules one rather than warning, and the update reports the
262
+ * form, which a removed answer no longer holds.
263
+ */
264
+ private readonly handleItems;
220
265
  }
221
266
  declare global {
222
267
  interface HTMLElementTagNameMap {
@@ -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 { commaList, customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, rovingStop, toggleValue, } from '@fusion.dev/helix-core';
7
+ import { commaList, customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, reportValues, rovingStop, toggleValue, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { HelixHeadlessToggle } from '../root/toggle-root.js';
@@ -13,15 +13,15 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
13
13
  super(...arguments);
14
14
  this.lastFocused = undefined;
15
15
  this.noteFocus = (event) => {
16
- const item = this.items.find((one) => one === event.target);
17
- if (this.multiple && item && item !== this.lastFocused) {
16
+ const item = event.target;
17
+ if (this.multiple && item !== this.lastFocused && this.items.includes(item)) {
18
18
  this.lastFocused = item;
19
19
  this.sync();
20
20
  }
21
21
  };
22
22
  this.focusable = true;
23
23
  this.indicator = new IndicatorController(this, {
24
- active: () => this.multiple ? undefined : this.items.find((item) => item.value === this.value),
24
+ active: () => this.chosenItem,
25
25
  indicator: () => this.partNamed('indicator'),
26
26
  observe: () => this.items,
27
27
  surface: () => this.partNamed('track'),
@@ -39,11 +39,25 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
39
39
  return;
40
40
  }
41
41
  const value = event.detail.value;
42
- this.requestValue(this.multiple
43
- ? toggleValue(this.values, value, this.items.map((item) => item.value)).join(',')
44
- : value);
42
+ if (!this.multiple) {
43
+ this.requestValue(value);
44
+ return;
45
+ }
46
+ const next = toggleValue(this.values, value, this.items.map((item) => item.value));
47
+ const was = this.chosen;
48
+ this.chosen = next;
49
+ if (!this.requestValue(next.join(','))) {
50
+ this.chosen = was;
51
+ }
45
52
  });
46
53
  };
54
+ this.chosen = undefined;
55
+ this.handleItems = () => {
56
+ this.adopt();
57
+ this.sync();
58
+ this.indicator.place();
59
+ this.requestUpdate();
60
+ };
47
61
  }
48
62
  adopt() {
49
63
  if (this.value !== '' || this.children === undefined) {
@@ -55,7 +69,7 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
55
69
  }
56
70
  }
57
71
  sync() {
58
- const active = this.multiple ? undefined : this.items.find((item) => item.value === this.value);
72
+ const active = this.chosenItem;
59
73
  const pressed = new Set(this.values);
60
74
  const entry = this.focusable ? this.entry() : undefined;
61
75
  for (const item of this.items) {
@@ -72,9 +86,12 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
72
86
  selected: (item) => item.pressed === true,
73
87
  });
74
88
  }
75
- const active = items.find((item) => item.value === this.value);
89
+ const active = this.chosenItem;
76
90
  return active && !active.disabled ? active : items.find((item) => !item.disabled);
77
91
  }
92
+ get chosenItem() {
93
+ return this.multiple ? undefined : this.items.find((item) => item.value === this.value);
94
+ }
78
95
  get multiple() {
79
96
  return this.selectionMode === 'multiple';
80
97
  }
@@ -90,14 +107,12 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
90
107
  if (this.value === '') {
91
108
  return false;
92
109
  }
93
- if (this.multiple) {
94
- return this.children === undefined || this.values.length > 0;
95
- }
96
110
  if (this.children === undefined) {
97
111
  return true;
98
112
  }
99
- const items = this.items;
100
- return items.length === 0 || items.some((item) => item.value === this.value);
113
+ return this.multiple
114
+ ? this.values.length > 0
115
+ : this.items.length === 0 || this.chosenItem !== undefined;
101
116
  }
102
117
  connectedCallback() {
103
118
  super.connectedCallback();
@@ -120,56 +135,55 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
120
135
  this.validate();
121
136
  this.linkHost();
122
137
  }
138
+ get groupRole() {
139
+ if (!this.multiple) {
140
+ return 'radiogroup';
141
+ }
142
+ return this.parentElement?.closest('[role=toolbar],helix-toolbar,helix-headless-toolbar')
143
+ ? 'group'
144
+ : 'toolbar';
145
+ }
123
146
  willUpdate(changed) {
124
147
  super.willUpdate(changed);
125
148
  this.adopt();
126
- hostAria(this.internals, { label: this.label, role: this.multiple ? 'toolbar' : 'radiogroup' });
149
+ hostAria(this.internals, { label: this.label, role: this.groupRole });
127
150
  this.internals.ariaOrientation = this.orientation ?? null;
128
- this.internals.setFormValue(this.formValue());
129
- }
130
- formValue() {
131
151
  if (!this.answered) {
132
- return null;
152
+ this.internals.setFormValue(null);
133
153
  }
134
- if (!this.multiple || this.name === '') {
135
- return this.value;
154
+ else if (this.multiple) {
155
+ reportValues(this.internals, this.name, this.values);
136
156
  }
137
- const data = new FormData();
138
- for (const value of this.values) {
139
- data.append(this.name, value);
157
+ else {
158
+ this.internals.setFormValue(this.value);
140
159
  }
141
- return data;
142
160
  }
143
161
  validate() {
144
162
  this.reportRequired(!this.answered, 'Choose one to continue.', 'track');
145
163
  }
146
164
  get values() {
147
- return this.multiple ? commaList(this.value) : this.value === '' ? [] : [this.value];
165
+ if (!this.multiple) {
166
+ return this.value === '' ? [] : [this.value];
167
+ }
168
+ return this.chosen && this.chosen.join(',') === this.value
169
+ ? [...this.chosen]
170
+ : commaList(this.value);
148
171
  }
149
172
  set values(next) {
173
+ this.chosen = [...next];
150
174
  this.value = next.join(',');
151
175
  }
176
+ formStateRestoreCallback(state) {
177
+ if (!(state instanceof FormData) || !this.multiple) {
178
+ super.formStateRestoreCallback(state);
179
+ return;
180
+ }
181
+ this.values = state.getAll(this.name);
182
+ }
152
183
  render() {
153
184
  const inside = this.labelPlacement === 'start';
154
185
  const label = this.renderGroupLabel();
155
- return html `${inside ? nothing : label}
156
- <div part="row">
157
- <slot name="start"></slot>
158
- <div part="track">
159
- ${inside ? label : nothing}
160
- <div part="indicator" aria-hidden="true"></div>
161
- <slot
162
- @slotchange=${() => {
163
- this.adopt();
164
- this.sync();
165
- this.indicator.place();
166
- this.requestUpdate();
167
- }}
168
- ></slot>
169
- </div>
170
- <slot name="end"></slot>
171
- </div>
172
- ${this.renderHint()}${this.renderFeedback()}`;
186
+ return html `${inside ? nothing : label}<div part="row"><slot name="start"></slot><div part="track">${inside ? label : nothing}<div part="indicator" aria-hidden="true"></div><slot @slotchange=${this.handleItems}></slot></div><slot name="end"></slot></div>${this.renderHint()}${this.renderFeedback()}`;
173
187
  }
174
188
  };
175
189
  __decorate([
@@ -31,14 +31,12 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends MixinSelectableItem(
31
31
  part="item"
32
32
  type="button"
33
33
  role=${this.pressed === undefined ? 'radio' : nothing}
34
- aria-checked=${this.pressed === undefined ? (this.selected ? 'true' : 'false') : nothing}
34
+ aria-checked=${this.pressed === undefined ? String(this.selected) : nothing}
35
35
  aria-pressed=${this.pressed === undefined ? nothing : String(this.pressed)}
36
36
  ?disabled=${this.disabled}
37
37
  tabindex=${(this.focusable ?? this.selected) || !this.childrenKnown ? '0' : '-1'}
38
38
  @click=${() => this.select()}
39
- >
40
- <slot></slot>
41
- </button>`;
39
+ ><slot></slot></button>`;
42
40
  }
43
41
  };
44
42
  __decorate([
@@ -20,11 +20,20 @@ import { type PropertyValues, type TemplateResult } from 'lit';
20
20
  * The arrows wrap from the last control to the first. Set `stop-at-ends` to
21
21
  * keep them at the ends, as Radix's `loop` set to false does.
22
22
  *
23
- * A nested composite, such as a toggle group, is one stop on the toolbar's
24
- * axis: the toolbar's arrows move past it, and the arrows across the toolbar
25
- * move inside it. A composite with a `focusable` property, as Toggle Group
26
- * has, gives up its own tab stop while the toolbar's is elsewhere, so Tab
27
- * stops once in the toolbar. A composite without one keeps its own tab stop.
23
+ * A toggle group of pressed buttons, `selection-mode="multiple"`, is walked
24
+ * through the same way, each toggle a stop on the toolbar's axis, as React
25
+ * Aria's toolbar walks its toggle buttons. Another nested composite, such as a
26
+ * radio-style toggle group, is one stop on the toolbar's axis: the toolbar's
27
+ * arrows move past it, and the arrows across the toolbar move inside it. A
28
+ * composite with a `focusable` property, as Toggle Group has, gives up its own
29
+ * tab stop while the toolbar's is elsewhere, so Tab stops once in the
30
+ * toolbar. A composite without one keeps its own tab stop.
31
+ *
32
+ * A toolbar inside another toolbar, a Helix one or the page's own
33
+ * `role="toolbar"`, is a `group` of the outer one, as React Aria's is: the
34
+ * outer toolbar's arrows walk through its controls and on past them, and it
35
+ * takes no keys and no tab stop of its own. A server renders it as a toolbar,
36
+ * having no parent to read, until it upgrades.
28
37
  *
29
38
  * @since 0.1.0
30
39
  * @status stable
@@ -123,6 +132,13 @@ export declare class HelixHeadlessToolbar extends HelixElement {
123
132
  * the stop hands it to the first one left.
124
133
  */
125
134
  private readonly restoreTabStop;
135
+ /**
136
+ * Whether this toolbar sits inside another, which then owns the keys and the
137
+ * tab stop: a toolbar inside a toolbar held the reader's arrows inside it.
138
+ * Read when it renders and when it connects, there being no parent on a
139
+ * server.
140
+ */
141
+ private get nested();
126
142
  /**
127
143
  * The orientation in force.
128
144
  *