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

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
@@ -60,30 +60,27 @@ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerC
60
60
  this.aria = new AriaForwardController(this, {
61
61
  target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
62
62
  });
63
- /**
64
- * Value submitted when the box is checked.
65
- */
66
- this.value = 'on';
67
63
  /**
68
64
  * Whether the box shows as neither checked nor unchecked.
69
65
  *
70
66
  * Presentation only. It never submits, and the first change resolves it.
71
67
  */
72
68
  this.indeterminate = false;
69
+ /**
70
+ * Value submitted when the box is checked.
71
+ */
72
+ this.value = 'on';
73
73
  this.handleChange = (event) => {
74
74
  const input = event.target;
75
- // The input has already flipped itself. Where the change is refused, or the
76
- // element is controlled, it is put back to whatever the element resolves
77
- // to, so the box never shows a state the element does not hold.
75
+ // The input has already flipped itself. Where the change is refused it is
76
+ // put back to whatever the element resolves to, so the box never shows a
77
+ // state the element does not hold.
78
78
  const next = input.checked;
79
- /* The dash goes only where the change is taken.
80
- *
81
- * It was cleared first and unconditionally, so a consumer calling
82
- * `preventDefault()` on the change kept the checked state and lost the
83
- * third one: the box came back neither ticked nor dashed, which is a state
84
- * nobody asked for and the element did not hold. Refusing a change should
85
- * leave everything as it was, which is the argument the line below already
86
- * makes for `checked`. */
79
+ /* The dash goes only where the change is taken. Clearing it
80
+ * unconditionally leaves a refused change holding the checked state and
81
+ * losing the third one: a box neither ticked nor dashed, which is a state
82
+ * nobody asked for. Refusing leaves everything as it was, which is the
83
+ * argument the line below already makes for `checked`. */
87
84
  if (this.requestChecked(next)) {
88
85
  this.indeterminate = false;
89
86
  }
@@ -124,8 +121,8 @@ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerC
124
121
  /** Returns the box to the state its markup declared. */
125
122
  formResetCallback() {
126
123
  this.indeterminate = false;
127
- // `resetChecked` drops both halves now, the consumer's and the element's,
128
- // so there is nothing to clear before it.
124
+ // `resetChecked` drops both halves, the consumer's and the element's, so
125
+ // there is nothing to clear before it.
129
126
  this.resetChecked();
130
127
  }
131
128
  willUpdate(changed) {
@@ -142,37 +139,34 @@ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerC
142
139
  *
143
140
  * Called on `slotchange` and after every update, and the second is not
144
141
  * belt-and-braces: **`slotchange` does not fire when nothing is assigned.**
145
- * So a checkbox labeled only by its property, which is most of them, never
146
- * heard about its own label and rendered without one. Caught by the spec that
147
- * asks a labeled row to be wider than a bare one.
142
+ * Without it a checkbox labeled only by its property, which is most of them,
143
+ * never hears about its own label and renders without one.
148
144
  *
149
- * **`:state(has-label)` and not `data-has-label`, since 27 Aug 2026.** This
150
- * one could never have been in server output whatever it was called, the
151
- * answer coming from `assignedNodes` and a server having no tree to ask, so
152
- * it was an attribute that appeared on every labeled checkbox the instant it
153
- * upgraded and on none that any server sent. See `HelixElement.toggleState`.
145
+ * **`:state(has-label)` and not `data-has-label`.** The answer comes from
146
+ * `assignedNodes` and a server has no tree to ask, so an attribute would
147
+ * appear on every labeled checkbox the instant it upgraded and on none that
148
+ * any server sent. See `HelixElement.toggleState`.
154
149
  */
155
150
  syncLabelPresence() {
156
151
  const slot = this.renderRoot.querySelector('[part="label"] slot');
157
152
  const filled = (slot?.assignedNodes({ flatten: true }) ?? []).some((node) => node.textContent?.trim() !== '' || node.nodeType === Node.ELEMENT_NODE);
158
153
  this.toggleState('has-label', filled);
159
154
  /* And `hidden` on the region itself, because the state is on the host and
160
- this tier has no sheet to turn one into the other: a checkbox with no
161
- label kept an empty label box beside it. The styled rule stays, since it
162
- hides through a descendant selector this cannot replace. */
155
+ this tier has no sheet to turn one into the other, so a checkbox with no
156
+ label would keep an empty label box beside it. The styled rule stays,
157
+ since it hides through a descendant selector this cannot replace. */
163
158
  this.renderRoot.querySelector('[part="label"]')?.toggleAttribute('hidden', !filled);
164
159
  }
165
160
  render() {
166
161
  /* A real `<label>` around both, which is the whole of what makes the text a
167
- target. It was a `<span>` beside the input, so pressing the words did
168
- nothing: the styled tier's own description claimed the pair behaved like
169
- a native label wrapping a checkbox, and nothing was doing that work.
162
+ target. A `<span>` beside the input leaves pressing the words doing
163
+ nothing.
170
164
 
171
165
  Labeling is behavior, which is what earns an element here rather than a
172
166
  bare slot: the wrapper is not decoration and there is no other way to get
173
167
  it. The browser handles the forwarding, so there is no click handler to
174
168
  write and none to get wrong.
175
-
169
+
176
170
  The one line of description goes under that row, which is where a field
177
171
  puts it too. */
178
172
  return html `<label part="field">
@@ -195,12 +189,12 @@ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerC
195
189
  ${this.renderHint()}${this.renderFeedback()}`;
196
190
  }
197
191
  };
198
- __decorate([
199
- property()
200
- ], HelixHeadlessCheckbox.prototype, "value", void 0);
201
192
  __decorate([
202
193
  property({ reflect: true, type: Boolean })
203
194
  ], HelixHeadlessCheckbox.prototype, "indeterminate", void 0);
195
+ __decorate([
196
+ property()
197
+ ], HelixHeadlessCheckbox.prototype, "value", void 0);
204
198
  HelixHeadlessCheckbox = __decorate([
205
199
  customElement('helix-headless-checkbox')
206
200
  ], HelixHeadlessCheckbox);
@@ -19,11 +19,9 @@ declare const HelixHeadlessCheckboxGroup_base: (new (...args: any[]) => import("
19
19
  * `value` is the checked values, comma separated, in the order the boxes are
20
20
  * written. Setting it ticks exactly those and unticks the rest.
21
21
  *
22
- * **Its message is always given, never derived.** Every form-related member of
23
- * `ElementInternals` throws on an element that is not form-associated, and this
24
- * one is not, on purpose: the boxes submit themselves. So `feedback` is what
25
- * shows here, and the browser has nothing to say about a set it does not know
26
- * is a set.
22
+ * **Its message is always given, never derived.** The group is form-associated
23
+ * for validity alone and never calls `setFormValue`, so `feedback` is what shows
24
+ * here: the browser has nothing to say about a set it does not submit.
27
25
  *
28
26
  * @since 0.1.0
29
27
  * @status stable
@@ -63,18 +61,17 @@ export declare class HelixHeadlessCheckboxGroup extends HelixHeadlessCheckboxGro
63
61
  /**
64
62
  * Reads the boxes' own state into `value`, once, before anything is pushed.
65
63
  *
66
- * `sync` used to refuse to write anything while `value` was empty, and the
67
- * guard was there for this: a group written with no `value` and boxes that
68
- * declare their own `checked` would have had them all cleared on the first
69
- * update. What it also did was make `group.value = ''` do nothing at all, so
70
- * the obvious way to clear a group silently did not, and the last box could
71
- * not be unticked through the group either.
64
+ * Seeding, and never a guard in `sync` refusing to write while `value` is
65
+ * empty. The guard would answer the same case, a group written with no `value`
66
+ * whose boxes declare their own `checked` being cleared on the first update,
67
+ * and it also makes `group.value = ''` do nothing at all: the obvious way to
68
+ * clear a group would silently not, and the last box could not be unticked
69
+ * through the group either.
72
70
  *
73
- * Seeding is the honest version of the same intent. The markup decides the
74
- * starting set, exactly as before, and from then on `value` is what the boxes
75
- * follow, including when it is empty. The group's `value` is a derived read
76
- * of the boxes rather than state it owns, so reading it out of them at the
77
- * start is what it already means.
71
+ * The markup decides the starting set, and from then on `value` is what the
72
+ * boxes follow, including when it is empty. The group's `value` is a derived
73
+ * read of the boxes rather than state it owns, so reading it out of them at
74
+ * the start is what it already means.
78
75
  */
79
76
  private seed;
80
77
  /**
@@ -95,18 +92,16 @@ export declare class HelixHeadlessCheckboxGroup extends HelixHeadlessCheckboxGro
95
92
  /**
96
93
  * Stops a box's own announcement, for the reason the request above is stopped.
97
94
  *
98
- * **The split gave the requests two names and left the notifications sharing
99
- * one.** A box announces `input` and `change` from its own host now, which is
100
- * what makes `onChange` work on a checkbox, and both bubble up through this
101
- * group: measured, one click produced `change` from the group and `input` and
95
+ * A box announces `input` and `change` from its own host, which is what makes
96
+ * `onChange` work on a checkbox, and both bubble up through this group:
97
+ * measured, one click produced `change` from the group and `input` and
102
98
  * `change` from the box, all three at a consumer listening here, two of them
103
- * describing one box rather than the set. That is exactly the collision the
104
- * comment on `handleToggle` describes, arriving by the other route.
99
+ * describing one box rather than the set.
105
100
  *
106
- * `stopImmediatePropagation` and not `stopPropagation`, and for the same
107
- * reason it gives: the box's event and this group's own carry one name from
108
- * what a consumer sees as one element, so stopping propagation alone still
109
- * leaves every other listener on this host receiving both.
101
+ * `stopImmediatePropagation` and not `stopPropagation`: the box's event and
102
+ * this group's own carry one name from what a consumer sees as one element,
103
+ * so stopping propagation alone still leaves every other listener on this
104
+ * host receiving both.
110
105
  *
111
106
  * A listener on the box itself is unaffected, which is where per-box handling
112
107
  * belongs. Each box is form-associated and submits itself; what this stops is
@@ -118,27 +113,19 @@ export declare class HelixHeadlessCheckboxGroup extends HelixHeadlessCheckboxGro
118
113
  protected willUpdate(changed: PropertyValues): void;
119
114
  protected firstUpdated(changed: PropertyValues): void;
120
115
  /**
121
- * Refuses an empty set where one was required, which nothing did.
116
+ * Refuses an empty set where one was required.
122
117
  *
123
- * `required` arrives with `MixinField`, reflects, and paints the asterisk
124
- * through the composed field sheet, and enforced nothing at all: no validity,
125
- * no message, and nothing cascading to the boxes. A group marked required
126
- * submitted empty.
118
+ * **The group is form-associated, and submits nothing.** Nothing here calls
119
+ * `setFormValue`, so the set that reaches the server is exactly the boxes,
120
+ * each of which submits itself. What form association buys is the other half
121
+ * of participation, validity, and there is no other mechanism for it:
122
+ * `setValidity` throws `NotSupportedError` on an element the platform does not
123
+ * know is a control. happy-dom's shim does not throw, so a spec passes against
124
+ * code that fails on every update in Chromium.
127
125
  *
128
- * **The group is form-associated, and submits nothing.** It was not, on the
129
- * reasoning that its boxes are the controls and each submits itself, which is
130
- * still true: nothing here calls `setFormValue`, so the set that reaches the
131
- * server is exactly the boxes it always was. What form association buys is the
132
- * other half of participation, validity, and there is no other mechanism for
133
- * it: `setValidity` throws `NotSupportedError` on an element the platform does
134
- * not know is a control.
135
- *
136
- * So the fix that was written for "a group marked required submitted empty"
137
- * threw on every update in a real browser, and happy-dom's shim does not
138
- * throw, so the specs passed and the behavior never worked. Eleven of them
139
- * failed the moment they were run in Chromium. It is also what makes the rest
140
- * work: the form now refuses to submit, which fires `invalid`, which is what
141
- * marks the field touched and puts the message on screen.
126
+ * It is also what makes the rest work: the form refuses to submit, which fires
127
+ * `invalid`, which is what marks the field touched and puts the message on
128
+ * screen.
142
129
  *
143
130
  * Anchored on the list, because the browser needs somewhere to point the
144
131
  * bubble.
@@ -25,11 +25,9 @@ import { HelixHeadlessCheckbox } from '../../checkbox/root/checkbox-root.js';
25
25
  * `value` is the checked values, comma separated, in the order the boxes are
26
26
  * written. Setting it ticks exactly those and unticks the rest.
27
27
  *
28
- * **Its message is always given, never derived.** Every form-related member of
29
- * `ElementInternals` throws on an element that is not form-associated, and this
30
- * one is not, on purpose: the boxes submit themselves. So `feedback` is what
31
- * shows here, and the browser has nothing to say about a set it does not know
32
- * is a set.
28
+ * **Its message is always given, never derived.** The group is form-associated
29
+ * for validity alone and never calls `setFormValue`, so `feedback` is what shows
30
+ * here: the browser has nothing to say about a set it does not submit.
33
31
  *
34
32
  * @since 0.1.0
35
33
  * @status stable
@@ -52,20 +50,18 @@ import { HelixHeadlessCheckbox } from '../../checkbox/root/checkbox-root.js';
52
50
  */
53
51
  let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinField(HelixFormElement) {
54
52
  constructor() {
55
- /* `name` is inherited. It arrives with `HelixFormElement` reflected and with
56
- the converter that makes an empty one absent rather than `name=""`, which
57
- the copy declared here had neither of. What it means differs slightly and
58
- the property does not: the group submits nothing under it, and hands it to
59
- every box that has none. */
53
+ /* `name` is inherited from `HelixFormElement`, reflected and with the
54
+ converter that makes an empty one absent rather than `name=""`. What it
55
+ means differs slightly and the property does not: the group submits nothing
56
+ under it, and hands it to every box that has none. */
60
57
  super(...arguments);
61
58
  /**
62
59
  * The checked values, comma separated.
63
60
  */
64
61
  this.value = '';
65
- /* Stated once, and the group never thinks about it again. See the
66
- controller: the cascade was four hand calls from four different
67
- methods, so which paths reached it differed by component and a fifth
68
- group would have got none at all. */
62
+ /* Stated once, and the group never thinks about it again. The controller is
63
+ what stops the cascade being hand-called from whichever methods a component
64
+ happens to have. */
69
65
  this.cascade = new DisabledCascadeController(this, {
70
66
  items: () => this.boxes,
71
67
  });
@@ -89,30 +85,22 @@ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinF
89
85
  if (!changed) {
90
86
  return;
91
87
  }
92
- /* Still stopped, though the names no longer collide. A box's `helix-toggle`
93
- bubbles, and the group is the single voice for the set: a consumer
94
- listening here wants the whole answer, not one box's half of it. Before
95
- the split this had to be `stopImmediatePropagation` rather than
96
- `stopPropagation`, because the box's event and the group's own carried
97
- the same name from the same host and the other listeners on it would have
98
- received both. */
88
+ /* A box's `helix-before-toggle` bubbles, and the group is the single voice
89
+ for the set: a consumer listening here wants the whole answer, not one
90
+ box's half of it. */
99
91
  event.stopImmediatePropagation();
100
92
  const wanted = event.detail.checked;
101
- /* Announced before it is written, which is the way round it was not: the
102
- group set its value and then dispatched, so `preventDefault()` refused a
103
- set that had already changed.
93
+ /* Announced before it is written, never after: dispatching once the group's
94
+ value has moved leaves `preventDefault()` refusing a set that has already
95
+ changed.
104
96
 
105
- Hand-rolled rather than through `MixinControllerValue`, and that is the
106
- decision rather than an omission. The group is deliberately not
107
- form-associated: its boxes are the form controls and each submits itself,
108
- so the mixin, which is constrained to `HelixFormElement`, does not apply
109
- to it. Its `value` is a derived read of the boxes rather than state it
110
- owns, which is also why it is not controllable and why that is written
111
- down rather than fixed.
97
+ Hand-rolled rather than through `MixinControllerValue`, and that is a
98
+ decision rather than an omission. The group's `value` is a derived read of
99
+ the boxes rather than state it owns, so there is nothing for the mixin to
100
+ control.
112
101
 
113
102
  The boxes have already moved either way. Each answered the reader before
114
- this ran, so refusing here stops the group's value from following, and
115
- the honest limit of that is recorded with the decision. */
103
+ this ran, so refusing here stops only the group's value from following. */
116
104
  const next = this.boxes
117
105
  .filter((box) => (box === changed ? wanted : box.checked))
118
106
  .map((box) => box.value)
@@ -126,27 +114,23 @@ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinF
126
114
 
127
115
  `input` beside it, because this is a discrete control and that is the
128
116
  pair a native `<select>` sends and the pair every other discrete control
129
- here sends through `MixinControllerValue`. The group had only `change`,
130
- so a consumer binding `onInput` on the set heard the boxes and never the
131
- group. */
117
+ here sends through `MixinControllerValue`. */
132
118
  this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
133
119
  this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
134
120
  };
135
121
  /**
136
122
  * Stops a box's own announcement, for the reason the request above is stopped.
137
123
  *
138
- * **The split gave the requests two names and left the notifications sharing
139
- * one.** A box announces `input` and `change` from its own host now, which is
140
- * what makes `onChange` work on a checkbox, and both bubble up through this
141
- * group: measured, one click produced `change` from the group and `input` and
124
+ * A box announces `input` and `change` from its own host, which is what makes
125
+ * `onChange` work on a checkbox, and both bubble up through this group:
126
+ * measured, one click produced `change` from the group and `input` and
142
127
  * `change` from the box, all three at a consumer listening here, two of them
143
- * describing one box rather than the set. That is exactly the collision the
144
- * comment on `handleToggle` describes, arriving by the other route.
128
+ * describing one box rather than the set.
145
129
  *
146
- * `stopImmediatePropagation` and not `stopPropagation`, and for the same
147
- * reason it gives: the box's event and this group's own carry one name from
148
- * what a consumer sees as one element, so stopping propagation alone still
149
- * leaves every other listener on this host receiving both.
130
+ * `stopImmediatePropagation` and not `stopPropagation`: the box's event and
131
+ * this group's own carry one name from what a consumer sees as one element,
132
+ * so stopping propagation alone still leaves every other listener on this
133
+ * host receiving both.
150
134
  *
151
135
  * A listener on the box itself is unaffected, which is where per-box handling
152
136
  * belongs. Each box is form-associated and submits itself; what this stops is
@@ -184,18 +168,17 @@ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinF
184
168
  /**
185
169
  * Reads the boxes' own state into `value`, once, before anything is pushed.
186
170
  *
187
- * `sync` used to refuse to write anything while `value` was empty, and the
188
- * guard was there for this: a group written with no `value` and boxes that
189
- * declare their own `checked` would have had them all cleared on the first
190
- * update. What it also did was make `group.value = ''` do nothing at all, so
191
- * the obvious way to clear a group silently did not, and the last box could
192
- * not be unticked through the group either.
171
+ * Seeding, and never a guard in `sync` refusing to write while `value` is
172
+ * empty. The guard would answer the same case, a group written with no `value`
173
+ * whose boxes declare their own `checked` being cleared on the first update,
174
+ * and it also makes `group.value = ''` do nothing at all: the obvious way to
175
+ * clear a group would silently not, and the last box could not be unticked
176
+ * through the group either.
193
177
  *
194
- * Seeding is the honest version of the same intent. The markup decides the
195
- * starting set, exactly as before, and from then on `value` is what the boxes
196
- * follow, including when it is empty. The group's `value` is a derived read
197
- * of the boxes rather than state it owns, so reading it out of them at the
198
- * start is what it already means.
178
+ * The markup decides the starting set, and from then on `value` is what the
179
+ * boxes follow, including when it is empty. The group's `value` is a derived
180
+ * read of the boxes rather than state it owns, so reading it out of them at
181
+ * the start is what it already means.
199
182
  */
200
183
  seed() {
201
184
  const checked = this.boxes.filter((box) => box.checked).map((box) => box.value);
@@ -233,27 +216,19 @@ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinF
233
216
  }
234
217
  }
235
218
  /**
236
- * Refuses an empty set where one was required, which nothing did.
219
+ * Refuses an empty set where one was required.
237
220
  *
238
- * `required` arrives with `MixinField`, reflects, and paints the asterisk
239
- * through the composed field sheet, and enforced nothing at all: no validity,
240
- * no message, and nothing cascading to the boxes. A group marked required
241
- * submitted empty.
221
+ * **The group is form-associated, and submits nothing.** Nothing here calls
222
+ * `setFormValue`, so the set that reaches the server is exactly the boxes,
223
+ * each of which submits itself. What form association buys is the other half
224
+ * of participation, validity, and there is no other mechanism for it:
225
+ * `setValidity` throws `NotSupportedError` on an element the platform does not
226
+ * know is a control. happy-dom's shim does not throw, so a spec passes against
227
+ * code that fails on every update in Chromium.
242
228
  *
243
- * **The group is form-associated, and submits nothing.** It was not, on the
244
- * reasoning that its boxes are the controls and each submits itself, which is
245
- * still true: nothing here calls `setFormValue`, so the set that reaches the
246
- * server is exactly the boxes it always was. What form association buys is the
247
- * other half of participation, validity, and there is no other mechanism for
248
- * it: `setValidity` throws `NotSupportedError` on an element the platform does
249
- * not know is a control.
250
- *
251
- * So the fix that was written for "a group marked required submitted empty"
252
- * threw on every update in a real browser, and happy-dom's shim does not
253
- * throw, so the specs passed and the behavior never worked. Eleven of them
254
- * failed the moment they were run in Chromium. It is also what makes the rest
255
- * work: the form now refuses to submit, which fires `invalid`, which is what
256
- * marks the field touched and puts the message on screen.
229
+ * It is also what makes the rest work: the form refuses to submit, which fires
230
+ * `invalid`, which is what marks the field touched and puts the message on
231
+ * screen.
257
232
  *
258
233
  * Anchored on the list, because the browser needs somewhere to point the
259
234
  * bubble.
@@ -275,9 +250,8 @@ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinF
275
250
  return html `${this.renderGroupLabel()}
276
251
  <div part="items">
277
252
  ${
278
- /* A box arriving after first render got neither the shared name nor
279
- the value's checked state, because nothing was listening: both
280
- sibling groups wire this and this one did not. */
253
+ /* A box arriving after first render has neither the shared name nor
254
+ the value's checked state until something pushes them onto it. */
281
255
  ''}
282
256
  <slot @slotchange=${() => this.requestUpdate()}></slot>
283
257
  </div>
@@ -59,10 +59,9 @@ export declare class HelixHeadlessCodeBlock extends HelixElement {
59
59
  *
60
60
  * **Reflected, because the gutter is a stylesheet rule.** `code-block.css`
61
61
  * reserves the copy button's width with `:host(:not([no-copy]))`, so the
62
- * attribute is what decides whether the block pays for a control. Set from
63
- * script the button went away, `render` reading the property, and the 40px it
64
- * stood in stayed reserved: the exact waste that rule was written to stop,
65
- * arrived at from the other side.
62
+ * attribute is what decides whether the block pays for a control. Unreflected,
63
+ * setting it from script takes the button away (`render` reads the property)
64
+ * and leaves the 40px it stood in reserved.
66
65
  *
67
66
  * A false boolean reflects as the attribute's absence, so this costs no
68
67
  * `no-copy=""` on hosts that never asked for one, and the rule about a
@@ -69,10 +69,9 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
69
69
  *
70
70
  * **Reflected, because the gutter is a stylesheet rule.** `code-block.css`
71
71
  * reserves the copy button's width with `:host(:not([no-copy]))`, so the
72
- * attribute is what decides whether the block pays for a control. Set from
73
- * script the button went away, `render` reading the property, and the 40px it
74
- * stood in stayed reserved: the exact waste that rule was written to stop,
75
- * arrived at from the other side.
72
+ * attribute is what decides whether the block pays for a control. Unreflected,
73
+ * setting it from script takes the button away (`render` reads the property)
74
+ * and leaves the 40px it stood in reserved.
76
75
  *
77
76
  * A false boolean reflects as the attribute's absence, so this costs no
78
77
  * `no-copy=""` on hosts that never asked for one, and the rule about a
@@ -109,14 +108,11 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
109
108
  this.requestUpdate();
110
109
  }
111
110
  render() {
112
- /* The copy button sits beside the code, not in a bar above it.
113
- *
114
- * It was in the header, which meant a block with nothing to call itself
115
- * still drew a full-width bar to hold one button: an empty strip above
116
- * every snippet, which is what a `Usage` section of one-line imports looked
117
- * like. Beside the code it needs no bar at all, so a block with no `label`
118
- * is just the code and a way to take it, and the header exists only when
119
- * there is a name to put in it. One less appearance to choose between. */
111
+ /* The copy button sits beside the code, not in a bar above it. In the
112
+ header, a block with nothing to call itself still draws a full-width bar
113
+ to hold one button, so a `Usage` section of one-line imports is a run of
114
+ empty strips. Beside the code, the header exists only when there is a
115
+ name to put in it. */
120
116
  return html `${this.label ? html `<div part="header"><span part="label">${this.label}</span></div>` : nothing}
121
117
  <div part="frame">
122
118
  <pre part="block"><code part="code"><slot @slotchange=${() => this.requestUpdate()}></slot></code></pre>
@@ -27,10 +27,10 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
27
27
  * the value itself, for the reason Date Input gives about its dates: half-typed
28
28
  * input does not survive a round trip through a formatter.
29
29
  *
30
- * The properties below are written by this component and read by whoever draws
31
- * it. A consumer sets none of them: they carry a number this element computed
32
- * and CSS cannot, which is what lets a stylesheet on this tier draw the thing
33
- * without measuring anything itself.
30
+ * The custom property below is written by this component and never set by a
31
+ * consumer: it carries a value this element resolved and CSS cannot, which is
32
+ * what lets a stylesheet on this tier paint the swatch without parsing anything
33
+ * itself.
34
34
  *
35
35
  * @since 0.1.0
36
36
  * @status experimental
@@ -92,48 +92,29 @@ declare const HelixHeadlessColorInput_base: (new (...args: any[]) => import("@fu
92
92
  */
93
93
  export declare class HelixHeadlessColorInput extends HelixHeadlessColorInput_base {
94
94
  protected readonly aria: AriaForwardController;
95
+ /**
96
+ * Whether the color carries an alpha channel.
97
+ */
98
+ alpha: boolean;
95
99
  /**
96
100
  * What the browser may autofill in the text field, as a platform token.
97
101
  *
98
102
  * **Defaults to `off`, which is not the platform's default and is the
99
- * point.** The field filters a list rather than collecting a value, so a
100
- * browser offering to fill it with a saved address is competing for the same
101
- * keystrokes as the listbox. A consumer who wants autofill can still ask.
103
+ * point.** The field holds a color, so a browser offering to fill it with a
104
+ * saved address is competing for the same keystrokes as the picker. A
105
+ * consumer who wants autofill can still ask.
102
106
  */
103
107
  autocomplete: string;
104
- /**
105
- * Whether the field is a text box with a swatch on it, or only the swatch.
106
- *
107
- * `swatch` is the native control's shape: a block of color that opens a
108
- * picker, with no text beside it. It is what a toolbar wants, and a form that
109
- * asks for a color among twenty other questions, where a hex in a box is
110
- * eleven characters of noise next to the thing itself.
111
- *
112
- * It also settles where the value is stated. The default field *is* the input,
113
- * so the panel is told `no-value` and would otherwise show a second one. A
114
- * swatch states nothing, so the panel keeps its own row and the value is
115
- * readable and typeable exactly once, in whichever of the two is present.
116
- *
117
- * The trade is real and is the reason this is not the default: a swatch cannot
118
- * be read or pasted into without opening the panel, which is worse for a form
119
- * where the color is the answer rather than a setting.
120
- */
121
- variant?: 'swatch';
122
- /**
123
- * Whether the color carries an alpha channel.
124
- */
125
- alpha: boolean;
126
108
  /**
127
109
  * The syntax the value is written in: `hex`, `rgb` or `hsl`.
128
110
  *
129
- * **Undefaulted, because it reflects.** The two together are what stamp an
130
- * attribute onto every host anybody renders, including the ones nobody
131
- * configured: the server wrote `format="hex"` on every color input on the
132
- * page, and React, holding no such prop, reported a hydration mismatch for
133
- * each one. That is the fault `Tree.chevronPlacement` had and the reason the
134
- * area rules say a reflected property takes no default. Hex is still what an
135
- * unset one writes; the difference is that the resting arrangement is the
136
- * attribute's absence rather than a value spelled out.
111
+ * **Undefaulted, because it reflects.** The two together stamp an attribute
112
+ * onto every host anybody renders, including the ones nobody configured: the
113
+ * server writes `format="hex"` on every color input on the page, and React,
114
+ * holding no such prop, reports a hydration mismatch for each one.
115
+ * `helix component`'s `reflected-defaults` holds it. Hex is still what an unset one
116
+ * writes; the resting arrangement is the attribute's absence rather than a
117
+ * value spelled out.
137
118
  */
138
119
  format?: ColorFormat;
139
120
  /**
@@ -152,6 +133,24 @@ export declare class HelixHeadlessColorInput extends HelixHeadlessColorInput_bas
152
133
  * Accessible name for the control that opens the panel.
153
134
  */
154
135
  triggerLabel: string;
136
+ /**
137
+ * Whether the field is a text box with a swatch on it, or only the swatch.
138
+ *
139
+ * `swatch` is the native control's shape: a block of color that opens a
140
+ * picker, with no text beside it. It is what a toolbar wants, and a form that
141
+ * asks for a color among twenty other questions, where a hex in a box is
142
+ * eleven characters of noise next to the thing itself.
143
+ *
144
+ * It also settles where the value is stated. The default field *is* the input,
145
+ * so the panel is told `no-value` and would otherwise show a second one. A
146
+ * swatch states nothing, so the panel keeps its own row and the value is
147
+ * readable and typeable exactly once, in whichever of the two is present.
148
+ *
149
+ * The trade is real and is the reason this is not the default: a swatch cannot
150
+ * be read or pasted into without opening the panel, which is worse for a form
151
+ * where the color is the answer rather than a setting.
152
+ */
153
+ variant?: 'swatch';
155
154
  /** The overlay, placed against the field for the reason Date Input gives. */
156
155
  protected readonly panel: PopoverController;
157
156
  /**