@fusion.dev/helix-headless 0.0.0-dev → 0.0.2

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 (210) hide show
  1. package/custom-elements.json +4513 -4483
  2. package/dist/accordion/item/accordion-item.d.ts +13 -15
  3. package/dist/accordion/item/accordion-item.js +15 -17
  4. package/dist/announcement/root/announcement-root.d.ts +7 -25
  5. package/dist/announcement/root/announcement-root.js +7 -20
  6. package/dist/app-header/root/app-header-root.d.ts +10 -17
  7. package/dist/app-header/root/app-header-root.js +9 -18
  8. package/dist/avatar/group/avatar-group.d.ts +10 -19
  9. package/dist/avatar/group/avatar-group.js +12 -17
  10. package/dist/avatar/root/avatar-root.d.ts +8 -8
  11. package/dist/avatar/root/avatar-root.js +19 -20
  12. package/dist/badge/root/badge-root.d.ts +6 -6
  13. package/dist/badge/root/badge-root.js +13 -13
  14. package/dist/bar-chart/root/bar-chart-root.d.ts +21 -29
  15. package/dist/bar-chart/root/bar-chart-root.js +42 -57
  16. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +12 -18
  17. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +13 -16
  18. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -28
  19. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -28
  20. package/dist/button/root/button-root.d.ts +84 -94
  21. package/dist/button/root/button-root.js +82 -92
  22. package/dist/callout/root/callout-root.d.ts +4 -5
  23. package/dist/carousel/root/carousel-root.d.ts +59 -71
  24. package/dist/carousel/root/carousel-root.js +73 -101
  25. package/dist/chat/composer/chat-composer.d.ts +29 -33
  26. package/dist/chat/composer/chat-composer.js +40 -44
  27. package/dist/chat/message/chat-message.d.ts +25 -25
  28. package/dist/chat/message/chat-message.js +26 -26
  29. package/dist/chat/root/chat-root.d.ts +28 -41
  30. package/dist/chat/root/chat-root.js +27 -40
  31. package/dist/checkbox/root/checkbox-root.d.ts +10 -12
  32. package/dist/checkbox/root/checkbox-root.js +29 -35
  33. package/dist/checkbox-group/root/checkbox-group-root.d.ts +32 -45
  34. package/dist/checkbox-group/root/checkbox-group-root.js +53 -79
  35. package/dist/code-block/root/code-block-root.d.ts +3 -4
  36. package/dist/code-block/root/code-block-root.js +8 -12
  37. package/dist/color-input/root/color-input-root.d.ts +36 -37
  38. package/dist/color-input/root/color-input-root.js +29 -34
  39. package/dist/color-picker/color.d.ts +7 -8
  40. package/dist/color-picker/color.js +7 -8
  41. package/dist/color-picker/root/color-picker-root.d.ts +55 -57
  42. package/dist/color-picker/root/color-picker-root.js +60 -64
  43. package/dist/combobox/root/combobox-root.d.ts +53 -58
  44. package/dist/combobox/root/combobox-root.js +85 -94
  45. package/dist/command/root/command-root.d.ts +8 -8
  46. package/dist/command/root/command-root.js +29 -33
  47. package/dist/copy-button/root/copy-button-root.d.ts +21 -24
  48. package/dist/copy-button/root/copy-button-root.js +25 -35
  49. package/dist/data-table/root/data-table-root.d.ts +77 -76
  50. package/dist/data-table/root/data-table-root.js +95 -84
  51. package/dist/data-table/root/order.d.ts +2 -2
  52. package/dist/data-table/root/order.js +1 -3
  53. package/dist/date-input/root/date-input-root.d.ts +88 -93
  54. package/dist/date-input/root/date-input-root.js +147 -158
  55. package/dist/date-picker/root/date-picker-root.d.ts +75 -83
  56. package/dist/date-picker/root/date-picker-root.js +120 -143
  57. package/dist/dialog/root/dialog-root.d.ts +41 -24
  58. package/dist/dialog/root/dialog-root.js +47 -24
  59. package/dist/divider/root/divider-root.d.ts +5 -6
  60. package/dist/divider/root/divider-root.js +4 -5
  61. package/dist/donut-chart/root/donut-chart-root.d.ts +22 -25
  62. package/dist/donut-chart/root/donut-chart-root.js +37 -51
  63. package/dist/drawer/root/drawer-root.d.ts +24 -29
  64. package/dist/drawer/root/drawer-root.js +15 -22
  65. package/dist/drilldown/item/drilldown-item.d.ts +14 -14
  66. package/dist/drilldown/item/drilldown-item.js +24 -26
  67. package/dist/drilldown/root/drilldown-root.d.ts +8 -10
  68. package/dist/drilldown/root/drilldown-root.js +6 -7
  69. package/dist/element-events.generated.js +1 -1
  70. package/dist/file-input/root/file-input-root.d.ts +20 -24
  71. package/dist/file-input/root/file-input-root.js +42 -57
  72. package/dist/format-date/root/format-date-root.js +1 -1
  73. package/dist/heatmap/root/buckets.d.ts +8 -8
  74. package/dist/heatmap/root/buckets.js +8 -8
  75. package/dist/heatmap/root/heatmap-root.d.ts +57 -63
  76. package/dist/heatmap/root/heatmap-root.js +72 -83
  77. package/dist/icon/root/icon-root.d.ts +4 -4
  78. package/dist/icon/root/icon-root.js +9 -9
  79. package/dist/icon-button/root/icon-button-root.d.ts +4 -6
  80. package/dist/icon-button/root/icon-button-root.js +4 -6
  81. package/dist/image/root/image-root.d.ts +49 -59
  82. package/dist/image/root/image-root.js +55 -65
  83. package/dist/index.d.ts +5 -5
  84. package/dist/index.js +5 -5
  85. package/dist/input/root/input-root.d.ts +61 -85
  86. package/dist/input/root/input-root.js +79 -106
  87. package/dist/kbd/root/kbd-root.d.ts +8 -7
  88. package/dist/kbd/root/kbd-root.js +71 -11
  89. package/dist/legend/root/legend-root.d.ts +1 -1
  90. package/dist/legend/root/legend-root.js +4 -5
  91. package/dist/line-chart/root/line-chart-root.d.ts +26 -30
  92. package/dist/line-chart/root/line-chart-root.js +10 -10
  93. package/dist/list/item/list-item.d.ts +14 -18
  94. package/dist/list/item/list-item.js +18 -22
  95. package/dist/list/root/list-root.d.ts +4 -4
  96. package/dist/list/root/list-root.js +3 -3
  97. package/dist/listbox/root/listbox-root.d.ts +31 -58
  98. package/dist/listbox/root/listbox-root.js +66 -109
  99. package/dist/megamenu/root/megamenu-root.d.ts +34 -35
  100. package/dist/megamenu/root/megamenu-root.js +53 -58
  101. package/dist/menu/item/menu-item.d.ts +39 -53
  102. package/dist/menu/item/menu-item.js +50 -64
  103. package/dist/menu/root/menu-root.d.ts +30 -40
  104. package/dist/menu/root/menu-root.js +49 -82
  105. package/dist/meter/root/meter-root.d.ts +49 -53
  106. package/dist/meter/root/meter-root.js +22 -27
  107. package/dist/navigation/root/navigation-root.js +11 -19
  108. package/dist/notifications/notification/notification.d.ts +16 -22
  109. package/dist/notifications/notification/notification.js +21 -27
  110. package/dist/notifications/root/notifications-root.d.ts +31 -39
  111. package/dist/notifications/root/notifications-root.js +41 -52
  112. package/dist/number-input/root/number-input-root.d.ts +31 -33
  113. package/dist/number-input/root/number-input-root.js +37 -39
  114. package/dist/option/root/option-root.d.ts +73 -74
  115. package/dist/option/root/option-root.js +62 -64
  116. package/dist/outline/root/outline-root.d.ts +38 -44
  117. package/dist/outline/root/outline-root.js +66 -82
  118. package/dist/pagination/root/pagination-root.d.ts +87 -92
  119. package/dist/pagination/root/pagination-root.js +116 -123
  120. package/dist/pagination/size/pagination-size.d.ts +31 -50
  121. package/dist/pagination/size/pagination-size.js +35 -55
  122. package/dist/pagination/summary/pagination-summary.d.ts +12 -12
  123. package/dist/pagination/summary/pagination-summary.js +18 -18
  124. package/dist/pin-input/root/pin-input-root.d.ts +53 -70
  125. package/dist/pin-input/root/pin-input-root.js +74 -94
  126. package/dist/popover/root/popover-root.d.ts +15 -20
  127. package/dist/popover/root/popover-root.js +19 -36
  128. package/dist/progress/root/progress-root.d.ts +12 -14
  129. package/dist/progress/root/progress-root.js +22 -25
  130. package/dist/qr-code/root/qr-code-root.d.ts +11 -11
  131. package/dist/qr-code/root/qr-code-root.js +12 -14
  132. package/dist/radio/group/radio-group.js +19 -26
  133. package/dist/radio/root/radio-root.d.ts +12 -13
  134. package/dist/radio/root/radio-root.js +12 -13
  135. package/dist/rating/root/rating-root.d.ts +25 -30
  136. package/dist/rating/root/rating-root.js +43 -50
  137. package/dist/scroll-area/root/scroll-area-root.d.ts +11 -14
  138. package/dist/scroll-area/root/scroll-area-root.js +39 -33
  139. package/dist/select/root/select-root.d.ts +7 -12
  140. package/dist/select/root/select-root.js +40 -55
  141. package/dist/slider/root/slider-root.d.ts +53 -60
  142. package/dist/slider/root/slider-root.js +74 -85
  143. package/dist/sparkline/root/sparkline-root.d.ts +43 -47
  144. package/dist/sparkline/root/sparkline-root.js +23 -32
  145. package/dist/speed-dial/item/speed-dial-item.d.ts +6 -6
  146. package/dist/speed-dial/item/speed-dial-item.js +9 -9
  147. package/dist/speed-dial/root/speed-dial-root.d.ts +21 -25
  148. package/dist/speed-dial/root/speed-dial-root.js +32 -40
  149. package/dist/splitter/root/splitter-root.d.ts +98 -111
  150. package/dist/splitter/root/splitter-root.js +96 -123
  151. package/dist/stat/root/stat-root.d.ts +2 -7
  152. package/dist/stat/root/stat-root.js +0 -5
  153. package/dist/steps/step/step.d.ts +19 -24
  154. package/dist/steps/step/step.js +27 -32
  155. package/dist/switch/root/switch-root.js +2 -2
  156. package/dist/table/column/table-column.d.ts +54 -60
  157. package/dist/table/column/table-column.js +95 -68
  158. package/dist/table/root/table-root.d.ts +5 -6
  159. package/dist/table/root/table-root.js +7 -10
  160. package/dist/tabs/panel/tab-panel.d.ts +21 -25
  161. package/dist/tabs/panel/tab-panel.js +25 -29
  162. package/dist/tabs/root/tabs-root.d.ts +25 -34
  163. package/dist/tabs/root/tabs-root.js +22 -28
  164. package/dist/tabs/tab/tab.d.ts +12 -12
  165. package/dist/tabs/tab/tab.js +19 -20
  166. package/dist/textarea/root/textarea-root.d.ts +36 -36
  167. package/dist/textarea/root/textarea-root.js +43 -47
  168. package/dist/time-input/root/time-input-root.d.ts +58 -68
  169. package/dist/time-input/root/time-input-root.js +62 -77
  170. package/dist/time-picker/root/time-picker-root.d.ts +73 -79
  171. package/dist/time-picker/root/time-picker-root.js +72 -84
  172. package/dist/timeline/item/timeline-item.d.ts +8 -11
  173. package/dist/timeline/item/timeline-item.js +8 -11
  174. package/dist/timeline/root/timeline-root.d.ts +5 -7
  175. package/dist/timeline/root/timeline-root.js +5 -7
  176. package/dist/toast/item/toast-item.d.ts +9 -27
  177. package/dist/toast/item/toast-item.js +19 -41
  178. package/dist/toast/root/toast-root.d.ts +10 -14
  179. package/dist/toast/root/toast-root.js +4 -5
  180. package/dist/toggle/group/toggle-group.d.ts +6 -15
  181. package/dist/toggle/group/toggle-group.js +21 -36
  182. package/dist/toggle/root/toggle-root.d.ts +26 -27
  183. package/dist/toggle/root/toggle-root.js +30 -31
  184. package/dist/toolbar/root/toolbar-root.d.ts +7 -10
  185. package/dist/toolbar/root/toolbar-root.js +10 -14
  186. package/dist/tooltip/root/tooltip-root.d.ts +52 -59
  187. package/dist/tooltip/root/tooltip-root.js +98 -93
  188. package/dist/tour/root/tour-root.d.ts +19 -23
  189. package/dist/tour/root/tour-root.js +31 -41
  190. package/dist/tour/stop/tour-stop.d.ts +14 -15
  191. package/dist/tour/stop/tour-stop.js +31 -34
  192. package/dist/tree/item/tree-item.d.ts +30 -35
  193. package/dist/tree/item/tree-item.js +43 -55
  194. package/dist/tree/root/tree-root.d.ts +7 -10
  195. package/dist/tree/root/tree-root.js +33 -42
  196. package/dist/trend/root/trend-root.d.ts +3 -5
  197. package/dist/trend/root/trend-root.js +5 -9
  198. package/dist/video/root/video-root.d.ts +100 -124
  199. package/dist/video/root/video-root.js +142 -176
  200. package/dist/video-playlist/item/video-playlist-item.d.ts +16 -16
  201. package/dist/video-playlist/item/video-playlist-item.js +24 -24
  202. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -8
  203. package/dist/video-playlist/menu/video-playlist-menu.js +20 -29
  204. package/dist/video-playlist/root/video-playlist-root.d.ts +16 -11
  205. package/dist/video-playlist/root/video-playlist-root.js +21 -25
  206. package/dist/virtual-list/root/virtual-list-root.d.ts +8 -12
  207. package/dist/virtual-list/root/virtual-list-root.js +11 -16
  208. package/jsx.d.ts +9797 -12561
  209. package/package.json +6 -6
  210. package/vue.d.ts +2684 -3228
@@ -70,34 +70,28 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
70
70
  * Accessible name for the dialog.
71
71
  */
72
72
  this.label = '';
73
+ /* Opened and closed from anywhere on the page, without a line of script:
74
+ `<helix-button commandfor="…" command="--show">`. See `CommandController`
75
+ for why this is the platform's invoker rather than a `data-` recipe. */
76
+ this.commands = new CommandController(this, {
77
+ commands: {
78
+ '--close': () => this.close(),
79
+ '--show': () => this.show(),
80
+ '--toggle': () => this.toggleOpen(),
81
+ },
82
+ });
73
83
  /**
74
- * Whether Escape can close it.
84
+ * Whether Escape or a press on the backdrop can close it.
75
85
  *
76
86
  * Off for a dialog that must be answered. It does not disable the close
77
87
  * control a consumer slots in: refusing to be dismissed is not the same as
78
88
  * refusing to be closed, and a dialog with no way out at all is a trap.
79
89
  *
80
- * Escape *and* a press on the backdrop, which it now genuinely means. The
81
- * sentence said both for a long time while nothing listened for a backdrop
82
- * press, so it promised a behavior a consumer would have written their
83
- * markup around; the fix then was to narrow the sentence, and the fix now is
84
- * to build the half that was missing.
85
- *
86
90
  * A persistent dialog does not ignore that press. It answers it: see
87
91
  * `refuse`, which is the only way a dialog that will not be dismissed can say
88
92
  * so at the moment a reader asks.
89
93
  */
90
94
  this.persistent = false;
91
- /* Opened and closed from anywhere on the page, without a line of script:
92
- `<helix-button commandfor="…" command="--show">`. See `CommandController`
93
- for why this is the platform's invoker rather than a `data-` recipe. */
94
- this.commands = new CommandController(this, {
95
- commands: {
96
- '--close': () => this.close(),
97
- '--show': () => this.show(),
98
- '--toggle': () => this.toggleOpen(),
99
- },
100
- });
101
95
  /** What a value set before the element existed is kept in. */
102
96
  this.returned = '';
103
97
  /**
@@ -134,7 +128,7 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
134
128
 
135
129
  `cancel` is deliberately not relayed. `handleCancel` prevents it so that
136
130
  Escape is a request rather than an act, so the native one never completes:
137
- relaying it would announce a dismissal that was refused. See 296. */
131
+ relaying it would announce a dismissal that was refused. */
138
132
  this.relayNativeEvent(event);
139
133
  };
140
134
  /**
@@ -172,9 +166,9 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
172
166
  *
173
167
  * **The whole point of a `<dialog>` returning a value is lost behind a shadow
174
168
  * boundary**, which is where this one is: the platform's contract is
175
- * `close(value)` then read `returnValue`, and a consumer could do neither
176
- * because `querySelector` does not reach the element. A confirmation asking
177
- * which button was pressed is the ordinary case and had no answer.
169
+ * `close(value)` then read `returnValue`, and `querySelector` does not reach
170
+ * the element to do either. A confirmation asking which button was pressed is
171
+ * the ordinary case.
178
172
  *
179
173
  * Held here as well as on the element, so a value set before the first render
180
174
  * survives to it and a consumer reading one back gets what they wrote.
@@ -273,19 +267,48 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
273
267
  * this decides only when it happens. Removed first so a second press
274
268
  * restarts it: without that, pressing twice does nothing the second time,
275
269
  * which is the impression the whole thing exists to avoid.
270
+ *
271
+ * **`once: true` is not a release when the event cannot arrive.** Under
272
+ * `prefers-reduced-motion: reduce` the styled tier sets `animation: none`, so
273
+ * no animation runs, `animationend` never fires, and every refused press left
274
+ * a listener that could not be removed and an attribute that stayed on. The
275
+ * controller bounds it to one listener, aborted before the next is added.
276
+ *
277
+ * **And the attribute is cleared at once when no animation is running**, asked
278
+ * of the platform rather than of a media query: this tier does not know what
279
+ * refusing looks like, and the same silence arrives from a consumer's
280
+ * stylesheet, from reduced motion, and from no styled tier being loaded at
281
+ * all.
282
+ *
283
+ * **`CSSAnimation` specifically, because `getAnimations` returns transitions
284
+ * too.** A panel that is still running its entrance transition answers the
285
+ * bare `length` check with a truthy number while no animation exists to end,
286
+ * so a refusal landing inside that window took the listener branch and waited
287
+ * for an `animationend` that was never coming: the attribute stayed on until
288
+ * the next refused press. That is the same bug this method exists to close,
289
+ * one window narrower. `getAnimations` flushes pending style itself, so no
290
+ * reflow is forced for it.
276
291
  */
277
292
  refuse() {
278
293
  const panel = this.dialog;
279
294
  if (!panel) {
280
295
  return;
281
296
  }
297
+ this.refusal?.abort();
282
298
  panel.removeAttribute('data-refused');
283
299
  // Read forces the removal to land before the attribute goes back on, or the
284
300
  // two happen in one frame and the animation never restarts.
285
301
  void panel.offsetWidth;
286
302
  panel.setAttribute('data-refused', '');
303
+ const animating = panel.getAnimations().some((one) => one instanceof CSSAnimation);
304
+ if (!animating) {
305
+ panel.removeAttribute('data-refused');
306
+ return;
307
+ }
308
+ this.refusal = new AbortController();
287
309
  panel.addEventListener('animationend', () => panel.removeAttribute('data-refused'), {
288
310
  once: true,
311
+ signal: this.refusal.signal,
289
312
  });
290
313
  }
291
314
  render() {
@@ -304,15 +327,15 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
304
327
  </dialog>`;
305
328
  }
306
329
  };
330
+ __decorate([
331
+ property({ attribute: 'closedby', reflect: true })
332
+ ], HelixHeadlessDialog.prototype, "closedBy", void 0);
307
333
  __decorate([
308
334
  property()
309
335
  ], HelixHeadlessDialog.prototype, "label", void 0);
310
336
  __decorate([
311
337
  property({ reflect: true, type: Boolean })
312
338
  ], HelixHeadlessDialog.prototype, "persistent", void 0);
313
- __decorate([
314
- property({ attribute: 'closedby', reflect: true })
315
- ], HelixHeadlessDialog.prototype, "closedBy", void 0);
316
339
  HelixHeadlessDialog = __decorate([
317
340
  customElement('helix-headless-dialog')
318
341
  ], HelixHeadlessDialog);
@@ -26,10 +26,6 @@ import { type PropertyValues, type TemplateResult } from 'lit';
26
26
  * @csspart line - The rule itself, or each half of it where something is set in.
27
27
  */
28
28
  export declare class HelixHeadlessDivider extends HelixElement {
29
- /**
30
- * Which way the rule runs.
31
- */
32
- orientation?: 'horizontal' | 'vertical';
33
29
  /**
34
30
  * Whether the rule is announced as a separator.
35
31
  *
@@ -45,14 +41,17 @@ export declare class HelixHeadlessDivider extends HelixElement {
45
41
  * here has to be.
46
42
  */
47
43
  announced: boolean;
44
+ /**
45
+ * Which way the rule runs.
46
+ */
47
+ orientation?: 'horizontal' | 'vertical';
48
48
  /**
49
49
  * Marks the middle region when nothing has been set into it.
50
50
  *
51
51
  * A divider with no content has to be one continuous line, and the space
52
52
  * either side of the content is what would break it. `:empty` cannot answer
53
53
  * this and neither can `:host(:has(...))`, which is invalid CSS dropped at
54
- * parse time: `check:selectors` caught exactly that rule here, written in
55
- * this file, by an author who had already read the note saying so.
54
+ * parse time.
56
55
  *
57
56
  * On the region inside the shadow root rather than on the host, because an
58
57
  * attribute written onto the host is a change to markup the consumer rendered.
@@ -57,8 +57,7 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
57
57
  * A divider with no content has to be one continuous line, and the space
58
58
  * either side of the content is what would break it. `:empty` cannot answer
59
59
  * this and neither can `:host(:has(...))`, which is invalid CSS dropped at
60
- * parse time: `check:selectors` caught exactly that rule here, written in
61
- * this file, by an author who had already read the note saying so.
60
+ * parse time.
62
61
  *
63
62
  * On the region inside the shadow root rather than on the host, because an
64
63
  * attribute written onto the host is a change to markup the consumer rendered.
@@ -104,12 +103,12 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
104
103
  <div part="line" role="presentation"></div>`;
105
104
  }
106
105
  };
107
- __decorate([
108
- property({ reflect: true })
109
- ], HelixHeadlessDivider.prototype, "orientation", void 0);
110
106
  __decorate([
111
107
  property({ reflect: true, type: Boolean })
112
108
  ], HelixHeadlessDivider.prototype, "announced", void 0);
109
+ __decorate([
110
+ property({ reflect: true })
111
+ ], HelixHeadlessDivider.prototype, "orientation", void 0);
113
112
  HelixHeadlessDivider = __decorate([
114
113
  customElement('helix-headless-divider')
115
114
  ], HelixHeadlessDivider);
@@ -15,7 +15,7 @@ declare const HelixHeadlessDonutChart_base: typeof HelixElement & (new (...args:
15
15
  *
16
16
  * **It refuses negative values rather than drawing them.** A share of a whole
17
17
  * cannot be less than nothing, and an arc for a negative number either runs
18
- * backwards over its neighbours or is silently dropped. Those rows are skipped
18
+ * backwards over its neighbors or is silently dropped. Those rows are skipped
19
19
  * and the total is of what is left, which is the only reading that stays true.
20
20
  *
21
21
  * **The shape is drawn with a dashed stroke, not with arc commands.** One
@@ -70,11 +70,10 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
70
70
  * reading for opposite sides of the chart. So the slices say which one they
71
71
  * are and this only holds the answer.
72
72
  *
73
- * Set here rather than in a constructor, and that is not a style choice. The
74
- * analyzer reads `this.pointer.axis = 'none'` in a constructor body as a
75
- * declaration of a public field called `axis`, and failed the build with
76
- * `HelixHeadlessDonutChart.tracks has no description` for a member that does not
77
- * exist on this class at all.
73
+ * Set here rather than in a constructor, and it must not move there: the
74
+ * analyzer reads `this.pointer.axis = 'none'` in a constructor body as the
75
+ * declaration of a public field, and fails the build demanding a description
76
+ * for a member this class does not have.
78
77
  */
79
78
  connectedCallback(): void;
80
79
  /**
@@ -90,11 +89,11 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
90
89
  * measured from anything but zero is, which is why this is a value here and
91
90
  * the bar chart's baseline is not a property at all.
92
91
  *
93
- * **Geometry rather than a CSS hook, and it had to move.** This was
94
- * `--donut-chart-thickness`, and the dash arithmetic needs the circumference,
95
- * which needs the radius: reading a custom property means `getComputedStyle`,
96
- * which is client-only, so a server would have drawn a different ring than
97
- * the client. A plot's proportions are markup for the same reason `curve` is.
92
+ * **Geometry rather than a CSS hook.** The dash arithmetic needs the
93
+ * circumference, which needs the radius, and reading a custom property means
94
+ * `getComputedStyle`, which is client-only: a server would draw a different
95
+ * ring than the client. A plot's proportions are markup for the same reason
96
+ * `curve` is.
98
97
  */
99
98
  hole?: 'large' | 'none' | 'small';
100
99
  /**
@@ -110,11 +109,10 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
110
109
  * the band is, this is angular and says how far round it goes. A `half`
111
110
  * `none` is a semi-pie and is a real thing to want.
112
111
  *
113
- * **Not a gauge**, and the distinction is worth stating because this row was
114
- * first filed as one. A gauge is one value against a range, which is a
115
- * different data shape entirely and is `Meter`, whose `round` example already
116
- * draws the reading as a ring. This divides a whole into parts and then
117
- * declines to use the bottom half of the circle.
112
+ * **Not a gauge.** A gauge is one value against a range, which is a different
113
+ * data shape entirely and is `Meter`, whose `round` example already draws the
114
+ * reading as a ring. This divides a whole into parts and then declines to use
115
+ * the bottom half of the circle.
118
116
  *
119
117
  * Reflected, because the stylesheet has three things to say about it: the
120
118
  * rotation that puts the first slice at nine o'clock, the aspect ratio of a
@@ -172,15 +170,14 @@ export declare class HelixHeadlessDonutChart extends HelixHeadlessDonutChart_bas
172
170
  * path is here for every donut and is `fill: none; stroke: none` until
173
171
  * something asks for it.
174
172
  *
175
- * **Not a replacement for the dash, which was the first plan.** The dash
176
- * carries three jobs and only one of them is the shape: a share growing is a
177
- * `stroke-dasharray` interpolating with no reflow, and `@starting-style` on
178
- * that same property is the whole reason the ring sweeps in rather than
179
- * appearing. A `d` cannot do either. CSS interpolates one only between paths
180
- * of identical command structure, and the large-arc flag flips the moment a
181
- * slice crosses a half turn, so a growing slice would pop partway through the
182
- * transition it was meant to smooth. Both animations stay on the dash and this
183
- * path follows it.
173
+ * **Not a replacement for the dash.** The dash carries three jobs and only
174
+ * one of them is the shape: a share growing is a `stroke-dasharray`
175
+ * interpolating with no reflow, and `@starting-style` on that same property is
176
+ * the whole reason the ring sweeps in rather than appearing. A `d` cannot do
177
+ * either. CSS interpolates one only between paths of identical command
178
+ * structure, and the large-arc flag flips the moment a slice crosses a half
179
+ * turn, so a growing slice would pop partway through the transition it was
180
+ * meant to smooth. Both animations stay on the dash and this path follows it.
184
181
  *
185
182
  * The turn to twelve o'clock is arithmetic here rather than the rotation the
186
183
  * stylesheet gives the circles. That rule uses `transform-box: fill-box`, so
@@ -29,12 +29,10 @@ const GAP = 9999;
29
29
  * How much of the radius the ring takes, by name.
30
30
  *
31
31
  * **The outer edge is fixed and the radius follows the thickness**, which is
32
- * what makes `none` a pie and makes clipping impossible. The stroke sits astride
33
- * its own radius, so a ring drawn at a fixed `r` grows outward as well as
34
- * inward: measured against a 100 box, the old fixed `r=40` had an unstated
35
- * ceiling at a thickness of 20, and anything past it crossed the view box and
36
- * was cut with nothing to say so. Closing the hole that way would have needed a
37
- * thickness of 80, spanning `r=0` to `r=80` in a box whose half is 50.
32
+ * what makes `none` a pie. The stroke sits astride its own radius, so a ring
33
+ * drawn at a fixed `r` grows outward as well as inward: against a 100 box, a
34
+ * fixed `r=40` has an unstated ceiling at a thickness of 20, and anything past
35
+ * it crosses the view box and is cut with nothing to say so.
38
36
  *
39
37
  * Derived instead, `r = EDGE - thickness / 2`, the outer edge lands on `EDGE`
40
38
  * for every value and the inner edge is `EDGE - thickness`. A pie is where the
@@ -65,7 +63,7 @@ const THICKNESS = {
65
63
  *
66
64
  * **It refuses negative values rather than drawing them.** A share of a whole
67
65
  * cannot be less than nothing, and an arc for a negative number either runs
68
- * backwards over its neighbours or is silently dropped. Those rows are skipped
66
+ * backwards over its neighbors or is silently dropped. Those rows are skipped
69
67
  * and the total is of what is left, which is the only reading that stays true.
70
68
  *
71
69
  * **The shape is drawn with a dashed stroke, not with arc commands.** One
@@ -110,7 +108,6 @@ const THICKNESS = {
110
108
  * @cssproperty --donut-chart-stroke - How thick the ring is drawn, derived from `hole`.
111
109
  */
112
110
  let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSource(HelixElement) {
113
- /* The slices, in table order, with anything negative dropped. */
114
111
  /**
115
112
  * The pointer is not mapped across this one.
116
113
  *
@@ -121,11 +118,10 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
121
118
  * reading for opposite sides of the chart. So the slices say which one they
122
119
  * are and this only holds the answer.
123
120
  *
124
- * Set here rather than in a constructor, and that is not a style choice. The
125
- * analyzer reads `this.pointer.axis = 'none'` in a constructor body as a
126
- * declaration of a public field called `axis`, and failed the build with
127
- * `HelixHeadlessDonutChart.tracks has no description` for a member that does not
128
- * exist on this class at all.
121
+ * Set here rather than in a constructor, and it must not move there: the
122
+ * analyzer reads `this.pointer.axis = 'none'` in a constructor body as the
123
+ * declaration of a public field, and fails the build demanding a description
124
+ * for a member this class does not have.
129
125
  */
130
126
  connectedCallback() {
131
127
  super.connectedCallback();
@@ -176,16 +172,10 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
176
172
  */
177
173
  renderPlot(shares) {
178
174
  /* The thickness is declared here, on the box that holds both the ring and
179
- the middle, and not on the slices.
180
- *
181
- * It was on each `<circle>`, and `[part="center"]` read it to size the hole
182
- * it fills. A custom property inherits down and never sideways, so the
183
- * middle, being a sibling, always got the fallback: the hole was sized as if
184
- * every ring were the resting thickness. At `hole="large"` that made the
185
- * middle smaller than the actual hole and the total fitted with room to
186
- * spare, and at the default the two matched exactly and the total overflowed
187
- * onto the slices. One reads as fine and the other as a bug, from one
188
- * mistake. */
175
+ the middle, and never on the slices. A custom property inherits down and
176
+ never sideways, so `[part="center"]` is a sibling of the circles and would
177
+ only ever read the fallback, sizing the hole as if every ring were the
178
+ resting thickness. */
189
179
  return html `<div
190
180
  aria-hidden="true"
191
181
  id="helix-chart-plot"
@@ -263,15 +253,14 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
263
253
  * path is here for every donut and is `fill: none; stroke: none` until
264
254
  * something asks for it.
265
255
  *
266
- * **Not a replacement for the dash, which was the first plan.** The dash
267
- * carries three jobs and only one of them is the shape: a share growing is a
268
- * `stroke-dasharray` interpolating with no reflow, and `@starting-style` on
269
- * that same property is the whole reason the ring sweeps in rather than
270
- * appearing. A `d` cannot do either. CSS interpolates one only between paths
271
- * of identical command structure, and the large-arc flag flips the moment a
272
- * slice crosses a half turn, so a growing slice would pop partway through the
273
- * transition it was meant to smooth. Both animations stay on the dash and this
274
- * path follows it.
256
+ * **Not a replacement for the dash.** The dash carries three jobs and only
257
+ * one of them is the shape: a share growing is a `stroke-dasharray`
258
+ * interpolating with no reflow, and `@starting-style` on that same property is
259
+ * the whole reason the ring sweeps in rather than appearing. A `d` cannot do
260
+ * either. CSS interpolates one only between paths of identical command
261
+ * structure, and the large-arc flag flips the moment a slice crosses a half
262
+ * turn, so a growing slice would pop partway through the transition it was
263
+ * meant to smooth. Both animations stay on the dash and this path follows it.
275
264
  *
276
265
  * The turn to twelve o'clock is arithmetic here rather than the rotation the
277
266
  * stylesheet gives the circles. That rule uses `transform-box: fill-box`, so
@@ -317,16 +306,14 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
317
306
  Ids are scoped to the shadow root, so an index is enough to keep them
318
307
  apart, and two donuts on a page cannot collide. */
319
308
  /* **`fill="none"` as an attribute, not a rule, because this tier has
320
- no rules.** An SVG path fills black by default and the styled tier
321
- says `fill: none` in its own stylesheet, so the shape was invisible
322
- there and four black slices covering the ring everywhere else. Caught
323
- by retaking the visual baselines: the headless donut lost two of its
324
- four greys to a closed shape nobody had told to stop filling.
309
+ no rules.** An SVG path fills black by default, and the styled tier's
310
+ own `fill: none` covers only that tier: everywhere else these closed
311
+ shapes paint over the ring.
325
312
 
326
313
  A presentation attribute loses to any CSS rule, so the styled tier
327
314
  still decides and a consumer can still fill this if they want one.
328
- What it cannot do any more is fill by accident on the tier whose
329
- whole premise is that it ships no CSS. */
315
+ What it cannot do is fill by accident on the tier whose whole premise
316
+ is that it ships no CSS. */
330
317
  const clip = `helix-donut-edge-${index}`;
331
318
  return svg `<clipPath id=${clip}><path d=${shape} /></clipPath>
332
319
  <path
@@ -353,24 +340,23 @@ let HelixHeadlessDonutChart = class HelixHeadlessDonutChart extends MixinChartSo
353
340
  if (!share) {
354
341
  return drawTooltip(this.sourceRows, at, this.tag('tooltip'));
355
342
  }
356
- /* **Outside the ring, on the slice's own bearing.** Centered in the hole was
357
- the first version: harmless over a donut, since the hole is empty, and it
358
- covers the data on a pie, and in neither case does it say *which* slice it
359
- means. Out here it does, and one rule serves both.
360
- *
361
- * The mid-angle, less a quarter turn because the ring is rotated to start
362
- * at twelve o'clock and this arithmetic starts at three. The point is the
363
- * outer edge, and the box is pushed a little further along the same bearing
364
- * so its arrow rests on the ring rather than in it. */
343
+ /* **Outside the ring, on the slice's own bearing**, rather than centered in
344
+ the hole: centered covers the data on a pie, and in neither shape does it
345
+ say *which* slice it means. Out here one rule serves both.
346
+
347
+ The mid-angle, less a quarter turn because the ring is rotated to start
348
+ at twelve o'clock and this arithmetic starts at three. The point is the
349
+ outer edge, and the box is pushed a little further along the same bearing
350
+ so its arrow rests on the ring rather than in it. */
365
351
  const angle = (share.start + share.fraction / 2) * 2 * Math.PI - Math.PI / 2;
366
352
  const edge = EDGE;
367
353
  const x = CENTER + Math.cos(angle) * edge;
368
354
  const y = CENTER + Math.sin(angle) * edge;
369
355
  return drawTooltip(this.sourceRows, at, this.tag('tooltip'), {
370
356
  /* The preferred side from the bearing's dominant axis, and
371
- `FloatingController` moves it if that side does not fit. Four fixed
372
- sides could not express a bearing at all, which is what made the arrow
373
- miss the ring; a preference plus flipping can. */
357
+ `FloatingController` moves it if that side does not fit. A fixed side
358
+ cannot express a bearing, so the arrow misses the ring; a preference
359
+ plus flipping can. */
374
360
  placement: Math.abs(Math.cos(angle)) > Math.abs(Math.sin(angle))
375
361
  ? Math.cos(angle) > 0
376
362
  ? 'right'
@@ -5,8 +5,9 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
5
5
  * @summary A panel that slides in from an edge.
6
6
  *
7
7
  * @description
8
- * Takes `MixinControllerOpen`, so `open`, `defaultOpen`, and `OpenChange` behave exactly
9
- * as they do on an accordion item, and a consumer already knows the API.
8
+ * Takes `MixinControllerOpen`, so `open`, `defaultOpen` and the
9
+ * `helix-before-open` and `helix-before-close` requests behave exactly as they
10
+ * do on an accordion item, and a consumer already knows the API.
10
11
  *
11
12
  * Modal by default, which is three things together and not one: focus is
12
13
  * trapped inside, Escape and an outside press close it, and the page behind is
@@ -15,16 +16,10 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
15
16
  *
16
17
  * Content stays mounted when closed, so it is in the server's markup and can
17
18
  * animate. A closed `<dialog>` is already out of the tab order and out of the
18
- * accessibility tree, so nothing here writes `inert`.
19
- *
20
- * **This described a hand-written `inert` until 21 Aug 2026, and had done since
21
- * the panel became a `<dialog>`.** The rewrite took the `role`, the
22
- * `aria-modal`, the scrim and the `inert` with it, because the element brings
23
- * all four, and the comments at the two call sites say so. The class doc did
24
- * not, and `drawer-root.ssr.spec.ts` has asserted the panel carries no `inert`
25
- * the whole time: a spec three files away existing to contradict the prose is
26
- * the same shape as `Stat`'s `detail` slot, which is what `check:references`
27
- * was written after and is the half it cannot see.
19
+ * accessibility tree, so nothing here writes `inert`. The `role`, the
20
+ * `aria-modal` and the scrim come from the element too, and
21
+ * `drawer-root.ssr.spec.ts` asserts the panel carries no hand-written `inert`
22
+ * and no hand-written `role`.
28
23
  *
29
24
  * Opened declaratively with the platform's invoker attributes:
30
25
  *
@@ -44,7 +39,7 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
44
39
  *
45
40
  * @event {Event} close - Relayed, because the platform's own does not escape.
46
41
  * @event {HelixBeforeCloseEvent} helix-before-close - Fired before the panel closes, and cancelable.
47
- * @event {HelixBeforeOpenEvent} helix-before-open - Fired before the drawer opens or closes. Cancelable: refusing it takes the decision and nothing moves.
42
+ * @event {HelixBeforeOpenEvent} helix-before-open - Fired before the panel opens. Cancelable: refusing it takes the decision and nothing moves.
48
43
  * @event {Event} toggle - Says the state moved, carrying `newState` and `oldState`.
49
44
  *
50
45
  * @csspart content - The scrolling content region.
@@ -54,14 +49,18 @@ declare const HelixHeadlessDrawer_base: (new (...args: any[]) => import("@fusion
54
49
  export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
55
50
  protected readonly commands: CommandController;
56
51
  /**
57
- * Which edge the drawer comes from.
52
+ * Which close requests the browser answers on its own.
58
53
  *
59
- * Unset is `end`, which the styled tier reads as `:host(:not([placement]))`
60
- * beside `:host([placement="end"])` rather than as a value written here: a
61
- * default assigned to the property would reflect onto every host and put a
62
- * `placement="end"` into markup no consumer wrote.
54
+ * `<dialog closedby>`, forwarded, and safe to forward because every path it
55
+ * opens still comes back through this element: a close request fires `cancel`
56
+ * first, `handleCancel` prevents it, and `requestOpen` decides. So
57
+ * `closedby="any"` gains light dismiss without giving up the refusal, which is
58
+ * the property this component exists to keep.
59
+ *
60
+ * Absent by default, which is the platform's `auto` and this library's rule
61
+ * that a resting value is an attribute's absence.
63
62
  */
64
- placement?: 'start' | 'end' | 'top' | 'bottom';
63
+ closedBy?: 'any' | 'closerequest' | 'none';
65
64
  /**
66
65
  * Accessible name for the panel.
67
66
  */
@@ -81,18 +80,14 @@ export declare class HelixHeadlessDrawer extends HelixHeadlessDrawer_base {
81
80
  */
82
81
  modal: boolean;
83
82
  /**
84
- * Which close requests the browser answers on its own.
85
- *
86
- * `<dialog closedby>`, forwarded, and safe to forward because every path it
87
- * opens still comes back through this element: a close request fires `cancel`
88
- * first, `handleCancel` prevents it, and `requestOpen` decides. So
89
- * `closedby="any"` gains light dismiss without giving up the refusal, which is
90
- * the property this component exists to keep.
83
+ * Which edge the drawer comes from.
91
84
  *
92
- * Absent by default, which is the platform's `auto` and this library's rule
93
- * that a resting value is an attribute's absence.
85
+ * Unset is `end`, which the styled tier reads as `:host(:not([placement]))`
86
+ * beside `:host([placement="end"])` rather than as a value written here: a
87
+ * default assigned to the property would reflect onto every host and put a
88
+ * `placement="end"` into markup no consumer wrote.
94
89
  */
95
- closedBy?: 'any' | 'closerequest' | 'none';
90
+ placement?: 'start' | 'end' | 'top' | 'bottom';
96
91
  /**
97
92
  * What the dialog closed with, the way `<dialog>` reports it.
98
93
  *
@@ -11,8 +11,9 @@ import { property } from 'lit/decorators.js';
11
11
  * @summary A panel that slides in from an edge.
12
12
  *
13
13
  * @description
14
- * Takes `MixinControllerOpen`, so `open`, `defaultOpen`, and `OpenChange` behave exactly
15
- * as they do on an accordion item, and a consumer already knows the API.
14
+ * Takes `MixinControllerOpen`, so `open`, `defaultOpen` and the
15
+ * `helix-before-open` and `helix-before-close` requests behave exactly as they
16
+ * do on an accordion item, and a consumer already knows the API.
16
17
  *
17
18
  * Modal by default, which is three things together and not one: focus is
18
19
  * trapped inside, Escape and an outside press close it, and the page behind is
@@ -21,16 +22,10 @@ import { property } from 'lit/decorators.js';
21
22
  *
22
23
  * Content stays mounted when closed, so it is in the server's markup and can
23
24
  * animate. A closed `<dialog>` is already out of the tab order and out of the
24
- * accessibility tree, so nothing here writes `inert`.
25
- *
26
- * **This described a hand-written `inert` until 21 Aug 2026, and had done since
27
- * the panel became a `<dialog>`.** The rewrite took the `role`, the
28
- * `aria-modal`, the scrim and the `inert` with it, because the element brings
29
- * all four, and the comments at the two call sites say so. The class doc did
30
- * not, and `drawer-root.ssr.spec.ts` has asserted the panel carries no `inert`
31
- * the whole time: a spec three files away existing to contradict the prose is
32
- * the same shape as `Stat`'s `detail` slot, which is what `check:references`
33
- * was written after and is the half it cannot see.
25
+ * accessibility tree, so nothing here writes `inert`. The `role`, the
26
+ * `aria-modal` and the scrim come from the element too, and
27
+ * `drawer-root.ssr.spec.ts` asserts the panel carries no hand-written `inert`
28
+ * and no hand-written `role`.
34
29
  *
35
30
  * Opened declaratively with the platform's invoker attributes:
36
31
  *
@@ -50,7 +45,7 @@ import { property } from 'lit/decorators.js';
50
45
  *
51
46
  * @event {Event} close - Relayed, because the platform's own does not escape.
52
47
  * @event {HelixBeforeCloseEvent} helix-before-close - Fired before the panel closes, and cancelable.
53
- * @event {HelixBeforeOpenEvent} helix-before-open - Fired before the drawer opens or closes. Cancelable: refusing it takes the decision and nothing moves.
48
+ * @event {HelixBeforeOpenEvent} helix-before-open - Fired before the panel opens. Cancelable: refusing it takes the decision and nothing moves.
54
49
  * @event {Event} toggle - Says the state moved, carrying `newState` and `oldState`.
55
50
  *
56
51
  * @csspart content - The scrolling content region.
@@ -115,7 +110,7 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
115
110
 
116
111
  `cancel` is deliberately not relayed. `handleCancel` prevents it so that
117
112
  Escape is a request rather than an act, so the native one never completes:
118
- relaying it would announce a dismissal that was refused. See 296. */
113
+ relaying it would announce a dismissal that was refused. */
119
114
  this.relayNativeEvent(event);
120
115
  };
121
116
  /**
@@ -167,10 +162,8 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
167
162
  throws and `close()` on a shut one fires a second `close` event.
168
163
  *
169
164
  * `showModal` when modal and `show` when not, which is the whole of what
170
- * `modal` means now: both put the panel in the top layer, and only the
171
- * first brings a backdrop, a focus trap and `inert` behind it. This was a
172
- * hand-built `position: fixed` panel with a scrim div, a focus trap and a
173
- * dismisser, none of which the platform needed telling. */
165
+ * `modal` means: both put the panel in the top layer, and only the first
166
+ * brings a backdrop, a focus trap and `inert` behind it. */
174
167
  const panel = this.panel;
175
168
  if (!panel) {
176
169
  return;
@@ -205,8 +198,8 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
205
198
  }
206
199
  };
207
200
  __decorate([
208
- property({ reflect: true })
209
- ], HelixHeadlessDrawer.prototype, "placement", void 0);
201
+ property({ attribute: 'closedby', reflect: true })
202
+ ], HelixHeadlessDrawer.prototype, "closedBy", void 0);
210
203
  __decorate([
211
204
  property()
212
205
  ], HelixHeadlessDrawer.prototype, "label", void 0);
@@ -214,8 +207,8 @@ __decorate([
214
207
  property({ converter: onUnlessFalse })
215
208
  ], HelixHeadlessDrawer.prototype, "modal", void 0);
216
209
  __decorate([
217
- property({ attribute: 'closedby', reflect: true })
218
- ], HelixHeadlessDrawer.prototype, "closedBy", void 0);
210
+ property({ reflect: true })
211
+ ], HelixHeadlessDrawer.prototype, "placement", void 0);
219
212
  HelixHeadlessDrawer = __decorate([
220
213
  customElement('helix-headless-drawer')
221
214
  ], HelixHeadlessDrawer);