@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
@@ -11,10 +11,23 @@ let HelixHeadlessDescriptionListItem = class HelixHeadlessDescriptionListItem ex
11
11
  constructor() {
12
12
  super(...arguments);
13
13
  this.label = '';
14
+ this.handleSlotChange = () => {
15
+ this.requestUpdate();
16
+ };
17
+ }
18
+ get several() {
19
+ return this.knownChildren.some((child) => child.localName === 'dd');
20
+ }
21
+ firstUpdated(changed) {
22
+ super.firstUpdated(changed);
23
+ this.finishHydration();
14
24
  }
15
25
  render() {
16
- return html `<dt part="label"><slot name="label">${this.label}</slot></dt>
17
- <dd part="value"><slot></slot></dd>`;
26
+ const label = html `<dt part="label"><slot name="label">${this.label}</slot></dt>`;
27
+ return this.several
28
+ ? html `${label}<slot @slotchange=${this.handleSlotChange}></slot>`
29
+ : html `${label}
30
+ <dd part="value"><slot @slotchange=${this.handleSlotChange}></slot></dd>`;
18
31
  }
19
32
  };
20
33
  __decorate([
@@ -1,5 +1,5 @@
1
1
  import { HelixElement } from '@fusion.dev/helix-core';
2
- import { type TemplateResult } from 'lit';
2
+ import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  /**
4
4
  * @summary A list of labels and their values, such as a details panel.
5
5
  *
@@ -15,6 +15,11 @@ import { type TemplateResult } from 'lit';
15
15
  * matches a plain `<dl>` with the same content node for node, both with a
16
16
  * slotted label and with an item set to `display: contents`.
17
17
  *
18
+ * **A named list is a named group.** A `<dl>` takes no name in ARIA 1.2, so
19
+ * the list becomes a group around it when it has `label`, `aria-label` or
20
+ * `aria-labelledby`, and the name lands on the group. Unnamed, the host adds
21
+ * nothing to the tree.
22
+ *
18
23
  * @since 0.1.0
19
24
  * @status stable
20
25
  * @category data
@@ -42,6 +47,27 @@ export declare class HelixHeadlessDescriptionList extends HelixElement {
42
47
  * and React reports that as a hydration mismatch.
43
48
  */
44
49
  direction?: 'row';
50
+ /**
51
+ * The list's name, read by screen readers, such as "Server details". It
52
+ * makes the list a named group.
53
+ */
54
+ label: string;
55
+ /**
56
+ * Hears a name written on the element, which no property mirrors.
57
+ *
58
+ * Lit observes the attributes of its own properties only, and `ariaLabel`
59
+ * and `ariaLabelledByElements` belong to the platform.
60
+ */
61
+ static get observedAttributes(): string[];
62
+ /**
63
+ * Called by the browser when an observed attribute changes. A name written
64
+ * or taken off asks for an update, because it decides whether the list is a
65
+ * group.
66
+ */
67
+ attributeChangedCallback(name: string, old: string | null, value: string | null): void;
68
+ /** Whether anything names the list. */
69
+ private get named();
70
+ protected willUpdate(changed: PropertyValues): void;
45
71
  protected render(): TemplateResult;
46
72
  }
47
73
  declare global {
@@ -4,10 +4,32 @@ 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 } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  let HelixHeadlessDescriptionList = class HelixHeadlessDescriptionList extends HelixElement {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.label = '';
14
+ }
15
+ static get observedAttributes() {
16
+ return [...super.observedAttributes, 'aria-label', 'aria-labelledby'];
17
+ }
18
+ attributeChangedCallback(name, old, value) {
19
+ super.attributeChangedCallback(name, old, value);
20
+ if (name === 'aria-label' || name === 'aria-labelledby') {
21
+ this.requestUpdate();
22
+ }
23
+ }
24
+ get named() {
25
+ return (this.label !== '' ||
26
+ Boolean(this.getAttribute?.('aria-label')) ||
27
+ Boolean(this.getAttribute?.('aria-labelledby')));
28
+ }
29
+ willUpdate(changed) {
30
+ super.willUpdate(changed);
31
+ hostAria(this.internals, { label: this.label, role: this.named ? 'group' : '' });
32
+ }
11
33
  render() {
12
34
  return html `<dl part="list"><slot></slot></dl>`;
13
35
  }
@@ -15,6 +37,9 @@ let HelixHeadlessDescriptionList = class HelixHeadlessDescriptionList extends He
15
37
  __decorate([
16
38
  property({ reflect: true })
17
39
  ], HelixHeadlessDescriptionList.prototype, "direction", void 0);
40
+ __decorate([
41
+ property()
42
+ ], HelixHeadlessDescriptionList.prototype, "label", void 0);
18
43
  HelixHeadlessDescriptionList = __decorate([
19
44
  customElement('helix-headless-description-list')
20
45
  ], HelixHeadlessDescriptionList);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The elements at the start of a slot that hold words and no control, up to the
3
+ * first one that is or holds a control.
4
+ *
5
+ * What a dialog is described by. A question above a form describes the dialog,
6
+ * and the form does not: a description that read out every field label would
7
+ * repeat what a reader hears again as they reach each field.
8
+ */
9
+ export declare const wordsIn: (slot: HTMLSlotElement | null) => Element[];
@@ -0,0 +1,14 @@
1
+ const CONTROL = 'a[href], audio[controls], button, details, form, iframe, input, select, textarea, video[controls], [contenteditable], [tabindex]';
2
+ const isControl = (element) => element.localName.includes('-') || element.matches(CONTROL);
3
+ export const wordsIn = (slot) => {
4
+ const words = [];
5
+ for (const one of slot?.assignedElements({ flatten: true }) ?? []) {
6
+ if (isControl(one) || [...one.querySelectorAll('*')].some(isControl)) {
7
+ break;
8
+ }
9
+ if ((one.textContent ?? '').trim() !== '') {
10
+ words.push(one);
11
+ }
12
+ }
13
+ return words;
14
+ };
@@ -1,4 +1,4 @@
1
- import { AriaForwardController, CommandController, HelixElement } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, CommandController, HelixElement, OpenPhaseController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
@@ -23,6 +23,16 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
23
23
  * the `header` slot, or the elements an `aria-labelledby` on the host names.
24
24
  * While it is open, the page behind it does not scroll.
25
25
  *
26
+ * The dialog is described by the words at the start of its body: the elements
27
+ * in the default slot before the first one that is or holds a control. A
28
+ * question above a form describes the dialog, and the form does not. An
29
+ * `aria-describedby` on the host replaces it.
30
+ *
31
+ * Set `alert` for a dialog that interrupts to ask for an answer, such as a
32
+ * confirmation before a deletion. It is an `alertdialog`, which a screen reader
33
+ * announces with its description as it opens. Set `dismissible` to draw a
34
+ * close control, labeled by `dismiss-label`.
35
+ *
26
36
  * @since 0.1.0
27
37
  * @status stable
28
38
  * @category overlays
@@ -30,6 +40,7 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
30
40
  * @documentation https://fusion.dev/helix/components/dialog
31
41
  *
32
42
  * @slot - The dialog's content.
43
+ * @slot dismiss-icon - Replaces the glyph inside the close control.
33
44
  * @slot footer - The dialog's actions.
34
45
  * @slot header - The title, and anything beside it.
35
46
  * @slot icon - An icon above the title, for a warning dialog.
@@ -39,11 +50,30 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
39
50
  * @event {HelixBeforeOpenEvent} helix-before-open - Fired before it opens, and cancelable.
40
51
  * @event {ToggleEvent} toggle - Sent when the dialog opens or closes, with `newState` and `oldState`.
41
52
  *
53
+ * @csspart body - The slot the content is in. It draws no box until you give it one.
42
54
  * @csspart dialog - The native dialog element.
55
+ * @csspart dismiss - The close control, drawn when the dialog is `dismissible`.
56
+ * @csspart dismiss-mark - The glyph on the close control, where none is slotted.
57
+ * @csspart footer - The slot the actions are in. It draws no box until you give it one.
58
+ * @csspart header - The slot the title is in. It draws no box until you give it one.
43
59
  *
60
+ * @cssstate entering - From the moment the dialog opens until its entrance has finished.
61
+ * @cssstate exiting - From the moment the dialog closes until its exit has finished.
44
62
  * @cssstate open - While the dialog is open.
45
63
  */
46
64
  export declare class HelixHeadlessDialog extends HelixHeadlessDialog_base {
65
+ /**
66
+ * Makes the dialog an alert dialog, for a message that interrupts to ask for
67
+ * an answer, such as a confirmation before something is deleted.
68
+ *
69
+ * The `<dialog>` takes `role="alertdialog"`, so a screen reader announces the
70
+ * dialog and its description as it opens. Everything else stays the same:
71
+ * the dialog is modal, Escape asks to close it, and `persistent` still
72
+ * refuses that.
73
+ *
74
+ * Not reflected, because no stylesheet selects on it.
75
+ */
76
+ alert: boolean;
47
77
  /**
48
78
  * Which close requests the browser handles on its own.
49
79
  *
@@ -57,11 +87,24 @@ export declare class HelixHeadlessDialog extends HelixHeadlessDialog_base {
57
87
  * that a resting value is an attribute's absence.
58
88
  */
59
89
  closedBy?: 'any' | 'closerequest' | 'none';
90
+ /**
91
+ * Draws a control that closes the dialog, in the corner where the title is.
92
+ *
93
+ * Pressing it is `close()`, so it sends `helix-before-close` like every other
94
+ * way out, and `persistent` does not disable it.
95
+ */
96
+ dismissible: boolean;
97
+ /**
98
+ * The close control's accessible name. Translate it with the rest of your
99
+ * interface.
100
+ */
101
+ dismissLabel: string;
60
102
  /**
61
103
  * Accessible name for the dialog. When it is empty, the heading in the
62
104
  * `header` slot names the dialog.
63
105
  */
64
106
  label: string;
107
+ protected readonly phases: OpenPhaseController;
65
108
  protected readonly aria: AriaForwardController;
66
109
  protected readonly commands: CommandController;
67
110
  /**
@@ -147,6 +190,19 @@ export declare class HelixHeadlessDialog extends HelixHeadlessDialog_base {
147
190
  * either. A browser without element reflection keeps the fallback name.
148
191
  */
149
192
  private nameByHeader;
193
+ /** Whether the body's words are what currently describe the dialog. */
194
+ private describedByBody;
195
+ /**
196
+ * Describes the dialog by the words at the start of its body, where nothing
197
+ * else describes it.
198
+ *
199
+ * An element reference, for the reason `nameByHeader` gives. Only the leading
200
+ * run of elements that hold no control, so a dialog asking a question above a
201
+ * form is described by the question: a description that read out every field
202
+ * label would repeat what a reader hears again as they reach each field. An
203
+ * `aria-describedby` on the host comes first.
204
+ */
205
+ private describeByBody;
150
206
  protected willUpdate(changed: PropertyValues): void;
151
207
  connectedCallback(): void;
152
208
  disconnectedCallback(): void;
@@ -203,6 +259,13 @@ export declare class HelixHeadlessDialog extends HelixHeadlessDialog_base {
203
259
  private refuse;
204
260
  /** Bounds the refusal listener to one, whether or not it ever fires. */
205
261
  private refusal;
262
+ /**
263
+ * The glyph on the close control, behind a seam.
264
+ *
265
+ * Slot fallback, so a consumer replaces it by slotting, and a method, so a
266
+ * tier above replaces it by overriding. The same pair `Toast.Item` draws.
267
+ */
268
+ protected renderDismissIcon(): TemplateResult;
206
269
  protected render(): TemplateResult;
207
270
  }
208
271
  declare global {
@@ -4,13 +4,25 @@ 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, CommandController, customElement, HelixElement, hostAria, lockScroll, MixinControllerOpen, unlockScroll, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, CommandController, customElement, drawDismiss, drawDismissGlyph, HelixElement, headingsIn, hostAria, lockScroll, MixinControllerOpen, OpenPhaseController, reflectElements, unlockScroll, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { wordsIn } from '../description.js';
10
11
  let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(HelixElement) {
11
12
  constructor() {
12
13
  super(...arguments);
14
+ this.alert = false;
15
+ this.dismissible = false;
16
+ this.dismissLabel = 'Close';
13
17
  this.label = '';
18
+ this.phases = new OpenPhaseController(this, {
19
+ mark: {
20
+ entering: (on) => this.toggleState('entering', on),
21
+ exiting: (on) => this.toggleState('exiting', on),
22
+ },
23
+ open: () => this.open,
24
+ surface: () => this.dialog,
25
+ });
14
26
  this.aria = new AriaForwardController(this, { target: () => this.dialog });
15
27
  this.commands = new CommandController(this, {
16
28
  commands: {
@@ -48,6 +60,7 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
48
60
  this.close(submitter?.hasAttribute('value') ? submitter.value : undefined);
49
61
  };
50
62
  this.namedByHeader = false;
63
+ this.describedByBody = false;
51
64
  this.handleBackdrop = (event) => {
52
65
  const panel = this.dialog;
53
66
  if (!panel || event.target !== panel) {
@@ -93,20 +106,16 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
93
106
  }
94
107
  }
95
108
  nameByHeader() {
96
- const dialog = this.dialog;
97
- if (!dialog || !('ariaLabelledByElements' in dialog)) {
98
- return;
99
- }
100
109
  const slot = this.renderRoot.querySelector('slot[name="header"]');
101
- const heading = this.label || this.hasAttribute('aria-labelledby') ? [] : headingsIn(slot);
102
- if (heading.length > 0) {
103
- dialog.ariaLabelledByElements = heading;
104
- this.namedByHeader = true;
105
- }
106
- else if (this.namedByHeader) {
107
- dialog.ariaLabelledByElements = null;
108
- this.namedByHeader = false;
109
- }
110
+ const heading = this.label || this.hasAttribute('aria-labelledby')
111
+ ? []
112
+ : headingsIn(slot?.assignedElements({ flatten: true }) ?? []);
113
+ this.namedByHeader = reflectElements(this.dialog, 'ariaLabelledByElements', heading, this.namedByHeader);
114
+ }
115
+ describeByBody() {
116
+ const slot = this.renderRoot.querySelector('slot:not([name])');
117
+ const words = this.hasAttribute('aria-describedby') ? [] : wordsIn(slot);
118
+ this.describedByBody = reflectElements(this.dialog, 'ariaDescribedByElements', words, this.describedByBody);
110
119
  }
111
120
  willUpdate(changed) {
112
121
  super.willUpdate(changed);
@@ -124,6 +133,7 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
124
133
  updated(changed) {
125
134
  super.updated(changed);
126
135
  this.nameByHeader();
136
+ this.describeByBody();
127
137
  if (this.open) {
128
138
  lockScroll(this);
129
139
  }
@@ -169,9 +179,15 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
169
179
  signal: this.refusal.signal,
170
180
  });
171
181
  }
182
+ renderDismissIcon() {
183
+ return html `<slot name="dismiss-icon">
184
+ ${drawDismissGlyph()}
185
+ </slot>`;
186
+ }
172
187
  render() {
173
188
  return html `<dialog
174
189
  part="dialog"
190
+ role=${this.alert ? 'alertdialog' : nothing}
175
191
  closedby=${this.closedBy ?? nothing}
176
192
  aria-label=${this.label || 'Dialog'}
177
193
  @cancel=${this.handleCancel}
@@ -179,15 +195,31 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
179
195
  @close=${this.handleClose}
180
196
  >
181
197
  <slot name="icon"></slot>
182
- <slot name="header" @slotchange=${this.nameByHeader}></slot>
183
- <slot></slot>
184
- <slot name="footer"></slot>
198
+ <slot name="header" part="header" @slotchange=${this.nameByHeader}></slot>
199
+ <slot part="body" @slotchange=${this.describeByBody}></slot>
200
+ <slot name="footer" part="footer"></slot>
201
+ ${this.dismissible
202
+ ? drawDismiss({
203
+ label: this.dismissLabel,
204
+ mark: this.renderDismissIcon(),
205
+ onDismiss: () => this.close(),
206
+ })
207
+ : nothing}
185
208
  </dialog>`;
186
209
  }
187
210
  };
211
+ __decorate([
212
+ property({ type: Boolean })
213
+ ], HelixHeadlessDialog.prototype, "alert", void 0);
188
214
  __decorate([
189
215
  property({ attribute: 'closedby', reflect: true })
190
216
  ], HelixHeadlessDialog.prototype, "closedBy", void 0);
217
+ __decorate([
218
+ property({ reflect: true, type: Boolean })
219
+ ], HelixHeadlessDialog.prototype, "dismissible", void 0);
220
+ __decorate([
221
+ property({ attribute: 'dismiss-label' })
222
+ ], HelixHeadlessDialog.prototype, "dismissLabel", void 0);
191
223
  __decorate([
192
224
  property()
193
225
  ], HelixHeadlessDialog.prototype, "label", void 0);
@@ -198,9 +230,3 @@ HelixHeadlessDialog = __decorate([
198
230
  customElement('helix-headless-dialog')
199
231
  ], HelixHeadlessDialog);
200
232
  export { HelixHeadlessDialog };
201
- const headingsIn = (slot) => {
202
- const assigned = slot?.assignedElements({ flatten: true }) ?? [];
203
- const heading = 'h1, h2, h3, h4, h5, h6, [role="heading"]';
204
- const found = assigned.flatMap((one) => one.matches(heading) ? [one] : [...one.querySelectorAll(heading)].slice(0, 1));
205
- return found.length > 0 ? found.slice(0, 1) : assigned;
206
- };
@@ -24,9 +24,15 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
24
24
  * **Negative values are skipped.** An arc cannot show a negative number, so
25
25
  * those rows are left out and the total is the sum of the remaining rows.
26
26
  *
27
- * The ring is `aria-hidden`. The `summary` part names the chart, from `label`
28
- * or the table's caption, and gives each slice's share, and the table beside
29
- * the chart has every amount.
27
+ * The ring is hidden from screen readers. The `summary` part names the chart,
28
+ * from `label` or the table's caption, and gives each slice's share, and the
29
+ * table beside the chart has every amount.
30
+ *
31
+ * **The ring is read by key.** The plot takes focus, named by `label` or the
32
+ * caption. Every arrow moves from slice to slice, the right and down arrows to
33
+ * the next, and Home and End go to the first and the last. The tooltip
34
+ * follows, the `live` part says the slice in words, and Escape puts the
35
+ * tooltip away.
30
36
  *
31
37
  * @since 0.1.0
32
38
  * @status stable
@@ -37,8 +43,9 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
37
43
  * @slot - Content in the middle of the ring, usually a total. It is read by screen readers, while the ring itself is hidden from them.
38
44
  *
39
45
  * @csspart center - The middle of the ring, holding whatever is slotted.
46
+ * @csspart live - The readout: a polite live region that says the slice the keys moved to. Hide it visually.
40
47
  * @csspart mark - The invisible point the tooltip is anchored to.
41
- * @csspart plot - The drawing.
48
+ * @csspart plot - The drawing, which takes focus to be read by key.
42
49
  * @csspart segment - One slice.
43
50
  * @csspart segment-active - The slice under the pointer. Set alongside `segment`.
44
51
  * @csspart segment-edge - One slice as a closed shape, used to draw its outline.
@@ -52,6 +59,7 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
52
59
  * @csspart tooltip-arrow-top - The point while the bubble is above the reading, on its bottom edge. Set alongside `tooltip-arrow`.
53
60
  * @csspart tooltip-bottom - The bubble while it is below the reading. Set alongside `tooltip`.
54
61
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
62
+ * @csspart tooltip-cell-current - The cell the series keys rest on, in the charts whose readings hold several series. A ring draws one, so it is never set here.
55
63
  * @csspart tooltip-label - The slice's own name inside the tooltip.
56
64
  * @csspart tooltip-left - The bubble while it is left of the reading. Set alongside `tooltip`.
57
65
  * @csspart tooltip-name - A column's name inside the tooltip.
@@ -154,6 +162,19 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
154
162
  * the table's rows named the row before the one under the pointer.
155
163
  */
156
164
  private get shares();
165
+ /**
166
+ * The palette slot for a cell, which a ring gives its first plotted column
167
+ * alone: it draws that column and no other, so a second numeric column is
168
+ * no series the keys could move to.
169
+ */
170
+ seriesOf(cell: number): number | undefined;
171
+ /**
172
+ * The number of slices, which the keys walk.
173
+ *
174
+ * The mixin counts the table's rows, and a row with no amount draws no
175
+ * slice, so a key stepping by rows would land on a slice that is not there.
176
+ */
177
+ get readings(): number;
157
178
  protected render(): TemplateResult;
158
179
  /**
159
180
  * What a reader who cannot see the ring is told: the chart's name and each
@@ -49,7 +49,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
49
49
  get shares() {
50
50
  const series = this.series;
51
51
  const points = series[0]?.points ?? [];
52
- const values = points.map((point) => Number.isFinite(point.value) && point.value > 0 ? point.value : 0);
52
+ const values = points.map((point) => Number.isFinite(point.value) && point.value > 0 && this.showsSeries(point.label)
53
+ ? point.value
54
+ : 0);
53
55
  const total = values.reduce((sum, one) => sum + one, 0);
54
56
  if (total === 0) {
55
57
  return [];
@@ -62,21 +64,34 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
62
64
  return { fraction, row: points[index]?.at ?? index, start: at };
63
65
  });
64
66
  }
67
+ seriesOf(cell) {
68
+ return cell === this.plottedColumns[0] ? seriesIndex(0) : undefined;
69
+ }
70
+ get readings() {
71
+ return this.shares.length;
72
+ }
65
73
  render() {
66
74
  const shares = this.shares;
67
75
  return html `${this.renderPlot(shares)}${shares.length === 0 ? nothing : this.renderSummary(shares)}`;
68
76
  }
69
77
  renderSummary(shares) {
70
78
  const rows = this.sourceRows;
71
- const parts = shares.map((share) => `${rows[share.row]?.label ?? ''} ${percentIn(this.locale).format(share.fraction)}`);
79
+ const parts = shares
80
+ .filter((share) => this.showsSeries(rows[share.row]?.label ?? ''))
81
+ .map((share) => `${rows[share.row]?.label ?? ''} ${percentIn(this.locale).format(share.fraction)}`);
72
82
  const named = this.named ? `${this.named}: ` : '';
73
- return html `<p part="summary">${named}${parts.join(', ')}.</p>`;
83
+ return html `<p id="helix-chart-summary" part="summary">${named}${parts.join(', ')}.</p>`;
74
84
  }
75
85
  renderPlot(shares) {
76
86
  return html `<div
87
+ aria-describedby=${this.named ? `helix-chart-summary${this.hole === 'none' ? '' : ' helix-chart-center'}` : nothing}
88
+ aria-label=${this.named || nothing}
89
+ aria-labelledby=${this.named ? nothing : 'helix-chart-summary'}
77
90
  id=${CHART_PLOT}
78
91
  part="plot"
92
+ role="application"
79
93
  style="--donut-chart-stroke: ${this.thickness}"
94
+ tabindex="0"
80
95
  >
81
96
  <svg
82
97
  aria-hidden="true"
@@ -95,7 +110,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
95
110
  />
96
111
  ${shares.map((share, index) => this.renderSegment(share, index))}
97
112
  </svg>
98
- ${this.hole === 'none' ? nothing : html `<div part="center"><slot></slot></div>`}
113
+ ${this.hole === 'none' ? nothing : html `<div id="helix-chart-center" part="center"><slot></slot></div>`}
99
114
  ${this.renderTooltip()}
100
115
  </div>`;
101
116
  }
@@ -163,7 +178,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
163
178
  const at = this.pointer.at;
164
179
  const share = this.shares[at];
165
180
  if (!share) {
166
- return drawTooltip(this.sourceRows, at, this.tag('tooltip'));
181
+ return drawTooltip(this.sourceRows, -1, this.tag('tooltip'), undefined, undefined, this.pointer);
167
182
  }
168
183
  const angle = (share.start + share.fraction / 2) * 2 * Math.PI * this.span + this.origin;
169
184
  const edge = EDGE;
@@ -184,7 +199,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
184
199
  : 'top',
185
200
  x: `${x}%`,
186
201
  y: `${y}%`,
187
- }, () => seriesIndex(at));
202
+ }, () => seriesIndex(at), this.pointer);
188
203
  }
189
204
  };
190
205
  __decorate([
@@ -1,4 +1,4 @@
1
- import { AriaForwardController, CommandController, HelixElement } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, CommandController, HelixElement, OpenPhaseController, SwipeController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
@@ -17,7 +17,15 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
17
17
  * - the page behind does not scroll
18
18
  *
19
19
  * A drawer with `modal="false"` leaves the page usable and still closes on
20
- * Escape.
20
+ * Escape, in a browser without `closedby` as well.
21
+ *
22
+ * **A touch or a pen swipes it away**, toward the edge it came from, resolved
23
+ * against the writing direction. A swipe past halfway, or a quick one, closes
24
+ * it through the same request as every other way out. `snap-points` lists the
25
+ * fractions of the panel a reader can leave on screen, such as `0.5 1` for a
26
+ * sheet that rests half open: it opens at the smallest, and a swipe settles at
27
+ * the nearest. While a swipe moves the panel, the distance is written on it as
28
+ * `--drawer-swipe-x` and `--drawer-swipe-y`. `swipe="false"` turns swiping off.
21
29
  *
22
30
  * The panel's name is `label` when you set it. Otherwise it is the heading in
23
31
  * the `header` slot, or the elements an `aria-labelledby` on the host names.
@@ -43,6 +51,7 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
43
51
  * @documentation https://fusion.dev/helix/components/drawer
44
52
  *
45
53
  * @slot - The drawer's content.
54
+ * @slot footer - Content pinned below the scrolling area, such as the drawer's actions.
46
55
  * @slot header - Content pinned above the scrolling area.
47
56
  *
48
57
  * @event {Event} close - Sent from the host after the drawer closes, because the native `close` event does not leave the shadow root.
@@ -51,9 +60,15 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
51
60
  * @event {ToggleEvent} toggle - Sent when the drawer opens or closes, with `newState` and `oldState`.
52
61
  *
53
62
  * @csspart content - The scrolling content region.
63
+ * @csspart footer - The footer region.
54
64
  * @csspart header - The header region.
55
65
  * @csspart panel - The sliding panel.
56
66
  *
67
+ * @cssproperty --drawer-swipe-x - How far a swipe, or a snap point, has moved the panel across, in pixels, toward the right.
68
+ * @cssproperty --drawer-swipe-y - How far a swipe, or a snap point, has moved the panel down, in pixels.
69
+ *
70
+ * @cssstate entering - From the moment the drawer opens until its entrance has finished.
71
+ * @cssstate exiting - From the moment the drawer closes until its exit has finished.
57
72
  * @cssstate open - While the drawer is open.
58
73
  */
59
74
  export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
@@ -100,6 +115,21 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
100
115
  * guarantees is the absence, and a sheet selects on it.
101
116
  */
102
117
  placement?: 'start' | 'end' | 'top' | 'bottom';
118
+ /**
119
+ * The fractions of the panel a reader can leave on screen, as a list such as
120
+ * `0.5 1`. The drawer opens at the smallest, and a swipe comes to rest at the
121
+ * nearest, or closes the drawer below the smallest.
122
+ *
123
+ * Empty is `1`: the whole panel, and a swipe either closes it or puts it
124
+ * back.
125
+ */
126
+ snapPoints: string;
127
+ /**
128
+ * Whether a touch or a pen can swipe the drawer away. `swipe="false"` turns
129
+ * it off, for a panel whose content has its own use for the gesture, such as
130
+ * a map.
131
+ */
132
+ swipe: boolean;
103
133
  /**
104
134
  * What the dialog closed with, the way `<dialog>` reports it.
105
135
  *
@@ -120,6 +150,37 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
120
150
  set returnValue(value: string);
121
151
  /** What a value set before the element existed is kept in. */
122
152
  private returned;
153
+ protected readonly phases: OpenPhaseController;
154
+ /** How far the panel rests toward its edge, in pixels, at the snap point it settled on. */
155
+ private rest;
156
+ /** The edge the panel leaves through, from its placement and the writing direction. */
157
+ private get edge();
158
+ /** The panel's size along the swipe, in pixels. */
159
+ private get extent();
160
+ protected readonly swipes: SwipeController;
161
+ /**
162
+ * Writes how far the panel sits toward its edge, as the two properties the
163
+ * styled tier translates it by. Nothing is written at rest.
164
+ */
165
+ private place;
166
+ /** Brings a released swipe to rest: at a snap point, or closed through the request. */
167
+ private settle;
168
+ /** Opens the drawer. */
169
+ show(): void;
170
+ /**
171
+ * Requests that the drawer close, and takes what it closed with, the way
172
+ * `Dialog.close(value)` does. A `helix-before-close` listener can refuse it,
173
+ * and then the value is not kept.
174
+ */
175
+ close(returnValue?: string): void;
176
+ /**
177
+ * Escape on a drawer that is not modal, in a browser without `closedby`.
178
+ *
179
+ * `show()` gives a `<dialog>` no close watcher, and `closedby="closerequest"`
180
+ * is what asks for one. Where the browser does not know the attribute, the
181
+ * key is read here, and comes through the same request.
182
+ */
183
+ private readonly handleKeydown;
123
184
  /** The panel, which is a real `<dialog>`. */
124
185
  private get panel();
125
186
  /**