@fusion.dev/helix-headless 0.145.0 → 0.146.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 (278) hide show
  1. package/custom-elements.json +7373 -3849
  2. package/dist/accordion/item/accordion-item.d.ts +14 -0
  3. package/dist/accordion/item/accordion-item.js +16 -6
  4. package/dist/accordion/root/accordion-root.d.ts +8 -5
  5. package/dist/announcement/root/announcement-root.d.ts +3 -2
  6. package/dist/announcement/root/announcement-root.js +3 -1
  7. package/dist/app-header/root/app-header-root.d.ts +7 -2
  8. package/dist/app-header/root/app-header-root.js +9 -1
  9. package/dist/app-header/sectioning.d.ts +3 -1
  10. package/dist/app-header/sectioning.js +3 -2
  11. package/dist/avatar/group/avatar-group.d.ts +20 -14
  12. package/dist/avatar/group/avatar-group.js +17 -19
  13. package/dist/badge/root/badge-root.d.ts +3 -1
  14. package/dist/badge/root/badge-root.js +2 -2
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +52 -15
  17. package/dist/bar-chart/stack.d.ts +15 -0
  18. package/dist/bar-chart/stack.js +19 -0
  19. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  20. package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
  21. package/dist/button/root/button-root.d.ts +26 -0
  22. package/dist/button/root/button-root.js +38 -18
  23. package/dist/button-group/root/button-group-root.d.ts +2 -1
  24. package/dist/button-group/root/button-group-root.js +5 -1
  25. package/dist/canvas/node/canvas-node.d.ts +4 -3
  26. package/dist/canvas/node/canvas-node.js +3 -2
  27. package/dist/canvas/root/canvas-root.js +2 -2
  28. package/dist/card/root/card-root.d.ts +24 -3
  29. package/dist/card/root/card-root.js +20 -8
  30. package/dist/carousel/root/carousel-root.d.ts +43 -4
  31. package/dist/carousel/root/carousel-root.js +40 -12
  32. package/dist/carousel/stops.d.ts +20 -0
  33. package/dist/carousel/stops.js +30 -0
  34. package/dist/chat/message/chat-message.js +5 -4
  35. package/dist/chat/naming.d.ts +5 -1
  36. package/dist/chat/naming.js +4 -2
  37. package/dist/chat/root/chat-root.d.ts +25 -3
  38. package/dist/chat/root/chat-root.js +22 -5
  39. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  40. package/dist/checkbox/root/checkbox-root.js +14 -1
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  42. package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
  43. package/dist/checkbox-group/select-all.d.ts +27 -0
  44. package/dist/checkbox-group/select-all.js +12 -0
  45. package/dist/code-block/highlight.d.ts +15 -0
  46. package/dist/code-block/highlight.js +4 -0
  47. package/dist/code-block/root/code-block-root.d.ts +49 -1
  48. package/dist/code-block/root/code-block-root.js +58 -3
  49. package/dist/color-input/root/color-input-root.d.ts +3 -0
  50. package/dist/color-input/root/color-input-root.js +6 -3
  51. package/dist/color-picker/root/color-picker-root.d.ts +33 -4
  52. package/dist/color-picker/root/color-picker-root.js +80 -21
  53. package/dist/color-picker/swatches.d.ts +12 -0
  54. package/dist/color-picker/swatches.js +26 -0
  55. package/dist/combobox/root/combobox-root.d.ts +43 -0
  56. package/dist/combobox/root/combobox-root.js +79 -15
  57. package/dist/command/root/command-root.d.ts +16 -1
  58. package/dist/command/root/command-root.js +22 -4
  59. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  60. package/dist/copy-button/root/copy-button-root.js +10 -3
  61. package/dist/data-table/index.d.ts +1 -1
  62. package/dist/data-table/index.js +1 -1
  63. package/dist/data-table/keys.d.ts +24 -0
  64. package/dist/data-table/keys.js +24 -0
  65. package/dist/data-table/root/data-table-root.d.ts +27 -18
  66. package/dist/data-table/root/data-table-root.js +20 -52
  67. package/dist/data-table/tree.d.ts +16 -1
  68. package/dist/data-table/tree.js +2 -3
  69. package/dist/date-input/root/date-input-root.d.ts +3 -1
  70. package/dist/date-input/root/date-input-root.js +18 -7
  71. package/dist/date-picker/root/date-picker-root.js +12 -6
  72. package/dist/dialog/description.js +15 -1
  73. package/dist/dialog/root/dialog-root.d.ts +8 -2
  74. package/dist/dialog/root/dialog-root.js +16 -1
  75. package/dist/divider/root/divider-root.d.ts +3 -0
  76. package/dist/divider/root/divider-root.js +2 -1
  77. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  78. package/dist/donut-chart/root/donut-chart-root.js +48 -1
  79. package/dist/drawer/reveal.d.ts +8 -0
  80. package/dist/drawer/reveal.js +1 -0
  81. package/dist/drawer/root/drawer-root.d.ts +59 -0
  82. package/dist/drawer/root/drawer-root.js +63 -4
  83. package/dist/drilldown/item/drilldown-item.js +1 -1
  84. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  85. package/dist/drilldown/root/drilldown-root.js +21 -3
  86. package/dist/element-events.generated.js +31 -5
  87. package/dist/empty/root/empty-root.d.ts +3 -1
  88. package/dist/empty/root/empty-root.js +3 -2
  89. package/dist/file-input/root/file-input-root.d.ts +69 -6
  90. package/dist/file-input/root/file-input-root.js +82 -19
  91. package/dist/file-input/screen.d.ts +2 -1
  92. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  93. package/dist/filter-input/menu/filter-menu.js +12 -4
  94. package/dist/filter-input/root/filter-input-root.d.ts +30 -6
  95. package/dist/filter-input/root/filter-input-root.js +1 -1
  96. package/dist/filter-input/suggest.d.ts +28 -3
  97. package/dist/filter-input/suggest.js +18 -8
  98. package/dist/format-date/root/format-date-root.d.ts +9 -16
  99. package/dist/format-date/root/format-date-root.js +10 -27
  100. package/dist/heatmap/root/heatmap-root.d.ts +24 -13
  101. package/dist/heatmap/root/heatmap-root.js +34 -12
  102. package/dist/icon/root/icon-root.d.ts +12 -1
  103. package/dist/icon/root/icon-root.js +21 -10
  104. package/dist/icon/settle.d.ts +7 -0
  105. package/dist/icon/settle.js +10 -0
  106. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  107. package/dist/image/root/image-root.d.ts +5 -1
  108. package/dist/image/root/image-root.js +1 -1
  109. package/dist/input/root/input-root.d.ts +12 -2
  110. package/dist/input/root/input-root.js +11 -2
  111. package/dist/kbd/root/kbd-root.d.ts +35 -1
  112. package/dist/kbd/root/kbd-root.js +23 -4
  113. package/dist/legend/root/legend-root.d.ts +55 -8
  114. package/dist/legend/root/legend-root.js +55 -13
  115. package/dist/lightbox/root/lightbox-root.d.ts +49 -6
  116. package/dist/lightbox/root/lightbox-root.js +86 -19
  117. package/dist/lightbox/zoom-controller.d.ts +59 -0
  118. package/dist/lightbox/zoom-controller.js +128 -0
  119. package/dist/lightbox/zoom.d.ts +22 -0
  120. package/dist/lightbox/zoom.js +16 -0
  121. package/dist/line-chart/root/line-chart-root.d.ts +22 -1
  122. package/dist/line-chart/root/line-chart-root.js +21 -1
  123. package/dist/list/item/list-item.d.ts +2 -0
  124. package/dist/list/item/list-item.js +11 -2
  125. package/dist/list/root/list-root.d.ts +62 -13
  126. package/dist/list/root/list-root.js +70 -13
  127. package/dist/list/selection.d.ts +37 -7
  128. package/dist/list/selection.js +16 -7
  129. package/dist/listbox/root/listbox-root.d.ts +37 -1
  130. package/dist/listbox/root/listbox-root.js +49 -3
  131. package/dist/loader/busy.d.ts +10 -0
  132. package/dist/loader/busy.js +11 -0
  133. package/dist/loader/root/loader-root.d.ts +9 -2
  134. package/dist/loader/root/loader-root.js +23 -3
  135. package/dist/megamenu/root/megamenu-root.d.ts +51 -10
  136. package/dist/megamenu/root/megamenu-root.js +76 -5
  137. package/dist/menu/item/menu-item.d.ts +51 -2
  138. package/dist/menu/item/menu-item.js +47 -23
  139. package/dist/menu/root/menu-root.d.ts +14 -0
  140. package/dist/menu/root/menu-root.js +2 -2
  141. package/dist/meter/root/meter-root.d.ts +20 -1
  142. package/dist/meter/root/meter-root.js +11 -15
  143. package/dist/navigation/root/navigation-root.d.ts +2 -1
  144. package/dist/navigation/root/navigation-root.js +2 -2
  145. package/dist/notifications/root/notifications-root.d.ts +10 -3
  146. package/dist/notifications/root/notifications-root.js +19 -7
  147. package/dist/number-input/root/number-input-root.d.ts +17 -8
  148. package/dist/number-input/root/number-input-root.js +2 -7
  149. package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
  150. package/dist/object-inspector/root/object-inspector-root.js +117 -76
  151. package/dist/object-inspector/rows.d.ts +18 -0
  152. package/dist/object-inspector/rows.js +33 -0
  153. package/dist/option/root/option-root.d.ts +5 -3
  154. package/dist/outline/root/outline-root.d.ts +18 -0
  155. package/dist/outline/root/outline-root.js +23 -5
  156. package/dist/pagination/size/pagination-size.d.ts +1 -0
  157. package/dist/pagination/size/pagination-size.js +1 -1
  158. package/dist/pin-input/code.d.ts +10 -0
  159. package/dist/pin-input/code.js +13 -0
  160. package/dist/pin-input/root/pin-input-root.d.ts +25 -1
  161. package/dist/pin-input/root/pin-input-root.js +10 -11
  162. package/dist/popover/hide-outside.d.ts +14 -0
  163. package/dist/popover/hide-outside.js +41 -0
  164. package/dist/popover/root/popover-root.d.ts +57 -7
  165. package/dist/popover/root/popover-root.js +58 -3
  166. package/dist/progress/root/progress-root.d.ts +20 -0
  167. package/dist/progress/root/progress-root.js +15 -15
  168. package/dist/qr-code/export.d.ts +26 -1
  169. package/dist/qr-code/export.js +14 -0
  170. package/dist/qr-code/root/qr-code-root.d.ts +19 -5
  171. package/dist/qr-code/root/qr-code-root.js +58 -9
  172. package/dist/quote/marks.d.ts +8 -0
  173. package/dist/quote/marks.js +5 -0
  174. package/dist/quote/root/quote-root.d.ts +14 -2
  175. package/dist/quote/root/quote-root.js +23 -1
  176. package/dist/radio/root/radio-root.d.ts +6 -2
  177. package/dist/radio/root/radio-root.js +6 -1
  178. package/dist/rating/root/rating-root.d.ts +9 -4
  179. package/dist/rating/root/rating-root.js +31 -7
  180. package/dist/rating/steps.d.ts +7 -0
  181. package/dist/rating/steps.js +9 -0
  182. package/dist/scatter-chart/fit.d.ts +15 -0
  183. package/dist/scatter-chart/fit.js +35 -0
  184. package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
  185. package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
  186. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  187. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  188. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  189. package/dist/scroll-area/scrollbar-controller.js +172 -0
  190. package/dist/scroll-area/scrollbar.d.ts +27 -0
  191. package/dist/scroll-area/scrollbar.js +9 -0
  192. package/dist/select/root/select-root.d.ts +15 -0
  193. package/dist/select/root/select-root.js +18 -6
  194. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  195. package/dist/skeleton/root/skeleton-root.js +4 -2
  196. package/dist/skip-link/root/skip-link-root.js +2 -2
  197. package/dist/slider/root/slider-root.d.ts +41 -4
  198. package/dist/slider/root/slider-root.js +23 -3
  199. package/dist/sparkline/readings.d.ts +18 -0
  200. package/dist/sparkline/readings.js +19 -0
  201. package/dist/sparkline/root/sparkline-root.d.ts +78 -7
  202. package/dist/sparkline/root/sparkline-root.js +118 -23
  203. package/dist/speed-dial/root/speed-dial-root.js +2 -2
  204. package/dist/splitter/root/splitter-root.d.ts +7 -12
  205. package/dist/splitter/root/splitter-root.js +209 -204
  206. package/dist/stat/root/stat-root.d.ts +14 -5
  207. package/dist/stat/root/stat-root.js +21 -5
  208. package/dist/steps/reach.d.ts +5 -0
  209. package/dist/steps/reach.js +3 -0
  210. package/dist/steps/root/steps-root.d.ts +49 -3
  211. package/dist/steps/root/steps-root.js +44 -5
  212. package/dist/steps/step/step.d.ts +7 -0
  213. package/dist/steps/step/step.js +7 -2
  214. package/dist/switch/root/switch-root.d.ts +10 -0
  215. package/dist/table/column/table-column.d.ts +0 -10
  216. package/dist/table/column/table-column.js +3 -19
  217. package/dist/table/root/table-root.d.ts +31 -10
  218. package/dist/table/root/table-root.js +2 -13
  219. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  220. package/dist/tabs/panel/tab-panel.js +34 -5
  221. package/dist/tabs/root/tabs-root.d.ts +12 -0
  222. package/dist/tabs/root/tabs-root.js +1 -1
  223. package/dist/tabs/tab/tab.d.ts +5 -0
  224. package/dist/tabs/tab/tab.js +5 -2
  225. package/dist/tag/group/tag-group.d.ts +31 -4
  226. package/dist/tag/group/tag-group.js +46 -7
  227. package/dist/tag/root/tag-root.js +9 -2
  228. package/dist/textarea/root/textarea-root.d.ts +28 -1
  229. package/dist/textarea/root/textarea-root.js +40 -1
  230. package/dist/time-input/root/time-input-root.d.ts +5 -1
  231. package/dist/time-input/root/time-input-root.js +16 -8
  232. package/dist/time-picker/root/time-picker-root.d.ts +18 -4
  233. package/dist/time-picker/root/time-picker-root.js +7 -10
  234. package/dist/time-picker/wheel-name.d.ts +9 -0
  235. package/dist/time-picker/wheel-name.js +15 -0
  236. package/dist/timeline/group/timeline-group.js +2 -2
  237. package/dist/toast/item/toast-item.d.ts +14 -1
  238. package/dist/toast/item/toast-item.js +22 -5
  239. package/dist/toast/root/toast-root.d.ts +6 -0
  240. package/dist/toast/root/toast-root.js +16 -1
  241. package/dist/toggle/group/toggle-group.d.ts +24 -3
  242. package/dist/toggle/group/toggle-group.js +34 -5
  243. package/dist/tooltip/root/tooltip-root.d.ts +13 -2
  244. package/dist/tooltip/root/tooltip-root.js +9 -1
  245. package/dist/tour/back.d.ts +10 -0
  246. package/dist/tour/back.js +8 -0
  247. package/dist/tour/root/tour-root.d.ts +30 -2
  248. package/dist/tour/root/tour-root.js +34 -8
  249. package/dist/tree/item/tree-item.d.ts +7 -3
  250. package/dist/tree/item/tree-item.js +3 -0
  251. package/dist/tree/root/tree-root.d.ts +24 -3
  252. package/dist/tree/root/tree-root.js +32 -13
  253. package/dist/tree/selection.js +2 -15
  254. package/dist/trend/root/trend-root.d.ts +43 -18
  255. package/dist/trend/root/trend-root.js +31 -6
  256. package/dist/video/media-events.d.ts +13 -18
  257. package/dist/video/media-events.js +1 -5
  258. package/dist/video/root/video-root.d.ts +18 -5
  259. package/dist/video/root/video-root.js +19 -10
  260. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  261. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  262. package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
  263. package/dist/virtual-list/fill.d.ts +0 -8
  264. package/dist/virtual-list/fill.js +1 -17
  265. package/dist/virtual-list/plan.d.ts +49 -0
  266. package/dist/virtual-list/plan.js +16 -0
  267. package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
  268. package/dist/virtual-list/root/virtual-list-root.js +183 -40
  269. package/lint.json +1 -1
  270. package/package.json +8 -8
  271. package/types/jsx.d.ts +4577 -835
  272. package/types/vue.d.ts +926 -168
  273. package/dist/chat/relative-clock.d.ts +0 -39
  274. package/dist/chat/relative-clock.js +0 -31
  275. package/dist/data-table/root/order.d.ts +0 -141
  276. package/dist/data-table/root/order.js +0 -76
  277. package/dist/tag/selection.d.ts +0 -10
  278. package/dist/tag/selection.js +0 -12
@@ -5,18 +5,18 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixHeadlessDataTable_1;
8
- import { countLabel, customElement, deepActiveElement, deepContains, fillTemplate, formatNumbers, HelixActivateEvent, HelixElement, HelixExpandEvent, HelixFilterEvent, HelixFilteredEvent, HelixLoadMoreEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, hostAria, inlineStep, isRtl, MixinCollection, markRegion, rangeAdd, reportRuntime, requestChange, Typeahead, typesCharacter, VirtualizeController, writtenList, } from '@fusion.dev/helix-core';
8
+ import { arranged, commaList, countLabel, customElement, cycle, deepActiveElement, deepContains, fillTemplate, format, formatNumbers, HelixActivateEvent, HelixElement, HelixExpandEvent, HelixFilterEvent, HelixFilteredEvent, HelixLoadMoreEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, hostAria, inlineStep, isRtl, MixinCollection, markRegion, ordered, parse, rangeAdd, reportRuntime, requestChange, Typeahead, toggleEvery, treeArrow, typesCharacter, VirtualizeController, valueAt, window_, writtenList, } from '@fusion.dev/helix-core';
9
9
  import { caretDown, caretRight } from '@fusion.dev/helix-icons';
10
10
  import { nothing } from 'lit';
11
11
  import { property, state } from 'lit/decorators.js';
12
12
  import { repeat } from 'lit/directives/repeat.js';
13
13
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
14
14
  import { html } from 'lit/static-html.js';
15
- import { at, edgeOf } from '../../table/column/table-column.js';
15
+ import { edgeOf } from '../../table/column/table-column.js';
16
16
  import '../../checkbox/index.js';
17
17
  import '../../pagination/index.js';
18
+ import { anchorAt, inRowOrder, toggledOpen } from '../keys.js';
18
19
  import { grow } from '../tree.js';
19
- import { arranged, cycle, format, ordered, parse, window_, } from './order.js';
20
20
  const CONTROL = [
21
21
  'a[href]',
22
22
  'button:not([disabled])',
@@ -79,7 +79,6 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
79
79
  this.typeahead = new Typeahead();
80
80
  this.anchorKey = undefined;
81
81
  this.shiftPressed = false;
82
- this.askedAt = -1;
83
82
  this.counts = {
84
83
  columns: undefined,
85
84
  rows: undefined,
@@ -427,7 +426,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
427
426
  return value;
428
427
  }
429
428
  get opened() {
430
- return new Set(writtenList(this.expanded.replaceAll(',', ' ')));
429
+ return new Set(commaList(this.expanded));
431
430
  }
432
431
  flat() {
433
432
  if (this.childField) {
@@ -472,7 +471,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
472
471
  if (!this.rowKey) {
473
472
  return String(index);
474
473
  }
475
- const value = at(row, this.rowKey);
474
+ const value = valueAt(row, this.rowKey);
476
475
  return value === undefined || value === null ? String(index) : String(value);
477
476
  }
478
477
  currentRow(rows) {
@@ -648,18 +647,15 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
648
647
  },
649
648
  event: (value) => new HelixSelectEvent({ value }),
650
649
  host: this,
651
- next: [...keys].join(','),
650
+ next: inRowOrder(keys, this.everyKey).join(','),
652
651
  });
653
652
  }
654
653
  get chosen() {
655
- return new Set(this.selected
656
- .split(',')
657
- .map((key) => key.trim())
658
- .filter(Boolean));
654
+ return new Set(commaList(this.selected));
659
655
  }
660
656
  keyOf(row, place) {
661
657
  if (this.rowKey) {
662
- const value = at(row, this.rowKey);
658
+ const value = valueAt(row, this.rowKey);
663
659
  return value === undefined || value === null ? String(place) : String(value);
664
660
  }
665
661
  if (this.selectable && !this.warnedAboutKey && typeof window !== 'undefined') {
@@ -684,11 +680,8 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
684
680
  }
685
681
  selectRange(to, from = to) {
686
682
  const keys = this.pageKeys;
687
- let anchor = this.anchorKey === undefined ? -1 : keys.indexOf(this.anchorKey);
688
- if (anchor < 0) {
689
- anchor = from;
690
- this.anchorKey = keys[from];
691
- }
683
+ const { anchor, anchorKey } = anchorAt(keys, this.anchorKey, from);
684
+ this.anchorKey = anchorKey;
692
685
  const next = rangeAdd([...this.chosen], keys, anchor, to);
693
686
  if (next) {
694
687
  this.requestSelected(new Set(next));
@@ -712,13 +705,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
712
705
  if (!this.windowed || !this.loadMore || this.loading) {
713
706
  return;
714
707
  }
715
- const screen = this.partNamed('table')?.clientHeight ?? 0;
716
- const count = this.rows.length;
717
- if (screen > 0 &&
718
- count > 0 &&
719
- this.askedAt !== count &&
720
- this.virtualize.remaining() <= screen) {
721
- this.askedAt = count;
708
+ if (this.virtualize.endInSight(this.rows.length)) {
722
709
  this.askForMore();
723
710
  }
724
711
  }
@@ -734,19 +721,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
734
721
  this.requestSelected(keys);
735
722
  }
736
723
  chooseAll() {
737
- const every = this.everyKey;
738
- const keys = this.chosen;
739
- if (every.length > 0 && every.every((key) => keys.has(key))) {
740
- for (const key of every) {
741
- keys.delete(key);
742
- }
743
- }
744
- else {
745
- for (const key of every) {
746
- keys.add(key);
747
- }
748
- }
749
- this.requestSelected(keys);
724
+ this.requestSelected(new Set(toggleEvery(this.chosen, this.everyKey)));
750
725
  }
751
726
  moveColumn(field, by) {
752
727
  const drawn = this.shownColumns.filter((column) => column.field !== '');
@@ -776,7 +751,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
776
751
  return /[",\r\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
777
752
  };
778
753
  const head = columns.map((column) => quote(column.textContent?.trim() || column.field));
779
- const body = rows.map((row) => columns.map((column) => quote(at(row, column.field))));
754
+ const body = rows.map((row) => columns.map((column) => quote(valueAt(row, column.field))));
780
755
  return [head, ...body].map((line) => line.join(',')).join('\r\n');
781
756
  }
782
757
  requestFilter(next) {
@@ -951,18 +926,11 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
951
926
  ><svg part="toggle-mark" ?data-mirror=${!open} fill="currentColor" viewBox=${glyph.viewBox}>${unsafeSVG(glyph.content)}</svg></span>`;
952
927
  }
953
928
  toggleOpen(row, open) {
954
- const key = this.rowKeyOf(row, -1);
955
- const keys = this.opened;
956
- if (keys.has(key) === open) {
929
+ const next = toggledOpen(this.expanded, this.rowKeyOf(row, -1), open, this.everyKey);
930
+ if (next === undefined) {
957
931
  return false;
958
932
  }
959
- if (open) {
960
- keys.add(key);
961
- }
962
- else {
963
- keys.delete(key);
964
- }
965
- this.expanded = [...keys].join(',');
933
+ this.expanded = next;
966
934
  this.dispatchEvent(new HelixExpandEvent({ value: this.expanded }));
967
935
  return true;
968
936
  }
@@ -1300,14 +1268,14 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
1300
1268
  return false;
1301
1269
  }
1302
1270
  const placed = this.tree().placed.get(row);
1303
- const forward = inlineStep(this, event.key) > 0;
1304
- if (placed?.branch && placed.open !== forward) {
1271
+ const arrow = treeArrow({ branch: placed?.branch ?? false, open: placed?.open ?? false }, inlineStep(this, event.key) > 0 ? 1 : -1);
1272
+ if (arrow === 'open' || arrow === 'close') {
1305
1273
  event.preventDefault();
1306
- this.toggleOpen(row, forward);
1274
+ this.toggleOpen(row, arrow === 'open');
1307
1275
  return true;
1308
1276
  }
1309
1277
  const parent = placed?.parent ? this.drawnPage.indexOf(placed.parent) : -1;
1310
- if (!forward && parent >= 0) {
1278
+ if (arrow === 'parent' && parent >= 0) {
1311
1279
  event.preventDefault();
1312
1280
  this.moveTo(parent, place.column);
1313
1281
  return true;
@@ -1,4 +1,19 @@
1
- import { type Axis, type DataRow } from './root/order.js';
1
+ /**
2
+ * Rows that hold rows, arranged for a tree grid: filtered, sorted within each
3
+ * parent, and laid out flat in reading order with the open rows' children under
4
+ * them.
5
+ *
6
+ * Pure and beside the family's `index.ts`, because which rows show and at what
7
+ * depth is a fact about the data, and a spec can hold it without a page.
8
+ *
9
+ * **Filtered by descent.** A row stays when it matches the query or any row
10
+ * under it does, so a match deep in the tree is shown with the rows that lead to
11
+ * it, and while a query is on every row with a match under it is open.
12
+ *
13
+ * **Sorted among siblings.** A sort orders each parent's rows and leaves every
14
+ * row under its parent, which is the only order a tree can be read in.
15
+ */
16
+ import { type Axis, type DataRow } from '@fusion.dev/helix-core';
2
17
  /** Where a row sits in the tree. */
3
18
  export interface Placement {
4
19
  /** Whether it has children to show. */
@@ -1,7 +1,6 @@
1
- import { at } from '../table/column/table-column.js';
2
- import { filter, parse, sort } from './root/order.js';
1
+ import { filter, parse, sort, valueAt } from '@fusion.dev/helix-core';
3
2
  export const childrenOf = (row, field) => {
4
- const value = at(row, field);
3
+ const value = valueAt(row, field);
5
4
  return Array.isArray(value) ? value : [];
6
5
  };
7
6
  export const grow = (rows, axes, { field, isOpen, query, spec, }) => {
@@ -36,6 +36,8 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
36
36
  * @slot feedback - The error message under the field.
37
37
  * @slot hint - The help text under the field.
38
38
  * @slot next-icon - The icon on the calendar's next month control.
39
+ * @slot panel-footer - Content in the panel under the calendar, such as a note or an action.
40
+ * @slot panel-header - Content in the panel above the calendar, such as a heading or a shortcut.
39
41
  * @slot previous-icon - The icon on the calendar's previous month control.
40
42
  * @slot trigger - The icon on the button that opens the calendar.
41
43
  *
@@ -355,7 +357,7 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
355
357
  /** Each date, where `mode` holds several, sent one entry each. */
356
358
  protected get answers(): readonly string[] | undefined;
357
359
  /** What is wrong with the dates, which the text input cannot say. */
358
- protected validate(): string;
360
+ protected validate(): string | readonly [keyof ValidityStateFlags, string];
359
361
  /**
360
362
  * The message shown when `disable-dates` or `disable-days` bars a date.
361
363
  */
@@ -176,14 +176,20 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
176
176
  : 'Enter dates as YYYY-MM-DD, separated by commas.'));
177
177
  }
178
178
  if (this.min !== '' && held.some((one) => one < this.min)) {
179
- return fillTemplate(this.rangeUnderflowMessage || 'Choose a date on or after {min}.', {
180
- min: this.written(this.min),
181
- });
179
+ return [
180
+ 'rangeUnderflow',
181
+ fillTemplate(this.rangeUnderflowMessage || 'Choose a date on or after {min}.', {
182
+ min: this.written(this.min),
183
+ }),
184
+ ];
182
185
  }
183
186
  if (this.max !== '' && held.some((one) => one > this.max)) {
184
- return fillTemplate(this.rangeOverflowMessage || 'Choose a date on or before {max}.', {
185
- max: this.written(this.max),
186
- });
187
+ return [
188
+ 'rangeOverflow',
189
+ fillTemplate(this.rangeOverflowMessage || 'Choose a date on or before {max}.', {
190
+ max: this.written(this.max),
191
+ }),
192
+ ];
187
193
  }
188
194
  const why = held.map((one) => {
189
195
  const date = asDate(one);
@@ -193,7 +199,10 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
193
199
  return this.unavailableMessage || 'Choose a date that is available.';
194
200
  }
195
201
  if (why.includes('step')) {
196
- return this.stepMismatchMessage || 'Choose one of the dates the calendar offers.';
202
+ return [
203
+ 'stepMismatch',
204
+ this.stepMismatchMessage || 'Choose one of the dates the calendar offers.',
205
+ ];
197
206
  }
198
207
  if (this.mode === 'range' && held.length > 2) {
199
208
  return this.rangeLengthMessage || 'A range is two dates.';
@@ -327,7 +336,9 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
327
336
  popover="manual"
328
337
  ?hidden=${!this.open}
329
338
  >
339
+ <slot name="panel-header"></slot>
330
340
  ${this.renderPicker()}
341
+ <slot name="panel-footer"></slot>
331
342
  </div>
332
343
  ${this.renderHint()}${this.renderFeedback()}`;
333
344
  }
@@ -21,6 +21,7 @@ const KEYS = new Set([
21
21
  'PageUp',
22
22
  ' ',
23
23
  ]);
24
+ const firstOf = (year, month) => addMonths(asDate('2000-01-01'), (year - 2000) * 12 + month);
24
25
  let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControllerValue(HelixFormElement) {
25
26
  constructor() {
26
27
  super(...arguments);
@@ -139,13 +140,13 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
139
140
  get shown() {
140
141
  const explicit = /^(\d{4})-(\d{2})$/.exec(this.monthState ?? this.defaultMonth);
141
142
  if (explicit) {
142
- return new Date(Date.UTC(Number(explicit[1]), Number(explicit[2]) - 1, 1));
143
+ return firstOf(Number(explicit[1]), Number(explicit[2]) - 1);
143
144
  }
144
145
  return this.derivedMonth;
145
146
  }
146
147
  get derivedMonth() {
147
148
  const from = asDate(this.selected[0] ?? '') ?? new Date();
148
- return new Date(Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), 1));
149
+ return firstOf(from.getUTCFullYear(), from.getUTCMonth());
149
150
  }
150
151
  get anchor() {
151
152
  const shown = this.shown;
@@ -268,11 +269,16 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
268
269
  return;
269
270
  }
270
271
  this.pageYear = at;
271
- this.periodFocus = at === this.shown.getUTCFullYear() ? this.shown.getUTCMonth() : 0;
272
+ const month = this.shown.getUTCMonth();
273
+ const open = Array.from({ length: 12 }, (_, index) => index).filter((index) => !this.monthOut(firstOf(at, index)));
274
+ this.periodFocus = open.includes(month)
275
+ ? month
276
+ : ([...open].sort((left, right) => Math.abs(left - month) - Math.abs(right - month))[0] ??
277
+ month);
272
278
  this.zoom('month');
273
279
  return;
274
280
  }
275
- const first = new Date(Date.UTC(this.periodYear, at, 1));
281
+ const first = firstOf(this.periodYear, at);
276
282
  if (this.monthOut(first)) {
277
283
  return;
278
284
  }
@@ -558,8 +564,8 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
558
564
  const years = this.view === 'year';
559
565
  const page = years ? yearPageOf(this.periodYear) : this.periodYear;
560
566
  const heading = years
561
- ? `${yearName.format(new Date(Date.UTC(page, 0, 1)))} – ${yearName.format(new Date(Date.UTC(page + YEARS_SHOWN - 1, 0, 1)))}`
562
- : yearName.format(new Date(Date.UTC(page, 0, 1)));
567
+ ? `${yearName.format(firstOf(page, 0))} – ${yearName.format(firstOf(page + YEARS_SHOWN - 1, 0))}`
568
+ : yearName.format(firstOf(page, 0));
563
569
  const stop = this.periodStop;
564
570
  const cells = periodCells({
565
571
  max: this.max,
@@ -1,5 +1,19 @@
1
1
  const CONTROL = 'a[href], audio[controls], button, details, form, iframe, input, select, textarea, video[controls], [contenteditable], [tabindex]';
2
- const isControl = (element) => element.localName.includes('-') || element.matches(CONTROL);
2
+ const isControl = (element) => {
3
+ if (element.matches(CONTROL)) {
4
+ return true;
5
+ }
6
+ if (!element.localName.includes('-')) {
7
+ return false;
8
+ }
9
+ const definition = customElements.get(element.localName);
10
+ const root = element.shadowRoot;
11
+ return (definition === undefined ||
12
+ !(element instanceof definition) ||
13
+ definition.formAssociated === true ||
14
+ root?.delegatesFocus === true ||
15
+ root?.querySelector(CONTROL) != null);
16
+ };
3
17
  export const wordsIn = (slot) => {
4
18
  const words = [];
5
19
  for (const one of slot?.assignedElements({ flatten: true }) ?? []) {
@@ -1,4 +1,4 @@
1
- import { AriaForwardController, CommandController, HelixElement, OpenPhaseController } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, CommandController, FocusScopeController, HelixElement, OpenPhaseController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
4
4
  /**
@@ -13,6 +13,10 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
13
13
  * - an inert page behind the dialog, unreachable by pointer, keyboard, or
14
14
  * virtual cursor
15
15
  *
16
+ * The dialog adds one thing to those: `Tab` from its last control goes to its
17
+ * first, and `Shift+Tab` from its first to its last. A native modal lets `Tab`
18
+ * past its last control out to the browser's own controls.
19
+ *
16
20
  * `open` calls `showModal()`, and every way the dialog closes goes through
17
21
  * `requestOpen`. A native dialog closes three ways: the property, Escape, and a
18
22
  * `<form method="dialog">` submit. Routing all three through `requestOpen`
@@ -25,7 +29,8 @@ declare const HelixHeadlessDialog_base: (new (...args: any[]) => import("@fusion
25
29
  *
26
30
  * The dialog is described by the words at the start of its body: the elements
27
31
  * in the default slot before the first one that is or holds a control. A
28
- * question above a form describes the dialog, and the form does not. An
32
+ * question above a form describes the dialog, and the form does not. A Helix
33
+ * component that draws words and no control, such as `Text`, counts as words. An
29
34
  * `aria-describedby` on the host replaces it.
30
35
  *
31
36
  * Set `alert` for a dialog that interrupts to ask for an answer, such as a
@@ -190,6 +195,7 @@ export declare class HelixHeadlessDialog extends HelixHeadlessDialog_base {
190
195
  * either. A browser without element reflection keeps the fallback name.
191
196
  */
192
197
  private nameByHeader;
198
+ protected readonly scope: FocusScopeController;
193
199
  /** Whether the body's words are what currently describe the dialog. */
194
200
  private describedByBody;
195
201
  /**
@@ -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, CommandController, customElement, drawDismiss, drawDismissGlyph, HelixElement, headingsIn, hostAria, lockScroll, MixinControllerOpen, OpenPhaseController, reflectElements, unlockScroll, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, auditName, CommandController, customElement, drawDismiss, drawDismissGlyph, FocusScopeController, HelixElement, headingsIn, hostAria, lockScroll, MixinControllerOpen, OpenPhaseController, reflectElements, unlockScroll, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { wordsIn } from '../description.js';
@@ -60,6 +60,16 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
60
60
  this.close(submitter?.hasAttribute('value') ? submitter.value : undefined);
61
61
  };
62
62
  this.namedByHeader = false;
63
+ this.scope = new FocusScopeController(this, {
64
+ contain: () => this.open,
65
+ contents: () => [
66
+ ...['icon', 'header', '', 'footer'].flatMap((name) => this.renderRoot
67
+ ?.querySelector(name ? `slot[name="${name}"]` : 'slot:not([name])')
68
+ ?.assignedElements({ flatten: true }) ?? []),
69
+ ...[...(this.dialog?.children ?? [])].filter((one) => !(one instanceof HTMLSlotElement)),
70
+ ],
71
+ surface: () => this.dialog,
72
+ });
63
73
  this.describedByBody = false;
64
74
  this.handleBackdrop = (event) => {
65
75
  const panel = this.dialog;
@@ -145,6 +155,11 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
145
155
  return;
146
156
  }
147
157
  if (this.open && !dialog.open) {
158
+ auditName(this, () => null, 'Give it a `label`, or a heading in the `header` slot.', () => this.label !== '' ||
159
+ this.namedByHeader ||
160
+ headingsIn(this.renderRoot
161
+ .querySelector('slot[name="header"]')
162
+ ?.assignedElements({ flatten: true }) ?? []).length > 0);
148
163
  void this.openWhenSlotted(dialog);
149
164
  }
150
165
  else if (!this.open && dialog.open) {
@@ -9,6 +9,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
9
9
  * rendered element. The semantics are then in the server-rendered markup, with
10
10
  * no attribute written by script after the element connects.
11
11
  *
12
+ * Set `announced` for a line that divides one thing from another, and it is
13
+ * read as a separator, named by any content set into it.
14
+ *
12
15
  * Use `orientation="vertical"` between items on one line, such as inside a
13
16
  * toolbar. A vertical divider stretches to fit its flex parent and sets no
14
17
  * height of its own.
@@ -23,9 +23,10 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
23
23
  return html `<div
24
24
  part="line"
25
25
  role=${this.announced ? 'separator' : 'presentation'}
26
+ aria-labelledby=${this.announced ? 'content' : nothing}
26
27
  aria-orientation=${this.announced ? (this.orientation ?? 'horizontal') : nothing}
27
28
  ></div>
28
- <span part="content"><slot @slotchange=${() => this.markEmpty()}></slot></span>
29
+ <span id="content" part="content"><slot @slotchange=${() => this.markEmpty()}></slot></span>
29
30
  <div part="line" role="presentation"></div>`;
30
31
  }
31
32
  };
@@ -49,6 +49,7 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
49
49
  * @csspart segment - One slice.
50
50
  * @csspart segment-active - The slice under the pointer. Set alongside `segment`.
51
51
  * @csspart segment-edge - One slice as a closed shape, used to draw its outline.
52
+ * @csspart slice-label - One slice's share, written on the slice under `slice-labels`. Placed with `left` and `top`, or `inset-inline-start` and `top` on a half ring, and carries its series color as `--chart-series`.
52
53
  * @csspart summary - The chart's name and each slice's share, written as a sentence for screen readers. Hide it visually.
53
54
  * @csspart tooltip - The bubble, forwarded from `Tooltip`.
54
55
  * @csspart tooltip-anchor - The `Tooltip` element itself.
@@ -115,6 +116,16 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
115
116
  * because the styled sheet selects on it.
116
117
  */
117
118
  hole?: 'large' | 'none' | 'small';
119
+ /**
120
+ * Writes each slice's share on the slice, the `slice-label` part, so a
121
+ * reader sees the parts without a legend or a pointer: "29%" in the middle
122
+ * of the band.
123
+ *
124
+ * Absent writes none. A slice under a twentieth of the whole takes no
125
+ * label, there being no room on it for one. A screen reader hears every
126
+ * share in the summary, and the labels are hidden from it.
127
+ */
128
+ sliceLabels: boolean;
118
129
  /**
119
130
  * How much of the circle the whole occupies.
120
131
  *
@@ -175,6 +186,11 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
175
186
  * slice, so a key stepping by rows would land on a slice that is not there.
176
187
  */
177
188
  get readings(): number;
189
+ /**
190
+ * Whether the slice at this place is drawn, which a slice a legend hid is
191
+ * not. The keys pass over it, as the ring closes over it.
192
+ */
193
+ showsReading(at: number): boolean;
178
194
  protected render(): TemplateResult;
179
195
  /**
180
196
  * What a reader who cannot see the ring is told: the chart's name and each
@@ -194,6 +210,13 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
194
210
  * table does not hold.
195
211
  */
196
212
  protected renderPlot(shares: DonutShare[]): TemplateResult;
213
+ /**
214
+ * Each slice's share, written in the middle of its band at its mid-angle,
215
+ * as an element beside the drawing so the text is not stretched with it.
216
+ * Placed as the tooltip's point is placed: from the left on a whole ring,
217
+ * whose bearing is a clock's, and from the inline start on a half one.
218
+ */
219
+ protected renderSliceLabels(shares: DonutShare[]): TemplateResult;
197
220
  /**
198
221
  * The view box, cropped to what is actually drawn.
199
222
  *
@@ -238,6 +261,14 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
238
261
  * box, which is the ring's center for a circle and is not for a sector.
239
262
  */
240
263
  protected renderEdge(share: DonutShare, index: number): TemplateResult;
264
+ /**
265
+ * The rows the tooltip reads, with the slice's share of the whole after its
266
+ * amount, as `AreaChart` writes a part's share under `share`: "612 (24%)".
267
+ *
268
+ * The share is what the ring shows and the table does not, so a reading
269
+ * said by key gives it too, as the summary does.
270
+ */
271
+ private withShare;
241
272
  /**
242
273
  * What a pointer resting on a slice shows.
243
274
  *
@@ -30,6 +30,10 @@ const THICKNESS = {
30
30
  small: 26,
31
31
  };
32
32
  let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSource(HelixElement) {
33
+ constructor() {
34
+ super(...arguments);
35
+ this.sliceLabels = false;
36
+ }
33
37
  connectedCallback() {
34
38
  super.connectedCallback();
35
39
  this.pointer.axis = 'none';
@@ -70,6 +74,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
70
74
  get readings() {
71
75
  return this.shares.length;
72
76
  }
77
+ showsReading(at) {
78
+ return (this.shares[at]?.fraction ?? 0) > 0;
79
+ }
73
80
  render() {
74
81
  const shares = this.shares;
75
82
  return html `${this.renderPlot(shares)}${shares.length === 0 ? nothing : this.renderSummary(shares)}`;
@@ -111,9 +118,31 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
111
118
  ${shares.map((share, index) => this.renderSegment(share, index))}
112
119
  </svg>
113
120
  ${this.hole === 'none' ? nothing : html `<div id="helix-chart-center" part="center"><slot></slot></div>`}
121
+ ${this.sliceLabels ? this.renderSliceLabels(shares) : nothing}
114
122
  ${this.renderTooltip()}
115
123
  </div>`;
116
124
  }
125
+ renderSliceLabels(shares) {
126
+ const half = this.sweep === 'half';
127
+ const top = half ? CENTER - EDGE : 0;
128
+ const tall = half ? EDGE + this.thickness / 2 : PLOT_HEIGHT;
129
+ const format = percentIn(this.locale);
130
+ return html `${shares.map((share, index) => {
131
+ if (share.fraction < 0.05) {
132
+ return nothing;
133
+ }
134
+ const angle = (share.start + share.fraction / 2) * 2 * Math.PI * this.span + this.origin;
135
+ const x = ((CENTER + Math.cos(angle) * this.radius) / PLOT_WIDTH) * 100;
136
+ const y = ((CENTER + Math.sin(angle) * this.radius - top) / tall) * 100;
137
+ return html `<span
138
+ aria-hidden="true"
139
+ data-series=${seriesIndex(index)}
140
+ part="slice-label"
141
+ style=${`--chart-series: var(--chart-series-${seriesIndex(index)}); ${half ? 'inset-inline-start' : 'left'}: ${x}%; top: ${y}%`}
142
+ >${format.format(share.fraction)}</span
143
+ >`;
144
+ })}`;
145
+ }
117
146
  get frame() {
118
147
  if (this.sweep !== 'half') {
119
148
  return `0 0 ${PLOT_WIDTH} ${PLOT_HEIGHT}`;
@@ -174,6 +203,21 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
174
203
  style="--chart-series: var(--chart-series-${seriesIndex(index)})"
175
204
  />`;
176
205
  }
206
+ withShare(share) {
207
+ const rows = this.sourceRows;
208
+ const column = this.plottedColumns[0];
209
+ const row = rows[share.row];
210
+ const cell = column === undefined ? undefined : row?.cells[column];
211
+ if (!row || !cell || column === undefined) {
212
+ return rows;
213
+ }
214
+ const cells = [...row.cells];
215
+ cells[column] = {
216
+ ...cell,
217
+ text: `${cell.text} (${percentIn(this.locale).format(share.fraction)})`,
218
+ };
219
+ return rows.map((one, index) => (index === share.row ? { ...row, cells } : one));
220
+ }
177
221
  renderTooltip() {
178
222
  const at = this.pointer.at;
179
223
  const share = this.shares[at];
@@ -188,7 +232,7 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
188
232
  const y = ((CENTER + Math.sin(angle) * edge - top) / tall) * 100;
189
233
  const turned = this.sweep === 'half' && this.pointer.mirrored;
190
234
  const across = Math.cos(angle) > 0 !== turned;
191
- return drawTooltip(this.sourceRows, share.row, this.tag('tooltip'), {
235
+ return drawTooltip(this.withShare(share), share.row, this.tag('tooltip'), {
192
236
  fixed: this.sweep !== 'half',
193
237
  placement: Math.abs(Math.cos(angle)) > Math.abs(Math.sin(angle))
194
238
  ? across
@@ -205,6 +249,9 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
205
249
  __decorate([
206
250
  property()
207
251
  ], HelixHeadlessDonutChart.prototype, "hole", void 0);
252
+ __decorate([
253
+ property({ attribute: 'slice-labels', reflect: true, type: Boolean })
254
+ ], HelixHeadlessDonutChart.prototype, "sliceLabels", void 0);
208
255
  __decorate([
209
256
  property({ reflect: true })
210
257
  ], HelixHeadlessDonutChart.prototype, "sweep", void 0);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether a box reaches past the window's edges, by more than a pixel.
3
+ *
4
+ * What a drawer resting at a snap point asks of the element focus has just
5
+ * moved to: the part of the panel past the window's edge is off screen, and a
6
+ * control there has focus where the reader cannot see it.
7
+ */
8
+ export declare const beyondWindow: (box: Pick<DOMRectReadOnly, 'bottom' | 'left' | 'right' | 'top'>, width: number, height: number) => boolean;
@@ -0,0 +1 @@
1
+ export const beyondWindow = (box, width, height) => box.top < -1 || box.left < -1 || box.bottom > height + 1 || box.right > width + 1;