@fusion.dev/helix-headless 0.146.0 → 0.148.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 (288) hide show
  1. package/custom-elements.json +9287 -1084
  2. package/dist/accordion/item/accordion-item.d.ts +43 -21
  3. package/dist/accordion/item/accordion-item.js +37 -11
  4. package/dist/accordion/root/accordion-root.d.ts +8 -2
  5. package/dist/accordion/root/accordion-root.js +6 -8
  6. package/dist/announcement/root/announcement-root.d.ts +66 -6
  7. package/dist/announcement/root/announcement-root.js +144 -13
  8. package/dist/area-chart/root/area-chart-root.d.ts +18 -1
  9. package/dist/area-chart/root/area-chart-root.js +14 -7
  10. package/dist/avatar/root/avatar-root.d.ts +31 -1
  11. package/dist/avatar/root/avatar-root.js +11 -1
  12. package/dist/badge/count.d.ts +14 -0
  13. package/dist/badge/count.js +20 -0
  14. package/dist/badge/root/badge-root.d.ts +57 -6
  15. package/dist/badge/root/badge-root.js +77 -8
  16. package/dist/bar-chart/root/bar-chart-root.js +11 -20
  17. package/dist/bar-chart/stack.d.ts +10 -0
  18. package/dist/bar-chart/stack.js +8 -0
  19. package/dist/blockquote/root/blockquote-root.d.ts +66 -8
  20. package/dist/blockquote/root/blockquote-root.js +85 -8
  21. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
  22. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
  23. package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -2
  24. package/dist/button/root/button-root.d.ts +24 -38
  25. package/dist/button/root/button-root.js +6 -37
  26. package/dist/button/submitter.d.ts +27 -0
  27. package/dist/button/submitter.js +25 -0
  28. package/dist/button-group/arrows.d.ts +14 -0
  29. package/dist/button-group/arrows.js +10 -0
  30. package/dist/button-group/root/button-group-root.d.ts +141 -3
  31. package/dist/button-group/root/button-group-root.js +142 -2
  32. package/dist/canvas/edge-pan.d.ts +61 -0
  33. package/dist/canvas/edge-pan.js +63 -0
  34. package/dist/canvas/node/canvas-node.d.ts +12 -2
  35. package/dist/canvas/node/canvas-node.js +6 -2
  36. package/dist/canvas/root/canvas-document.d.ts +10 -0
  37. package/dist/canvas/root/canvas-document.js +1 -0
  38. package/dist/canvas/root/canvas-root.d.ts +107 -5
  39. package/dist/canvas/root/canvas-root.js +140 -36
  40. package/dist/canvas/snap.d.ts +42 -0
  41. package/dist/canvas/snap.js +32 -0
  42. package/dist/card/root/card-root.d.ts +12 -1
  43. package/dist/card/root/card-root.js +11 -4
  44. package/dist/carousel/root/carousel-root.d.ts +4 -3
  45. package/dist/carousel/root/carousel-root.js +2 -6
  46. package/dist/chat/root/chat-root.d.ts +28 -4
  47. package/dist/chat/root/chat-root.js +12 -7
  48. package/dist/checkbox/root/checkbox-root.js +5 -7
  49. package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
  50. package/dist/checkbox-group/root/checkbox-group-root.js +16 -7
  51. package/dist/checkbox-group/select-all.d.ts +9 -4
  52. package/dist/checkbox-group/select-all.js +1 -1
  53. package/dist/code-block/root/code-block-root.d.ts +41 -18
  54. package/dist/code-block/root/code-block-root.js +21 -6
  55. package/dist/color-input/root/color-input-root.d.ts +11 -0
  56. package/dist/color-input/root/color-input-root.js +12 -5
  57. package/dist/color-picker/channels.js +1 -2
  58. package/dist/color-picker/root/color-picker-root.d.ts +32 -24
  59. package/dist/color-picker/root/color-picker-root.js +99 -55
  60. package/dist/color-picker/wheel.d.ts +28 -0
  61. package/dist/color-picker/wheel.js +15 -0
  62. package/dist/combobox/root/combobox-root.d.ts +83 -11
  63. package/dist/combobox/root/combobox-root.js +81 -18
  64. package/dist/command/root/command-root.d.ts +7 -4
  65. package/dist/command/root/command-root.js +2 -19
  66. package/dist/copy-button/root/copy-button-root.d.ts +16 -1
  67. package/dist/copy-button/root/copy-button-root.js +7 -2
  68. package/dist/data-table/keys.d.ts +0 -18
  69. package/dist/data-table/keys.js +1 -11
  70. package/dist/data-table/root/data-table-root.js +29 -50
  71. package/dist/date-input/root/date-input-root.d.ts +8 -1
  72. package/dist/date-input/root/date-input-root.js +8 -5
  73. package/dist/date-picker/root/date-picker-root.d.ts +14 -9
  74. package/dist/date-picker/root/date-picker-root.js +21 -16
  75. package/dist/description-list/item/description-list-item.d.ts +22 -4
  76. package/dist/description-list/item/description-list-item.js +14 -4
  77. package/dist/divider/root/divider-root.d.ts +45 -16
  78. package/dist/divider/root/divider-root.js +28 -4
  79. package/dist/donut-chart/root/donut-chart-root.js +13 -6
  80. package/dist/donut-chart/slice-label.d.ts +35 -0
  81. package/dist/donut-chart/slice-label.js +11 -0
  82. package/dist/drawer/root/drawer-root.d.ts +4 -2
  83. package/dist/drawer/root/drawer-root.js +15 -3
  84. package/dist/drilldown/item/drilldown-item.d.ts +21 -1
  85. package/dist/drilldown/item/drilldown-item.js +38 -4
  86. package/dist/drilldown/root/drilldown-root.js +3 -2
  87. package/dist/element-events.generated.js +5 -1
  88. package/dist/empty/root/empty-root.d.ts +46 -2
  89. package/dist/empty/root/empty-root.js +50 -5
  90. package/dist/file-input/root/file-input-root.d.ts +34 -6
  91. package/dist/file-input/root/file-input-root.js +55 -21
  92. package/dist/file-input/status.d.ts +24 -0
  93. package/dist/file-input/status.js +11 -0
  94. package/dist/filter-input/chip/filter-chip.d.ts +23 -0
  95. package/dist/filter-input/chip/filter-chip.js +10 -2
  96. package/dist/filter-input/root/filter-input-root.d.ts +8 -0
  97. package/dist/filter-input/root/filter-input-root.js +17 -27
  98. package/dist/format-date/fields.d.ts +20 -0
  99. package/dist/format-date/fields.js +14 -0
  100. package/dist/format-date/options.d.ts +5 -5
  101. package/dist/format-date/options.js +10 -39
  102. package/dist/format-date/root/format-date-root.d.ts +53 -4
  103. package/dist/format-date/root/format-date-root.js +38 -50
  104. package/dist/graph/root/graph-root.d.ts +23 -5
  105. package/dist/graph/root/graph-root.js +17 -20
  106. package/dist/heatmap/root/buckets.d.ts +21 -0
  107. package/dist/heatmap/root/buckets.js +34 -0
  108. package/dist/heatmap/root/heatmap-root.d.ts +76 -3
  109. package/dist/heatmap/root/heatmap-root.js +105 -20
  110. package/dist/icon/index.d.ts +1 -1
  111. package/dist/icon/index.js +1 -1
  112. package/dist/icon/registry.d.ts +26 -1
  113. package/dist/icon/registry.js +12 -1
  114. package/dist/icon/root/icon-root.d.ts +13 -0
  115. package/dist/icon/root/icon-root.js +23 -2
  116. package/dist/icon/root/index.d.ts +1 -1
  117. package/dist/icon/root/index.js +1 -1
  118. package/dist/image/root/image-root.d.ts +20 -0
  119. package/dist/image/root/image-root.js +6 -1
  120. package/dist/input/root/input-root.d.ts +23 -2
  121. package/dist/input/root/input-root.js +12 -8
  122. package/dist/kbd/root/kbd-root.d.ts +20 -3
  123. package/dist/kbd/root/kbd-root.js +23 -50
  124. package/dist/legend/hidden-series.d.ts +10 -2
  125. package/dist/legend/hidden-series.js +5 -2
  126. package/dist/legend/root/legend-root.d.ts +25 -7
  127. package/dist/legend/root/legend-root.js +25 -26
  128. package/dist/lightbox/root/lightbox-root.d.ts +50 -5
  129. package/dist/lightbox/root/lightbox-root.js +76 -8
  130. package/dist/lightbox/zoom.d.ts +2 -0
  131. package/dist/lightbox/zoom.js +5 -3
  132. package/dist/line-chart/root/line-chart-root.d.ts +16 -0
  133. package/dist/line-chart/root/line-chart-root.js +10 -2
  134. package/dist/list/root/list-root.d.ts +10 -2
  135. package/dist/list/root/list-root.js +31 -24
  136. package/dist/list/selection.d.ts +17 -0
  137. package/dist/list/selection.js +16 -0
  138. package/dist/listbox/root/listbox-root.d.ts +125 -26
  139. package/dist/listbox/root/listbox-root.js +156 -166
  140. package/dist/map/marker/map-marker.d.ts +2 -1
  141. package/dist/map/root/map-root.d.ts +40 -2
  142. package/dist/map/root/map-root.js +64 -23
  143. package/dist/megamenu/hand-over.d.ts +75 -0
  144. package/dist/megamenu/hand-over.js +67 -0
  145. package/dist/megamenu/root/megamenu-root.d.ts +38 -14
  146. package/dist/megamenu/root/megamenu-root.js +29 -50
  147. package/dist/menu/item/menu-item.js +4 -4
  148. package/dist/menu/root/menu-root.d.ts +5 -2
  149. package/dist/meter/root/meter-root.d.ts +42 -0
  150. package/dist/meter/root/meter-root.js +33 -7
  151. package/dist/navigation/root/navigation-root.js +5 -8
  152. package/dist/notifications/group/notification-group.d.ts +8 -1
  153. package/dist/notifications/group/notification-group.js +12 -6
  154. package/dist/notifications/notification/notification.d.ts +12 -1
  155. package/dist/notifications/notification/notification.js +3 -1
  156. package/dist/notifications/root/notifications-root.d.ts +48 -3
  157. package/dist/notifications/root/notifications-root.js +36 -6
  158. package/dist/number-input/grain.d.ts +28 -0
  159. package/dist/number-input/grain.js +14 -0
  160. package/dist/number-input/root/number-input-root.d.ts +17 -1
  161. package/dist/number-input/root/number-input-root.js +29 -18
  162. package/dist/object-inspector/root/object-inspector-root.d.ts +17 -6
  163. package/dist/object-inspector/root/object-inspector-root.js +31 -20
  164. package/dist/option/index.d.ts +1 -0
  165. package/dist/option/index.js +1 -0
  166. package/dist/option/separator/option-separator.d.ts +30 -0
  167. package/dist/option/separator/option-separator.js +21 -0
  168. package/dist/outline/root/outline-root.d.ts +12 -0
  169. package/dist/outline/root/outline-root.js +5 -19
  170. package/dist/pagination/size/pagination-size.d.ts +6 -0
  171. package/dist/pagination/size/pagination-size.js +5 -3
  172. package/dist/pin-input/code.d.ts +51 -1
  173. package/dist/pin-input/code.js +37 -0
  174. package/dist/pin-input/root/pin-input-root.d.ts +98 -121
  175. package/dist/pin-input/root/pin-input-root.js +151 -156
  176. package/dist/popover/hide-outside.js +2 -9
  177. package/dist/popover/root/popover-root.d.ts +7 -1
  178. package/dist/popover/root/popover-root.js +9 -1
  179. package/dist/progress/root/progress-root.d.ts +27 -0
  180. package/dist/progress/root/progress-root.js +25 -7
  181. package/dist/qr-code/export.d.ts +19 -0
  182. package/dist/qr-code/export.js +14 -0
  183. package/dist/qr-code/name.d.ts +11 -0
  184. package/dist/qr-code/name.js +7 -0
  185. package/dist/qr-code/root/qr-code-root.d.ts +31 -9
  186. package/dist/qr-code/root/qr-code-root.js +29 -17
  187. package/dist/radio/group/radio-group.d.ts +15 -0
  188. package/dist/radio/root/radio-root.js +2 -2
  189. package/dist/rating/root/rating-root.d.ts +22 -9
  190. package/dist/rating/root/rating-root.js +15 -39
  191. package/dist/scatter-chart/measures.d.ts +22 -0
  192. package/dist/scatter-chart/measures.js +11 -0
  193. package/dist/scatter-chart/root/scatter-chart-root.d.ts +26 -0
  194. package/dist/scatter-chart/root/scatter-chart-root.js +21 -7
  195. package/dist/scroll-area/scrollbar.d.ts +0 -8
  196. package/dist/scroll-area/scrollbar.js +1 -1
  197. package/dist/select/align.d.ts +47 -0
  198. package/dist/select/align.js +7 -0
  199. package/dist/select/root/select-root.d.ts +115 -11
  200. package/dist/select/root/select-root.js +104 -20
  201. package/dist/slider/root/slider-root.d.ts +18 -1
  202. package/dist/slider/root/slider-root.js +22 -0
  203. package/dist/sparkline/readings.d.ts +30 -12
  204. package/dist/sparkline/readings.js +32 -15
  205. package/dist/sparkline/root/sparkline-root.d.ts +46 -3
  206. package/dist/sparkline/root/sparkline-root.js +60 -21
  207. package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
  208. package/dist/speed-dial/group/speed-dial-group.js +43 -0
  209. package/dist/speed-dial/index.d.ts +1 -0
  210. package/dist/speed-dial/index.js +1 -0
  211. package/dist/speed-dial/item/speed-dial-item.d.ts +27 -2
  212. package/dist/speed-dial/item/speed-dial-item.js +43 -5
  213. package/dist/speed-dial/long-press.d.ts +50 -0
  214. package/dist/speed-dial/long-press.js +48 -0
  215. package/dist/speed-dial/root/speed-dial-root.d.ts +86 -1
  216. package/dist/speed-dial/root/speed-dial-root.js +123 -6
  217. package/dist/splitter/root/splitter-root.d.ts +9 -2
  218. package/dist/splitter/root/splitter-root.js +18 -3
  219. package/dist/steps/root/steps-root.d.ts +8 -1
  220. package/dist/steps/root/steps-root.js +6 -1
  221. package/dist/steps/step/step.d.ts +1 -0
  222. package/dist/steps/step/step.js +1 -1
  223. package/dist/table/cell/table-cell.d.ts +8 -1
  224. package/dist/table/cell/table-cell.js +6 -2
  225. package/dist/table/column/table-column.d.ts +6 -0
  226. package/dist/table/column/table-column.js +5 -1
  227. package/dist/table/grid-controller.d.ts +117 -0
  228. package/dist/table/grid-controller.js +293 -0
  229. package/dist/table/root/table-root.d.ts +47 -3
  230. package/dist/table/root/table-root.js +93 -29
  231. package/dist/table/row/table-row.d.ts +36 -0
  232. package/dist/table/row/table-row.js +52 -2
  233. package/dist/tabs/root/tabs-root.d.ts +5 -3
  234. package/dist/tag/group/tag-group.d.ts +16 -4
  235. package/dist/tag/group/tag-group.js +23 -20
  236. package/dist/textarea/root/textarea-root.d.ts +14 -2
  237. package/dist/textarea/root/textarea-root.js +6 -7
  238. package/dist/time-input/root/time-input-root.d.ts +5 -1
  239. package/dist/time-input/root/time-input-root.js +10 -7
  240. package/dist/time-picker/root/time-picker-root.d.ts +12 -14
  241. package/dist/time-picker/root/time-picker-root.js +18 -23
  242. package/dist/toast/item/toast-item.d.ts +9 -6
  243. package/dist/toast/item/toast-item.js +1 -1
  244. package/dist/toast/root/toast-root.d.ts +40 -4
  245. package/dist/toast/root/toast-root.js +68 -16
  246. package/dist/toast/words.d.ts +12 -0
  247. package/dist/toast/words.js +25 -0
  248. package/dist/toggle/group/toggle-group.d.ts +29 -5
  249. package/dist/toggle/group/toggle-group.js +26 -43
  250. package/dist/toggle/root/toggle-root.js +2 -4
  251. package/dist/toolbar/root/toolbar-root.d.ts +52 -5
  252. package/dist/toolbar/root/toolbar-root.js +88 -13
  253. package/dist/tooltip/root/tooltip-root.d.ts +7 -1
  254. package/dist/tooltip/root/tooltip-root.js +10 -2
  255. package/dist/tour/root/tour-root.d.ts +15 -0
  256. package/dist/tour/root/tour-root.js +20 -1
  257. package/dist/tour/stop/tour-stop.d.ts +3 -0
  258. package/dist/tour/stop/tour-stop.js +3 -3
  259. package/dist/tree/root/tree-root.js +2 -2
  260. package/dist/trend/figure.d.ts +16 -0
  261. package/dist/trend/figure.js +8 -0
  262. package/dist/trend/root/trend-root.d.ts +41 -2
  263. package/dist/trend/root/trend-root.js +29 -3
  264. package/dist/video/root/extra-controls.d.ts +12 -0
  265. package/dist/video/root/extra-controls.js +6 -2
  266. package/dist/video/root/video-root.d.ts +16 -1
  267. package/dist/video/root/video-root.js +15 -1
  268. package/dist/video-playlist/root/video-playlist-root.d.ts +11 -1
  269. package/dist/video-playlist/root/video-playlist-root.js +3 -0
  270. package/dist/virtual-list/fill.d.ts +11 -0
  271. package/dist/virtual-list/fill.js +9 -0
  272. package/dist/virtual-list/keys.d.ts +16 -7
  273. package/dist/virtual-list/keys.js +17 -6
  274. package/dist/virtual-list/plan.d.ts +17 -1
  275. package/dist/virtual-list/plan.js +13 -2
  276. package/dist/virtual-list/root/virtual-list-root.d.ts +25 -3
  277. package/dist/virtual-list/root/virtual-list-root.js +53 -41
  278. package/lint.json +1 -1
  279. package/package.json +5 -5
  280. package/types/jsx.d.ts +4934 -954
  281. package/types/svelte.d.ts +2 -0
  282. package/types/vue.d.ts +946 -253
  283. package/dist/color-picker/swatches.d.ts +0 -12
  284. package/dist/color-picker/swatches.js +0 -26
  285. package/dist/rating/steps.d.ts +0 -7
  286. package/dist/rating/steps.js +0 -9
  287. package/dist/tooltip/focus-target.d.ts +0 -6
  288. package/dist/tooltip/focus-target.js +0 -9
@@ -4,21 +4,27 @@ 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, deepActiveElement, HelixElement, HelixSelectEvent, } from '@fusion.dev/helix-core';
7
+ import { ariaChord, chordParts, customElement, deepActiveElement, HelixElement, HelixSelectEvent, keyNames, onApple, reportRuntime, slotFilled, } 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
+ let toldSelected = false;
10
11
  let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixElement {
11
12
  constructor() {
12
13
  super(...arguments);
13
14
  this.disabled = false;
15
+ this.shortcut = '';
14
16
  this.value = '';
15
17
  this.isSpeedDialItem = true;
18
+ this.hasShortcut = false;
19
+ this.readShortcut = () => {
20
+ this.hasShortcut = slotFilled(this.renderRoot.querySelector('slot[name="shortcut"]'));
21
+ };
16
22
  this.handleClick = () => {
17
23
  this.choose();
18
24
  };
19
25
  }
20
- focus() {
21
- this.partNamed('item')?.focus();
26
+ focus(options) {
27
+ this.partNamed('item')?.focus(options);
22
28
  }
23
29
  focusItem() {
24
30
  this.focus();
@@ -31,6 +37,14 @@ let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixE
31
37
  return active !== null && active.getRootNode() === this.renderRoot;
32
38
  }
33
39
  get selected() {
40
+ if (!toldSelected) {
41
+ toldSelected = true;
42
+ reportRuntime({
43
+ kind: 'deprecated',
44
+ message: `<${this.localName}>.selected is deprecated: read \`active\`, which says the same.`,
45
+ tag: this.localName,
46
+ });
47
+ }
34
48
  return this.active;
35
49
  }
36
50
  choose() {
@@ -40,26 +54,50 @@ let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixE
40
54
  this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
41
55
  }
42
56
  render() {
57
+ const keys = this.shortcut === '' ? nothing : ariaChord(this.shortcut, !this.hydrating && onApple());
43
58
  return html `<button
44
59
  part="item"
45
60
  role="menuitem"
46
61
  type="button"
47
62
  aria-disabled=${this.disabled ? 'true' : nothing}
63
+ aria-keyshortcuts=${keys}
48
64
  ?disabled=${this.disabled}
49
65
  tabindex="-1"
50
66
  @click=${this.handleClick}
51
67
  >
52
68
  <span part="icon"><slot name="icon"></slot></span>
53
- <span part="label"><slot></slot></span>
69
+ <span part="label"><slot></slot><span
70
+ part="shortcut"
71
+ aria-hidden="true"
72
+ ?hidden=${!this.hasShortcut && this.shortcut === ''}
73
+ >${this.renderShortcut()}</span
74
+ ></span>
54
75
  </button>`;
55
76
  }
77
+ renderShortcut() {
78
+ const drawn = keyNames(chordParts(this.shortcut), !this.hydrating && onApple());
79
+ return html `<slot name="shortcut" @slotchange=${this.readShortcut}>${drawn.keys.join(drawn.separator)}</slot>`;
80
+ }
81
+ firstUpdated(changed) {
82
+ super.firstUpdated(changed);
83
+ this.readShortcut();
84
+ if (this.shortcut !== '') {
85
+ this.finishHydration();
86
+ }
87
+ }
56
88
  };
57
89
  __decorate([
58
90
  property({ reflect: true, type: Boolean })
59
91
  ], HelixHeadlessSpeedDialItem.prototype, "disabled", void 0);
92
+ __decorate([
93
+ property()
94
+ ], HelixHeadlessSpeedDialItem.prototype, "shortcut", void 0);
60
95
  __decorate([
61
96
  property()
62
97
  ], HelixHeadlessSpeedDialItem.prototype, "value", void 0);
98
+ __decorate([
99
+ state()
100
+ ], HelixHeadlessSpeedDialItem.prototype, "hasShortcut", void 0);
63
101
  HelixHeadlessSpeedDialItem = __decorate([
64
102
  customElement('helix-headless-speed-dial-item')
65
103
  ], HelixHeadlessSpeedDialItem);
@@ -0,0 +1,50 @@
1
+ import type { ReactiveControllerHost } from 'lit';
2
+ /** How long a press is held before it counts, in milliseconds, as React Aria waits. */
3
+ export declare const LONG_PRESS_DELAY = 500;
4
+ /**
5
+ * How far a held pointer may drift and still be the same press, in pixels. A
6
+ * finger is never still, and one that moves further is scrolling or dragging.
7
+ */
8
+ export declare const LONG_PRESS_SLOP = 10;
9
+ /** What a long press reads and calls. */
10
+ export interface LongPressOptions {
11
+ /** Called once a press has been held for the delay without drifting. */
12
+ onLongPress: () => void;
13
+ }
14
+ /**
15
+ * Watches one control's presses for a held one.
16
+ *
17
+ * The control's own handlers call `down`, `move` and `up`, so a press counts
18
+ * only where it started on the control, and `cancel` drops it. The click a
19
+ * held press ends in is the long press's, and `takeClick` says so once, so the
20
+ * control's own action does not run as well.
21
+ */
22
+ export declare class LongPress {
23
+ private readonly options;
24
+ private readonly wait;
25
+ /** Where the press began, while one is held and still counts. */
26
+ private from;
27
+ /** Whether the press that just ended was a long one, until its click is taken. */
28
+ private held;
29
+ constructor(host: ReactiveControllerHost, options: LongPressOptions);
30
+ /** Starts the wait for a press of the primary button. */
31
+ down(event: PointerEvent): void;
32
+ /** Drops the press once the pointer drifts past the slop. */
33
+ move(event: PointerEvent): void;
34
+ /**
35
+ * Ends the press. A press released before the delay is an ordinary one.
36
+ *
37
+ * A held one keeps its claim on a click only until the task ends: the click
38
+ * a release makes comes in the same task, and a release that makes none, off
39
+ * the control or after a touch's own menu, must not leave the next Enter on
40
+ * the control swallowed.
41
+ */
42
+ up(): void;
43
+ /** Drops the press, which then neither opens anything nor swallows a click. */
44
+ cancel(): void;
45
+ /**
46
+ * Whether a click belongs to the long press that just ended, and so is not
47
+ * the control's. True once.
48
+ */
49
+ takeClick(): boolean;
50
+ }
@@ -0,0 +1,48 @@
1
+ import { DelayController } from '@fusion.dev/helix-core';
2
+ export const LONG_PRESS_DELAY = 500;
3
+ export const LONG_PRESS_SLOP = 10;
4
+ export class LongPress {
5
+ constructor(host, options) {
6
+ this.options = options;
7
+ this.from = undefined;
8
+ this.held = false;
9
+ this.wait = new DelayController(host);
10
+ }
11
+ down(event) {
12
+ this.held = false;
13
+ if (event.button !== 0) {
14
+ return;
15
+ }
16
+ this.from = { x: event.clientX, y: event.clientY };
17
+ this.wait.start(LONG_PRESS_DELAY, () => {
18
+ this.from = undefined;
19
+ this.held = true;
20
+ this.options.onLongPress();
21
+ });
22
+ }
23
+ move(event) {
24
+ const from = this.from;
25
+ if (from && Math.hypot(event.clientX - from.x, event.clientY - from.y) > LONG_PRESS_SLOP) {
26
+ this.cancel();
27
+ }
28
+ }
29
+ up() {
30
+ this.from = undefined;
31
+ this.wait.cancel();
32
+ if (this.held) {
33
+ setTimeout(() => {
34
+ this.held = false;
35
+ });
36
+ }
37
+ }
38
+ cancel() {
39
+ this.from = undefined;
40
+ this.held = false;
41
+ this.wait.cancel();
42
+ }
43
+ takeClick() {
44
+ const held = this.held;
45
+ this.held = false;
46
+ return held;
47
+ }
48
+ }
@@ -25,6 +25,31 @@ declare const HelixHeadlessSpeedDial_base: (new (...args: any[]) => import("@fus
25
25
  * action whose name starts with it. The actions are one tab stop, and Tab
26
26
  * closes the dial and moves on.
27
27
  *
28
+ * **Keyboard.** On the trigger, Enter, Space or a press opens the dial on its
29
+ * first action. With the dial open:
30
+ *
31
+ * | Key | What it does |
32
+ * |---|---|
33
+ * | Down, Right | Moves to the next action, from the last back to the first. |
34
+ * | Up, Left | Moves to the action before, from the first round to the last. |
35
+ * | Home, End | Moves to the first or the last action. |
36
+ * | A letter | Moves to the next action whose name starts with it. |
37
+ * | Enter, Space | Chooses the action, and the dial closes. |
38
+ * | Escape | Closes the dial and puts focus back on the trigger. |
39
+ * | Tab | Closes the dial and moves on. |
40
+ *
41
+ * **Groups.** Put actions in `Speed Dial.Group`, named by its `label`, to set
42
+ * them apart as Menu's sections do: each is a `group` of the menu, and the
43
+ * arrow keys walk through every group's actions in order.
44
+ *
45
+ * **A trigger with its own action.** With `open-on="long-press"`, a press on
46
+ * the trigger is the trigger's own, such as composing a message, and holding it
47
+ * for half a second opens the dial, as React Aria's menu trigger does with
48
+ * `trigger="longPress"`. Alt+Down or Alt+Up opens it from the keyboard, and
49
+ * the trigger says so in its description, `long-press-label`, the drawn one
50
+ * and a slotted one alike. A press that has opened the dial does not also do
51
+ * the trigger's action.
52
+ *
28
53
  * @since 0.1.0
29
54
  * @status stable
30
55
  * @category actions
@@ -49,10 +74,26 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
49
74
  * Accessible name for the trigger and the set of actions it opens.
50
75
  */
51
76
  label: string;
77
+ /**
78
+ * The description the trigger gives under `open-on="long-press"`, saying how
79
+ * its actions are reached.
80
+ *
81
+ * A slotted trigger is described by the dial, which carries the words as
82
+ * its own label for that: a Helix button's inner control at once, and a
83
+ * plain element of yours once a reader reaches it, after hydration, unless
84
+ * you described or labeled it yourself.
85
+ */
86
+ longPressLabel: string;
52
87
  /**
53
88
  * Space between the trigger and the actions, in pixels.
54
89
  */
55
90
  offset: number;
91
+ /**
92
+ * What opens the dial. `click` opens it on a press of the trigger. Under
93
+ * `long-press`, a press is the trigger's own action, and the dial opens on a
94
+ * press held for half a second, or on Alt+Down or Alt+Up.
95
+ */
96
+ openOn: 'click' | 'long-press';
56
97
  /**
57
98
  * The direction the actions open in. They move to another side if that side
58
99
  * does not fit.
@@ -74,11 +115,34 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
74
115
  protected readonly panel: PopoverController;
75
116
  /** Whatever the consumer slotted, or the button rendered in its place. */
76
117
  private get trigger();
77
- /** The actions, which are this element's own rows and nothing else slotted. */
118
+ /**
119
+ * The actions, in order: this element's own rows, and the rows of each group
120
+ * slotted beside them, and nothing else slotted.
121
+ */
78
122
  private get items();
123
+ /** Watches the trigger for a held press, under `open-on="long-press"`. */
124
+ private readonly longPress;
125
+ private get pressHeld();
126
+ /**
127
+ * Puts focus on the trigger, the slotted one or the button drawn in its
128
+ * place, as a `focus()` on a native control would. The host itself takes no
129
+ * focus, so a page focusing it after a dialog closes landed nowhere.
130
+ */
131
+ focus(options?: FocusOptions): void;
79
132
  /** Shuts it and puts the reader back on the trigger. */
80
133
  private close;
81
134
  private readonly handleTriggerClick;
135
+ /**
136
+ * Takes the click a held press ends in, ahead of the trigger's own
137
+ * listeners, so a press that opened the dial does not also do the trigger's
138
+ * action. In capture, on the host, which is above a slotted trigger.
139
+ */
140
+ private readonly handleHeldClick;
141
+ private readonly handleTriggerPointerDown;
142
+ private readonly handleTriggerPointerMove;
143
+ private readonly handleTriggerPointerUp;
144
+ private readonly handleTriggerPointerCancel;
145
+ private readonly handleTriggerContextMenu;
82
146
  private readonly handleSelect;
83
147
  private readonly handleKeydown;
84
148
  connectedCallback(): void;
@@ -107,6 +171,27 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
107
171
  * is expanded is already saying it has something to expand.
108
172
  */
109
173
  private announce;
174
+ /** The control the dial has described, so the description can be taken back. */
175
+ private described;
176
+ /**
177
+ * Describes a slotted trigger by `long-press-label` under
178
+ * `open-on="long-press"`, as the drawn one is, or takes it back.
179
+ *
180
+ * **By the host, which carries the words as its label.** The drawn
181
+ * trigger's description is in this shadow root, and a reference from the
182
+ * consumer's trigger, or from the button inside a Helix one, cannot point
183
+ * in; it can point out, to the host. Core's `linkDescription` says where
184
+ * that is safe: inside a component's shadow root always, and on the
185
+ * consumer's own element only once `light` says a reader has acted, which
186
+ * is after hydration. React Aria's long press describes whatever trigger it
187
+ * is given.
188
+ *
189
+ * @param light A reader has just reached the trigger.
190
+ */
191
+ private describeTrigger;
192
+ /** A reader reaching a slotted trigger, which is late enough to describe a plain one. */
193
+ private readonly handleTriggerFocusIn;
194
+ protected firstUpdated(changed: PropertyValues): void;
110
195
  protected updated(changed: PropertyValues): void;
111
196
  /**
112
197
  * The control that opens it, behind a seam the styled tier can move.
@@ -4,20 +4,31 @@ 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 { anchorElement, customElement, drawIcon, HelixElement, KeyboardNavigationController, MixinControllerOpen, PopoverController, slottedWords, tellDisclosure, typeaheadBy, } from '@fusion.dev/helix-core';
7
+ import { anchorElement, customElement, drawIcon, focusTarget, HelixElement, KeyboardNavigationController, linkDescription, MixinControllerOpen, PopoverController, slottedWords, tellDisclosure, typeaheadByWords, unlinkDescription, } from '@fusion.dev/helix-core';
8
8
  import { plus } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
11
+ import { LongPress } from '../long-press.js';
12
+ const navigable = (item) => ({
13
+ contains: (node) => item.contains(node),
14
+ disabled: item.disabled,
15
+ focusItem: () => item.focusItem(),
16
+ select: () => item.select(),
17
+ selected: item.active,
18
+ words: slottedWords(item, ['']),
19
+ });
11
20
  let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControllerOpen(HelixElement) {
12
21
  constructor() {
13
22
  super(...arguments);
14
23
  this.label = 'Actions';
24
+ this.longPressLabel = 'Long press or press Alt+Down to show the actions';
15
25
  this.offset = 12;
26
+ this.openOn = 'click';
16
27
  this.placement = 'top-end';
17
28
  this.keys = new KeyboardNavigationController(this, {
18
- items: () => (this.open ? this.items : []),
29
+ items: () => (this.open ? this.items.map(navigable) : []),
19
30
  selects: () => false,
20
- typeahead: typeaheadBy((item) => slottedWords(item, [''])),
31
+ typeahead: typeaheadByWords(),
21
32
  });
22
33
  this.focusOnOpen = false;
23
34
  this.panel = new PopoverController(this, {
@@ -29,13 +40,48 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
29
40
  placement: () => this.placement,
30
41
  surface: () => this.partNamed('actions'),
31
42
  });
43
+ this.longPress = new LongPress(this, {
44
+ onLongPress: () => {
45
+ if (!this.open) {
46
+ this.focusOnOpen = this.requestOpen(true);
47
+ }
48
+ },
49
+ });
32
50
  this.handleTriggerClick = () => {
33
51
  if (this.open) {
34
52
  this.requestOpen(false);
35
53
  return;
36
54
  }
55
+ if (this.pressHeld) {
56
+ return;
57
+ }
37
58
  this.focusOnOpen = this.requestOpen(true);
38
59
  };
60
+ this.handleHeldClick = (event) => {
61
+ if (this.pressHeld && this.longPress.takeClick()) {
62
+ event.stopImmediatePropagation();
63
+ event.preventDefault();
64
+ }
65
+ };
66
+ this.handleTriggerPointerDown = (event) => {
67
+ if (this.pressHeld && !this.open) {
68
+ this.longPress.down(event);
69
+ }
70
+ };
71
+ this.handleTriggerPointerMove = (event) => {
72
+ this.longPress.move(event);
73
+ };
74
+ this.handleTriggerPointerUp = () => {
75
+ this.longPress.up();
76
+ };
77
+ this.handleTriggerPointerCancel = () => {
78
+ this.longPress.cancel();
79
+ };
80
+ this.handleTriggerContextMenu = (event) => {
81
+ if (this.pressHeld) {
82
+ event.preventDefault();
83
+ }
84
+ };
39
85
  this.handleSelect = (event) => {
40
86
  queueMicrotask(() => {
41
87
  if (!event.defaultPrevented) {
@@ -45,6 +91,12 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
45
91
  };
46
92
  this.handleKeydown = (event) => {
47
93
  if (!this.open) {
94
+ if (this.pressHeld &&
95
+ event.altKey &&
96
+ (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
97
+ event.preventDefault();
98
+ this.focusOnOpen = this.requestOpen(true);
99
+ }
48
100
  return;
49
101
  }
50
102
  if (event.key === 'Tab') {
@@ -58,29 +110,57 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
58
110
  this.close();
59
111
  event.preventDefault();
60
112
  };
113
+ this.handleTriggerFocusIn = () => {
114
+ if (this.pressHeld) {
115
+ this.describeTrigger(true);
116
+ }
117
+ };
61
118
  }
62
119
  get trigger() {
63
120
  return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.partNamed('trigger') ?? this);
64
121
  }
65
122
  get items() {
66
123
  const slot = this.renderRoot?.querySelector('slot:not([name])');
67
- return (slot?.assignedElements?.() ?? []).filter((one) => one.isSpeedDialItem === true);
124
+ const isItem = (one) => one.isSpeedDialItem === true;
125
+ return (slot?.assignedElements?.() ?? []).flatMap((one) => isItem(one)
126
+ ? [one]
127
+ : one.isSpeedDialGroup === true
128
+ ? [...one.children].filter(isItem)
129
+ : []);
130
+ }
131
+ get pressHeld() {
132
+ return this.openOn === 'long-press';
133
+ }
134
+ focus(options) {
135
+ const trigger = this.trigger;
136
+ if (trigger === this) {
137
+ super.focus(options);
138
+ return;
139
+ }
140
+ trigger.focus(options);
68
141
  }
69
142
  close() {
70
143
  if (!this.requestOpen(false)) {
71
144
  return;
72
145
  }
73
- this.trigger.focus();
146
+ this.focus();
74
147
  }
75
148
  connectedCallback() {
76
149
  super.connectedCallback();
77
150
  this.addEventListener('helix-select', this.handleSelect);
78
151
  this.addEventListener('keydown', this.handleKeydown);
152
+ this.addEventListener('click', this.handleHeldClick, true);
79
153
  }
80
154
  disconnectedCallback() {
81
155
  super.disconnectedCallback();
156
+ if (this.described) {
157
+ unlinkDescription(this.described, this);
158
+ this.described = undefined;
159
+ this.internals.ariaLabel = null;
160
+ }
82
161
  this.removeEventListener('helix-select', this.handleSelect);
83
162
  this.removeEventListener('keydown', this.handleKeydown);
163
+ this.removeEventListener('click', this.handleHeldClick, true);
84
164
  }
85
165
  announce() {
86
166
  const trigger = this.trigger;
@@ -89,9 +169,27 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
89
169
  }
90
170
  tellDisclosure(trigger, this.open, 'menu');
91
171
  }
172
+ describeTrigger(light = false) {
173
+ const trigger = this.trigger;
174
+ const slotted = this.pressHeld && trigger !== this && trigger !== this.partNamed('trigger');
175
+ const control = slotted ? focusTarget(trigger) : undefined;
176
+ if (this.described && this.described !== control) {
177
+ unlinkDescription(this.described, this);
178
+ this.described = undefined;
179
+ }
180
+ if (control && control !== this.described && linkDescription(control, this, light)) {
181
+ this.described = control;
182
+ }
183
+ this.internals.ariaLabel = this.described ? this.longPressLabel : null;
184
+ }
185
+ firstUpdated(changed) {
186
+ super.firstUpdated(changed);
187
+ requestAnimationFrame(() => this.describeTrigger());
188
+ }
92
189
  updated(changed) {
93
190
  super.updated?.(changed);
94
191
  this.announce();
192
+ this.describeTrigger();
95
193
  if (this.open && this.focusOnOpen) {
96
194
  this.focusOnOpen = false;
97
195
  this.updateComplete.then(() => {
@@ -102,10 +200,22 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
102
200
  }
103
201
  }
104
202
  renderTrigger() {
105
- return html `<slot name="trigger" @click=${this.handleTriggerClick}>
203
+ const held = this.pressHeld;
204
+ return html `<slot
205
+ name="trigger"
206
+ @click=${this.handleTriggerClick}
207
+ @contextmenu=${this.handleTriggerContextMenu}
208
+ @focusin=${this.handleTriggerFocusIn}
209
+ @pointercancel=${this.handleTriggerPointerCancel}
210
+ @pointerdown=${this.handleTriggerPointerDown}
211
+ @pointermove=${this.handleTriggerPointerMove}
212
+ @pointerup=${this.handleTriggerPointerUp}
213
+ @slotchange=${() => this.describeTrigger()}
214
+ >
106
215
  <button
107
216
  part="trigger"
108
217
  type="button"
218
+ aria-describedby=${held ? 'long-press' : nothing}
109
219
  aria-expanded=${this.open ? 'true' : 'false'}
110
220
  aria-haspopup="menu"
111
221
  aria-label=${this.label}
@@ -113,6 +223,7 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
113
223
  ${''}
114
224
  ${drawIcon(plus)}
115
225
  </button>
226
+ ${held ? html `<span id="long-press" hidden>${this.longPressLabel}</span>` : nothing}
116
227
  </slot>`;
117
228
  }
118
229
  render() {
@@ -131,9 +242,15 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
131
242
  __decorate([
132
243
  property()
133
244
  ], HelixHeadlessSpeedDial.prototype, "label", void 0);
245
+ __decorate([
246
+ property({ attribute: 'long-press-label' })
247
+ ], HelixHeadlessSpeedDial.prototype, "longPressLabel", void 0);
134
248
  __decorate([
135
249
  property({ type: Number })
136
250
  ], HelixHeadlessSpeedDial.prototype, "offset", void 0);
251
+ __decorate([
252
+ property({ attribute: 'open-on' })
253
+ ], HelixHeadlessSpeedDial.prototype, "openOn", void 0);
137
254
  __decorate([
138
255
  property()
139
256
  ], HelixHeadlessSpeedDial.prototype, "placement", void 0);
@@ -13,8 +13,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
13
13
  * added at `firstUpdated` and is not in the server markup. Before it appears,
14
14
  * both dividers work on their own.
15
15
  *
16
- * The divider has `role="separator"` and `aria-valuenow`, and `aria-controls`
17
- * names the start pane. Drag it with a pointer or move it with the arrow keys,
16
+ * The divider has `role="separator"` and `aria-valuenow`, with
17
+ * `aria-valuetext` saying the start pane's share as a percentage in the
18
+ * reader's locale, and `aria-controls` names the start pane. Drag it with a pointer or move it with the arrow keys,
18
19
  * press `Home` or `End` to move it to its bounds, and press `Enter` to collapse
19
20
  * the start pane and open it again. A drag in progress is tracked as a state, so both dividers a
20
21
  * corner moves stay lit for as long as they move.
@@ -36,12 +37,14 @@ import { type PropertyValues, type TemplateResult } from 'lit';
36
37
  * @documentation https://fusion.dev/helix/components/splitter
37
38
  *
38
39
  * @slot end - The pane after the divider.
40
+ * @slot handle - A mark drawn at the middle of the divider, such as a grip icon. It takes no focus and no pointer of its own: a press on it is a press on the divider.
39
41
  * @slot start - The pane before the divider.
40
42
  *
41
43
  * @event {HelixBeforeCollapseEvent} helix-before-collapse - Fired before a pane shuts or reopens, whether or not the resize that caused it was allowed. It carries its own position, because a shut pane sits at `collapsed-size`. Cancelable: canceling it leaves the pane as it was and the divider where the gesture put it.
42
44
  * @event {HelixBeforeResizeEvent} helix-before-resize - Fired before the divider settles, and only when the gesture moved it. A press that moved nothing, a drag that came back, an arrow key with no room left, and a corner that moved only the other divider do not fire it. Cancelable: canceling it leaves the position to you and keeps the rest of the gesture, so a collapse the gesture reached still fires `helix-before-collapse`, which you can also cancel. A dragged divider stays where it was dropped until you set your own `position`.
43
45
  * @event {HelixCollapseEvent} helix-collapse - Fired after a pane shuts or reopens, with the side that is shut, or empty where both are open.
44
46
  * @event {HelixResizedEvent} helix-resized - Fired after the divider settles somewhere new, with the new position.
47
+ * @event {Event} input - Fired each time the divider moves, as a range input does: on each step of a drag, and before `helix-resized` for a key, a double click or a corner. Read `position` for where it is now.
45
48
  *
46
49
  * @csspart corner - The handle where two dividers cross, added on the client.
47
50
  * @csspart end - The box that holds the second pane.
@@ -50,6 +53,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
50
53
  *
51
54
  * @cssproperty --splitter-corner-at - Where a nested splitter crosses this one, as a percentage.
52
55
  * @cssproperty --splitter-position - Where the divider sits, as a percentage of the box.
56
+ *
57
+ * @cssstate collapsed - While a pane is shut. `data-collapsed` on the host says which.
58
+ * @cssstate dragging - While the pointer or a corner holds the divider.
59
+ * @cssstate vertical - While the panes are one above the other, whether `orientation` says so or `auto` turned them.
53
60
  */
54
61
  export declare class HelixHeadlessSplitter extends HelixElement {
55
62
  /**
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixHeadlessSplitter_1;
8
- import { AriaForwardController, capturePointer, closestInstance, commaList, customElement, HelixBeforeCollapseEvent, HelixBeforeResizeEvent, HelixCollapseEvent, HelixElement, HelixResizedEvent, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
8
+ import { AriaForwardController, capturePointer, closestInstance, commaList, customElement, formatPercent, HelixBeforeCollapseEvent, HelixBeforeResizeEvent, HelixCollapseEvent, HelixElement, HelixResizedEvent, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  import { snapTo } from '../snap.js';
@@ -127,6 +127,7 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
127
127
  this.positionState = wanted;
128
128
  this.collapsedState = 'none';
129
129
  this.requestUpdate('position', previous);
130
+ this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
130
131
  }
131
132
  settle(next) {
132
133
  const wanted = this.clamp(next);
@@ -143,6 +144,9 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
143
144
  const previous = this.position;
144
145
  this.positionState = value;
145
146
  this.requestUpdate('position', previous);
147
+ if (value !== previous) {
148
+ this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
149
+ }
146
150
  this.dispatchEvent(new HelixResizedEvent({ value: String(value) }));
147
151
  },
148
152
  event: (value) => new HelixBeforeResizeEvent({ value: String(value) }),
@@ -446,6 +450,7 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
446
450
  super.firstUpdated(changed);
447
451
  this.watchWidth();
448
452
  this.findOuter();
453
+ this.finishHydration();
449
454
  }
450
455
  updated(changed) {
451
456
  super.updated(changed);
@@ -471,6 +476,9 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
471
476
  }
472
477
  willUpdate(changed) {
473
478
  super.willUpdate(changed);
479
+ this.toggleState('dragging', this.dragging);
480
+ this.toggleState('collapsed', this.collapsed !== undefined);
481
+ this.toggleState('vertical', this.vertical);
474
482
  }
475
483
  render() {
476
484
  const position = this.showing;
@@ -492,7 +500,11 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
492
500
  aria-valuemax=${this.collapsed ? 100 : this.clamp(this.maxPercent)}
493
501
  aria-valuemin=${this.collapsed ? 0 : this.clamp(this.minPercent)}
494
502
  aria-valuenow=${Math.round(position)}
495
- aria-valuetext=${this.collapsed ? this.collapsedLabel : nothing}
503
+ aria-valuetext=${this.collapsed
504
+ ? this.collapsedLabel
505
+ : this.hydrating
506
+ ? nothing
507
+ : formatPercent(Math.round(position) / 100)}
496
508
  ?data-dragging=${this.dragging}
497
509
  ?data-flush=${this.flush}
498
510
  @dblclick=${this.handleDoubleClick}
@@ -501,7 +513,9 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
501
513
  @pointerdown=${this.handlePointerDown}
502
514
  @pointermove=${this.handlePointerMove}
503
515
  @pointerup=${this.handlePointerUp}
504
- ></div>
516
+ >
517
+ <slot name="handle"></slot>
518
+ </div>
505
519
  <div part="end" ?data-dragging=${this.dragging}>
506
520
  <slot name="end"></slot>
507
521
  </div>
@@ -514,6 +528,7 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
514
528
  aria-valuemax="100"
515
529
  aria-valuemin="0"
516
530
  aria-valuenow=${Math.round(crossing.at)}
531
+ aria-valuetext=${formatPercent(Math.round(crossing.at) / 100)}
517
532
  data-cross=${index}
518
533
  style="--splitter-corner-at: ${crossing.at}%; --splitter-position: ${position}%"
519
534
  @dblclick=${this.handleCornerDoubleClick}