@fusion.dev/helix-headless 0.144.0 → 0.146.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 (319) hide show
  1. package/custom-elements.json +15195 -4240
  2. package/dist/accordion/item/accordion-item.d.ts +62 -12
  3. package/dist/accordion/item/accordion-item.js +41 -10
  4. package/dist/accordion/root/accordion-root.d.ts +14 -5
  5. package/dist/accordion/root/accordion-root.js +7 -1
  6. package/dist/announcement/root/announcement-root.d.ts +24 -3
  7. package/dist/announcement/root/announcement-root.js +39 -2
  8. package/dist/app-header/root/app-header-root.d.ts +12 -0
  9. package/dist/app-header/root/app-header-root.js +13 -1
  10. package/dist/app-header/sectioning.d.ts +9 -0
  11. package/dist/app-header/sectioning.js +27 -0
  12. package/dist/avatar/group/avatar-group.d.ts +20 -14
  13. package/dist/avatar/group/avatar-group.js +17 -19
  14. package/dist/badge/root/badge-root.d.ts +3 -1
  15. package/dist/badge/root/badge-root.js +2 -2
  16. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  17. package/dist/bar-chart/root/bar-chart-root.js +52 -15
  18. package/dist/bar-chart/stack.d.ts +15 -0
  19. package/dist/bar-chart/stack.js +19 -0
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +57 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +73 -3
  22. package/dist/button/root/button-root.d.ts +26 -0
  23. package/dist/button/root/button-root.js +38 -18
  24. package/dist/button-group/root/button-group-root.d.ts +2 -1
  25. package/dist/button-group/root/button-group-root.js +5 -1
  26. package/dist/canvas/node/canvas-node.d.ts +4 -3
  27. package/dist/canvas/node/canvas-node.js +3 -2
  28. package/dist/canvas/root/canvas-root.d.ts +38 -3
  29. package/dist/canvas/root/canvas-root.js +123 -42
  30. package/dist/card/root/card-root.d.ts +24 -3
  31. package/dist/card/root/card-root.js +20 -8
  32. package/dist/carousel/root/carousel-root.d.ts +133 -4
  33. package/dist/carousel/root/carousel-root.js +174 -24
  34. package/dist/carousel/stops.d.ts +20 -0
  35. package/dist/carousel/stops.js +30 -0
  36. package/dist/chat/composer/chat-composer.d.ts +38 -6
  37. package/dist/chat/composer/chat-composer.js +42 -9
  38. package/dist/chat/message/chat-message.d.ts +32 -1
  39. package/dist/chat/message/chat-message.js +27 -10
  40. package/dist/chat/naming.d.ts +26 -0
  41. package/dist/chat/naming.js +14 -0
  42. package/dist/chat/root/chat-root.d.ts +58 -0
  43. package/dist/chat/root/chat-root.js +43 -3
  44. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  45. package/dist/checkbox/root/checkbox-root.js +14 -1
  46. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  47. package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
  48. package/dist/checkbox-group/select-all.d.ts +27 -0
  49. package/dist/checkbox-group/select-all.js +12 -0
  50. package/dist/code-block/highlight.d.ts +15 -0
  51. package/dist/code-block/highlight.js +4 -0
  52. package/dist/code-block/root/code-block-root.d.ts +57 -2
  53. package/dist/code-block/root/code-block-root.js +63 -8
  54. package/dist/color-input/root/color-input-root.d.ts +3 -0
  55. package/dist/color-input/root/color-input-root.js +6 -3
  56. package/dist/color-picker/root/color-picker-root.d.ts +33 -4
  57. package/dist/color-picker/root/color-picker-root.js +80 -21
  58. package/dist/color-picker/swatches.d.ts +12 -0
  59. package/dist/color-picker/swatches.js +26 -0
  60. package/dist/combobox/root/combobox-root.d.ts +43 -0
  61. package/dist/combobox/root/combobox-root.js +79 -15
  62. package/dist/command/root/command-root.d.ts +16 -1
  63. package/dist/command/root/command-root.js +22 -4
  64. package/dist/copy-button/root/copy-button-root.d.ts +26 -1
  65. package/dist/copy-button/root/copy-button-root.js +12 -5
  66. package/dist/data-table/index.d.ts +1 -1
  67. package/dist/data-table/index.js +1 -1
  68. package/dist/data-table/keys.d.ts +24 -0
  69. package/dist/data-table/keys.js +24 -0
  70. package/dist/data-table/root/data-table-root.d.ts +170 -13
  71. package/dist/data-table/root/data-table-root.js +294 -52
  72. package/dist/data-table/tree.d.ts +55 -0
  73. package/dist/data-table/tree.js +54 -0
  74. package/dist/date-input/root/date-input-root.d.ts +3 -1
  75. package/dist/date-input/root/date-input-root.js +18 -7
  76. package/dist/date-picker/root/date-picker-root.js +12 -6
  77. package/dist/description-list/item/description-list-item.d.ts +17 -2
  78. package/dist/description-list/item/description-list-item.js +15 -2
  79. package/dist/description-list/root/description-list-root.d.ts +27 -1
  80. package/dist/description-list/root/description-list-root.js +26 -1
  81. package/dist/dialog/description.js +15 -1
  82. package/dist/dialog/root/dialog-root.d.ts +8 -2
  83. package/dist/dialog/root/dialog-root.js +16 -1
  84. package/dist/divider/root/divider-root.d.ts +3 -0
  85. package/dist/divider/root/divider-root.js +2 -1
  86. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  87. package/dist/donut-chart/root/donut-chart-root.js +48 -1
  88. package/dist/drawer/reveal.d.ts +8 -0
  89. package/dist/drawer/reveal.js +1 -0
  90. package/dist/drawer/root/drawer-root.d.ts +59 -0
  91. package/dist/drawer/root/drawer-root.js +63 -4
  92. package/dist/drilldown/item/drilldown-item.d.ts +11 -6
  93. package/dist/drilldown/item/drilldown-item.js +8 -5
  94. package/dist/drilldown/root/drilldown-root.d.ts +29 -0
  95. package/dist/drilldown/root/drilldown-root.js +28 -5
  96. package/dist/element-events.generated.js +83 -12
  97. package/dist/empty/root/empty-root.d.ts +3 -1
  98. package/dist/empty/root/empty-root.js +3 -2
  99. package/dist/file-input/root/file-input-root.d.ts +69 -6
  100. package/dist/file-input/root/file-input-root.js +82 -19
  101. package/dist/file-input/screen.d.ts +2 -1
  102. package/dist/filter-input/menu/filter-menu.d.ts +5 -0
  103. package/dist/filter-input/menu/filter-menu.js +16 -4
  104. package/dist/filter-input/root/filter-input-root.d.ts +30 -6
  105. package/dist/filter-input/root/filter-input-root.js +1 -1
  106. package/dist/filter-input/suggest.d.ts +28 -3
  107. package/dist/filter-input/suggest.js +18 -8
  108. package/dist/format-date/root/format-date-root.d.ts +9 -16
  109. package/dist/format-date/root/format-date-root.js +10 -27
  110. package/dist/heatmap/root/heatmap-root.d.ts +24 -13
  111. package/dist/heatmap/root/heatmap-root.js +34 -12
  112. package/dist/icon/root/icon-root.d.ts +12 -1
  113. package/dist/icon/root/icon-root.js +21 -10
  114. package/dist/icon/settle.d.ts +7 -0
  115. package/dist/icon/settle.js +10 -0
  116. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  117. package/dist/image/root/image-root.d.ts +5 -1
  118. package/dist/image/root/image-root.js +10 -2
  119. package/dist/input/root/input-root.d.ts +13 -3
  120. package/dist/input/root/input-root.js +12 -3
  121. package/dist/kbd/root/kbd-root.d.ts +35 -1
  122. package/dist/kbd/root/kbd-root.js +23 -4
  123. package/dist/legend/root/legend-root.d.ts +55 -8
  124. package/dist/legend/root/legend-root.js +55 -13
  125. package/dist/lightbox/root/lightbox-root.d.ts +49 -6
  126. package/dist/lightbox/root/lightbox-root.js +86 -19
  127. package/dist/lightbox/zoom-controller.d.ts +59 -0
  128. package/dist/lightbox/zoom-controller.js +128 -0
  129. package/dist/lightbox/zoom.d.ts +22 -0
  130. package/dist/lightbox/zoom.js +16 -0
  131. package/dist/line-chart/root/line-chart-root.d.ts +22 -1
  132. package/dist/line-chart/root/line-chart-root.js +21 -1
  133. package/dist/list/item/list-item.d.ts +70 -1
  134. package/dist/list/item/list-item.js +77 -6
  135. package/dist/list/numbering.d.ts +14 -0
  136. package/dist/list/numbering.js +8 -0
  137. package/dist/list/root/list-root.d.ts +155 -9
  138. package/dist/list/root/list-root.js +246 -4
  139. package/dist/list/selection.d.ts +49 -0
  140. package/dist/list/selection.js +30 -0
  141. package/dist/listbox/root/listbox-root.d.ts +37 -1
  142. package/dist/listbox/root/listbox-root.js +49 -4
  143. package/dist/loader/busy.d.ts +10 -0
  144. package/dist/loader/busy.js +11 -0
  145. package/dist/loader/root/loader-root.d.ts +9 -2
  146. package/dist/loader/root/loader-root.js +23 -3
  147. package/dist/map/root/map-root.d.ts +6 -2
  148. package/dist/map/root/map-root.js +5 -2
  149. package/dist/megamenu/root/megamenu-root.d.ts +62 -0
  150. package/dist/megamenu/root/megamenu-root.js +90 -5
  151. package/dist/menu/index.d.ts +1 -0
  152. package/dist/menu/index.js +1 -0
  153. package/dist/menu/item/menu-item.d.ts +87 -11
  154. package/dist/menu/item/menu-item.js +78 -22
  155. package/dist/menu/root/menu-root.d.ts +39 -1
  156. package/dist/menu/root/menu-root.js +65 -8
  157. package/dist/menu/section/menu-section.d.ts +55 -0
  158. package/dist/menu/section/menu-section.js +60 -0
  159. package/dist/meter/root/meter-root.d.ts +20 -1
  160. package/dist/meter/root/meter-root.js +11 -15
  161. package/dist/navigation/root/navigation-root.d.ts +18 -2
  162. package/dist/navigation/root/navigation-root.js +29 -3
  163. package/dist/notifications/root/notifications-root.d.ts +25 -0
  164. package/dist/notifications/root/notifications-root.js +33 -5
  165. package/dist/number-input/root/number-input-root.d.ts +17 -8
  166. package/dist/number-input/root/number-input-root.js +2 -7
  167. package/dist/object-inspector/root/object-inspector-root.d.ts +161 -32
  168. package/dist/object-inspector/root/object-inspector-root.js +264 -123
  169. package/dist/object-inspector/rows.d.ts +75 -0
  170. package/dist/object-inspector/rows.js +119 -0
  171. package/dist/option/root/option-root.d.ts +5 -3
  172. package/dist/outline/levels.d.ts +31 -0
  173. package/dist/outline/levels.js +23 -0
  174. package/dist/outline/root/outline-root.d.ts +86 -3
  175. package/dist/outline/root/outline-root.js +95 -12
  176. package/dist/pagination/size/pagination-size.d.ts +12 -2
  177. package/dist/pagination/size/pagination-size.js +20 -5
  178. package/dist/pin-input/code.d.ts +10 -0
  179. package/dist/pin-input/code.js +13 -0
  180. package/dist/pin-input/root/pin-input-root.d.ts +25 -1
  181. package/dist/pin-input/root/pin-input-root.js +10 -11
  182. package/dist/popover/hide-outside.d.ts +14 -0
  183. package/dist/popover/hide-outside.js +41 -0
  184. package/dist/popover/root/popover-root.d.ts +57 -7
  185. package/dist/popover/root/popover-root.js +58 -3
  186. package/dist/progress/root/progress-root.d.ts +20 -0
  187. package/dist/progress/root/progress-root.js +15 -15
  188. package/dist/qr-code/export.d.ts +26 -1
  189. package/dist/qr-code/export.js +14 -0
  190. package/dist/qr-code/root/qr-code-root.d.ts +19 -5
  191. package/dist/qr-code/root/qr-code-root.js +58 -9
  192. package/dist/quote/marks.d.ts +8 -0
  193. package/dist/quote/marks.js +5 -0
  194. package/dist/quote/root/quote-root.d.ts +14 -2
  195. package/dist/quote/root/quote-root.js +23 -1
  196. package/dist/radio/group/radio-group.d.ts +4 -10
  197. package/dist/radio/group/radio-group.js +5 -10
  198. package/dist/radio/root/radio-root.d.ts +6 -2
  199. package/dist/radio/root/radio-root.js +6 -1
  200. package/dist/rating/root/rating-root.d.ts +10 -5
  201. package/dist/rating/root/rating-root.js +32 -8
  202. package/dist/rating/steps.d.ts +7 -0
  203. package/dist/rating/steps.js +9 -0
  204. package/dist/scatter-chart/fit.d.ts +15 -0
  205. package/dist/scatter-chart/fit.js +35 -0
  206. package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
  207. package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
  208. package/dist/scroll-area/root/scroll-area-root.d.ts +84 -0
  209. package/dist/scroll-area/root/scroll-area-root.js +106 -7
  210. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  211. package/dist/scroll-area/scrollbar-controller.js +172 -0
  212. package/dist/scroll-area/scrollbar.d.ts +92 -0
  213. package/dist/scroll-area/scrollbar.js +33 -0
  214. package/dist/select/root/select-root.d.ts +15 -0
  215. package/dist/select/root/select-root.js +18 -6
  216. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  217. package/dist/skeleton/root/skeleton-root.js +4 -2
  218. package/dist/skip-link/root/skip-link-root.js +2 -2
  219. package/dist/slider/root/slider-root.d.ts +41 -4
  220. package/dist/slider/root/slider-root.js +23 -3
  221. package/dist/sparkline/readings.d.ts +18 -0
  222. package/dist/sparkline/readings.js +19 -0
  223. package/dist/sparkline/root/sparkline-root.d.ts +78 -7
  224. package/dist/sparkline/root/sparkline-root.js +118 -23
  225. package/dist/speed-dial/root/speed-dial-root.js +2 -2
  226. package/dist/splitter/root/splitter-root.d.ts +20 -12
  227. package/dist/splitter/root/splitter-root.js +226 -203
  228. package/dist/splitter/snap.d.ts +9 -0
  229. package/dist/splitter/snap.js +12 -0
  230. package/dist/stat/root/stat-root.d.ts +14 -5
  231. package/dist/stat/root/stat-root.js +21 -5
  232. package/dist/steps/reach.d.ts +20 -0
  233. package/dist/steps/reach.js +15 -0
  234. package/dist/steps/root/steps-root.d.ts +76 -0
  235. package/dist/steps/root/steps-root.js +93 -1
  236. package/dist/steps/step/step.d.ts +45 -2
  237. package/dist/steps/step/step.js +33 -6
  238. package/dist/switch/root/switch-root.d.ts +10 -0
  239. package/dist/table/column/table-column.d.ts +11 -10
  240. package/dist/table/column/table-column.js +8 -19
  241. package/dist/table/root/table-root.d.ts +126 -4
  242. package/dist/table/root/table-root.js +156 -6
  243. package/dist/table/row/table-row.d.ts +47 -1
  244. package/dist/table/row/table-row.js +39 -2
  245. package/dist/tabs/panel/tab-panel.d.ts +22 -5
  246. package/dist/tabs/panel/tab-panel.js +34 -6
  247. package/dist/tabs/root/tabs-root.d.ts +37 -1
  248. package/dist/tabs/root/tabs-root.js +22 -4
  249. package/dist/tabs/tab/tab.d.ts +41 -4
  250. package/dist/tabs/tab/tab.js +49 -3
  251. package/dist/tag/group/tag-group.d.ts +31 -4
  252. package/dist/tag/group/tag-group.js +46 -7
  253. package/dist/tag/root/tag-root.js +9 -2
  254. package/dist/textarea/root/textarea-root.d.ts +28 -1
  255. package/dist/textarea/root/textarea-root.js +40 -1
  256. package/dist/time-input/root/time-input-root.d.ts +5 -1
  257. package/dist/time-input/root/time-input-root.js +16 -8
  258. package/dist/time-picker/root/time-picker-root.d.ts +18 -4
  259. package/dist/time-picker/root/time-picker-root.js +7 -10
  260. package/dist/time-picker/wheel-name.d.ts +9 -0
  261. package/dist/time-picker/wheel-name.js +15 -0
  262. package/dist/timeline/group/timeline-group.d.ts +46 -0
  263. package/dist/timeline/group/timeline-group.js +37 -0
  264. package/dist/timeline/index.d.ts +1 -0
  265. package/dist/timeline/index.js +1 -0
  266. package/dist/timeline/root/timeline-root.d.ts +10 -3
  267. package/dist/toast/item/toast-item.d.ts +24 -18
  268. package/dist/toast/item/toast-item.js +36 -40
  269. package/dist/toast/root/toast-root.d.ts +6 -0
  270. package/dist/toast/root/toast-root.js +16 -1
  271. package/dist/toggle/group/toggle-group.d.ts +24 -3
  272. package/dist/toggle/group/toggle-group.js +34 -5
  273. package/dist/toolbar/root/toolbar-root.d.ts +13 -0
  274. package/dist/toolbar/root/toolbar-root.js +15 -5
  275. package/dist/tooltip/root/tooltip-root.d.ts +13 -2
  276. package/dist/tooltip/root/tooltip-root.js +9 -1
  277. package/dist/tour/back.d.ts +10 -0
  278. package/dist/tour/back.js +8 -0
  279. package/dist/tour/root/tour-root.d.ts +30 -2
  280. package/dist/tour/root/tour-root.js +34 -8
  281. package/dist/tree/item/tree-item.d.ts +61 -4
  282. package/dist/tree/item/tree-item.js +92 -20
  283. package/dist/tree/root/tree-root.d.ts +58 -0
  284. package/dist/tree/root/tree-root.js +80 -16
  285. package/dist/tree/selection.d.ts +24 -0
  286. package/dist/tree/selection.js +13 -0
  287. package/dist/trend/root/trend-root.d.ts +43 -18
  288. package/dist/trend/root/trend-root.js +31 -6
  289. package/dist/video/media-events.d.ts +44 -0
  290. package/dist/video/media-events.js +35 -0
  291. package/dist/video/root/video-root.d.ts +117 -18
  292. package/dist/video/root/video-root.js +93 -47
  293. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
  294. package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
  295. package/dist/video-playlist/order.d.ts +41 -0
  296. package/dist/video-playlist/order.js +34 -0
  297. package/dist/video-playlist/root/video-playlist-root.d.ts +77 -3
  298. package/dist/video-playlist/root/video-playlist-root.js +60 -16
  299. package/dist/virtual-list/controls.d.ts +4 -0
  300. package/dist/virtual-list/controls.js +30 -0
  301. package/dist/virtual-list/fill.d.ts +22 -0
  302. package/dist/virtual-list/fill.js +23 -0
  303. package/dist/virtual-list/keys.d.ts +15 -0
  304. package/dist/virtual-list/keys.js +24 -0
  305. package/dist/virtual-list/plan.d.ts +49 -0
  306. package/dist/virtual-list/plan.js +16 -0
  307. package/dist/virtual-list/root/virtual-list-root.d.ts +259 -26
  308. package/dist/virtual-list/root/virtual-list-root.js +333 -49
  309. package/lint.json +1 -1
  310. package/package.json +8 -8
  311. package/types/jsx.d.ts +8113 -1394
  312. package/types/svelte.d.ts +2 -0
  313. package/types/vue.d.ts +1678 -353
  314. package/dist/data-table/root/order.d.ts +0 -141
  315. package/dist/data-table/root/order.js +0 -76
  316. package/dist/listbox/range.d.ts +0 -17
  317. package/dist/listbox/range.js +0 -5
  318. package/dist/tag/selection.d.ts +0 -10
  319. package/dist/tag/selection.js +0 -12
@@ -30,6 +30,10 @@ const THICKNESS = {
30
30
  small: 26,
31
31
  };
32
32
  let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSource(HelixElement) {
33
+ constructor() {
34
+ super(...arguments);
35
+ this.sliceLabels = false;
36
+ }
33
37
  connectedCallback() {
34
38
  super.connectedCallback();
35
39
  this.pointer.axis = 'none';
@@ -70,6 +74,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
70
74
  get readings() {
71
75
  return this.shares.length;
72
76
  }
77
+ showsReading(at) {
78
+ return (this.shares[at]?.fraction ?? 0) > 0;
79
+ }
73
80
  render() {
74
81
  const shares = this.shares;
75
82
  return html `${this.renderPlot(shares)}${shares.length === 0 ? nothing : this.renderSummary(shares)}`;
@@ -111,9 +118,31 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
111
118
  ${shares.map((share, index) => this.renderSegment(share, index))}
112
119
  </svg>
113
120
  ${this.hole === 'none' ? nothing : html `<div id="helix-chart-center" part="center"><slot></slot></div>`}
121
+ ${this.sliceLabels ? this.renderSliceLabels(shares) : nothing}
114
122
  ${this.renderTooltip()}
115
123
  </div>`;
116
124
  }
125
+ renderSliceLabels(shares) {
126
+ const half = this.sweep === 'half';
127
+ const top = half ? CENTER - EDGE : 0;
128
+ const tall = half ? EDGE + this.thickness / 2 : PLOT_HEIGHT;
129
+ const format = percentIn(this.locale);
130
+ return html `${shares.map((share, index) => {
131
+ if (share.fraction < 0.05) {
132
+ return nothing;
133
+ }
134
+ const angle = (share.start + share.fraction / 2) * 2 * Math.PI * this.span + this.origin;
135
+ const x = ((CENTER + Math.cos(angle) * this.radius) / PLOT_WIDTH) * 100;
136
+ const y = ((CENTER + Math.sin(angle) * this.radius - top) / tall) * 100;
137
+ return html `<span
138
+ aria-hidden="true"
139
+ data-series=${seriesIndex(index)}
140
+ part="slice-label"
141
+ style=${`--chart-series: var(--chart-series-${seriesIndex(index)}); ${half ? 'inset-inline-start' : 'left'}: ${x}%; top: ${y}%`}
142
+ >${format.format(share.fraction)}</span
143
+ >`;
144
+ })}`;
145
+ }
117
146
  get frame() {
118
147
  if (this.sweep !== 'half') {
119
148
  return `0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}`;
@@ -174,6 +203,21 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
174
203
  style="--chart-series: var(--chart-series-${seriesIndex(index)})"
175
204
  />`;
176
205
  }
206
+ withShare(share) {
207
+ const rows = this.sourceRows;
208
+ const column = this.plottedColumns[0];
209
+ const row = rows[share.row];
210
+ const cell = column === undefined ? undefined : row?.cells[column];
211
+ if (!row || !cell || column === undefined) {
212
+ return rows;
213
+ }
214
+ const cells = [...row.cells];
215
+ cells[column] = {
216
+ ...cell,
217
+ text: `${cell.text} (${percentIn(this.locale).format(share.fraction)})`,
218
+ };
219
+ return rows.map((one, index) => (index === share.row ? { ...row, cells } : one));
220
+ }
177
221
  renderTooltip() {
178
222
  const at = this.pointer.at;
179
223
  const share = this.shares[at];
@@ -188,7 +232,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
188
232
  const y = ((CENTER + Math.sin(angle) * edge - top) / tall) * 100;
189
233
  const turned = this.sweep === 'half' && this.pointer.mirrored;
190
234
  const across = Math.cos(angle) > 0 !== turned;
191
- return drawTooltip(this.sourceRows, share.row, this.tag('tooltip'), {
235
+ return drawTooltip(this.withShare(share), share.row, this.tag('tooltip'), {
192
236
  fixed: this.sweep !== 'half',
193
237
  placement: Math.abs(Math.cos(angle)) > Math.abs(Math.sin(angle))
194
238
  ? across
@@ -205,6 +249,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
205
249
  __decorate([
206
250
  property()
207
251
  ], HelixHeadlessDonutChart.prototype, "hole", void 0);
252
+ __decorate([
253
+ property({ attribute: 'slice-labels', reflect: true, type: Boolean })
254
+ ], HelixHeadlessDonutChart.prototype, "sliceLabels", void 0);
208
255
  __decorate([
209
256
  property({ reflect: true })
210
257
  ], HelixHeadlessDonutChart.prototype, "sweep", void 0);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether a box reaches past the window's edges, by more than a pixel.
3
+ *
4
+ * What a drawer resting at a snap point asks of the element focus has just
5
+ * moved to: the part of the panel past the window's edge is off screen, and a
6
+ * control there has focus where the reader cannot see it.
7
+ */
8
+ export declare const beyondWindow: (box: Pick<DOMRectReadOnly, 'bottom' | 'left' | 'right' | 'top'>, width: number, height: number) => boolean;
@@ -0,0 +1 @@
1
+ export const beyondWindow = (box, width, height) => box.top < -1 || box.left < -1 || box.bottom > height + 1 || box.right > width + 1;
@@ -27,6 +27,16 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
27
27
  * the nearest. While a swipe moves the panel, the distance is written on it as
28
28
  * `--drawer-swipe-x` and `--drawer-swipe-y`. `swipe="false"` turns swiping off.
29
29
  *
30
+ * `snap` is the snap point the panel rests at, and `:state(snapped)` is on the
31
+ * host while that is less than the whole panel. `snapTo()` moves it to
32
+ * another. **Focus moving to a control past the
33
+ * window's edge opens the panel to its largest snap point**, so a reader
34
+ * moving through a half open sheet with `Tab` never lands on a control they
35
+ * cannot see.
36
+ *
37
+ * Set `dismissible` to draw a close control in the corner, labeled by
38
+ * `dismiss-label`, as `Dialog` draws one.
39
+ *
30
40
  * The panel's name is `label` when you set it. Otherwise it is the heading in
31
41
  * the `header` slot, or the elements an `aria-labelledby` on the host names.
32
42
  *
@@ -51,6 +61,7 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
51
61
  * @documentation https://fusion.dev/helix/components/drawer
52
62
  *
53
63
  * @slot - The drawer's content.
64
+ * @slot dismiss-icon - Replaces the glyph inside the close control.
54
65
  * @slot footer - Content pinned below the scrolling area, such as the drawer's actions.
55
66
  * @slot header - Content pinned above the scrolling area.
56
67
  *
@@ -60,6 +71,8 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
60
71
  * @event {ToggleEvent} toggle - Sent when the drawer opens or closes, with `newState` and `oldState`.
61
72
  *
62
73
  * @csspart content - The scrolling content region.
74
+ * @csspart dismiss - The close control, drawn when the drawer is `dismissible`.
75
+ * @csspart dismiss-mark - The glyph on the close control, where none is slotted.
63
76
  * @csspart footer - The footer region.
64
77
  * @csspart header - The header region.
65
78
  * @csspart panel - The sliding panel.
@@ -70,6 +83,7 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
70
83
  * @cssstate entering - From the moment the drawer opens until its entrance has finished.
71
84
  * @cssstate exiting - From the moment the drawer closes until its exit has finished.
72
85
  * @cssstate open - While the drawer is open.
86
+ * @cssstate snapped - While the panel rests at a snap point that shows less than the whole panel.
73
87
  */
74
88
  export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
75
89
  protected readonly commands: CommandController;
@@ -86,6 +100,18 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
86
100
  * that a resting value is an attribute's absence.
87
101
  */
88
102
  closedBy?: 'any' | 'closerequest' | 'none';
103
+ /**
104
+ * Draws a control that closes the drawer, in the corner where the title is.
105
+ *
106
+ * Pressing it is `close()`, so it sends `helix-before-close` like every other
107
+ * way out.
108
+ */
109
+ dismissible: boolean;
110
+ /**
111
+ * The close control's accessible name. Translate it with the rest of your
112
+ * interface.
113
+ */
114
+ dismissLabel: string;
89
115
  /**
90
116
  * Accessible name for the panel. When it is empty, the heading in the
91
117
  * `header` slot names the panel.
@@ -153,6 +179,8 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
153
179
  protected readonly phases: OpenPhaseController;
154
180
  /** How far the panel rests toward its edge, in pixels, at the snap point it settled on. */
155
181
  private rest;
182
+ /** The fraction of the panel on screen at the snap point it rests at. */
183
+ private shown;
156
184
  /** The edge the panel leaves through, from its placement and the writing direction. */
157
185
  private get edge();
158
186
  /** The panel's size along the swipe, in pixels. */
@@ -165,6 +193,30 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
165
193
  private place;
166
194
  /** Brings a released swipe to rest: at a snap point, or closed through the request. */
167
195
  private settle;
196
+ /**
197
+ * The fraction of the panel on screen at the snap point it rests at, such as
198
+ * `0.5`. It is `1`, the whole panel, while the drawer is closed or has no
199
+ * `snap-points`.
200
+ */
201
+ get snap(): number;
202
+ /**
203
+ * Puts the panel at rest at a snap point, and says on the host, as
204
+ * `:state(snapped)`, while that is short of the whole panel.
205
+ */
206
+ private restAt;
207
+ /** Says whether the panel rests short of the whole, and nothing while closed. */
208
+ private markSnap;
209
+ /**
210
+ * Moves the open panel to rest at the snap point nearest `point`, a fraction
211
+ * of the panel such as `1` for the whole of it.
212
+ */
213
+ snapTo(point: number): void;
214
+ /**
215
+ * Focus moving to a control past the window's edge, in a panel resting short
216
+ * of the whole: the panel opens to its largest snap point, so the control is
217
+ * on screen.
218
+ */
219
+ private readonly handleFocusIn;
168
220
  /** Opens the drawer. */
169
221
  show(): void;
170
222
  /**
@@ -216,9 +268,16 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
216
268
  * reflection keeps the fallback name.
217
269
  */
218
270
  private nameByHeader;
271
+ connectedCallback(): void;
219
272
  disconnectedCallback(): void;
220
273
  protected updated(changed: PropertyValues): void;
221
274
  protected render(): TemplateResult;
275
+ /**
276
+ * The glyph on the close control, behind a seam: slot fallback, so a
277
+ * consumer replaces it by slotting, and a method, so a tier above replaces it
278
+ * by overriding. As `Dialog` draws it.
279
+ */
280
+ protected renderDismissIcon(): TemplateResult;
222
281
  }
223
282
  declare global {
224
283
  interface HTMLElementTagNameMap {
@@ -4,9 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, CommandController, customElement, edgeOffset, HelixElement, headingsIn, isRtl, lockScroll, MixinControllerOpen, OpenPhaseController, onUnlessFalse, parseSnapPoints, reflectElements, SwipeController, settleSwipe, snapTravel, swipeAxis, swipeEdge, towardEdge, unlockScroll, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, CommandController, customElement, drawDismiss, drawDismissGlyph, edgeOffset, HelixElement, headingsIn, isRtl, lockScroll, MixinControllerOpen, OpenPhaseController, onUnlessFalse, parseSnapPoints, reflectElements, SwipeController, settleSwipe, snapTravel, swipeAxis, swipeEdge, towardEdge, unlockScroll, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { beyondWindow } from '../reveal.js';
10
11
  import { startsSwipe } from '../swipe-start.js';
11
12
  let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(HelixElement) {
12
13
  constructor() {
@@ -18,6 +19,8 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
18
19
  '--toggle': () => this.toggleOpen(),
19
20
  },
20
21
  });
22
+ this.dismissible = false;
23
+ this.dismissLabel = 'Close';
21
24
  this.label = '';
22
25
  this.aria = new AriaForwardController(this, { target: () => this.panel });
23
26
  this.modal = true;
@@ -33,6 +36,7 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
33
36
  surface: () => this.panel,
34
37
  });
35
38
  this.rest = 0;
39
+ this.shown = 1;
36
40
  this.swipes = new SwipeController(this, {
37
41
  axis: () => (this.open && this.swipe ? swipeAxis(this.edge) : undefined),
38
42
  end: (dx, dy, vx, vy) => this.settle(dx, dy, vx, vy),
@@ -40,6 +44,15 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
40
44
  start: (target, event) => startsSwipe(target, event.pointerType, swipeAxis(this.edge), this.partNamed('content')),
41
45
  surface: () => this.panel,
42
46
  });
47
+ this.handleFocusIn = (event) => {
48
+ const target = event.composedPath()[0];
49
+ if (this.shown >= 1 || !(target instanceof Element) || typeof window === 'undefined') {
50
+ return;
51
+ }
52
+ if (beyondWindow(target.getBoundingClientRect(), window.innerWidth, window.innerHeight)) {
53
+ this.snapTo(1);
54
+ }
55
+ };
43
56
  this.handleKeydown = (event) => {
44
57
  if (event.key !== 'Escape' ||
45
58
  event.defaultPrevented ||
@@ -117,9 +130,31 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
117
130
  return;
118
131
  }
119
132
  if (shown !== 0) {
120
- this.rest = snapTravel(size, shown);
133
+ this.restAt(shown);
121
134
  }
135
+ else {
136
+ this.place(this.rest);
137
+ }
138
+ }
139
+ get snap() {
140
+ return this.open ? this.shown : 1;
141
+ }
142
+ restAt(shown) {
143
+ this.shown = shown;
144
+ this.rest = snapTravel(this.extent, shown);
122
145
  this.place(this.rest);
146
+ this.markSnap();
147
+ }
148
+ markSnap() {
149
+ this.toggleState('snapped', this.open && this.shown < 1);
150
+ }
151
+ snapTo(point) {
152
+ if (!this.open) {
153
+ return;
154
+ }
155
+ const points = parseSnapPoints(this.snapPoints);
156
+ const nearest = points.reduce((best, one) => Math.abs(one - point) < Math.abs(best - point) ? one : best);
157
+ this.restAt(nearest);
123
158
  }
124
159
  show() {
125
160
  this.requestOpen(true);
@@ -143,8 +178,13 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
143
178
  : headingsIn(slot?.assignedElements({ flatten: true }) ?? []);
144
179
  this.namedByHeader = reflectElements(this.panel, 'ariaLabelledByElements', heading, this.namedByHeader);
145
180
  }
181
+ connectedCallback() {
182
+ super.connectedCallback();
183
+ this.addEventListener('focusin', this.handleFocusIn);
184
+ }
146
185
  disconnectedCallback() {
147
186
  super.disconnectedCallback();
187
+ this.removeEventListener('focusin', this.handleFocusIn);
148
188
  unlockScroll(this);
149
189
  }
150
190
  updated(changed) {
@@ -152,7 +192,9 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
152
192
  this.nameByHeader();
153
193
  if (changed.has('open') && !this.open) {
154
194
  this.rest = 0;
195
+ this.shown = 1;
155
196
  this.place(0);
197
+ this.markSnap();
156
198
  }
157
199
  if (this.open && this.modal) {
158
200
  lockScroll(this);
@@ -171,8 +213,7 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
171
213
  else {
172
214
  panel.show();
173
215
  }
174
- this.rest = snapTravel(this.extent, parseSnapPoints(this.snapPoints)[0] ?? 1);
175
- this.place(this.rest);
216
+ this.restAt(parseSnapPoints(this.snapPoints)[0] ?? 1);
176
217
  }
177
218
  else if (!this.open && panel.open) {
178
219
  panel.close();
@@ -192,12 +233,30 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
192
233
  <div part="header"><slot name="header" @slotchange=${this.nameByHeader}></slot></div>
193
234
  <div part="content"><slot></slot></div>
194
235
  <div part="footer"><slot name="footer"></slot></div>
236
+ ${this.dismissible
237
+ ? drawDismiss({
238
+ label: this.dismissLabel,
239
+ mark: this.renderDismissIcon(),
240
+ onDismiss: () => this.close(),
241
+ })
242
+ : nothing}
195
243
  </dialog>`;
196
244
  }
245
+ renderDismissIcon() {
246
+ return html `<slot name="dismiss-icon">
247
+ ${drawDismissGlyph()}
248
+ </slot>`;
249
+ }
197
250
  };
198
251
  __decorate([
199
252
  property({ attribute: 'closedby', reflect: true })
200
253
  ], HelixHeadlessDrawer.prototype, "closedBy", void 0);
254
+ __decorate([
255
+ property({ reflect: true, type: Boolean })
256
+ ], HelixHeadlessDrawer.prototype, "dismissible", void 0);
257
+ __decorate([
258
+ property({ attribute: 'dismiss-label' })
259
+ ], HelixHeadlessDrawer.prototype, "dismissLabel", void 0);
201
260
  __decorate([
202
261
  property()
203
262
  ], HelixHeadlessDrawer.prototype, "label", void 0);
@@ -29,6 +29,7 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
29
29
  * @documentation https://fusion.dev/helix/components/drilldown
30
30
  *
31
31
  * @slot - The row's label.
32
+ * @slot chevron - Replaces the caret of a row that opens a page, such as with your own icon.
32
33
  * @slot end - Content after the label, usually an icon or a count.
33
34
  * @slot page - The rows of the page this row opens.
34
35
  * @slot start - Content before the label, usually an icon.
@@ -65,15 +66,14 @@ export declare class HelixHeadlessDrilldownItem extends HelixElement {
65
66
  */
66
67
  readonly isDrilldownItem = true;
67
68
  /**
68
- * Whether the page showing is the one this row is on.
69
- *
70
- * Written by the stack.
69
+ * @internal Whether the page showing is the one this row is on. Written by
70
+ * the stack, and not a consumer's to set: a framework reading `onPage` as an
71
+ * event handler is why it is kept off the typings.
71
72
  */
72
73
  onPage: boolean;
73
74
  /**
74
- * Whether this row's own page is the one showing.
75
- *
76
- * Written by the stack.
75
+ * @internal Whether this row's own page is the one showing. Written by the
76
+ * stack.
77
77
  */
78
78
  showingPage: boolean;
79
79
  /**
@@ -134,6 +134,11 @@ export declare class HelixHeadlessDrilldownItem extends HelixElement {
134
134
  get selected(): boolean;
135
135
  /** Fires `helix-select` for this row. */
136
136
  select(): void;
137
+ /**
138
+ * The caret of a row that opens a page, as the `chevron` slot's fallback, so
139
+ * an icon of your own replaces it by being slotted.
140
+ */
141
+ protected renderMark(): TemplateResult;
137
142
  protected render(): TemplateResult | typeof nothing;
138
143
  }
139
144
  declare global {
@@ -50,6 +50,13 @@ let HelixHeadlessDrilldownItem = class HelixHeadlessDrilldownItem extends HelixE
50
50
  }
51
51
  this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
52
52
  }
53
+ renderMark() {
54
+ return html `<slot name="chevron" aria-hidden="true"
55
+ ><svg part="mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
56
+ ${unsafeSVG(caretRight.content)}
57
+ </svg></slot
58
+ >`;
59
+ }
53
60
  render() {
54
61
  if (this.showingPage) {
55
62
  return html `<slot name="page" @slotchange=${this.readPage}></slot>`;
@@ -69,11 +76,7 @@ let HelixHeadlessDrilldownItem = class HelixHeadlessDrilldownItem extends HelixE
69
76
  <slot name="start"></slot>
70
77
  <span part="label"><slot></slot></span>
71
78
  <slot name="end"></slot>
72
- ${this.page
73
- ? html `<svg part="mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
74
- ${unsafeSVG(caretRight.content)}
75
- </svg>`
76
- : nothing}
79
+ ${this.page ? this.renderMark() : nothing}
77
80
  </button>
78
81
  <div hidden><slot name="page" @slotchange=${this.readPage}></slot></div>`;
79
82
  }
@@ -20,6 +20,18 @@ declare const HelixHeadlessDrilldown_base: (new (...args: any[]) => import("@fus
20
20
  * and reads the rest from the DOM. The behavior lives in `DrilldownController`,
21
21
  * which `Menu` shares.
22
22
  *
23
+ * After each move the host carries `data-direction`, `forward` into a page or
24
+ * `back` out of one, and records `:state(forward)` or `:state(back)`, so a
25
+ * stylesheet can slide the new page in from the side the reader is going. Both
26
+ * are written again on every move, so an animation keyed on them runs for each
27
+ * page, two moves the same way included. The styled tier slides the page and
28
+ * swaps it at once under `prefers-reduced-motion`.
29
+ *
30
+ * Keys, on a row: Up and Down Arrow move between the rows, Home and End go to
31
+ * the first and the last, and a typed letter moves to the next row whose name
32
+ * starts with it. Enter, Space, or Right Arrow opens a row's page, and Left
33
+ * Arrow or Escape goes back, the two arrows swapping on a right-to-left page.
34
+ *
23
35
  * The rows of the page showing are a `menu`, named by `label` on the top page
24
36
  * and by the page's title below it. The back button and the title sit above
25
37
  * the menu. Disabled rows stay reachable with the arrow keys, and typing a
@@ -32,6 +44,7 @@ declare const HelixHeadlessDrilldown_base: (new (...args: any[]) => import("@fus
32
44
  * @documentation https://fusion.dev/helix/components/drilldown
33
45
  *
34
46
  * @slot - The rows of the top page.
47
+ * @slot back-icon - Replaces the icon on the back button.
35
48
  *
36
49
  * @event {HelixSelectEvent} helix-select - Fired when a row with no page is chosen. Cancelable: canceling it stops the change and leaves the decision to you.
37
50
  *
@@ -44,7 +57,9 @@ declare const HelixHeadlessDrilldown_base: (new (...args: any[]) => import("@fus
44
57
  * @csspart page - The menu the rows are in.
45
58
  * @csspart title - The name of the page showing.
46
59
  *
60
+ * @cssstate back - The last move went back out of a page.
47
61
  * @cssstate drilled - A row's page is showing, so a frame around the drilldown can style itself for that depth.
62
+ * @cssstate forward - The last move went into a page.
48
63
  */
49
64
  export declare class HelixHeadlessDrilldown extends HelixHeadlessDrilldown_base {
50
65
  /**
@@ -74,6 +89,8 @@ export declare class HelixHeadlessDrilldown extends HelixHeadlessDrilldown_base
74
89
  * not suppress it.
75
90
  */
76
91
  private direction?;
92
+ /** Whether a move happened since the last update, so its marks are written again. */
93
+ private moved;
77
94
  private readonly drilldown;
78
95
  /**
79
96
  * The rows on the page showing, which is what the keys move over.
@@ -133,8 +150,20 @@ export declare class HelixHeadlessDrilldown extends HelixHeadlessDrilldown_base
133
150
  connectedCallback(): void;
134
151
  disconnectedCallback(): void;
135
152
  protected updated(changed: PropertyValues): void;
153
+ /**
154
+ * Writes which way the last move went. After a move, the marks come off and
155
+ * the page's style is read before they go back on, so an animation keyed on
156
+ * them starts again for the new page: two moves the same way would otherwise
157
+ * leave the same rule in force and the second page would arrive still.
158
+ */
159
+ private markDirection;
136
160
  /** Walks the tree marking which rows are on the page showing. */
137
161
  private mark;
162
+ /**
163
+ * The back button's icon, as the `back-icon` slot's fallback, so an icon of
164
+ * your own replaces it by being slotted.
165
+ */
166
+ protected renderBackIcon(): TemplateResult;
138
167
  protected render(): TemplateResult;
139
168
  }
140
169
  declare global {
@@ -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 { AriaForwardController, customElement, DrilldownController, HelixElement, inlineStep, KeyboardNavigationController, keyClaimed, MixinCollection, slottedWords, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, customElement, DrilldownController, HelixElement, inlineStep, KeyboardNavigationController, keyClaimed, MixinCollection, slottedWords, typeaheadBy, } from '@fusion.dev/helix-core';
8
8
  import { caretLeft } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -15,6 +15,7 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
15
15
  super(...arguments);
16
16
  this.label = 'Navigation';
17
17
  this.backLabel = 'Back';
18
+ this.moved = false;
18
19
  this.drilldown = new DrilldownController(this, {
19
20
  isRow: (element) => 'isDrilldownItem' in element && element.isDrilldownItem === true,
20
21
  root: () => [...this.children],
@@ -37,7 +38,7 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
37
38
  })),
38
39
  reserved: () => ['ArrowLeft', 'ArrowRight'],
39
40
  selects: () => false,
40
- typeahead: (item) => item.words,
41
+ typeahead: typeaheadBy((item) => item.words),
41
42
  });
42
43
  this.handleFocusIn = (event) => {
43
44
  const item = this.drilldown.rows.find((row) => row.contains(event.target));
@@ -100,6 +101,7 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
100
101
  return;
101
102
  }
102
103
  this.direction = 'forward';
104
+ this.moved = true;
103
105
  this.updateComplete.then(() => this.items[0]?.focusItem());
104
106
  }
105
107
  back() {
@@ -108,6 +110,7 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
108
110
  return false;
109
111
  }
110
112
  this.direction = 'back';
113
+ this.moved = true;
111
114
  this.updateComplete.then(() => leaving?.focusItem());
112
115
  return true;
113
116
  }
@@ -134,12 +137,27 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
134
137
  }
135
138
  this.placeTabStop();
136
139
  this.toggleState('drilled', !this.drilldown.atRoot);
140
+ this.markDirection();
141
+ }
142
+ markDirection() {
143
+ if (this.moved) {
144
+ this.moved = false;
145
+ this.removeAttribute('data-direction');
146
+ this.toggleState('back', false);
147
+ this.toggleState('forward', false);
148
+ const page = this.partNamed('page');
149
+ if (page && typeof getComputedStyle === 'function') {
150
+ getComputedStyle(page).animationName;
151
+ }
152
+ }
137
153
  if (this.direction === undefined) {
138
154
  this.removeAttribute('data-direction');
139
155
  }
140
156
  else {
141
157
  this.setAttribute('data-direction', this.direction);
142
158
  }
159
+ this.toggleState('back', this.direction === 'back');
160
+ this.toggleState('forward', this.direction === 'forward');
143
161
  }
144
162
  mark(item, page, onPage) {
145
163
  item.onPage = onPage;
@@ -150,14 +168,19 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
150
168
  }
151
169
  }
152
170
  }
171
+ renderBackIcon() {
172
+ return html `<slot name="back-icon" aria-hidden="true"
173
+ ><svg part="back-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
174
+ ${unsafeSVG(caretLeft.content)}
175
+ </svg></slot
176
+ >`;
177
+ }
153
178
  render() {
154
179
  return html `${this.drilldown.atRoot
155
180
  ? ''
156
181
  : html `<div part="header">
157
182
  <button part="back" type="button" aria-label=${this.backLabel} @click=${() => this.back()}>
158
- <svg part="back-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
159
- ${unsafeSVG(caretLeft.content)}
160
- </svg>
183
+ ${this.renderBackIcon()}
161
184
  </button>
162
185
  <span id="title" part="title">${this.drilldown.label}</span>
163
186
  </div>`}