@fusion.dev/helix-headless 0.145.0 → 0.147.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/custom-elements.json +12286 -4281
  2. package/dist/accordion/item/accordion-item.d.ts +51 -18
  3. package/dist/accordion/item/accordion-item.js +45 -13
  4. package/dist/accordion/root/accordion-root.d.ts +16 -7
  5. package/dist/accordion/root/accordion-root.js +3 -3
  6. package/dist/announcement/root/announcement-root.d.ts +16 -6
  7. package/dist/announcement/root/announcement-root.js +37 -7
  8. package/dist/app-header/root/app-header-root.d.ts +7 -2
  9. package/dist/app-header/root/app-header-root.js +9 -1
  10. package/dist/app-header/sectioning.d.ts +3 -1
  11. package/dist/app-header/sectioning.js +3 -2
  12. package/dist/area-chart/root/area-chart-root.d.ts +18 -1
  13. package/dist/area-chart/root/area-chart-root.js +11 -3
  14. package/dist/avatar/group/avatar-group.d.ts +20 -14
  15. package/dist/avatar/group/avatar-group.js +17 -19
  16. package/dist/avatar/root/avatar-root.d.ts +31 -1
  17. package/dist/avatar/root/avatar-root.js +11 -1
  18. package/dist/badge/root/badge-root.d.ts +60 -7
  19. package/dist/badge/root/badge-root.js +89 -6
  20. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  21. package/dist/bar-chart/root/bar-chart-root.js +48 -20
  22. package/dist/bar-chart/stack.d.ts +25 -0
  23. package/dist/bar-chart/stack.js +27 -0
  24. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
  25. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
  26. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  27. package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
  28. package/dist/button/root/button-root.d.ts +50 -38
  29. package/dist/button/root/button-root.js +42 -53
  30. package/dist/button/submitter.d.ts +27 -0
  31. package/dist/button/submitter.js +25 -0
  32. package/dist/button-group/root/button-group-root.d.ts +2 -1
  33. package/dist/button-group/root/button-group-root.js +5 -1
  34. package/dist/canvas/node/canvas-node.d.ts +4 -3
  35. package/dist/canvas/node/canvas-node.js +3 -2
  36. package/dist/canvas/root/canvas-root.js +2 -2
  37. package/dist/card/root/card-root.d.ts +36 -4
  38. package/dist/card/root/card-root.js +29 -10
  39. package/dist/carousel/root/carousel-root.d.ts +43 -4
  40. package/dist/carousel/root/carousel-root.js +40 -12
  41. package/dist/carousel/stops.d.ts +20 -0
  42. package/dist/carousel/stops.js +30 -0
  43. package/dist/chat/message/chat-message.js +5 -4
  44. package/dist/chat/naming.d.ts +5 -1
  45. package/dist/chat/naming.js +4 -2
  46. package/dist/chat/root/chat-root.d.ts +40 -4
  47. package/dist/chat/root/chat-root.js +32 -6
  48. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  49. package/dist/checkbox/root/checkbox-root.js +18 -7
  50. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  51. package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
  52. package/dist/checkbox-group/select-all.d.ts +21 -0
  53. package/dist/checkbox-group/select-all.js +7 -0
  54. package/dist/code-block/highlight.d.ts +15 -0
  55. package/dist/code-block/highlight.js +4 -0
  56. package/dist/code-block/root/code-block-root.d.ts +79 -10
  57. package/dist/code-block/root/code-block-root.js +74 -5
  58. package/dist/color-input/root/color-input-root.d.ts +14 -0
  59. package/dist/color-input/root/color-input-root.js +17 -7
  60. package/dist/color-picker/channels.js +1 -2
  61. package/dist/color-picker/root/color-picker-root.d.ts +53 -16
  62. package/dist/color-picker/root/color-picker-root.js +155 -46
  63. package/dist/color-picker/wheel.d.ts +17 -0
  64. package/dist/color-picker/wheel.js +6 -0
  65. package/dist/combobox/root/combobox-root.d.ts +56 -0
  66. package/dist/combobox/root/combobox-root.js +92 -15
  67. package/dist/command/root/command-root.d.ts +19 -2
  68. package/dist/command/root/command-root.js +24 -23
  69. package/dist/copy-button/root/copy-button-root.d.ts +21 -1
  70. package/dist/copy-button/root/copy-button-root.js +16 -4
  71. package/dist/data-table/index.d.ts +1 -1
  72. package/dist/data-table/index.js +1 -1
  73. package/dist/data-table/keys.d.ts +6 -0
  74. package/dist/data-table/keys.js +14 -0
  75. package/dist/data-table/root/data-table-root.d.ts +27 -18
  76. package/dist/data-table/root/data-table-root.js +31 -57
  77. package/dist/data-table/tree.d.ts +16 -1
  78. package/dist/data-table/tree.js +2 -3
  79. package/dist/date-input/root/date-input-root.d.ts +11 -2
  80. package/dist/date-input/root/date-input-root.js +26 -12
  81. package/dist/date-picker/root/date-picker-root.d.ts +14 -9
  82. package/dist/date-picker/root/date-picker-root.js +33 -22
  83. package/dist/description-list/item/description-list-item.d.ts +18 -4
  84. package/dist/description-list/item/description-list-item.js +8 -4
  85. package/dist/dialog/description.js +15 -1
  86. package/dist/dialog/root/dialog-root.d.ts +8 -2
  87. package/dist/dialog/root/dialog-root.js +16 -1
  88. package/dist/divider/root/divider-root.d.ts +3 -0
  89. package/dist/divider/root/divider-root.js +2 -1
  90. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  91. package/dist/donut-chart/root/donut-chart-root.js +55 -1
  92. package/dist/donut-chart/slice-label.d.ts +35 -0
  93. package/dist/donut-chart/slice-label.js +11 -0
  94. package/dist/drawer/reveal.d.ts +8 -0
  95. package/dist/drawer/reveal.js +1 -0
  96. package/dist/drawer/root/drawer-root.d.ts +63 -2
  97. package/dist/drawer/root/drawer-root.js +75 -4
  98. package/dist/drilldown/item/drilldown-item.d.ts +21 -1
  99. package/dist/drilldown/item/drilldown-item.js +40 -5
  100. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  101. package/dist/drilldown/root/drilldown-root.js +22 -3
  102. package/dist/element-events.generated.js +35 -6
  103. package/dist/empty/root/empty-root.d.ts +34 -2
  104. package/dist/empty/root/empty-root.js +26 -4
  105. package/dist/file-input/root/file-input-root.d.ts +99 -8
  106. package/dist/file-input/root/file-input-root.js +120 -22
  107. package/dist/file-input/screen.d.ts +2 -1
  108. package/dist/file-input/status.d.ts +24 -0
  109. package/dist/file-input/status.js +10 -0
  110. package/dist/filter-input/chip/filter-chip.d.ts +23 -0
  111. package/dist/filter-input/chip/filter-chip.js +11 -2
  112. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  113. package/dist/filter-input/menu/filter-menu.js +12 -4
  114. package/dist/filter-input/root/filter-input-root.d.ts +38 -6
  115. package/dist/filter-input/root/filter-input-root.js +18 -28
  116. package/dist/filter-input/suggest.d.ts +28 -3
  117. package/dist/filter-input/suggest.js +18 -8
  118. package/dist/format-date/options.d.ts +3 -4
  119. package/dist/format-date/options.js +2 -2
  120. package/dist/format-date/root/format-date-root.d.ts +27 -17
  121. package/dist/format-date/root/format-date-root.js +27 -48
  122. package/dist/heatmap/root/buckets.d.ts +21 -0
  123. package/dist/heatmap/root/buckets.js +34 -0
  124. package/dist/heatmap/root/heatmap-root.d.ts +83 -11
  125. package/dist/heatmap/root/heatmap-root.js +104 -12
  126. package/dist/icon/index.d.ts +1 -1
  127. package/dist/icon/index.js +1 -1
  128. package/dist/icon/registry.d.ts +26 -1
  129. package/dist/icon/registry.js +12 -1
  130. package/dist/icon/root/icon-root.d.ts +25 -1
  131. package/dist/icon/root/icon-root.js +44 -12
  132. package/dist/icon/root/index.d.ts +1 -1
  133. package/dist/icon/root/index.js +1 -1
  134. package/dist/icon/settle.d.ts +7 -0
  135. package/dist/icon/settle.js +10 -0
  136. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  137. package/dist/image/root/image-root.d.ts +14 -1
  138. package/dist/image/root/image-root.js +7 -2
  139. package/dist/input/root/input-root.d.ts +34 -3
  140. package/dist/input/root/input-root.js +17 -4
  141. package/dist/kbd/keys.d.ts +29 -0
  142. package/dist/kbd/keys.js +52 -0
  143. package/dist/kbd/root/kbd-root.d.ts +52 -1
  144. package/dist/kbd/root/kbd-root.js +40 -47
  145. package/dist/legend/hidden-series.d.ts +10 -2
  146. package/dist/legend/hidden-series.js +5 -2
  147. package/dist/legend/root/legend-root.d.ts +77 -12
  148. package/dist/legend/root/legend-root.js +71 -17
  149. package/dist/lightbox/root/lightbox-root.d.ts +98 -10
  150. package/dist/lightbox/root/lightbox-root.js +153 -18
  151. package/dist/lightbox/zoom-controller.d.ts +59 -0
  152. package/dist/lightbox/zoom-controller.js +128 -0
  153. package/dist/lightbox/zoom.d.ts +24 -0
  154. package/dist/lightbox/zoom.js +18 -0
  155. package/dist/line-chart/root/line-chart-root.d.ts +38 -1
  156. package/dist/line-chart/root/line-chart-root.js +31 -3
  157. package/dist/list/item/list-item.d.ts +2 -0
  158. package/dist/list/item/list-item.js +11 -2
  159. package/dist/list/root/list-root.d.ts +70 -13
  160. package/dist/list/root/list-root.js +91 -13
  161. package/dist/list/selection.d.ts +54 -7
  162. package/dist/list/selection.js +32 -7
  163. package/dist/listbox/root/listbox-root.d.ts +44 -4
  164. package/dist/listbox/root/listbox-root.js +72 -34
  165. package/dist/loader/busy.d.ts +10 -0
  166. package/dist/loader/busy.js +11 -0
  167. package/dist/loader/root/loader-root.d.ts +9 -2
  168. package/dist/loader/root/loader-root.js +23 -3
  169. package/dist/megamenu/hand-over.d.ts +75 -0
  170. package/dist/megamenu/hand-over.js +67 -0
  171. package/dist/megamenu/root/megamenu-root.d.ts +80 -15
  172. package/dist/megamenu/root/megamenu-root.js +76 -19
  173. package/dist/menu/item/menu-item.d.ts +51 -2
  174. package/dist/menu/item/menu-item.js +50 -26
  175. package/dist/menu/root/menu-root.d.ts +17 -0
  176. package/dist/menu/root/menu-root.js +2 -2
  177. package/dist/meter/root/meter-root.d.ts +62 -1
  178. package/dist/meter/root/meter-root.js +38 -16
  179. package/dist/navigation/root/navigation-root.d.ts +2 -1
  180. package/dist/navigation/root/navigation-root.js +2 -2
  181. package/dist/notifications/root/notifications-root.d.ts +20 -4
  182. package/dist/notifications/root/notifications-root.js +30 -8
  183. package/dist/number-input/grain.d.ts +28 -0
  184. package/dist/number-input/grain.js +14 -0
  185. package/dist/number-input/root/number-input-root.d.ts +34 -9
  186. package/dist/number-input/root/number-input-root.js +31 -25
  187. package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
  188. package/dist/object-inspector/root/object-inspector-root.js +134 -92
  189. package/dist/object-inspector/rows.d.ts +18 -0
  190. package/dist/object-inspector/rows.js +33 -0
  191. package/dist/option/index.d.ts +1 -0
  192. package/dist/option/index.js +1 -0
  193. package/dist/option/root/option-root.d.ts +5 -3
  194. package/dist/option/separator/option-separator.d.ts +30 -0
  195. package/dist/option/separator/option-separator.js +21 -0
  196. package/dist/outline/root/outline-root.d.ts +30 -0
  197. package/dist/outline/root/outline-root.js +17 -13
  198. package/dist/pagination/size/pagination-size.d.ts +6 -0
  199. package/dist/pagination/size/pagination-size.js +5 -3
  200. package/dist/pin-input/code.d.ts +37 -0
  201. package/dist/pin-input/code.js +25 -0
  202. package/dist/pin-input/root/pin-input-root.d.ts +116 -115
  203. package/dist/pin-input/root/pin-input-root.js +163 -155
  204. package/dist/popover/hide-outside.d.ts +14 -0
  205. package/dist/popover/hide-outside.js +34 -0
  206. package/dist/popover/root/popover-root.d.ts +64 -8
  207. package/dist/popover/root/popover-root.js +67 -4
  208. package/dist/progress/root/progress-root.d.ts +47 -0
  209. package/dist/progress/root/progress-root.js +34 -16
  210. package/dist/qr-code/export.d.ts +45 -1
  211. package/dist/qr-code/export.js +28 -0
  212. package/dist/qr-code/name.d.ts +11 -0
  213. package/dist/qr-code/name.js +7 -0
  214. package/dist/qr-code/root/qr-code-root.d.ts +36 -11
  215. package/dist/qr-code/root/qr-code-root.js +58 -11
  216. package/dist/quote/marks.d.ts +8 -0
  217. package/dist/quote/marks.js +5 -0
  218. package/dist/quote/root/quote-root.d.ts +14 -2
  219. package/dist/quote/root/quote-root.js +23 -1
  220. package/dist/radio/group/radio-group.d.ts +15 -0
  221. package/dist/radio/root/radio-root.d.ts +6 -2
  222. package/dist/radio/root/radio-root.js +7 -2
  223. package/dist/rating/root/rating-root.d.ts +30 -12
  224. package/dist/rating/root/rating-root.js +27 -27
  225. package/dist/scatter-chart/fit.d.ts +15 -0
  226. package/dist/scatter-chart/fit.js +35 -0
  227. package/dist/scatter-chart/root/scatter-chart-root.d.ts +51 -1
  228. package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
  229. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  230. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  231. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  232. package/dist/scroll-area/scrollbar-controller.js +172 -0
  233. package/dist/scroll-area/scrollbar.d.ts +27 -8
  234. package/dist/scroll-area/scrollbar.js +10 -1
  235. package/dist/select/align.d.ts +47 -0
  236. package/dist/select/align.js +7 -0
  237. package/dist/select/root/select-root.d.ts +71 -0
  238. package/dist/select/root/select-root.js +78 -6
  239. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  240. package/dist/skeleton/root/skeleton-root.js +4 -2
  241. package/dist/skip-link/root/skip-link-root.js +2 -2
  242. package/dist/slider/root/slider-root.d.ts +59 -5
  243. package/dist/slider/root/slider-root.js +45 -3
  244. package/dist/sparkline/readings.d.ts +36 -0
  245. package/dist/sparkline/readings.js +36 -0
  246. package/dist/sparkline/root/sparkline-root.d.ts +121 -7
  247. package/dist/sparkline/root/sparkline-root.js +160 -26
  248. package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
  249. package/dist/speed-dial/item/speed-dial-item.js +2 -2
  250. package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
  251. package/dist/speed-dial/root/speed-dial-root.js +11 -3
  252. package/dist/splitter/root/splitter-root.d.ts +10 -12
  253. package/dist/splitter/root/splitter-root.js +211 -204
  254. package/dist/stat/root/stat-root.d.ts +14 -5
  255. package/dist/stat/root/stat-root.js +21 -5
  256. package/dist/steps/reach.d.ts +5 -0
  257. package/dist/steps/reach.js +3 -0
  258. package/dist/steps/root/steps-root.d.ts +56 -3
  259. package/dist/steps/root/steps-root.js +50 -6
  260. package/dist/steps/step/step.d.ts +8 -0
  261. package/dist/steps/step/step.js +8 -3
  262. package/dist/switch/root/switch-root.d.ts +10 -0
  263. package/dist/table/column/table-column.d.ts +6 -10
  264. package/dist/table/column/table-column.js +8 -20
  265. package/dist/table/root/table-root.d.ts +31 -10
  266. package/dist/table/root/table-root.js +14 -18
  267. package/dist/table/row/table-row.d.ts +24 -0
  268. package/dist/table/row/table-row.js +37 -1
  269. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  270. package/dist/tabs/panel/tab-panel.js +34 -5
  271. package/dist/tabs/root/tabs-root.d.ts +17 -3
  272. package/dist/tabs/root/tabs-root.js +1 -1
  273. package/dist/tabs/tab/tab.d.ts +5 -0
  274. package/dist/tabs/tab/tab.js +5 -2
  275. package/dist/tag/group/tag-group.d.ts +44 -5
  276. package/dist/tag/group/tag-group.js +60 -9
  277. package/dist/tag/root/tag-root.js +9 -2
  278. package/dist/textarea/root/textarea-root.d.ts +41 -2
  279. package/dist/textarea/root/textarea-root.js +39 -1
  280. package/dist/time-input/root/time-input-root.d.ts +10 -2
  281. package/dist/time-input/root/time-input-root.js +24 -13
  282. package/dist/time-picker/root/time-picker-root.d.ts +28 -17
  283. package/dist/time-picker/root/time-picker-root.js +18 -29
  284. package/dist/time-picker/wheel-name.d.ts +9 -0
  285. package/dist/time-picker/wheel-name.js +15 -0
  286. package/dist/timeline/group/timeline-group.js +2 -2
  287. package/dist/toast/item/toast-item.d.ts +16 -3
  288. package/dist/toast/item/toast-item.js +22 -6
  289. package/dist/toast/root/toast-root.d.ts +34 -4
  290. package/dist/toast/root/toast-root.js +74 -13
  291. package/dist/toast/words.d.ts +12 -0
  292. package/dist/toast/words.js +25 -0
  293. package/dist/toggle/group/toggle-group.d.ts +52 -7
  294. package/dist/toggle/group/toggle-group.js +58 -44
  295. package/dist/toggle/root/toggle-root.js +2 -4
  296. package/dist/toolbar/root/toolbar-root.d.ts +21 -5
  297. package/dist/toolbar/root/toolbar-root.js +52 -8
  298. package/dist/tooltip/root/tooltip-root.d.ts +20 -3
  299. package/dist/tooltip/root/tooltip-root.js +18 -1
  300. package/dist/tour/back.d.ts +10 -0
  301. package/dist/tour/back.js +8 -0
  302. package/dist/tour/root/tour-root.d.ts +45 -2
  303. package/dist/tour/root/tour-root.js +53 -8
  304. package/dist/tour/stop/tour-stop.d.ts +3 -0
  305. package/dist/tour/stop/tour-stop.js +3 -3
  306. package/dist/tree/item/tree-item.d.ts +7 -3
  307. package/dist/tree/item/tree-item.js +3 -0
  308. package/dist/tree/root/tree-root.d.ts +24 -3
  309. package/dist/tree/root/tree-root.js +32 -13
  310. package/dist/tree/selection.js +2 -15
  311. package/dist/trend/figure.d.ts +16 -0
  312. package/dist/trend/figure.js +8 -0
  313. package/dist/trend/root/trend-root.d.ts +83 -19
  314. package/dist/trend/root/trend-root.js +59 -8
  315. package/dist/video/media-events.d.ts +13 -18
  316. package/dist/video/media-events.js +1 -5
  317. package/dist/video/root/extra-controls.d.ts +12 -0
  318. package/dist/video/root/extra-controls.js +6 -2
  319. package/dist/video/root/video-root.d.ts +23 -6
  320. package/dist/video/root/video-root.js +19 -10
  321. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  322. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  323. package/dist/video-playlist/root/video-playlist-root.d.ts +17 -1
  324. package/dist/video-playlist/root/video-playlist-root.js +3 -0
  325. package/dist/virtual-list/fill.d.ts +11 -8
  326. package/dist/virtual-list/fill.js +10 -17
  327. package/dist/virtual-list/keys.d.ts +16 -7
  328. package/dist/virtual-list/keys.js +17 -6
  329. package/dist/virtual-list/plan.d.ts +65 -0
  330. package/dist/virtual-list/plan.js +27 -0
  331. package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
  332. package/dist/virtual-list/root/virtual-list-root.js +218 -51
  333. package/lint.json +1 -1
  334. package/package.json +8 -8
  335. package/types/jsx.d.ts +7441 -1458
  336. package/types/svelte.d.ts +1 -0
  337. package/types/vue.d.ts +1501 -326
  338. package/dist/chat/relative-clock.d.ts +0 -39
  339. package/dist/chat/relative-clock.js +0 -31
  340. package/dist/data-table/root/order.d.ts +0 -141
  341. package/dist/data-table/root/order.js +0 -76
  342. package/dist/tag/selection.d.ts +0 -10
  343. package/dist/tag/selection.js +0 -12
@@ -5,14 +5,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixHeadlessObjectInspector_1;
8
- import { AriaForwardController, CopyController, countLabel, customElement, drawStatus, elementById, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeActivateEvent, HelixElement, HelixFilterEvent, HelixFilteredEvent, inlineStep, requestChange, StatusController, scrollItemIntoView, searchableById, VirtualizeController, } from '@fusion.dev/helix-core';
8
+ import { AriaForwardController, CopyController, countLabel, customElement, drawStatus, elementById, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeCloseEvent, HelixBeforeOpenEvent, HelixElement, HelixFilterEvent, HelixFilteredEvent, inlineStep, requestChange, StatusController, scrollItemIntoView, searchableById, Typeahead, treeArrow, VirtualizeController, } from '@fusion.dev/helix-core';
9
9
  import { caretDown, caretRight } from '@fusion.dev/helix-icons';
10
10
  import { html, nothing } from 'lit';
11
11
  import { property, state } from 'lit/decorators.js';
12
+ import { repeat } from 'lit/directives/repeat.js';
12
13
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
13
14
  import { html as staticHtml } from 'lit/static-html.js';
14
15
  import '../../copy-button/index.js';
15
- import { ancestorsOf, entries, flatten, search, seed } from '../rows.js';
16
+ import { cursorFor, entries, flatten, search, seed, siblingBranches, withAncestors, } from '../rows.js';
16
17
  let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends HelixElement {
17
18
  constructor() {
18
19
  super(...arguments);
@@ -38,7 +39,9 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
38
39
  this.opened = new Set();
39
40
  this.cursor = 0;
40
41
  this.revealing = false;
41
- this.typed = { at: 0, text: '' };
42
+ this.focusing = false;
43
+ this.hadFocus = false;
44
+ this.typed = new Typeahead();
42
45
  this.branches = new Set();
43
46
  this.aria = new AriaForwardController(this, {
44
47
  label: true,
@@ -81,24 +84,31 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
81
84
  case 'End':
82
85
  this.move(rows.length - 1);
83
86
  break;
87
+ case 'PageDown':
88
+ this.move(this.cursor + this.pageRows());
89
+ break;
90
+ case 'PageUp':
91
+ this.move(this.cursor - this.pageRows());
92
+ break;
84
93
  case 'ArrowRight':
85
94
  case 'ArrowLeft':
86
- if (inlineStep(this, event.key) === 1) {
87
- if (row.branch && !row.open) {
88
- this.toggle(row, true);
89
- }
90
- else if (row.open) {
95
+ switch (treeArrow(row, inlineStep(this, event.key) === 1 ? 1 : -1)) {
96
+ case 'open':
97
+ case 'close':
98
+ this.toggle(row, !row.open);
99
+ break;
100
+ case 'child':
91
101
  this.move(this.cursor + 1);
102
+ break;
103
+ case 'parent': {
104
+ const parent = rows.findLastIndex((candidate, at) => at < this.cursor && candidate.depth === row.depth - 1);
105
+ if (parent >= 0) {
106
+ this.move(parent);
107
+ }
108
+ break;
92
109
  }
93
- }
94
- else if (row.open) {
95
- this.toggle(row, false);
96
- }
97
- else {
98
- const parent = rows.findLastIndex((candidate, at) => at < this.cursor && candidate.depth === row.depth - 1);
99
- if (parent >= 0) {
100
- this.move(parent);
101
- }
110
+ default:
111
+ break;
102
112
  }
103
113
  break;
104
114
  case 'Enter':
@@ -108,7 +118,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
108
118
  }
109
119
  break;
110
120
  case '*':
111
- this.openSiblings(row);
121
+ this.requestOpen(siblingBranches(rows, row), true);
112
122
  break;
113
123
  default:
114
124
  if (event.key.length !== 1 || event.altKey || event.ctrlKey || event.metaKey) {
@@ -136,9 +146,22 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
136
146
  }
137
147
  };
138
148
  this.handleFilterKeydown = (event) => {
139
- if (event.key === 'ArrowDown') {
149
+ if (event.key === 'ArrowDown' && this.rows.length > 0) {
140
150
  event.preventDefault();
141
- this.partNamed('tree')?.focus();
151
+ this.revealing = true;
152
+ this.focusing = true;
153
+ this.requestUpdate();
154
+ }
155
+ };
156
+ this.handleFocusIn = (event) => {
157
+ const index = Number(event.target.dataset?.index);
158
+ if (Number.isInteger(index) && index !== this.cursor) {
159
+ this.move(index);
160
+ }
161
+ };
162
+ this.handleFocusOut = () => {
163
+ if (this.windowed) {
164
+ this.requestUpdate();
142
165
  }
143
166
  };
144
167
  }
@@ -173,18 +196,11 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
173
196
  }
174
197
  }
175
198
  openAround(paths) {
176
- const opened = new Set(this.opened);
177
- for (const path of paths) {
178
- for (const above of ancestorsOf(path)) {
179
- if (this.branches.has(above)) {
180
- opened.add(above);
181
- }
182
- }
183
- }
184
- this.opened = opened;
199
+ this.opened = withAncestors(this.opened, this.branches, paths);
185
200
  }
186
201
  willUpdate(changed) {
187
202
  super.willUpdate(changed);
203
+ this.hadFocus = this.hasFocusedRow();
188
204
  if (this.loadedFor !== this.for && searchableById(this) && !this.hydrating) {
189
205
  this.loadedFor = this.for;
190
206
  this.load();
@@ -212,26 +228,12 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
212
228
  wanted !== undefined ||
213
229
  ['active', 'defaultDepth', 'expanded', 'filter', 'opened'].some((name) => changed.has(name))) {
214
230
  this.rows = flatten(this.root, this.opened, this.found);
215
- this.cursor = this.place(wanted ?? was, changed.has('filter'));
231
+ this.cursor = cursorFor(this.rows, wanted ?? was, this.cursor, changed.has('filter'));
216
232
  }
217
233
  if (changed.has('filter') && this.hasUpdated) {
218
234
  this.tell();
219
235
  }
220
236
  }
221
- place(path, filtered) {
222
- const rows = this.rows;
223
- const at = (one) => rows.findIndex((row) => row.path === one);
224
- const own = path === undefined ? -1 : at(path);
225
- if (own >= 0 || path === undefined) {
226
- return own >= 0 ? own : Math.min(this.cursor, Math.max(0, rows.length - 1));
227
- }
228
- const match = filtered ? rows.findIndex((row) => row.match) : -1;
229
- const around = ancestorsOf(path)
230
- .reverse()
231
- .map(at)
232
- .find((one) => one >= 0);
233
- return match >= 0 ? match : (around ?? 0);
234
- }
235
237
  tell() {
236
238
  if (this.found) {
237
239
  this.status.say(countLabel(this.found.size, this.resultLabel, this.resultsLabel, this.lang));
@@ -250,6 +252,19 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
250
252
  this.revealing = false;
251
253
  this.reveal();
252
254
  }
255
+ const lost = this.hadFocus &&
256
+ !this.hasFocusedRow() &&
257
+ this.ownerDocument.activeElement === this.ownerDocument.body;
258
+ if (this.focusing || lost) {
259
+ this.focusing = false;
260
+ this.focusActive();
261
+ }
262
+ }
263
+ focusActive() {
264
+ const row = this.partNamed('tree')?.querySelector(`[data-index="${this.cursor}"]`);
265
+ if (row && this.shadowRoot?.activeElement !== row) {
266
+ row.focus({ preventScroll: true });
267
+ }
253
268
  }
254
269
  load() {
255
270
  const text = this.for === '' ? '' : (elementById(this, this.for)?.textContent ?? '');
@@ -277,7 +292,10 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
277
292
  const from = Number(this.cursor > Number(last.dataset.index) ? last.dataset.index : first.dataset.index);
278
293
  tree.scrollTop += (this.cursor - from) * height;
279
294
  this.virtualize.measure();
280
- void this.updateComplete.then(() => this.reveal(attempts - 1));
295
+ void this.updateComplete.then(() => {
296
+ this.reveal(attempts - 1);
297
+ this.focusActive();
298
+ });
281
299
  }
282
300
  copyable(row) {
283
301
  if (!row) {
@@ -288,15 +306,44 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
288
306
  }
289
307
  return JSON.stringify(row.value, null, 2) ?? String(row.value);
290
308
  }
291
- toggle(row, open = !row.open) {
292
- const opened = new Set(this.opened);
293
- if (open) {
294
- opened.add(row.path);
309
+ requestOpen(paths, open) {
310
+ if (paths.length === 0) {
311
+ return false;
295
312
  }
296
- else {
297
- opened.delete(row.path);
313
+ const applied = requestChange({
314
+ apply: () => {
315
+ const opened = new Set(this.opened);
316
+ for (const path of paths) {
317
+ if (open) {
318
+ opened.add(path);
319
+ }
320
+ else {
321
+ opened.delete(path);
322
+ }
323
+ }
324
+ this.opened = opened;
325
+ },
326
+ event: (next) => (next ? new HelixBeforeOpenEvent() : new HelixBeforeCloseEvent()),
327
+ host: this,
328
+ next: open,
329
+ });
330
+ if (applied) {
331
+ this.announceToggle(open);
298
332
  }
299
- this.opened = opened;
333
+ return applied;
334
+ }
335
+ announceToggle(open) {
336
+ const states = { newState: open ? 'open' : 'closed', oldState: open ? 'closed' : 'open' };
337
+ if (typeof ToggleEvent === 'function') {
338
+ this.dispatchEvent(new ToggleEvent('toggle', states));
339
+ return;
340
+ }
341
+ const event = new Event('toggle', { bubbles: false, cancelable: false, composed: false });
342
+ Object.assign(event, states);
343
+ this.dispatchEvent(event);
344
+ }
345
+ toggle(row, open = !row.open) {
346
+ this.requestOpen([row.path], open);
300
347
  }
301
348
  move(to) {
302
349
  const at = Math.max(0, Math.min(to, this.rows.length - 1));
@@ -319,37 +366,21 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
319
366
  this.dispatchEvent(new HelixActivateEvent({ value: path }));
320
367
  }
321
368
  this.revealing = true;
369
+ this.focusing = true;
322
370
  return true;
323
371
  }
324
- openSiblings(row) {
325
- const parent = row.path.slice(0, row.path.lastIndexOf('/'));
326
- const opened = new Set(this.opened);
327
- for (const one of this.rows) {
328
- if (one.branch &&
329
- one.depth === row.depth &&
330
- one.path.slice(0, one.path.lastIndexOf('/')) === parent) {
331
- opened.add(one.path);
332
- }
333
- }
334
- this.opened = opened;
335
- }
336
372
  typeahead(letter) {
337
- const now = Date.now();
338
- const text = now - this.typed.at < 500 ? this.typed.text + letter : letter;
339
- this.typed = { at: now, text };
340
- const wanted = text.toLocaleLowerCase();
341
- const repeated = [...wanted].every((one) => one === wanted[0]);
342
- const rows = this.rows;
343
- const start = wanted.length === 1 || repeated ? this.cursor + 1 : this.cursor;
344
- for (let step = 0; step < rows.length; step += 1) {
345
- const at = (start + step) % rows.length;
346
- const key = rows[at]?.key?.toLocaleLowerCase();
347
- if (key?.startsWith(repeated ? (wanted[0] ?? '') : wanted)) {
348
- this.move(at);
349
- return;
350
- }
373
+ const at = this.typed.match(letter, this.rows.map((row) => row.key ?? ''), this.cursor);
374
+ if (at >= 0) {
375
+ this.move(at);
351
376
  }
352
377
  }
378
+ pageRows() {
379
+ const tree = this.partNamed('tree');
380
+ const room = tree && tree.scrollHeight > tree.clientHeight + 1 ? tree.clientHeight : window.innerHeight;
381
+ const tall = this.virtualize.sizeOf(this.cursor) || HelixHeadlessObjectInspector_1.ESTIMATE;
382
+ return Math.max(1, Math.floor(room / tall) - 1);
383
+ }
353
384
  handleRowClick(index, row) {
354
385
  if (this.move(index) && row.branch) {
355
386
  this.toggle(row);
@@ -391,18 +422,17 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
391
422
  const active = index === this.cursor;
392
423
  return html `<div
393
424
  part="row${active ? ' row-active' : ''}${row.match ? ' row-match' : ''}"
394
- role="treeitem"
425
+ role="row"
395
426
  id=${`row-${index}`}
396
427
  data-index=${index}
428
+ tabindex=${active ? '0' : '-1'}
397
429
  aria-level=${row.depth + 1}
398
430
  aria-posinset=${row.position}
399
- aria-selected="false"
400
431
  aria-setsize=${row.siblings}
401
432
  aria-expanded=${row.branch ? String(row.open) : nothing}
402
433
  style=${`--object-inspector-level: ${row.depth}`}
403
434
  @click=${() => this.handleRowClick(index, row)}
404
- >
405
- ${row.branch
435
+ ><div role="gridcell" style="display: contents">${row.branch
406
436
  ? html `<svg
407
437
  part="toggle"
408
438
  ?data-mirror=${!row.open}
@@ -412,13 +442,17 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
412
442
  >
413
443
  ${unsafeSVG((row.open ? caretDown : caretRight).content)}
414
444
  </svg>`
415
- : nothing}${row.key === undefined ? nothing : html `<span part="key">${row.key}</span>: `}${this.renderValue(row)}
445
+ : nothing}${row.key === undefined ? nothing : html `<span part="key">${row.key}</span>: `}${this.renderValue(row)}</div>
416
446
  </div>`;
417
447
  }
448
+ hasFocusedRow() {
449
+ const focused = this.shadowRoot?.activeElement;
450
+ return focused?.getAttribute?.('role') === 'row';
451
+ }
418
452
  renderCopyButton(row) {
419
453
  return staticHtml `<${this.tag('copy-button')}
420
454
  part="copy"
421
- exportparts="button: copy-button, live: copy-live, text: copy-text, mark: copy-mark, tooltip: copy-tooltip,
455
+ exportparts="button: copy-button, live: copy-live, spinner: copy-spinner, text: copy-text, mark: copy-mark, tooltip: copy-tooltip,
422
456
  tooltip-arrow: copy-tooltip-arrow, tooltip-arrow-bottom: copy-tooltip-arrow-bottom,
423
457
  tooltip-arrow-left: copy-tooltip-arrow-left, tooltip-arrow-right: copy-tooltip-arrow-right,
424
458
  tooltip-arrow-top: copy-tooltip-arrow-top, tooltip-bottom: copy-tooltip-bottom,
@@ -429,10 +463,18 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
429
463
  }
430
464
  render() {
431
465
  const rows = this.rows;
432
- const { after, before, first, last } = this.windowed
433
- ? this.virtualize.window
434
- : { after: 0, before: 0, first: 0, last: rows.length };
435
- const shown = rows.slice(first, last);
466
+ const { first, last } = this.windowed ? this.virtualize.window : { first: 0, last: rows.length };
467
+ const kept = this.windowed && (this.cursor < first || this.cursor >= last) && this.hasFocusedRow()
468
+ ? this.cursor
469
+ : undefined;
470
+ const { after, before } = this.windowed
471
+ ? this.virtualize.spacers(kept)
472
+ : { after: 0, before: 0 };
473
+ const shown = rows.slice(first, last).map((row, at) => [row, first + at]);
474
+ const keptRow = kept === undefined ? undefined : rows[kept];
475
+ if (kept !== undefined && keptRow) {
476
+ shown.splice(kept < first ? 0 : shown.length, 0, [keptRow, kept]);
477
+ }
436
478
  return html `${this.label ? html `<div part="header"><span part="label">${this.label}</span></div>` : nothing}${this.filterable
437
479
  ? html `<input
438
480
  part="search-field"
@@ -450,16 +492,16 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
450
492
  <div
451
493
  part="tree"
452
494
  id="tree"
453
- role="tree"
454
- tabindex="0"
495
+ role="treegrid"
455
496
  ?data-scroller=${this.windowed}
456
497
  aria-label=${this.label || this.treeLabel}
457
- aria-activedescendant=${rows.length > 0 ? `row-${this.cursor}` : nothing}
458
498
  @keydown=${this.handleKeydown}
499
+ @focusin=${this.handleFocusIn}
500
+ @focusout=${this.handleFocusOut}
459
501
  @scroll=${() => this.virtualize.measure()}
460
502
  >
461
503
  ${this.windowed ? html `<div part="before" role="presentation" style="block-size: ${before}px"></div>` : nothing}
462
- ${shown.map((row, at) => this.renderRow(row, first + at))}
504
+ ${repeat(shown, ([row]) => row.path, ([row, at]) => this.renderRow(row, at))}
463
505
  ${this.windowed ? html `<div part="after" role="presentation" style="block-size: ${after}px"></div>` : nothing}
464
506
  </div>
465
507
  ${this.noCopy ? nothing : this.renderCopyButton(rows[this.cursor])}
@@ -55,3 +55,21 @@ export declare const seed: (root: unknown, depth: number, known?: Set<string>, o
55
55
  branches: Set<string>;
56
56
  opened: Set<string>;
57
57
  };
58
+ /**
59
+ * Where the active row goes once the rows have moved, as an index into `rows`.
60
+ *
61
+ * Onto `path` where it is still shown. Where a filter just hid it
62
+ * (`filtered`), onto the first match. Otherwise onto the nearest branch around
63
+ * it that is shown. With no path to keep, `cursor` held inside the rows.
64
+ */
65
+ export declare const cursorFor: (rows: readonly Row[], path: string | undefined, cursor: number, filtered: boolean) => number;
66
+ /**
67
+ * The open branches with every branch around each of `paths` opened too,
68
+ * where the value has that branch (`branches`).
69
+ */
70
+ export declare const withAncestors: (opened: ReadonlySet<string>, branches: ReadonlySet<string>, paths: Iterable<string>) => Set<string>;
71
+ /**
72
+ * The branches `*` opens from `row`: every branch at its depth under the same
73
+ * parent, itself included, that is not open yet.
74
+ */
75
+ export declare const siblingBranches: (rows: readonly Row[], row: Row) => string[];
@@ -84,3 +84,36 @@ export const seed = (root, depth, known = new Set(), opened = new Set()) => {
84
84
  visit(root, '', 0);
85
85
  return { branches, opened: open };
86
86
  };
87
+ export const cursorFor = (rows, path, cursor, filtered) => {
88
+ const at = (one) => rows.findIndex((row) => row.path === one);
89
+ const own = path === undefined ? -1 : at(path);
90
+ if (own >= 0 || path === undefined) {
91
+ return own >= 0 ? own : Math.min(cursor, Math.max(0, rows.length - 1));
92
+ }
93
+ const match = filtered ? rows.findIndex((row) => row.match) : -1;
94
+ const around = ancestorsOf(path)
95
+ .reverse()
96
+ .map(at)
97
+ .find((one) => one >= 0);
98
+ return match >= 0 ? match : (around ?? 0);
99
+ };
100
+ export const withAncestors = (opened, branches, paths) => {
101
+ const next = new Set(opened);
102
+ for (const path of paths) {
103
+ for (const above of ancestorsOf(path)) {
104
+ if (branches.has(above)) {
105
+ next.add(above);
106
+ }
107
+ }
108
+ }
109
+ return next;
110
+ };
111
+ export const siblingBranches = (rows, row) => {
112
+ const parent = row.path.slice(0, row.path.lastIndexOf('/'));
113
+ return rows
114
+ .filter((one) => one.branch &&
115
+ !one.open &&
116
+ one.depth === row.depth &&
117
+ one.path.slice(0, one.path.lastIndexOf('/')) === parent)
118
+ .map((one) => one.path);
119
+ };
@@ -1,2 +1,3 @@
1
1
  export * from './group/option-group.js';
2
2
  export * from './root/option-root.js';
3
+ export * from './separator/option-separator.js';
@@ -1,2 +1,3 @@
1
1
  export * from './group/option-group.js';
2
2
  export * from './root/option-root.js';
3
+ export * from './separator/option-separator.js';
@@ -63,9 +63,11 @@ export declare class HelixHeadlessOption extends HelixElement {
63
63
  /**
64
64
  * Whether this is the option the keyboard is on.
65
65
  *
66
- * Written by the listbox, which writes it once a reader moves the highlight.
67
- * It shows as `:state(active)`, and as a `data-active` attribute for the
68
- * stylesheets written before the state existed.
66
+ * Written by the listbox once a reader moves the highlight. Style it with
67
+ * `:state(active)`, or `::part(item-active)` for an option inside another
68
+ * component's shadow root. The `data-active` attribute sets it from markup;
69
+ * it is also written back for stylesheets from before the state, and no
70
+ * stylesheet of the library's own selects it.
69
71
  */
70
72
  active: boolean;
71
73
  /**
@@ -0,0 +1,30 @@
1
+ import { HelixElement } from '@fusion.dev/helix-core';
2
+ import { nothing, type PropertyValues } from 'lit';
3
+ /**
4
+ * @summary A rule between options or groups inside a listbox.
5
+ *
6
+ * @description
7
+ * Sets one run of options apart from the next where a heading would say too
8
+ * much, as React Aria's ListBox takes a `Separator`: actions apart from
9
+ * choices in a command palette, say, or the options a reader uses most apart
10
+ * from the rest.
11
+ *
12
+ * It has `role="separator"`, so a screen reader can say where one run ends,
13
+ * and it is no stop: the arrow keys move from the option before it to the one
14
+ * after. The list hides it while a filter is narrowing the options, since a
15
+ * rule between two runs of which only some options are left separates nothing.
16
+ *
17
+ * @since 0.1.0
18
+ * @status stable
19
+ * @aliases Divider, ListBoxSeparator
20
+ * @documentation https://fusion.dev/helix/components/option
21
+ */
22
+ export declare class HelixHeadlessOptionSeparator extends HelixElement {
23
+ protected willUpdate(changed: PropertyValues): void;
24
+ protected render(): typeof nothing;
25
+ }
26
+ declare global {
27
+ interface HTMLElementTagNameMap {
28
+ 'helix-headless-option-separator': HelixHeadlessOptionSeparator;
29
+ }
30
+ }
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
+ import { nothing } from 'lit';
9
+ let HelixHeadlessOptionSeparator = class HelixHeadlessOptionSeparator extends HelixElement {
10
+ willUpdate(changed) {
11
+ super.willUpdate(changed);
12
+ hostAria(this.internals, { role: 'separator' });
13
+ }
14
+ render() {
15
+ return nothing;
16
+ }
17
+ };
18
+ HelixHeadlessOptionSeparator = __decorate([
19
+ customElement('helix-headless-option-separator')
20
+ ], HelixHeadlessOptionSeparator);
21
+ export { HelixHeadlessOptionSeparator };
@@ -20,6 +20,21 @@ import { type Branch } from '../levels.js';
20
20
  *
21
21
  * A heading slotted into `heading` names the navigation, in place of `label`.
22
22
  *
23
+ * In a contents rail with a scrollbar of its own, `follow` keeps the link of
24
+ * the section in view showing as the reader scrolls the page.
25
+ *
26
+ * **Keyboard.** The links are your anchors, in the tab order as you wrote
27
+ * them, so the outline adds no keys of its own: Tab moves through the links
28
+ * and Enter follows one. Following a link moves focus to its section, so the
29
+ * next Tab goes on from the heading, also with `behavior` set.
30
+ *
31
+ * **What a screen reader hears.** A navigation landmark named by `label`, "On
32
+ * this page", or by the slotted heading. The links are lists, nested by level,
33
+ * so a reader hears how many links a level holds and where each one is. The
34
+ * link to the section in view carries `aria-current="location"`, read as
35
+ * "current location", and it moves as the page scrolls without announcing,
36
+ * which would interrupt the reading it follows.
37
+ *
23
38
  * The current section is decided by the headings' positions. An
24
39
  * `IntersectionObserver` with a band near the top fails both ways: when
25
40
  * headings are far apart, none is in the band and no section is marked, and
@@ -73,6 +88,13 @@ export declare class HelixHeadlessOutline extends HelixElement {
73
88
  * JavaScript rather than CSS decides.
74
89
  */
75
90
  behavior: ScrollBehavior;
91
+ /**
92
+ * Keeps the link of the section in view in view itself, in an outline
93
+ * longer than the box it scrolls in, such as a contents rail with a
94
+ * scrollbar of its own. Only that box moves: never the page, and never the
95
+ * box the sections scroll in.
96
+ */
97
+ follow: boolean;
76
98
  /**
77
99
  * The navigation's name, read by screen readers. A heading in the `heading`
78
100
  * slot names it in place of this.
@@ -154,6 +176,14 @@ export declare class HelixHeadlessOutline extends HelixElement {
154
176
  private mark;
155
177
  /** Where the destination is set, whether measured or asked for. */
156
178
  private markTo;
179
+ /**
180
+ * Scrolls the box the links scroll in to show `link`, under `follow`.
181
+ *
182
+ * The nearest box above the link that scrolls, and only where it is the
183
+ * rail's own: the page, the box the sections scroll in, or a box holding it
184
+ * would move the reading under the reader, which is the scroll this marks.
185
+ */
186
+ private reveal;
157
187
  /**
158
188
  * Whether the page has no more scroll left.
159
189
  *
@@ -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 { customElement, elementById, HelixActivateEvent, HelixElement, IndicatorController, reflectElements, } from '@fusion.dev/helix-core';
7
+ import { customElement, elementById, HelixActivateEvent, HelixElement, IndicatorController, plainClick, reflectElements, scrollItemIntoView, scrollingAncestor, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { levelOf, nest } from '../levels.js';
@@ -18,6 +18,7 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
18
18
  surface: () => this.partNamed('nav'),
19
19
  });
20
20
  this.behavior = 'auto';
21
+ this.follow = false;
21
22
  this.label = 'On this page';
22
23
  this.offset = 0;
23
24
  this.reading = '';
@@ -32,10 +33,7 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
32
33
  });
33
34
  };
34
35
  this.handleClick = (event) => {
35
- if (event.defaultPrevented || event.button !== 0) {
36
- return;
37
- }
38
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
36
+ if (event.defaultPrevented || !plainClick(event)) {
39
37
  return;
40
38
  }
41
39
  const link = event.target?.closest?.('a[href^="#"]');
@@ -142,9 +140,19 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
142
140
  if (next !== this.reading) {
143
141
  this.reading = next;
144
142
  this.indicator.place();
143
+ if (this.follow && active) {
144
+ this.reveal(active.link);
145
+ }
145
146
  this.dispatchEvent(new HelixActivateEvent({ value: next }));
146
147
  }
147
148
  }
149
+ reveal(link) {
150
+ const sections = this.scroller;
151
+ const node = scrollingAncestor(link, { axis: 'y', overflowing: true, stop: this.page });
152
+ if (node && node !== sections && !node.contains(sections)) {
153
+ scrollItemIntoView(link, { scroller: node });
154
+ }
155
+ }
148
156
  get atEnd() {
149
157
  const doc = this.scroller;
150
158
  return Math.ceil(doc.scrollTop + doc.clientHeight) >= doc.scrollHeight - 1;
@@ -154,15 +162,8 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
154
162
  return (doc.scrollingElement ?? doc.documentElement);
155
163
  }
156
164
  get scroller() {
157
- const doc = globalThis.document;
158
165
  const first = this.sections[0]?.target;
159
- for (let node = first?.parentElement; node && node !== doc.body && node !== doc.documentElement; node = node.parentElement) {
160
- const { overflowY } = getComputedStyle(node);
161
- if (/auto|scroll|overlay/.test(overflowY) && node.scrollHeight > node.clientHeight) {
162
- return node;
163
- }
164
- }
165
- return this.page;
166
+ return (first && scrollingAncestor(first, { axis: 'y', overflowing: true })) || this.page;
166
167
  }
167
168
  reach() {
168
169
  for (const { target } of this.sections) {
@@ -282,6 +283,9 @@ let HelixHeadlessOutline = class HelixHeadlessOutline extends HelixElement {
282
283
  __decorate([
283
284
  property()
284
285
  ], HelixHeadlessOutline.prototype, "behavior", void 0);
286
+ __decorate([
287
+ property({ type: Boolean })
288
+ ], HelixHeadlessOutline.prototype, "follow", void 0);
285
289
  __decorate([
286
290
  property()
287
291
  ], HelixHeadlessOutline.prototype, "label", void 0);
@@ -14,6 +14,11 @@ import '../../select/index.js';
14
14
  * `currentColor`, and the label is a real `<label for>` pointing at the
15
15
  * trigger's id.
16
16
  *
17
+ * A `<label for>` pointing at this element, or its own `aria-label` or
18
+ * `aria-labelledby`, names the select in place of `label`, so a reader hears
19
+ * the page's words for it, and the select draws no label of its own beside
20
+ * the page's.
21
+ *
17
22
  * The label sits on the same row as the select. `Select`'s host is a column,
18
23
  * and an outer-tree rule overrides a `:host` rule, so the row layout needs no
19
24
  * property on `Select` and nothing added to your markup.
@@ -49,6 +54,7 @@ import '../../select/index.js';
49
54
  * @csspart control-label - The label beside the number.
50
55
  * @csspart control-listbox - The list inside the panel.
51
56
  * @csspart control-listbox-empty - The text shown when the filter hides every option.
57
+ * @csspart control-listbox-error - The inner list's `error` part, shown while its `load-error` is set.
52
58
  * @csspart control-listbox-feedback - The inner list's message that says what is wrong with the value.
53
59
  * @csspart control-listbox-filter-icon - The icon beside the filter field.
54
60
  * @csspart control-listbox-filter-mark - The default icon beside the filter field, shown when none is slotted.