@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
@@ -26,6 +26,7 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
26
26
  this.rangeText = '{start} to {end}';
27
27
  this.showValue = false;
28
28
  this.step = 1;
29
+ this.tooltip = false;
29
30
  this.handleInput = (event) => {
30
31
  event.stopPropagation();
31
32
  const control = event.target;
@@ -181,6 +182,22 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
181
182
  super.updated(changed);
182
183
  this.sync();
183
184
  }
185
+ renderTooltips(start, end) {
186
+ if (!this.tooltip) {
187
+ return nothing;
188
+ }
189
+ const bubble = (fraction, text, thumb) => html `<span part="tooltip" data-thumb=${thumb ?? nothing} style="--slider-at: ${fraction}"
190
+ >${text}</span
191
+ >`;
192
+ return html `<div part="tooltips" aria-hidden="true">
193
+ ${this.range
194
+ ? [
195
+ bubble(this.along(start), this.said(start), 'start'),
196
+ bubble(this.along(end), this.said(end), 'end'),
197
+ ]
198
+ : bubble(this.fraction, this.said(this.value))}
199
+ </div>`;
200
+ }
184
201
  render() {
185
202
  const [start, end] = this.bounds;
186
203
  const thumb = (which, at) => html `<input
@@ -212,6 +229,7 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
212
229
  part="field"
213
230
  data-markers=${this.markerValues.length > 0 ? '' : nothing}
214
231
  data-range=${this.range ? '' : nothing}
232
+ data-tooltip=${this.tooltip ? '' : nothing}
215
233
  style="--slider-fraction: ${this.fraction}; --slider-from: ${this.along(start)}; --slider-to: ${this.along(end)}"
216
234
  >
217
235
  ${this.range ? thumb('start', start) : nothing}
@@ -247,6 +265,7 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
247
265
  >`)}
248
266
  </div>`
249
267
  : nothing}
268
+ ${this.renderTooltips(start, end)}
250
269
  ${this.showValue
251
270
  ? html `<output
252
271
  part="output"
@@ -310,6 +329,9 @@ __decorate([
310
329
  __decorate([
311
330
  property({ type: Number })
312
331
  ], HelixHeadlessSlider.prototype, "step", void 0);
332
+ __decorate([
333
+ property({ type: Boolean })
334
+ ], HelixHeadlessSlider.prototype, "tooltip", void 0);
313
335
  __decorate([
314
336
  property({ attribute: 'value-text' })
315
337
  ], HelixHeadlessSlider.prototype, "valueText", void 0);
@@ -1,18 +1,36 @@
1
- /** Where the highest and the lowest readings are, by place, or none. */
2
- export interface Extremes {
3
- /** The place of the highest reading, the first where several tie. */
4
- high?: number;
5
- /** The place of the lowest reading, the first where several tie. */
6
- low?: number;
7
- }
8
- /**
9
- * Where the highest and the lowest readings stand. A blank slot is passed
10
- * over, and a list with nothing in it has neither.
11
- */
12
- export declare const extremesOf: (slots: readonly (number | undefined)[]) => Extremes;
1
+ import { type Point } from '@fusion.dev/helix-core';
13
2
  /**
14
3
  * A reading in words, for the readout: the row's name where a table gave one,
15
4
  * the reading as it is written, and where it stands in brackets, such as
16
5
  * "Mon: 12 (3 of 7)". The same order every chart's readout uses.
17
6
  */
18
7
  export declare const readingWords: (label: string, text: string, position: string) => string;
8
+ /**
9
+ * The readings in their places: `count` slots, each holding the value read at
10
+ * that place, or nothing where the place is blank. A point outside the places
11
+ * is left out.
12
+ */
13
+ export declare const slotsOf: (points: readonly {
14
+ at: number;
15
+ value: number;
16
+ }[], count: number) => (number | undefined)[];
17
+ /** One unbroken stretch of the line: its drawn path and the points it runs through. */
18
+ export interface Run {
19
+ /** The path the line draws through the points. */
20
+ path: string;
21
+ /** The points, in drawing coordinates. */
22
+ run: readonly Point[];
23
+ }
24
+ /**
25
+ * Each run of the line closed down to `floor`, the path the wash fills: the
26
+ * run's own path, then down from its last point, across and back up to its
27
+ * first. Empty where there are no runs.
28
+ */
29
+ export declare const areaPath: (runs: readonly Run[], floor: number) => string;
30
+ /**
31
+ * What the readings come to, in `template`: `{first}` and `{last}` for the
32
+ * first and the last reading, `{high}` and `{low}` for the highest and the
33
+ * lowest, each written by `write`. Empty where there are fewer than two
34
+ * readings, which make no trend.
35
+ */
36
+ export declare const overviewWords: (template: string, slots: readonly (number | undefined)[], write: (at: number) => string) => string;
@@ -1,19 +1,36 @@
1
- export const extremesOf = (slots) => {
2
- const found = {};
3
- slots.forEach((value, at) => {
4
- if (value === undefined) {
5
- return;
6
- }
7
- if (found.high === undefined || value > slots[found.high]) {
8
- found.high = at;
9
- }
10
- if (found.low === undefined || value < slots[found.low]) {
11
- found.low = at;
12
- }
13
- });
14
- return found;
15
- };
1
+ import { extremesOf, fillTemplate } from '@fusion.dev/helix-core';
16
2
  export const readingWords = (label, text, position) => {
17
3
  const named = label === '' ? text : text === '' ? label : `${label}: ${text}`;
18
4
  return position === '' ? named : `${named} (${position})`;
19
5
  };
6
+ export const slotsOf = (points, count) => {
7
+ const slots = Array.from({ length: count }, () => undefined);
8
+ for (const point of points) {
9
+ if (point.at >= 0 && point.at < count) {
10
+ slots[point.at] = point.value;
11
+ }
12
+ }
13
+ return slots;
14
+ };
15
+ export const areaPath = (runs, floor) => runs
16
+ .map((one) => {
17
+ const first = one.run[0];
18
+ const last = one.run.at(-1);
19
+ return `${one.path}L${last[0]},${floor}L${first[0]},${floor}Z`;
20
+ })
21
+ .join('');
22
+ export const overviewWords = (template, slots, write) => {
23
+ const placed = slots.flatMap((value, at) => (value === undefined ? [] : [at]));
24
+ const first = placed[0];
25
+ const last = placed.at(-1);
26
+ const { high, low } = extremesOf(slots);
27
+ if (placed.length < 2 || first === undefined || last === undefined) {
28
+ return '';
29
+ }
30
+ return fillTemplate(template, {
31
+ first: write(first),
32
+ high: write(high),
33
+ last: write(last),
34
+ low: write(low),
35
+ });
36
+ };
@@ -1,4 +1,4 @@
1
- import { ChartPointerController, type Curve, HelixElement, SourceController } from '@fusion.dev/helix-core';
1
+ import { ChartPointerController, type Curve, HelixElement, type Series, SourceController } from '@fusion.dev/helix-core';
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  /**
4
4
  * @summary A small chart with no axes that shows the shape of a series beside its number.
@@ -19,10 +19,16 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
19
19
  * the last, Escape puts the reading away, and the `live` part says each
20
20
  * reading with where it stands, such as "Mon: 12 (3 of 7)".
21
21
  *
22
+ * **A named sparkline describes itself.** Beside its name, a screen reader
23
+ * hears what the readings come to, the first and the last, the highest and
24
+ * the lowest, in `overview-label`: "From 12 to 20, highest 30, lowest 8". An
25
+ * `aria-label` on the element names it as `label` does.
26
+ *
22
27
  * A pointer resting on the drawing shows the reading under it: the `cursor`
23
28
  * part marks it and the `readout` part writes it. `marks` adds a mark on the
24
- * highest and the lowest reading. A blank cell in a `for` table is a gap in
25
- * the line.
29
+ * highest and the lowest reading, and `range` draws a band between two values,
30
+ * such as a normal range. A blank cell in a `for` table is a gap in the line,
31
+ * and a reading alone between two blanks is a `lone` mark.
26
32
  *
27
33
  * Place it beside a `Stat`, because a change beside a figure is a second fact,
28
34
  * as `Stat`'s own spec says. `Trend` is composed the same way.
@@ -44,7 +50,10 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
44
50
  * @csspart high - The mark on the highest reading, under `marks="high"`. Placed as `cursor` is.
45
51
  * @csspart line - The line's path.
46
52
  * @csspart live - A polite region that says the reading a key moved to, rendered only with a `label`. Hide it visually.
53
+ * @csspart lone - The mark on a reading no line reaches, with a blank or an end on each side. Placed as `cursor` is.
47
54
  * @csspart low - The mark on the lowest reading, under `marks="low"`. Placed as `cursor` is.
55
+ * @csspart overview - What the readings come to, in `overview-label`, which describes the drawing. Rendered `hidden` with a name, since it is read through the description and not shown.
56
+ * @csspart range - The band between the two values of `range`, drawn behind the line.
48
57
  * @csspart readout - The reading a pointer or a key rests on, as the table or `values` writes it, rendered only while there is one. Placed as `cursor` is.
49
58
  * @csspart svg - The drawing, which takes focus to be read by key where there is a `label`.
50
59
  * @csspart terminus - The mark on the last value.
@@ -120,6 +129,15 @@ export declare class HelixHeadlessSparkline extends HelixElement {
120
129
  * placed at its reading, for a stylesheet to draw.
121
130
  */
122
131
  marks: string;
132
+ /**
133
+ * What the readings come to, said after the name: `{first}` and `{last}`
134
+ * for the first and the last reading, `{high}` and `{low}` for the highest
135
+ * and the lowest, each written as the readout writes it.
136
+ *
137
+ * Set it to the words of the page's language, or to nothing to say no
138
+ * more than the name. Said only where the sparkline is named.
139
+ */
140
+ overviewLabel: string;
123
141
  /**
124
142
  * What the readings are drawn as.
125
143
  *
@@ -159,6 +177,14 @@ export declare class HelixHeadlessSparkline extends HelixElement {
159
177
  * {count}`, or to nothing to say no position.
160
178
  */
161
179
  positionLabel: string;
180
+ /**
181
+ * Two values a band is drawn between, behind the line, separated by a
182
+ * space: `range="60 100"` marks a normal range.
183
+ *
184
+ * The scale stretches to hold the band where the readings do not reach it.
185
+ * Absent draws none.
186
+ */
187
+ range: string;
162
188
  /**
163
189
  * The numbers, separated by whitespace or by commas.
164
190
  *
@@ -174,6 +200,17 @@ export declare class HelixHeadlessSparkline extends HelixElement {
174
200
  * chart, so a sparkline is read the way they are.
175
201
  */
176
202
  readonly pointer: ChartPointerController;
203
+ /**
204
+ * Hears an `aria-label` written on the sparkline, which no property mirrors,
205
+ * because it names the drawing as `label` does, as on every chart.
206
+ */
207
+ static get observedAttributes(): string[];
208
+ /** Called by the browser when an observed attribute changes; a new `aria-label` renames the drawing. */
209
+ attributeChangedCallback(name: string, old: string | null, value: string | null): void;
210
+ /** The drawing's name: an `aria-label` written on the sparkline, then `label`. */
211
+ get named(): string;
212
+ /** The two values of `range`, lower first, or none. */
213
+ private get band();
177
214
  protected willUpdate(changed: PropertyValues<this>): void;
178
215
  /**
179
216
  * The series to draw, and how many readings it has room for: the table's
@@ -193,6 +230,12 @@ export declare class HelixHeadlessSparkline extends HelixElement {
193
230
  */
194
231
  private reading;
195
232
  protected render(): TemplateResult;
233
+ /**
234
+ * A mark on each reading with a blank on either side, which no line can
235
+ * reach, so a line and an area show it as `LineChart` does. Not on a bar
236
+ * plot, whose column already shows it.
237
+ */
238
+ protected renderLone(series: Series | undefined, at: (index: number, value: number) => string): TemplateResult | typeof nothing;
196
239
  /** The marks `marks` asks for, on the highest and the lowest reading. */
197
240
  protected renderMarks(slots: (number | undefined)[], at: (index: number, value: number) => string): TemplateResult | typeof nothing;
198
241
  /**
@@ -4,10 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { CHART_PLOT, ChartPointerController, customElement, extent, formatNumbers, HelixElement, linear, linePath, PLOT_WIDTH, SourceController, unbroken, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
7
+ import { CHART_PLOT, ChartPointerController, customElement, extent, extremesOf, formatNumbers, HelixElement, linear, linePath, PLOT_WIDTH, SourceController, unbroken, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing, svg } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
- import { extremesOf, readingWords } from '../readings.js';
10
+ import { areaPath, overviewWords, readingWords, slotsOf } from '../readings.js';
11
11
  const STRIP_HEIGHT = 32;
12
12
  let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
13
13
  constructor() {
@@ -16,11 +16,31 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
16
16
  this.label = '';
17
17
  this.locale = '';
18
18
  this.marks = '';
19
+ this.overviewLabel = 'From {first} to {last}, highest {high}, lowest {low}';
19
20
  this.positionLabel = '{position} of {count}';
21
+ this.range = '';
20
22
  this.values = '';
21
23
  this.source = new SourceController(this);
22
24
  this.pointer = new ChartPointerController(this);
23
25
  }
26
+ static get observedAttributes() {
27
+ return [...super.observedAttributes, 'aria-label'];
28
+ }
29
+ attributeChangedCallback(name, old, value) {
30
+ super.attributeChangedCallback(name, old, value);
31
+ if (name === 'aria-label') {
32
+ this.requestUpdate();
33
+ }
34
+ }
35
+ get named() {
36
+ return this.getAttribute?.('aria-label') || this.label;
37
+ }
38
+ get band() {
39
+ const [one, two] = writtenNumbers(this.range);
40
+ return one === undefined || two === undefined
41
+ ? undefined
42
+ : [Math.min(one, two), Math.max(one, two)];
43
+ }
24
44
  willUpdate(changed) {
25
45
  if (changed.has('for')) {
26
46
  this.source.watch();
@@ -54,15 +74,11 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
54
74
  }
55
75
  render() {
56
76
  const { count, series } = this.drawn();
57
- const slots = Array.from({ length: count }, () => undefined);
58
- for (const point of series.points) {
59
- if (point.at >= 0 && point.at < count) {
60
- slots[point.at] = point.value;
61
- }
62
- }
77
+ const slots = slotsOf(series.points, count);
63
78
  const points = slots.filter((value) => value !== undefined);
79
+ const band = this.band;
64
80
  const x = linear([0, Math.max(count - 1, 1)], [0, PLOT_WIDTH]);
65
- const [low, high] = extent(points.length > 0 ? points : [0]);
81
+ const [low, high] = extent(points.length > 0 ? [...points, ...(band ?? [])] : [0]);
66
82
  const y = this.plot === 'bar'
67
83
  ? linear([Math.min(0, low), Math.max(0, high)], [STRIP_HEIGHT, 0])
68
84
  : linear([low, high], [STRIP_HEIGHT, 0]);
@@ -73,15 +89,7 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
73
89
  .map((run) => ({ path: linePath(run, this.curve ?? 'smooth'), run }))
74
90
  .filter((one) => one.path !== '');
75
91
  const path = runs.map((one) => one.path).join('');
76
- const area = this.plot !== 'bar' && this.plot !== 'line' && path !== ''
77
- ? runs
78
- .map((one) => {
79
- const first = one.run[0];
80
- const last = one.run.at(-1);
81
- return `${one.path}L${last[0]},${STRIP_HEIGHT}L${first[0]},${STRIP_HEIGHT}Z`;
82
- })
83
- .join('')
84
- : '';
92
+ const area = this.plot !== 'bar' && this.plot !== 'line' && path !== '' ? areaPath(runs, STRIP_HEIGHT) : '';
85
93
  const slot = PLOT_WIDTH / Math.max(count, 1);
86
94
  const floor = y(0);
87
95
  const bars = this.plot === 'bar'
@@ -104,10 +112,15 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
104
112
  const across = this.plot === 'bar' ? index * slot + slot / 2 : x(index);
105
113
  return `inset-inline-start: ${(across / PLOT_WIDTH) * 100}%; inset-block-start: ${(y(value) / STRIP_HEIGHT) * 100}%`;
106
114
  };
107
- const named = this.label !== '';
115
+ const name = this.named;
116
+ const named = name !== '';
117
+ const overview = named
118
+ ? overviewWords(this.overviewLabel, slots, (index) => this.reading(index, slots[index]).text)
119
+ : '';
108
120
  return html `<svg
121
+ aria-describedby=${overview === '' ? nothing : 'sparkline-overview'}
109
122
  aria-hidden=${named ? nothing : 'true'}
110
- aria-label=${named ? this.label : nothing}
123
+ aria-label=${named ? name : nothing}
111
124
  data-mirror
112
125
  id=${CHART_PLOT}
113
126
  part="svg"
@@ -123,6 +136,15 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
123
136
  <stop offset="1" part="wash-end" />
124
137
  </linearGradient>
125
138
  </defs>`}
139
+ ${band === undefined
140
+ ? nothing
141
+ : svg `<rect
142
+ height=${Math.abs(y(band[0]) - y(band[1]))}
143
+ part="range"
144
+ width=${PLOT_WIDTH}
145
+ x="0"
146
+ y=${Math.min(y(band[0]), y(band[1]))}
147
+ />`}
126
148
  ${path === '' ? nothing : svg `<path d=${path} part="line" />`}
127
149
  ${area === '' ? nothing : svg `<path d=${area} part="area" />`}
128
150
  ${bars.map((bar) => svg `<rect
@@ -135,7 +157,18 @@ let HelixHeadlessSparkline = class HelixHeadlessSparkline extends HelixElement {
135
157
  </svg>
136
158
  ${points.length < 2 || this.plot === 'bar'
137
159
  ? nothing
138
- : html `<span aria-hidden="true" part="terminus" style=${end ?? nothing}></span>`}${this.renderMarks(slots, at)}${this.renderReading(slots, at)}${named && count > 0 ? this.renderLive(slots) : nothing}`;
160
+ : html `<span aria-hidden="true" part="terminus" style=${end ?? nothing}></span>`}${this.renderLone(points.length < 2 ? undefined : series, at)}${this.renderMarks(slots, at)}${this.renderReading(slots, at)}${named && count > 0 ? this.renderLive(slots) : nothing}${overview === ''
161
+ ? nothing
162
+ : html `<span hidden id="sparkline-overview" part="overview">${overview}</span>`}`;
163
+ }
164
+ renderLone(series, at) {
165
+ if (!series || this.plot === 'bar') {
166
+ return nothing;
167
+ }
168
+ const alone = unbroken(series).filter((run) => run.length === 1);
169
+ return alone.length === 0
170
+ ? nothing
171
+ : html `${alone.map(([point]) => html `<span aria-hidden="true" part="lone" style=${at(point?.at ?? 0, point?.value ?? 0)}></span>`)}`;
139
172
  }
140
173
  renderMarks(slots, at) {
141
174
  const asked = writtenList(this.marks);
@@ -184,12 +217,18 @@ __decorate([
184
217
  __decorate([
185
218
  property()
186
219
  ], HelixHeadlessSparkline.prototype, "marks", void 0);
220
+ __decorate([
221
+ property({ attribute: 'overview-label' })
222
+ ], HelixHeadlessSparkline.prototype, "overviewLabel", void 0);
187
223
  __decorate([
188
224
  property({ reflect: true })
189
225
  ], HelixHeadlessSparkline.prototype, "plot", void 0);
190
226
  __decorate([
191
227
  property({ attribute: 'position-label' })
192
228
  ], HelixHeadlessSparkline.prototype, "positionLabel", void 0);
229
+ __decorate([
230
+ property()
231
+ ], HelixHeadlessSparkline.prototype, "range", void 0);
193
232
  __decorate([
194
233
  property()
195
234
  ], HelixHeadlessSparkline.prototype, "values", void 0);
@@ -0,0 +1,48 @@
1
+ import { HelixElement } from '@fusion.dev/helix-core';
2
+ import { type PropertyValues, type TemplateResult } from 'lit';
3
+ /**
4
+ * @summary A named set of actions inside a speed dial, set apart from the rest.
5
+ *
6
+ * @description
7
+ * A `group` of the dial's menu, named by its label, as React Aria's menu
8
+ * sections and Menu's groups are: a reader hears the name on entering the set,
9
+ * and the arrow keys walk through every group's actions in order, from the
10
+ * last action of one group to the first of the next.
11
+ *
12
+ * Put actions straight into the group, and the group straight into the dial.
13
+ * Anything else slotted here is drawn and is not an action.
14
+ *
15
+ * @since 0.141.0
16
+ * @status stable
17
+ * @category actions
18
+ * @aliases Speed dial section, Action group
19
+ * @documentation https://fusion.dev/helix/components/speed-dial
20
+ *
21
+ * @slot - The group's actions.
22
+ * @slot label - The group's name, for content richer than the `label` text.
23
+ *
24
+ * @csspart group - The set, which carries the `group` role.
25
+ * @csspart label - The group's name, drawn above its actions while there is one.
26
+ */
27
+ export declare class HelixHeadlessSpeedDialGroup extends HelixElement {
28
+ /**
29
+ * The group's name, drawn above its actions and read by screen readers.
30
+ */
31
+ label: string;
32
+ /**
33
+ * @internal Read by the dial to find the actions inside a group, which is
34
+ * cheaper than `instanceof` and is why this is public rather than protected.
35
+ * Not a consumer's to read or set.
36
+ */
37
+ readonly isSpeedDialGroup = true;
38
+ /** Whether anything is in the `label` slot, so the name is drawn from it. */
39
+ private labelSlotted;
40
+ private readonly readLabel;
41
+ protected firstUpdated(changed: PropertyValues): void;
42
+ protected render(): TemplateResult;
43
+ }
44
+ declare global {
45
+ interface HTMLElementTagNameMap {
46
+ 'helix-headless-speed-dial-group': HelixHeadlessSpeedDialGroup;
47
+ }
48
+ }
@@ -0,0 +1,43 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { customElement, HelixElement, slotFilled } from '@fusion.dev/helix-core';
8
+ import { html, nothing } from 'lit';
9
+ import { property, state } from 'lit/decorators.js';
10
+ let HelixHeadlessSpeedDialGroup = class HelixHeadlessSpeedDialGroup extends HelixElement {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.label = '';
14
+ this.isSpeedDialGroup = true;
15
+ this.labelSlotted = false;
16
+ this.readLabel = () => {
17
+ this.labelSlotted = slotFilled(this.renderRoot.querySelector('slot[name="label"]'));
18
+ };
19
+ }
20
+ firstUpdated(changed) {
21
+ super.firstUpdated(changed);
22
+ this.readLabel();
23
+ }
24
+ render() {
25
+ const named = this.label !== '' || this.labelSlotted;
26
+ return html `<div part="group" role="group" aria-labelledby=${named ? 'label' : nothing}>
27
+ <span id="label" part="label" ?hidden=${!named}
28
+ ><slot name="label" @slotchange=${this.readLabel}>${this.label}</slot></span
29
+ >
30
+ <slot></slot>
31
+ </div>`;
32
+ }
33
+ };
34
+ __decorate([
35
+ property()
36
+ ], HelixHeadlessSpeedDialGroup.prototype, "label", void 0);
37
+ __decorate([
38
+ state()
39
+ ], HelixHeadlessSpeedDialGroup.prototype, "labelSlotted", void 0);
40
+ HelixHeadlessSpeedDialGroup = __decorate([
41
+ customElement('helix-headless-speed-dial-group')
42
+ ], HelixHeadlessSpeedDialGroup);
43
+ export { HelixHeadlessSpeedDialGroup };
@@ -1,2 +1,3 @@
1
+ export * from './group/speed-dial-group.js';
1
2
  export * from './item/speed-dial-item.js';
2
3
  export * from './root/speed-dial-root.js';
@@ -1,2 +1,3 @@
1
+ export * from './group/speed-dial-group.js';
1
2
  export * from './item/speed-dial-item.js';
2
3
  export * from './root/speed-dial-root.js';
@@ -1,5 +1,5 @@
1
1
  import { HelixElement } from '@fusion.dev/helix-core';
2
- import { type TemplateResult } from 'lit';
2
+ import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  /**
4
4
  * @summary One action in a speed dial: an icon and a name beside it.
5
5
  *
@@ -12,6 +12,13 @@ import { type TemplateResult } from 'lit';
12
12
  * `title` on an icon shows only on hover. Visible text is read, searched, and
13
13
  * translated like other text.
14
14
  *
15
+ * `shortcut` gives the action's keyboard shortcut as a chord, such as `mod+s`,
16
+ * the grammar Menu's rows use. The action carries it as `aria-keyshortcuts`
17
+ * and draws it after the name in the platform's glyphs or words, `⌘S` on an
18
+ * Apple keyboard and `Ctrl+S` elsewhere, as Menu draws its rows' shortcuts.
19
+ * Put a `Kbd` in the `shortcut` slot to draw it as keys instead; the dial
20
+ * imports no `Kbd` of its own. Showing a shortcut does not bind it.
21
+ *
15
22
  * @since 0.1.0
16
23
  * @status stable
17
24
  * @category actions
@@ -20,18 +27,26 @@ import { type TemplateResult } from 'lit';
20
27
  *
21
28
  * @slot - The action's name.
22
29
  * @slot icon - The action's icon, the main way the action is recognized.
30
+ * @slot shortcut - The action's keyboard shortcut, drawn after its name, such as a `Kbd`. It replaces the text drawn for `shortcut`, and is hidden from the name, which `aria-keyshortcuts` carries instead.
23
31
  *
24
32
  * @event {HelixSelectEvent} helix-select - The action was chosen. Cancelable: cancel it to keep the dial open.
25
33
  *
26
34
  * @csspart icon - The box that holds the icon.
27
35
  * @csspart item - The control for the action.
28
36
  * @csspart label - The action's name, beside the icon.
37
+ * @csspart shortcut - The box after the name that holds the shortcut, shown while `shortcut` is set or something is in the `shortcut` slot.
29
38
  */
30
39
  export declare class HelixHeadlessSpeedDialItem extends HelixElement {
31
40
  /**
32
41
  * Whether the action is disabled, so it cannot be chosen.
33
42
  */
34
43
  disabled: boolean;
44
+ /**
45
+ * The action's keyboard shortcut as a chord, such as `mod+s`, carried as
46
+ * `aria-keyshortcuts` and drawn after the name. `mod` is Command on an Apple
47
+ * keyboard and Control elsewhere. Showing a shortcut does not bind it.
48
+ */
49
+ shortcut: string;
35
50
  /**
36
51
  * The action's value, sent in `helix-select` when the action is chosen.
37
52
  */
@@ -43,7 +58,7 @@ export declare class HelixHeadlessSpeedDialItem extends HelixElement {
43
58
  */
44
59
  readonly isSpeedDialItem = true;
45
60
  /** Puts focus on the control inside the item. */
46
- focus(): void;
61
+ focus(options?: FocusOptions): void;
47
62
  /**
48
63
  * Moves focus to the action. Part of `NavigableItem`, which the shared
49
64
  * keyboard controller uses for the arrow keys.
@@ -66,9 +81,19 @@ export declare class HelixHeadlessSpeedDialItem extends HelixElement {
66
81
  * chosen out of a set, and a speed dial's action is never chosen that way.
67
82
  */
68
83
  get selected(): boolean;
84
+ /** Whether anything is in the `shortcut` slot, so its box is drawn. */
85
+ private hasShortcut;
86
+ private readonly readShortcut;
69
87
  private choose;
70
88
  private readonly handleClick;
71
89
  protected render(): TemplateResult;
90
+ /**
91
+ * The `shortcut` slot, holding the shortcut drawn after the name as Kbd
92
+ * draws a chord and from the same table: the slot's fallback, so a `Kbd`
93
+ * slotted in replaces it.
94
+ */
95
+ protected renderShortcut(): TemplateResult;
96
+ protected firstUpdated(changed: PropertyValues): void;
72
97
  }
73
98
  declare global {
74
99
  interface HTMLElementTagNameMap {