@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,8 +4,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, customElement, HelixElement, inlineStep, keyClaimed, } from '@fusion.dev/helix-core';
8
- import { html } from 'lit';
7
+ var HelixHeadlessToolbar_1;
8
+ import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, } from '@fusion.dev/helix-core';
9
+ import { html, nothing } from 'lit';
9
10
  import { property } from 'lit/decorators.js';
10
11
  const KEYS = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End']);
11
12
  const ownsTabStop = (node) => 'focusable' in node;
@@ -22,7 +23,9 @@ const takesFocus = (node) => {
22
23
  node.shadowRoot?.delegatesFocus === true ||
23
24
  node.shadowRoot?.querySelector(TABBABLE) != null);
24
25
  };
25
- let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
26
+ const flattens = (node) => ownsTabStop(node) &&
27
+ node.selectionMode === 'multiple';
28
+ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar extends HelixElement {
26
29
  constructor() {
27
30
  super(...arguments);
28
31
  this.label = 'Toolbar';
@@ -33,14 +36,23 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
33
36
  this.wroteForeign = false;
34
37
  this.stopAtEnds = false;
35
38
  this.handleFocusIn = (event) => {
39
+ if (this.nested) {
40
+ return;
41
+ }
36
42
  const control = this.origin(event);
37
43
  if (control) {
38
44
  this.setTabStop(control);
39
45
  }
40
46
  };
41
47
  this.restoreTabStop = () => {
48
+ if (this.nested) {
49
+ return;
50
+ }
42
51
  const controls = this.controls;
43
52
  const held = controls.some((control) => {
53
+ if (control.group) {
54
+ return control.group.focusable;
55
+ }
44
56
  const composite = control.stops.length !== 1;
45
57
  const element = composite ? control.child : control.stops[0];
46
58
  if (ownsTabStop(element)) {
@@ -53,8 +65,11 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
53
65
  }
54
66
  };
55
67
  this.handleCompositeKeydown = (event) => {
68
+ if (this.nested) {
69
+ return;
70
+ }
56
71
  const control = this.origin(event);
57
- if (!control || control.stops.length === 1) {
72
+ if (!control || (control.stops.length === 1 && !control.group)) {
58
73
  return;
59
74
  }
60
75
  this.handleKeydown(event);
@@ -63,7 +78,7 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
63
78
  }
64
79
  };
65
80
  this.handleKeydown = (event) => {
66
- if (!KEYS.has(event.key) || keyClaimed(event)) {
81
+ if (this.nested || !KEYS.has(event.key) || keyClaimed(event)) {
67
82
  return;
68
83
  }
69
84
  const along = inlineStep(this, event.key);
@@ -115,7 +130,14 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
115
130
  continue;
116
131
  }
117
132
  if (takesFocus(child)) {
118
- controls.push({ child, stops: this.inside(child) });
133
+ const stops = this.inside(child);
134
+ if (stops.length > 1 && flattens(child)) {
135
+ for (const stop of stops) {
136
+ controls.push({ child: stop, group: child, stops: [stop] });
137
+ }
138
+ continue;
139
+ }
140
+ controls.push({ child, stops });
119
141
  continue;
120
142
  }
121
143
  for (const stop of this.within(child)) {
@@ -151,6 +173,10 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
151
173
  this.wroteForeign = true;
152
174
  }
153
175
  for (const control of this.controls) {
176
+ if (control.group) {
177
+ control.group.focusable = control.group === active?.group;
178
+ continue;
179
+ }
154
180
  if (control.stops.length !== 1) {
155
181
  if (ownsTabStop(control.child)) {
156
182
  control.child.focusable = control.child === active?.child;
@@ -168,15 +194,27 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
168
194
  }
169
195
  }
170
196
  async claimTabStop() {
197
+ if (this.nested) {
198
+ return;
199
+ }
171
200
  const pending = [...new Set([...this.children].map((child) => child.localName))].filter((name) => name.includes('-'));
172
201
  await Promise.all(pending.map((name) => customElements.whenDefined(name)));
173
202
  this.setTabStop(this.controls[0], false);
174
203
  }
204
+ get nested() {
205
+ const parent = this.parentElement;
206
+ if (!parent) {
207
+ return false;
208
+ }
209
+ return (closestInstance(parent, HelixHeadlessToolbar_1) !== null ||
210
+ parent.closest('[role="toolbar"]') !== null);
211
+ }
175
212
  get axis() {
176
213
  return this.orientation ?? 'horizontal';
177
214
  }
178
215
  connectedCallback() {
179
216
  super.connectedCallback();
217
+ this.requestUpdate();
180
218
  this.addEventListener('keydown', this.handleCompositeKeydown, true);
181
219
  this.addEventListener('keydown', this.handleKeydown);
182
220
  this.addEventListener('focusin', this.handleFocusIn);
@@ -200,7 +238,13 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
200
238
  void this.claimTabStop();
201
239
  }
202
240
  render() {
203
- return html `<div part="toolbar" role="toolbar" aria-label=${this.label} aria-orientation=${this.axis}>
241
+ const nested = this.nested;
242
+ return html `<div
243
+ part="toolbar"
244
+ role=${nested ? 'group' : 'toolbar'}
245
+ aria-label=${this.label}
246
+ aria-orientation=${nested ? nothing : this.axis}
247
+ >
204
248
  <slot @slotchange=${() => this.claimTabStop()}></slot>
205
249
  </div>`;
206
250
  }
@@ -214,7 +258,7 @@ __decorate([
214
258
  __decorate([
215
259
  property({ attribute: 'stop-at-ends', type: Boolean })
216
260
  ], HelixHeadlessToolbar.prototype, "stopAtEnds", void 0);
217
- HelixHeadlessToolbar = __decorate([
261
+ HelixHeadlessToolbar = HelixHeadlessToolbar_1 = __decorate([
218
262
  customElement('helix-headless-toolbar')
219
263
  ], HelixHeadlessToolbar);
220
264
  export { HelixHeadlessToolbar };
@@ -1,4 +1,4 @@
1
- import { HelixElement, type Placement } from '@fusion.dev/helix-core';
1
+ import { HelixElement, OpenPhaseController, type Placement } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
@@ -27,10 +27,15 @@ declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusio
27
27
  * `aria-describedby` pointing at the tooltip yourself to have the link in the
28
28
  * server's markup. Where the browser has no element references, write it
29
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.
30
33
  *
31
34
  * The tooltip shows on hover and on focus. It hides on pointer leave, on blur,
32
35
  * on Escape, and when the trigger is activated. The pointer can move from the
33
- * trigger onto the bubble and the bubble stays.
36
+ * trigger onto the bubble and the bubble stays, unless you set
37
+ * `hoverable="false"`. `delay` is how long the pointer rests before it shows,
38
+ * and `delay-out` how long it stays once the pointer leaves.
34
39
  *
35
40
  * Once one tooltip is showing, moving to another trigger shows its tooltip
36
41
  * with no `delay`, and the first one hides. The same holds for `skip-delay`
@@ -63,6 +68,8 @@ declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusio
63
68
  * @csspart tooltip-right - Added to `tooltip` while the bubble is right of its trigger.
64
69
  * @csspart tooltip-top - Added to `tooltip` while the bubble is above its trigger.
65
70
  *
71
+ * @cssstate entering - From the moment the bubble shows until its entrance has finished.
72
+ * @cssstate exiting - From the moment the bubble hides until its exit has finished.
66
73
  * @cssstate open - While the tooltip shows.
67
74
  * @cssstate placed-bottom - While the bubble sits below its trigger.
68
75
  * @cssstate placed-left - While the bubble sits to the left of its trigger.
@@ -87,7 +94,9 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
87
94
  */
88
95
  delay: number;
89
96
  /**
90
- * How long the bubble stays after the pointer leaves, in milliseconds.
97
+ * How long the bubble stays after the pointer leaves the trigger or the
98
+ * bubble, in milliseconds: the close delay. It is the time a reader has to
99
+ * cross the gap onto the bubble.
91
100
  */
92
101
  delayOut: number;
93
102
  /**
@@ -115,6 +124,13 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
115
124
  * why this does not reflect and nothing styles on it.
116
125
  */
117
126
  for: string;
127
+ /**
128
+ * Whether the pointer can move onto the bubble and the bubble stays, so a
129
+ * reader can read it under a magnifier or select its words, as WCAG 1.4.13
130
+ * asks. `hoverable="false"` hides the bubble once the pointer reaches it,
131
+ * for a bubble that covers something a reader moves on to.
132
+ */
133
+ hoverable: boolean;
118
134
  /**
119
135
  * The space between the trigger and the tip of the bubble, in pixels.
120
136
  *
@@ -225,6 +241,7 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
225
241
  * it must stay inside, and a component often has one and not the other.
226
242
  */
227
243
  private get enclosure();
244
+ protected readonly phases: OpenPhaseController;
228
245
  private get bubble();
229
246
  /**
230
247
  * Whether there is anything to show.
@@ -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 { anchorElement, arrowReach, customElement, elementById, HelixElement, hostAria, linkDescription, MixinControllerOpen, PopoverController, reportRuntime, sideOf, unlinkDescription, } from '@fusion.dev/helix-core';
7
+ import { anchorElement, arrowReach, customElement, elementById, HelixElement, hostAria, linkDescription, MixinControllerOpen, OpenPhaseController, onUnlessFalse, PopoverController, reportRuntime, sideOf, unlinkDescription, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  import { focusTarget } from '../focus-target.js';
@@ -23,6 +23,7 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
23
23
  this.delayOut = 100;
24
24
  this.disabled = false;
25
25
  this.for = '';
26
+ this.hoverable = true;
26
27
  this.offset = 8;
27
28
  this.persist = false;
28
29
  this.placement = 'top';
@@ -50,6 +51,14 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
50
51
  surface: () => this.partNamed('tooltip'),
51
52
  within: () => this.enclosure,
52
53
  });
54
+ this.phases = new OpenPhaseController(this, {
55
+ mark: {
56
+ entering: (on) => this.toggleState('entering', on),
57
+ exiting: (on) => this.toggleState('exiting', on),
58
+ },
59
+ open: () => this.open,
60
+ surface: () => this.partNamed('tooltip'),
61
+ });
53
62
  this.handleContentChange = () => {
54
63
  this.requestUpdate();
55
64
  };
@@ -68,6 +77,10 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
68
77
  this.timer = setTimeout(() => this.show(), this.delay);
69
78
  };
70
79
  this.holdOnBubble = () => {
80
+ if (!this.hoverable) {
81
+ this.hideLater();
82
+ return;
83
+ }
71
84
  if (!this.named) {
72
85
  return;
73
86
  }
@@ -330,6 +343,7 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
330
343
  describedBy: this.hasContent ? [bubble] : [],
331
344
  label: this.describedText,
332
345
  });
346
+ this.internals.ariaHidden = this.for !== '' && !this.open ? 'true' : null;
333
347
  }
334
348
  render() {
335
349
  const side = this.side;
@@ -365,6 +379,9 @@ __decorate([
365
379
  __decorate([
366
380
  property()
367
381
  ], HelixHeadlessTooltip.prototype, "for", void 0);
382
+ __decorate([
383
+ property({ converter: onUnlessFalse })
384
+ ], HelixHeadlessTooltip.prototype, "hoverable", void 0);
368
385
  __decorate([
369
386
  property({ type: Number })
370
387
  ], HelixHeadlessTooltip.prototype, "offset", void 0);
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The stop Back goes to from `index`: the nearest stop before it that is not a
3
+ * `wait` stop, or `undefined` where there is none.
4
+ *
5
+ * A `wait` stop shows nothing and moves on by itself once its target is on the
6
+ * page, so going back onto one either moves straight on again or leaves the
7
+ * reader at a stop with nothing in it. Back passes over it to the stop that
8
+ * told the reader what to do.
9
+ */
10
+ export declare const stopBefore: (types: readonly (string | undefined)[], index: number) => number | undefined;
@@ -0,0 +1,8 @@
1
+ export const stopBefore = (types, index) => {
2
+ for (let at = Math.min(index, types.length) - 1; at >= 0; at -= 1) {
3
+ if (types[at] !== 'wait') {
4
+ return at;
5
+ }
6
+ }
7
+ return undefined;
8
+ };
@@ -22,6 +22,11 @@ declare const HelixHeadlessTour_base: (new (...args: any[]) => import("@fusion.d
22
22
  * `toggle` work as they do on `Dialog`. Setting `open` starts the run, and
23
23
  * `skip()` and `requestOpen(false)` end it early.
24
24
  *
25
+ * The box the light falls on is on the `spotlight` part as
26
+ * `--tour-spotlight-x`, `--tour-spotlight-y`, `--tour-spotlight-width` and
27
+ * `--tour-spotlight-height`, for a sheet that draws its own light, such as a
28
+ * ring around the target.
29
+ *
25
30
  * Each stop is told its place in the run, from `progress-label`, such as "2 of
26
31
  * 5". It describes the stop's panel, so a screen reader says it at every stop,
27
32
  * and `progress` draws it in the panel as well. A dialog or a floating stop,
@@ -35,6 +40,12 @@ declare const HelixHeadlessTour_base: (new (...args: any[]) => import("@fusion.d
35
40
  * you have moved it somewhere else on the page. A stop does not trap focus, so
36
41
  * you can still `Tab` out to the element it describes.
37
42
  *
43
+ * **The arrow keys move between stops** while focus is in one: the arrow that
44
+ * points the way the line runs goes on, and the other goes back, so on a
45
+ * right-to-left page `ArrowLeft` goes on. Neither finishes the tour at the last
46
+ * stop, and a text field in a stop keeps its own arrows. `Escape` skips the
47
+ * tour.
48
+ *
38
49
  * @since 0.1.0
39
50
  * @status stable
40
51
  * @category overlays
@@ -50,12 +61,19 @@ declare const HelixHeadlessTour_base: (new (...args: any[]) => import("@fusion.d
50
61
  * @event {HelixCompleteEvent} helix-complete - Fired when the last stop is
51
62
  * finished.
52
63
  * @event {HelixTourAskEvent} helix-tour-ask - Fired when a stop's control is pressed to move the tour. The stop sends it, and the tour handles it.
64
+ * @event {HelixTourStatusEvent} helix-tour-status - Fired when the tour starts waiting at a `wait` stop, is skipped, or is completed, with the stop's index and `detail.status` saying which.
53
65
  * @event {ToggleEvent} toggle - Sent when the tour starts or ends, with `newState` and `oldState`.
54
66
  *
55
67
  * @csspart backdrop - Behind a dialog or a floating stop, which lights nothing. It draws no box until you give it one.
56
68
  * @csspart spotlight - The box over the current target. It also draws the dimmed area around the target.
57
69
  *
70
+ * @cssproperty --tour-spotlight-height - The lit box's height, in pixels, padding included. Written on the spotlight while it lights a target.
71
+ * @cssproperty --tour-spotlight-width - The lit box's width, in pixels, padding included. Written on the spotlight while it lights a target.
72
+ * @cssproperty --tour-spotlight-x - The lit box's left edge, from the window's left edge, in pixels. Written on the spotlight while it lights a target.
73
+ * @cssproperty --tour-spotlight-y - The lit box's top edge, from the window's top edge, in pixels. Written on the spotlight while it lights a target.
74
+ *
58
75
  * @cssstate open - While the tour is running.
76
+ * @cssstate waiting - While the tour waits at a `wait` stop for its target to be on the page.
59
77
  */
60
78
  export declare class HelixHeadlessTour extends HelixHeadlessTour_base {
61
79
  /**
@@ -131,7 +149,10 @@ export declare class HelixHeadlessTour extends HelixHeadlessTour_base {
131
149
  get length(): number;
132
150
  /** Goes to the next stop, and finishes the tour on the last stop. */
133
151
  next(): void;
134
- /** Goes to the previous stop. It does nothing on the first stop. */
152
+ /**
153
+ * Goes to the previous stop, passing over a `wait` stop, which shows nothing.
154
+ * It does nothing on the first stop, or where only `wait` stops come before.
155
+ */
135
156
  back(): void;
136
157
  /**
137
158
  * Ends the tour early, as a close. `helix-complete` is not fired.
@@ -144,6 +165,15 @@ export declare class HelixHeadlessTour extends HelixHeadlessTour_base {
144
165
  private finish;
145
166
  private move;
146
167
  private readonly handleAsk;
168
+ /**
169
+ * The arrow along the line, from inside a stop: on, or back.
170
+ *
171
+ * A move and never a finish, so a reader walking the stops with the arrows
172
+ * cannot end the tour by going one too far; that is Next on the last stop.
173
+ */
174
+ private readonly handleArrows;
175
+ /** Whether `back()` would move, there being a stop that shows before this one. */
176
+ private get canGoBack();
147
177
  private readonly handleKeydown;
148
178
  private readonly handleViewport;
149
179
  connectedCallback(): void;
@@ -164,7 +194,20 @@ export declare class HelixHeadlessTour extends HelixHeadlessTour_base {
164
194
  * where to be.
165
195
  */
166
196
  private follow;
167
- /** Focuses the current stop's panel once the stop has shown it. */
197
+ /**
198
+ * Where focus was put while a `wait` stop waits, so the move on from it still
199
+ * counts as a move from inside the tour while focus has stayed there.
200
+ */
201
+ private parked;
202
+ /**
203
+ * Focuses the current stop's panel once the stop has shown it.
204
+ *
205
+ * A `wait` stop shows no panel, and focus would fall to the body. It goes to
206
+ * the target of the stop before instead, which is usually the control the
207
+ * reader is asked to use, such as the button that opens the menu the stop
208
+ * waits for. Where that target holds no control, it goes back to where it
209
+ * was when the tour opened.
210
+ */
168
211
  private focusCurrent;
169
212
  /**
170
213
  * Tells each stop where it is in the run.
@@ -4,9 +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, deepActiveElement, deepContains, fillTemplate, HelixActivateEvent, HelixBeforeActivateEvent, HelixCompleteEvent, HelixElement, hostAria, MixinControllerOpen, requestChange, whenHydrated, } from '@fusion.dev/helix-core';
7
+ import { controlsIn, customElement, deepActiveElement, deepContains, fillTemplate, HelixActivateEvent, HelixBeforeActivateEvent, HelixCompleteEvent, HelixElement, HelixTourStatusEvent, hostAria, inlineStep, keyClaimed, MixinControllerOpen, requestChange, whenHydrated, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property, queryAssignedElements, state } from 'lit/decorators.js';
10
+ import { stopBefore } from '../back.js';
10
11
  import { onPage, waitFor } from '../wait.js';
11
12
  let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(HelixElement) {
12
13
  constructor() {
@@ -35,6 +36,20 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
35
36
  this.skip();
36
37
  }
37
38
  };
39
+ this.handleArrows = (event) => {
40
+ if (!this.open || keyClaimed(event) || event.altKey || event.ctrlKey || event.metaKey) {
41
+ return;
42
+ }
43
+ const along = inlineStep(this, event.key);
44
+ if (along === 1 && this.index < this.length - 1) {
45
+ event.preventDefault();
46
+ this.next();
47
+ }
48
+ else if (along === -1 && this.canGoBack) {
49
+ event.preventDefault();
50
+ this.back();
51
+ }
52
+ };
38
53
  this.handleKeydown = (event) => {
39
54
  if (this.open && event.key === 'Escape' && !event.defaultPrevented) {
40
55
  event.preventDefault();
@@ -69,16 +84,20 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
69
84
  this.move(this.index + 1);
70
85
  }
71
86
  back() {
72
- if (this.index <= 0) {
73
- return;
87
+ const to = stopBefore(this.stops.map((stop) => stop.type), this.index);
88
+ if (to !== undefined) {
89
+ this.move(to);
74
90
  }
75
- this.move(this.index - 1);
76
91
  }
77
92
  skip() {
78
- this.requestOpen(false);
93
+ const at = this.index;
94
+ if (this.open && this.requestOpen(false)) {
95
+ this.dispatchEvent(new HelixTourStatusEvent({ index: at, status: 'skipped' }));
96
+ }
79
97
  }
80
98
  finish() {
81
99
  this.dispatchEvent(new HelixCompleteEvent({ value: String(this.index) }));
100
+ this.dispatchEvent(new HelixTourStatusEvent({ index: this.index, status: 'completed' }));
82
101
  this.open = false;
83
102
  }
84
103
  move(to) {
@@ -94,9 +113,13 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
94
113
  this.dispatchEvent(new HelixActivateEvent({ value: String(this.index) }));
95
114
  }
96
115
  }
116
+ get canGoBack() {
117
+ return (stopBefore(this.stops.map((stop) => stop.type), this.index) !== undefined);
118
+ }
97
119
  connectedCallback() {
98
120
  super.connectedCallback();
99
121
  this.addEventListener('helix-tour-ask', this.handleAsk);
122
+ this.addEventListener('keydown', this.handleArrows);
100
123
  document.addEventListener('keydown', this.handleKeydown);
101
124
  window.addEventListener('resize', this.handleViewport, { passive: true });
102
125
  window.addEventListener('scroll', this.handleViewport, { capture: true, passive: true });
@@ -107,6 +130,7 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
107
130
  disconnectedCallback() {
108
131
  super.disconnectedCallback();
109
132
  this.removeEventListener('helix-tour-ask', this.handleAsk);
133
+ this.removeEventListener('keydown', this.handleArrows);
110
134
  document.removeEventListener('keydown', this.handleKeydown);
111
135
  window.removeEventListener('resize', this.handleViewport);
112
136
  window.removeEventListener('scroll', this.handleViewport, { capture: true });
@@ -115,6 +139,7 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
115
139
  this.unwait?.();
116
140
  this.unwait = undefined;
117
141
  this.waiting = undefined;
142
+ this.toggleState('waiting', false);
118
143
  }
119
144
  willUpdate(changed) {
120
145
  super.willUpdate(changed);
@@ -138,7 +163,13 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
138
163
  const opened = changed.has('open') && this.open && changed.get('open') === false;
139
164
  const closed = changed.has('open') && !this.open && changed.get('open') === true;
140
165
  const active = deepActiveElement();
141
- const inside = active === null || active === document.body || deepContains(this, active);
166
+ const inside = active === null ||
167
+ active === document.body ||
168
+ deepContains(this, active) ||
169
+ (this.parked !== undefined && active === this.parked);
170
+ if (opened || closed || changed.has('index')) {
171
+ this.parked = undefined;
172
+ }
142
173
  if (opened) {
143
174
  if (active instanceof HTMLElement && !deepContains(this, active)) {
144
175
  this.returnFocus = active;
@@ -158,10 +189,21 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
158
189
  }
159
190
  focusCurrent() {
160
191
  const stops = this.stops;
161
- const stop = stops[Math.max(0, Math.min(this.index, stops.length - 1))];
192
+ const at = Math.max(0, Math.min(this.index, stops.length - 1));
193
+ const stop = stops[at];
162
194
  if (!stop) {
163
195
  return;
164
196
  }
197
+ if (stop.type === 'wait') {
198
+ const before = stopBefore(stops.map((one) => one.type), at);
199
+ const target = before === undefined ? undefined : stops[before]?.target;
200
+ const park = (target ? controlsIn([target])[0] : undefined) ?? this.returnFocus;
201
+ if (park?.isConnected) {
202
+ park.focus();
203
+ this.parked = park;
204
+ }
205
+ return;
206
+ }
165
207
  void stop.updateComplete.then(() => {
166
208
  if (this.open && stop.current) {
167
209
  stop.focus();
@@ -213,12 +255,15 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
213
255
  this.unwait?.();
214
256
  this.unwait = undefined;
215
257
  this.waiting = next;
258
+ this.toggleState('waiting', next !== undefined);
216
259
  if (!next) {
217
260
  return;
218
261
  }
262
+ this.dispatchEvent(new HelixTourStatusEvent({ index: this.index, status: 'waiting' }));
219
263
  this.unwait = waitFor(next.getRootNode(), () => onPage(next.target), () => {
220
264
  this.waiting = undefined;
221
265
  this.unwait = undefined;
266
+ this.toggleState('waiting', false);
222
267
  queueMicrotask(() => {
223
268
  if (this.open && this.current === next) {
224
269
  this.next();
@@ -274,7 +319,7 @@ let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(Heli
274
319
  : html `<div
275
320
  part="spotlight"
276
321
  aria-hidden="true"
277
- style=${`left: ${spot.left}px; top: ${spot.top}px; block-size: ${spot.height}px; inline-size: ${spot.width}px`}
322
+ style=${`left: ${spot.left}px; top: ${spot.top}px; block-size: ${spot.height}px; inline-size: ${spot.width}px; --tour-spotlight-x: ${spot.left}px; --tour-spotlight-y: ${spot.top}px; --tour-spotlight-width: ${spot.width}px; --tour-spotlight-height: ${spot.height}px`}
278
323
  ></div>`}
279
324
  <slot></slot>`;
280
325
  }
@@ -62,6 +62,7 @@ import '../../button/index.js';
62
62
  * @csspart back - The control that goes to the previous stop.
63
63
  * @csspart back-button - The button inside `back`.
64
64
  * @csspart back-live - The live region inside `back`.
65
+ * @csspart back-spinner - The ring `back` turns while it is pending.
65
66
  * @csspart back-text - The words on that button, trimmed to their capitals and baseline.
66
67
  * @csspart bubble - The panel that points at the target.
67
68
  * @csspart content - The region holding the slotted content.
@@ -70,11 +71,13 @@ import '../../button/index.js';
70
71
  * @csspart next - The control that goes to the next stop, and finishes the tour on the last stop.
71
72
  * @csspart next-button - The button inside `next`.
72
73
  * @csspart next-live - The live region inside `next`.
74
+ * @csspart next-spinner - The ring `next` turns while it is pending.
73
75
  * @csspart next-text - The words on that button, trimmed to their capitals and baseline.
74
76
  * @csspart progress - The stop's place in the tour, such as "2 of 5". It describes the panel, and is shown when the tour has `progress`.
75
77
  * @csspart skip - The control that ends the tour early.
76
78
  * @csspart skip-button - The button inside `skip`.
77
79
  * @csspart skip-live - The live region inside `skip`.
80
+ * @csspart skip-spinner - The ring `skip` turns while it is pending.
78
81
  * @csspart skip-text - The words on that button, trimmed to their capitals and baseline.
79
82
  *
80
83
  * @cssstate placed-bottom - The panel sits below its target.
@@ -86,14 +86,14 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
86
86
  return html `<slot name="actions">
87
87
  <${this.tag('button')}
88
88
  part="skip"
89
- exportparts="button: skip-button, live: skip-live, text: skip-text" emphasis="ghost" @click=${() => this.ask('skip')}>
89
+ exportparts="button: skip-button, live: skip-live, spinner: skip-spinner, text: skip-text" emphasis="ghost" @click=${() => this.ask('skip')}>
90
90
  ${this.skipLabel}
91
91
  </${this.tag('button')}>
92
92
  ${this.first
93
93
  ? ''
94
94
  : html `<${this.tag('button')}
95
95
  part="back"
96
- exportparts="button: back-button, live: back-live, text: back-text"
96
+ exportparts="button: back-button, live: back-live, spinner: back-spinner, text: back-text"
97
97
  emphasis="outlined"
98
98
  @click=${() => this.ask('back')}
99
99
  >
@@ -101,7 +101,7 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
101
101
  </${this.tag('button')}>`}
102
102
  <${this.tag('button')}
103
103
  part="next"
104
- exportparts="button: next-button, live: next-live, text: next-text"
104
+ exportparts="button: next-button, live: next-live, spinner: next-spinner, text: next-text"
105
105
  emphasis="solid"
106
106
  tone="primary"
107
107
  @click=${() => this.ask('next')}
@@ -21,7 +21,8 @@ declare const HelixHeadlessTreeItem_base: (new (...args: any[]) => import("@fusi
21
21
  *
22
22
  * Pressing a branch, or Enter or Space on it, opens or closes it. A branch with
23
23
  * a `value` is chosen as well and sends `helix-select`, unless the tree has
24
- * `nesting="heading"`, where a branch names the list under it.
24
+ * `nesting="heading"`, where a branch names the list under it, or
25
+ * `selection-mode="leaf"`, where only the items at the ends are chosen.
25
26
  *
26
27
  * A `disabled` item is reached by the arrow keys and announced as unavailable,
27
28
  * and a press, Enter or Space on it does nothing.
@@ -58,7 +59,9 @@ declare const HelixHeadlessTreeItem_base: (new (...args: any[]) => import("@fusi
58
59
  *
59
60
  * @cssproperty --tree-level - How deep this row sits, counting from one as `aria-level` does, for the indent.
60
61
  *
62
+ * @cssstate checked - While it is checked, in a tree with `selection-mode="multiple"`.
61
63
  * @cssstate loading - While a `lazy` item is open and its children have not arrived.
64
+ * @cssstate mixed - While some of a branch's items are checked, in a tree with `selection-mode="multiple"`.
62
65
  * @cssstate open - While its children are shown.
63
66
  * @cssstate selected - While it is selected.
64
67
  */
@@ -80,8 +83,9 @@ export declare class HelixHeadlessTreeItem extends HelixHeadlessTreeItem_base {
80
83
  disabled: boolean;
81
84
  /**
82
85
  * @internal Set by the tree: whether a branch heads the list under it, as
83
- * under `nesting="heading"`. Such a branch only opens and closes when it is
84
- * pressed, because it names a list and is not a destination of its own.
86
+ * under `nesting="heading"`, or is not chosen at all, as under
87
+ * `selection-mode="leaf"`. Such a branch only opens and closes when it is
88
+ * pressed.
85
89
  */
86
90
  heads: boolean;
87
91
  /**
@@ -110,6 +110,7 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
110
110
  renderToggle() {
111
111
  return html `<slot
112
112
  name="chevron"
113
+ aria-hidden="true"
113
114
  @click=${this.href === '' ? nothing : this.handleToggleClick}
114
115
  ><svg part="toggle" fill="currentColor" viewBox=${caretDown.viewBox} aria-hidden="true">
115
116
  ${unsafeSVG(caretDown.content)}
@@ -140,6 +141,8 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
140
141
  willUpdate(changed) {
141
142
  super.willUpdate(changed);
142
143
  this.toggleState('selected', this.selected);
144
+ this.toggleState('checked', this.checkable && this.checked === true);
145
+ this.toggleState('mixed', this.checkable && this.checked === 'mixed');
143
146
  this.toggleState('loading', this.open && this.lazy);
144
147
  if (this.childrenKnown) {
145
148
  this.branch = this.knownChildren.some((child) => child.slot === 'children');