@fusion.dev/helix-headless 0.143.0 → 0.145.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 (314) hide show
  1. package/custom-elements.json +16990 -1383
  2. package/dist/accordion/item/accordion-item.d.ts +48 -12
  3. package/dist/accordion/item/accordion-item.js +26 -5
  4. package/dist/accordion/root/accordion-root.d.ts +6 -0
  5. package/dist/accordion/root/accordion-root.js +7 -1
  6. package/dist/announcement/root/announcement-root.d.ts +21 -1
  7. package/dist/announcement/root/announcement-root.js +36 -1
  8. package/dist/app-header/root/app-header-root.d.ts +7 -0
  9. package/dist/app-header/root/app-header-root.js +5 -1
  10. package/dist/app-header/sectioning.d.ts +7 -0
  11. package/dist/app-header/sectioning.js +26 -0
  12. package/dist/area-chart/root/area-chart-root.d.ts +12 -4
  13. package/dist/area-chart/root/area-chart-root.js +24 -7
  14. package/dist/avatar/root/avatar-root.d.ts +14 -0
  15. package/dist/avatar/root/avatar-root.js +23 -9
  16. package/dist/badge/root/badge-root.d.ts +11 -7
  17. package/dist/badge/root/badge-root.js +1 -1
  18. package/dist/bar-chart/root/bar-chart-root.d.ts +12 -3
  19. package/dist/bar-chart/root/bar-chart-root.js +17 -10
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +32 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +25 -2
  22. package/dist/button/root/button-root.d.ts +47 -1
  23. package/dist/button/root/button-root.js +38 -4
  24. package/dist/callout/root/callout-root.d.ts +18 -1
  25. package/dist/callout/root/callout-root.js +15 -4
  26. package/dist/canvas/root/canvas-root.d.ts +38 -3
  27. package/dist/canvas/root/canvas-root.js +121 -40
  28. package/dist/card/root/card-root.d.ts +30 -1
  29. package/dist/card/root/card-root.js +38 -5
  30. package/dist/carousel/root/carousel-root.d.ts +90 -0
  31. package/dist/carousel/root/carousel-root.js +134 -12
  32. package/dist/chat/composer/chat-composer.d.ts +38 -6
  33. package/dist/chat/composer/chat-composer.js +42 -9
  34. package/dist/chat/message/chat-message.d.ts +32 -1
  35. package/dist/chat/message/chat-message.js +25 -9
  36. package/dist/chat/naming.d.ts +22 -0
  37. package/dist/chat/naming.js +12 -0
  38. package/dist/chat/relative-clock.d.ts +39 -0
  39. package/dist/chat/relative-clock.js +31 -0
  40. package/dist/chat/root/chat-root.d.ts +36 -0
  41. package/dist/chat/root/chat-root.js +24 -1
  42. package/dist/checkbox/root/checkbox-root.js +2 -0
  43. package/dist/checkbox-group/root/checkbox-group-root.d.ts +53 -3
  44. package/dist/checkbox-group/root/checkbox-group-root.js +71 -22
  45. package/dist/code-block/lines.d.ts +13 -0
  46. package/dist/code-block/lines.js +2 -0
  47. package/dist/code-block/root/code-block-root.d.ts +38 -1
  48. package/dist/code-block/root/code-block-root.js +28 -7
  49. package/dist/color-input/root/color-input-root.d.ts +34 -1
  50. package/dist/color-input/root/color-input-root.js +23 -4
  51. package/dist/color-picker/channels.d.ts +26 -0
  52. package/dist/color-picker/channels.js +84 -0
  53. package/dist/color-picker/root/color-picker-root.d.ts +81 -5
  54. package/dist/color-picker/root/color-picker-root.js +103 -10
  55. package/dist/combobox/root/combobox-root.d.ts +38 -3
  56. package/dist/combobox/root/combobox-root.js +64 -2
  57. package/dist/command/root/command-root.d.ts +30 -4
  58. package/dist/command/root/command-root.js +33 -3
  59. package/dist/copy-button/from.d.ts +22 -0
  60. package/dist/copy-button/from.js +28 -0
  61. package/dist/copy-button/root/copy-button-root.d.ts +47 -1
  62. package/dist/copy-button/root/copy-button-root.js +44 -8
  63. package/dist/data-table/root/data-table-root.d.ts +150 -2
  64. package/dist/data-table/root/data-table-root.js +303 -29
  65. package/dist/data-table/tree.d.ts +40 -0
  66. package/dist/data-table/tree.js +55 -0
  67. package/dist/date-input/root/date-input-root.d.ts +73 -4
  68. package/dist/date-input/root/date-input-root.js +93 -43
  69. package/dist/date-picker/root/date-picker-root.d.ts +145 -1
  70. package/dist/date-picker/root/date-picker-root.js +239 -48
  71. package/dist/description-list/item/description-list-item.d.ts +17 -2
  72. package/dist/description-list/item/description-list-item.js +15 -2
  73. package/dist/description-list/root/description-list-root.d.ts +27 -1
  74. package/dist/description-list/root/description-list-root.js +26 -1
  75. package/dist/dialog/description.d.ts +9 -0
  76. package/dist/dialog/description.js +14 -0
  77. package/dist/dialog/root/dialog-root.d.ts +64 -1
  78. package/dist/dialog/root/dialog-root.js +49 -23
  79. package/dist/donut-chart/root/donut-chart-root.d.ts +25 -4
  80. package/dist/donut-chart/root/donut-chart-root.js +21 -6
  81. package/dist/drawer/root/drawer-root.d.ts +63 -2
  82. package/dist/drawer/root/drawer-root.js +95 -19
  83. package/dist/drawer/swipe-start.d.ts +9 -0
  84. package/dist/drawer/swipe-start.js +12 -0
  85. package/dist/drilldown/item/drilldown-item.d.ts +11 -6
  86. package/dist/drilldown/item/drilldown-item.js +8 -5
  87. package/dist/drilldown/root/drilldown-root.d.ts +11 -0
  88. package/dist/drilldown/root/drilldown-root.js +8 -3
  89. package/dist/element-events.generated.js +61 -13
  90. package/dist/empty/root/empty-root.d.ts +1 -1
  91. package/dist/file-input/root/file-input-root.d.ts +47 -0
  92. package/dist/file-input/root/file-input-root.js +60 -22
  93. package/dist/file-input/screen.d.ts +35 -0
  94. package/dist/file-input/screen.js +49 -0
  95. package/dist/filter-input/menu/filter-menu.d.ts +3 -0
  96. package/dist/filter-input/menu/filter-menu.js +8 -4
  97. package/dist/filter-input/root/filter-input-root.d.ts +38 -4
  98. package/dist/filter-input/root/filter-input-root.js +67 -3
  99. package/dist/filter-input/suggest.d.ts +17 -0
  100. package/dist/filter-input/suggest.js +23 -0
  101. package/dist/format-date/options.d.ts +33 -0
  102. package/dist/format-date/options.js +42 -0
  103. package/dist/format-date/root/format-date-root.d.ts +51 -0
  104. package/dist/format-date/root/format-date-root.js +58 -38
  105. package/dist/heatmap/root/heatmap-root.d.ts +23 -6
  106. package/dist/heatmap/root/heatmap-root.js +24 -13
  107. package/dist/icon/index.d.ts +2 -0
  108. package/dist/icon/index.js +2 -0
  109. package/dist/icon/registry.d.ts +37 -0
  110. package/dist/icon/registry.js +83 -0
  111. package/dist/icon/root/icon-root.d.ts +30 -4
  112. package/dist/icon/root/icon-root.js +41 -6
  113. package/dist/icon/root/index.d.ts +2 -0
  114. package/dist/icon/root/index.js +2 -0
  115. package/dist/icon/set.d.ts +1 -0
  116. package/dist/icon/set.js +3 -0
  117. package/dist/image/root/image-root.d.ts +14 -0
  118. package/dist/image/root/image-root.js +23 -2
  119. package/dist/input/root/input-root.d.ts +11 -0
  120. package/dist/input/root/input-root.js +16 -1
  121. package/dist/kbd/root/kbd-root.d.ts +20 -13
  122. package/dist/kbd/root/kbd-root.js +35 -37
  123. package/dist/kbd/shortcut.d.ts +18 -0
  124. package/dist/kbd/shortcut.js +35 -0
  125. package/dist/legend/hidden-series.d.ts +8 -0
  126. package/dist/legend/hidden-series.js +13 -0
  127. package/dist/legend/root/legend-root.d.ts +56 -0
  128. package/dist/legend/root/legend-root.js +54 -5
  129. package/dist/lightbox/item/lightbox-item.d.ts +15 -0
  130. package/dist/lightbox/item/lightbox-item.js +10 -1
  131. package/dist/lightbox/root/lightbox-root.d.ts +61 -1
  132. package/dist/lightbox/root/lightbox-root.js +94 -4
  133. package/dist/line-chart/root/line-chart-root.d.ts +11 -3
  134. package/dist/line-chart/root/line-chart-root.js +19 -5
  135. package/dist/list/item/list-item.d.ts +68 -1
  136. package/dist/list/item/list-item.js +66 -4
  137. package/dist/list/numbering.d.ts +14 -0
  138. package/dist/list/numbering.js +8 -0
  139. package/dist/list/root/list-root.d.ts +106 -9
  140. package/dist/list/root/list-root.js +189 -4
  141. package/dist/list/selection.d.ts +19 -0
  142. package/dist/list/selection.js +21 -0
  143. package/dist/listbox/root/listbox-root.d.ts +74 -3
  144. package/dist/listbox/root/listbox-root.js +86 -9
  145. package/dist/loader/busy.d.ts +17 -0
  146. package/dist/loader/busy.js +24 -0
  147. package/dist/loader/root/loader-root.d.ts +37 -0
  148. package/dist/loader/root/loader-root.js +52 -3
  149. package/dist/map/root/map-root.d.ts +6 -2
  150. package/dist/map/root/map-root.js +5 -2
  151. package/dist/megamenu/root/megamenu-root.d.ts +21 -0
  152. package/dist/megamenu/root/megamenu-root.js +16 -2
  153. package/dist/menu/index.d.ts +1 -0
  154. package/dist/menu/index.js +1 -0
  155. package/dist/menu/item/menu-item.d.ts +38 -11
  156. package/dist/menu/item/menu-item.js +33 -1
  157. package/dist/menu/root/menu-root.d.ts +25 -1
  158. package/dist/menu/root/menu-root.js +63 -6
  159. package/dist/menu/section/menu-section.d.ts +55 -0
  160. package/dist/menu/section/menu-section.js +60 -0
  161. package/dist/meter/root/meter-root.d.ts +7 -0
  162. package/dist/meter/root/meter-root.js +6 -3
  163. package/dist/navigation/root/navigation-root.d.ts +16 -1
  164. package/dist/navigation/root/navigation-root.js +27 -1
  165. package/dist/notifications/feed-keys.d.ts +10 -0
  166. package/dist/notifications/feed-keys.js +14 -0
  167. package/dist/notifications/notification/notification.d.ts +17 -0
  168. package/dist/notifications/notification/notification.js +21 -2
  169. package/dist/notifications/root/notifications-root.d.ts +60 -0
  170. package/dist/notifications/root/notifications-root.js +76 -1
  171. package/dist/number-input/root/number-input-root.d.ts +47 -0
  172. package/dist/number-input/root/number-input-root.js +58 -22
  173. package/dist/object-inspector/root/object-inspector-root.d.ts +98 -16
  174. package/dist/object-inspector/root/object-inspector-root.js +180 -80
  175. package/dist/object-inspector/rows.d.ts +57 -0
  176. package/dist/object-inspector/rows.js +86 -0
  177. package/dist/option/root/option-root.d.ts +54 -5
  178. package/dist/option/root/option-root.js +34 -5
  179. package/dist/outline/levels.d.ts +31 -0
  180. package/dist/outline/levels.js +23 -0
  181. package/dist/outline/root/outline-root.d.ts +68 -3
  182. package/dist/outline/root/outline-root.js +73 -8
  183. package/dist/pagination/size/pagination-size.d.ts +11 -2
  184. package/dist/pagination/size/pagination-size.js +19 -4
  185. package/dist/pin-input/format.d.ts +7 -0
  186. package/dist/pin-input/format.js +16 -0
  187. package/dist/pin-input/root/pin-input-root.d.ts +21 -0
  188. package/dist/pin-input/root/pin-input-root.js +29 -2
  189. package/dist/popover/root/popover-root.d.ts +62 -4
  190. package/dist/popover/root/popover-root.js +53 -5
  191. package/dist/progress/root/progress-root.d.ts +7 -0
  192. package/dist/progress/root/progress-root.js +9 -3
  193. package/dist/qr-code/export.d.ts +31 -0
  194. package/dist/qr-code/export.js +10 -0
  195. package/dist/qr-code/root/qr-code-root.d.ts +26 -0
  196. package/dist/qr-code/root/qr-code-root.js +49 -2
  197. package/dist/radio/group/radio-group.d.ts +17 -0
  198. package/dist/radio/group/radio-group.js +14 -1
  199. package/dist/rating/root/rating-root.d.ts +25 -0
  200. package/dist/rating/root/rating-root.js +46 -4
  201. package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
  202. package/dist/scatter-chart/root/scatter-chart-root.js +25 -7
  203. package/dist/scroll-area/root/scroll-area-root.d.ts +113 -0
  204. package/dist/scroll-area/root/scroll-area-root.js +218 -3
  205. package/dist/scroll-area/scrollbar.d.ts +65 -0
  206. package/dist/scroll-area/scrollbar.js +24 -0
  207. package/dist/select/root/select-root.d.ts +24 -0
  208. package/dist/select/root/select-root.js +21 -7
  209. package/dist/skeleton/root/skeleton-root.d.ts +25 -0
  210. package/dist/skeleton/root/skeleton-root.js +17 -2
  211. package/dist/slider/root/slider-root.d.ts +39 -0
  212. package/dist/slider/root/slider-root.js +45 -9
  213. package/dist/splitter/root/splitter-root.d.ts +13 -0
  214. package/dist/splitter/root/splitter-root.js +20 -2
  215. package/dist/splitter/snap.d.ts +9 -0
  216. package/dist/splitter/snap.js +12 -0
  217. package/dist/stat/root/stat-root.d.ts +2 -0
  218. package/dist/stat/root/stat-root.js +1 -1
  219. package/dist/steps/reach.d.ts +15 -0
  220. package/dist/steps/reach.js +12 -0
  221. package/dist/steps/root/steps-root.d.ts +30 -0
  222. package/dist/steps/root/steps-root.js +53 -0
  223. package/dist/steps/step/step.d.ts +39 -2
  224. package/dist/steps/step/step.js +29 -7
  225. package/dist/switch/root/switch-root.d.ts +12 -2
  226. package/dist/switch/root/switch-root.js +6 -1
  227. package/dist/table/column/table-column.d.ts +11 -0
  228. package/dist/table/column/table-column.js +6 -1
  229. package/dist/table/root/table-root.d.ts +101 -0
  230. package/dist/table/root/table-root.js +166 -5
  231. package/dist/table/row/table-row.d.ts +47 -1
  232. package/dist/table/row/table-row.js +39 -2
  233. package/dist/tabs/panel/tab-panel.d.ts +9 -5
  234. package/dist/tabs/panel/tab-panel.js +3 -4
  235. package/dist/tabs/root/tabs-root.d.ts +25 -1
  236. package/dist/tabs/root/tabs-root.js +21 -3
  237. package/dist/tabs/tab/tab.d.ts +36 -4
  238. package/dist/tabs/tab/tab.js +46 -3
  239. package/dist/tag/group/tag-group.d.ts +107 -0
  240. package/dist/tag/group/tag-group.js +157 -0
  241. package/dist/tag/index.d.ts +1 -0
  242. package/dist/tag/index.js +1 -0
  243. package/dist/tag/root/tag-root.d.ts +60 -0
  244. package/dist/tag/root/tag-root.js +74 -18
  245. package/dist/tag/selection.d.ts +10 -0
  246. package/dist/tag/selection.js +12 -0
  247. package/dist/textarea/grow.d.ts +22 -0
  248. package/dist/textarea/grow.js +20 -0
  249. package/dist/textarea/root/textarea-root.d.ts +9 -0
  250. package/dist/textarea/root/textarea-root.js +9 -1
  251. package/dist/time-input/root/time-input-root.d.ts +44 -5
  252. package/dist/time-input/root/time-input-root.js +69 -39
  253. package/dist/time-picker/root/time-picker-root.d.ts +54 -8
  254. package/dist/time-picker/root/time-picker-root.js +121 -91
  255. package/dist/timeline/group/timeline-group.d.ts +46 -0
  256. package/dist/timeline/group/timeline-group.js +37 -0
  257. package/dist/timeline/index.d.ts +1 -0
  258. package/dist/timeline/index.js +1 -0
  259. package/dist/timeline/root/timeline-root.d.ts +10 -3
  260. package/dist/toast/hotkey.d.ts +22 -0
  261. package/dist/toast/hotkey.js +23 -0
  262. package/dist/toast/item/toast-item.d.ts +26 -18
  263. package/dist/toast/item/toast-item.js +55 -48
  264. package/dist/toast/root/toast-root.d.ts +42 -8
  265. package/dist/toast/root/toast-root.js +64 -4
  266. package/dist/toggle/group/toggle-group.d.ts +57 -15
  267. package/dist/toggle/group/toggle-group.js +69 -9
  268. package/dist/toggle/root/toggle-root.d.ts +12 -1
  269. package/dist/toggle/root/toggle-root.js +11 -3
  270. package/dist/toolbar/root/toolbar-root.d.ts +13 -0
  271. package/dist/toolbar/root/toolbar-root.js +15 -5
  272. package/dist/tooltip/focus-target.d.ts +6 -0
  273. package/dist/tooltip/focus-target.js +9 -0
  274. package/dist/tooltip/root/tooltip-root.d.ts +42 -17
  275. package/dist/tooltip/root/tooltip-root.js +50 -9
  276. package/dist/tour/naming.d.ts +30 -0
  277. package/dist/tour/naming.js +10 -0
  278. package/dist/tour/root/tour-root.d.ts +35 -0
  279. package/dist/tour/root/tour-root.js +56 -5
  280. package/dist/tour/stop/tour-stop.d.ts +53 -8
  281. package/dist/tour/stop/tour-stop.js +45 -15
  282. package/dist/tour/wait.d.ts +11 -0
  283. package/dist/tour/wait.js +19 -0
  284. package/dist/tree/item/tree-item.d.ts +54 -1
  285. package/dist/tree/item/tree-item.js +89 -20
  286. package/dist/tree/root/tree-root.d.ts +37 -0
  287. package/dist/tree/root/tree-root.js +51 -6
  288. package/dist/tree/selection.d.ts +24 -0
  289. package/dist/tree/selection.js +26 -0
  290. package/dist/trend/root/trend-root.d.ts +13 -0
  291. package/dist/trend/root/trend-root.js +14 -9
  292. package/dist/video/media-events.d.ts +49 -0
  293. package/dist/video/media-events.js +39 -0
  294. package/dist/video/root/video-root.d.ts +99 -13
  295. package/dist/video/root/video-root.js +84 -47
  296. package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -0
  297. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  298. package/dist/video-playlist/order.d.ts +41 -0
  299. package/dist/video-playlist/order.js +34 -0
  300. package/dist/video-playlist/root/video-playlist-root.d.ts +70 -2
  301. package/dist/video-playlist/root/video-playlist-root.js +60 -16
  302. package/dist/virtual-list/controls.d.ts +4 -0
  303. package/dist/virtual-list/controls.js +30 -0
  304. package/dist/virtual-list/fill.d.ts +30 -0
  305. package/dist/virtual-list/fill.js +39 -0
  306. package/dist/virtual-list/keys.d.ts +15 -0
  307. package/dist/virtual-list/keys.js +24 -0
  308. package/dist/virtual-list/root/virtual-list-root.d.ts +155 -23
  309. package/dist/virtual-list/root/virtual-list-root.js +175 -34
  310. package/lint.json +1 -1
  311. package/package.json +5 -5
  312. package/types/jsx.d.ts +8871 -1286
  313. package/types/svelte.d.ts +3 -0
  314. package/types/vue.d.ts +1918 -269
@@ -1,5 +1,5 @@
1
1
  import { HelixElement } from '@fusion.dev/helix-core';
2
- import { type PropertyValues, type TemplateResult } from 'lit';
2
+ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
5
5
  * @summary One collapsible section of an accordion.
@@ -18,12 +18,18 @@ declare const HelixHeadlessAccordionItem_base: (new (...args: any[]) => import("
18
18
  * out of the tab order and the accessibility tree after the styled tier's
19
19
  * `display` overrides `hidden`.
20
20
  *
21
+ * Set `hidden-until-found` and the browser's find in page searches a closed
22
+ * section too: a match opens it, with `helix-before-open` first, as React
23
+ * Aria's disclosure does. The content is then `hidden="until-found"` while
24
+ * closed, and not `inert`, since an inert region is never searched.
25
+ *
21
26
  * @since 0.1.0
22
27
  * @status stable
23
28
  * @aliases Collapsible, Expander, Disclosure
24
29
  * @documentation https://fusion.dev/helix/components/accordion
25
30
  *
26
31
  * @slot - The content shown when the section is open.
32
+ * @slot chevron - Replaces the open and close indicator, such as with your own icon.
27
33
  * @slot summary - The text of the button that opens and closes the section. Always shown.
28
34
  *
29
35
  * @event {HelixBeforeCloseEvent} helix-before-close - The section is about to close. Cancelable: cancel it to keep it open.
@@ -51,8 +57,13 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
51
57
  * have two.
52
58
  */
53
59
  chevronPlacement?: 'auto' | 'start' | 'end' | 'none';
54
- /** The chevron, or nothing when suppressed. */
55
- private renderChevron;
60
+ /**
61
+ * The chevron, or nothing when suppressed.
62
+ *
63
+ * The drawn chevron is the `chevron` slot's fallback, so an icon of your own
64
+ * replaces it by being slotted, and a tier drawing its own overrides this.
65
+ */
66
+ protected renderChevron(): TemplateResult | typeof nothing;
56
67
  /**
57
68
  * Whether the section is disabled, so its trigger cannot be pressed or
58
69
  * reached with the arrow keys. A script can still open and close it.
@@ -64,6 +75,11 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
64
75
  * causes a hydration mismatch.
65
76
  */
66
77
  groupHeadingLevel: number | undefined;
78
+ /**
79
+ * @internal The accordion's `hidden-until-found`, written by the accordion,
80
+ * for the reason `groupHeadingLevel` is a property.
81
+ */
82
+ groupHiddenUntilFound: boolean;
67
83
  /**
68
84
  * The level of the heading around the trigger, from 1 to 6.
69
85
  *
@@ -71,6 +87,16 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
71
87
  * too.
72
88
  */
73
89
  headingLevel?: number;
90
+ /**
91
+ * Whether find in page searches the section while it is closed, and opens it
92
+ * on a match.
93
+ *
94
+ * Off by default. A closed section is then `hidden="until-found"`, which
95
+ * hides through `content-visibility`, so a stylesheet that animates the
96
+ * section closed shows an empty box for the length of that animation. The
97
+ * accordion's own `hidden-until-found` turns it on for every section.
98
+ */
99
+ hiddenUntilFound: boolean;
74
100
  /**
75
101
  * A group name. Opening an item closes the other items with the same name,
76
102
  * as `<details name>` does.
@@ -92,6 +118,15 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
92
118
  * absence. Caught by `hydration.dom.spec.ts`.
93
119
  */
94
120
  name?: string;
121
+ /** Whether find in page searches this section while it is closed. */
122
+ private get findable();
123
+ /**
124
+ * Opens the section find in page has matched in, before the match is shown.
125
+ *
126
+ * The browser removes `hidden` itself. A refusal puts it back, so the trigger
127
+ * and the region still agree.
128
+ */
129
+ private readonly handleBeforeMatch;
95
130
  /** Whether the item was open at the last update, and `undefined` before one. */
96
131
  private wasOpen;
97
132
  /**
@@ -157,16 +192,17 @@ export declare class HelixHeadlessAccordionItem extends HelixHeadlessAccordionIt
157
192
  * part outranks it and the transition runs exactly as before. Measured on
158
193
  * both tiers.
159
194
  *
160
- * **Not `hidden="until-found"`**, which would be the better accordion and is
161
- * a different piece of work. It hides through `content-visibility` rather
162
- * than `display`, which an author `display` does not override, so a collapsed
163
- * section a sheet animates would open to nothing. It also needs a
164
- * `beforematch` handler to set `open`, or find-in-page reveals text while the
165
- * trigger still reports collapsed.
195
+ * **`hidden="until-found"` only where it was asked for.** It hides through
196
+ * `content-visibility` rather than `display`, which an author `display` does
197
+ * not override, so a section a sheet animates closed shows an empty box while
198
+ * it shrinks. `beforematch` sets `open`, so find in page never reveals text
199
+ * under a trigger that still reports collapsed.
166
200
  *
167
- * `inert` stays. `hidden` answers the reader who can see and `inert` answers
168
- * the one tabbing through, and wherever a sheet overrides `display`, `inert`
169
- * is the only one of the two still in force.
201
+ * `inert` stays, except under `until-found`. `hidden` answers the reader who
202
+ * can see and `inert` answers the one tabbing through, and wherever a sheet
203
+ * overrides `display`, `inert` is the only one of the two still in force.
204
+ * `content-visibility: hidden` keeps skipped content out of the tab order and
205
+ * the accessibility tree by itself, and an inert region is never searched.
170
206
  */
171
207
  protected render(): TemplateResult;
172
208
  }
@@ -17,6 +17,15 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
17
17
  super(...arguments);
18
18
  this.disabled = false;
19
19
  this.groupHeadingLevel = undefined;
20
+ this.groupHiddenUntilFound = false;
21
+ this.hiddenUntilFound = false;
22
+ this.handleBeforeMatch = (event) => {
23
+ if (this.open || this.requestOpen(true)) {
24
+ return;
25
+ }
26
+ ;
27
+ event.currentTarget.setAttribute('hidden', 'until-found');
28
+ };
20
29
  this.wasOpen = undefined;
21
30
  this.handleToggle = () => {
22
31
  if (this.disabled) {
@@ -39,9 +48,14 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
39
48
  if (this.chevronPlacement === 'none') {
40
49
  return nothing;
41
50
  }
42
- return html `<svg part="chevron" fill="currentColor" viewBox=${caretDown.viewBox} aria-hidden="true">
43
- ${unsafeSVG(caretDown.content)}
44
- </svg>`;
51
+ return html `<slot name="chevron"
52
+ ><svg part="chevron" fill="currentColor" viewBox=${caretDown.viewBox} aria-hidden="true">
53
+ ${unsafeSVG(caretDown.content)}
54
+ </svg></slot
55
+ >`;
56
+ }
57
+ get findable() {
58
+ return this.hiddenUntilFound || this.groupHiddenUntilFound;
45
59
  }
46
60
  get accordion() {
47
61
  return closestInstance(this, HelixHeadlessAccordion);
@@ -103,9 +117,10 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
103
117
  id=${CONTENT_ID}
104
118
  aria-labelledby=${TRIGGER_ID}
105
119
  part="content"
106
- ?hidden=${!open}
107
- ?inert=${!open}
120
+ hidden=${open ? nothing : this.findable ? 'until-found' : ''}
121
+ ?inert=${!open && !this.findable}
108
122
  role="region"
123
+ @beforematch=${this.handleBeforeMatch}
109
124
  >
110
125
  <div part="content-inner">
111
126
  <slot></slot>
@@ -124,9 +139,15 @@ __decorate([
124
139
  __decorate([
125
140
  property({ attribute: false })
126
141
  ], HelixHeadlessAccordionItem.prototype, "groupHeadingLevel", void 0);
142
+ __decorate([
143
+ property({ attribute: false })
144
+ ], HelixHeadlessAccordionItem.prototype, "groupHiddenUntilFound", void 0);
127
145
  __decorate([
128
146
  property({ attribute: 'heading-level', type: Number })
129
147
  ], HelixHeadlessAccordionItem.prototype, "headingLevel", void 0);
148
+ __decorate([
149
+ property({ attribute: 'hidden-until-found', type: Boolean })
150
+ ], HelixHeadlessAccordionItem.prototype, "hiddenUntilFound", void 0);
130
151
  __decorate([
131
152
  property({ reflect: true })
132
153
  ], HelixHeadlessAccordionItem.prototype, "name", void 0);
@@ -39,6 +39,12 @@ export declare class HelixHeadlessAccordion extends HelixElement {
39
39
  * Unset is 3. An item's own `heading-level` wins over this.
40
40
  */
41
41
  headingLevel?: number;
42
+ /**
43
+ * Whether find in page searches every closed section, and opens the one it
44
+ * matches in. Each item's own `hidden-until-found` turns it on for that item
45
+ * alone.
46
+ */
47
+ hiddenUntilFound: boolean;
42
48
  /**
43
49
  * How many sections may be open at once.
44
50
  *
@@ -18,6 +18,7 @@ const navigable = (item) => ({
18
18
  let HelixHeadlessAccordion = class HelixHeadlessAccordion extends HelixElement {
19
19
  constructor() {
20
20
  super(...arguments);
21
+ this.hiddenUntilFound = false;
21
22
  this.keys = new KeyboardNavigationController(this, {
22
23
  items: () => this.items.map(navigable),
23
24
  origin: 'focus',
@@ -32,6 +33,7 @@ let HelixHeadlessAccordion = class HelixHeadlessAccordion extends HelixElement {
32
33
  for (const item of items) {
33
34
  whenHydrated(item, () => {
34
35
  item.groupHeadingLevel = this.headingLevel;
36
+ item.groupHiddenUntilFound = this.hiddenUntilFound;
35
37
  });
36
38
  }
37
39
  if (this.mode === undefined) {
@@ -56,7 +58,8 @@ let HelixHeadlessAccordion = class HelixHeadlessAccordion extends HelixElement {
56
58
  }
57
59
  updated(changed) {
58
60
  super.updated(changed);
59
- if (this.hasUpdated && (changed.has('mode') || changed.has('headingLevel'))) {
61
+ if (this.hasUpdated &&
62
+ (changed.has('mode') || changed.has('headingLevel') || changed.has('hiddenUntilFound'))) {
60
63
  this.settle();
61
64
  }
62
65
  }
@@ -67,6 +70,9 @@ let HelixHeadlessAccordion = class HelixHeadlessAccordion extends HelixElement {
67
70
  __decorate([
68
71
  property({ attribute: 'heading-level', type: Number })
69
72
  ], HelixHeadlessAccordion.prototype, "headingLevel", void 0);
73
+ __decorate([
74
+ property({ attribute: 'hidden-until-found', type: Boolean })
75
+ ], HelixHeadlessAccordion.prototype, "hiddenUntilFound", void 0);
70
76
  __decorate([
71
77
  property({ reflect: true })
72
78
  ], HelixHeadlessAccordion.prototype, "mode", void 0);
@@ -28,6 +28,11 @@ declare const HelixHeadlessAnnouncement_base: (new (...args: any[]) => import("@
28
28
  * announcement beside it, move focus yourself, for example to the page's main
29
29
  * heading.
30
30
  *
31
+ * Set `duration` to dismiss it after a time. The clock stops while the pointer
32
+ * or focus is on the announcement, and continues from what was left, so a
33
+ * reader partway through is not cut off. When the time runs out it sends
34
+ * `helix-dismiss`, as the button does.
35
+ *
31
36
  * @since 0.1.0
32
37
  * @status stable
33
38
  * @category feedback
@@ -38,7 +43,7 @@ declare const HelixHeadlessAnnouncement_base: (new (...args: any[]) => import("@
38
43
  * @slot actions - Actions for the message, usually a link or a button.
39
44
  * @slot icon - Replaces the icon inside the dismiss button.
40
45
  *
41
- * @event {HelixDismissEvent} helix-dismiss - The dismiss button was pressed. The announcement does not remove itself, so remove it in response. Cancelable.
46
+ * @event {HelixDismissEvent} helix-dismiss - The dismiss button was pressed, or `duration` ran out. The announcement does not remove itself, so remove it in response. Cancelable.
42
47
  *
43
48
  * @csspart actions - The region after the message that holds the actions.
44
49
  * @csspart content - The region that holds the message.
@@ -47,6 +52,14 @@ declare const HelixHeadlessAnnouncement_base: (new (...args: any[]) => import("@
47
52
  * @csspart live - A copy of the message in a live region, read by screen readers when the announcement appears after the page has loaded, and emptied seven seconds later. Visually hidden in the styled tier.
48
53
  */
49
54
  export declare class HelixHeadlessAnnouncement extends HelixHeadlessAnnouncement_base {
55
+ /**
56
+ * How long the announcement stays, in milliseconds, before it sends
57
+ * `helix-dismiss`. When it is not set, it stays until it is dismissed.
58
+ *
59
+ * Read once when the announcement is first rendered, as `Toast` reads its
60
+ * own. The clock stops while the pointer or focus is on the announcement.
61
+ */
62
+ duration?: number;
50
63
  /**
51
64
  * The band's color.
52
65
  *
@@ -71,6 +84,13 @@ export declare class HelixHeadlessAnnouncement extends HelixHeadlessAnnouncement
71
84
  */
72
85
  tone?: 'accent' | 'danger' | 'info' | 'neutral' | 'primary' | 'success' | 'warning';
73
86
  protected readonly arrival: ArrivalController;
87
+ /** The time `duration` gives it, held while a reader is on it. */
88
+ private readonly countdown;
89
+ private readonly handleHold;
90
+ private readonly handleRelease;
91
+ connectedCallback(): void;
92
+ disconnectedCallback(): void;
93
+ protected firstUpdated(changed: PropertyValues): void;
74
94
  protected updated(changed: PropertyValues): void;
75
95
  /**
76
96
  * Says on the `actions` region whether anything is in it.
@@ -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 { ArrivalController, customElement, HelixElement, MixinDismissible, markRegion, slottedWords, } from '@fusion.dev/helix-core';
7
+ import { ArrivalController, CountdownController, customElement, HelixElement, MixinDismissible, markRegion, slottedWords, } from '@fusion.dev/helix-core';
8
8
  import { x } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
@@ -16,6 +16,38 @@ let HelixHeadlessAnnouncement = class HelixHeadlessAnnouncement extends MixinDis
16
16
  arriving: () => !this.serverRendered && document.readyState === 'complete',
17
17
  text: () => slottedWords(this, ['']),
18
18
  });
19
+ this.countdown = new CountdownController(this, {
20
+ done: () => {
21
+ this.dismiss();
22
+ },
23
+ });
24
+ this.handleHold = () => {
25
+ this.countdown.hold();
26
+ };
27
+ this.handleRelease = () => {
28
+ this.countdown.release();
29
+ };
30
+ }
31
+ connectedCallback() {
32
+ super.connectedCallback();
33
+ this.addEventListener('mouseenter', this.handleHold);
34
+ this.addEventListener('mouseleave', this.handleRelease);
35
+ this.addEventListener('focusin', this.handleHold);
36
+ this.addEventListener('focusout', this.handleRelease);
37
+ if (this.hasUpdated) {
38
+ this.countdown.resume();
39
+ }
40
+ }
41
+ disconnectedCallback() {
42
+ super.disconnectedCallback();
43
+ this.removeEventListener('mouseenter', this.handleHold);
44
+ this.removeEventListener('mouseleave', this.handleRelease);
45
+ this.removeEventListener('focusin', this.handleHold);
46
+ this.removeEventListener('focusout', this.handleRelease);
47
+ }
48
+ firstUpdated(changed) {
49
+ super.firstUpdated(changed);
50
+ this.countdown.start(this.duration);
19
51
  }
20
52
  updated(changed) {
21
53
  super.updated(changed);
@@ -47,6 +79,9 @@ let HelixHeadlessAnnouncement = class HelixHeadlessAnnouncement extends MixinDis
47
79
  : nothing}`;
48
80
  }
49
81
  };
82
+ __decorate([
83
+ property({ type: Number })
84
+ ], HelixHeadlessAnnouncement.prototype, "duration", void 0);
50
85
  __decorate([
51
86
  property({ reflect: true })
52
87
  ], HelixHeadlessAnnouncement.prototype, "tone", void 0);
@@ -19,6 +19,12 @@ import { type PropertyValues, type TemplateResult } from 'lit';
19
19
  * The page is the window unless `scroller` names the element that scrolls, for
20
20
  * an app shell whose content scrolls inside a container.
21
21
  *
22
+ * The host is the page's `banner` landmark. Placed inside `main`, `article`,
23
+ * `aside`, `nav` or `section`, it is a plain box instead, as a native
24
+ * `<header>` is there, so a header inside a card or a pane does not add a
25
+ * second banner. A server cannot see the ancestors, so it serves the banner and
26
+ * the browser corrects it when the element connects.
27
+ *
22
28
  * @since 0.1.0
23
29
  * @status stable
24
30
  * @category navigation
@@ -64,6 +70,7 @@ export declare class HelixHeadlessAppHeader extends HelixElement {
64
70
  * scrolls a container instead of the window. Unset is the window.
65
71
  */
66
72
  scroller?: string;
73
+ private landmark;
67
74
  private scrolled;
68
75
  /** What scroll is listened to now, so a change of `scroller` moves it. */
69
76
  private source;
@@ -7,9 +7,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { customElement, elementById, HelixElement, HelixScrolledEvent, hostAria, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { inSectioningContent } from '../sectioning.js';
10
11
  let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
11
12
  constructor() {
12
13
  super(...arguments);
14
+ this.landmark = 'banner';
13
15
  this.scrolled = false;
14
16
  this.handleScroll = () => {
15
17
  const source = this.source ?? window;
@@ -41,10 +43,12 @@ let HelixHeadlessAppHeader = class HelixHeadlessAppHeader extends HelixElement {
41
43
  }
42
44
  willUpdate(changed) {
43
45
  super.willUpdate(changed);
44
- hostAria(this.internals, { role: 'banner' });
46
+ hostAria(this.internals, { role: this.landmark });
45
47
  }
46
48
  connectedCallback() {
47
49
  super.connectedCallback();
50
+ this.landmark = inSectioningContent(this) ? '' : 'banner';
51
+ hostAria(this.internals, { role: this.landmark });
48
52
  this.listen();
49
53
  }
50
54
  disconnectedCallback() {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Whether an element sits inside sectioning content, read across shadow
3
+ * boundaries as the accessibility tree reads it.
4
+ *
5
+ * Client only: a server has no ancestors to read.
6
+ */
7
+ export declare const inSectioningContent: (element: Element) => boolean;
@@ -0,0 +1,26 @@
1
+ const SECTIONING = [
2
+ 'article',
3
+ 'aside',
4
+ 'main',
5
+ 'nav',
6
+ 'section',
7
+ '[role="article"]',
8
+ '[role="complementary"]',
9
+ '[role="main"]',
10
+ '[role="navigation"]',
11
+ '[role="region"]',
12
+ ].join(', ');
13
+ export const inSectioningContent = (element) => {
14
+ let node = element.parentElement ?? hostOf(element);
15
+ while (node) {
16
+ if (node.matches(SECTIONING)) {
17
+ return true;
18
+ }
19
+ node = node.parentElement ?? hostOf(node);
20
+ }
21
+ return false;
22
+ };
23
+ const hostOf = (element) => {
24
+ const root = element.getRootNode();
25
+ return root instanceof ShadowRoot ? root.host : null;
26
+ };
@@ -44,9 +44,15 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
44
44
  * bands show each part's share. Use it to see which part grew. The default
45
45
  * shows whether the total grew.
46
46
  *
47
- * The drawing is `aria-hidden`. The text summary gives the latest reading's
48
- * total and each part's share of it, and the table beside the chart has every
49
- * number.
47
+ * The drawing is hidden from screen readers. The text summary gives the latest
48
+ * reading's total and each part's share of it, and the table beside the chart
49
+ * has every number.
50
+ *
51
+ * **The plot is read by key.** It takes focus, named by `label` or the caption.
52
+ * The left and right arrows move from reading to reading, Home and End go to
53
+ * the first and the last, and the up and down arrows move among the series of
54
+ * a reading. The tooltip follows, the `live` part says the reading in words,
55
+ * and Escape puts the tooltip away.
50
56
  *
51
57
  * Every numeric column is a part, so leave a total column out of the table the
52
58
  * chart reads, or it is counted twice. A negative reading is drawn as zero.
@@ -64,8 +70,9 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
64
70
  * @csspart label - One reading's name.
65
71
  * @csspart labels - The row of reading names.
66
72
  * @csspart line - The top edge of one part's band.
73
+ * @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
67
74
  * @csspart mark - The invisible point the tooltip is anchored to.
68
- * @csspart plot - The drawing.
75
+ * @csspart plot - The drawing, which takes focus to be read by key.
69
76
  * @csspart summary - The total and each part's share at the latest reading, written as a sentence for screen readers.
70
77
  * @csspart svg - The drawing surface the bands sit on.
71
78
  * @csspart tooltip - The bubble, forwarded from `Tooltip`.
@@ -77,6 +84,7 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
77
84
  * @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
78
85
  * @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
79
86
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
87
+ * @csspart tooltip-cell-current - The cell the up and down arrows rest on, while they rest there. Set alongside `tooltip-cell`.
80
88
  * @csspart tooltip-label - The reading's own name inside the tooltip.
81
89
  * @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
82
90
  * @csspart tooltip-name - A column's name inside the tooltip.
@@ -36,7 +36,11 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
36
36
  get stack() {
37
37
  const rows = this.sourceRows;
38
38
  const columns = this.plottedColumns;
39
- const values = columns.map((column) => rows.map((row) => {
39
+ const names = columns.map((column) => rows.find((row) => row.cells[column])?.cells[column]?.name ?? '');
40
+ const values = columns.map((column, depth) => rows.map((row) => {
41
+ if (!this.showsSeries(names[depth] ?? '')) {
42
+ return 0;
43
+ }
40
44
  const value = row.cells[column]?.value ?? 0;
41
45
  if (value < 0) {
42
46
  this.warnNegative();
@@ -59,7 +63,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
59
63
  return {
60
64
  columns,
61
65
  layers,
62
- names: columns.map((column) => rows.find((row) => row.cells[column])?.cells[column]?.name ?? ''),
66
+ names,
63
67
  totals,
64
68
  values,
65
69
  };
@@ -94,8 +98,17 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
94
98
  }
95
99
  renderPlot(stack, count, x, y, domain) {
96
100
  const order = stack.layers.map((_, depth) => depth).reverse();
97
- return html `<div aria-hidden="true" id=${CHART_PLOT} part="plot">
101
+ return html `<div
102
+ aria-describedby=${this.named ? 'helix-chart-summary' : nothing}
103
+ aria-label=${this.named || nothing}
104
+ aria-labelledby=${this.named ? nothing : 'helix-chart-summary'}
105
+ id=${CHART_PLOT}
106
+ part="plot"
107
+ role="application"
108
+ tabindex="0"
109
+ >
98
110
  <svg part="svg"
111
+ aria-hidden="true"
99
112
  data-mirror
100
113
  preserveAspectRatio="none"
101
114
  viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
@@ -162,9 +175,13 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
162
175
  const last = rows.length - 1;
163
176
  const total = stack.totals[last] ?? 0;
164
177
  const format = formatNumbers(this.locale);
165
- const shares = stack.names.map((name, depth) => `${name} ${percentIn(this.locale).format(total > 0 ? (stack.values[depth]?.[last] ?? 0) / total : 0)}`);
178
+ const shares = stack.names.flatMap((name, depth) => this.showsSeries(name)
179
+ ? [
180
+ `${name} ${percentIn(this.locale).format(total > 0 ? (stack.values[depth]?.[last] ?? 0) / total : 0)}`,
181
+ ]
182
+ : []);
166
183
  const named = this.named ? `${this.named}, ` : '';
167
- return html `<p part="summary">
184
+ return html `<p id="helix-chart-summary" part="summary">
168
185
  ${named}${rows[last]?.label ?? ''}: ${this.totalLabel} ${format(total)}; ${shares.join(', ')}.
169
186
  </p>`;
170
187
  }
@@ -190,14 +207,14 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
190
207
  const at = this.pointer.at;
191
208
  const rows = this.tallied(this.sourceRows, stack);
192
209
  if (at < 0) {
193
- return drawTooltip(rows, at, this.tag('tooltip'));
210
+ return drawTooltip(rows, at, this.tag('tooltip'), undefined, undefined, this.pointer);
194
211
  }
195
212
  const slot = 100 / rows.length;
196
213
  return drawTooltip(rows, at, this.tag('tooltip'), {
197
214
  placement: 'top',
198
215
  x: `${at * slot + slot / 2}%`,
199
216
  y: `${y(stack.layers.at(-1)?.[at] ?? 0)}%`,
200
- }, (cell) => this.seriesOf(cell));
217
+ }, (cell) => this.seriesOf(cell), this.pointer);
201
218
  }
202
219
  };
203
220
  __decorate([
@@ -32,6 +32,17 @@ export declare const initialsOf: (name: string) => string;
32
32
  * @csspart initials - The initials shown when there is no usable image.
33
33
  */
34
34
  export declare class HelixHeadlessAvatar extends HelixElement {
35
+ /**
36
+ * How long, in milliseconds, a picture may take before the initials stand
37
+ * in for it while it loads.
38
+ *
39
+ * Absent keeps the picture's place empty until it arrives or fails. Set,
40
+ * the initials show once the wait is over and the picture
41
+ * replaces them when it arrives, so a slow connection shows who it is
42
+ * without a cached picture flashing initials first. Radix's `delayMs` is the
43
+ * same idea.
44
+ */
45
+ fallbackDelay?: number;
35
46
  /**
36
47
  * Name of the person or entity.
37
48
  *
@@ -65,10 +76,13 @@ export declare class HelixHeadlessAvatar extends HelixElement {
65
76
  * report waits for the event it reports, below.
66
77
  */
67
78
  private broken;
79
+ /** The wait `fallback-delay` asks for, which has run out for the picture loading now or not. */
80
+ private readonly wait;
68
81
  private readonly handleError;
69
82
  private readonly handleLoad;
70
83
  protected willUpdate(changed: PropertyValues): void;
71
84
  protected firstUpdated(changed: PropertyValues): void;
85
+ private startWait;
72
86
  protected updated(changed: PropertyValues): void;
73
87
  protected render(): TemplateResult;
74
88
  /**
@@ -4,8 +4,8 @@ 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, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
- import { html } from 'lit';
7
+ import { customElement, DelayController, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
+ import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  export const initialsOf = (name) => {
11
11
  const words = name.trim().split(/\s+/).filter(Boolean);
@@ -24,6 +24,7 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
24
24
  this.src = '';
25
25
  this.status = 'loading';
26
26
  this.broken = false;
27
+ this.wait = new DelayController(this);
27
28
  this.handleError = (event) => {
28
29
  this.broken = true;
29
30
  this.status = 'error';
@@ -64,8 +65,16 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
64
65
  });
65
66
  }
66
67
  }
68
+ startWait() {
69
+ this.wait.start(this.fallbackDelay !== undefined && this.src !== ''
70
+ ? Math.max(this.fallbackDelay, 0)
71
+ : undefined);
72
+ }
67
73
  updated(changed) {
68
74
  super.updated(changed);
75
+ if (changed.has('src') || changed.has('fallbackDelay')) {
76
+ this.startWait();
77
+ }
69
78
  if (changed.has('status')) {
70
79
  if (this.status === 'loading') {
71
80
  this.removeAttribute('data-status');
@@ -77,13 +86,15 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
77
86
  }
78
87
  render() {
79
88
  if (this.src !== '' && !this.broken) {
80
- return html `<img
81
- part="image"
82
- src=${this.src}
83
- alt=""
84
- @error=${this.handleError}
85
- @load=${this.handleLoad}
86
- />`;
89
+ const standIn = this.wait.elapsed && this.status === 'loading';
90
+ return html `${standIn ? this.renderInitials() : nothing}<img
91
+ part="image"
92
+ src=${this.src}
93
+ alt=""
94
+ ?hidden=${standIn}
95
+ @error=${this.handleError}
96
+ @load=${this.handleLoad}
97
+ />`;
87
98
  }
88
99
  return this.renderInitials();
89
100
  }
@@ -93,6 +104,9 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
93
104
  </slot>`;
94
105
  }
95
106
  };
107
+ __decorate([
108
+ property({ attribute: 'fallback-delay', type: Number })
109
+ ], HelixHeadlessAvatar.prototype, "fallbackDelay", void 0);
96
110
  __decorate([
97
111
  property()
98
112
  ], HelixHeadlessAvatar.prototype, "name", void 0);
@@ -18,13 +18,17 @@ import { type TemplateResult } from 'lit';
18
18
  * fuller name, such as `4 unread`. A dot needs a `label`. Without one, the dot
19
19
  * is a colored circle that screen readers do not announce.
20
20
  *
21
- * **The count is not part of the wrapped control's name.** It is a status of
22
- * its own, read when it changes and when a reader moves to it, so focusing a
23
- * button inside a badge announces the button's name alone. Where the count
24
- * belongs in that name, write it into the control's own label, such as
25
- * `aria-label="Inbox, 8 unread"` on a button that reads "Inbox". The badge
26
- * cannot add it: a reference from the control to the count would point into
27
- * the badge's shadow root, which the platform does not allow.
21
+ * **A badge wrapped around a control is not part of the control's name.** It
22
+ * is a status of its own, read when it changes and when a reader moves to it,
23
+ * so focusing a button inside a badge announces the button's name alone. A
24
+ * reference from the control to the count would point into the badge's shadow
25
+ * root, which the platform does not allow.
26
+ *
27
+ * **Put the badge inside the control to have its count read with the
28
+ * control's name**, as Web Awesome and Shoelace do: `<button>Inbox
29
+ * <helix-badge value="8" label="8 unread"></helix-badge></button>` is the
30
+ * button "Inbox 8 unread", and stays current as the count changes. The styled
31
+ * tier's `placement="inline"` draws the mark in the line for that case.
28
32
  *
29
33
  * @since 0.1.0
30
34
  * @status stable