@fusion.dev/helix-headless 0.145.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 (278) hide show
  1. package/custom-elements.json +7373 -3849
  2. package/dist/accordion/item/accordion-item.d.ts +14 -0
  3. package/dist/accordion/item/accordion-item.js +16 -6
  4. package/dist/accordion/root/accordion-root.d.ts +8 -5
  5. package/dist/announcement/root/announcement-root.d.ts +3 -2
  6. package/dist/announcement/root/announcement-root.js +3 -1
  7. package/dist/app-header/root/app-header-root.d.ts +7 -2
  8. package/dist/app-header/root/app-header-root.js +9 -1
  9. package/dist/app-header/sectioning.d.ts +3 -1
  10. package/dist/app-header/sectioning.js +3 -2
  11. package/dist/avatar/group/avatar-group.d.ts +20 -14
  12. package/dist/avatar/group/avatar-group.js +17 -19
  13. package/dist/badge/root/badge-root.d.ts +3 -1
  14. package/dist/badge/root/badge-root.js +2 -2
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +52 -15
  17. package/dist/bar-chart/stack.d.ts +15 -0
  18. package/dist/bar-chart/stack.js +19 -0
  19. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  20. package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
  21. package/dist/button/root/button-root.d.ts +26 -0
  22. package/dist/button/root/button-root.js +38 -18
  23. package/dist/button-group/root/button-group-root.d.ts +2 -1
  24. package/dist/button-group/root/button-group-root.js +5 -1
  25. package/dist/canvas/node/canvas-node.d.ts +4 -3
  26. package/dist/canvas/node/canvas-node.js +3 -2
  27. package/dist/canvas/root/canvas-root.js +2 -2
  28. package/dist/card/root/card-root.d.ts +24 -3
  29. package/dist/card/root/card-root.js +20 -8
  30. package/dist/carousel/root/carousel-root.d.ts +43 -4
  31. package/dist/carousel/root/carousel-root.js +40 -12
  32. package/dist/carousel/stops.d.ts +20 -0
  33. package/dist/carousel/stops.js +30 -0
  34. package/dist/chat/message/chat-message.js +5 -4
  35. package/dist/chat/naming.d.ts +5 -1
  36. package/dist/chat/naming.js +4 -2
  37. package/dist/chat/root/chat-root.d.ts +25 -3
  38. package/dist/chat/root/chat-root.js +22 -5
  39. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  40. package/dist/checkbox/root/checkbox-root.js +14 -1
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  42. package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
  43. package/dist/checkbox-group/select-all.d.ts +27 -0
  44. package/dist/checkbox-group/select-all.js +12 -0
  45. package/dist/code-block/highlight.d.ts +15 -0
  46. package/dist/code-block/highlight.js +4 -0
  47. package/dist/code-block/root/code-block-root.d.ts +49 -1
  48. package/dist/code-block/root/code-block-root.js +58 -3
  49. package/dist/color-input/root/color-input-root.d.ts +3 -0
  50. package/dist/color-input/root/color-input-root.js +6 -3
  51. package/dist/color-picker/root/color-picker-root.d.ts +33 -4
  52. package/dist/color-picker/root/color-picker-root.js +80 -21
  53. package/dist/color-picker/swatches.d.ts +12 -0
  54. package/dist/color-picker/swatches.js +26 -0
  55. package/dist/combobox/root/combobox-root.d.ts +43 -0
  56. package/dist/combobox/root/combobox-root.js +79 -15
  57. package/dist/command/root/command-root.d.ts +16 -1
  58. package/dist/command/root/command-root.js +22 -4
  59. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  60. package/dist/copy-button/root/copy-button-root.js +10 -3
  61. package/dist/data-table/index.d.ts +1 -1
  62. package/dist/data-table/index.js +1 -1
  63. package/dist/data-table/keys.d.ts +24 -0
  64. package/dist/data-table/keys.js +24 -0
  65. package/dist/data-table/root/data-table-root.d.ts +27 -18
  66. package/dist/data-table/root/data-table-root.js +20 -52
  67. package/dist/data-table/tree.d.ts +16 -1
  68. package/dist/data-table/tree.js +2 -3
  69. package/dist/date-input/root/date-input-root.d.ts +3 -1
  70. package/dist/date-input/root/date-input-root.js +18 -7
  71. package/dist/date-picker/root/date-picker-root.js +12 -6
  72. package/dist/dialog/description.js +15 -1
  73. package/dist/dialog/root/dialog-root.d.ts +8 -2
  74. package/dist/dialog/root/dialog-root.js +16 -1
  75. package/dist/divider/root/divider-root.d.ts +3 -0
  76. package/dist/divider/root/divider-root.js +2 -1
  77. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  78. package/dist/donut-chart/root/donut-chart-root.js +48 -1
  79. package/dist/drawer/reveal.d.ts +8 -0
  80. package/dist/drawer/reveal.js +1 -0
  81. package/dist/drawer/root/drawer-root.d.ts +59 -0
  82. package/dist/drawer/root/drawer-root.js +63 -4
  83. package/dist/drilldown/item/drilldown-item.js +1 -1
  84. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  85. package/dist/drilldown/root/drilldown-root.js +21 -3
  86. package/dist/element-events.generated.js +31 -5
  87. package/dist/empty/root/empty-root.d.ts +3 -1
  88. package/dist/empty/root/empty-root.js +3 -2
  89. package/dist/file-input/root/file-input-root.d.ts +69 -6
  90. package/dist/file-input/root/file-input-root.js +82 -19
  91. package/dist/file-input/screen.d.ts +2 -1
  92. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  93. package/dist/filter-input/menu/filter-menu.js +12 -4
  94. package/dist/filter-input/root/filter-input-root.d.ts +30 -6
  95. package/dist/filter-input/root/filter-input-root.js +1 -1
  96. package/dist/filter-input/suggest.d.ts +28 -3
  97. package/dist/filter-input/suggest.js +18 -8
  98. package/dist/format-date/root/format-date-root.d.ts +9 -16
  99. package/dist/format-date/root/format-date-root.js +10 -27
  100. package/dist/heatmap/root/heatmap-root.d.ts +24 -13
  101. package/dist/heatmap/root/heatmap-root.js +34 -12
  102. package/dist/icon/root/icon-root.d.ts +12 -1
  103. package/dist/icon/root/icon-root.js +21 -10
  104. package/dist/icon/settle.d.ts +7 -0
  105. package/dist/icon/settle.js +10 -0
  106. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  107. package/dist/image/root/image-root.d.ts +5 -1
  108. package/dist/image/root/image-root.js +1 -1
  109. package/dist/input/root/input-root.d.ts +12 -2
  110. package/dist/input/root/input-root.js +11 -2
  111. package/dist/kbd/root/kbd-root.d.ts +35 -1
  112. package/dist/kbd/root/kbd-root.js +23 -4
  113. package/dist/legend/root/legend-root.d.ts +55 -8
  114. package/dist/legend/root/legend-root.js +55 -13
  115. package/dist/lightbox/root/lightbox-root.d.ts +49 -6
  116. package/dist/lightbox/root/lightbox-root.js +86 -19
  117. package/dist/lightbox/zoom-controller.d.ts +59 -0
  118. package/dist/lightbox/zoom-controller.js +128 -0
  119. package/dist/lightbox/zoom.d.ts +22 -0
  120. package/dist/lightbox/zoom.js +16 -0
  121. package/dist/line-chart/root/line-chart-root.d.ts +22 -1
  122. package/dist/line-chart/root/line-chart-root.js +21 -1
  123. package/dist/list/item/list-item.d.ts +2 -0
  124. package/dist/list/item/list-item.js +11 -2
  125. package/dist/list/root/list-root.d.ts +62 -13
  126. package/dist/list/root/list-root.js +70 -13
  127. package/dist/list/selection.d.ts +37 -7
  128. package/dist/list/selection.js +16 -7
  129. package/dist/listbox/root/listbox-root.d.ts +37 -1
  130. package/dist/listbox/root/listbox-root.js +49 -3
  131. package/dist/loader/busy.d.ts +10 -0
  132. package/dist/loader/busy.js +11 -0
  133. package/dist/loader/root/loader-root.d.ts +9 -2
  134. package/dist/loader/root/loader-root.js +23 -3
  135. package/dist/megamenu/root/megamenu-root.d.ts +51 -10
  136. package/dist/megamenu/root/megamenu-root.js +76 -5
  137. package/dist/menu/item/menu-item.d.ts +51 -2
  138. package/dist/menu/item/menu-item.js +47 -23
  139. package/dist/menu/root/menu-root.d.ts +14 -0
  140. package/dist/menu/root/menu-root.js +2 -2
  141. package/dist/meter/root/meter-root.d.ts +20 -1
  142. package/dist/meter/root/meter-root.js +11 -15
  143. package/dist/navigation/root/navigation-root.d.ts +2 -1
  144. package/dist/navigation/root/navigation-root.js +2 -2
  145. package/dist/notifications/root/notifications-root.d.ts +10 -3
  146. package/dist/notifications/root/notifications-root.js +19 -7
  147. package/dist/number-input/root/number-input-root.d.ts +17 -8
  148. package/dist/number-input/root/number-input-root.js +2 -7
  149. package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
  150. package/dist/object-inspector/root/object-inspector-root.js +117 -76
  151. package/dist/object-inspector/rows.d.ts +18 -0
  152. package/dist/object-inspector/rows.js +33 -0
  153. package/dist/option/root/option-root.d.ts +5 -3
  154. package/dist/outline/root/outline-root.d.ts +18 -0
  155. package/dist/outline/root/outline-root.js +23 -5
  156. package/dist/pagination/size/pagination-size.d.ts +1 -0
  157. package/dist/pagination/size/pagination-size.js +1 -1
  158. package/dist/pin-input/code.d.ts +10 -0
  159. package/dist/pin-input/code.js +13 -0
  160. package/dist/pin-input/root/pin-input-root.d.ts +25 -1
  161. package/dist/pin-input/root/pin-input-root.js +10 -11
  162. package/dist/popover/hide-outside.d.ts +14 -0
  163. package/dist/popover/hide-outside.js +41 -0
  164. package/dist/popover/root/popover-root.d.ts +57 -7
  165. package/dist/popover/root/popover-root.js +58 -3
  166. package/dist/progress/root/progress-root.d.ts +20 -0
  167. package/dist/progress/root/progress-root.js +15 -15
  168. package/dist/qr-code/export.d.ts +26 -1
  169. package/dist/qr-code/export.js +14 -0
  170. package/dist/qr-code/root/qr-code-root.d.ts +19 -5
  171. package/dist/qr-code/root/qr-code-root.js +58 -9
  172. package/dist/quote/marks.d.ts +8 -0
  173. package/dist/quote/marks.js +5 -0
  174. package/dist/quote/root/quote-root.d.ts +14 -2
  175. package/dist/quote/root/quote-root.js +23 -1
  176. package/dist/radio/root/radio-root.d.ts +6 -2
  177. package/dist/radio/root/radio-root.js +6 -1
  178. package/dist/rating/root/rating-root.d.ts +9 -4
  179. package/dist/rating/root/rating-root.js +31 -7
  180. package/dist/rating/steps.d.ts +7 -0
  181. package/dist/rating/steps.js +9 -0
  182. package/dist/scatter-chart/fit.d.ts +15 -0
  183. package/dist/scatter-chart/fit.js +35 -0
  184. package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
  185. package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
  186. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  187. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  188. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  189. package/dist/scroll-area/scrollbar-controller.js +172 -0
  190. package/dist/scroll-area/scrollbar.d.ts +27 -0
  191. package/dist/scroll-area/scrollbar.js +9 -0
  192. package/dist/select/root/select-root.d.ts +15 -0
  193. package/dist/select/root/select-root.js +18 -6
  194. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  195. package/dist/skeleton/root/skeleton-root.js +4 -2
  196. package/dist/skip-link/root/skip-link-root.js +2 -2
  197. package/dist/slider/root/slider-root.d.ts +41 -4
  198. package/dist/slider/root/slider-root.js +23 -3
  199. package/dist/sparkline/readings.d.ts +18 -0
  200. package/dist/sparkline/readings.js +19 -0
  201. package/dist/sparkline/root/sparkline-root.d.ts +78 -7
  202. package/dist/sparkline/root/sparkline-root.js +118 -23
  203. package/dist/speed-dial/root/speed-dial-root.js +2 -2
  204. package/dist/splitter/root/splitter-root.d.ts +7 -12
  205. package/dist/splitter/root/splitter-root.js +209 -204
  206. package/dist/stat/root/stat-root.d.ts +14 -5
  207. package/dist/stat/root/stat-root.js +21 -5
  208. package/dist/steps/reach.d.ts +5 -0
  209. package/dist/steps/reach.js +3 -0
  210. package/dist/steps/root/steps-root.d.ts +49 -3
  211. package/dist/steps/root/steps-root.js +44 -5
  212. package/dist/steps/step/step.d.ts +7 -0
  213. package/dist/steps/step/step.js +7 -2
  214. package/dist/switch/root/switch-root.d.ts +10 -0
  215. package/dist/table/column/table-column.d.ts +0 -10
  216. package/dist/table/column/table-column.js +3 -19
  217. package/dist/table/root/table-root.d.ts +31 -10
  218. package/dist/table/root/table-root.js +2 -13
  219. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  220. package/dist/tabs/panel/tab-panel.js +34 -5
  221. package/dist/tabs/root/tabs-root.d.ts +12 -0
  222. package/dist/tabs/root/tabs-root.js +1 -1
  223. package/dist/tabs/tab/tab.d.ts +5 -0
  224. package/dist/tabs/tab/tab.js +5 -2
  225. package/dist/tag/group/tag-group.d.ts +31 -4
  226. package/dist/tag/group/tag-group.js +46 -7
  227. package/dist/tag/root/tag-root.js +9 -2
  228. package/dist/textarea/root/textarea-root.d.ts +28 -1
  229. package/dist/textarea/root/textarea-root.js +40 -1
  230. package/dist/time-input/root/time-input-root.d.ts +5 -1
  231. package/dist/time-input/root/time-input-root.js +16 -8
  232. package/dist/time-picker/root/time-picker-root.d.ts +18 -4
  233. package/dist/time-picker/root/time-picker-root.js +7 -10
  234. package/dist/time-picker/wheel-name.d.ts +9 -0
  235. package/dist/time-picker/wheel-name.js +15 -0
  236. package/dist/timeline/group/timeline-group.js +2 -2
  237. package/dist/toast/item/toast-item.d.ts +14 -1
  238. package/dist/toast/item/toast-item.js +22 -5
  239. package/dist/toast/root/toast-root.d.ts +6 -0
  240. package/dist/toast/root/toast-root.js +16 -1
  241. package/dist/toggle/group/toggle-group.d.ts +24 -3
  242. package/dist/toggle/group/toggle-group.js +34 -5
  243. package/dist/tooltip/root/tooltip-root.d.ts +13 -2
  244. package/dist/tooltip/root/tooltip-root.js +9 -1
  245. package/dist/tour/back.d.ts +10 -0
  246. package/dist/tour/back.js +8 -0
  247. package/dist/tour/root/tour-root.d.ts +30 -2
  248. package/dist/tour/root/tour-root.js +34 -8
  249. package/dist/tree/item/tree-item.d.ts +7 -3
  250. package/dist/tree/item/tree-item.js +3 -0
  251. package/dist/tree/root/tree-root.d.ts +24 -3
  252. package/dist/tree/root/tree-root.js +32 -13
  253. package/dist/tree/selection.js +2 -15
  254. package/dist/trend/root/trend-root.d.ts +43 -18
  255. package/dist/trend/root/trend-root.js +31 -6
  256. package/dist/video/media-events.d.ts +13 -18
  257. package/dist/video/media-events.js +1 -5
  258. package/dist/video/root/video-root.d.ts +18 -5
  259. package/dist/video/root/video-root.js +19 -10
  260. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  261. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  262. package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
  263. package/dist/virtual-list/fill.d.ts +0 -8
  264. package/dist/virtual-list/fill.js +1 -17
  265. package/dist/virtual-list/plan.d.ts +49 -0
  266. package/dist/virtual-list/plan.js +16 -0
  267. package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
  268. package/dist/virtual-list/root/virtual-list-root.js +183 -40
  269. package/lint.json +1 -1
  270. package/package.json +8 -8
  271. package/types/jsx.d.ts +4577 -835
  272. package/types/vue.d.ts +926 -168
  273. package/dist/chat/relative-clock.d.ts +0 -39
  274. package/dist/chat/relative-clock.js +0 -31
  275. package/dist/data-table/root/order.d.ts +0 -141
  276. package/dist/data-table/root/order.js +0 -76
  277. package/dist/tag/selection.d.ts +0 -10
  278. package/dist/tag/selection.js +0 -12
@@ -30,6 +30,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
30
30
  this.submenu = false;
31
31
  this.start = false;
32
32
  this.end = false;
33
+ this.description = false;
33
34
  this.readStart = () => {
34
35
  const slot = this.renderRoot.querySelector('slot[name="start"]');
35
36
  this.start = (slot?.assignedNodes().length ?? 0) > 0;
@@ -38,6 +39,10 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
38
39
  const slot = this.renderRoot.querySelector('slot[name="end"]');
39
40
  this.end = (slot?.assignedNodes().length ?? 0) > 0;
40
41
  };
42
+ this.readDescription = () => {
43
+ const slot = this.renderRoot.querySelector('slot[name="description"]');
44
+ this.description = (slot?.assignedNodes().length ?? 0) > 0;
45
+ };
41
46
  this.readSubmenu = () => {
42
47
  const slot = this.renderRoot.querySelector('slot[name="submenu"]');
43
48
  this.submenu = (slot?.assignedElements().length ?? 0) > 0;
@@ -74,11 +79,27 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
74
79
  this.submenu = named('submenu');
75
80
  this.start = named('start');
76
81
  this.end = named('end');
82
+ this.description = named('description');
77
83
  }
78
84
  firstUpdated(changed) {
79
85
  super.firstUpdated(changed);
80
86
  this.finishHydration();
81
87
  }
88
+ renderDescription() {
89
+ return html `<slot
90
+ id="description"
91
+ name="description"
92
+ aria-hidden="true"
93
+ ?data-empty=${!this.description}
94
+ @slotchange=${this.readDescription}
95
+ ></slot>`;
96
+ }
97
+ get describedBy() {
98
+ const ids = [this.description ? 'description' : '', this.end ? 'end-words' : '']
99
+ .filter((id) => id !== '')
100
+ .join(' ');
101
+ return ids === '' ? nothing : ids;
102
+ }
82
103
  renderEnd() {
83
104
  const kbd = this.tag('kbd');
84
105
  return html `<span part="end" ?data-empty=${!this.end && this.shortcut === ''}
@@ -86,10 +107,10 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
86
107
  ? nothing
87
108
  : staticHtml `<${kbd}
88
109
  part="shortcut"
89
- exportparts="kbd: shortcut-kbd"
110
+ exportparts="kbd: shortcut-kbd, key: shortcut-key, separator: shortcut-separator"
90
111
  aria-hidden="true"
91
112
  keys=${this.shortcut}
92
- ></${kbd}>`}<slot name="end" @slotchange=${this.readEnd}></slot
113
+ ></${kbd}>`}<slot id="end-words" name="end" aria-hidden="true" @slotchange=${this.readEnd}></slot
93
114
  ></span>`;
94
115
  }
95
116
  focus() {
@@ -152,6 +173,23 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
152
173
  this.tick();
153
174
  this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
154
175
  }
176
+ renderMark(submenu) {
177
+ if (submenu) {
178
+ return html `<slot name="chevron" aria-hidden="true"
179
+ ><svg part="mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
180
+ ${unsafeSVG(caretRight.content)}
181
+ </svg></slot
182
+ >`;
183
+ }
184
+ if (this.checked) {
185
+ return html `<slot name="check" aria-hidden="true"
186
+ ><svg part="mark" fill="currentColor" viewBox=${check.viewBox} aria-hidden="true">
187
+ ${unsafeSVG(check.content)}
188
+ </svg></slot
189
+ >`;
190
+ }
191
+ return nothing;
192
+ }
155
193
  render() {
156
194
  if (this.showingSubmenu) {
157
195
  return html `<slot name="submenu" @slotchange=${this.readSubmenu}></slot>`;
@@ -169,28 +207,9 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
169
207
  ><slot name="start" @slotchange=${this.readStart}></slot
170
208
  ></span>
171
209
  <slot></slot>
210
+ ${this.renderDescription()}
172
211
  ${this.renderEnd()}
173
- ${submenu
174
- ? html `<svg
175
- part="mark"
176
- data-mirror
177
- fill="currentColor"
178
- viewBox=${caretRight.viewBox}
179
- aria-hidden="true"
180
- >
181
- ${unsafeSVG(caretRight.content)}
182
- </svg>`
183
- : this.checked
184
- ? html `<svg
185
- part="mark"
186
- fill="currentColor"
187
- viewBox=${check.viewBox}
188
- aria-hidden="true"
189
- >
190
- ${unsafeSVG(check.content)}
191
- </svg>`
192
- :
193
- nothing}`;
212
+ ${this.renderMark(submenu)}`;
194
213
  return html `${linked
195
214
  ? html `<a
196
215
  part="item"
@@ -200,6 +219,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
200
219
  ?download=${this.download}
201
220
  role=${role}
202
221
  aria-checked=${checkedState}
222
+ aria-describedby=${this.describedBy}
203
223
  aria-haspopup=${submenu ? 'menu' : nothing}
204
224
  aria-keyshortcuts=${keys}
205
225
  tabindex="-1"
@@ -210,6 +230,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
210
230
  part="item"
211
231
  role=${role}
212
232
  aria-checked=${checkedState}
233
+ aria-describedby=${this.describedBy}
213
234
  aria-disabled=${this.disabled ? 'true' : nothing}
214
235
  aria-haspopup=${submenu ? 'menu' : nothing}
215
236
  aria-keyshortcuts=${keys}
@@ -265,6 +286,9 @@ __decorate([
265
286
  __decorate([
266
287
  state()
267
288
  ], HelixHeadlessMenuItem.prototype, "end", void 0);
289
+ __decorate([
290
+ state()
291
+ ], HelixHeadlessMenuItem.prototype, "description", void 0);
268
292
  HelixHeadlessMenuItem = __decorate([
269
293
  customElement('helix-headless-menu-item')
270
294
  ], HelixHeadlessMenuItem);
@@ -28,6 +28,20 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
28
28
  * its heading. Between runs of rows, a `<helix-divider announced>` is a
29
29
  * separator a screen reader announces.
30
30
  *
31
+ * Keys: Enter, Space or Down Arrow on the trigger opens the menu on its first
32
+ * row, and Up Arrow on its last. In the menu, Up and Down Arrow move between
33
+ * rows, Home and End go to the first and the last, a typed letter moves to
34
+ * the next row whose name starts with it, Enter and Space choose, Right Arrow
35
+ * opens a row's submenu and Left Arrow goes back, the two swapping on a
36
+ * right-to-left page, and Escape closes the menu and returns focus to the
37
+ * trigger. Tab closes it and moves on.
38
+ *
39
+ * While it is open, the surface carries the trigger's width as
40
+ * `--floating-anchor-inline-size` and the room left below it as
41
+ * `--floating-available-block-size`, as Radix's dropdown menu publishes its
42
+ * trigger's width, for a menu as wide as its trigger:
43
+ * `helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }`.
44
+ *
31
45
  * With `context`, the trigger is an area and the menu is its context menu: a
32
46
  * right-click, a long press, Shift+F10 or the menu key over the area opens it
33
47
  * at the pointer, or at the area's corner from the keyboard, as Radix's context
@@ -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, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, slottedWords, tellDisclosure, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, slottedWords, tellDisclosure, 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 } from 'lit/decorators.js';
@@ -29,7 +29,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
29
29
  items: () => (this.open ? this.items : []),
30
30
  reserved: () => ['ArrowLeft', 'ArrowRight'],
31
31
  selects: () => false,
32
- typeahead: (item) => slottedWords(item, ['']),
32
+ typeahead: typeaheadBy((item) => slottedWords(item, [''])),
33
33
  });
34
34
  this.aria = new AriaForwardController(this, {
35
35
  label: true,
@@ -71,6 +71,21 @@ export declare class HelixHeadlessMeter extends HelixElement {
71
71
  * no reader.
72
72
  */
73
73
  band?: MeterBand;
74
+ /**
75
+ * `Intl.NumberFormat` options the reading is written with, as React Aria's
76
+ * Meter and ProgressBar take them: a unit, a currency, or a number of
77
+ * decimals. Written as JSON in the attribute.
78
+ *
79
+ * ```html
80
+ * <helix-meter value="18" max="32" format-options='{"style":"unit","unit":"gigabyte"}'></helix-meter>
81
+ * ```
82
+ *
83
+ * A `percent` style writes the share of the range, and any other the value
84
+ * itself, so the example says "18 GB", and a value past an end as it is.
85
+ * Absent is a whole percentage. The words are announced as well as shown.
86
+ * `value-text` still wins.
87
+ */
88
+ formatOptions?: Intl.NumberFormatOptions;
74
89
  /**
75
90
  * Bottom of the high band.
76
91
  *
@@ -199,7 +214,11 @@ export declare class HelixHeadlessMeter extends HelixElement {
199
214
  * keeps an unbanded meter from being painted as good news.
200
215
  */
201
216
  private get computedBand();
202
- /** What the reading says, which is the consumer's words or a percentage. */
217
+ /**
218
+ * What the reading says: the consumer's words, or the reading in
219
+ * `format-options`, a share of the range for a percent and the value for
220
+ * anything else.
221
+ */
203
222
  private get text();
204
223
  protected willUpdate(changed: PropertyValues): void;
205
224
  /**
@@ -4,21 +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 { customElement, HelixElement, hostAria, slottedWords } from '@fusion.dev/helix-core';
7
+ import { customElement, formatNumber, HelixElement, hostAria, slottedWords, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing, svg } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
- const percents = new Map();
11
- const percent = (share, locale) => {
12
- let format = percents.get(locale);
13
- if (!format) {
14
- format = new Intl.NumberFormat(locale || undefined, {
15
- maximumFractionDigits: 0,
16
- style: 'percent',
17
- });
18
- percents.set(locale, format);
19
- }
20
- return format.format(share);
21
- };
10
+ const WHOLE_PERCENT = { maximumFractionDigits: 0, style: 'percent' };
22
11
  let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
23
12
  constructor() {
24
13
  super(...arguments);
@@ -80,7 +69,11 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
80
69
  return distance === 0 ? 'good' : distance === 1 ? 'fair' : 'poor';
81
70
  }
82
71
  get text() {
83
- return this.valueText || percent(this.ratio, this.locale);
72
+ const options = this.formatOptions;
73
+ return (this.valueText ||
74
+ (options && options.style !== 'percent'
75
+ ? formatNumber(Number.isFinite(this.value) ? this.value : this.span.min, this.locale, options)
76
+ : formatNumber(this.ratio, this.locale, options ?? WHOLE_PERCENT)));
84
77
  }
85
78
  willUpdate(changed) {
86
79
  super.willUpdate(changed);
@@ -90,7 +83,7 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
90
83
  this.internals.ariaValueMax = String(max);
91
84
  this.internals.ariaValueNow = String(this.reading);
92
85
  this.internals.ariaValueText =
93
- this.valueText || (this.beyond ? percent(this.ratio, this.locale) : null);
86
+ this.valueText || this.formatOptions !== undefined || this.beyond ? this.text : null;
94
87
  }
95
88
  renderRound() {
96
89
  const bounds = this.thresholds;
@@ -144,6 +137,9 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
144
137
  __decorate([
145
138
  property()
146
139
  ], HelixHeadlessMeter.prototype, "band", void 0);
140
+ __decorate([
141
+ property({ attribute: 'format-options', type: Object })
142
+ ], HelixHeadlessMeter.prototype, "formatOptions", void 0);
147
143
  __decorate([
148
144
  property({ type: Number })
149
145
  ], HelixHeadlessMeter.prototype, "high", void 0);
@@ -36,8 +36,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
36
36
  * @documentation https://fusion.dev/helix/components/navigation
37
37
  *
38
38
  * @slot - The destinations, as your own links.
39
+ * @slot indicator - A marker of your own, drawn inside the `indicator` part, where the current destination's place and size reach it.
39
40
  *
40
- * @csspart indicator - The marker that moves to the current destination.
41
+ * @csspart indicator - The marker that moves to the current destination. It carries the destination's place and size as `--indicator-x`, `--indicator-y`, `--indicator-inline-size` and `--indicator-block-size`, and `data-placed` once it has been placed.
41
42
  * @csspart nav - The navigation landmark.
42
43
  */
43
44
  export declare class HelixHeadlessNavigation extends HelixElement {
@@ -53,7 +53,7 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
53
53
  });
54
54
  }
55
55
  get items() {
56
- const slot = this.renderRoot.querySelector('slot');
56
+ const slot = this.renderRoot.querySelector('slot:not([name])');
57
57
  return (slot?.assignedElements() ?? []);
58
58
  }
59
59
  watch() {
@@ -80,7 +80,7 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
80
80
  }
81
81
  render() {
82
82
  return html `<nav part="nav" aria-label=${this.label}>
83
- <div part="indicator" aria-hidden="true"></div>
83
+ <div part="indicator" aria-hidden="true"><slot name="indicator"></slot></div>
84
84
  <slot @slotchange=${() => this.watch()}></slot>
85
85
  </nav>`;
86
86
  }
@@ -32,7 +32,8 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
32
32
  * **`load-more` adds a button after the list** that sends `helix-load-more`,
33
33
  * for a feed that holds one page of a longer list. Append the next page, set
34
34
  * `loading` while it is on its way, and take `load-more` off once there is
35
- * nothing more. The button is hidden while the feed is loading.
35
+ * nothing more. While the feed is loading the button stays, so focus stays on
36
+ * it, and it is `aria-disabled` and sends nothing.
36
37
  *
37
38
  * @since 0.1.0
38
39
  * @status stable
@@ -55,7 +56,7 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
55
56
  * @csspart live - A copy of the empty and loading messages, in a live region that screen readers announce when they change. Visually hidden in the styled tier.
56
57
  * @csspart loading - Shown while the feed is loading.
57
58
  * @csspart mark-all - The control that marks everything read.
58
- * @csspart more - The button after the list that asks for more, while `load-more` is set and the feed is not loading.
59
+ * @csspart more - The button after the list that asks for more, while `load-more` is set. It is `aria-disabled` while the feed is loading.
59
60
  *
60
61
  * @cssstate media - While a notification in the list holds something in its media slot, so every row keeps that column.
61
62
  */
@@ -260,7 +261,13 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
260
261
  private markEmpty;
261
262
  protected updated(changed: PropertyValues): void;
262
263
  protected render(): TemplateResult;
263
- /** Asks for the next page, for the `load-more` button. */
264
+ /**
265
+ * Asks for the next page, for the `load-more` button, unless a page is
266
+ * already on its way.
267
+ *
268
+ * The button stays while the feed is loading, marked `aria-disabled`, so
269
+ * focus stays on it: removed, it took focus with it to the body.
270
+ */
264
271
  private readonly askForMore;
265
272
  /**
266
273
  * Marks everything read, and keeps focus in the feed.
@@ -54,7 +54,9 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
54
54
  }
55
55
  };
56
56
  this.askForMore = () => {
57
- this.dispatchEvent(new HelixLoadMoreEvent());
57
+ if (!this.loading) {
58
+ this.dispatchEvent(new HelixLoadMoreEvent());
59
+ }
58
60
  };
59
61
  this.handleMarkAll = (event) => {
60
62
  const button = event.currentTarget;
@@ -151,9 +153,9 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
151
153
  rove() {
152
154
  const rows = this.reachable;
153
155
  const stop = rovingStop(rows, this.stopRow);
154
- const direct = this.rows;
155
- for (const row of this.items) {
156
- const position = direct.indexOf(row) + 1;
156
+ const items = this.items;
157
+ for (const row of items) {
158
+ const position = items.indexOf(row) + 1;
157
159
  whenHydrated(row, () => {
158
160
  row.stop = row === stop;
159
161
  row.position = this.total === undefined ? 0 : position;
@@ -210,13 +212,23 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
210
212
  </button>`
211
213
  : nothing}
212
214
  </div>
213
- <div part="list" role="list" aria-busy=${this.loading ? 'true' : nothing}>
215
+ <div
216
+ part="list"
217
+ role="list"
218
+ aria-busy=${this.loading ? 'true' : nothing}
219
+ aria-label=${this.label || nothing}
220
+ >
214
221
  <slot name="items" @slotchange=${this.handleSlotChange}></slot>
215
222
  ${this.renderStatus(hasItems)}
216
223
  </div>
217
224
  ${this.renderLive(hasItems)}
218
- ${this.loadMore && !this.loading
219
- ? html `<button part="more" type="button" @click=${this.askForMore}>
225
+ ${this.loadMore
226
+ ? html `<button
227
+ part="more"
228
+ type="button"
229
+ aria-disabled=${this.loading ? 'true' : nothing}
230
+ @click=${this.askForMore}
231
+ >
220
232
  ${this.loadMoreLabel}
221
233
  </button>`
222
234
  : nothing}
@@ -25,9 +25,10 @@ declare const HelixHeadlessNumberInput_base: (new (...args: any[]) => import("@f
25
25
  * The locale's group separators are read in every field, so `1,234` is a
26
26
  * number in `en-US`.
27
27
  *
28
- * On iOS and iPadOS the field is a text field described as a number field,
29
- * with no `role="spinbutton"`, which VoiceOver reads as a slider you cannot
30
- * type in. React Aria's NumberField does the same.
28
+ * On iOS and iPadOS the field is a plain text field, with no
29
+ * `role="spinbutton"`, which VoiceOver reads as a slider you cannot type in,
30
+ * and no role description, so VoiceOver says the field is required. React
31
+ * Aria's NumberField does the same.
31
32
  *
32
33
  * Validity follows the platform's rules: `min`, `max`, and `step` are checked
33
34
  * and reported through the host's own `setValidity`, under the platform's flag
@@ -36,6 +37,19 @@ declare const HelixHeadlessNumberInput_base: (new (...args: any[]) => import("@f
36
37
  * Stepping is separate from typing, so a number is not corrected while you type
37
38
  * it.
38
39
  *
40
+ * **Keyboard.** The field is one tab stop, and the stepper buttons are not in
41
+ * the tab order.
42
+ *
43
+ * | Key | What it does |
44
+ * |---|---|
45
+ * | Up, Down | Steps the value up or down by `step`. |
46
+ * | Page Up, Page Down | Steps by `large-step` steps, ten by default. |
47
+ * | Home, End | Goes to `min` or `max`, where there is one. Without one, moves the caret. |
48
+ * | Enter | Commits the typed number and submits the form, as a native field does. |
49
+ *
50
+ * The field has `role="spinbutton"` with `aria-valuenow`, `aria-valuemin`,
51
+ * `aria-valuemax`, and the formatted text in `aria-valuetext`.
52
+ *
39
53
  * @since 0.1.0
40
54
  * @status stable
41
55
  * @category forms
@@ -154,11 +168,6 @@ export declare class HelixHeadlessNumberInput extends HelixHeadlessNumberInput_b
154
168
  * Prevents editing. The value is still submitted with the form.
155
169
  */
156
170
  readOnly: boolean;
157
- /**
158
- * What the field is described as on iOS and iPadOS, where it carries no
159
- * spinbutton role. See the class description.
160
- */
161
- roleDescription: string;
162
171
  /**
163
172
  * Makes the label a grip that changes the value when it is dragged.
164
173
  *
@@ -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, appleTouch, valueAsNumber as asNumber, customElement, fillTemplate, formatNumber, numberAsValue as fromNumber, HelixFormElement, holdCaret, MixinControllerValue, MixinField, parseNumber, restoreValue, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, appleTouch, valueAsNumber as asNumber, customElement, fillTemplate, formatNumber, numberAsValue as fromNumber, HelixFormElement, holdCaret, MixinControllerValue, MixinField, parseNumber, restoreValue, submitImplicitly, } from '@fusion.dev/helix-core';
8
8
  import { minus, plus } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -24,7 +24,6 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
24
24
  this.locale = '';
25
25
  this.placeholder = '';
26
26
  this.readOnly = false;
27
- this.roleDescription = 'number field';
28
27
  this.scrub = false;
29
28
  this.step = 1;
30
29
  this.valueText = '';
@@ -138,7 +137,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
138
137
  };
139
138
  this.handleKeypress = (event) => {
140
139
  if (event.key === 'Enter' && !event.defaultPrevented) {
141
- this.submitImplicitly();
140
+ submitImplicitly(this.form);
142
141
  }
143
142
  };
144
143
  }
@@ -317,7 +316,6 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
317
316
  .value=${this.shown}
318
317
  type="text"
319
318
  role=${this.touchApple ? nothing : 'spinbutton'}
320
- aria-roledescription=${this.touchApple ? this.roleDescription : nothing}
321
319
  inputmode="decimal"
322
320
  autocomplete=${this.autocomplete || nothing}
323
321
  name=${this.name || nothing}
@@ -411,9 +409,6 @@ __decorate([
411
409
  __decorate([
412
410
  property({ attribute: 'readonly', reflect: true, type: Boolean })
413
411
  ], HelixHeadlessNumberInput.prototype, "readOnly", void 0);
414
- __decorate([
415
- property({ attribute: 'role-description' })
416
- ], HelixHeadlessNumberInput.prototype, "roleDescription", void 0);
417
412
  __decorate([
418
413
  property({ reflect: true, type: Boolean })
419
414
  ], HelixHeadlessNumberInput.prototype, "scrub", void 0);
@@ -15,13 +15,29 @@ import { type Row } from '../rows.js';
15
15
  * works with server rendering and with React hydration, which skips object
16
16
  * properties. `value` wins when both are set.
17
17
  *
18
- * The tree is one tab stop. Up and Down move between rows, Right opens a branch
19
- * or moves into it, Left closes it or moves to its parent, and Home and End
20
- * move to the first and last rows. Typing moves to the next row whose key
21
- * starts with what was typed, and `*` opens every branch beside the active
22
- * row. Focus stays on the tree, and `aria-activedescendant` marks the active
23
- * row. Each row carries its real level, position, and set size, including in
24
- * a windowed tree.
18
+ * **Keyboard.** The tree is one tab stop, and focus moves from row to row.
19
+ *
20
+ * | Key | What it does |
21
+ * |---|---|
22
+ * | Down, Up | Moves to the next or the previous row. |
23
+ * | Right | Opens a closed branch, or moves into an open one. Left on a right-to-left page. |
24
+ * | Left | Closes an open branch, or moves to the parent. Right on a right-to-left page. |
25
+ * | Home, End | Moves to the first or the last row. |
26
+ * | Enter, Space | Opens or closes a branch. |
27
+ * | `*` | Opens every branch beside the active row. |
28
+ * | A letter or a word | Moves to the next row whose key starts with what you typed. |
29
+ * | Command+C, Control+C | Copies the active row, where no text is selected. |
30
+ *
31
+ * The tree is a `treegrid`, as React Aria's Tree is: each entry is a `row` with
32
+ * one cell, and carries its real level, position, and set size, including in a
33
+ * windowed tree. Nothing in it is chosen, so no row carries `aria-selected`,
34
+ * and a focused row is not announced as selected.
35
+ *
36
+ * A reader opening or closing a branch sends `helix-before-open` or
37
+ * `helix-before-close`, which you can cancel, and then `toggle` with
38
+ * `newState` and `oldState`, as `<details>` does. The branch is the active
39
+ * row, and `expanded` holds every open branch. `*` asks once for all the
40
+ * branches it opens. A script writing `expanded` or `active` sends nothing.
25
41
  *
26
42
  * `active` is the active row's path, written the way a JSON Pointer writes it:
27
43
  * the empty string for the root and `/meta/tags/0` for an entry under it.
@@ -60,9 +76,12 @@ import { type Row } from '../rows.js';
60
76
  *
61
77
  * @event {HelixActivateEvent} helix-activate - The active row moved, by a key or a click. The detail's `value` is its path.
62
78
  * @event {HelixBeforeActivateEvent} helix-before-activate - The active row is about to move, with its new path. Cancelable: cancel it to keep the row where it is.
79
+ * @event {HelixBeforeCloseEvent} helix-before-close - A reader is about to close the active branch. Cancelable: cancel it to keep the branch open.
80
+ * @event {HelixBeforeOpenEvent} helix-before-open - A reader is about to open the active branch, or `*` the branches beside it. Cancelable: cancel it to keep them closed.
63
81
  * @event {HelixCopyEvent} helix-copy - A value was put on the clipboard, from the copy button or the keyboard.
64
82
  * @event {HelixFilterEvent} helix-filter - Text was typed in the filter field, with what it now holds. Cancelable: cancel it to keep the filter as it was.
65
83
  * @event {HelixFilteredEvent} helix-filtered - The filter field changed `filter`, which now holds the text.
84
+ * @event {ToggleEvent} toggle - A reader opened or closed a branch, with `newState` and `oldState`. `expanded` holds every open branch.
66
85
  *
67
86
  * @csspart after - The space the rows below the drawn rows would take, when `windowed` is set.
68
87
  * @csspart before - The space the rows above the drawn rows would take, when `windowed` is set.
@@ -90,14 +109,14 @@ import { type Row } from '../rows.js';
90
109
  * @csspart live - How many entries a filter matched, in a region that screen readers announce when it changes. Drawn from the first filter on. Visually hidden in the styled tier.
91
110
  * @csspart null - A `null`.
92
111
  * @csspart number - A number.
93
- * @csspart row - One entry, as a tree item.
94
- * @csspart row-active - The entry the keyboard is on. Set alongside `row`.
112
+ * @csspart row - One entry, as a row of the tree grid, which takes focus.
113
+ * @csspart row-active - The entry the keyboard is on, which holds the tab stop. Set alongside `row`.
95
114
  * @csspart row-match - An entry whose key or value holds the filter. Set alongside `row`.
96
115
  * @csspart search-field - The field that sets `filter`, with `filterable`.
97
116
  * @csspart string - A string, in quotes.
98
117
  * @csspart summary - The brackets that stand for a branch's contents.
99
118
  * @csspart toggle - The caret on a branch. It points down when the branch is open and sideways when it is closed.
100
- * @csspart tree - The tree, which is the element that receives focus.
119
+ * @csspart tree - The tree grid that holds the rows.
101
120
  *
102
121
  * @cssproperty --object-inspector-level - How deep a row is, from 0 at the root, for indenting it.
103
122
  */
@@ -230,6 +249,10 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
230
249
  private found;
231
250
  /** Set by a keyboard move, so the next render brings the active row into view. */
232
251
  private revealing;
252
+ /** Set by a reader's move, so the next render moves focus to the active row. */
253
+ private focusing;
254
+ /** Whether a row held focus as this update began, so a row the render moved gets it back. */
255
+ private hadFocus;
233
256
  /** What has been typed toward a key, and when the last letter came. */
234
257
  private typed;
235
258
  /** The branches of the last value seen, by path, so a new value can tell old ones from new. */
@@ -266,16 +289,17 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
266
289
  /** Opens the branches around each path, where the value has them. */
267
290
  private openAround;
268
291
  protected willUpdate(changed: PropertyValues): void;
269
- /**
270
- * Where the active row goes once the rows have moved: onto `path` where it
271
- * is still shown, onto the first match where a filter just hid it, and
272
- * otherwise onto the nearest branch around it that is.
273
- */
274
- private place;
275
292
  /** Says how many entries the filter matched, and nothing for an empty one. */
276
293
  private tell;
277
294
  protected firstUpdated(changed: PropertyValues): void;
278
295
  protected updated(changed: PropertyValues): void;
296
+ /**
297
+ * Moves focus to the active row, once it is drawn.
298
+ *
299
+ * After a reader's move only, so a script writing `active` does not take
300
+ * focus from wherever the reader is.
301
+ */
302
+ private focusActive;
279
303
  private load;
280
304
  /**
281
305
  * Brings the active row into the box.
@@ -292,6 +316,20 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
292
316
  private reveal;
293
317
  /** What copying takes: a branch as indented JSON, a string as itself. */
294
318
  private copyable;
319
+ /**
320
+ * Asks to open or close branches, and then does and says so:
321
+ * `helix-before-open` or `helix-before-close`, which a listener can cancel,
322
+ * then `toggle`. A reader's act only. Returns whether they moved.
323
+ */
324
+ private requestOpen;
325
+ /**
326
+ * Says a branch opened or closed under the platform's own name and in its
327
+ * shape: `toggle` with `newState` and `oldState`, not bubbling, as
328
+ * `<details>` sends it and as the open mixin does for the families whose
329
+ * open state it owns. A real `ToggleEvent` where the platform has one, and a
330
+ * plain event carrying the same two fields where it does not.
331
+ */
332
+ private announceToggle;
295
333
  private toggle;
296
334
  /**
297
335
  * Moves the active row, asking first: `helix-before-activate` with the path,
@@ -299,8 +337,6 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
299
337
  */
300
338
  private move;
301
339
  private readonly handleKeydown;
302
- /** Opens every branch at the active row's level under the same parent, as `*` asks. */
303
- private openSiblings;
304
340
  /**
305
341
  * Moves to the next row whose key starts with what was typed.
306
342
  *
@@ -313,7 +349,7 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
313
349
  private handleRowClick;
314
350
  /** Text typed in the filter field, asked for before the tree narrows to it. */
315
351
  private readonly handleFilterInput;
316
- /** Down from the filter field goes to the tree, where the matches are. */
352
+ /** Down from the filter field goes to the active row, where the matches are. */
317
353
  private readonly handleFilterKeydown;
318
354
  private renderValue;
319
355
  /**
@@ -321,17 +357,29 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
321
357
  *
322
358
  * **`row-active` and no attribute beside it.** Which row the keys are on is
323
359
  * drawn by a sheet and by nothing else: the accessibility tree hears it from
324
- * `aria-activedescendant` on the tree, which points at this row's id, so an
325
- * attribute would be a second spelling with no reader. The name is the one a
326
- * consumer can reach, nothing being able to follow `::part()` with an
327
- * attribute selector.
360
+ * focus, which the row holds, so an attribute would be a second spelling with
361
+ * no reader. The name is the one a consumer can reach, nothing being able to
362
+ * follow `::part()` with an attribute selector.
328
363
  *
329
- * **`aria-selected="false"` on every row**, because nothing here is chosen.
330
- * Chromium takes the active descendant of a single-selection tree as selected
331
- * when no row says otherwise, so every arrow press was also announced as a
332
- * selection. An explicit false is the one thing that turns that off.
364
+ * **A `row` of a `treegrid` with one cell, focused itself, and no
365
+ * `aria-selected`**, because nothing here is chosen. Chromium takes the
366
+ * focused item of a single-selection `tree` as selected, by focus or by
367
+ * `aria-activedescendant` (measured), so every arrow press was also announced
368
+ * as a selection, and `aria-selected="false"` on every row was the one way to
369
+ * turn it off. A row of a tree grid is not selected by focus, which is why
370
+ * React Aria's Tree is one. The cell is `display: contents`, so the row lays
371
+ * out its text as it did.
333
372
  */
334
373
  private renderRow;
374
+ /** Whether a row of the tree holds focus. */
375
+ private hasFocusedRow;
376
+ /**
377
+ * A row that takes focus some other way than the keys, from a script or a
378
+ * screen reader, becomes the active row, so focus and the keys agree.
379
+ */
380
+ private readonly handleFocusIn;
381
+ /** A row kept drawn for focus is let go once focus leaves it. */
382
+ private readonly handleFocusOut;
335
383
  /** The copy button, behind the seam Code Block's uses, so each tier renders its own. */
336
384
  protected renderCopyButton(row: Row | undefined): TemplateResult;
337
385
  protected render(): TemplateResult;