@fusion.dev/helix-headless 0.147.0 → 0.149.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 (296) hide show
  1. package/custom-elements.json +11222 -2332
  2. package/dist/accordion/item/accordion-item.d.ts +5 -2
  3. package/dist/accordion/item/accordion-item.js +11 -7
  4. package/dist/accordion/root/accordion-root.js +4 -6
  5. package/dist/announcement/root/announcement-root.d.ts +61 -5
  6. package/dist/announcement/root/announcement-root.js +126 -20
  7. package/dist/area-chart/root/area-chart-root.d.ts +11 -0
  8. package/dist/area-chart/root/area-chart-root.js +21 -9
  9. package/dist/avatar/group/avatar-group.d.ts +10 -2
  10. package/dist/avatar/group/avatar-group.js +10 -5
  11. package/dist/badge/count.d.ts +19 -0
  12. package/dist/badge/count.js +20 -0
  13. package/dist/badge/root/badge-root.d.ts +6 -2
  14. package/dist/badge/root/badge-root.js +8 -22
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +13 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +17 -4
  17. package/dist/blockquote/root/blockquote-root.d.ts +66 -8
  18. package/dist/blockquote/root/blockquote-root.js +85 -8
  19. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +2 -2
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +8 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +5 -2
  22. package/dist/button/root/button-root.d.ts +10 -1
  23. package/dist/button/root/button-root.js +3 -2
  24. package/dist/button-group/arrows.d.ts +14 -0
  25. package/dist/button-group/arrows.js +10 -0
  26. package/dist/button-group/root/button-group-root.d.ts +144 -3
  27. package/dist/button-group/root/button-group-root.js +142 -2
  28. package/dist/callout/root/callout-root.d.ts +16 -2
  29. package/dist/callout/root/callout-root.js +16 -4
  30. package/dist/canvas/describe.d.ts +10 -0
  31. package/dist/canvas/describe.js +9 -0
  32. package/dist/canvas/edge-pan.d.ts +61 -0
  33. package/dist/canvas/edge-pan.js +63 -0
  34. package/dist/canvas/neighbor.d.ts +17 -0
  35. package/dist/canvas/neighbor.js +1 -0
  36. package/dist/canvas/node/canvas-node.d.ts +12 -2
  37. package/dist/canvas/node/canvas-node.js +8 -3
  38. package/dist/canvas/root/canvas-document.d.ts +10 -0
  39. package/dist/canvas/root/canvas-document.js +1 -0
  40. package/dist/canvas/root/canvas-root.d.ts +168 -9
  41. package/dist/canvas/root/canvas-root.js +239 -69
  42. package/dist/canvas/snap.d.ts +42 -0
  43. package/dist/canvas/snap.js +32 -0
  44. package/dist/carousel/root/carousel-root.d.ts +9 -3
  45. package/dist/carousel/root/carousel-root.js +17 -10
  46. package/dist/chat/composer/chat-composer.d.ts +5 -0
  47. package/dist/chat/composer/chat-composer.js +4 -1
  48. package/dist/chat/message/chat-message.d.ts +9 -5
  49. package/dist/chat/message/chat-message.js +8 -4
  50. package/dist/chat/naming.js +2 -2
  51. package/dist/chat/root/chat-root.d.ts +40 -4
  52. package/dist/chat/root/chat-root.js +38 -14
  53. package/dist/checkbox/root/checkbox-root.d.ts +11 -0
  54. package/dist/checkbox/root/checkbox-root.js +8 -2
  55. package/dist/checkbox-group/root/checkbox-group-root.d.ts +24 -0
  56. package/dist/checkbox-group/root/checkbox-group-root.js +28 -12
  57. package/dist/checkbox-group/select-all.d.ts +11 -0
  58. package/dist/checkbox-group/select-all.js +5 -0
  59. package/dist/code-block/root/code-block-root.d.ts +20 -8
  60. package/dist/code-block/root/code-block-root.js +16 -5
  61. package/dist/color-input/root/color-input-root.d.ts +13 -0
  62. package/dist/color-input/root/color-input-root.js +18 -5
  63. package/dist/color-picker/root/color-picker-root.d.ts +19 -3
  64. package/dist/color-picker/root/color-picker-root.js +52 -24
  65. package/dist/color-picker/wheel.d.ts +11 -0
  66. package/dist/color-picker/wheel.js +9 -0
  67. package/dist/combobox/root/combobox-root.d.ts +106 -18
  68. package/dist/combobox/root/combobox-root.js +101 -26
  69. package/dist/command/root/command-root.d.ts +19 -9
  70. package/dist/command/root/command-root.js +9 -4
  71. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  72. package/dist/copy-button/root/copy-button-root.js +7 -2
  73. package/dist/data-table/root/data-table-root.d.ts +171 -29
  74. package/dist/data-table/root/data-table-root.js +284 -161
  75. package/dist/date-input/root/date-input-root.d.ts +32 -9
  76. package/dist/date-input/root/date-input-root.js +66 -44
  77. package/dist/date-picker/root/date-picker-root.d.ts +38 -15
  78. package/dist/date-picker/root/date-picker-root.js +52 -33
  79. package/dist/description-list/item/description-list-item.d.ts +4 -0
  80. package/dist/description-list/item/description-list-item.js +7 -1
  81. package/dist/dialog/root/dialog-root.d.ts +12 -1
  82. package/dist/dialog/root/dialog-root.js +11 -4
  83. package/dist/divider/root/divider-root.d.ts +45 -16
  84. package/dist/divider/root/divider-root.js +28 -4
  85. package/dist/donut-chart/root/donut-chart-root.d.ts +5 -0
  86. package/dist/donut-chart/root/donut-chart-root.js +8 -5
  87. package/dist/drawer/root/drawer-root.d.ts +12 -1
  88. package/dist/drawer/root/drawer-root.js +9 -2
  89. package/dist/drilldown/item/drilldown-item.js +3 -4
  90. package/dist/drilldown/root/drilldown-root.d.ts +5 -0
  91. package/dist/drilldown/root/drilldown-root.js +4 -1
  92. package/dist/element-events.generated.js +26 -3
  93. package/dist/empty/root/empty-root.d.ts +17 -3
  94. package/dist/empty/root/empty-root.js +29 -5
  95. package/dist/file-input/root/file-input-root.d.ts +18 -3
  96. package/dist/file-input/root/file-input-root.js +34 -18
  97. package/dist/file-input/status.js +2 -1
  98. package/dist/filter-input/chip/filter-chip.d.ts +13 -0
  99. package/dist/filter-input/chip/filter-chip.js +7 -3
  100. package/dist/filter-input/menu/filter-menu.d.ts +5 -0
  101. package/dist/filter-input/menu/filter-menu.js +3 -1
  102. package/dist/filter-input/root/filter-input-root.d.ts +20 -3
  103. package/dist/filter-input/root/filter-input-root.js +8 -4
  104. package/dist/format-date/fields.d.ts +20 -0
  105. package/dist/format-date/fields.js +14 -0
  106. package/dist/format-date/options.d.ts +2 -1
  107. package/dist/format-date/options.js +9 -38
  108. package/dist/format-date/root/format-date-root.d.ts +55 -5
  109. package/dist/format-date/root/format-date-root.js +29 -34
  110. package/dist/graph/root/graph-model.d.ts +11 -0
  111. package/dist/graph/root/graph-model.js +4 -0
  112. package/dist/graph/root/graph-root.d.ts +101 -14
  113. package/dist/graph/root/graph-root.js +140 -46
  114. package/dist/heatmap/root/heatmap-root.d.ts +37 -4
  115. package/dist/heatmap/root/heatmap-root.js +51 -16
  116. package/dist/icon-button/root/icon-button-root.d.ts +5 -0
  117. package/dist/icon-button/root/icon-button-root.js +1 -0
  118. package/dist/image/root/image-root.d.ts +11 -0
  119. package/dist/input/root/input-root.d.ts +5 -0
  120. package/dist/input/root/input-root.js +4 -1
  121. package/dist/kbd/root/kbd-root.js +1 -2
  122. package/dist/legend/root/legend-root.js +4 -17
  123. package/dist/lightbox/root/lightbox-root.d.ts +14 -4
  124. package/dist/lightbox/root/lightbox-root.js +25 -7
  125. package/dist/line-chart/root/line-chart-root.d.ts +5 -0
  126. package/dist/line-chart/root/line-chart-root.js +4 -2
  127. package/dist/list/item/list-item.d.ts +32 -0
  128. package/dist/list/item/list-item.js +34 -7
  129. package/dist/list/root/list-root.d.ts +87 -0
  130. package/dist/list/root/list-root.js +119 -23
  131. package/dist/listbox/reorder/index.d.ts +1 -0
  132. package/dist/listbox/reorder/index.js +4 -0
  133. package/dist/listbox/reorder/listbox-reorder.d.ts +83 -0
  134. package/dist/listbox/reorder/listbox-reorder.js +151 -0
  135. package/dist/listbox/root/listbox-root.d.ts +185 -33
  136. package/dist/listbox/root/listbox-root.js +166 -136
  137. package/dist/loader/root/loader-root.d.ts +5 -0
  138. package/dist/loader/root/loader-root.js +3 -1
  139. package/dist/map/area/map-area.d.ts +5 -0
  140. package/dist/map/area/map-area.js +3 -1
  141. package/dist/map/buildings/map-buildings.d.ts +5 -0
  142. package/dist/map/buildings/map-buildings.js +3 -1
  143. package/dist/map/contours/map-contours.d.ts +5 -0
  144. package/dist/map/contours/map-contours.js +3 -1
  145. package/dist/map/landcover/map-landcover.d.ts +5 -0
  146. package/dist/map/landcover/map-landcover.js +3 -1
  147. package/dist/map/marker/map-marker.d.ts +18 -2
  148. package/dist/map/marker/map-marker.js +13 -5
  149. package/dist/map/points/map-points.d.ts +5 -0
  150. package/dist/map/points/map-points.js +6 -4
  151. package/dist/map/position/map-position.d.ts +5 -0
  152. package/dist/map/position/map-position.js +3 -1
  153. package/dist/map/raster/map-raster.d.ts +5 -0
  154. package/dist/map/raster/map-raster.js +3 -1
  155. package/dist/map/root/map-root.d.ts +73 -16
  156. package/dist/map/root/map-root.js +122 -44
  157. package/dist/map/route/map-route.d.ts +5 -0
  158. package/dist/map/route/map-route.js +3 -1
  159. package/dist/map/terrain/map-terrain.d.ts +5 -0
  160. package/dist/map/terrain/map-terrain.js +3 -1
  161. package/dist/megamenu/root/megamenu-root.js +4 -11
  162. package/dist/menu/root/menu-root.d.ts +7 -2
  163. package/dist/menu/root/menu-root.js +3 -1
  164. package/dist/meter/root/meter-root.d.ts +16 -3
  165. package/dist/meter/root/meter-root.js +12 -5
  166. package/dist/navigation/root/navigation-root.d.ts +5 -0
  167. package/dist/navigation/root/navigation-root.js +7 -8
  168. package/dist/notifications/group/notification-group.d.ts +8 -1
  169. package/dist/notifications/group/notification-group.js +12 -6
  170. package/dist/notifications/notification/notification.d.ts +17 -1
  171. package/dist/notifications/notification/notification.js +6 -2
  172. package/dist/notifications/root/notifications-root.d.ts +49 -5
  173. package/dist/notifications/root/notifications-root.js +36 -8
  174. package/dist/number-input/root/number-input-root.d.ts +21 -8
  175. package/dist/number-input/root/number-input-root.js +26 -11
  176. package/dist/object-inspector/root/object-inspector-root.d.ts +56 -13
  177. package/dist/object-inspector/root/object-inspector-root.js +41 -30
  178. package/dist/outline/root/outline-root.d.ts +5 -0
  179. package/dist/outline/root/outline-root.js +3 -1
  180. package/dist/pagination/root/pagination-root.d.ts +7 -1
  181. package/dist/pagination/root/pagination-root.js +16 -7
  182. package/dist/pagination/size/pagination-size.d.ts +8 -3
  183. package/dist/pagination/size/pagination-size.js +5 -3
  184. package/dist/pagination/summary/pagination-summary.d.ts +8 -6
  185. package/dist/pagination/summary/pagination-summary.js +4 -9
  186. package/dist/pin-input/code.d.ts +23 -0
  187. package/dist/pin-input/code.js +21 -0
  188. package/dist/pin-input/root/pin-input-root.d.ts +9 -3
  189. package/dist/pin-input/root/pin-input-root.js +13 -23
  190. package/dist/popover/root/popover-root.d.ts +12 -2
  191. package/dist/popover/root/popover-root.js +10 -4
  192. package/dist/progress/root/progress-root.d.ts +7 -2
  193. package/dist/progress/root/progress-root.js +5 -2
  194. package/dist/qr-code/name.d.ts +3 -2
  195. package/dist/qr-code/name.js +2 -2
  196. package/dist/qr-code/root/qr-code-root.d.ts +26 -5
  197. package/dist/qr-code/root/qr-code-root.js +27 -6
  198. package/dist/radio/group/radio-group.d.ts +11 -0
  199. package/dist/radio/group/radio-group.js +8 -2
  200. package/dist/rating/root/rating-root.d.ts +12 -1
  201. package/dist/rating/root/rating-root.js +10 -3
  202. package/dist/scatter-chart/measures.d.ts +22 -0
  203. package/dist/scatter-chart/measures.js +11 -0
  204. package/dist/scatter-chart/root/scatter-chart-root.d.ts +22 -8
  205. package/dist/scatter-chart/root/scatter-chart-root.js +25 -23
  206. package/dist/select/root/select-root.d.ts +67 -8
  207. package/dist/select/root/select-root.js +45 -11
  208. package/dist/skip-link/root/skip-link-root.d.ts +5 -0
  209. package/dist/skip-link/root/skip-link-root.js +3 -1
  210. package/dist/slider/root/slider-root.d.ts +7 -2
  211. package/dist/slider/root/slider-root.js +11 -5
  212. package/dist/sparkline/readings.d.ts +15 -5
  213. package/dist/sparkline/readings.js +3 -3
  214. package/dist/sparkline/root/sparkline-root.d.ts +9 -4
  215. package/dist/sparkline/root/sparkline-root.js +9 -3
  216. package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
  217. package/dist/speed-dial/group/speed-dial-group.js +43 -0
  218. package/dist/speed-dial/index.d.ts +1 -0
  219. package/dist/speed-dial/index.js +1 -0
  220. package/dist/speed-dial/item/speed-dial-item.d.ts +26 -1
  221. package/dist/speed-dial/item/speed-dial-item.js +41 -3
  222. package/dist/speed-dial/long-press.d.ts +50 -0
  223. package/dist/speed-dial/long-press.js +48 -0
  224. package/dist/speed-dial/root/speed-dial-root.d.ts +85 -1
  225. package/dist/speed-dial/root/speed-dial-root.js +117 -5
  226. package/dist/splitter/root/splitter-root.d.ts +12 -3
  227. package/dist/splitter/root/splitter-root.js +22 -4
  228. package/dist/steps/root/steps-root.d.ts +9 -2
  229. package/dist/steps/root/steps-root.js +6 -3
  230. package/dist/steps/step/step.d.ts +12 -0
  231. package/dist/steps/step/step.js +11 -2
  232. package/dist/switch/root/switch-root.d.ts +11 -0
  233. package/dist/switch/root/switch-root.js +8 -2
  234. package/dist/table/cell/table-cell.d.ts +8 -1
  235. package/dist/table/cell/table-cell.js +6 -2
  236. package/dist/table/column/table-column.d.ts +11 -4
  237. package/dist/table/column/table-column.js +15 -10
  238. package/dist/table/grid-controller.d.ts +122 -0
  239. package/dist/table/grid-controller.js +299 -0
  240. package/dist/table/root/table-root.d.ts +154 -8
  241. package/dist/table/root/table-root.js +197 -38
  242. package/dist/table/row/table-row.d.ts +55 -1
  243. package/dist/table/row/table-row.js +60 -7
  244. package/dist/tabs/root/tabs-root.d.ts +5 -0
  245. package/dist/tabs/root/tabs-root.js +3 -1
  246. package/dist/tag/group/tag-group.d.ts +5 -0
  247. package/dist/tag/group/tag-group.js +8 -15
  248. package/dist/tag/root/tag-root.d.ts +14 -1
  249. package/dist/tag/root/tag-root.js +11 -8
  250. package/dist/textarea/root/textarea-root.d.ts +5 -0
  251. package/dist/textarea/root/textarea-root.js +3 -1
  252. package/dist/time-input/root/time-input-root.d.ts +14 -7
  253. package/dist/time-input/root/time-input-root.js +43 -32
  254. package/dist/time-picker/root/time-picker-root.d.ts +16 -7
  255. package/dist/time-picker/root/time-picker-root.js +28 -12
  256. package/dist/toast/item/toast-item.d.ts +13 -3
  257. package/dist/toast/item/toast-item.js +2 -0
  258. package/dist/toast/root/toast-root.d.ts +22 -2
  259. package/dist/toast/root/toast-root.js +24 -17
  260. package/dist/toggle/group/toggle-group.js +3 -5
  261. package/dist/toolbar/root/toolbar-root.d.ts +36 -0
  262. package/dist/toolbar/root/toolbar-root.js +43 -9
  263. package/dist/tooltip/root/tooltip-root.d.ts +27 -17
  264. package/dist/tooltip/root/tooltip-root.js +1 -2
  265. package/dist/tour/root/tour-root.d.ts +8 -2
  266. package/dist/tour/root/tour-root.js +4 -2
  267. package/dist/tour/stop/tour-stop.d.ts +5 -0
  268. package/dist/tour/stop/tour-stop.js +6 -1
  269. package/dist/tree/grip.d.ts +5 -0
  270. package/dist/tree/grip.js +1 -0
  271. package/dist/tree/item/tree-item.d.ts +24 -0
  272. package/dist/tree/item/tree-item.js +27 -5
  273. package/dist/tree/root/tree-root.d.ts +66 -1
  274. package/dist/tree/root/tree-root.js +77 -5
  275. package/dist/trend/root/trend-root.d.ts +20 -4
  276. package/dist/trend/root/trend-root.js +20 -5
  277. package/dist/video/root/video-root.d.ts +23 -3
  278. package/dist/video/root/video-root.js +56 -15
  279. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
  280. package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
  281. package/dist/video-playlist/root/video-playlist-root.d.ts +5 -0
  282. package/dist/video-playlist/root/video-playlist-root.js +3 -1
  283. package/dist/virtual-list/root/virtual-list-root.d.ts +19 -3
  284. package/dist/virtual-list/root/virtual-list-root.js +10 -19
  285. package/lint.json +1 -1
  286. package/package.json +7 -6
  287. package/types/jsx.d.ts +6005 -2114
  288. package/types/svelte.d.ts +1 -0
  289. package/types/vue.d.ts +1594 -676
  290. package/types/words.d.ts +3280 -0
  291. package/dist/kbd/keys.d.ts +0 -29
  292. package/dist/kbd/keys.js +0 -52
  293. package/dist/toast/hotkey.d.ts +0 -22
  294. package/dist/toast/hotkey.js +0 -23
  295. package/dist/tooltip/focus-target.d.ts +0 -6
  296. package/dist/tooltip/focus-target.js +0 -9
@@ -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, byRow, CHART_PLOT, commaList, customElement, drawTooltip, fillTemplate, formatNumbers, HelixBeforeChangeEvent, HelixElement, HelixResizeEvent, MixinChartSource, markRegion, pressedValue, rangeAdd, requestChange, StatusController, searchableById, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, byRow, CHART_PLOT, commaList, customElement, drawTooltip, formatWords, HelixElement, HelixResizeEvent, MixinChartSource, markRegion, pressedValue, rangeAdd, requestValue, StatusController, searchableById, words, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  import '../../tooltip/index.js';
@@ -16,8 +16,11 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
16
16
  this.emptyText = 'No readings';
17
17
  this.gap = 2;
18
18
  this.minCell = 8;
19
+ this.overviewLabel = '{busiestLabel}: {busiest}; {totalLabel} {total}.';
19
20
  this.rows = 1;
20
- this.selectionLabel = '{count} selected';
21
+ this.selectedLabel = 'selected';
22
+ this.selectionLabel = '{count, plural, one {# selected} other {# selected}}';
23
+ this.stripLabel = 'Heatmap';
21
24
  this.thresholds = '';
22
25
  this.tones = '';
23
26
  this.totalLabel = 'Total';
@@ -72,6 +75,7 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
72
75
  }
73
76
  };
74
77
  }
78
+ static { this.words = 'helix-heatmap'; }
75
79
  get visible() {
76
80
  return Math.min(this.points.length, this.room);
77
81
  }
@@ -84,15 +88,9 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
84
88
  if (next === this.value) {
85
89
  return;
86
90
  }
87
- requestChange({
88
- apply: (value) => {
89
- this.value = value;
90
- this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
91
- this.status.say(fillTemplate(this.selectionLabel, { count: commaList(value).length }));
92
- },
93
- event: (value) => new HelixBeforeChangeEvent({ value }),
94
- host: this,
95
- next,
91
+ requestValue(this, next, (value) => {
92
+ this.value = value;
93
+ this.status.say(formatWords(this, 'selectionLabel', { count: commaList(value).length }));
96
94
  });
97
95
  }
98
96
  press(index) {
@@ -213,7 +211,7 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
213
211
  const chosen = new Set(this.selectionMode ? commaList(this.value) : []);
214
212
  return html `<div
215
213
  aria-describedby=${readable ? 'helix-chart-summary' : nothing}
216
- aria-label=${this.named || 'Heatmap'}
214
+ aria-label=${this.named || this.stripLabel}
217
215
  part="strip"
218
216
  id=${CHART_PLOT}
219
217
  role=${readable ? 'application' : 'img'}
@@ -259,9 +257,13 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
259
257
  const { busiest, total } = overviewOf(cells);
260
258
  const row = rows[offset + busiest];
261
259
  const text = row?.cells[column]?.text ?? '';
262
- const most = row ? `${this.busiestLabel}: ${row.label}${text === '' ? '' : `, ${text}`}` : '';
263
- const sum = `${this.totalLabel} ${formatNumbers(this.locale)(total)}`;
264
- return html `<p id="helix-chart-summary" part="overview">${most ? `${most}; ${sum}` : sum}.</p>`;
260
+ const said = formatWords(this, 'overviewLabel', {
261
+ busiest: text === '' ? (row?.label ?? '') : `${row?.label ?? ''}, ${text}`,
262
+ busiestLabel: this.busiestLabel,
263
+ total,
264
+ totalLabel: this.totalLabel,
265
+ });
266
+ return html `<p id="helix-chart-summary" part="overview">${said}</p>`;
265
267
  }
266
268
  renderTooltip() {
267
269
  const at = this.pointer.at;
@@ -277,13 +279,32 @@ let HelixHeadlessHeatmap = class HelixHeadlessHeatmap extends MixinChartSource(H
277
279
  placement: 'top',
278
280
  x: `${column * (cell + gap) + cell / 2}px`,
279
281
  y: `${row * (cell + gap)}px`,
280
- }, undefined, this.pointer);
282
+ }, undefined, this.reading(at));
283
+ }
284
+ reading(at) {
285
+ const pointer = this.pointer;
286
+ const key = this.keysOf(this.drawn)[at] ?? '';
287
+ if (!this.selectionMode || key === '' || this.selectedLabel === '') {
288
+ return pointer;
289
+ }
290
+ if (!commaList(this.value).includes(key)) {
291
+ return pointer;
292
+ }
293
+ return {
294
+ column: pointer.column,
295
+ keyed: pointer.keyed,
296
+ position: pointer.position,
297
+ shows: (cell) => pointer.shows(cell),
298
+ state: this.selectedLabel,
299
+ };
281
300
  }
282
301
  };
283
302
  __decorate([
303
+ words,
284
304
  property({ attribute: 'busiest-label' })
285
305
  ], HelixHeadlessHeatmap.prototype, "busiestLabel", void 0);
286
306
  __decorate([
307
+ words,
287
308
  property({ attribute: 'empty-text' })
288
309
  ], HelixHeadlessHeatmap.prototype, "emptyText", void 0);
289
310
  __decorate([
@@ -292,15 +313,28 @@ __decorate([
292
313
  __decorate([
293
314
  property({ attribute: 'min-cell', type: Number })
294
315
  ], HelixHeadlessHeatmap.prototype, "minCell", void 0);
316
+ __decorate([
317
+ words,
318
+ property({ attribute: 'overview-label' })
319
+ ], HelixHeadlessHeatmap.prototype, "overviewLabel", void 0);
295
320
  __decorate([
296
321
  property({ type: Number })
297
322
  ], HelixHeadlessHeatmap.prototype, "rows", void 0);
298
323
  __decorate([
324
+ words,
325
+ property({ attribute: 'selected-label' })
326
+ ], HelixHeadlessHeatmap.prototype, "selectedLabel", void 0);
327
+ __decorate([
328
+ words,
299
329
  property({ attribute: 'selection-label' })
300
330
  ], HelixHeadlessHeatmap.prototype, "selectionLabel", void 0);
301
331
  __decorate([
302
332
  property({ attribute: 'selection-mode' })
303
333
  ], HelixHeadlessHeatmap.prototype, "selectionMode", void 0);
334
+ __decorate([
335
+ words,
336
+ property({ attribute: 'strip-label' })
337
+ ], HelixHeadlessHeatmap.prototype, "stripLabel", void 0);
304
338
  __decorate([
305
339
  property()
306
340
  ], HelixHeadlessHeatmap.prototype, "thresholds", void 0);
@@ -308,6 +342,7 @@ __decorate([
308
342
  property()
309
343
  ], HelixHeadlessHeatmap.prototype, "tones", void 0);
310
344
  __decorate([
345
+ words,
311
346
  property({ attribute: 'total-label' })
312
347
  ], HelixHeadlessHeatmap.prototype, "totalLabel", void 0);
313
348
  __decorate([
@@ -30,6 +30,11 @@ import { HelixHeadlessButton } from '../../button/root/button-root.js';
30
30
  * @csspart button - The inner button.
31
31
  */
32
32
  export declare class HelixHeadlessIconButton extends HelixHeadlessButton {
33
+ /**
34
+ * The key this family's words are registered under, its styled tag:
35
+ * `registerWords('de', { 'helix-icon-button': { pendingLabel: 'Wird geladen' } })`.
36
+ */
37
+ static words: string;
33
38
  }
34
39
  declare global {
35
40
  interface HTMLElementTagNameMap {
@@ -7,6 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessButton } from '../../button/root/button-root.js';
9
9
  let HelixHeadlessIconButton = class HelixHeadlessIconButton extends HelixHeadlessButton {
10
+ static { this.words = 'helix-icon-button'; }
10
11
  };
11
12
  HelixHeadlessIconButton = __decorate([
12
13
  customElement('helix-headless-icon-button')
@@ -16,6 +16,17 @@ import { type PropertyValues, type TemplateResult } from 'lit';
16
16
  * its own. The fallback is read once the picture fails, after the picture's
17
17
  * `alt`, so a reader hears that it did not load, as a sighted reader sees.
18
18
  *
19
+ * **An image with no `alt` says so.** At its first render it reports a
20
+ * `missing-alt` warning, printed in the console and counted by
21
+ * `@fusion.dev/helix-diagnostics`, which names the fix: describe the picture
22
+ * in `alt`, or write `alt=""` for one that is decoration. An image hidden with
23
+ * `aria-hidden="true"` needs neither and is not reported.
24
+ *
25
+ * A sheet of yours reads the state as `:state(loading)`, `:state(loaded)`,
26
+ * `:state(error)`, and `:state(waiting)`, the last while `placeholder-delay`
27
+ * holds the placeholder back. It can also read `data-status` on the host once
28
+ * the picture has loaded or failed.
29
+ *
19
30
  * @since 0.1.0
20
31
  * @status stable
21
32
  * @category media
@@ -69,6 +69,11 @@ declare const HelixHeadlessInput_base: (new (...args: any[]) => import("@fusion.
69
69
  * @cssstate invalid - The control has an error to show, from the browser's validation, `validate`, or your `feedback`.
70
70
  */
71
71
  export declare class HelixHeadlessInput extends HelixHeadlessInput_base {
72
+ /**
73
+ * The key this family's words are registered under, its styled tag:
74
+ * `registerWords('de', { 'helix-input': { clearLabel: 'Leeren' } })`.
75
+ */
76
+ static words: string;
72
77
  protected readonly aria: AriaForwardController;
73
78
  /** Typed or dragged, so every edit is announced. See `announcesInput`. */
74
79
  protected readonly announcesInput = true;
@@ -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, applyOwnRule, customElement, drawIcon, HelixClearEvent, HelixFormElement, holdCaret, MixinControllerValue, MixinField, restoreValue, submitImplicitly, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, applyOwnRule, customElement, drawIcon, HelixClearEvent, HelixFormElement, holdCaret, MixinControllerValue, MixinField, restoreValue, submitImplicitly, words, } from '@fusion.dev/helix-core';
8
8
  import { eye, eyeSlash, x } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -59,6 +59,7 @@ let HelixHeadlessInput = class HelixHeadlessInput extends MixinControllerValue(M
59
59
  this.step = '';
60
60
  this.type = 'text';
61
61
  }
62
+ static { this.words = 'helix-input'; }
62
63
  get effectiveType() {
63
64
  return this.revealed && this.type === 'password' ? 'text' : this.type;
64
65
  }
@@ -234,6 +235,7 @@ __decorate([
234
235
  property({ type: Boolean })
235
236
  ], HelixHeadlessInput.prototype, "clearable", void 0);
236
237
  __decorate([
238
+ words,
237
239
  property({ attribute: 'clear-label' })
238
240
  ], HelixHeadlessInput.prototype, "clearLabel", void 0);
239
241
  __decorate([
@@ -270,6 +272,7 @@ __decorate([
270
272
  state()
271
273
  ], HelixHeadlessInput.prototype, "revealed", void 0);
272
274
  __decorate([
275
+ words,
273
276
  property({ attribute: 'reveal-label' })
274
277
  ], HelixHeadlessInput.prototype, "revealLabel", void 0);
275
278
  __decorate([
@@ -4,10 +4,9 @@ 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 { ariaChord, chordParts, customElement, elementById, HelixElement, HelixShortcutEvent, matchesChord, onApple, printableChord, wordsConverter, } from '@fusion.dev/helix-core';
7
+ import { ariaChord, chordParts, customElement, elementById, HelixElement, HelixShortcutEvent, keyNames, matchesChord, onApple, printableChord, wordsConverter, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
- import { keyNames } from '../keys.js';
11
10
  import { claimShortcut, releaseShortcut } from '../shortcut.js';
12
11
  const typing = (node) => {
13
12
  if (node instanceof HTMLTextAreaElement) {
@@ -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 { customElement, HelixBeforeChangeEvent, HelixElement, KeyboardNavigationController, requestChange, SourceController, seriesIndex, seriesKey, typeaheadBy, } from '@fusion.dev/helix-core';
7
+ import { customElement, focusItemOf, HelixElement, KeyboardNavigationController, requestValue, SourceController, seriesIndex, seriesKey, typeaheadBy, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  import { isHidden, namesIn, toggledNames } from '../hidden-series.js';
@@ -19,14 +19,7 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
19
19
  this.stop = 0;
20
20
  this.keys = new KeyboardNavigationController(this, {
21
21
  items: () => this.toggles
22
- ? [...this.renderRoot.querySelectorAll('[part="toggle"]')].map((button) => ({
23
- contains: (node) => button.contains(node),
24
- disabled: false,
25
- focusItem: () => button.focus(),
26
- select: () => { },
27
- selected: false,
28
- words: button.textContent?.trim() ?? '',
29
- }))
22
+ ? [...this.renderRoot.querySelectorAll('[part="toggle"]')].map((button) => focusItemOf(button, { words: button.textContent?.trim() ?? '' }))
30
23
  : [],
31
24
  origin: 'focus',
32
25
  selects: () => false,
@@ -73,14 +66,8 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
73
66
  super.disconnectedCallback();
74
67
  }
75
68
  toggle(name) {
76
- requestChange({
77
- apply: (value) => {
78
- this.hiddenSeries = value;
79
- this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
80
- },
81
- event: (value) => new HelixBeforeChangeEvent({ value }),
82
- host: this,
83
- next: toggledNames(this.hiddenSeries, name),
69
+ requestValue(this, toggledNames(this.hiddenSeries, name), (value) => {
70
+ this.hiddenSeries = value;
84
71
  });
85
72
  }
86
73
  names() {
@@ -97,6 +97,11 @@ declare const HelixHeadlessLightbox_base: (new (...args: any[]) => import("@fusi
97
97
  * @cssstate zoomed - While the shown item is zoomed past its own size.
98
98
  */
99
99
  export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
100
+ /**
101
+ * The key this family's words are registered under, its styled tag:
102
+ * `registerWords('de', { 'helix-lightbox': { nextLabel: 'Weiter' } })`.
103
+ */
104
+ static words: string;
100
105
  /**
101
106
  * Draws the viewer's own previous, next and close controls over the picture,
102
107
  * and zoom-out and zoom-in controls where `max-zoom` allows zooming.
@@ -120,6 +125,8 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
120
125
  * interface.
121
126
  */
122
127
  dismissLabel: string;
128
+ /** The viewer's name where `label` is empty. */
129
+ fallbackLabel: string;
123
130
  /**
124
131
  * How long the user can be idle before the header and footer hide, in
125
132
  * milliseconds.
@@ -152,7 +159,7 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
152
159
  previousLabel: string;
153
160
  /**
154
161
  * The name of an item with no `label` of its own, with `{index}` and
155
- * `{count}` filled in.
162
+ * `{count}` filled in, written in the locale.
156
163
  */
157
164
  slideLabel: string;
158
165
  /**
@@ -163,7 +170,7 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
163
170
  slideRoleLabel: string;
164
171
  /**
165
172
  * The status text that says which item is shown, with `{index}`, `{count}`
166
- * and the item's `{label}` filled in.
173
+ * and the item's `{label}` filled in, the numbers written in the locale.
167
174
  *
168
175
  * Announced rather than only drawn, because the picture changing under a
169
176
  * reader who cannot see it is otherwise silent. A consumer who has their own
@@ -179,8 +186,11 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
179
186
  */
180
187
  zoomOutLabel: string;
181
188
  /**
182
- * What the live region says once a reader has stopped zooming, with the
183
- * scale as a whole `{percent}` filled in. Empty it to say nothing.
189
+ * What the live region says once a reader has stopped zooming. `{scale,
190
+ * number, percent}` writes the scale as a percentage the way the locale
191
+ * writes one, such as `150%`, or `150 %` in French. `{percent}` is the same
192
+ * scale as a whole number, for a sentence that places the sign itself. Empty
193
+ * it to say nothing.
184
194
  */
185
195
  zoomStatusLabel: string;
186
196
  /** Whether the reader has been still long enough to hide the chrome. */
@@ -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 { CommandController, customElement, DelayController, deepActiveElement, deepContains, drawDismiss, drawDismissGlyph, FullscreenController, fillTemplate, HelixElement, hostAria, IdleController, inlineStep, isRtl, keyClaimed, lockScroll, MixinControllerActive, MixinControllerOpen, resolveActiveItem, SwipeController, swipeStep, unlockScroll, whenHydrated, } from '@fusion.dev/helix-core';
7
+ import { CommandController, customElement, DelayController, deepActiveElement, deepContains, drawDismiss, drawDismissGlyph, FullscreenController, formatWords, HelixElement, hostAria, IdleController, inlineStep, isRtl, keyClaimed, lockScroll, MixinControllerActive, MixinControllerOpen, resolveActiveItem, SwipeController, swipeStep, unlockScroll, whenHydrated, words, } from '@fusion.dev/helix-core';
8
8
  import { caretLeft, caretRight, minus, plus } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -18,6 +18,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
18
18
  this.controls = false;
19
19
  this.counter = false;
20
20
  this.dismissLabel = 'Close';
21
+ this.fallbackLabel = 'Lightbox';
21
22
  this.idleDelay = 0;
22
23
  this.label = '';
23
24
  this.loop = false;
@@ -29,7 +30,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
29
30
  this.statusLabel = '{index} of {count}';
30
31
  this.zoomInLabel = 'Zoom in';
31
32
  this.zoomOutLabel = 'Zoom out';
32
- this.zoomStatusLabel = 'Zoomed to {percent}%';
33
+ this.zoomStatusLabel = 'Zoomed to {scale, number, percent}';
33
34
  this.resting = false;
34
35
  this.filled = false;
35
36
  this.announcement = '';
@@ -125,6 +126,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
125
126
  this.requestOpen(false);
126
127
  };
127
128
  }
129
+ static { this.words = 'helix-lightbox'; }
128
130
  drawZoom(scale, pan) {
129
131
  const viewport = this.partNamed('viewport');
130
132
  const zoomed = scale > 1;
@@ -144,7 +146,10 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
144
146
  return;
145
147
  }
146
148
  this.zoomSaid.start(400, () => {
147
- this.announcement = fillTemplate(this.zoomStatusLabel, { percent: percentOf(this.zoomScale) });
149
+ this.announcement = formatWords(this, 'zoomStatusLabel', {
150
+ percent: percentOf(this.zoomScale),
151
+ scale: this.zoomScale,
152
+ });
148
153
  });
149
154
  }
150
155
  zoomTo(scale) {
@@ -272,7 +277,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
272
277
  items.forEach((item, at) => {
273
278
  item.current = item === current;
274
279
  whenHydrated(item, () => {
275
- item.position = fillTemplate(this.slideLabel, {
280
+ item.position = formatWords(this, 'slideLabel', {
276
281
  count: items.length,
277
282
  index: at + 1,
278
283
  label: item.label,
@@ -301,7 +306,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
301
306
  this.announcement =
302
307
  at === -1 || !current
303
308
  ? ''
304
- : fillTemplate(this.statusLabel, {
309
+ : formatWords(this, 'statusLabel', {
305
310
  count: items.length,
306
311
  index: at + 1,
307
312
  label: current.label,
@@ -311,7 +316,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
311
316
  const items = this.items;
312
317
  const current = resolveActiveItem(this.active, items);
313
318
  return current
314
- ? fillTemplate(this.statusLabel, {
319
+ ? formatWords(this, 'statusLabel', {
315
320
  count: items.length,
316
321
  index: items.indexOf(current) + 1,
317
322
  label: current.label,
@@ -321,7 +326,7 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
321
326
  render() {
322
327
  return html `<dialog
323
328
  part="dialog"
324
- aria-label=${this.label || 'Lightbox'}
329
+ aria-label=${this.label || this.fallbackLabel}
325
330
  autofocus
326
331
  tabindex="-1"
327
332
  @cancel=${this.handleCancel}
@@ -412,8 +417,13 @@ __decorate([
412
417
  property({ reflect: true, type: Boolean })
413
418
  ], HelixHeadlessLightbox.prototype, "counter", void 0);
414
419
  __decorate([
420
+ words,
415
421
  property({ attribute: 'dismiss-label' })
416
422
  ], HelixHeadlessLightbox.prototype, "dismissLabel", void 0);
423
+ __decorate([
424
+ words,
425
+ property({ attribute: 'fallback-label' })
426
+ ], HelixHeadlessLightbox.prototype, "fallbackLabel", void 0);
417
427
  __decorate([
418
428
  property({ attribute: 'idle-delay', type: Number })
419
429
  ], HelixHeadlessLightbox.prototype, "idleDelay", void 0);
@@ -427,27 +437,35 @@ __decorate([
427
437
  property({ attribute: 'max-zoom', type: Number })
428
438
  ], HelixHeadlessLightbox.prototype, "maxZoom", void 0);
429
439
  __decorate([
440
+ words,
430
441
  property({ attribute: 'next-label' })
431
442
  ], HelixHeadlessLightbox.prototype, "nextLabel", void 0);
432
443
  __decorate([
444
+ words,
433
445
  property({ attribute: 'previous-label' })
434
446
  ], HelixHeadlessLightbox.prototype, "previousLabel", void 0);
435
447
  __decorate([
448
+ words,
436
449
  property({ attribute: 'slide-label' })
437
450
  ], HelixHeadlessLightbox.prototype, "slideLabel", void 0);
438
451
  __decorate([
452
+ words,
439
453
  property({ attribute: 'slide-role-label' })
440
454
  ], HelixHeadlessLightbox.prototype, "slideRoleLabel", void 0);
441
455
  __decorate([
456
+ words,
442
457
  property({ attribute: 'status-label' })
443
458
  ], HelixHeadlessLightbox.prototype, "statusLabel", void 0);
444
459
  __decorate([
460
+ words,
445
461
  property({ attribute: 'zoom-in-label' })
446
462
  ], HelixHeadlessLightbox.prototype, "zoomInLabel", void 0);
447
463
  __decorate([
464
+ words,
448
465
  property({ attribute: 'zoom-out-label' })
449
466
  ], HelixHeadlessLightbox.prototype, "zoomOutLabel", void 0);
450
467
  __decorate([
468
+ words,
451
469
  property({ attribute: 'zoom-status-label' })
452
470
  ], HelixHeadlessLightbox.prototype, "zoomStatusLabel", void 0);
453
471
  __decorate([
@@ -81,6 +81,11 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
81
81
  * @cssproperty --chart-terminus-y - Where a series' last reading sits vertically, as a percentage. Written by the component.
82
82
  */
83
83
  export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base {
84
+ /**
85
+ * The key this family's words are registered under, its styled tag:
86
+ * `registerWords('de', { 'helix-line-chart': { positionLabel: '{position} von {count}' } })`.
87
+ */
88
+ static words: string;
84
89
  /**
85
90
  * Draws a wash under each line, down to the floor of the plot. The washes
86
91
  * overlap and do not add up, so for parts that make a total, use
@@ -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 { byRow, CHART_PLOT, commaList, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, ticks, unbroken, } from '@fusion.dev/helix-core';
7
+ import { byRow, CHART_PLOT, commaList, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, ticks, unbroken, wordsLocale, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing, svg } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import '../../tooltip/index.js';
@@ -16,6 +16,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
16
16
  this.markers = false;
17
17
  this.zero = false;
18
18
  }
19
+ static { this.words = 'helix-line-chart'; }
19
20
  get rulesValue() {
20
21
  return this.gridlines !== undefined && this.gridlines !== 'category';
21
22
  }
@@ -71,8 +72,9 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
71
72
  return [{ label: last.label, reading: `${one.name} ${text}` }];
72
73
  });
73
74
  const shared = latest.every((one) => one.label === latest[0]?.label);
75
+ const listed = new Intl.ListFormat(wordsLocale(this), { style: 'short', type: 'unit' });
74
76
  const body = shared
75
- ? `${latest[0]?.label ?? ''}: ${latest.map((one) => one.reading).join(', ')}`
77
+ ? `${latest[0]?.label ?? ''}: ${listed.format(latest.map((one) => one.reading))}`
76
78
  : latest.map((one) => `${one.label}: ${one.reading}`).join('; ');
77
79
  const named = this.named ? `${this.named}, ` : '';
78
80
  return html `<p id="helix-chart-summary" part="summary">${named}${body}.</p>`;
@@ -2,6 +2,8 @@ import { HelixElement } from '@fusion.dev/helix-core';
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  /** The values `current` takes, which are `aria-current`'s. */
4
4
  export type ListItemCurrent = 'date' | 'location' | 'page' | 'step' | 'time' | 'true';
5
+ /** Where a row stands in a move: the row being moved, or the one the drop indicator is beside. */
6
+ export type ListItemMove = 'dragging' | 'drop-after' | 'drop-before';
5
7
  /**
6
8
  * @summary One row of a list.
7
9
  *
@@ -35,6 +37,11 @@ export type ListItemCurrent = 'date' | 'location' | 'page' | 'step' | 'time' | '
35
37
  * selects, whether it is selected. Its link leaves the tab order there, and
36
38
  * Enter follows it from the row.
37
39
  *
40
+ * **In a `reorderable` list, the row has a grip** after its `end` slot, named
41
+ * by the list's `move-label`. The list says which row is moving and where the
42
+ * drop indicator is, with the `dragging`, `drop-before`, and `drop-after`
43
+ * states.
44
+ *
38
45
  * @since 0.1.0
39
46
  * @status stable
40
47
  * @aliases Row, Entry
@@ -47,10 +54,15 @@ export type ListItemCurrent = 'date' | 'location' | 'page' | 'step' | 'time' | '
47
54
  *
48
55
  * @event {HelixActionEvent} helix-action - The reader pressed Enter on the row, or pressed the row in a list that selects nothing, in a list with `selection-mode`. Read the row from `target`. A row with `href` follows its link instead.
49
56
  *
57
+ * @csspart grip - The button that moves the row, in a `reorderable` list.
58
+ * @csspart grip-mark - The icon on the grip.
50
59
  * @csspart link - The link, when the row has `href`. It holds every region except `end`.
51
60
  * @csspart row - The row's layout. It sits inside the host so the host can carry a list marker. In a list with `selection-mode` it is the grid cell that takes focus.
52
61
  * @csspart row-current - Added to `row` while the row is `current`.
53
62
  *
63
+ * @cssstate dragging - The row is being moved, in a `reorderable` list.
64
+ * @cssstate drop-after - The row being moved goes after this one when it is dropped.
65
+ * @cssstate drop-before - The row being moved goes before this one when it is dropped.
54
66
  * @cssstate selected - The row is selected, in a list that selects.
55
67
  */
56
68
  export declare class HelixHeadlessListItem extends HelixElement {
@@ -77,6 +89,13 @@ export declare class HelixHeadlessListItem extends HelixElement {
77
89
  * it is coordination between elements, as `Tag.focusable` is.
78
90
  */
79
91
  focusable?: boolean | undefined;
92
+ /**
93
+ * The name of the row's grip, written by a `reorderable` list from its
94
+ * `move-label`, and unset in a list that does not reorder, which draws no
95
+ * grip. No attribute: it is coordination between elements, as `focusable`
96
+ * is.
97
+ */
98
+ grip?: string | undefined;
80
99
  /**
81
100
  * The URL the row links to. Leave it empty for a row that is not a link.
82
101
  *
@@ -85,6 +104,11 @@ export declare class HelixHeadlessListItem extends HelixElement {
85
104
  * to the current page on every row a consumer never asked to be one.
86
105
  */
87
106
  href: string;
107
+ /**
108
+ * Where the row stands in a move, written by a `reorderable` list: the row
109
+ * being moved, or the one the drop indicator is beside. Unset otherwise.
110
+ */
111
+ move?: ListItemMove | undefined;
88
112
  /**
89
113
  * The link's `rel` value. You set it yourself. It is not derived from
90
114
  * `target`, for the reason `Tree.Item` gives.
@@ -121,11 +145,19 @@ export declare class HelixHeadlessListItem extends HelixElement {
121
145
  * over.
122
146
  */
123
147
  get controls(): HTMLElement[];
148
+ /** @internal The grip that moves the row, in a `reorderable` list. */
149
+ get gripElement(): HTMLElement | null;
124
150
  /** Moves focus to the row's cell, in a list with `selection-mode`. */
125
151
  focusItem(): void;
126
152
  /** @internal Follows the row's link, as a press on it would. Called by the list on Enter. */
127
153
  follow(): void;
128
154
  protected willUpdate(changed: PropertyValues): void;
155
+ /**
156
+ * The grip, after `end`, in a `reorderable` list. A tab stop of its own in a
157
+ * list a reader reads, and reached with Left and Right in a list with
158
+ * `selection-mode`, as a control in `end` is.
159
+ */
160
+ private renderGrip;
129
161
  /**
130
162
  * The cell before the row's content, which this tier leaves empty.
131
163
  *