@fusion.dev/helix-headless 0.143.0 → 0.145.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 (314) hide show
  1. package/custom-elements.json +16990 -1383
  2. package/dist/accordion/item/accordion-item.d.ts +48 -12
  3. package/dist/accordion/item/accordion-item.js +26 -5
  4. package/dist/accordion/root/accordion-root.d.ts +6 -0
  5. package/dist/accordion/root/accordion-root.js +7 -1
  6. package/dist/announcement/root/announcement-root.d.ts +21 -1
  7. package/dist/announcement/root/announcement-root.js +36 -1
  8. package/dist/app-header/root/app-header-root.d.ts +7 -0
  9. package/dist/app-header/root/app-header-root.js +5 -1
  10. package/dist/app-header/sectioning.d.ts +7 -0
  11. package/dist/app-header/sectioning.js +26 -0
  12. package/dist/area-chart/root/area-chart-root.d.ts +12 -4
  13. package/dist/area-chart/root/area-chart-root.js +24 -7
  14. package/dist/avatar/root/avatar-root.d.ts +14 -0
  15. package/dist/avatar/root/avatar-root.js +23 -9
  16. package/dist/badge/root/badge-root.d.ts +11 -7
  17. package/dist/badge/root/badge-root.js +1 -1
  18. package/dist/bar-chart/root/bar-chart-root.d.ts +12 -3
  19. package/dist/bar-chart/root/bar-chart-root.js +17 -10
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +32 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +25 -2
  22. package/dist/button/root/button-root.d.ts +47 -1
  23. package/dist/button/root/button-root.js +38 -4
  24. package/dist/callout/root/callout-root.d.ts +18 -1
  25. package/dist/callout/root/callout-root.js +15 -4
  26. package/dist/canvas/root/canvas-root.d.ts +38 -3
  27. package/dist/canvas/root/canvas-root.js +121 -40
  28. package/dist/card/root/card-root.d.ts +30 -1
  29. package/dist/card/root/card-root.js +38 -5
  30. package/dist/carousel/root/carousel-root.d.ts +90 -0
  31. package/dist/carousel/root/carousel-root.js +134 -12
  32. package/dist/chat/composer/chat-composer.d.ts +38 -6
  33. package/dist/chat/composer/chat-composer.js +42 -9
  34. package/dist/chat/message/chat-message.d.ts +32 -1
  35. package/dist/chat/message/chat-message.js +25 -9
  36. package/dist/chat/naming.d.ts +22 -0
  37. package/dist/chat/naming.js +12 -0
  38. package/dist/chat/relative-clock.d.ts +39 -0
  39. package/dist/chat/relative-clock.js +31 -0
  40. package/dist/chat/root/chat-root.d.ts +36 -0
  41. package/dist/chat/root/chat-root.js +24 -1
  42. package/dist/checkbox/root/checkbox-root.js +2 -0
  43. package/dist/checkbox-group/root/checkbox-group-root.d.ts +53 -3
  44. package/dist/checkbox-group/root/checkbox-group-root.js +71 -22
  45. package/dist/code-block/lines.d.ts +13 -0
  46. package/dist/code-block/lines.js +2 -0
  47. package/dist/code-block/root/code-block-root.d.ts +38 -1
  48. package/dist/code-block/root/code-block-root.js +28 -7
  49. package/dist/color-input/root/color-input-root.d.ts +34 -1
  50. package/dist/color-input/root/color-input-root.js +23 -4
  51. package/dist/color-picker/channels.d.ts +26 -0
  52. package/dist/color-picker/channels.js +84 -0
  53. package/dist/color-picker/root/color-picker-root.d.ts +81 -5
  54. package/dist/color-picker/root/color-picker-root.js +103 -10
  55. package/dist/combobox/root/combobox-root.d.ts +38 -3
  56. package/dist/combobox/root/combobox-root.js +64 -2
  57. package/dist/command/root/command-root.d.ts +30 -4
  58. package/dist/command/root/command-root.js +33 -3
  59. package/dist/copy-button/from.d.ts +22 -0
  60. package/dist/copy-button/from.js +28 -0
  61. package/dist/copy-button/root/copy-button-root.d.ts +47 -1
  62. package/dist/copy-button/root/copy-button-root.js +44 -8
  63. package/dist/data-table/root/data-table-root.d.ts +150 -2
  64. package/dist/data-table/root/data-table-root.js +303 -29
  65. package/dist/data-table/tree.d.ts +40 -0
  66. package/dist/data-table/tree.js +55 -0
  67. package/dist/date-input/root/date-input-root.d.ts +73 -4
  68. package/dist/date-input/root/date-input-root.js +93 -43
  69. package/dist/date-picker/root/date-picker-root.d.ts +145 -1
  70. package/dist/date-picker/root/date-picker-root.js +239 -48
  71. package/dist/description-list/item/description-list-item.d.ts +17 -2
  72. package/dist/description-list/item/description-list-item.js +15 -2
  73. package/dist/description-list/root/description-list-root.d.ts +27 -1
  74. package/dist/description-list/root/description-list-root.js +26 -1
  75. package/dist/dialog/description.d.ts +9 -0
  76. package/dist/dialog/description.js +14 -0
  77. package/dist/dialog/root/dialog-root.d.ts +64 -1
  78. package/dist/dialog/root/dialog-root.js +49 -23
  79. package/dist/donut-chart/root/donut-chart-root.d.ts +25 -4
  80. package/dist/donut-chart/root/donut-chart-root.js +21 -6
  81. package/dist/drawer/root/drawer-root.d.ts +63 -2
  82. package/dist/drawer/root/drawer-root.js +95 -19
  83. package/dist/drawer/swipe-start.d.ts +9 -0
  84. package/dist/drawer/swipe-start.js +12 -0
  85. package/dist/drilldown/item/drilldown-item.d.ts +11 -6
  86. package/dist/drilldown/item/drilldown-item.js +8 -5
  87. package/dist/drilldown/root/drilldown-root.d.ts +11 -0
  88. package/dist/drilldown/root/drilldown-root.js +8 -3
  89. package/dist/element-events.generated.js +61 -13
  90. package/dist/empty/root/empty-root.d.ts +1 -1
  91. package/dist/file-input/root/file-input-root.d.ts +47 -0
  92. package/dist/file-input/root/file-input-root.js +60 -22
  93. package/dist/file-input/screen.d.ts +35 -0
  94. package/dist/file-input/screen.js +49 -0
  95. package/dist/filter-input/menu/filter-menu.d.ts +3 -0
  96. package/dist/filter-input/menu/filter-menu.js +8 -4
  97. package/dist/filter-input/root/filter-input-root.d.ts +38 -4
  98. package/dist/filter-input/root/filter-input-root.js +67 -3
  99. package/dist/filter-input/suggest.d.ts +17 -0
  100. package/dist/filter-input/suggest.js +23 -0
  101. package/dist/format-date/options.d.ts +33 -0
  102. package/dist/format-date/options.js +42 -0
  103. package/dist/format-date/root/format-date-root.d.ts +51 -0
  104. package/dist/format-date/root/format-date-root.js +58 -38
  105. package/dist/heatmap/root/heatmap-root.d.ts +23 -6
  106. package/dist/heatmap/root/heatmap-root.js +24 -13
  107. package/dist/icon/index.d.ts +2 -0
  108. package/dist/icon/index.js +2 -0
  109. package/dist/icon/registry.d.ts +37 -0
  110. package/dist/icon/registry.js +83 -0
  111. package/dist/icon/root/icon-root.d.ts +30 -4
  112. package/dist/icon/root/icon-root.js +41 -6
  113. package/dist/icon/root/index.d.ts +2 -0
  114. package/dist/icon/root/index.js +2 -0
  115. package/dist/icon/set.d.ts +1 -0
  116. package/dist/icon/set.js +3 -0
  117. package/dist/image/root/image-root.d.ts +14 -0
  118. package/dist/image/root/image-root.js +23 -2
  119. package/dist/input/root/input-root.d.ts +11 -0
  120. package/dist/input/root/input-root.js +16 -1
  121. package/dist/kbd/root/kbd-root.d.ts +20 -13
  122. package/dist/kbd/root/kbd-root.js +35 -37
  123. package/dist/kbd/shortcut.d.ts +18 -0
  124. package/dist/kbd/shortcut.js +35 -0
  125. package/dist/legend/hidden-series.d.ts +8 -0
  126. package/dist/legend/hidden-series.js +13 -0
  127. package/dist/legend/root/legend-root.d.ts +56 -0
  128. package/dist/legend/root/legend-root.js +54 -5
  129. package/dist/lightbox/item/lightbox-item.d.ts +15 -0
  130. package/dist/lightbox/item/lightbox-item.js +10 -1
  131. package/dist/lightbox/root/lightbox-root.d.ts +61 -1
  132. package/dist/lightbox/root/lightbox-root.js +94 -4
  133. package/dist/line-chart/root/line-chart-root.d.ts +11 -3
  134. package/dist/line-chart/root/line-chart-root.js +19 -5
  135. package/dist/list/item/list-item.d.ts +68 -1
  136. package/dist/list/item/list-item.js +66 -4
  137. package/dist/list/numbering.d.ts +14 -0
  138. package/dist/list/numbering.js +8 -0
  139. package/dist/list/root/list-root.d.ts +106 -9
  140. package/dist/list/root/list-root.js +189 -4
  141. package/dist/list/selection.d.ts +19 -0
  142. package/dist/list/selection.js +21 -0
  143. package/dist/listbox/root/listbox-root.d.ts +74 -3
  144. package/dist/listbox/root/listbox-root.js +86 -9
  145. package/dist/loader/busy.d.ts +17 -0
  146. package/dist/loader/busy.js +24 -0
  147. package/dist/loader/root/loader-root.d.ts +37 -0
  148. package/dist/loader/root/loader-root.js +52 -3
  149. package/dist/map/root/map-root.d.ts +6 -2
  150. package/dist/map/root/map-root.js +5 -2
  151. package/dist/megamenu/root/megamenu-root.d.ts +21 -0
  152. package/dist/megamenu/root/megamenu-root.js +16 -2
  153. package/dist/menu/index.d.ts +1 -0
  154. package/dist/menu/index.js +1 -0
  155. package/dist/menu/item/menu-item.d.ts +38 -11
  156. package/dist/menu/item/menu-item.js +33 -1
  157. package/dist/menu/root/menu-root.d.ts +25 -1
  158. package/dist/menu/root/menu-root.js +63 -6
  159. package/dist/menu/section/menu-section.d.ts +55 -0
  160. package/dist/menu/section/menu-section.js +60 -0
  161. package/dist/meter/root/meter-root.d.ts +7 -0
  162. package/dist/meter/root/meter-root.js +6 -3
  163. package/dist/navigation/root/navigation-root.d.ts +16 -1
  164. package/dist/navigation/root/navigation-root.js +27 -1
  165. package/dist/notifications/feed-keys.d.ts +10 -0
  166. package/dist/notifications/feed-keys.js +14 -0
  167. package/dist/notifications/notification/notification.d.ts +17 -0
  168. package/dist/notifications/notification/notification.js +21 -2
  169. package/dist/notifications/root/notifications-root.d.ts +60 -0
  170. package/dist/notifications/root/notifications-root.js +76 -1
  171. package/dist/number-input/root/number-input-root.d.ts +47 -0
  172. package/dist/number-input/root/number-input-root.js +58 -22
  173. package/dist/object-inspector/root/object-inspector-root.d.ts +98 -16
  174. package/dist/object-inspector/root/object-inspector-root.js +180 -80
  175. package/dist/object-inspector/rows.d.ts +57 -0
  176. package/dist/object-inspector/rows.js +86 -0
  177. package/dist/option/root/option-root.d.ts +54 -5
  178. package/dist/option/root/option-root.js +34 -5
  179. package/dist/outline/levels.d.ts +31 -0
  180. package/dist/outline/levels.js +23 -0
  181. package/dist/outline/root/outline-root.d.ts +68 -3
  182. package/dist/outline/root/outline-root.js +73 -8
  183. package/dist/pagination/size/pagination-size.d.ts +11 -2
  184. package/dist/pagination/size/pagination-size.js +19 -4
  185. package/dist/pin-input/format.d.ts +7 -0
  186. package/dist/pin-input/format.js +16 -0
  187. package/dist/pin-input/root/pin-input-root.d.ts +21 -0
  188. package/dist/pin-input/root/pin-input-root.js +29 -2
  189. package/dist/popover/root/popover-root.d.ts +62 -4
  190. package/dist/popover/root/popover-root.js +53 -5
  191. package/dist/progress/root/progress-root.d.ts +7 -0
  192. package/dist/progress/root/progress-root.js +9 -3
  193. package/dist/qr-code/export.d.ts +31 -0
  194. package/dist/qr-code/export.js +10 -0
  195. package/dist/qr-code/root/qr-code-root.d.ts +26 -0
  196. package/dist/qr-code/root/qr-code-root.js +49 -2
  197. package/dist/radio/group/radio-group.d.ts +17 -0
  198. package/dist/radio/group/radio-group.js +14 -1
  199. package/dist/rating/root/rating-root.d.ts +25 -0
  200. package/dist/rating/root/rating-root.js +46 -4
  201. package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
  202. package/dist/scatter-chart/root/scatter-chart-root.js +25 -7
  203. package/dist/scroll-area/root/scroll-area-root.d.ts +113 -0
  204. package/dist/scroll-area/root/scroll-area-root.js +218 -3
  205. package/dist/scroll-area/scrollbar.d.ts +65 -0
  206. package/dist/scroll-area/scrollbar.js +24 -0
  207. package/dist/select/root/select-root.d.ts +24 -0
  208. package/dist/select/root/select-root.js +21 -7
  209. package/dist/skeleton/root/skeleton-root.d.ts +25 -0
  210. package/dist/skeleton/root/skeleton-root.js +17 -2
  211. package/dist/slider/root/slider-root.d.ts +39 -0
  212. package/dist/slider/root/slider-root.js +45 -9
  213. package/dist/splitter/root/splitter-root.d.ts +13 -0
  214. package/dist/splitter/root/splitter-root.js +20 -2
  215. package/dist/splitter/snap.d.ts +9 -0
  216. package/dist/splitter/snap.js +12 -0
  217. package/dist/stat/root/stat-root.d.ts +2 -0
  218. package/dist/stat/root/stat-root.js +1 -1
  219. package/dist/steps/reach.d.ts +15 -0
  220. package/dist/steps/reach.js +12 -0
  221. package/dist/steps/root/steps-root.d.ts +30 -0
  222. package/dist/steps/root/steps-root.js +53 -0
  223. package/dist/steps/step/step.d.ts +39 -2
  224. package/dist/steps/step/step.js +29 -7
  225. package/dist/switch/root/switch-root.d.ts +12 -2
  226. package/dist/switch/root/switch-root.js +6 -1
  227. package/dist/table/column/table-column.d.ts +11 -0
  228. package/dist/table/column/table-column.js +6 -1
  229. package/dist/table/root/table-root.d.ts +101 -0
  230. package/dist/table/root/table-root.js +166 -5
  231. package/dist/table/row/table-row.d.ts +47 -1
  232. package/dist/table/row/table-row.js +39 -2
  233. package/dist/tabs/panel/tab-panel.d.ts +9 -5
  234. package/dist/tabs/panel/tab-panel.js +3 -4
  235. package/dist/tabs/root/tabs-root.d.ts +25 -1
  236. package/dist/tabs/root/tabs-root.js +21 -3
  237. package/dist/tabs/tab/tab.d.ts +36 -4
  238. package/dist/tabs/tab/tab.js +46 -3
  239. package/dist/tag/group/tag-group.d.ts +107 -0
  240. package/dist/tag/group/tag-group.js +157 -0
  241. package/dist/tag/index.d.ts +1 -0
  242. package/dist/tag/index.js +1 -0
  243. package/dist/tag/root/tag-root.d.ts +60 -0
  244. package/dist/tag/root/tag-root.js +74 -18
  245. package/dist/tag/selection.d.ts +10 -0
  246. package/dist/tag/selection.js +12 -0
  247. package/dist/textarea/grow.d.ts +22 -0
  248. package/dist/textarea/grow.js +20 -0
  249. package/dist/textarea/root/textarea-root.d.ts +9 -0
  250. package/dist/textarea/root/textarea-root.js +9 -1
  251. package/dist/time-input/root/time-input-root.d.ts +44 -5
  252. package/dist/time-input/root/time-input-root.js +69 -39
  253. package/dist/time-picker/root/time-picker-root.d.ts +54 -8
  254. package/dist/time-picker/root/time-picker-root.js +121 -91
  255. package/dist/timeline/group/timeline-group.d.ts +46 -0
  256. package/dist/timeline/group/timeline-group.js +37 -0
  257. package/dist/timeline/index.d.ts +1 -0
  258. package/dist/timeline/index.js +1 -0
  259. package/dist/timeline/root/timeline-root.d.ts +10 -3
  260. package/dist/toast/hotkey.d.ts +22 -0
  261. package/dist/toast/hotkey.js +23 -0
  262. package/dist/toast/item/toast-item.d.ts +26 -18
  263. package/dist/toast/item/toast-item.js +55 -48
  264. package/dist/toast/root/toast-root.d.ts +42 -8
  265. package/dist/toast/root/toast-root.js +64 -4
  266. package/dist/toggle/group/toggle-group.d.ts +57 -15
  267. package/dist/toggle/group/toggle-group.js +69 -9
  268. package/dist/toggle/root/toggle-root.d.ts +12 -1
  269. package/dist/toggle/root/toggle-root.js +11 -3
  270. package/dist/toolbar/root/toolbar-root.d.ts +13 -0
  271. package/dist/toolbar/root/toolbar-root.js +15 -5
  272. package/dist/tooltip/focus-target.d.ts +6 -0
  273. package/dist/tooltip/focus-target.js +9 -0
  274. package/dist/tooltip/root/tooltip-root.d.ts +42 -17
  275. package/dist/tooltip/root/tooltip-root.js +50 -9
  276. package/dist/tour/naming.d.ts +30 -0
  277. package/dist/tour/naming.js +10 -0
  278. package/dist/tour/root/tour-root.d.ts +35 -0
  279. package/dist/tour/root/tour-root.js +56 -5
  280. package/dist/tour/stop/tour-stop.d.ts +53 -8
  281. package/dist/tour/stop/tour-stop.js +45 -15
  282. package/dist/tour/wait.d.ts +11 -0
  283. package/dist/tour/wait.js +19 -0
  284. package/dist/tree/item/tree-item.d.ts +54 -1
  285. package/dist/tree/item/tree-item.js +89 -20
  286. package/dist/tree/root/tree-root.d.ts +37 -0
  287. package/dist/tree/root/tree-root.js +51 -6
  288. package/dist/tree/selection.d.ts +24 -0
  289. package/dist/tree/selection.js +26 -0
  290. package/dist/trend/root/trend-root.d.ts +13 -0
  291. package/dist/trend/root/trend-root.js +14 -9
  292. package/dist/video/media-events.d.ts +49 -0
  293. package/dist/video/media-events.js +39 -0
  294. package/dist/video/root/video-root.d.ts +99 -13
  295. package/dist/video/root/video-root.js +84 -47
  296. package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -0
  297. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  298. package/dist/video-playlist/order.d.ts +41 -0
  299. package/dist/video-playlist/order.js +34 -0
  300. package/dist/video-playlist/root/video-playlist-root.d.ts +70 -2
  301. package/dist/video-playlist/root/video-playlist-root.js +60 -16
  302. package/dist/virtual-list/controls.d.ts +4 -0
  303. package/dist/virtual-list/controls.js +30 -0
  304. package/dist/virtual-list/fill.d.ts +30 -0
  305. package/dist/virtual-list/fill.js +39 -0
  306. package/dist/virtual-list/keys.d.ts +15 -0
  307. package/dist/virtual-list/keys.js +24 -0
  308. package/dist/virtual-list/root/virtual-list-root.d.ts +155 -23
  309. package/dist/virtual-list/root/virtual-list-root.js +175 -34
  310. package/lint.json +1 -1
  311. package/package.json +5 -5
  312. package/types/jsx.d.ts +8871 -1286
  313. package/types/svelte.d.ts +3 -0
  314. package/types/vue.d.ts +1918 -269
@@ -4,14 +4,20 @@ 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 } from '@fusion.dev/helix-core';
7
+ import { capturePointer, customElement, DelayController, HelixElement, isRtl, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
+ import { hasScrollbar, offsetAt, scrollFraction, scrollPerPixel, showsScrollbar, thumbFraction, } from '../scrollbar.js';
10
11
  const EDGES = ['block-start', 'block-end', 'inline-start', 'inline-end'];
11
12
  let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement {
12
13
  constructor() {
13
14
  super(...arguments);
15
+ this.hideDelay = 600;
14
16
  this.label = '';
17
+ this.active = false;
18
+ this.hovered = false;
19
+ this.over = false;
20
+ this.hide = new DelayController(this, { renders: false });
15
21
  this.more = [];
16
22
  this.scrolls = false;
17
23
  this.measure = () => {
@@ -36,6 +42,56 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
36
42
  }
37
43
  this.more = found;
38
44
  this.scrolls = box.scrollHeight > box.clientHeight || box.scrollWidth > box.clientWidth;
45
+ if (this.scrollbars) {
46
+ this.readBars(box);
47
+ }
48
+ };
49
+ this.handleVerticalDown = (event) => {
50
+ this.grab(event, 'vertical');
51
+ };
52
+ this.handleHorizontalDown = (event) => {
53
+ this.grab(event, 'horizontal');
54
+ };
55
+ this.handleDragMove = (event) => {
56
+ const drag = this.drag;
57
+ const box = this.scroller;
58
+ if (!drag || !box) {
59
+ return;
60
+ }
61
+ const pointer = drag.axis === 'vertical' ? event.clientY : event.clientX;
62
+ this.scrollAlong(box, drag.axis, drag.from + (pointer - drag.pointer) * drag.sign * drag.perPixel);
63
+ };
64
+ this.handleDragEnd = () => {
65
+ if (!this.drag) {
66
+ return;
67
+ }
68
+ this.drag = undefined;
69
+ this.wake();
70
+ this.requestUpdate();
71
+ };
72
+ this.handleBarEnter = () => {
73
+ this.over = true;
74
+ };
75
+ this.handleBarLeave = () => {
76
+ this.over = false;
77
+ this.wake();
78
+ };
79
+ this.handleEnter = () => {
80
+ this.hovered = true;
81
+ };
82
+ this.handleLeave = () => {
83
+ this.hovered = false;
84
+ if (this.scrollbars === 'hover') {
85
+ this.wake();
86
+ }
87
+ };
88
+ this.handleScroll = (event) => {
89
+ this.measure();
90
+ this.wake();
91
+ this.relayNativeEvent(event);
92
+ };
93
+ this.handleScrollEnd = (event) => {
94
+ this.relayNativeEvent(event);
39
95
  };
40
96
  this.handleSlotChange = (event) => {
41
97
  const slot = event.target;
@@ -48,8 +104,84 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
48
104
  get scroller() {
49
105
  return this.partNamed('viewport');
50
106
  }
107
+ extent(box, axis) {
108
+ return axis === 'vertical'
109
+ ? { client: box.clientHeight, offset: box.scrollTop, scroll: box.scrollHeight }
110
+ : { client: box.clientWidth, offset: Math.abs(box.scrollLeft), scroll: box.scrollWidth };
111
+ }
112
+ readBars(box) {
113
+ const mode = this.scrollbars ?? 'auto';
114
+ const style = getComputedStyle(box);
115
+ const bar = (axis, overflow) => {
116
+ const extent = this.extent(box, axis);
117
+ return {
118
+ along: scrollFraction(extent),
119
+ drawn: hasScrollbar(mode, !['clip', 'hidden', 'visible'].includes(overflow), extent.offset > 1 || extent.client < extent.scroll - 1),
120
+ thumb: thumbFraction(extent),
121
+ };
122
+ };
123
+ const next = {
124
+ horizontal: bar('horizontal', style.overflowX),
125
+ vertical: bar('vertical', style.overflowY),
126
+ };
127
+ if (JSON.stringify(next) !== JSON.stringify(this.bars)) {
128
+ this.bars = next;
129
+ }
130
+ }
131
+ wake() {
132
+ if (this.scrollbars !== 'scroll' && this.scrollbars !== 'hover') {
133
+ return;
134
+ }
135
+ this.active = true;
136
+ this.hide.start(this.hideDelay, () => {
137
+ this.active = false;
138
+ });
139
+ }
140
+ scrollAlong(box, axis, offset) {
141
+ box.scrollTo(axis === 'vertical'
142
+ ? { behavior: 'instant', top: offset }
143
+ : { behavior: 'instant', left: isRtl(box) ? -offset : offset });
144
+ }
145
+ grab(event, axis) {
146
+ const box = this.scroller;
147
+ const bar = event.currentTarget;
148
+ const thumb = bar.querySelector('[part~="thumb"]');
149
+ if (event.button !== 0 || !box || !thumb) {
150
+ return;
151
+ }
152
+ event.preventDefault();
153
+ const vertical = axis === 'vertical';
154
+ const rtl = !vertical && isRtl(box);
155
+ const track = bar.getBoundingClientRect();
156
+ const held = thumb.getBoundingClientRect();
157
+ const length = vertical ? track.height : track.width;
158
+ const size = vertical ? held.height : held.width;
159
+ const extent = this.extent(box, axis);
160
+ const pointer = vertical ? event.clientY : event.clientX;
161
+ let from = extent.offset;
162
+ if (!thumb.contains(event.target)) {
163
+ const along = vertical
164
+ ? pointer - track.top
165
+ : rtl
166
+ ? track.right - pointer
167
+ : pointer - track.left;
168
+ from = offsetAt(extent, along, length, size);
169
+ this.scrollAlong(box, axis, from);
170
+ }
171
+ this.drag = {
172
+ axis,
173
+ from,
174
+ perPixel: scrollPerPixel(extent, length, size),
175
+ pointer,
176
+ sign: rtl ? -1 : 1,
177
+ };
178
+ capturePointer(bar, event.pointerId);
179
+ this.requestUpdate();
180
+ }
51
181
  connectedCallback() {
52
182
  super.connectedCallback();
183
+ this.addEventListener('pointerenter', this.handleEnter);
184
+ this.addEventListener('pointerleave', this.handleLeave);
53
185
  this.watcher = new ResizeObserver(this.measure);
54
186
  if (this.hasUpdated) {
55
187
  this.watchContent();
@@ -57,8 +189,14 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
57
189
  }
58
190
  disconnectedCallback() {
59
191
  super.disconnectedCallback();
192
+ this.removeEventListener('pointerenter', this.handleEnter);
193
+ this.removeEventListener('pointerleave', this.handleLeave);
60
194
  this.watcher?.disconnect();
61
195
  this.watcher = undefined;
196
+ this.drag = undefined;
197
+ this.active = false;
198
+ this.hovered = false;
199
+ this.over = false;
62
200
  }
63
201
  firstUpdated(changed) {
64
202
  super.firstUpdated?.(changed);
@@ -79,11 +217,20 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
79
217
  }
80
218
  updated(changed) {
81
219
  super.updated?.(changed);
220
+ if (changed.has('scrollbars') && this.hasUpdated && this.scrollbars) {
221
+ const box = this.scroller;
222
+ if (box) {
223
+ this.readBars(box);
224
+ }
225
+ }
82
226
  this.toggleState('scrolls', this.scrolls);
83
227
  this.toggleState('more-block-start', this.more.includes('block-start'));
84
228
  this.toggleState('more-block-end', this.more.includes('block-end'));
85
229
  this.toggleState('more-inline-start', this.more.includes('inline-start'));
86
230
  this.toggleState('more-inline-end', this.more.includes('inline-end'));
231
+ const drawn = this.scrollbars ? this.bars : undefined;
232
+ this.toggleState('scrollbar-horizontal', drawn?.horizontal.drawn === true);
233
+ this.toggleState('scrollbar-vertical', drawn?.vertical.drawn === true);
87
234
  }
88
235
  render() {
89
236
  return html `<div
@@ -92,7 +239,8 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
92
239
  role=${this.label ? 'region' : nothing}
93
240
  aria-label=${this.label || nothing}
94
241
  tabindex=${this.scrolls ? '0' : nothing}
95
- @scroll=${this.measure}
242
+ @scroll=${this.handleScroll}
243
+ @scrollend=${this.handleScrollEnd}
96
244
  >
97
245
  <slot @slotchange=${this.handleSlotChange}></slot>
98
246
  </div>
@@ -104,12 +252,79 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
104
252
  <div
105
253
  part="edges"
106
254
  aria-hidden="true"
107
- ></div>`;
255
+ ></div>${this.scrollbars ? this.renderScrollbars(this.scrollbars) : nothing}`;
256
+ }
257
+ renderScrollbars(mode) {
258
+ const bars = this.bars;
259
+ const moment = {
260
+ active: this.active,
261
+ held: this.over || this.drag !== undefined,
262
+ hovered: this.hovered,
263
+ };
264
+ const shown = showsScrollbar(mode, moment);
265
+ const facts = (bar) => bar
266
+ ? `--scroll-area-thumb-fraction: ${bar.thumb}; --scroll-area-scroll-fraction: ${bar.along}`
267
+ : nothing;
268
+ const vertical = bars?.vertical.drawn === true;
269
+ const horizontal = bars?.horizontal.drawn === true;
270
+ return html `<div
271
+ part="scrollbar scrollbar-vertical${vertical && shown ? ' scrollbar-visible' : ''}"
272
+ aria-hidden="true"
273
+ ?hidden=${!vertical}
274
+ style=${facts(bars?.vertical)}
275
+ @pointerdown=${this.handleVerticalDown}
276
+ @pointermove=${this.handleDragMove}
277
+ @pointerup=${this.handleDragEnd}
278
+ @pointercancel=${this.handleDragEnd}
279
+ @lostpointercapture=${this.handleDragEnd}
280
+ @pointerenter=${this.handleBarEnter}
281
+ @pointerleave=${this.handleBarLeave}
282
+ >
283
+ <div part="thumb thumb-vertical"></div>
284
+ </div>
285
+ <div
286
+ part="scrollbar scrollbar-horizontal${horizontal && shown ? ' scrollbar-visible' : ''}"
287
+ aria-hidden="true"
288
+ ?hidden=${!horizontal}
289
+ style=${facts(bars?.horizontal)}
290
+ @pointerdown=${this.handleHorizontalDown}
291
+ @pointermove=${this.handleDragMove}
292
+ @pointerup=${this.handleDragEnd}
293
+ @pointercancel=${this.handleDragEnd}
294
+ @lostpointercapture=${this.handleDragEnd}
295
+ @pointerenter=${this.handleBarEnter}
296
+ @pointerleave=${this.handleBarLeave}
297
+ >
298
+ <div part="thumb thumb-horizontal"></div>
299
+ </div>
300
+ <div
301
+ part="corner"
302
+ aria-hidden="true"
303
+ ?hidden=${!(vertical && horizontal)}
304
+ ></div>`;
108
305
  }
109
306
  };
307
+ __decorate([
308
+ property({ attribute: 'hide-delay', type: Number })
309
+ ], HelixHeadlessScrollArea.prototype, "hideDelay", void 0);
110
310
  __decorate([
111
311
  property()
112
312
  ], HelixHeadlessScrollArea.prototype, "label", void 0);
313
+ __decorate([
314
+ property({ reflect: true })
315
+ ], HelixHeadlessScrollArea.prototype, "scrollbars", void 0);
316
+ __decorate([
317
+ state()
318
+ ], HelixHeadlessScrollArea.prototype, "bars", void 0);
319
+ __decorate([
320
+ state()
321
+ ], HelixHeadlessScrollArea.prototype, "active", void 0);
322
+ __decorate([
323
+ state()
324
+ ], HelixHeadlessScrollArea.prototype, "hovered", void 0);
325
+ __decorate([
326
+ state()
327
+ ], HelixHeadlessScrollArea.prototype, "over", void 0);
113
328
  __decorate([
114
329
  state()
115
330
  ], HelixHeadlessScrollArea.prototype, "more", void 0);
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The arithmetic behind the scrollbars a scroll area draws under `scrollbars`.
3
+ *
4
+ * Every length here is along one axis and counted from that axis' start, which
5
+ * is the right-hand edge on a right-to-left page for the horizontal one. The
6
+ * component turns a pointer and a `scrollLeft` into those counts, so nothing
7
+ * below has to know which way the line runs.
8
+ */
9
+ /** Which scrollbars are drawn, and when. Absent keeps the browser's own. */
10
+ export type Scrollbars = 'always' | 'auto' | 'hover' | 'scroll';
11
+ /** One axis of the viewport, read off the box. */
12
+ export interface Extent {
13
+ /** How much of the content the viewport shows, `clientHeight` or `clientWidth`. */
14
+ client: number;
15
+ /** How far from its start the axis is scrolled, never negative. */
16
+ offset: number;
17
+ /** The whole length of the content, `scrollHeight` or `scrollWidth`. */
18
+ scroll: number;
19
+ }
20
+ /**
21
+ * The share of the track the thumb covers, from 0 to 1: how much of the content
22
+ * is in view. A box with no content, or one that shows all of it, is 1.
23
+ */
24
+ export declare const thumbFraction: ({ client, scroll }: Extent) => number;
25
+ /**
26
+ * How far along the axis is scrolled, from 0 at the start to 1 at the end. An
27
+ * axis with nothing to scroll is 0.
28
+ */
29
+ export declare const scrollFraction: ({ client, offset, scroll }: Extent) => number;
30
+ /**
31
+ * How far the content moves for each pixel the thumb is dragged.
32
+ *
33
+ * The thumb travels the track less its own length, and the content travels
34
+ * its length less the view, so the ratio of the two is the gearing. Zero where
35
+ * the thumb fills the track and cannot move.
36
+ */
37
+ export declare const scrollPerPixel: (extent: Extent, track: number, thumb: number) => number;
38
+ /**
39
+ * The offset that puts the middle of the thumb under a press on the track.
40
+ *
41
+ * `along` is where the press landed, counted from the track's start. The thumb
42
+ * stops at either end of the track, so a press near an end scrolls to that end.
43
+ */
44
+ export declare const offsetAt: (extent: Extent, along: number, track: number, thumb: number) => number;
45
+ /**
46
+ * Whether an axis has a scrollbar at all: it can scroll, and under every value
47
+ * but `always` it has something to scroll.
48
+ *
49
+ * An axis whose `overflow` is `hidden` or `clip` cannot be scrolled by a reader,
50
+ * so it gets no scrollbar whatever `scrollbars` says. That is how a consumer
51
+ * keeps a horizontal bar off a list that only scrolls down.
52
+ */
53
+ export declare const hasScrollbar: (mode: Scrollbars, scrollable: boolean, overflows: boolean) => boolean;
54
+ /**
55
+ * Whether a scrollbar that exists is showing at this moment.
56
+ *
57
+ * `auto` and `always` show it the whole time. `scroll` shows it while the
58
+ * content is moving and for the hide delay after, and while the pointer holds
59
+ * it. `hover` adds the time the pointer is over the scroll area.
60
+ */
61
+ export declare const showsScrollbar: (mode: Scrollbars, moment: {
62
+ active: boolean;
63
+ held: boolean;
64
+ hovered: boolean;
65
+ }) => boolean;
@@ -0,0 +1,24 @@
1
+ const clamp = (value, low, high) => Math.min(Math.max(value, low), high);
2
+ export const thumbFraction = ({ client, scroll }) => scroll <= 0 ? 1 : clamp(client / scroll, 0, 1);
3
+ export const scrollFraction = ({ client, offset, scroll }) => {
4
+ const room = scroll - client;
5
+ return room <= 0 ? 0 : clamp(offset / room, 0, 1);
6
+ };
7
+ export const scrollPerPixel = (extent, track, thumb) => {
8
+ const run = track - thumb;
9
+ return run <= 0 ? 0 : Math.max(0, extent.scroll - extent.client) / run;
10
+ };
11
+ export const offsetAt = (extent, along, track, thumb) => {
12
+ const run = track - thumb;
13
+ if (run <= 0) {
14
+ return 0;
15
+ }
16
+ return clamp((along - thumb / 2) / run, 0, 1) * Math.max(0, extent.scroll - extent.client);
17
+ };
18
+ export const hasScrollbar = (mode, scrollable, overflows) => scrollable && (mode === 'always' || overflows);
19
+ export const showsScrollbar = (mode, moment) => {
20
+ if (mode === 'auto' || mode === 'always') {
21
+ return true;
22
+ }
23
+ return moment.active || moment.held || (mode === 'hover' && moment.hovered);
24
+ };
@@ -1,5 +1,6 @@
1
1
  import { AriaForwardController, HelixFormElement, PopoverController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
+ import { type HelixHeadlessOption } from '../../option/root/option-root.js';
3
4
  import '../../listbox/index.js';
4
5
  declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
5
6
  /**
@@ -17,6 +18,9 @@ declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion
17
18
  * `Select` owns the value, passes it down to the listbox, and takes changes
18
19
  * back, so the value lives in one place.
19
20
  *
21
+ * Set `valueContent` to draw the trigger's content from the chosen options,
22
+ * and several chosen options are written as a list in the reader's language.
23
+ *
20
24
  * In the open list the arrow keys, Home, End, PageUp, PageDown and typed
21
25
  * letters move the highlight, and Enter, Space or a click chooses it and
22
26
  * closes the list. Tab closes the list and moves on. On the closed trigger,
@@ -103,6 +107,17 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
103
107
  * Shown on the trigger while nothing is chosen.
104
108
  */
105
109
  placeholder: string;
110
+ /**
111
+ * What the trigger shows for the chosen options: a function given them, in
112
+ * the order they appear, that returns text, an element or a Lit template.
113
+ *
114
+ * For a trigger that shows more than the words, an avatar beside a name or a
115
+ * count of a long set, as React Aria's `SelectValue` takes children. The
116
+ * trigger is named by what this draws, so keep the words in it. Nothing
117
+ * chosen still shows `placeholder`. A property only, there being no way to
118
+ * write a function in markup.
119
+ */
120
+ valueContent?: ((chosen: readonly HelixHeadlessOption[]) => unknown) | undefined;
106
121
  /**
107
122
  * Which option is chosen, as an index, or `-1` where none is.
108
123
  *
@@ -168,6 +183,13 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
168
183
  * the commit creates the text node it needs.
169
184
  */
170
185
  private get display();
186
+ /** The chosen options, in the order they appear. None on a server or while hydrating. */
187
+ private get chosenOptions();
188
+ /**
189
+ * What the trigger shows, behind a seam: what `value-content` draws for the
190
+ * chosen options, or their words, or the placeholder.
191
+ */
192
+ protected renderValue(): unknown;
171
193
  /** Where the highlight goes when the list opens, set by the key that opened it. */
172
194
  private opening;
173
195
  /**
@@ -187,6 +209,8 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
187
209
  * Made on connection, there being no `MutationObserver` on a server.
188
210
  */
189
211
  private watchers;
212
+ /** A link option, once followed, closes the panel as a choice does. */
213
+ private readonly handleLinkFollowed;
190
214
  connectedCallback(): void;
191
215
  disconnectedCallback(): void;
192
216
  /** Opens the list with the highlight where the opening key says. */
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, customElement, HelixFormElement, hostAria, MixinControllerOpen, MixinControllerValue, MixinField, PopoverController, reportValues, typesCharacter, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, afterLinkFollowed, customElement, HelixFormElement, hostAria, MixinControllerOpen, MixinControllerValue, MixinField, PopoverController, reportValues, typesCharacter, } from '@fusion.dev/helix-core';
8
8
  import { caretDown } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
@@ -43,6 +43,9 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
43
43
  this.opening = 'selected';
44
44
  this.seen = new Set();
45
45
  this.watchers = [];
46
+ this.handleLinkFollowed = (event) => {
47
+ afterLinkFollowed(event, () => this.requestOpen(false));
48
+ };
46
49
  this.handleChange = (event) => {
47
50
  const next = event.detail.value;
48
51
  if (!this.requestValue(next)) {
@@ -105,16 +108,23 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
105
108
  }
106
109
  get display() {
107
110
  const chosen = new Set(this.value === '' ? [] : this.value.split(','));
108
- const words = optionsAmong(this.knownChildren)
109
- .filter((option) => chosen.has(option.value))
110
- .map((option) => option.text);
111
+ const words = this.chosenOptions.map((option) => option.text);
111
112
  if (words.length > 0) {
112
- return words.join(', ');
113
+ return new Intl.ListFormat(this.lang || undefined, { style: 'short', type: 'unit' }).format(words);
113
114
  }
114
115
  return chosen.size > 0 && !this.childrenKnown ? nothing : this.placeholder;
115
116
  }
117
+ get chosenOptions() {
118
+ const chosen = new Set(this.value === '' ? [] : this.value.split(','));
119
+ return optionsAmong(this.knownChildren).filter((option) => chosen.has(option.value));
120
+ }
121
+ renderValue() {
122
+ const chosen = this.chosenOptions;
123
+ return this.valueContent && chosen.length > 0 ? this.valueContent(chosen) : this.display;
124
+ }
116
125
  connectedCallback() {
117
126
  super.connectedCallback();
127
+ this.addEventListener('helix-select', this.handleLinkFollowed);
118
128
  const words = new MutationObserver(() => this.requestUpdate());
119
129
  words.observe(this, {
120
130
  attributeFilter: ['label', 'value'],
@@ -128,6 +138,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
128
138
  }
129
139
  disconnectedCallback() {
130
140
  super.disconnectedCallback();
141
+ this.removeEventListener('helix-select', this.handleLinkFollowed);
131
142
  for (const watcher of this.watchers) {
132
143
  watcher.disconnect();
133
144
  }
@@ -211,7 +222,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
211
222
  ?multiple=${this.multiple}
212
223
  ?filterable=${this.filterable}
213
224
  manual
214
- aria-label=${this.label || nothing}
225
+ aria-label=${this.label || this.getAttribute('aria-label') || nothing}
215
226
  @keydown=${this.handleListKeydown}
216
227
  @helix-before-change=${this.handleChange}
217
228
  @change=${this.stopInner}
@@ -252,7 +263,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
252
263
  @keydown=${this.handleTriggerKeydown}
253
264
  >
254
265
  <slot name="start"></slot>
255
- <span part="value" id="value">${this.display}</span>
266
+ <span part="value" id="value">${this.renderValue()}</span>
256
267
  ${''}
257
268
  <slot name="end"></slot>
258
269
  ${''}
@@ -283,6 +294,9 @@ __decorate([
283
294
  __decorate([
284
295
  property()
285
296
  ], HelixHeadlessSelect.prototype, "placeholder", void 0);
297
+ __decorate([
298
+ property({ attribute: false })
299
+ ], HelixHeadlessSelect.prototype, "valueContent", void 0);
286
300
  HelixHeadlessSelect = __decorate([
287
301
  customElement('helix-headless-select')
288
302
  ], HelixHeadlessSelect);
@@ -15,12 +15,22 @@ import { type PropertyValues, type TemplateResult } from 'lit';
15
15
  * There is no `shape` property. Whether a placeholder is a line, a block, or a
16
16
  * circle is presentation, which belongs to the styled tier.
17
17
  *
18
+ * **Put the real content inside and set `loading`, and the skeleton takes its
19
+ * size.** While `loading` is set the content is inert, the host is
20
+ * `aria-busy`, and the styled tier hides the content and paints the
21
+ * placeholder over its box, so nothing moves when the content arrives. Take
22
+ * `loading` off and the content is shown as it is. An empty skeleton is a
23
+ * placeholder of its own size, as before.
24
+ *
18
25
  * @since 0.1.0
19
26
  * @status stable
20
27
  * @category feedback
21
28
  * @aliases Placeholder, Shimmer, Ghost
22
29
  * @documentation https://fusion.dev/helix/components/skeleton
23
30
  *
31
+ * @slot - The content the skeleton stands in for, which sizes it. Optional.
32
+ *
33
+ * @csspart content - The box around the content, inert while `loading`.
24
34
  * @csspart skeleton - The placeholder shape.
25
35
  */
26
36
  export declare class HelixHeadlessSkeleton extends HelixElement {
@@ -31,7 +41,22 @@ export declare class HelixHeadlessSkeleton extends HelixElement {
31
41
  * Absent hides the placeholder from screen readers.
32
42
  */
33
43
  label: string;
44
+ /**
45
+ * Whether the content inside is still loading, which keeps it inert and
46
+ * draws the placeholder over it.
47
+ *
48
+ * Absent shows the content. An empty skeleton is a placeholder whatever
49
+ * this says. Reflected, because the styled tier hides the content on it.
50
+ */
51
+ loading: boolean;
52
+ /**
53
+ * Whether the skeleton holds content, read off its children where they can
54
+ * be known. Not on a server, where an unlabeled skeleton is taken for an
55
+ * empty one until the page has its children.
56
+ */
57
+ private get wraps();
34
58
  protected willUpdate(changed: PropertyValues): void;
59
+ protected firstUpdated(changed: PropertyValues): void;
35
60
  protected render(): TemplateResult;
36
61
  }
37
62
  declare global {
@@ -11,25 +11,40 @@ let HelixHeadlessSkeleton = class HelixHeadlessSkeleton extends HelixElement {
11
11
  constructor() {
12
12
  super(...arguments);
13
13
  this.label = '';
14
+ this.loading = false;
15
+ }
16
+ get wraps() {
17
+ return (this.childrenKnown &&
18
+ [...this.childNodes].some((node) => node.nodeType === 1 || (node.textContent ?? '').trim() !== ''));
14
19
  }
15
20
  willUpdate(changed) {
16
21
  super.willUpdate(changed);
22
+ this.internals.ariaBusy = this.loading ? 'true' : null;
17
23
  if (this.label) {
18
24
  hostAria(this.internals, { label: this.label, role: 'progressbar' });
19
25
  this.internals.ariaHidden = null;
20
26
  }
21
27
  else {
22
28
  hostAria(this.internals, { label: '', role: '' });
23
- this.internals.ariaHidden = 'true';
29
+ this.internals.ariaHidden = this.wraps ? null : 'true';
24
30
  }
25
31
  }
32
+ firstUpdated(changed) {
33
+ super.firstUpdated(changed);
34
+ this.finishHydration();
35
+ }
26
36
  render() {
27
- return html `<span part="skeleton"></span>`;
37
+ return html `<span part="content" ?inert=${this.loading}
38
+ ><slot @slotchange=${() => this.requestUpdate()}></slot></span
39
+ ><span part="skeleton"></span>`;
28
40
  }
29
41
  };
30
42
  __decorate([
31
43
  property()
32
44
  ], HelixHeadlessSkeleton.prototype, "label", void 0);
45
+ __decorate([
46
+ property({ reflect: true, type: Boolean })
47
+ ], HelixHeadlessSkeleton.prototype, "loading", void 0);
33
48
  HelixHeadlessSkeleton = __decorate([
34
49
  customElement('helix-headless-skeleton')
35
50
  ], HelixHeadlessSkeleton);
@@ -20,6 +20,13 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
20
20
  *
21
21
  * A range with two thumbs is two inputs stacked on one track, because there is
22
22
  * no native two-thumb range. Each thumb keeps its own value.
23
+ * `min-steps-between-thumbs` keeps them that many steps apart.
24
+ *
25
+ * `format-options` writes the value with `Intl.NumberFormat` in `locale`, as a
26
+ * currency, a percent or a unit, and `formatter` writes it with a function of
27
+ * your own, such as words for a scale. Either one is what a screen reader
28
+ * hears, what the readout shows and what the marker labels say. `value-text`
29
+ * still wraps it in a sentence, with the formatted value in its place.
23
30
  *
24
31
  * `required` comes with the field mixin and cannot fail. A range is never
25
32
  * empty: the platform shows its midpoint when no value is set, and `willUpdate`
@@ -62,6 +69,27 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
62
69
  protected readonly aria: AriaForwardController;
63
70
  /** Typed or dragged, so every edit is announced. See `announcesInput`. */
64
71
  protected readonly announcesInput = true;
72
+ /**
73
+ * `Intl.NumberFormat` options the value is written with: a currency, a
74
+ * percent, a unit, or a number of decimals. Written as JSON in the
75
+ * attribute.
76
+ *
77
+ * ```html
78
+ * <helix-slider format-options='{"style":"currency","currency":"USD"}'></helix-slider>
79
+ * ```
80
+ */
81
+ formatOptions?: Intl.NumberFormatOptions;
82
+ /**
83
+ * Writes a value as text, in place of `format-options`: words for a scale,
84
+ * or anything `Intl.NumberFormat` cannot say. A property, since a function
85
+ * cannot be written in an attribute.
86
+ */
87
+ formatter?: (value: number) => string;
88
+ /**
89
+ * The locale `format-options` writes the value in, such as `de-DE`. Empty is
90
+ * the reader's own.
91
+ */
92
+ locale: string;
65
93
  /**
66
94
  * Shows the value at each mark.
67
95
  */
@@ -102,6 +130,11 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
102
130
  min: number;
103
131
  /** The name of a range's lower thumb, read after the slider's label. */
104
132
  minimumLabel: string;
133
+ /**
134
+ * How many steps a range's two thumbs stay apart, as Zag's
135
+ * `minStepsBetweenThumbs`. A thumb pushed closer stops there.
136
+ */
137
+ minStepsBetweenThumbs: number;
105
138
  /**
106
139
  * The direction the track runs. `vertical` stands it on end.
107
140
  *
@@ -223,6 +256,12 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
223
256
  * step, or for a range, two of them in order.
224
257
  */
225
258
  private sanitize;
259
+ /** How far apart a range's thumbs stay, in the slider's own units. */
260
+ private get gap();
261
+ /** Whether the value is written by `formatter` or `format-options`. */
262
+ private get formats();
263
+ /** A value as the reader sees it: formatted where asked, the number otherwise. */
264
+ private said;
226
265
  /** What a screen reader says for one thumb, where `value-text` asks. */
227
266
  private spoken;
228
267
  protected updated(changed: PropertyValues): void;