@fusion.dev/helix-headless 0.147.0 → 0.149.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 (296) hide show
  1. package/custom-elements.json +11222 -2332
  2. package/dist/accordion/item/accordion-item.d.ts +5 -2
  3. package/dist/accordion/item/accordion-item.js +11 -7
  4. package/dist/accordion/root/accordion-root.js +4 -6
  5. package/dist/announcement/root/announcement-root.d.ts +61 -5
  6. package/dist/announcement/root/announcement-root.js +126 -20
  7. package/dist/area-chart/root/area-chart-root.d.ts +11 -0
  8. package/dist/area-chart/root/area-chart-root.js +21 -9
  9. package/dist/avatar/group/avatar-group.d.ts +10 -2
  10. package/dist/avatar/group/avatar-group.js +10 -5
  11. package/dist/badge/count.d.ts +19 -0
  12. package/dist/badge/count.js +20 -0
  13. package/dist/badge/root/badge-root.d.ts +6 -2
  14. package/dist/badge/root/badge-root.js +8 -22
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +13 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +17 -4
  17. package/dist/blockquote/root/blockquote-root.d.ts +66 -8
  18. package/dist/blockquote/root/blockquote-root.js +85 -8
  19. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +2 -2
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +8 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +5 -2
  22. package/dist/button/root/button-root.d.ts +10 -1
  23. package/dist/button/root/button-root.js +3 -2
  24. package/dist/button-group/arrows.d.ts +14 -0
  25. package/dist/button-group/arrows.js +10 -0
  26. package/dist/button-group/root/button-group-root.d.ts +144 -3
  27. package/dist/button-group/root/button-group-root.js +142 -2
  28. package/dist/callout/root/callout-root.d.ts +16 -2
  29. package/dist/callout/root/callout-root.js +16 -4
  30. package/dist/canvas/describe.d.ts +10 -0
  31. package/dist/canvas/describe.js +9 -0
  32. package/dist/canvas/edge-pan.d.ts +61 -0
  33. package/dist/canvas/edge-pan.js +63 -0
  34. package/dist/canvas/neighbor.d.ts +17 -0
  35. package/dist/canvas/neighbor.js +1 -0
  36. package/dist/canvas/node/canvas-node.d.ts +12 -2
  37. package/dist/canvas/node/canvas-node.js +8 -3
  38. package/dist/canvas/root/canvas-document.d.ts +10 -0
  39. package/dist/canvas/root/canvas-document.js +1 -0
  40. package/dist/canvas/root/canvas-root.d.ts +168 -9
  41. package/dist/canvas/root/canvas-root.js +239 -69
  42. package/dist/canvas/snap.d.ts +42 -0
  43. package/dist/canvas/snap.js +32 -0
  44. package/dist/carousel/root/carousel-root.d.ts +9 -3
  45. package/dist/carousel/root/carousel-root.js +17 -10
  46. package/dist/chat/composer/chat-composer.d.ts +5 -0
  47. package/dist/chat/composer/chat-composer.js +4 -1
  48. package/dist/chat/message/chat-message.d.ts +9 -5
  49. package/dist/chat/message/chat-message.js +8 -4
  50. package/dist/chat/naming.js +2 -2
  51. package/dist/chat/root/chat-root.d.ts +40 -4
  52. package/dist/chat/root/chat-root.js +38 -14
  53. package/dist/checkbox/root/checkbox-root.d.ts +11 -0
  54. package/dist/checkbox/root/checkbox-root.js +8 -2
  55. package/dist/checkbox-group/root/checkbox-group-root.d.ts +24 -0
  56. package/dist/checkbox-group/root/checkbox-group-root.js +28 -12
  57. package/dist/checkbox-group/select-all.d.ts +11 -0
  58. package/dist/checkbox-group/select-all.js +5 -0
  59. package/dist/code-block/root/code-block-root.d.ts +20 -8
  60. package/dist/code-block/root/code-block-root.js +16 -5
  61. package/dist/color-input/root/color-input-root.d.ts +13 -0
  62. package/dist/color-input/root/color-input-root.js +18 -5
  63. package/dist/color-picker/root/color-picker-root.d.ts +19 -3
  64. package/dist/color-picker/root/color-picker-root.js +52 -24
  65. package/dist/color-picker/wheel.d.ts +11 -0
  66. package/dist/color-picker/wheel.js +9 -0
  67. package/dist/combobox/root/combobox-root.d.ts +106 -18
  68. package/dist/combobox/root/combobox-root.js +101 -26
  69. package/dist/command/root/command-root.d.ts +19 -9
  70. package/dist/command/root/command-root.js +9 -4
  71. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  72. package/dist/copy-button/root/copy-button-root.js +7 -2
  73. package/dist/data-table/root/data-table-root.d.ts +171 -29
  74. package/dist/data-table/root/data-table-root.js +284 -161
  75. package/dist/date-input/root/date-input-root.d.ts +32 -9
  76. package/dist/date-input/root/date-input-root.js +66 -44
  77. package/dist/date-picker/root/date-picker-root.d.ts +38 -15
  78. package/dist/date-picker/root/date-picker-root.js +52 -33
  79. package/dist/description-list/item/description-list-item.d.ts +4 -0
  80. package/dist/description-list/item/description-list-item.js +7 -1
  81. package/dist/dialog/root/dialog-root.d.ts +12 -1
  82. package/dist/dialog/root/dialog-root.js +11 -4
  83. package/dist/divider/root/divider-root.d.ts +45 -16
  84. package/dist/divider/root/divider-root.js +28 -4
  85. package/dist/donut-chart/root/donut-chart-root.d.ts +5 -0
  86. package/dist/donut-chart/root/donut-chart-root.js +8 -5
  87. package/dist/drawer/root/drawer-root.d.ts +12 -1
  88. package/dist/drawer/root/drawer-root.js +9 -2
  89. package/dist/drilldown/item/drilldown-item.js +3 -4
  90. package/dist/drilldown/root/drilldown-root.d.ts +5 -0
  91. package/dist/drilldown/root/drilldown-root.js +4 -1
  92. package/dist/element-events.generated.js +26 -3
  93. package/dist/empty/root/empty-root.d.ts +17 -3
  94. package/dist/empty/root/empty-root.js +29 -5
  95. package/dist/file-input/root/file-input-root.d.ts +18 -3
  96. package/dist/file-input/root/file-input-root.js +34 -18
  97. package/dist/file-input/status.js +2 -1
  98. package/dist/filter-input/chip/filter-chip.d.ts +13 -0
  99. package/dist/filter-input/chip/filter-chip.js +7 -3
  100. package/dist/filter-input/menu/filter-menu.d.ts +5 -0
  101. package/dist/filter-input/menu/filter-menu.js +3 -1
  102. package/dist/filter-input/root/filter-input-root.d.ts +20 -3
  103. package/dist/filter-input/root/filter-input-root.js +8 -4
  104. package/dist/format-date/fields.d.ts +20 -0
  105. package/dist/format-date/fields.js +14 -0
  106. package/dist/format-date/options.d.ts +2 -1
  107. package/dist/format-date/options.js +9 -38
  108. package/dist/format-date/root/format-date-root.d.ts +55 -5
  109. package/dist/format-date/root/format-date-root.js +29 -34
  110. package/dist/graph/root/graph-model.d.ts +11 -0
  111. package/dist/graph/root/graph-model.js +4 -0
  112. package/dist/graph/root/graph-root.d.ts +101 -14
  113. package/dist/graph/root/graph-root.js +140 -46
  114. package/dist/heatmap/root/heatmap-root.d.ts +37 -4
  115. package/dist/heatmap/root/heatmap-root.js +51 -16
  116. package/dist/icon-button/root/icon-button-root.d.ts +5 -0
  117. package/dist/icon-button/root/icon-button-root.js +1 -0
  118. package/dist/image/root/image-root.d.ts +11 -0
  119. package/dist/input/root/input-root.d.ts +5 -0
  120. package/dist/input/root/input-root.js +4 -1
  121. package/dist/kbd/root/kbd-root.js +1 -2
  122. package/dist/legend/root/legend-root.js +4 -17
  123. package/dist/lightbox/root/lightbox-root.d.ts +14 -4
  124. package/dist/lightbox/root/lightbox-root.js +25 -7
  125. package/dist/line-chart/root/line-chart-root.d.ts +5 -0
  126. package/dist/line-chart/root/line-chart-root.js +4 -2
  127. package/dist/list/item/list-item.d.ts +32 -0
  128. package/dist/list/item/list-item.js +34 -7
  129. package/dist/list/root/list-root.d.ts +87 -0
  130. package/dist/list/root/list-root.js +119 -23
  131. package/dist/listbox/reorder/index.d.ts +1 -0
  132. package/dist/listbox/reorder/index.js +4 -0
  133. package/dist/listbox/reorder/listbox-reorder.d.ts +83 -0
  134. package/dist/listbox/reorder/listbox-reorder.js +151 -0
  135. package/dist/listbox/root/listbox-root.d.ts +185 -33
  136. package/dist/listbox/root/listbox-root.js +166 -136
  137. package/dist/loader/root/loader-root.d.ts +5 -0
  138. package/dist/loader/root/loader-root.js +3 -1
  139. package/dist/map/area/map-area.d.ts +5 -0
  140. package/dist/map/area/map-area.js +3 -1
  141. package/dist/map/buildings/map-buildings.d.ts +5 -0
  142. package/dist/map/buildings/map-buildings.js +3 -1
  143. package/dist/map/contours/map-contours.d.ts +5 -0
  144. package/dist/map/contours/map-contours.js +3 -1
  145. package/dist/map/landcover/map-landcover.d.ts +5 -0
  146. package/dist/map/landcover/map-landcover.js +3 -1
  147. package/dist/map/marker/map-marker.d.ts +18 -2
  148. package/dist/map/marker/map-marker.js +13 -5
  149. package/dist/map/points/map-points.d.ts +5 -0
  150. package/dist/map/points/map-points.js +6 -4
  151. package/dist/map/position/map-position.d.ts +5 -0
  152. package/dist/map/position/map-position.js +3 -1
  153. package/dist/map/raster/map-raster.d.ts +5 -0
  154. package/dist/map/raster/map-raster.js +3 -1
  155. package/dist/map/root/map-root.d.ts +73 -16
  156. package/dist/map/root/map-root.js +122 -44
  157. package/dist/map/route/map-route.d.ts +5 -0
  158. package/dist/map/route/map-route.js +3 -1
  159. package/dist/map/terrain/map-terrain.d.ts +5 -0
  160. package/dist/map/terrain/map-terrain.js +3 -1
  161. package/dist/megamenu/root/megamenu-root.js +4 -11
  162. package/dist/menu/root/menu-root.d.ts +7 -2
  163. package/dist/menu/root/menu-root.js +3 -1
  164. package/dist/meter/root/meter-root.d.ts +16 -3
  165. package/dist/meter/root/meter-root.js +12 -5
  166. package/dist/navigation/root/navigation-root.d.ts +5 -0
  167. package/dist/navigation/root/navigation-root.js +7 -8
  168. package/dist/notifications/group/notification-group.d.ts +8 -1
  169. package/dist/notifications/group/notification-group.js +12 -6
  170. package/dist/notifications/notification/notification.d.ts +17 -1
  171. package/dist/notifications/notification/notification.js +6 -2
  172. package/dist/notifications/root/notifications-root.d.ts +49 -5
  173. package/dist/notifications/root/notifications-root.js +36 -8
  174. package/dist/number-input/root/number-input-root.d.ts +21 -8
  175. package/dist/number-input/root/number-input-root.js +26 -11
  176. package/dist/object-inspector/root/object-inspector-root.d.ts +56 -13
  177. package/dist/object-inspector/root/object-inspector-root.js +41 -30
  178. package/dist/outline/root/outline-root.d.ts +5 -0
  179. package/dist/outline/root/outline-root.js +3 -1
  180. package/dist/pagination/root/pagination-root.d.ts +7 -1
  181. package/dist/pagination/root/pagination-root.js +16 -7
  182. package/dist/pagination/size/pagination-size.d.ts +8 -3
  183. package/dist/pagination/size/pagination-size.js +5 -3
  184. package/dist/pagination/summary/pagination-summary.d.ts +8 -6
  185. package/dist/pagination/summary/pagination-summary.js +4 -9
  186. package/dist/pin-input/code.d.ts +23 -0
  187. package/dist/pin-input/code.js +21 -0
  188. package/dist/pin-input/root/pin-input-root.d.ts +9 -3
  189. package/dist/pin-input/root/pin-input-root.js +13 -23
  190. package/dist/popover/root/popover-root.d.ts +12 -2
  191. package/dist/popover/root/popover-root.js +10 -4
  192. package/dist/progress/root/progress-root.d.ts +7 -2
  193. package/dist/progress/root/progress-root.js +5 -2
  194. package/dist/qr-code/name.d.ts +3 -2
  195. package/dist/qr-code/name.js +2 -2
  196. package/dist/qr-code/root/qr-code-root.d.ts +26 -5
  197. package/dist/qr-code/root/qr-code-root.js +27 -6
  198. package/dist/radio/group/radio-group.d.ts +11 -0
  199. package/dist/radio/group/radio-group.js +8 -2
  200. package/dist/rating/root/rating-root.d.ts +12 -1
  201. package/dist/rating/root/rating-root.js +10 -3
  202. package/dist/scatter-chart/measures.d.ts +22 -0
  203. package/dist/scatter-chart/measures.js +11 -0
  204. package/dist/scatter-chart/root/scatter-chart-root.d.ts +22 -8
  205. package/dist/scatter-chart/root/scatter-chart-root.js +25 -23
  206. package/dist/select/root/select-root.d.ts +67 -8
  207. package/dist/select/root/select-root.js +45 -11
  208. package/dist/skip-link/root/skip-link-root.d.ts +5 -0
  209. package/dist/skip-link/root/skip-link-root.js +3 -1
  210. package/dist/slider/root/slider-root.d.ts +7 -2
  211. package/dist/slider/root/slider-root.js +11 -5
  212. package/dist/sparkline/readings.d.ts +15 -5
  213. package/dist/sparkline/readings.js +3 -3
  214. package/dist/sparkline/root/sparkline-root.d.ts +9 -4
  215. package/dist/sparkline/root/sparkline-root.js +9 -3
  216. package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
  217. package/dist/speed-dial/group/speed-dial-group.js +43 -0
  218. package/dist/speed-dial/index.d.ts +1 -0
  219. package/dist/speed-dial/index.js +1 -0
  220. package/dist/speed-dial/item/speed-dial-item.d.ts +26 -1
  221. package/dist/speed-dial/item/speed-dial-item.js +41 -3
  222. package/dist/speed-dial/long-press.d.ts +50 -0
  223. package/dist/speed-dial/long-press.js +48 -0
  224. package/dist/speed-dial/root/speed-dial-root.d.ts +85 -1
  225. package/dist/speed-dial/root/speed-dial-root.js +117 -5
  226. package/dist/splitter/root/splitter-root.d.ts +12 -3
  227. package/dist/splitter/root/splitter-root.js +22 -4
  228. package/dist/steps/root/steps-root.d.ts +9 -2
  229. package/dist/steps/root/steps-root.js +6 -3
  230. package/dist/steps/step/step.d.ts +12 -0
  231. package/dist/steps/step/step.js +11 -2
  232. package/dist/switch/root/switch-root.d.ts +11 -0
  233. package/dist/switch/root/switch-root.js +8 -2
  234. package/dist/table/cell/table-cell.d.ts +8 -1
  235. package/dist/table/cell/table-cell.js +6 -2
  236. package/dist/table/column/table-column.d.ts +11 -4
  237. package/dist/table/column/table-column.js +15 -10
  238. package/dist/table/grid-controller.d.ts +122 -0
  239. package/dist/table/grid-controller.js +299 -0
  240. package/dist/table/root/table-root.d.ts +154 -8
  241. package/dist/table/root/table-root.js +197 -38
  242. package/dist/table/row/table-row.d.ts +55 -1
  243. package/dist/table/row/table-row.js +60 -7
  244. package/dist/tabs/root/tabs-root.d.ts +5 -0
  245. package/dist/tabs/root/tabs-root.js +3 -1
  246. package/dist/tag/group/tag-group.d.ts +5 -0
  247. package/dist/tag/group/tag-group.js +8 -15
  248. package/dist/tag/root/tag-root.d.ts +14 -1
  249. package/dist/tag/root/tag-root.js +11 -8
  250. package/dist/textarea/root/textarea-root.d.ts +5 -0
  251. package/dist/textarea/root/textarea-root.js +3 -1
  252. package/dist/time-input/root/time-input-root.d.ts +14 -7
  253. package/dist/time-input/root/time-input-root.js +43 -32
  254. package/dist/time-picker/root/time-picker-root.d.ts +16 -7
  255. package/dist/time-picker/root/time-picker-root.js +28 -12
  256. package/dist/toast/item/toast-item.d.ts +13 -3
  257. package/dist/toast/item/toast-item.js +2 -0
  258. package/dist/toast/root/toast-root.d.ts +22 -2
  259. package/dist/toast/root/toast-root.js +24 -17
  260. package/dist/toggle/group/toggle-group.js +3 -5
  261. package/dist/toolbar/root/toolbar-root.d.ts +36 -0
  262. package/dist/toolbar/root/toolbar-root.js +43 -9
  263. package/dist/tooltip/root/tooltip-root.d.ts +27 -17
  264. package/dist/tooltip/root/tooltip-root.js +1 -2
  265. package/dist/tour/root/tour-root.d.ts +8 -2
  266. package/dist/tour/root/tour-root.js +4 -2
  267. package/dist/tour/stop/tour-stop.d.ts +5 -0
  268. package/dist/tour/stop/tour-stop.js +6 -1
  269. package/dist/tree/grip.d.ts +5 -0
  270. package/dist/tree/grip.js +1 -0
  271. package/dist/tree/item/tree-item.d.ts +24 -0
  272. package/dist/tree/item/tree-item.js +27 -5
  273. package/dist/tree/root/tree-root.d.ts +66 -1
  274. package/dist/tree/root/tree-root.js +77 -5
  275. package/dist/trend/root/trend-root.d.ts +20 -4
  276. package/dist/trend/root/trend-root.js +20 -5
  277. package/dist/video/root/video-root.d.ts +23 -3
  278. package/dist/video/root/video-root.js +56 -15
  279. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
  280. package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
  281. package/dist/video-playlist/root/video-playlist-root.d.ts +5 -0
  282. package/dist/video-playlist/root/video-playlist-root.js +3 -1
  283. package/dist/virtual-list/root/virtual-list-root.d.ts +19 -3
  284. package/dist/virtual-list/root/virtual-list-root.js +10 -19
  285. package/lint.json +1 -1
  286. package/package.json +7 -6
  287. package/types/jsx.d.ts +6005 -2114
  288. package/types/svelte.d.ts +1 -0
  289. package/types/vue.d.ts +1594 -676
  290. package/types/words.d.ts +3280 -0
  291. package/dist/kbd/keys.d.ts +0 -29
  292. package/dist/kbd/keys.js +0 -52
  293. package/dist/toast/hotkey.d.ts +0 -22
  294. package/dist/toast/hotkey.js +0 -23
  295. package/dist/tooltip/focus-target.d.ts +0 -6
  296. package/dist/tooltip/focus-target.js +0 -9
@@ -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 { clockLocale, commaList, customElement, dayPeriod, fillTemplate, HelixFormElement, hostWords, inlineStep, isTwelveHour, localeOf, MixinControllerValue, MixinPickerFeedback, nearestTime, offeredTimes, reportValues, secondsAsValue, timeBarred, timeFault, valueAsSeconds, wheelParts, wholeHour, writeClock, } from '@fusion.dev/helix-core';
7
+ import { clockLocale, commaList, customElement, dayPeriod, formatWords, HelixFormElement, hostWords, inlineStep, isTwelveHour, MixinControllerValue, MixinPickerFeedback, nearestTime, offeredTimes, reportValues, secondsAsValue, timeBarred, timeFault, valueAsSeconds, wheelParts, wholeHour, words, wordsLocale, writeClock, } 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';
@@ -14,12 +14,15 @@ import '../../option/index.js';
14
14
  let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerFeedback(MixinControllerValue(HelixFormElement)) {
15
15
  constructor() {
16
16
  super(...arguments);
17
+ this.badInputMessage = '{mode, select, single {Enter a time as {shape}.} other {Enter times as {shape}, separated by commas.}}';
17
18
  this.disableTimes = '';
18
19
  this.label = 'Time';
19
20
  this.locale = '';
20
21
  this.manual = false;
21
22
  this.max = '23:59';
22
23
  this.min = '00:00';
24
+ this.rangeOverflowMessage = 'Choose a time at or before {max}.';
25
+ this.rangeUnderflowMessage = 'Choose a time at or after {min}.';
23
26
  this.handleListInput = (event) => {
24
27
  event.stopPropagation();
25
28
  };
@@ -76,6 +79,9 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
76
79
  this.required = false;
77
80
  this.seconds = false;
78
81
  this.step = 15;
82
+ this.stepMismatchMessage = 'Choose one of the times on offer.';
83
+ this.unavailableMessage = 'Choose a time that is available.';
84
+ this.valueMissingMessage = 'Choose a time.';
79
85
  this.listRevealed = false;
80
86
  this.naming = undefined;
81
87
  this.handleColumnsKeydown = (event) => {
@@ -93,8 +99,9 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
93
99
  next.focus();
94
100
  };
95
101
  }
102
+ static { this.words = 'helix-time-picker'; }
96
103
  get language() {
97
- return localeOf(this, this.locale);
104
+ return wordsLocale(this);
98
105
  }
99
106
  get times() {
100
107
  return offeredTimes(this.min, this.max, this.step, this.seconds);
@@ -183,21 +190,21 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
183
190
  case 'rangeUnderflow':
184
191
  return [
185
192
  'rangeUnderflow',
186
- fillTemplate(this.rangeUnderflowMessage || 'Choose a time at or after {min}.', {
193
+ formatWords(this, 'rangeUnderflowMessage', {
187
194
  min: writeClock(this.min, this.clock, this.seconds),
188
195
  }),
189
196
  ];
190
197
  case 'rangeOverflow':
191
198
  return [
192
199
  'rangeOverflow',
193
- fillTemplate(this.rangeOverflowMessage || 'Choose a time at or before {max}.', {
200
+ formatWords(this, 'rangeOverflowMessage', {
194
201
  max: writeClock(this.max, this.clock, this.seconds),
195
202
  }),
196
203
  ];
197
204
  case 'unavailable':
198
- return ['badInput', this.unavailableMessage || 'Choose a time that is available.'];
205
+ return ['badInput', this.unavailableMessage];
199
206
  case 'stepMismatch':
200
- return ['stepMismatch', this.stepMismatchMessage || 'Choose one of the times on offer.'];
207
+ return ['stepMismatch', this.stepMismatchMessage];
201
208
  default:
202
209
  return undefined;
203
210
  }
@@ -205,16 +212,15 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
205
212
  reportRequired() {
206
213
  const anchor = this.partNamed('list') ?? undefined;
207
214
  if (this.required && this.value === '') {
208
- this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage || 'Choose a time.', anchor);
215
+ this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage, anchor);
209
216
  return;
210
217
  }
211
218
  const held = this.held;
212
219
  if (held.length > 0 && held.some((one) => valueAsSeconds(one) === null)) {
213
- const shape = this.seconds ? 'HH:mm:ss' : 'HH:mm';
214
- this.internals.setValidity({ badInput: true }, this.badInputMessage ||
215
- (this.mode === undefined
216
- ? `Enter a time as ${shape}.`
217
- : `Enter times as ${shape}, separated by commas.`), anchor);
220
+ this.internals.setValidity({ badInput: true }, formatWords(this, 'badInputMessage', {
221
+ mode: this.mode ?? 'single',
222
+ shape: this.seconds ? 'HH:mm:ss' : 'HH:mm',
223
+ }), anchor);
218
224
  return;
219
225
  }
220
226
  for (const one of held) {
@@ -256,6 +262,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
256
262
  willUpdate(changed) {
257
263
  super.willUpdate(changed);
258
264
  this.report();
265
+ this.toggleState('blank', this.value === '');
259
266
  }
260
267
  updated(changed) {
261
268
  super.updated(changed);
@@ -277,6 +284,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
277
284
  return html `<${this.tag('listbox')}
278
285
  part="column"
279
286
  data-column=${part}
287
+ aria-describedby=${this.feedback === '' ? nothing : 'feedback'}
280
288
  aria-invalid=${this.marked ? 'true' : nothing}
281
289
  exportparts="empty: column-empty, error: column-error, feedback: column-feedback, filter-icon: column-filter-icon,
282
290
  filter-mark: column-filter-mark, hint: column-hint, items: column-items, label: column-label,
@@ -328,6 +336,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
328
336
  renderList() {
329
337
  return html `<${this.tag('listbox')}
330
338
  part="list"
339
+ aria-describedby=${this.feedback === '' ? nothing : 'feedback'}
331
340
  aria-invalid=${this.marked ? 'true' : nothing}
332
341
  exportparts="empty: list-empty, error: list-error, feedback: list-feedback, filter-icon: list-filter-icon,
333
342
  filter-mark: list-filter-mark, hint: list-hint, items: list-items, label: list-label,
@@ -382,6 +391,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
382
391
  }
383
392
  };
384
393
  __decorate([
394
+ words,
385
395
  property({ attribute: 'bad-input-message' })
386
396
  ], HelixHeadlessTimePicker.prototype, "badInputMessage", void 0);
387
397
  __decorate([
@@ -394,6 +404,7 @@ __decorate([
394
404
  property({ attribute: 'hour-label' })
395
405
  ], HelixHeadlessTimePicker.prototype, "hourLabel", void 0);
396
406
  __decorate([
407
+ words,
397
408
  property()
398
409
  ], HelixHeadlessTimePicker.prototype, "label", void 0);
399
410
  __decorate([
@@ -418,9 +429,11 @@ __decorate([
418
429
  property({ reflect: true })
419
430
  ], HelixHeadlessTimePicker.prototype, "mode", void 0);
420
431
  __decorate([
432
+ words,
421
433
  property({ attribute: 'range-overflow-message' })
422
434
  ], HelixHeadlessTimePicker.prototype, "rangeOverflowMessage", void 0);
423
435
  __decorate([
436
+ words,
424
437
  property({ attribute: 'range-underflow-message' })
425
438
  ], HelixHeadlessTimePicker.prototype, "rangeUnderflowMessage", void 0);
426
439
  __decorate([
@@ -439,12 +452,15 @@ __decorate([
439
452
  property({ type: Number })
440
453
  ], HelixHeadlessTimePicker.prototype, "step", void 0);
441
454
  __decorate([
455
+ words,
442
456
  property({ attribute: 'step-mismatch-message' })
443
457
  ], HelixHeadlessTimePicker.prototype, "stepMismatchMessage", void 0);
444
458
  __decorate([
459
+ words,
445
460
  property({ attribute: 'unavailable-message' })
446
461
  ], HelixHeadlessTimePicker.prototype, "unavailableMessage", void 0);
447
462
  __decorate([
463
+ words,
448
464
  property({ attribute: 'value-missing-message' })
449
465
  ], HelixHeadlessTimePicker.prototype, "valueMissingMessage", void 0);
450
466
  __decorate([
@@ -10,7 +10,8 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
10
10
  *
11
11
  * **Each item runs its own timer.** A timer held by the region would restart
12
12
  * with each new message, and the last of three messages would stay for nine
13
- * seconds.
13
+ * seconds. It pauses while the pointer or focus is on the message, and while
14
+ * the page is hidden, so a message is not spent in a background tab.
14
15
  *
15
16
  * **Each message is an `alertdialog` named by its words**, which is how a reader
16
17
  * who moves into the stack hears which message they are on. Give it a
@@ -58,6 +59,13 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
58
59
  * @cssproperty --toast-swipe-x - How far a swipe has moved the message across, in pixels, toward the right.
59
60
  */
60
61
  export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base {
62
+ /**
63
+ * The key this part's words are registered under, its styled tag. The close
64
+ * control's `dismiss-label` comes from a mixin other families share, and
65
+ * registers as `{ 'helix-toast-item': { dismissLabel: 'Schließen' } }` once
66
+ * that mixin declares it a word.
67
+ */
68
+ static words: string;
61
69
  /**
62
70
  * How long the message stays, in milliseconds. When it is not set, the
63
71
  * message stays until it is dismissed.
@@ -85,8 +93,10 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
85
93
  /** Writes how far a swipe has moved the message toward the end of the line. */
86
94
  private slide;
87
95
  /**
88
- * The dismiss timer, which pauses while a reader is on the message and
89
- * continues from what was left.
96
+ * The dismiss timer, which pauses while a reader is on the message, and
97
+ * while the page is hidden, and continues from what was left. A message that
98
+ * arrives in a background tab waits for the reader to come back, as React
99
+ * Aria's toast queue does.
90
100
  *
91
101
  * Paused is said on the host so the indicator can freeze with the clock. A
92
102
  * `data-` attribute rather than a property, because it is written after
@@ -35,6 +35,7 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
35
35
  done: () => {
36
36
  this.dismiss();
37
37
  },
38
+ holdWhileHidden: true,
38
39
  paused: (paused) => {
39
40
  this.toggleAttribute('data-paused', paused);
40
41
  },
@@ -58,6 +59,7 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
58
59
  });
59
60
  };
60
61
  }
62
+ static { this.words = 'helix-toast-item'; }
61
63
  get open() {
62
64
  return this.openState ?? true;
63
65
  }
@@ -63,9 +63,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
63
63
  * @csspart region - The stack the messages are in. It is in the top layer while a message shows, and takes focus from `hotkey` where no message holds a control.
64
64
  */
65
65
  export declare class HelixHeadlessToast extends HelixElement {
66
+ /**
67
+ * The key this family's words are registered under, its styled tag:
68
+ * `registerWords('de', { 'helix-toast': { label: 'Benachrichtigungen ({hotkey})' } })`.
69
+ * A message's own words are under `helix-toast-item`.
70
+ */
71
+ static words: string;
66
72
  /**
67
73
  * The key that takes focus to the stack and back, such as `F8` or `Alt+T`:
68
- * keys joined by `+`, the last one the key. Empty turns it off.
74
+ * keys joined by `+`, the last one the key, as `Announcement`'s `hotkey`
75
+ * reads them: `mod` is Command on Apple devices and Control elsewhere.
76
+ * Empty turns it off.
69
77
  */
70
78
  hotkey: string;
71
79
  /**
@@ -106,12 +114,24 @@ export declare class HelixHeadlessToast extends HelixElement {
106
114
  /** What the assertive region is saying. */
107
115
  private urgent;
108
116
  private readonly hush;
117
+ /**
118
+ * Words waiting for the next frame: the polite ones and the urgent ones.
119
+ *
120
+ * Collected rather than written straight in, because the accessibility tree
121
+ * is built once a frame: two messages that arrive in separate tasks of one
122
+ * frame would otherwise each overwrite the region, and only the second
123
+ * would be heard.
124
+ */
125
+ private readonly pending;
126
+ /** Whether a frame is already coming to say what is pending. */
127
+ private filling;
109
128
  /**
110
129
  * Says messages that have just arrived, each once, `danger` ones assertively.
111
130
  *
112
131
  * Emptied first and filled a frame later, so a message with the same words
113
132
  * as the one before is still a change, and so a region the stack has just
114
- * shown is in the accessibility tree before its words land.
133
+ * shown is in the accessibility tree before its words land. Every message
134
+ * that arrives before that frame is said in it, each as its own sentence.
115
135
  */
116
136
  private announce;
117
137
  /**
@@ -4,11 +4,10 @@ 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, DelayController, deepActiveElement, deepContains, FocusScopeController, fillTemplate, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
7
+ import { animationsFinished, customElement, DelayController, deepActiveElement, deepContains, FocusScopeController, focusableElements, formatWords, HelixElement, hostAria, matchesChord, onApple, scrollHolders, words, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
- import { matchesHotkey, parseHotkey } from '../hotkey.js';
11
- import { messageWords } from '../words.js';
10
+ import { joinSaid, messageWords } from '../words.js';
12
11
  let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
13
12
  constructor() {
14
13
  super(...arguments);
@@ -17,6 +16,8 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
17
16
  this.said = '';
18
17
  this.urgent = '';
19
18
  this.hush = new DelayController(this, { renders: false });
19
+ this.pending = { said: [], urgent: [] };
20
+ this.filling = false;
20
21
  this.scope = new FocusScopeController(this, {
21
22
  contents: () => this.showing.flatMap((one) => {
22
23
  const target = focusTarget(one);
@@ -25,7 +26,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
25
26
  surface: () => this.region,
26
27
  });
27
28
  this.handleHotkey = (event) => {
28
- if (event.defaultPrevented || !matchesHotkey(event, parseHotkey(this.hotkey))) {
29
+ if (event.defaultPrevented || !matchesChord(event, this.hotkey, onApple())) {
29
30
  return;
30
31
  }
31
32
  if (this.scope.holdsFocus) {
@@ -83,27 +84,34 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
83
84
  });
84
85
  };
85
86
  }
87
+ static { this.words = 'helix-toast'; }
86
88
  willUpdate(changed) {
87
89
  super.willUpdate(changed);
88
90
  hostAria(this.internals, {
89
- label: fillTemplate(this.label, { hotkey: this.hotkey }),
91
+ label: formatWords(this, 'label', { hotkey: this.hotkey }),
90
92
  role: 'region',
91
93
  });
92
94
  }
93
95
  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() === '') {
96
+ for (const one of arrived) {
97
+ const words = messageWords(one);
98
+ if (words !== '') {
99
+ ;
100
+ (isDanger(one) ? this.pending.urgent : this.pending.said).push(words);
101
+ }
102
+ }
103
+ if (this.filling || (this.pending.said.length === 0 && this.pending.urgent.length === 0)) {
100
104
  return;
101
105
  }
106
+ this.filling = true;
102
107
  this.said = '';
103
108
  this.urgent = '';
104
109
  const fill = () => {
105
- this.said = said;
106
- this.urgent = urgent;
110
+ this.filling = false;
111
+ this.said = joinSaid(this.pending.said);
112
+ this.urgent = joinSaid(this.pending.urgent);
113
+ this.pending.said = [];
114
+ this.pending.urgent = [];
107
115
  this.hush.start(1000, () => {
108
116
  this.said = '';
109
117
  this.urgent = '';
@@ -161,8 +169,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
161
169
  continue;
162
170
  }
163
171
  this.made.delete(one);
164
- const running = typeof one.getAnimations === 'function' ? one.getAnimations({ subtree: true }) : [];
165
- void Promise.allSettled(running.map((animation) => animation.finished)).then(() => one.remove());
172
+ void animationsFinished(one).then(() => one.remove());
166
173
  }
167
174
  }
168
175
  get showing() {
@@ -194,8 +201,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
194
201
  }
195
202
  }
196
203
  lowerWhenStill(region) {
197
- const running = typeof this.getAnimations === 'function' ? this.getAnimations({ subtree: true }) : [];
198
- void Promise.allSettled(running.map((one) => one.finished)).then(() => {
204
+ void animationsFinished(this).then(() => {
199
205
  if (this.showing.length === 0 && popoverOpen(region)) {
200
206
  region.hidePopover();
201
207
  }
@@ -266,6 +272,7 @@ __decorate([
266
272
  property()
267
273
  ], HelixHeadlessToast.prototype, "hotkey", void 0);
268
274
  __decorate([
275
+ words,
269
276
  property()
270
277
  ], HelixHeadlessToast.prototype, "label", void 0);
271
278
  __decorate([
@@ -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, reportValues, rovingStop, toggleValue, } from '@fusion.dev/helix-core';
7
+ import { commaList, customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, reportValues, rovingStop, toggleValue, toolbarAround, } 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';
@@ -139,9 +139,7 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
139
139
  if (!this.multiple) {
140
140
  return 'radiogroup';
141
141
  }
142
- return this.parentElement?.closest('[role=toolbar],helix-toolbar,helix-headless-toolbar')
143
- ? 'group'
144
- : 'toolbar';
142
+ return toolbarAround(this) ? 'group' : 'toolbar';
145
143
  }
146
144
  willUpdate(changed) {
147
145
  super.willUpdate(changed);
@@ -152,7 +150,7 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
152
150
  this.internals.setFormValue(null);
153
151
  }
154
152
  else if (this.multiple) {
155
- reportValues(this.internals, this.name, this.values);
153
+ reportValues(this.internals, this.name, this.values, { state: 'entries' });
156
154
  }
157
155
  else {
158
156
  this.internals.setFormValue(this.value);
@@ -12,6 +12,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
12
12
  * focus counts as a control, including your own elements. A child that takes no
13
13
  * focus, such as a divider, is skipped. A menu is reached at its trigger.
14
14
  *
15
+ * A Divider in the toolbar is a separator across the toolbar's axis, as React
16
+ * Aria's is: vertical in a horizontal toolbar and horizontal in a vertical
17
+ * one, without an `orientation` of its own.
18
+ *
15
19
  * Controls inside a plain wrapper, such as a `Button Group`, are each a stop
16
20
  * of the toolbar's own, as React Aria's toolbar flattens a group: the arrows
17
21
  * walk through the group's buttons and on past it, and the group takes no tab
@@ -20,6 +24,28 @@ import { type PropertyValues, type TemplateResult } from 'lit';
20
24
  * The arrows wrap from the last control to the first. Set `stop-at-ends` to
21
25
  * keep them at the ends, as Radix's `loop` set to false does.
22
26
  *
27
+ * **Keyboard.** Tab enters the toolbar on the control that last had focus, the
28
+ * first control at the start, and the next Tab leaves it.
29
+ *
30
+ * | Key | What it does |
31
+ * |---|---|
32
+ * | Right | Moves to the next control in a horizontal toolbar, from the last back to the first. |
33
+ * | Left | Moves to the control before in a horizontal toolbar, from the first round to the last. |
34
+ * | Down, Up | The same in a vertical toolbar. |
35
+ * | Home, End | Moves to the first or the last control. |
36
+ *
37
+ * Left and Right swap on a right-to-left page, where the first control is on
38
+ * the right. The arrows across the toolbar's axis are left to the control that
39
+ * has focus, so a radio-style toggle group or a select answers them itself.
40
+ * The toolbar is `role="toolbar"` with `aria-orientation`, named by `label`.
41
+ *
42
+ * The stop moves through a control's own `focusable` property where it has
43
+ * one, as Button, Select and Toggle Group do. A control without one has
44
+ * `tabindex` written on the element that takes focus: a native element
45
+ * itself, or the control inside a custom element's open shadow root, so the
46
+ * host keeps the markup you rendered. Only a custom element whose shadow root
47
+ * is closed takes it on the host.
48
+ *
23
49
  * A toggle group of pressed buttons, `selection-mode="multiple"`, is walked
24
50
  * through the same way, each toggle a stop on the toolbar's axis, as React
25
51
  * Aria's toolbar walks its toggle buttons. Another nested composite, such as a
@@ -44,8 +70,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
44
70
  * @slot - The toolbar's controls.
45
71
  *
46
72
  * @csspart toolbar - The toolbar container.
73
+ *
74
+ * @cssstate horizontal - The controls run along a row, which is the default.
75
+ * @cssstate nested - The toolbar is a group inside another toolbar, which owns the keys and the tab stop.
76
+ * @cssstate vertical - The controls run down a column, under `orientation="vertical"`.
47
77
  */
48
78
  export declare class HelixHeadlessToolbar extends HelixElement {
79
+ /**
80
+ * The key this family's words are registered under, its styled tag:
81
+ * `registerWords('de', { 'helix-toolbar': { label: 'Werkzeugleiste' } })`.
82
+ */
83
+ static words: string;
49
84
  /**
50
85
  * The toolbar's name, read by screen readers.
51
86
  *
@@ -159,6 +194,7 @@ export declare class HelixHeadlessToolbar extends HelixElement {
159
194
  connectedCallback(): void;
160
195
  disconnectedCallback(): void;
161
196
  protected firstUpdated(changed: PropertyValues): void;
197
+ protected willUpdate(changed: PropertyValues): void;
162
198
  protected render(): TemplateResult;
163
199
  }
164
200
  declare global {
@@ -5,13 +5,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixHeadlessToolbar_1;
8
- import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, } from '@fusion.dev/helix-core';
8
+ import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, toolbarAround, words, } from '@fusion.dev/helix-core';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
11
11
  const KEYS = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End']);
12
12
  const ownsTabStop = (node) => 'focusable' in node;
13
13
  const NATIVE = 'a[href], button, input, select, textarea, [tabindex], [contenteditable=""], [contenteditable="true"]';
14
14
  const TABBABLE = NATIVE.replace('[tabindex]', '[tabindex]:not([tabindex="-1"])');
15
+ const innerStops = new WeakMap();
15
16
  const takesFocus = (node) => {
16
17
  if (!(node instanceof HTMLElement) ||
17
18
  node.hasAttribute('disabled') ||
@@ -21,11 +22,29 @@ const takesFocus = (node) => {
21
22
  return (node.matches(NATIVE) ||
22
23
  ownsTabStop(node) ||
23
24
  node.shadowRoot?.delegatesFocus === true ||
24
- node.shadowRoot?.querySelector(TABBABLE) != null);
25
+ node.shadowRoot?.querySelector(TABBABLE) != null ||
26
+ innerStops.get(node)?.isConnected === true);
27
+ };
28
+ const stopOf = (node) => {
29
+ if (node.hasAttribute('tabindex')) {
30
+ return node;
31
+ }
32
+ const held = innerStops.get(node);
33
+ if (held?.isConnected && held.getRootNode() === node.shadowRoot) {
34
+ return held;
35
+ }
36
+ const inner = node.localName.includes('-')
37
+ ? node.shadowRoot?.querySelector(TABBABLE)
38
+ : null;
39
+ if (!inner) {
40
+ return node;
41
+ }
42
+ innerStops.set(node, inner);
43
+ return inner;
25
44
  };
26
45
  const flattens = (node) => ownsTabStop(node) &&
27
46
  node.selectionMode === 'multiple';
28
- let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar extends HelixElement {
47
+ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
29
48
  constructor() {
30
49
  super(...arguments);
31
50
  this.label = 'Toolbar';
@@ -58,7 +77,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
58
77
  if (ownsTabStop(element)) {
59
78
  return element.focusable;
60
79
  }
61
- return composite || element.tabIndex === 0;
80
+ return composite || stopOf(element).tabIndex === 0;
62
81
  });
63
82
  if (controls.length > 0 && !held) {
64
83
  this.setTabStop(controls[0], false);
@@ -116,11 +135,14 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
116
135
  if (element && 'focusItem' in element && typeof element.focusItem === 'function') {
117
136
  element.focusItem();
118
137
  }
119
- else {
120
- element?.focus();
138
+ else if (element) {
139
+ ;
140
+ (ownsTabStop(element) ? element : stopOf(element)).focus();
121
141
  }
122
142
  };
123
143
  }
144
+ static { HelixHeadlessToolbar_1 = this; }
145
+ static { this.words = 'helix-toolbar'; }
124
146
  get controls() {
125
147
  const controls = [];
126
148
  for (const child of this.children) {
@@ -189,7 +211,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
189
211
  element.focusable = stop;
190
212
  }
191
213
  else if (foreign || this.wroteForeign) {
192
- element.tabIndex = stop ? 0 : -1;
214
+ stopOf(element).tabIndex = stop ? 0 : -1;
193
215
  }
194
216
  }
195
217
  }
@@ -206,8 +228,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
206
228
  if (!parent) {
207
229
  return false;
208
230
  }
209
- return (closestInstance(parent, HelixHeadlessToolbar_1) !== null ||
210
- parent.closest('[role="toolbar"]') !== null);
231
+ return closestInstance(parent, HelixHeadlessToolbar_1) !== null || toolbarAround(this) !== null;
211
232
  }
212
233
  get axis() {
213
234
  return this.orientation ?? 'horizontal';
@@ -237,6 +258,18 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
237
258
  super.firstUpdated(changed);
238
259
  void this.claimTabStop();
239
260
  }
261
+ willUpdate(changed) {
262
+ super.willUpdate(changed);
263
+ this.toggleState('nested', this.nested);
264
+ this.toggleState('horizontal', this.axis === 'horizontal');
265
+ this.toggleState('vertical', this.axis === 'vertical');
266
+ if (this.hasUpdated && changed.has('orientation')) {
267
+ for (const child of this.children) {
268
+ ;
269
+ child.requestUpdate?.();
270
+ }
271
+ }
272
+ }
240
273
  render() {
241
274
  const nested = this.nested;
242
275
  return html `<div
@@ -250,6 +283,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
250
283
  }
251
284
  };
252
285
  __decorate([
286
+ words,
253
287
  property()
254
288
  ], HelixHeadlessToolbar.prototype, "label", void 0);
255
289
  __decorate([
@@ -5,31 +5,33 @@ declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusio
5
5
  * @summary A short text that appears next to an element on hover and focus.
6
6
  *
7
7
  * @description
8
- * The trigger is slotted and stays your own element. The bubble renders in the
8
+ * The trigger stays your own element. The bubble renders in the
9
9
  * top layer through the popover API, so an ancestor with `overflow: hidden`
10
10
  * does not clip it and no `z-index` is needed. `FloatingController` positions
11
11
  * it and flips it to another side when the preferred side does not fit.
12
12
  *
13
- * **The tooltip describes its trigger itself, in both forms.** Wrap the
14
- * trigger, or place the tooltip beside it and name the trigger with `for`:
13
+ * **Place the tooltip beside its trigger, name the trigger with `for`, and
14
+ * name the tooltip in the trigger's `aria-describedby`.** The description is
15
+ * then in your own markup, so it is in the server's HTML and in the
16
+ * accessibility tree at rest, in every browser, before anyone points at the
17
+ * trigger or focuses it:
15
18
  *
16
19
  * ```html
17
- * <helix-headless-button id="save">Save</helix-headless-button>
18
- * <helix-headless-tooltip for="save" content="Save your work"></helix-headless-tooltip>
20
+ * <helix-headless-button aria-describedby="save-tip" id="save">Save</helix-headless-button>
21
+ * <helix-headless-tooltip content="Save your work" for="save" id="save-tip"></helix-headless-tooltip>
19
22
  * ```
20
23
  *
21
- * The link is an element reference on the control that takes focus, and it is
22
- * never written into your markup before a reader has acted. A trigger that is a
23
- * Helix component is described at once, inside its own shadow root. A plain
24
- * element in your markup is described when a reader first points at it or
25
- * focuses it, which is after any hydration, and only where you have written no
26
- * `aria-describedby` or `aria-labelledby` of your own. Write
27
- * `aria-describedby` pointing at the tooltip yourself to have the link in the
28
- * server's markup. Where the browser has no element references, write it
29
- * yourself; the tooltip warns once on first open if nothing links the two.
30
- * In the `for` form the tooltip itself is out of the accessibility tree while
31
- * its bubble is down, so a reader walking the page meets its words once, as
32
- * the trigger's description.
24
+ * Without the attribute, the tooltip links itself through an element reference
25
+ * on the control that takes focus, and it never writes into your markup before
26
+ * you act, so hydration stays intact. A trigger that is a Helix component is
27
+ * described at once, inside its own shadow root. A plain element in your
28
+ * markup is described when you first point at it or focus it, so a screen
29
+ * reader in reading mode meets it with no description until then. Where the
30
+ * browser has no element references, nothing links the two, and the tooltip
31
+ * warns once on first open. The tooltip can also wrap its trigger, which
32
+ * describes a Helix component and leaves a plain element undescribed. In the
33
+ * `for` form the tooltip itself is out of the accessibility tree while its
34
+ * bubble is down, so you meet its words once, as the trigger's description.
33
35
  *
34
36
  * The tooltip shows on hover and on focus. It hides on pointer leave, on blur,
35
37
  * on Escape, and when the trigger is activated. The pointer can move from the
@@ -114,6 +116,14 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
114
116
  * Names an element in the same tree, so a tooltip inside another component's
115
117
  * shadow root points at one in that root rather than one in the document.
116
118
  *
119
+ * Give the tooltip an `id` and name it in the trigger's `aria-describedby`,
120
+ * so the trigger is described in the server's markup and at rest:
121
+ *
122
+ * ```html
123
+ * <button aria-describedby="save-tip" id="save">Save</button>
124
+ * <helix-headless-tooltip content="Save your work" for="save" id="save-tip"></helix-headless-tooltip>
125
+ * ```
126
+ *
117
127
  * **In React this arrives as a property and not as an attribute**, which is
118
128
  * worth knowing before someone reads the DOM and thinks it did not take.
119
129
  * Measured against React 19.2.8: `for` exists on the prototype, so React sets