@fusion.dev/helix-headless 0.142.1 → 0.144.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 (285) hide show
  1. package/custom-elements.json +25381 -1202
  2. package/dist/accordion/item/accordion-item.d.ts +38 -2
  3. package/dist/accordion/item/accordion-item.js +38 -6
  4. package/dist/accordion/root/accordion-root.d.ts +23 -1
  5. package/dist/accordion/root/accordion-root.js +39 -3
  6. package/dist/announcement/root/announcement-root.d.ts +11 -7
  7. package/dist/announcement/root/announcement-root.js +1 -1
  8. package/dist/app-header/root/app-header-root.d.ts +21 -0
  9. package/dist/app-header/root/app-header-root.js +31 -5
  10. package/dist/area-chart/root/area-chart-root.d.ts +12 -4
  11. package/dist/area-chart/root/area-chart-root.js +39 -11
  12. package/dist/avatar/group/avatar-group.d.ts +24 -3
  13. package/dist/avatar/group/avatar-group.js +34 -2
  14. package/dist/avatar/root/avatar-root.d.ts +17 -1
  15. package/dist/avatar/root/avatar-root.js +31 -10
  16. package/dist/badge/root/badge-root.d.ts +12 -0
  17. package/dist/badge/root/badge-root.js +1 -1
  18. package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
  19. package/dist/bar-chart/root/bar-chart-root.js +58 -21
  20. package/dist/blockquote/root/blockquote-root.d.ts +12 -7
  21. package/dist/blockquote/root/blockquote-root.js +6 -4
  22. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
  23. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
  24. package/dist/button/root/button-root.d.ts +84 -1
  25. package/dist/button/root/button-root.js +81 -3
  26. package/dist/callout/root/callout-root.d.ts +32 -6
  27. package/dist/callout/root/callout-root.js +26 -7
  28. package/dist/canvas/root/canvas-root.d.ts +1 -0
  29. package/dist/canvas/root/canvas-root.js +10 -1
  30. package/dist/card/root/card-root.d.ts +30 -1
  31. package/dist/card/root/card-root.js +38 -5
  32. package/dist/carousel/root/carousel-root.d.ts +47 -5
  33. package/dist/carousel/root/carousel-root.js +53 -21
  34. package/dist/chat/composer/chat-composer.d.ts +13 -11
  35. package/dist/chat/composer/chat-composer.js +6 -12
  36. package/dist/chat/message/chat-message.js +8 -1
  37. package/dist/chat/root/chat-root.d.ts +1 -0
  38. package/dist/chat/root/chat-root.js +2 -1
  39. package/dist/checkbox/root/checkbox-root.d.ts +7 -0
  40. package/dist/checkbox/root/checkbox-root.js +9 -3
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
  42. package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
  43. package/dist/code/root/code-root.d.ts +1 -1
  44. package/dist/code-block/lines.d.ts +13 -0
  45. package/dist/code-block/lines.js +2 -0
  46. package/dist/code-block/root/code-block-root.d.ts +49 -0
  47. package/dist/code-block/root/code-block-root.js +44 -3
  48. package/dist/color-input/root/color-input-root.d.ts +60 -2
  49. package/dist/color-input/root/color-input-root.js +55 -7
  50. package/dist/color-picker/channels.d.ts +26 -0
  51. package/dist/color-picker/channels.js +84 -0
  52. package/dist/color-picker/root/color-picker-root.d.ts +118 -12
  53. package/dist/color-picker/root/color-picker-root.js +183 -13
  54. package/dist/combobox/root/combobox-root.d.ts +126 -3
  55. package/dist/combobox/root/combobox-root.js +224 -21
  56. package/dist/command/root/command-root.d.ts +47 -10
  57. package/dist/command/root/command-root.js +45 -4
  58. package/dist/copy-button/from.d.ts +22 -0
  59. package/dist/copy-button/from.js +28 -0
  60. package/dist/copy-button/root/copy-button-root.d.ts +48 -7
  61. package/dist/copy-button/root/copy-button-root.js +54 -8
  62. package/dist/data-table/root/data-table-root.d.ts +164 -10
  63. package/dist/data-table/root/data-table-root.js +488 -57
  64. package/dist/date-input/root/date-input-root.d.ts +123 -9
  65. package/dist/date-input/root/date-input-root.js +147 -45
  66. package/dist/date-picker/root/date-picker-root.d.ts +229 -18
  67. package/dist/date-picker/root/date-picker-root.js +342 -46
  68. package/dist/dialog/description.d.ts +9 -0
  69. package/dist/dialog/description.js +14 -0
  70. package/dist/dialog/root/dialog-root.d.ts +101 -10
  71. package/dist/dialog/root/dialog-root.js +83 -4
  72. package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
  73. package/dist/donut-chart/root/donut-chart-root.js +48 -13
  74. package/dist/drawer/root/drawer-root.d.ts +93 -7
  75. package/dist/drawer/root/drawer-root.js +126 -5
  76. package/dist/drawer/swipe-start.d.ts +9 -0
  77. package/dist/drawer/swipe-start.js +12 -0
  78. package/dist/drilldown/item/drilldown-item.d.ts +16 -13
  79. package/dist/drilldown/item/drilldown-item.js +6 -2
  80. package/dist/drilldown/root/drilldown-root.d.ts +21 -5
  81. package/dist/drilldown/root/drilldown-root.js +26 -10
  82. package/dist/element-events.generated.js +42 -13
  83. package/dist/empty/root/empty-root.d.ts +1 -1
  84. package/dist/file-input/root/file-input-root.d.ts +65 -1
  85. package/dist/file-input/root/file-input-root.js +76 -12
  86. package/dist/file-input/screen.d.ts +35 -0
  87. package/dist/file-input/screen.js +49 -0
  88. package/dist/filter-input/menu/filter-menu.d.ts +9 -0
  89. package/dist/filter-input/menu/filter-menu.js +8 -0
  90. package/dist/filter-input/root/filter-input-root.d.ts +43 -6
  91. package/dist/filter-input/root/filter-input-root.js +89 -10
  92. package/dist/filter-input/suggest.d.ts +17 -0
  93. package/dist/filter-input/suggest.js +23 -0
  94. package/dist/format-date/options.d.ts +33 -0
  95. package/dist/format-date/options.js +42 -0
  96. package/dist/format-date/root/format-date-root.d.ts +62 -3
  97. package/dist/format-date/root/format-date-root.js +78 -37
  98. package/dist/graph/root/graph-root.d.ts +24 -3
  99. package/dist/graph/root/graph-root.js +66 -12
  100. package/dist/heatmap/root/buckets.d.ts +2 -1
  101. package/dist/heatmap/root/buckets.js +5 -1
  102. package/dist/heatmap/root/heatmap-root.d.ts +47 -9
  103. package/dist/heatmap/root/heatmap-root.js +46 -18
  104. package/dist/icon/index.d.ts +2 -0
  105. package/dist/icon/index.js +2 -0
  106. package/dist/icon/registry.d.ts +37 -0
  107. package/dist/icon/registry.js +83 -0
  108. package/dist/icon/root/icon-root.d.ts +53 -6
  109. package/dist/icon/root/icon-root.js +72 -4
  110. package/dist/icon/root/index.d.ts +2 -0
  111. package/dist/icon/root/index.js +2 -0
  112. package/dist/icon/set.d.ts +1 -0
  113. package/dist/icon/set.js +3 -0
  114. package/dist/icon-button/root/icon-button-root.d.ts +1 -1
  115. package/dist/image/root/image-root.d.ts +23 -2
  116. package/dist/image/root/image-root.js +23 -4
  117. package/dist/input/root/input-root.d.ts +62 -9
  118. package/dist/input/root/input-root.js +61 -5
  119. package/dist/kbd/root/kbd-root.d.ts +26 -11
  120. package/dist/kbd/root/kbd-root.js +35 -38
  121. package/dist/kbd/shortcut.d.ts +18 -0
  122. package/dist/kbd/shortcut.js +35 -0
  123. package/dist/legend/hidden-series.d.ts +8 -0
  124. package/dist/legend/hidden-series.js +13 -0
  125. package/dist/legend/root/legend-root.d.ts +63 -0
  126. package/dist/legend/root/legend-root.js +61 -7
  127. package/dist/lightbox/item/lightbox-item.d.ts +17 -1
  128. package/dist/lightbox/item/lightbox-item.js +10 -1
  129. package/dist/lightbox/root/lightbox-root.d.ts +77 -6
  130. package/dist/lightbox/root/lightbox-root.js +116 -5
  131. package/dist/line-chart/root/line-chart-root.d.ts +29 -4
  132. package/dist/line-chart/root/line-chart-root.js +58 -17
  133. package/dist/list/item/list-item.d.ts +11 -5
  134. package/dist/list/item/list-item.js +5 -6
  135. package/dist/listbox/range.d.ts +17 -0
  136. package/dist/listbox/range.js +5 -0
  137. package/dist/listbox/root/listbox-root.d.ts +184 -4
  138. package/dist/listbox/root/listbox-root.js +229 -23
  139. package/dist/loader/busy.d.ts +17 -0
  140. package/dist/loader/busy.js +24 -0
  141. package/dist/loader/root/loader-root.d.ts +37 -0
  142. package/dist/loader/root/loader-root.js +52 -3
  143. package/dist/map/root/map-root.d.ts +19 -4
  144. package/dist/map/root/map-root.js +36 -7
  145. package/dist/megamenu/root/megamenu-root.d.ts +10 -1
  146. package/dist/megamenu/root/megamenu-root.js +10 -1
  147. package/dist/menu/item/menu-item.d.ts +41 -12
  148. package/dist/menu/item/menu-item.js +46 -3
  149. package/dist/menu/root/menu-root.d.ts +32 -2
  150. package/dist/menu/root/menu-root.js +48 -8
  151. package/dist/meter/root/meter-root.d.ts +13 -0
  152. package/dist/meter/root/meter-root.js +24 -5
  153. package/dist/navigation/root/navigation-root.d.ts +10 -2
  154. package/dist/navigation/root/navigation-root.js +13 -2
  155. package/dist/notifications/feed-keys.d.ts +10 -0
  156. package/dist/notifications/feed-keys.js +14 -0
  157. package/dist/notifications/group/notification-group.d.ts +1 -0
  158. package/dist/notifications/notification/notification.d.ts +29 -0
  159. package/dist/notifications/notification/notification.js +51 -3
  160. package/dist/notifications/root/notifications-root.d.ts +49 -0
  161. package/dist/notifications/root/notifications-root.js +76 -2
  162. package/dist/number-input/root/number-input-root.d.ts +109 -7
  163. package/dist/number-input/root/number-input-root.js +109 -21
  164. package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
  165. package/dist/object-inspector/root/object-inspector-root.js +92 -12
  166. package/dist/option/root/option-root.d.ts +58 -6
  167. package/dist/option/root/option-root.js +35 -5
  168. package/dist/outline/root/outline-root.d.ts +13 -2
  169. package/dist/outline/root/outline-root.js +4 -2
  170. package/dist/pagination/root/pagination-root.d.ts +19 -1
  171. package/dist/pagination/root/pagination-root.js +49 -9
  172. package/dist/pagination/size/pagination-size.d.ts +13 -3
  173. package/dist/pagination/size/pagination-size.js +7 -0
  174. package/dist/pin-input/format.d.ts +7 -0
  175. package/dist/pin-input/format.js +16 -0
  176. package/dist/pin-input/root/pin-input-root.d.ts +37 -0
  177. package/dist/pin-input/root/pin-input-root.js +48 -7
  178. package/dist/popover/root/popover-root.d.ts +78 -3
  179. package/dist/popover/root/popover-root.js +74 -5
  180. package/dist/progress/root/progress-root.d.ts +23 -1
  181. package/dist/progress/root/progress-root.js +40 -10
  182. package/dist/qr-code/export.d.ts +31 -0
  183. package/dist/qr-code/export.js +10 -0
  184. package/dist/qr-code/root/qr-code-root.d.ts +45 -0
  185. package/dist/qr-code/root/qr-code-root.js +78 -3
  186. package/dist/radio/group/radio-group.d.ts +64 -0
  187. package/dist/radio/group/radio-group.js +66 -12
  188. package/dist/radio/root/radio-root.d.ts +8 -5
  189. package/dist/radio/root/radio-root.js +1 -2
  190. package/dist/rating/root/rating-root.d.ts +49 -1
  191. package/dist/rating/root/rating-root.js +69 -10
  192. package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
  193. package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
  194. package/dist/select/root/select-root.d.ts +93 -3
  195. package/dist/select/root/select-root.js +111 -13
  196. package/dist/skeleton/root/skeleton-root.d.ts +39 -3
  197. package/dist/skeleton/root/skeleton-root.js +33 -4
  198. package/dist/skip-link/root/skip-link-root.d.ts +10 -0
  199. package/dist/skip-link/root/skip-link-root.js +15 -1
  200. package/dist/slider/root/slider-root.d.ts +59 -2
  201. package/dist/slider/root/slider-root.js +82 -8
  202. package/dist/sparkline/root/sparkline-root.d.ts +9 -10
  203. package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
  204. package/dist/speed-dial/item/speed-dial-item.js +7 -2
  205. package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
  206. package/dist/speed-dial/root/speed-dial-root.js +19 -5
  207. package/dist/splitter/root/splitter-root.d.ts +28 -6
  208. package/dist/splitter/root/splitter-root.js +35 -1
  209. package/dist/stat/root/stat-root.d.ts +9 -1
  210. package/dist/stat/root/stat-root.js +15 -2
  211. package/dist/steps/root/steps-root.js +1 -1
  212. package/dist/steps/step/step.d.ts +1 -0
  213. package/dist/steps/step/step.js +1 -1
  214. package/dist/switch/root/switch-root.d.ts +14 -2
  215. package/dist/switch/root/switch-root.js +7 -1
  216. package/dist/table/cell/table-cell.d.ts +24 -4
  217. package/dist/table/cell/table-cell.js +21 -1
  218. package/dist/table/column/table-column.d.ts +32 -6
  219. package/dist/table/column/table-column.js +36 -6
  220. package/dist/table/root/table-root.d.ts +94 -3
  221. package/dist/table/root/table-root.js +128 -5
  222. package/dist/table/row/table-row.d.ts +7 -0
  223. package/dist/table/row/table-row.js +9 -1
  224. package/dist/tabs/root/tabs-root.d.ts +6 -1
  225. package/dist/tabs/root/tabs-root.js +6 -2
  226. package/dist/tag/group/tag-group.d.ts +107 -0
  227. package/dist/tag/group/tag-group.js +157 -0
  228. package/dist/tag/index.d.ts +1 -0
  229. package/dist/tag/index.js +1 -0
  230. package/dist/tag/root/tag-root.d.ts +83 -1
  231. package/dist/tag/root/tag-root.js +87 -17
  232. package/dist/tag/selection.d.ts +10 -0
  233. package/dist/tag/selection.js +12 -0
  234. package/dist/textarea/grow.d.ts +22 -0
  235. package/dist/textarea/grow.js +20 -0
  236. package/dist/textarea/root/textarea-root.d.ts +13 -0
  237. package/dist/textarea/root/textarea-root.js +10 -2
  238. package/dist/time-input/root/time-input-root.d.ts +71 -6
  239. package/dist/time-input/root/time-input-root.js +110 -44
  240. package/dist/time-picker/root/time-picker-root.d.ts +155 -26
  241. package/dist/time-picker/root/time-picker-root.js +192 -63
  242. package/dist/toast/hotkey.d.ts +22 -0
  243. package/dist/toast/hotkey.js +23 -0
  244. package/dist/toast/item/toast-item.d.ts +16 -1
  245. package/dist/toast/item/toast-item.js +41 -13
  246. package/dist/toast/root/toast-root.d.ts +105 -8
  247. package/dist/toast/root/toast-root.js +209 -4
  248. package/dist/toggle/group/toggle-group.d.ts +95 -16
  249. package/dist/toggle/group/toggle-group.js +99 -13
  250. package/dist/toggle/root/toggle-root.d.ts +26 -11
  251. package/dist/toggle/root/toggle-root.js +14 -6
  252. package/dist/toolbar/root/toolbar-root.d.ts +55 -15
  253. package/dist/toolbar/root/toolbar-root.js +99 -16
  254. package/dist/tooltip/focus-target.d.ts +6 -0
  255. package/dist/tooltip/focus-target.js +9 -0
  256. package/dist/tooltip/root/tooltip-root.d.ts +73 -15
  257. package/dist/tooltip/root/tooltip-root.js +96 -7
  258. package/dist/tour/naming.d.ts +30 -0
  259. package/dist/tour/naming.js +10 -0
  260. package/dist/tour/root/tour-root.d.ts +67 -3
  261. package/dist/tour/root/tour-root.js +105 -17
  262. package/dist/tour/stop/tour-stop.d.ts +65 -3
  263. package/dist/tour/stop/tour-stop.js +61 -11
  264. package/dist/tour/wait.d.ts +11 -0
  265. package/dist/tour/wait.js +19 -0
  266. package/dist/tree/item/tree-item.d.ts +21 -5
  267. package/dist/tree/item/tree-item.js +14 -4
  268. package/dist/tree/root/tree-root.d.ts +29 -5
  269. package/dist/tree/root/tree-root.js +64 -8
  270. package/dist/trend/root/trend-root.d.ts +36 -1
  271. package/dist/trend/root/trend-root.js +41 -15
  272. package/dist/video/root/keys.d.ts +5 -0
  273. package/dist/video/root/keys.js +13 -1
  274. package/dist/video/root/video-root.d.ts +19 -0
  275. package/dist/video/root/video-root.js +48 -4
  276. package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
  277. package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
  278. package/dist/video-playlist/root/video-playlist-root.js +6 -3
  279. package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
  280. package/dist/virtual-list/root/virtual-list-root.js +103 -21
  281. package/lint.json +1 -1
  282. package/package.json +5 -5
  283. package/types/jsx.d.ts +9140 -1149
  284. package/types/svelte.d.ts +1 -0
  285. package/types/vue.d.ts +2089 -267
@@ -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, HelixElement, hostAria, reportRuntime } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixElement, hostAria, reportRuntime, whenHydrated, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  export const FOLDS_UP_TO = 12;
@@ -12,6 +12,8 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
12
12
  constructor() {
13
13
  super(...arguments);
14
14
  this.label = '';
15
+ this.overflowLabel = '{count} more';
16
+ this.folded = new WeakSet();
15
17
  this.warned = false;
16
18
  }
17
19
  get avatars() {
@@ -32,6 +34,7 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
32
34
  }
33
35
  updated(changed) {
34
36
  super.updated(changed);
37
+ this.fold();
35
38
  const limit = this.max ?? 0;
36
39
  if (limit > FOLDS_UP_TO && this.avatars.length > limit && !this.warned) {
37
40
  this.warned = true;
@@ -44,10 +47,36 @@ let HelixHeadlessAvatarGroup = class HelixHeadlessAvatarGroup extends HelixEleme
44
47
  });
45
48
  }
46
49
  }
50
+ fold() {
51
+ const limit = this.max ?? 0;
52
+ const limited = limit > 0 && limit <= FOLDS_UP_TO;
53
+ for (const [index, avatar] of this.avatars.entries()) {
54
+ const past = limited && index >= limit;
55
+ if (past && !avatar.hidden) {
56
+ this.folded.add(avatar);
57
+ whenHydrated(avatar, () => {
58
+ avatar.hidden = true;
59
+ });
60
+ }
61
+ else if (!past && this.folded.has(avatar)) {
62
+ this.folded.delete(avatar);
63
+ whenHydrated(avatar, () => {
64
+ avatar.hidden = false;
65
+ });
66
+ }
67
+ }
68
+ }
47
69
  render() {
48
70
  const past = this.overflow;
49
71
  return html `<slot @slotchange=${() => this.requestUpdate()}></slot>
50
- ${past > 0 ? html `<span part="overflow" aria-hidden="true">+${past}</span>` : ''}`;
72
+ ${past > 0
73
+ ? html `<span
74
+ part="overflow"
75
+ role="img"
76
+ aria-label=${this.overflowLabel.replace('{count}', String(past))}
77
+ >+${past}</span
78
+ >`
79
+ : ''}`;
51
80
  }
52
81
  };
53
82
  __decorate([
@@ -56,6 +85,9 @@ __decorate([
56
85
  __decorate([
57
86
  property({ reflect: true, type: Number })
58
87
  ], HelixHeadlessAvatarGroup.prototype, "max", void 0);
88
+ __decorate([
89
+ property({ attribute: 'overflow-label' })
90
+ ], HelixHeadlessAvatarGroup.prototype, "overflowLabel", void 0);
59
91
  HelixHeadlessAvatarGroup = __decorate([
60
92
  customElement('helix-headless-avatar-group')
61
93
  ], HelixHeadlessAvatarGroup);
@@ -32,6 +32,17 @@ export declare const initialsOf: (name: string) => string;
32
32
  * @csspart initials - The initials shown when there is no usable image.
33
33
  */
34
34
  export declare class HelixHeadlessAvatar extends HelixElement {
35
+ /**
36
+ * How long, in milliseconds, a picture may take before the initials stand
37
+ * in for it while it loads.
38
+ *
39
+ * Absent keeps the picture's place empty until it arrives or fails. Set,
40
+ * the initials show once the wait is over and the picture
41
+ * replaces them when it arrives, so a slow connection shows who it is
42
+ * without a cached picture flashing initials first. Radix's `delayMs` is the
43
+ * same idea.
44
+ */
45
+ fallbackDelay?: number;
35
46
  /**
36
47
  * Name of the person or entity.
37
48
  *
@@ -46,7 +57,9 @@ export declare class HelixHeadlessAvatar extends HelixElement {
46
57
  src: string;
47
58
  /**
48
59
  * The image's state: `loading` while it is on its way, `loaded` once it
49
- * arrives, or `error` when it fails and the initials replace it.
60
+ * arrives, or `error` when it fails and the initials replace it. An avatar
61
+ * with no `src` has no image to wait for, and reports `error` as well, since
62
+ * the initials are what it shows.
50
63
  *
51
64
  * Read-only to a consumer: it is a report rather than a setting, and the same
52
65
  * report `Image` gives, for the same reason. `load` and `error` fire once, so
@@ -63,10 +76,13 @@ export declare class HelixHeadlessAvatar extends HelixElement {
63
76
  * report waits for the event it reports, below.
64
77
  */
65
78
  private broken;
79
+ /** The wait `fallback-delay` asks for, which has run out for the picture loading now or not. */
80
+ private readonly wait;
66
81
  private readonly handleError;
67
82
  private readonly handleLoad;
68
83
  protected willUpdate(changed: PropertyValues): void;
69
84
  protected firstUpdated(changed: PropertyValues): void;
85
+ private startWait;
70
86
  protected updated(changed: PropertyValues): void;
71
87
  protected render(): TemplateResult;
72
88
  /**
@@ -4,8 +4,8 @@ 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, hostAria } from '@fusion.dev/helix-core';
8
- import { html } from 'lit';
7
+ import { customElement, DelayController, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
+ import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  export const initialsOf = (name) => {
11
11
  const words = name.trim().split(/\s+/).filter(Boolean);
@@ -24,6 +24,7 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
24
24
  this.src = '';
25
25
  this.status = 'loading';
26
26
  this.broken = false;
27
+ this.wait = new DelayController(this);
27
28
  this.handleError = (event) => {
28
29
  this.broken = true;
29
30
  this.status = 'error';
@@ -38,7 +39,7 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
38
39
  super.willUpdate(changed);
39
40
  if (changed.has('src')) {
40
41
  this.broken = false;
41
- this.status = 'loading';
42
+ this.status = this.src === '' && this.hasUpdated ? 'error' : 'loading';
42
43
  }
43
44
  hostAria(this.internals, {
44
45
  label: this.name,
@@ -47,6 +48,13 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
47
48
  }
48
49
  firstUpdated(changed) {
49
50
  super.firstUpdated(changed);
51
+ if (this.src === '') {
52
+ setTimeout(() => {
53
+ if (this.src === '' && this.status === 'loading') {
54
+ this.status = 'error';
55
+ }
56
+ });
57
+ }
50
58
  const image = this.serverRendered ? this.renderRoot.querySelector('img') : null;
51
59
  if (image?.complete) {
52
60
  const broken = image.naturalWidth === 0;
@@ -57,8 +65,16 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
57
65
  });
58
66
  }
59
67
  }
68
+ startWait() {
69
+ this.wait.start(this.fallbackDelay !== undefined && this.src !== ''
70
+ ? Math.max(this.fallbackDelay, 0)
71
+ : undefined);
72
+ }
60
73
  updated(changed) {
61
74
  super.updated(changed);
75
+ if (changed.has('src') || changed.has('fallbackDelay')) {
76
+ this.startWait();
77
+ }
62
78
  if (changed.has('status')) {
63
79
  if (this.status === 'loading') {
64
80
  this.removeAttribute('data-status');
@@ -70,13 +86,15 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
70
86
  }
71
87
  render() {
72
88
  if (this.src !== '' && !this.broken) {
73
- return html `<img
74
- part="image"
75
- src=${this.src}
76
- alt=""
77
- @error=${this.handleError}
78
- @load=${this.handleLoad}
79
- />`;
89
+ const standIn = this.wait.elapsed && this.status === 'loading';
90
+ return html `${standIn ? this.renderInitials() : nothing}<img
91
+ part="image"
92
+ src=${this.src}
93
+ alt=""
94
+ ?hidden=${standIn}
95
+ @error=${this.handleError}
96
+ @load=${this.handleLoad}
97
+ />`;
80
98
  }
81
99
  return this.renderInitials();
82
100
  }
@@ -86,6 +104,9 @@ let HelixHeadlessAvatar = class HelixHeadlessAvatar extends HelixElement {
86
104
  </slot>`;
87
105
  }
88
106
  };
107
+ __decorate([
108
+ property({ attribute: 'fallback-delay', type: Number })
109
+ ], HelixHeadlessAvatar.prototype, "fallbackDelay", void 0);
89
110
  __decorate([
90
111
  property()
91
112
  ], HelixHeadlessAvatar.prototype, "name", void 0);
@@ -18,6 +18,18 @@ import { type TemplateResult } from 'lit';
18
18
  * fuller name, such as `4 unread`. A dot needs a `label`. Without one, the dot
19
19
  * is a colored circle that screen readers do not announce.
20
20
  *
21
+ * **A badge wrapped around a control is not part of the control's name.** It
22
+ * is a status of its own, read when it changes and when a reader moves to it,
23
+ * so focusing a button inside a badge announces the button's name alone. A
24
+ * reference from the control to the count would point into the badge's shadow
25
+ * root, which the platform does not allow.
26
+ *
27
+ * **Put the badge inside the control to have its count read with the
28
+ * control's name**, as Web Awesome and Shoelace do: `<button>Inbox
29
+ * <helix-badge value="8" label="8 unread"></helix-badge></button>` is the
30
+ * button "Inbox 8 unread", and stays current as the count changes. The styled
31
+ * tier's `placement="inline"` draws the mark in the line for that case.
32
+ *
21
33
  * @since 0.1.0
22
34
  * @status stable
23
35
  * @category markers
@@ -36,7 +36,7 @@ let HelixHeadlessBadge = class HelixHeadlessBadge extends HelixElement {
36
36
  data-blank=${blank ? '' : nothing}
37
37
  data-single=${text.length <= 1 ? '' : nothing}
38
38
  role="status"
39
- aria-label=${this.label !== '' && announced ? this.label : nothing}
39
+ aria-label=${announced ? this.label || text : nothing}
40
40
  >${blank ? html `<span aria-hidden="true">${text}</span>` : text}</span
41
41
  >`;
42
42
  }
@@ -15,8 +15,17 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
15
15
  * and 43px in a wide one, and SVG has no setting that keeps text at one size
16
16
  * the way `vector-effect` does for strokes.
17
17
  *
18
- * The table is the accessible representation, and the drawing is `aria-hidden`,
19
- * so screen reader users get the numbers themselves.
18
+ * The table is the accessible representation, and the drawing is hidden from
19
+ * screen readers, so they get the numbers themselves. The `summary` part names
20
+ * the chart, from `label` or the table's caption, and gives each series' highest
21
+ * reading.
22
+ *
23
+ * **The plot is read by key.** It takes focus, named by `label` or the caption.
24
+ * The arrows along the categories move from one to the next, which is left and
25
+ * right for columns and up and down for `orientation="horizontal"`. Home and
26
+ * End go to the first and the last, and the other pair of arrows moves among
27
+ * the series of a category. The tooltip follows, the `live` part says the
28
+ * reading in words, and Escape puts the tooltip away.
20
29
  *
21
30
  * The component writes the custom properties below with numbers it computes,
22
31
  * and the stylesheet that draws the chart reads them. Do not set them yourself.
@@ -39,8 +48,10 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
39
48
  * @csspart label - One category's name.
40
49
  * @csspart labels - The row of category names.
41
50
  * @csspart line - A series drawn as a line, named in `lines`.
51
+ * @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
42
52
  * @csspart mark - The invisible point the tooltip is anchored to.
43
- * @csspart plot - The drawing.
53
+ * @csspart plot - The drawing, which takes focus to be read by key.
54
+ * @csspart summary - The chart's name and each series' highest reading, written as a sentence for screen readers. Hide it visually.
44
55
  * @csspart svg - The drawing surface the bars and lines sit on.
45
56
  * @csspart tick - One number on an axis.
46
57
  * @csspart tooltip - The tooltip bubble, forwarded from `Tooltip`.
@@ -52,6 +63,7 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
52
63
  * @csspart tooltip-arrow-top - The arrow while the bubble is above the reading, on the bubble's bottom edge. Set together with `tooltip-arrow`.
53
64
  * @csspart tooltip-bottom - The bubble while it is below the reading. Set together with `tooltip`.
54
65
  * @csspart tooltip-cell - One column's name and value inside the tooltip.
66
+ * @csspart tooltip-cell-current - The cell the series keys rest on, while they rest there. Set alongside `tooltip-cell`.
55
67
  * @csspart tooltip-label - The reading's category name inside the tooltip.
56
68
  * @csspart tooltip-left - The bubble while it is left of the reading. Set together with `tooltip`.
57
69
  * @csspart tooltip-name - A column's name inside the tooltip.
@@ -87,6 +99,10 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
87
99
  * and reach no reader through the table.
88
100
  */
89
101
  gridlines?: 'both' | 'category' | 'value';
102
+ /**
103
+ * The word the summary puts before each series' highest reading.
104
+ */
105
+ highestLabel: string;
90
106
  /**
91
107
  * The names of the series to draw as lines. The other series are drawn as
92
108
  * columns.
@@ -121,8 +137,8 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
121
137
  * turns on its side, and neither is as readable as putting them down the left
122
138
  * where they read normally.
123
139
  *
124
- * `orientation` and not `orientation`, which `Trend` uses in the same group for
125
- * which way a number moved.
140
+ * Named `orientation` because `direction` is taken: `Trend` uses it in the
141
+ * same group for which way a number moved.
126
142
  */
127
143
  orientation?: 'horizontal';
128
144
  /**
@@ -182,6 +198,15 @@ export declare class HelixHeadlessBarChart extends HelixHeadlessBarChart_base {
182
198
  */
183
199
  protected willUpdate(changed: PropertyValues<this>): void;
184
200
  protected render(): TemplateResult;
201
+ /**
202
+ * What a reader who cannot see the columns is told: the chart's name and
203
+ * each series' highest reading.
204
+ *
205
+ * The highest, because which category leads is the question a bar chart is
206
+ * read for, and the table beside it has every other number. The reading is
207
+ * written the way the table writes it, such as `$128k` for `128000`.
208
+ */
209
+ protected renderSummary(series: Series[]): TemplateResult;
185
210
  /**
186
211
  * The columns themselves, behind a seam the styled tier can move.
187
212
  *
@@ -4,11 +4,15 @@ 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, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, ticks, } from '@fusion.dev/helix-core';
7
+ import { byRow, CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, ticks, unbroken, } 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';
11
11
  let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource(HelixElement) {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.highestLabel = 'Highest';
15
+ }
12
16
  get scaled() {
13
17
  return new Set(seriesNames(this.secondary));
14
18
  }
@@ -27,15 +31,16 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
27
31
  }
28
32
  render() {
29
33
  const series = this.series;
30
- const categories = series[0]?.points.map((point) => point.label) ?? [];
34
+ const categories = series.length === 0 ? [] : this.sourceRows.map((row) => row.label);
31
35
  if (categories.length === 0) {
32
36
  return html `<div id=${CHART_PLOT} part="plot"></div>`;
33
37
  }
34
38
  const scaled = this.scaled;
35
39
  const own = (one) => scaled.has(one.name.trim().toLowerCase());
36
- const values = series.flatMap((one) => one.points.map((point) => point.value));
40
+ const shown = series.filter((one) => this.showsSeries(one.name));
41
+ const values = shown.flatMap((one) => one.points.map((point) => point.value));
37
42
  const on = (which) => {
38
- const found = series.filter(which).flatMap((one) => one.points.map((point) => point.value));
43
+ const found = shown.filter(which).flatMap((one) => one.points.map((point) => point.value));
39
44
  return found.length > 0 ? found : values.length > 0 ? values : [0];
40
45
  };
41
46
  const [low, high] = extent(scaled.size === 0 ? on(() => true) : on((one) => !own(one)));
@@ -49,12 +54,26 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
49
54
  const z = scaled.size > 0 ? linear(other, range) : undefined;
50
55
  const widest = z === undefined
51
56
  ? 0
52
- : Math.max(...[...ticks(domain), ...ticks(other)].map((level) => level.toLocaleString().length));
57
+ : Math.max(...[...ticks(domain), ...ticks(other)].map((level) => formatNumbers(this.locale)(level).length));
53
58
  const lone = series.filter(own);
54
59
  const tint = lone.length === 1 && lone[0] !== undefined
55
60
  ? `--bar-chart-secondary: var(--chart-series-${seriesIndex(series.indexOf(lone[0]))})`
56
61
  : undefined;
57
- return html `${z === undefined ? nothing : this.renderAxis(y, domain, 'primary', sideways, widest)}${this.renderPlot(series, categories, y, domain, floor, z)}${z === undefined ? nothing : this.renderAxis(z, other, 'secondary', sideways, widest, tint)}${this.renderLabels(categories)}`;
62
+ return html `${z === undefined ? nothing : this.renderAxis(y, domain, 'primary', sideways, widest)}${this.renderPlot(series, categories, y, domain, floor, z)}${z === undefined ? nothing : this.renderAxis(z, other, 'secondary', sideways, widest, tint)}${this.renderLabels(categories)}${this.renderSummary(series)}`;
63
+ }
64
+ renderSummary(series) {
65
+ const rows = this.sourceRows;
66
+ const columns = this.plottedColumns;
67
+ const highest = series.flatMap((one, depth) => {
68
+ const top = one.points.reduce((best, point) => (best === undefined || point.value > best.value ? point : best), undefined);
69
+ if (top === undefined) {
70
+ return [];
71
+ }
72
+ const text = rows[top.at]?.cells[columns[depth] ?? -1]?.text ?? String(top.value);
73
+ return [`${one.name} ${top.label} ${text}`];
74
+ });
75
+ const named = this.named ? `${this.named}. ` : '';
76
+ return html `<p id="helix-chart-summary" part="summary">${named}${this.highestLabel}: ${highest.join('; ')}.</p>`;
58
77
  }
59
78
  renderPlot(series, categories, y, domain, floor, z) {
60
79
  const sideways = this.orientation === 'horizontal';
@@ -64,8 +83,8 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
64
83
  const own = (one) => scaled.has(one.name.trim().toLowerCase());
65
84
  const against = (one) => z !== undefined && own(one) ? z : y;
66
85
  const columns = series
67
- .map((one, index) => ({ one, tone: index }))
68
- .filter(({ one }) => !lined.has(one.name.trim().toLowerCase()));
86
+ .map((one, index) => ({ one, slots: byRow(one, categories.length), tone: index }))
87
+ .filter(({ one }) => !lined.has(one.name.trim().toLowerCase()) && this.showsSeries(one.name));
69
88
  const stride = (slot * 0.72) / Math.max(columns.length, 1);
70
89
  const gap = columns.length > 1 ? stride * 0.08 : 0;
71
90
  const thickness = stride - gap;
@@ -95,11 +114,16 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
95
114
  />`;
96
115
  };
97
116
  return html `<div
98
- aria-hidden="true"
117
+ aria-describedby=${this.named ? 'helix-chart-summary' : nothing}
118
+ aria-label=${this.named || nothing}
119
+ aria-labelledby=${this.named ? nothing : 'helix-chart-summary'}
99
120
  id=${CHART_PLOT}
100
121
  part="plot"
122
+ role="application"
123
+ tabindex="0"
101
124
  >
102
125
  <svg part="svg"
126
+ aria-hidden="true"
103
127
  data-mirror
104
128
  preserveAspectRatio="none"
105
129
  viewBox="0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}"
@@ -127,9 +151,14 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
127
151
  data-active=${this.pointer.at === index ? '' : nothing}
128
152
  part="group${this.pointer.at === index ? ' group-active' : ''}"
129
153
  >
130
- ${columns.map(({ one, tone }, depth) => bar(one.points[index]?.value ?? 0, index, depth, tone, against(one)))}
154
+ ${columns.map(({ slots, one, tone }, depth) => {
155
+ const point = slots[index];
156
+ return point === undefined
157
+ ? nothing
158
+ : bar(point.value, index, depth, tone, against(one));
159
+ })}
131
160
  </g>`)}
132
- ${series.map((one) => lined.has(one.name.trim().toLowerCase())
161
+ ${series.map((one) => lined.has(one.name.trim().toLowerCase()) && this.showsSeries(one.name)
133
162
  ? this.renderLine(one, series.indexOf(one), slot, against(one), sideways)
134
163
  : nothing)}
135
164
  </svg>
@@ -147,7 +176,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
147
176
  ${ticks(domain).map((level) => html `<span
148
177
  part="tick"
149
178
  style=${sideways ? `inset-inline-start: ${scale(level)}%` : `inset-block-start: ${scale(level)}%`}
150
- >${level.toLocaleString()}</span
179
+ >${formatNumbers(this.locale)(level)}</span
151
180
  >`)}
152
181
  </div>`;
153
182
  }
@@ -184,13 +213,15 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
184
213
  </div>`;
185
214
  }
186
215
  renderLine(one, depth, slot, y, sideways) {
187
- const points = one.points.map((point, index) => {
188
- const across = index * slot + slot / 2;
216
+ const path = unbroken(one)
217
+ .map((run) => linePath(run.map((point) => {
218
+ const across = point.at * slot + slot / 2;
189
219
  const along = y(point.value);
190
220
  return sideways ? [along, across] : [across, along];
191
- });
221
+ }), 'straight'))
222
+ .join('');
192
223
  return svg `<path
193
- d=${linePath(points, 'straight')}
224
+ d=${path}
194
225
  data-series=${seriesIndex(depth)}
195
226
  part="line"
196
227
  style="--chart-series: var(--chart-series-${seriesIndex(depth)})"
@@ -200,15 +231,18 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
200
231
  const at = this.pointer.at;
201
232
  const series = this.series;
202
233
  if (at < 0 || series.length === 0) {
203
- return drawTooltip(this.sourceRows, at, this.tag('tooltip'));
234
+ return drawTooltip(this.sourceRows, at, this.tag('tooltip'), undefined, undefined, this.pointer);
204
235
  }
205
- const values = series.map((one) => one.points[at]?.value ?? 0);
206
- const all = series.flatMap((one) => one.points.map((point) => point.value));
236
+ const shown = series.filter((one) => this.showsSeries(one.name));
237
+ const values = shown
238
+ .map((one) => byRow(one, this.readings)[at]?.value)
239
+ .filter((one) => one !== undefined);
240
+ const all = shown.flatMap((one) => one.points.map((point) => point.value));
207
241
  const [low, high] = extent(all.length > 0 ? all : [0]);
208
242
  const domain = [Math.min(0, low), Math.max(0, high)];
209
243
  const sideways = this.orientation === 'horizontal';
210
244
  const scale = sideways ? linear(domain, [0, PLOT_HEIGHT]) : linear(domain, [PLOT_HEIGHT, 0]);
211
- const ends = values.map((one) => scale(one));
245
+ const ends = (values.length > 0 ? values : [0]).map((one) => scale(one));
212
246
  const far = sideways ? Math.max(...ends) : Math.min(...ends);
213
247
  const slot = 100 / this.readings;
214
248
  const across = at * slot + slot / 2;
@@ -216,12 +250,15 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
216
250
  placement: sideways ? (this.pointer.mirrored ? 'left' : 'right') : 'top',
217
251
  x: sideways ? `${far}%` : `${across}%`,
218
252
  y: sideways ? `${across}%` : `${far}%`,
219
- }, (cell) => this.seriesOf(cell));
253
+ }, (cell) => this.seriesOf(cell), this.pointer);
220
254
  }
221
255
  };
222
256
  __decorate([
223
257
  property()
224
258
  ], HelixHeadlessBarChart.prototype, "gridlines", void 0);
259
+ __decorate([
260
+ property({ attribute: 'highest-label' })
261
+ ], HelixHeadlessBarChart.prototype, "highestLabel", void 0);
225
262
  __decorate([
226
263
  property()
227
264
  ], HelixHeadlessBarChart.prototype, "lines", void 0);
@@ -4,9 +4,13 @@ import { type PropertyValues, type TemplateResult } from 'lit';
4
4
  * @summary A passage set off from the prose around it.
5
5
  *
6
6
  * @description
7
- * Renders a `<blockquote>` with a `<footer>` for the attribution, the structure
8
- * the HTML spec describes. The attribution sits outside the quoted text because
9
- * it is about the quotation.
7
+ * Renders a `<figure>` holding the `<blockquote>` and a `<figcaption>` for the
8
+ * attribution, the structure the HTML spec describes. The attribution sits
9
+ * outside the quotation because it is about the quotation, and it names the
10
+ * figure, so a screen reader reads the source as the figure's caption.
11
+ *
12
+ * The figure keeps the browser's default margins on this tier. Set
13
+ * `::part(figure) { margin: 0 }` where they are unwanted.
10
14
  *
11
15
  * For a quotation inside a sentence, use `Quote`.
12
16
  *
@@ -19,8 +23,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
19
23
  * @slot - The quoted passage.
20
24
  * @slot attribution - Who said it, and where.
21
25
  *
22
- * @csspart attribution - The footer carrying the source.
26
+ * @csspart attribution - The `<figcaption>` carrying the source.
23
27
  * @csspart blockquote - The quotation.
28
+ * @csspart figure - The `<figure>` holding the quotation and its attribution.
24
29
  */
25
30
  export declare class HelixHeadlessBlockquote extends HelixElement {
26
31
  /**
@@ -28,13 +33,13 @@ export declare class HelixHeadlessBlockquote extends HelixElement {
28
33
  */
29
34
  cite: string;
30
35
  /**
31
- * Says on the footer whether there is an attribution in it.
36
+ * Says on the caption whether there is an attribution in it.
32
37
  *
33
- * A `<footer>` with nothing in it is still a block in the quote's flow and
38
+ * A `<figcaption>` with nothing in it is still a block in the quote's flow and
34
39
  * still takes the container's gap, so every blockquote written without an
35
40
  * attribution reserved a full space below itself. There is no selector that
36
41
  * can ask, `slot:empty` being about a slot's fallback rather than its
37
- * assigned nodes, so the component asks and says so on the footer inside this
42
+ * assigned nodes, so the component asks and says so on the caption inside this
38
43
  * shadow root: an attribute on the host is a change to markup the consumer
39
44
  * rendered, which React reports on hydration.
40
45
  */
@@ -20,10 +20,12 @@ let HelixHeadlessBlockquote = class HelixHeadlessBlockquote extends HelixElement
20
20
  this.markEmpty();
21
21
  }
22
22
  render() {
23
- return html `<blockquote part="blockquote" cite=${this.cite || nothing}>
24
- <slot></slot>
25
- <footer part="attribution"><slot name="attribution"></slot></footer>
26
- </blockquote>`;
23
+ return html `<figure aria-labelledby="attribution" part="figure">
24
+ <blockquote part="blockquote" cite=${this.cite || nothing}><slot></slot></blockquote>
25
+ <figcaption id="attribution" part="attribution"
26
+ ><slot name="attribution" @slotchange=${() => this.markEmpty()}></slot
27
+ ></figcaption>
28
+ </figure>`;
27
29
  }
28
30
  };
29
31
  __decorate([
@@ -4,9 +4,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
4
4
  * @summary Shows the path to the current page.
5
5
  *
6
6
  * @description
7
- * The host is the navigation landmark, so an `aria-label` on it names the
8
- * trail. When a page has more than one navigation landmark, screen reader users
9
- * choose between them by name.
7
+ * The host is the navigation landmark, named "Breadcrumb" by default. An
8
+ * `aria-label` on the host names the trail instead, and so does `label`. When a
9
+ * page has more than one navigation landmark, screen reader users choose
10
+ * between them by name.
10
11
  *
11
12
  * The `<ol>` has an explicit `role="list"`, because Safari removes list
12
13
  * semantics from a list with `list-style: none`, and the trail always hides its
@@ -30,6 +31,11 @@ import { type PropertyValues, type TemplateResult } from 'lit';
30
31
  * @csspart list - The ordered list.
31
32
  */
32
33
  export declare class HelixHeadlessBreadcrumbs extends HelixElement {
34
+ /**
35
+ * The landmark's name, read by screen readers. An `aria-label` on the host
36
+ * wins over it.
37
+ */
38
+ label: string;
33
39
  protected willUpdate(changed: PropertyValues): void;
34
40
  protected render(): TemplateResult;
35
41
  }
@@ -6,10 +6,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
+ import { property } from 'lit/decorators.js';
9
10
  let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixElement {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.label = 'Breadcrumb';
14
+ }
10
15
  willUpdate(changed) {
11
16
  super.willUpdate(changed);
12
- hostAria(this.internals, { role: 'navigation' });
17
+ hostAria(this.internals, { label: this.label, role: 'navigation' });
13
18
  }
14
19
  render() {
15
20
  return html `<ol part="list" role="list">
@@ -17,6 +22,9 @@ let HelixHeadlessBreadcrumbs = class HelixHeadlessBreadcrumbs extends HelixEleme
17
22
  </ol>`;
18
23
  }
19
24
  };
25
+ __decorate([
26
+ property()
27
+ ], HelixHeadlessBreadcrumbs.prototype, "label", void 0);
20
28
  HelixHeadlessBreadcrumbs = __decorate([
21
29
  customElement('helix-headless-breadcrumbs')
22
30
  ], HelixHeadlessBreadcrumbs);