@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
@@ -4,123 +4,114 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, customElement, fillTemplate, HelixCompleteEvent, HelixFormElement, MixinControllerValue, MixinField, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, customElement, fillTemplate, HelixCompleteEvent, HelixFormElement, MixinControllerValue, MixinField, restoreValue, submitImplicitly, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
- import { property } from 'lit/decorators.js';
9
+ import { property, state } from 'lit/decorators.js';
10
+ import { cleanCode, overwriteCode, readTyped, } from '../code.js';
10
11
  import { separatorsAfter } from '../format.js';
12
+ const UNSEEN = 'position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;font-size:16px';
13
+ const keepFocus = (event) => event.preventDefault();
11
14
  let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerValue(MixinField(HelixFormElement)) {
12
15
  constructor() {
13
16
  super(...arguments);
14
17
  this.aria = new AriaForwardController(this, {
15
- target: () => this.partNamed('field'),
18
+ target: () => this.control,
16
19
  });
17
20
  this.announcesInput = true;
18
21
  this.autocomplete = 'one-time-code';
19
22
  this.autosubmit = false;
23
+ this.case = 'preserve';
20
24
  this.cellLabel = 'Character {index} of {length}';
21
25
  this.format = '';
22
26
  this.length = 6;
23
27
  this.mask = false;
28
+ this.maskCharacter = '•';
24
29
  this.placeholder = '';
25
30
  this.readOnly = false;
26
31
  this.type = 'numeric';
32
+ this.active = -1;
33
+ this.pressedAt = undefined;
27
34
  this.handleInput = (event) => {
28
35
  event.stopPropagation();
29
- const cell = event.target;
30
- const at = this.cells.indexOf(cell);
31
- if (at === -1) {
32
- return;
33
- }
34
- if (cell.value === '') {
35
- const characters = this.characters;
36
- characters[at] = '';
37
- this.requestValue(characters.join(''));
38
- this.updateComplete.then(() => {
39
- this.paint();
40
- this.cells[at]?.focus();
41
- });
42
- return;
43
- }
44
- this.write(at, cell.value);
45
- this.updateComplete.then(() => this.paint());
36
+ const control = event.target;
37
+ this.take(readTyped(control.value, control.selectionStart ?? control.value.length, this.type, this.case, this.count));
46
38
  };
47
39
  this.handlePaste = (event) => {
48
- const cell = event.target;
49
- const at = this.cells.indexOf(cell);
50
- if (at === -1 || this.isDisabled || this.readOnly) {
40
+ event.preventDefault();
41
+ const control = this.control;
42
+ if (!control || this.isDisabled || this.readOnly) {
51
43
  return;
52
44
  }
53
- event.preventDefault();
54
- this.write(at, event.clipboardData?.getData('text') ?? '');
45
+ const text = cleanCode(event.clipboardData?.getData('text') ?? '', this.type, this.case);
46
+ if (text === '') {
47
+ return;
48
+ }
49
+ const start = control.selectionStart ?? this.end;
50
+ const end = control.selectionEnd ?? start;
51
+ const kept = end - start > 1 ? this.value.slice(0, start) + this.value.slice(end) : this.value;
52
+ this.take(overwriteCode(kept, start, text, this.count));
55
53
  };
56
54
  this.handleKeydown = (event) => {
57
- const cell = event.target;
58
- const at = this.cells.indexOf(cell);
59
- if (at === -1 || this.isDisabled || this.readOnly) {
55
+ if (event.isComposing || this.isDisabled) {
60
56
  return;
61
57
  }
62
- const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
63
- const to = event.key === 'Home'
64
- ? 0
65
- : event.key === 'End'
66
- ? Math.min(this.value.length, this.count - 1)
67
- : at + step;
68
- if (event.key === 'Delete' && at < this.value.length) {
69
- const characters = this.characters;
70
- characters.splice(at, 1);
71
- this.requestValue(characters.join('').replace(/\s+$/, ''));
72
- this.updateComplete.then(() => {
73
- this.paint();
74
- this.cells[at]?.focus();
75
- });
76
- }
77
- else if (event.key === 'Backspace' && cell.value === '' && at > 0) {
78
- const characters = this.characters;
79
- characters[at - 1] = '';
80
- this.requestValue(characters.join('').replace(/\s+$/, ''));
81
- this.updateComplete.then(() => {
82
- this.paint();
83
- this.cells[at - 1]?.focus();
84
- });
85
- }
86
- else if (to !== at && to >= 0 && to < this.count) {
87
- this.cells[to]?.focus();
88
- this.cells[to]?.select();
58
+ if (this.readOnly) {
59
+ if (event.key === 'Backspace' || event.key === 'Delete') {
60
+ event.preventDefault();
61
+ }
62
+ return;
89
63
  }
90
- else {
64
+ const to = event.key === 'ArrowRight'
65
+ ? this.caretBox + 1
66
+ : event.key === 'ArrowLeft'
67
+ ? this.caretBox - 1
68
+ : event.key === 'Home'
69
+ ? 0
70
+ : event.key === 'End'
71
+ ? this.end
72
+ : undefined;
73
+ if (to === undefined) {
91
74
  return;
92
75
  }
93
76
  event.preventDefault();
77
+ this.active = Math.max(0, Math.min(to, this.end));
78
+ this.placeCaret(true);
94
79
  };
95
- this.committed = '';
96
- this.handleFocus = (event) => {
97
- ;
98
- event.target.select();
99
- };
100
- this.within = false;
101
- this.handleFocusIn = () => {
102
- if (this.within) {
80
+ this.handlePress = (event) => {
81
+ const control = this.control;
82
+ if (!control || this.isDisabled) {
103
83
  return;
104
84
  }
105
- this.within = true;
106
- this.committed = this.value;
107
- };
108
- this.handleFocusOut = (event) => {
109
- if (this.cells.includes(event.relatedTarget)) {
85
+ const boxes = [...this.renderRoot.querySelectorAll('[part~="cell"]')];
86
+ const box = event.target.closest('[part~="cell"]');
87
+ const at = box ? boxes.indexOf(box) : this.end;
88
+ if (this.shadowRoot?.activeElement === control) {
89
+ if (!this.readOnly) {
90
+ this.active = Math.min(at, this.end);
91
+ this.placeCaret(true);
92
+ }
110
93
  return;
111
94
  }
112
- this.within = false;
95
+ this.pressedAt = at;
96
+ control.focus();
97
+ };
98
+ this.committed = '';
99
+ this.handleFocus = () => {
100
+ this.committed = this.value;
101
+ this.active = this.readOnly ? -1 : Math.min(this.pressedAt ?? this.end, this.end);
102
+ this.pressedAt = undefined;
103
+ this.placeCaret(true);
104
+ };
105
+ this.handleBlur = () => {
106
+ this.active = -1;
113
107
  this.commit();
114
108
  };
115
109
  this.handleKeypress = (event) => {
116
110
  if (event.key === 'Enter' && !event.defaultPrevented) {
117
- this.submitImplicitly();
111
+ submitImplicitly(this.form);
118
112
  }
119
113
  };
120
114
  }
121
- get namedControl() {
122
- return this.partNamed('field');
123
- }
124
115
  static { this.shadowRootOptions = {
125
116
  ...HelixFormElement.shadowRootOptions,
126
117
  delegatesFocus: true,
@@ -128,56 +119,45 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
128
119
  get count() {
129
120
  return Math.max(1, Math.floor(this.length) || 1);
130
121
  }
131
- get cells() {
132
- return [...this.renderRoot.querySelectorAll('[part="cell"]')];
122
+ get control() {
123
+ return this.partNamed('control');
133
124
  }
134
- get characters() {
135
- return Array.from({ length: this.count }, (_, at) => this.value[at] ?? '');
125
+ get end() {
126
+ return Math.min(this.value.length, this.count - 1);
136
127
  }
137
- clean(text) {
138
- const trimmed = text.trim();
139
- if (this.type === 'numeric') {
140
- return trimmed.replace(/\D/g, '');
141
- }
142
- if (this.type === 'alphanumeric') {
143
- return trimmed.replace(/[^0-9A-Za-z]/g, '');
144
- }
145
- return trimmed;
128
+ get caretBox() {
129
+ return this.active < 0 ? -1 : Math.min(this.active, this.end);
146
130
  }
147
- write(from, text) {
148
- const cleaned = this.clean(text);
149
- if (cleaned === '') {
150
- return;
131
+ take({ caret, code }) {
132
+ const applied = this.requestValue(code);
133
+ const control = this.control;
134
+ if (control) {
135
+ restoreValue(control, this.value);
151
136
  }
152
- const start = Math.min(from, this.value.length);
153
- const characters = this.characters;
154
- for (let at = 0; at < cleaned.length && start + at < this.count; at += 1) {
155
- characters[start + at] = cleaned[at];
137
+ if (this.active >= 0 && applied) {
138
+ this.active = caret;
156
139
  }
157
- const next = characters.join('');
158
- const filled = Math.min(this.count - 1, start + cleaned.length);
159
- const applied = this.requestValue(next);
160
- this.updateComplete.then(() => {
161
- this.paint();
162
- this.cells[filled]?.focus();
163
- this.cells[filled]?.select();
164
- if (applied && this.value === next && next.length === this.count) {
165
- this.dispatchEvent(new HelixCompleteEvent({ value: next }));
166
- this.commit();
167
- if (this.autosubmit) {
168
- this.submitImplicitly();
169
- }
140
+ this.placeCaret(true);
141
+ if (applied && this.value === code && code.length === this.count) {
142
+ this.dispatchEvent(new HelixCompleteEvent({ value: code }));
143
+ this.commit();
144
+ if (this.autosubmit) {
145
+ submitImplicitly(this.form);
170
146
  }
171
- });
147
+ }
172
148
  }
173
- paint() {
174
- const characters = this.characters;
175
- for (const [at, cell] of this.cells.entries()) {
176
- const want = characters[at] ?? '';
177
- if (cell.value !== want) {
178
- cell.value = want;
179
- }
149
+ placeCaret(force = false) {
150
+ const control = this.control;
151
+ const at = this.caretBox;
152
+ if (!control || at < 0) {
153
+ return;
154
+ }
155
+ const start = control.selectionStart ?? 0;
156
+ const end = control.selectionEnd ?? start;
157
+ if (!force && end - start > 1) {
158
+ return;
180
159
  }
160
+ control.setSelectionRange(at, at < this.value.length ? at + 1 : at);
181
161
  }
182
162
  commit() {
183
163
  if (this.value === this.committed) {
@@ -188,34 +168,34 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
188
168
  }
189
169
  sync() {
190
170
  this.internals.setFormValue(this.value);
191
- const first = this.cells[0];
192
- if (!first) {
171
+ const control = this.control;
172
+ if (!control) {
193
173
  return;
194
174
  }
195
175
  if (this.required && this.value === '') {
196
- this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage || 'Please fill in this field.', first);
176
+ this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage || 'Please fill in this field.', control);
197
177
  }
198
178
  else if (this.value !== '' && this.value.length < this.count) {
199
179
  this.internals.setValidity({ tooShort: true }, fillTemplate(this.tooShortMessage || 'Please enter all {length} characters.', {
200
180
  length: this.count,
201
- }), first);
181
+ }), control);
202
182
  }
203
183
  else {
204
- this.internals.setValidity({}, '', first);
184
+ this.internals.setValidity({}, '', control);
205
185
  }
206
186
  this.refreshFeedback();
207
187
  }
208
188
  focus(options) {
209
- const cells = this.cells;
210
- const at = Math.min(this.value.length, cells.length - 1);
211
- cells[at]?.focus(options);
189
+ this.control?.focus(options);
212
190
  }
213
191
  clear() {
214
192
  this.requestValue('');
215
- this.updateComplete.then(() => {
216
- this.paint();
217
- this.cells[0]?.focus();
218
- });
193
+ const control = this.control;
194
+ if (control) {
195
+ restoreValue(control, this.value);
196
+ this.pressedAt = 0;
197
+ control.focus();
198
+ }
219
199
  }
220
200
  firstUpdated(changed) {
221
201
  super.firstUpdated(changed);
@@ -223,44 +203,63 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
223
203
  }
224
204
  updated(changed) {
225
205
  super.updated(changed);
226
- this.paint();
206
+ this.toggleState('complete', this.value.length >= this.count);
227
207
  this.sync();
208
+ this.placeCaret();
228
209
  }
229
210
  get blocksImplicitSubmission() {
230
211
  return true;
231
212
  }
213
+ renderBox(character, at) {
214
+ const caret = at === this.caretBox;
215
+ const content = character !== ''
216
+ ? this.mask
217
+ ? this.maskCharacter
218
+ : character
219
+ : caret
220
+ ? html `<span part="caret"></span>`
221
+ : this.placeholder
222
+ ? html `<span part="placeholder">${this.placeholder}</span>`
223
+ : nothing;
224
+ return html `<div
225
+ part="cell${caret ? ' cell-active' : ''}${character === '' ? '' : ' cell-filled'}"
226
+ aria-hidden="true"
227
+ >${content}</div>`;
228
+ }
232
229
  render() {
233
- const characters = this.characters;
234
230
  const separators = separatorsAfter(this.format, this.count);
235
- return html `${this.renderGroupLabel()}
231
+ return html `${this.renderLabel()}
236
232
  <div
237
233
  dir="ltr"
238
234
  part="field"
239
- role="group"
240
- aria-describedby=${this.describedBy ?? nothing}
241
- aria-labelledby=${this.labeled ? this.labelId : nothing}
242
- @focusin=${this.handleFocusIn}
243
- @focusout=${this.handleFocusOut}
235
+ @click=${this.handlePress}
236
+ @mousedown=${keepFocus}
244
237
  >
245
- ${characters.map((character, at) => html `<input
246
- part="cell"
247
- .value=${character}
248
- type=${this.mask ? 'password' : 'text'}
249
- placeholder=${this.placeholder || nothing}
250
- inputmode=${this.type === 'numeric' ? 'numeric' : 'text'}
251
- autocomplete=${at === 0 ? this.autocomplete || nothing : 'off'}
252
- aria-label=${fillTemplate(this.cellLabel, { index: at + 1, length: this.count })}
253
- aria-invalid=${this.invalidity ?? nothing}
254
- ?disabled=${this.isDisabled}
255
- ?readonly=${this.readOnly}
256
- @focus=${this.handleFocus}
257
- @input=${this.handleInput}
258
- @keydown=${this.handleKeydown}
259
- @keypress=${this.handleKeypress}
260
- @paste=${this.handlePaste}
261
- />${separators[at]
262
- ? html `<span part="separator" aria-hidden="true">${separators[at]}</span>`
263
- : nothing}`)}
238
+ <input
239
+ part="control"
240
+ id=${this.controlId}
241
+ style=${UNSEEN}
242
+ .value=${this.value}
243
+ type=${this.mask ? 'password' : 'text'}
244
+ inputmode=${this.type === 'numeric' ? 'numeric' : 'text'}
245
+ autocomplete=${this.autocomplete || nothing}
246
+ aria-describedby=${this.describedBy ?? nothing}
247
+ aria-invalid=${this.invalidity ?? nothing}
248
+ aria-required=${this.required ? 'true' : nothing}
249
+ ?disabled=${this.isDisabled}
250
+ ?readonly=${this.readOnly}
251
+ @blur=${this.handleBlur}
252
+ @focus=${this.handleFocus}
253
+ @input=${this.handleInput}
254
+ @keydown=${this.handleKeydown}
255
+ @keypress=${this.handleKeypress}
256
+ @paste=${this.handlePaste}
257
+ />${Array.from({ length: this.count }, (_, at) => {
258
+ const separator = separators[at];
259
+ return html `${this.renderBox(this.value[at] ?? '', at)}${separator
260
+ ? html `<span part="separator" aria-hidden="true">${separator}</span>`
261
+ : nothing}`;
262
+ })}
264
263
  </div>
265
264
  ${this.renderHint()}${this.renderFeedback()}`;
266
265
  }
@@ -271,6 +270,9 @@ __decorate([
271
270
  __decorate([
272
271
  property({ type: Boolean })
273
272
  ], HelixHeadlessPinInput.prototype, "autosubmit", void 0);
273
+ __decorate([
274
+ property()
275
+ ], HelixHeadlessPinInput.prototype, "case", void 0);
274
276
  __decorate([
275
277
  property({ attribute: 'cell-label' })
276
278
  ], HelixHeadlessPinInput.prototype, "cellLabel", void 0);
@@ -283,6 +285,9 @@ __decorate([
283
285
  __decorate([
284
286
  property({ reflect: true, type: Boolean })
285
287
  ], HelixHeadlessPinInput.prototype, "mask", void 0);
288
+ __decorate([
289
+ property({ attribute: 'mask-character' })
290
+ ], HelixHeadlessPinInput.prototype, "maskCharacter", void 0);
286
291
  __decorate([
287
292
  property()
288
293
  ], HelixHeadlessPinInput.prototype, "placeholder", void 0);
@@ -295,6 +300,9 @@ __decorate([
295
300
  __decorate([
296
301
  property()
297
302
  ], HelixHeadlessPinInput.prototype, "type", void 0);
303
+ __decorate([
304
+ state()
305
+ ], HelixHeadlessPinInput.prototype, "active", void 0);
298
306
  HelixHeadlessPinInput = __decorate([
299
307
  customElement('helix-headless-pin-input')
300
308
  ], HelixHeadlessPinInput);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Hides everything on the page from assistive technology except `kept`, and
3
+ * returns a function that shows it again.
4
+ *
5
+ * Climbs from each kept element to the top of the document, through any shadow
6
+ * root it is in, and marks every sibling on the way that holds no kept element
7
+ * with `aria-hidden="true"`. What already says `aria-hidden` is left as it is,
8
+ * and given back as it was. Live regions are kept, so a message that arrives
9
+ * while the page is hidden is still announced.
10
+ *
11
+ * What a modal popover rests on: `Tab` is kept inside the panel, and this keeps
12
+ * a screen reader's virtual cursor there too.
13
+ */
14
+ export declare const hideOutside: (kept: readonly Element[]) => (() => void);
@@ -0,0 +1,34 @@
1
+ import { deepContains } from '@fusion.dev/helix-core';
2
+ const KEEP = 'script, style, template, link, meta, [aria-live], [role="alert"], [role="log"], [role="status"]';
3
+ export const hideOutside = (kept) => {
4
+ const hidden = [];
5
+ const holds = (element) => kept.some((one) => deepContains(element, one));
6
+ const seen = new Set();
7
+ for (const start of kept) {
8
+ let node = start;
9
+ while (node && node !== document.documentElement) {
10
+ const parent = node.parentNode;
11
+ if (!parent || seen.has(parent)) {
12
+ break;
13
+ }
14
+ seen.add(parent);
15
+ for (const sibling of parent.children ?? []) {
16
+ if (sibling === node ||
17
+ holds(sibling) ||
18
+ sibling.matches(KEEP) ||
19
+ sibling.hasAttribute('aria-hidden')) {
20
+ continue;
21
+ }
22
+ sibling.setAttribute('aria-hidden', 'true');
23
+ hidden.push(sibling);
24
+ }
25
+ node = parent instanceof ShadowRoot ? parent.host : parent;
26
+ }
27
+ }
28
+ return () => {
29
+ for (const one of hidden) {
30
+ one.removeAttribute('aria-hidden');
31
+ }
32
+ hidden.length = 0;
33
+ };
34
+ };
@@ -1,4 +1,4 @@
1
- import { AriaForwardController, CommandController, HelixElement, type Placement } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, CommandController, HelixElement, OpenPhaseController, type Placement } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
@@ -9,9 +9,11 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
9
9
  * commands, `Select` holds options, and `Tooltip` holds a description. Popover
10
10
  * holds any content you put in it, so it has no keyboard handling of its own.
11
11
  *
12
- * The trigger is slotted and stays your own element. The popover writes nothing
13
- * onto it, including `aria-expanded`, `id`, and `tabindex`, because changing
14
- * your markup after upgrade causes a React hydration mismatch.
12
+ * The trigger is slotted and stays your own element. A Helix trigger is told
13
+ * whether the popover is open inside its own shadow root. On a plain element,
14
+ * such as a `<button>`, the popover writes `aria-expanded` only once a reader
15
+ * has pressed it, which is after any hydration, and never where you wrote
16
+ * `aria-expanded` yourself. It writes nothing else onto your markup.
15
17
  *
16
18
  * The panel is in the top layer through the popover API, so it needs no
17
19
  * `z-index`, and an ancestor with `overflow: hidden`, `transform`, `filter`, or
@@ -28,7 +30,9 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
28
30
  *
29
31
  * `modal` keeps `Tab` inside the panel while it is open and says so with
30
32
  * `aria-modal`, for a panel that has to be answered before the page goes on.
31
- * Without it the popover does not trap focus.
33
+ * The rest of the page is hidden from screen readers with `aria-hidden` while
34
+ * it is open, so the virtual cursor stays in the panel too. Without it the
35
+ * popover does not trap focus.
32
36
  *
33
37
  * The panel's name is `label` when you set it. Otherwise it is the first
34
38
  * heading in the panel, or the elements an `aria-labelledby` on the host names.
@@ -65,6 +69,11 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
65
69
  * @csspart content - The scrolling region inside the panel.
66
70
  * @csspart popover - The panel.
67
71
  *
72
+ * @cssproperty --floating-anchor-inline-size - The trigger's width, written on the panel while it is open, as in `min-inline-size: var(--floating-anchor-inline-size)`. Read it; a value set here is written over.
73
+ * @cssproperty --floating-available-block-size - The room between the panel and the edge of the screen it opens toward, written on the panel while it is open. Read it; a value set here is written over.
74
+ *
75
+ * @cssstate entering - From the moment the panel shows until its entrance has finished.
76
+ * @cssstate exiting - From the moment the panel hides until its exit has finished.
68
77
  * @cssstate open - While the popover is open.
69
78
  * @cssstate placed-bottom - While the panel sits below its trigger.
70
79
  * @cssstate placed-left - While the panel sits to the left of its trigger.
@@ -85,8 +94,9 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
85
94
  */
86
95
  label: string;
87
96
  /**
88
- * Keeps `Tab` inside the panel while it is open, and marks the panel
89
- * `aria-modal`. A press outside and Escape still close it.
97
+ * Keeps `Tab` inside the panel while it is open, marks the panel
98
+ * `aria-modal`, and hides the rest of the page from screen readers. A press
99
+ * outside and Escape still close it.
90
100
  */
91
101
  modal: boolean;
92
102
  protected readonly aria: AriaForwardController;
@@ -100,6 +110,7 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
100
110
  * It moves if that side does not fit.
101
111
  */
102
112
  placement: Placement;
113
+ protected readonly phases: OpenPhaseController;
103
114
  private readonly panel;
104
115
  /**
105
116
  * The side of its trigger the panel last landed on, which names the arrow's
@@ -138,6 +149,26 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
138
149
  show(): void;
139
150
  /** Closes the panel and puts focus back on the trigger. */
140
151
  hide(): void;
152
+ /**
153
+ * Closes the panel, giving focus back to the trigger where `giveBack` is set
154
+ * and focus is inside the panel that is going away. A popover dismissed by a
155
+ * press somewhere else has not taken focus with it, and pulling focus back to
156
+ * the trigger would move a reader who was already somewhere else on purpose.
157
+ */
158
+ private close;
159
+ /**
160
+ * Whether focus is in the panel, on the panel itself or on anything slotted
161
+ * into it. `deepActiveElement`, which walks into shadow roots:
162
+ * `document.activeElement` stops at the outermost host, so a popover living
163
+ * inside another component's shadow root would never see its own focus.
164
+ */
165
+ private get focusInside();
166
+ /**
167
+ * Whether the update under way closes the panel while focus is inside it,
168
+ * read before the panel is hidden and focus has fallen to the body.
169
+ */
170
+ private closingFromInside;
171
+ protected willUpdate(changed: PropertyValues): void;
141
172
  /**
142
173
  * Focus leaving the control closes the panel.
143
174
  *
@@ -149,10 +180,35 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
149
180
  */
150
181
  private readonly handleFocusOut;
151
182
  connectedCallback(): void;
183
+ /**
184
+ * A press on the slotted trigger, heard on the host on the way down, before
185
+ * the trigger slot's own listener opens the panel and the update that
186
+ * schedules reads it in `tellTrigger`.
187
+ */
188
+ private readonly notePress;
152
189
  disconnectedCallback(): void;
153
190
  private readonly handleTriggerClick;
154
- /** Tells a slotted trigger the disclosure state, by property. See `tellDisclosure`. */
191
+ /** Whether a reader has pressed the trigger, which is after any hydration. */
192
+ private pressed;
193
+ /** The plain trigger this popover writes `aria-expanded` on, once it may. */
194
+ private told;
195
+ /**
196
+ * Tells a slotted trigger the disclosure state.
197
+ *
198
+ * A Helix trigger by property, through `tellDisclosure`. A plain element,
199
+ * which has no shadow root to keep the state out of the markup, by
200
+ * `aria-expanded`, and only from a reader's first press on: by then a server
201
+ * or a framework has long finished writing the element, so the write cannot
202
+ * be a hydration mismatch. One that already carries `aria-expanded` is the
203
+ * consumer's to keep, and is left alone.
204
+ */
155
205
  private tellTrigger;
206
+ /** Whether the first update, which is the server's, has passed. */
207
+ private settled;
208
+ /** Shows the page again, while a modal panel has it hidden. */
209
+ private showOutside;
210
+ /** Hides the page outside a modal panel while it is open, and shows it again after. */
211
+ private hideAround;
156
212
  /**
157
213
  * Puts the panel where `open` says it should be, however it got there.
158
214
  *