@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,4 +1,4 @@
1
- import { HelixElement, type ToneMark } from '@fusion.dev/helix-core';
1
+ import { HelixElement, SwipeController, type ToneMark } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fusion.dev/helix-core").DismissibleElement) & typeof HelixElement;
4
4
  /**
@@ -12,6 +12,16 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
12
12
  * with each new message, and the last of three messages would stay for nine
13
13
  * seconds.
14
14
  *
15
+ * **Each message is an `alertdialog` named by its words**, which is how a reader
16
+ * who moves into the stack hears which message they are on. A `danger` message
17
+ * is its own assertive live region, so it is announced at once; every other one
18
+ * is announced politely by the region.
19
+ *
20
+ * A touch or a pen swipes a message toward the end of the line, and past
21
+ * halfway, or quickly, dismisses it through the same `helix-dismiss` as its
22
+ * control. While it moves, the distance is on the `item` part as
23
+ * `--toast-swipe-x`.
24
+ *
15
25
  * **Messages are inverted by default.** The item flips `color-scheme`, so a new
16
26
  * message stands out from the page without using a color that carries meaning.
17
27
  *
@@ -39,6 +49,7 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
39
49
  * @csspart timer - The bar showing how long is left, where a duration was given.
40
50
  *
41
51
  * @cssproperty --toast-duration - How long this message stays, in milliseconds, for a progress hint.
52
+ * @cssproperty --toast-swipe-x - How far a swipe has moved the message across, in pixels, toward the right.
42
53
  */
43
54
  export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base {
44
55
  /**
@@ -64,11 +75,19 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
64
75
  */
65
76
  get open(): boolean;
66
77
  set open(next: boolean);
67
- /** When the current run of the timer began, or nothing while it is paused. */
68
- private startedAt;
69
- /** What is left of the duration, so resuming continues rather than restarts. */
70
- private remaining;
71
- private timer;
78
+ protected readonly swipes: SwipeController;
79
+ /** Writes how far a swipe has moved the message toward the end of the line. */
80
+ private slide;
81
+ /**
82
+ * The dismiss timer, which pauses while a reader is on the message and
83
+ * continues from what was left.
84
+ *
85
+ * Paused is said on the host so the indicator can freeze with the clock. A
86
+ * `data-` attribute rather than a property, because it is written after
87
+ * upgrade from a pointer moving: nothing declares it and no server rendered
88
+ * it, which is the same reason `Carousel` names its slides from here.
89
+ */
90
+ private readonly countdown;
72
91
  /**
73
92
  * The kind of message, which sets its mark and the mark's accessible name.
74
93
  *
@@ -90,22 +109,11 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
90
109
  pause(): void;
91
110
  /** Restarts the dismiss timer from where it paused. */
92
111
  resume(): void;
93
- /**
94
- * How many reasons there are to hold the clock, rather than whether there is
95
- * one.
96
- *
97
- * Hover and focus stop the same timer, and the two are genuinely independent:
98
- * a pointer can leave while focus stays, and focus can leave while the
99
- * pointer stays. Uncounted, a reader who tabs into a message and then moves
100
- * the pointer off it has the clock restarted underneath them, which is the
101
- * case the pause exists for. Only the last one out starts it again.
102
- */
103
- private holds;
104
112
  private readonly handlePause;
105
113
  private readonly handleResume;
106
114
  connectedCallback(): void;
107
- disconnectedCallback(): void;
108
115
  protected willUpdate(changed: PropertyValues): void;
116
+ protected updated(changed: PropertyValues): void;
109
117
  protected firstUpdated(changed: PropertyValues): void;
110
118
  /**
111
119
  * The mark for the message's tone, behind a seam.
@@ -4,25 +4,47 @@ 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, MixinDismissible, requestChange, toneMark, } from '@fusion.dev/helix-core';
8
- import { x } from '@fusion.dev/helix-icons';
7
+ import { CountdownController, customElement, drawDismiss, drawDismissGlyph, HelixElement, hostAria, isRtl, MixinDismissible, requestChange, SwipeController, settleSwipe, swipeEdge, toneMark, towardEdge, } from '@fusion.dev/helix-core';
9
8
  import { html, nothing } from 'lit';
10
9
  import { property } from 'lit/decorators.js';
11
10
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
12
11
  let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissible(HelixElement) {
13
12
  constructor() {
14
13
  super(...arguments);
14
+ this.swipes = new SwipeController(this, {
15
+ axis: () => (this.open ? 'x' : undefined),
16
+ end: (dx, _dy, vx) => {
17
+ const edge = swipeEdge('end', isRtl(this));
18
+ const width = this.partNamed('item')?.getBoundingClientRect().width ?? 0;
19
+ const shown = settleSwipe({
20
+ points: [1],
21
+ size: width,
22
+ travel: Math.max(0, towardEdge(edge, dx, 0)),
23
+ velocity: towardEdge(edge, vx, 0),
24
+ });
25
+ if (shown === 0 && this.dismiss()) {
26
+ return;
27
+ }
28
+ this.slide(0);
29
+ },
30
+ move: (dx) => this.slide(Math.max(0, towardEdge(swipeEdge('end', isRtl(this)), dx, 0))),
31
+ start: (_target, event) => event.pointerType !== 'mouse',
32
+ surface: () => this.partNamed('item'),
33
+ });
34
+ this.countdown = new CountdownController(this, {
35
+ done: () => {
36
+ this.dismiss();
37
+ },
38
+ paused: (paused) => {
39
+ this.toggleAttribute('data-paused', paused);
40
+ },
41
+ });
15
42
  this.openState = undefined;
16
- this.holds = 0;
17
43
  this.handlePause = () => {
18
- this.holds += 1;
19
- this.pause();
44
+ this.countdown.hold();
20
45
  };
21
46
  this.handleResume = () => {
22
- this.holds = Math.max(this.holds - 1, 0);
23
- if (this.holds === 0) {
24
- this.resume();
25
- }
47
+ this.countdown.release();
26
48
  };
27
49
  }
28
50
  get open() {
@@ -33,12 +55,15 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
33
55
  this.openState = next;
34
56
  this.requestUpdate('open', previous);
35
57
  }
58
+ slide(travel) {
59
+ const physical = isRtl(this) ? -travel : travel;
60
+ this.partNamed('item')?.style.setProperty('--toast-swipe-x', travel === 0 ? '' : `${Math.round(physical)}px`);
61
+ }
36
62
  dismiss() {
37
63
  if (!this.open) {
38
64
  return true;
39
65
  }
40
- clearTimeout(this.timer);
41
- this.timer = undefined;
66
+ this.countdown.cancel();
42
67
  return requestChange({
43
68
  apply: () => {
44
69
  const previous = this.open;
@@ -51,25 +76,10 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
51
76
  });
52
77
  }
53
78
  pause() {
54
- if (this.timer === undefined || this.startedAt === undefined) {
55
- return;
56
- }
57
- clearTimeout(this.timer);
58
- this.timer = undefined;
59
- this.remaining = Math.max((this.remaining ?? 0) - (Date.now() - this.startedAt), 0);
60
- this.startedAt = undefined;
61
- this.toggleAttribute('data-paused', true);
79
+ this.countdown.pause();
62
80
  }
63
81
  resume() {
64
- if (this.timer !== undefined || this.remaining === undefined || this.remaining <= 0) {
65
- return;
66
- }
67
- this.startedAt = Date.now();
68
- this.toggleAttribute('data-paused', false);
69
- this.timer = setTimeout(() => {
70
- this.timer = undefined;
71
- this.dismiss();
72
- }, this.remaining);
82
+ this.countdown.resume();
73
83
  }
74
84
  connectedCallback() {
75
85
  super.connectedCallback();
@@ -77,22 +87,24 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
77
87
  this.resume();
78
88
  }
79
89
  }
80
- disconnectedCallback() {
81
- super.disconnectedCallback();
82
- this.pause();
83
- this.holds = 0;
84
- }
85
90
  willUpdate(changed) {
86
91
  super.willUpdate(changed);
87
92
  this.toggleAttribute('data-closed', !this.open);
88
93
  this.toggleAttribute('hidden', !this.open);
94
+ hostAria(this.internals, { role: 'alertdialog' });
95
+ this.internals.ariaModal = 'false';
96
+ this.internals.ariaLive = this.tone === 'danger' ? 'assertive' : null;
97
+ }
98
+ updated(changed) {
99
+ super.updated(changed);
100
+ const words = this.partNamed('content');
101
+ if (words) {
102
+ hostAria(this.internals, { labelledBy: [words] });
103
+ }
89
104
  }
90
105
  firstUpdated(changed) {
91
106
  super.firstUpdated(changed);
92
- if (this.duration !== undefined && this.duration > 0) {
93
- this.remaining = this.duration;
94
- this.resume();
95
- }
107
+ this.countdown.start(this.duration);
96
108
  }
97
109
  renderIcon(mark) {
98
110
  return html `<slot name="icon">
@@ -108,9 +120,7 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
108
120
  }
109
121
  renderDismissIcon() {
110
122
  return html `<slot name="dismiss-icon">
111
- <svg part="dismiss-mark" viewBox=${x.viewBox} fill="currentColor" aria-hidden="true">
112
- ${unsafeSVG(x.content)}
113
- </svg>
123
+ ${drawDismissGlyph()}
114
124
  </slot>`;
115
125
  }
116
126
  render() {
@@ -130,14 +140,11 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
130
140
  <div part="content"><slot></slot></div>
131
141
  <div part="actions"><slot name="actions"></slot></div>
132
142
  ${this.dismissible
133
- ? html `<button
134
- part="dismiss"
135
- type="button"
136
- aria-label=${this.dismissLabel}
137
- @click=${() => this.dismiss()}
138
- >
139
- ${this.renderDismissIcon()}
140
- </button>`
143
+ ? drawDismiss({
144
+ label: this.dismissLabel,
145
+ mark: this.renderDismissIcon(),
146
+ onDismiss: () => this.dismiss(),
147
+ })
141
148
  : nothing}
142
149
  ${this.duration
143
150
  ? html `<div
@@ -9,9 +9,15 @@ import { type PropertyValues, type TemplateResult } from 'lit';
9
9
  * announce a region that arrives already holding its message. `Radio.Group` is
10
10
  * part of its family for the same reason.
11
11
  *
12
- * **The region is polite, never assertive.** `role="alert"` interrupts whatever
13
- * a screen reader is reading. For something that cannot wait, use a `Dialog`,
14
- * which stops the page for every user.
12
+ * **The region is a landmark named by `label`, and a polite live region.** A
13
+ * `danger` message is announced assertively, and every other one politely.
14
+ * Each message is an `alertdialog` named by its words, so a reader who moves
15
+ * into the stack hears which message they are on.
16
+ *
17
+ * **`hotkey` takes focus to the stack and back**, F8 unless you set it, and
18
+ * `label` says which key: `{hotkey}` in it is filled in, so the default name
19
+ * is "Notifications (F8)". Pressed while focus is in the stack, it gives focus
20
+ * back to where it was.
15
21
  *
16
22
  * **The region never creates or removes items.** You render items and remove
17
23
  * them. An item requests closing with a cancelable `helix-dismiss` event. A
@@ -19,9 +25,11 @@ import { type PropertyValues, type TemplateResult } from 'lit';
19
25
  * and the DOM stay in sync. It hides on its own unless you set `open`, which
20
26
  * makes the state yours.
21
27
  *
22
- * There is no `toast.show()`. For a `toast()` function, write a small one over
23
- * your app's state, which also lets you render the same messages on the server,
24
- * in a test, or more than once.
28
+ * **`add()` shows a message from script**, for a page with no framework state
29
+ * to render them from: it appends a message of the region's own tier and
30
+ * removes it once it has been dismissed and has finished leaving. Messages
31
+ * you render yourself stay yours, and the region never removes them. A touch
32
+ * or a pen swipes a message away toward the end of the line.
25
33
  *
26
34
  * **The stack is in the top layer.** The `region` part is a `popover="manual"`
27
35
  * shown while a message is showing, and shown again above a modal dialog that
@@ -46,11 +54,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
46
54
  *
47
55
  * @event {HelixDismissEvent} helix-dismiss - A message is being dismissed, by its control or by its timer. The message sends it, and you can listen for it on the region. Cancelable: canceling it keeps the message.
48
56
  *
49
- * @csspart region - The stack the messages are in. It is in the top layer while a message shows.
57
+ * @csspart region - The stack the messages are in. It is in the top layer while a message shows, and takes focus from `hotkey` where no message holds a control.
50
58
  */
51
59
  export declare class HelixHeadlessToast extends HelixElement {
52
60
  /**
53
- * Accessible name for the region, such as "Notifications".
61
+ * The key that takes focus to the stack and back, such as `F8` or `Alt+T`:
62
+ * keys joined by `+`, the last one the key. Empty turns it off.
63
+ */
64
+ hotkey: string;
65
+ /**
66
+ * Accessible name for the region, with `{hotkey}` filled in. Translate it with
67
+ * the rest of your interface.
54
68
  */
55
69
  label: string;
56
70
  /**
@@ -83,6 +97,26 @@ export declare class HelixHeadlessToast extends HelixElement {
83
97
  protected willUpdate(changed: PropertyValues): void;
84
98
  /** The element focus came from when it entered the stack. */
85
99
  private focusOrigin;
100
+ private readonly scope;
101
+ /** Takes focus to the stack and back, on `hotkey`. */
102
+ private readonly handleHotkey;
103
+ /** Messages `add()` made, which are the region's to remove. */
104
+ private readonly made;
105
+ /**
106
+ * Shows a message from script, and returns the element.
107
+ *
108
+ * The message is the region's own tier of `Toast.Item`, appended to the
109
+ * stack, holding `message` as its text. The region removes it once it has
110
+ * been dismissed and has finished leaving, which is the one case where it
111
+ * removes anything: a message you render stays yours.
112
+ */
113
+ add(message: string, options?: {
114
+ dismissible?: boolean;
115
+ duration?: number;
116
+ tone?: 'danger' | 'info' | 'success' | 'warning';
117
+ }): HTMLElement;
118
+ /** Removes a message `add()` made, once it has hidden and finished leaving. */
119
+ private sweep;
86
120
  /** Watches the messages arrive and hide, to raise or lower the stack. */
87
121
  private watcher;
88
122
  /** The messages that are showing, in order. */
@@ -4,13 +4,37 @@ 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, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
7
+ import { customElement, deepActiveElement, deepContains, FocusScopeController, fillTemplate, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { matchesHotkey, parseHotkey } from '../hotkey.js';
10
11
  let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
11
12
  constructor() {
12
13
  super(...arguments);
13
- this.label = 'Notifications';
14
+ this.hotkey = 'F8';
15
+ this.label = 'Notifications ({hotkey})';
16
+ this.scope = new FocusScopeController(this, {
17
+ contents: () => this.showing.flatMap((one) => {
18
+ const target = focusTarget(one);
19
+ return target ? [target] : [];
20
+ }),
21
+ surface: () => this.region,
22
+ });
23
+ this.handleHotkey = (event) => {
24
+ if (event.defaultPrevented || !matchesHotkey(event, parseHotkey(this.hotkey))) {
25
+ return;
26
+ }
27
+ if (this.scope.holdsFocus) {
28
+ event.preventDefault();
29
+ this.scope.leave();
30
+ return;
31
+ }
32
+ if (this.showing.length > 0) {
33
+ event.preventDefault();
34
+ this.scope.enter();
35
+ }
36
+ };
37
+ this.made = new WeakSet();
14
38
  this.handleFocusIn = (event) => {
15
39
  const from = event.relatedTarget;
16
40
  if (from instanceof HTMLElement && !deepContains(this, from)) {
@@ -57,11 +81,41 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
57
81
  }
58
82
  willUpdate(changed) {
59
83
  super.willUpdate(changed);
60
- hostAria(this.internals, { label: this.label, role: 'status' });
84
+ hostAria(this.internals, {
85
+ label: fillTemplate(this.label, { hotkey: this.hotkey }),
86
+ role: 'region',
87
+ });
61
88
  this.internals.ariaLive = 'polite';
62
89
  this.internals.ariaRelevant = 'additions';
63
90
  this.internals.ariaAtomic = 'false';
64
91
  }
92
+ add(message, options = {}) {
93
+ const tier = this.constructor.tier;
94
+ const item = document.createElement(`${tier}toast-item`);
95
+ item.textContent = message;
96
+ if (options.tone) {
97
+ item.setAttribute('tone', options.tone);
98
+ }
99
+ if (options.duration !== undefined) {
100
+ item.setAttribute('duration', String(options.duration));
101
+ }
102
+ if (options.dismissible ?? true) {
103
+ item.toggleAttribute('dismissible', true);
104
+ }
105
+ this.made.add(item);
106
+ this.append(item);
107
+ return item;
108
+ }
109
+ sweep() {
110
+ for (const one of [...this.children]) {
111
+ if (!(one instanceof HTMLElement) || !one.hidden || !this.made.has(one)) {
112
+ continue;
113
+ }
114
+ this.made.delete(one);
115
+ const running = typeof one.getAnimations === 'function' ? one.getAnimations({ subtree: true }) : [];
116
+ void Promise.allSettled(running.map((animation) => animation.finished)).then(() => one.remove());
117
+ }
118
+ }
65
119
  get showing() {
66
120
  return [...this.children].filter((one) => one instanceof HTMLElement && !one.hidden);
67
121
  }
@@ -129,8 +183,10 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
129
183
  super.connectedCallback();
130
184
  this.addEventListener('focusin', this.handleFocusIn);
131
185
  this.addEventListener('helix-dismiss', this.handleDismiss);
186
+ document.addEventListener('keydown', this.handleHotkey);
132
187
  this.watcher = new MutationObserver((records) => {
133
188
  this.place(records.flatMap((record) => [...record.addedNodes]));
189
+ this.sweep();
134
190
  });
135
191
  this.watcher.observe(this, {
136
192
  attributeFilter: ['hidden'],
@@ -146,6 +202,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
146
202
  super.disconnectedCallback();
147
203
  this.removeEventListener('focusin', this.handleFocusIn);
148
204
  this.removeEventListener('helix-dismiss', this.handleDismiss);
205
+ document.removeEventListener('keydown', this.handleHotkey);
149
206
  this.watcher?.disconnect();
150
207
  this.watcher = undefined;
151
208
  }
@@ -154,9 +211,12 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
154
211
  this.place();
155
212
  }
156
213
  render() {
157
- return html `<div part="region" popover="manual"><slot></slot></div>`;
214
+ return html `<div part="region" popover="manual" tabindex="-1"><slot></slot></div>`;
158
215
  }
159
216
  };
217
+ __decorate([
218
+ property()
219
+ ], HelixHeadlessToast.prototype, "hotkey", void 0);
160
220
  __decorate([
161
221
  property()
162
222
  ], HelixHeadlessToast.prototype, "label", void 0);
@@ -14,6 +14,17 @@ declare const HelixHeadlessToggleGroup_base: (new (...args: any[]) => import("@f
14
14
  * Measurement happens on the client, so the server renders the indicator hidden
15
15
  * and it fades in once measured.
16
16
  *
17
+ * `selection-mode="multiple"` makes the group a toolbar of buttons that each
18
+ * say whether they are pressed with `aria-pressed`, as React Aria's
19
+ * ToggleButtonGroup and Radix's ToggleGroup do. A press presses or releases
20
+ * one item, the arrow keys move focus without pressing, and `value` is the
21
+ * pressed values, comma separated, which `values` also gives as a list. The
22
+ * form receives one entry per pressed value. The indicator stays hidden, and
23
+ * each pressed item is marked with `:state(pressed)`.
24
+ *
25
+ * `orientation="vertical"` runs the items down a column, says so to the
26
+ * accessibility tree, and the up and down arrows move between them.
27
+ *
17
28
  * @since 0.1.0
18
29
  * @status stable
19
30
  * @aliases SegmentedControl, Segmented, Navigation, Switcher
@@ -98,6 +109,11 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
98
109
  * goes to the first item that can be chosen, as in `Radio.Group`.
99
110
  */
100
111
  private entry;
112
+ /** The item focus was last on, in a toolbar, which holds its tab stop. */
113
+ private lastFocused;
114
+ private readonly noteFocus;
115
+ /** Whether several items can be pressed at once. */
116
+ private get multiple();
101
117
  /**
102
118
  * Whether the group holds a tab stop of its own.
103
119
  *
@@ -110,6 +126,37 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
110
126
  * reason to set it.
111
127
  */
112
128
  focusable: boolean;
129
+ /**
130
+ * Where the group's label sits. `start` puts it on the track's line.
131
+ *
132
+ * Absent is above, which is what a field looks like and what almost every
133
+ * group wants. `start` is for a row of controls that are labeled rather than
134
+ * a form of fields: a toolbar reads as one line, and a label stacked over
135
+ * every group in it turns one row into two.
136
+ *
137
+ * **A placement rather than a slot, and that is the whole point of it.** A
138
+ * `start` slot would let a consumer put the word there, and would also let
139
+ * them put it there *instead of* setting `label`, which is the group's
140
+ * accessible name: the set would then be named for nobody using a screen
141
+ * reader while looking correct to everybody else. Worse, setting both draws
142
+ * it twice. One property moves the label the consumer already has to give,
143
+ * and cannot be used to remove it.
144
+ */
145
+ labelPlacement?: 'start';
146
+ /**
147
+ * The direction the items run. `vertical` puts them in a column, and the up
148
+ * and down arrows move between them.
149
+ *
150
+ * Optional, so the attribute is absent until a consumer writes it.
151
+ */
152
+ orientation?: 'horizontal' | 'vertical';
153
+ /**
154
+ * Whether one item is chosen, as a radio group, or several can be pressed,
155
+ * as a toolbar of buttons with `aria-pressed`.
156
+ *
157
+ * Optional, so the attribute is absent until a consumer writes it.
158
+ */
159
+ selectionMode?: 'multiple' | 'single';
113
160
  /**
114
161
  * Focus goes to the item that holds the stop, and to the item that would
115
162
  * hold it while a toolbar holds the stop instead, so a label press or a
@@ -132,6 +179,11 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
132
179
  protected firstUpdated(changed: PropertyValues): void;
133
180
  protected updated(changed: PropertyValues): void;
134
181
  protected willUpdate(changed: PropertyValues): void;
182
+ /**
183
+ * What the form receives: the value, or under `selection-mode="multiple"`
184
+ * one entry per pressed value, as a native `<select multiple>` sends.
185
+ */
186
+ private formValue;
135
187
  /**
136
188
  * The verdict on the answer `required` asks for.
137
189
  *
@@ -145,22 +197,12 @@ export declare class HelixHeadlessToggleGroup extends HelixHeadlessToggleGroup_b
145
197
  */
146
198
  private validate;
147
199
  /**
148
- * Where the group's label sits. `start` puts it on the track's line.
149
- *
150
- * Absent is above, which is what a field looks like and what almost every
151
- * group wants. `start` is for a row of controls that are labeled rather than
152
- * a form of fields: a toolbar reads as one line, and a label stacked over
153
- * every group in it turns one row into two.
154
- *
155
- * **A placement rather than a slot, and that is the whole point of it.** A
156
- * `start` slot would let a consumer put the word there, and would also let
157
- * them put it there *instead of* setting `label`, which is the group's
158
- * accessible name: the set would then be named for nobody using a screen
159
- * reader while looking correct to everybody else. Worse, setting both draws
160
- * it twice. One property moves the label the consumer already has to give,
161
- * and cannot be used to remove it.
200
+ * The pressed values as a list, under `selection-mode="multiple"`, in the
201
+ * order the items are written. Written, it presses exactly those items.
202
+ * Where one item is chosen, it is that one value, or none.
162
203
  */
163
- labelPlacement?: 'start';
204
+ get values(): string[];
205
+ set values(next: string[]);
164
206
  /**
165
207
  * The row the track sits in, so something can sit beside it.
166
208
  *