@fusion.dev/helix-core 0.145.0 → 0.147.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/custom-elements.json +6585 -1920
  2. package/dist/controllers/aria-forward-controller/aria-forward-controller.d.ts +3 -2
  3. package/dist/controllers/aria-forward-controller/aria-forward-controller.js +8 -17
  4. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +71 -3
  5. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +50 -9
  6. package/dist/controllers/chart-pointer-controller/reading-step.d.ts +7 -1
  7. package/dist/controllers/chart-pointer-controller/reading-step.js +5 -0
  8. package/dist/controllers/copy-controller/copy-controller.d.ts +4 -1
  9. package/dist/controllers/copy-controller/copy-controller.js +2 -1
  10. package/dist/controllers/countdown-controller/countdown-controller.d.ts +4 -1
  11. package/dist/controllers/countdown-controller/countdown-controller.js +3 -1
  12. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +14 -55
  13. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.js +7 -39
  14. package/dist/controllers/relative-clock-controller/relative-clock-controller.d.ts +44 -0
  15. package/dist/controllers/relative-clock-controller/relative-clock-controller.js +31 -0
  16. package/dist/controllers/source-controller/source-controller.d.ts +10 -3
  17. package/dist/controllers/source-controller/source-controller.js +9 -4
  18. package/dist/controllers/swipe-controller/swipe-controller.d.ts +10 -1
  19. package/dist/controllers/swipe-controller/swipe-controller.js +1 -1
  20. package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +48 -1
  21. package/dist/controllers/virtualize-controller/virtualize-controller.js +52 -7
  22. package/dist/events/action.d.ts +12 -0
  23. package/dist/events/action.js +6 -0
  24. package/dist/events/activate.d.ts +22 -0
  25. package/dist/events/activate.js +11 -0
  26. package/dist/events/aura-fallback.d.ts +12 -0
  27. package/dist/events/aura-fallback.js +11 -0
  28. package/dist/events/band.d.ts +13 -0
  29. package/dist/events/band.js +11 -0
  30. package/dist/events/before-activate.d.ts +24 -0
  31. package/dist/events/before-activate.js +11 -0
  32. package/dist/events/before-change.d.ts +26 -0
  33. package/dist/events/before-change.js +11 -0
  34. package/dist/events/before-close.d.ts +6 -0
  35. package/dist/events/before-close.js +11 -0
  36. package/dist/events/before-collapse.d.ts +6 -0
  37. package/dist/events/before-collapse.js +11 -0
  38. package/dist/events/before-edit.d.ts +6 -0
  39. package/dist/events/before-edit.js +11 -0
  40. package/dist/events/before-move.d.ts +17 -0
  41. package/dist/events/before-move.js +11 -0
  42. package/dist/events/before-open.d.ts +17 -0
  43. package/dist/events/before-open.js +11 -0
  44. package/dist/events/before-panel-resize.d.ts +13 -0
  45. package/dist/events/before-panel-resize.js +11 -0
  46. package/dist/events/before-pin.d.ts +6 -0
  47. package/dist/events/before-pin.js +11 -0
  48. package/dist/events/before-reconnect.d.ts +14 -0
  49. package/dist/events/before-reconnect.js +11 -0
  50. package/dist/events/before-relabel.d.ts +15 -0
  51. package/dist/events/before-relabel.js +11 -0
  52. package/dist/events/before-resize.d.ts +6 -0
  53. package/dist/events/before-resize.js +11 -0
  54. package/dist/events/before-split.d.ts +12 -0
  55. package/dist/events/before-split.js +11 -0
  56. package/dist/events/before-toggle.d.ts +23 -0
  57. package/dist/events/before-toggle.js +11 -0
  58. package/dist/events/canvas-edit.d.ts +16 -0
  59. package/dist/events/canvas-edit.js +11 -0
  60. package/dist/events/canvas-pan.d.ts +13 -0
  61. package/dist/events/canvas-pan.js +11 -0
  62. package/dist/events/canvas-view.d.ts +14 -0
  63. package/dist/events/canvas-view.js +11 -0
  64. package/dist/events/canvas-zoom.d.ts +6 -0
  65. package/dist/events/canvas-zoom.js +11 -0
  66. package/dist/events/caret.d.ts +17 -0
  67. package/dist/events/caret.js +11 -0
  68. package/dist/events/clear.d.ts +11 -0
  69. package/dist/events/clear.js +6 -0
  70. package/dist/events/collapse.d.ts +12 -0
  71. package/dist/events/collapse.js +11 -0
  72. package/dist/events/complete.d.ts +26 -0
  73. package/dist/events/complete.js +11 -0
  74. package/dist/events/connect.d.ts +14 -0
  75. package/dist/events/connect.js +11 -0
  76. package/dist/events/console.d.ts +13 -0
  77. package/dist/events/console.js +11 -0
  78. package/dist/events/copy-error.d.ts +9 -0
  79. package/dist/events/copy-error.js +6 -0
  80. package/dist/events/copy.d.ts +12 -0
  81. package/dist/events/copy.js +10 -0
  82. package/dist/events/create.d.ts +18 -0
  83. package/dist/events/create.js +11 -0
  84. package/dist/events/details.d.ts +459 -0
  85. package/dist/events/details.js +1 -0
  86. package/dist/events/dismiss.d.ts +16 -0
  87. package/dist/events/dismiss.js +11 -0
  88. package/dist/events/edit.d.ts +12 -0
  89. package/dist/events/edit.js +11 -0
  90. package/dist/events/end.d.ts +9 -0
  91. package/dist/events/end.js +6 -0
  92. package/dist/events/events.d.ts +113 -1478
  93. package/dist/events/events.js +93 -863
  94. package/dist/events/expand.d.ts +10 -0
  95. package/dist/events/expand.js +11 -0
  96. package/dist/events/facet.d.ts +17 -0
  97. package/dist/events/facet.js +11 -0
  98. package/dist/events/filter.d.ts +12 -0
  99. package/dist/events/filter.js +11 -0
  100. package/dist/events/filtered.d.ts +12 -0
  101. package/dist/events/filtered.js +11 -0
  102. package/dist/events/graph-filter.d.ts +10 -0
  103. package/dist/events/graph-filter.js +11 -0
  104. package/dist/events/graph-layout.d.ts +10 -0
  105. package/dist/events/graph-layout.js +11 -0
  106. package/dist/events/graph-pan.d.ts +9 -0
  107. package/dist/events/graph-pan.js +11 -0
  108. package/dist/events/graph-part-change.d.ts +10 -0
  109. package/dist/events/graph-part-change.js +11 -0
  110. package/dist/events/graph-ready.d.ts +8 -0
  111. package/dist/events/graph-ready.js +6 -0
  112. package/dist/events/graph-signal.d.ts +11 -0
  113. package/dist/events/graph-signal.js +11 -0
  114. package/dist/events/graph-zoom.d.ts +6 -0
  115. package/dist/events/graph-zoom.js +11 -0
  116. package/dist/events/history.d.ts +16 -0
  117. package/dist/events/history.js +11 -0
  118. package/dist/events/load-more.d.ts +12 -0
  119. package/dist/events/load-more.js +6 -0
  120. package/dist/events/load.d.ts +12 -0
  121. package/dist/events/load.js +6 -0
  122. package/dist/events/map-cluster.d.ts +15 -0
  123. package/dist/events/map-cluster.js +11 -0
  124. package/dist/events/map-pan.d.ts +18 -0
  125. package/dist/events/map-pan.js +11 -0
  126. package/dist/events/map-part-change.d.ts +16 -0
  127. package/dist/events/map-part-change.js +11 -0
  128. package/dist/events/map-ready.d.ts +15 -0
  129. package/dist/events/map-ready.js +6 -0
  130. package/dist/events/map-rotate.d.ts +9 -0
  131. package/dist/events/map-rotate.js +11 -0
  132. package/dist/events/map-tilt.d.ts +9 -0
  133. package/dist/events/map-tilt.js +11 -0
  134. package/dist/events/map-zoom.d.ts +13 -0
  135. package/dist/events/map-zoom.js +11 -0
  136. package/dist/events/move.d.ts +11 -0
  137. package/dist/events/move.js +11 -0
  138. package/dist/events/names.d.ts +18 -0
  139. package/dist/events/names.js +13 -0
  140. package/dist/events/navigate.d.ts +13 -0
  141. package/dist/events/navigate.js +11 -0
  142. package/dist/events/next.d.ts +23 -0
  143. package/dist/events/next.js +11 -0
  144. package/dist/events/panel-resize.d.ts +12 -0
  145. package/dist/events/panel-resize.js +11 -0
  146. package/dist/events/pin.d.ts +12 -0
  147. package/dist/events/pin.js +11 -0
  148. package/dist/events/press.d.ts +19 -0
  149. package/dist/events/press.js +11 -0
  150. package/dist/events/preview.d.ts +14 -0
  151. package/dist/events/preview.js +11 -0
  152. package/dist/events/previous.d.ts +6 -0
  153. package/dist/events/previous.js +11 -0
  154. package/dist/events/range-change.d.ts +10 -0
  155. package/dist/events/range-change.js +11 -0
  156. package/dist/events/read.d.ts +19 -0
  157. package/dist/events/read.js +11 -0
  158. package/dist/events/reconnect.d.ts +6 -0
  159. package/dist/events/reconnect.js +11 -0
  160. package/dist/events/reject.d.ts +13 -0
  161. package/dist/events/reject.js +11 -0
  162. package/dist/events/relabel.d.ts +6 -0
  163. package/dist/events/relabel.js +11 -0
  164. package/dist/events/remove.d.ts +12 -0
  165. package/dist/events/remove.js +11 -0
  166. package/dist/events/reorder.d.ts +18 -0
  167. package/dist/events/reorder.js +11 -0
  168. package/dist/events/reordered.d.ts +12 -0
  169. package/dist/events/reordered.js +11 -0
  170. package/dist/events/resize.d.ts +19 -0
  171. package/dist/events/resize.js +11 -0
  172. package/dist/events/resized.d.ts +16 -0
  173. package/dist/events/resized.js +11 -0
  174. package/dist/events/sample-end.d.ts +5 -0
  175. package/dist/events/sample-end.js +6 -0
  176. package/dist/events/sample-start.d.ts +18 -0
  177. package/dist/events/sample-start.js +6 -0
  178. package/dist/events/scrolled.d.ts +32 -0
  179. package/dist/events/scrolled.js +11 -0
  180. package/dist/events/select.d.ts +12 -0
  181. package/dist/events/select.js +11 -0
  182. package/dist/events/selected.d.ts +12 -0
  183. package/dist/events/selected.js +11 -0
  184. package/dist/events/send.d.ts +18 -0
  185. package/dist/events/send.js +11 -0
  186. package/dist/events/shortcut.d.ts +13 -0
  187. package/dist/events/shortcut.js +11 -0
  188. package/dist/events/sort.d.ts +17 -0
  189. package/dist/events/sort.js +11 -0
  190. package/dist/events/sorted.d.ts +15 -0
  191. package/dist/events/sorted.js +11 -0
  192. package/dist/events/split.d.ts +12 -0
  193. package/dist/events/split.js +11 -0
  194. package/dist/events/toggle.d.ts +15 -0
  195. package/dist/events/toggle.js +11 -0
  196. package/dist/events/tour-ask.d.ts +16 -0
  197. package/dist/events/tour-ask.js +11 -0
  198. package/dist/events/tour-status.d.ts +14 -0
  199. package/dist/events/tour-status.js +11 -0
  200. package/dist/events/typing.d.ts +10 -0
  201. package/dist/events/typing.js +11 -0
  202. package/dist/helix-element/helix-element.js +9 -43
  203. package/dist/helix-element/react-bridge.d.ts +23 -0
  204. package/dist/helix-element/react-bridge.js +2 -2
  205. package/dist/helix-form-element/helix-form-element.d.ts +5 -20
  206. package/dist/helix-form-element/helix-form-element.js +4 -56
  207. package/dist/index.d.ts +30 -9
  208. package/dist/index.js +30 -9
  209. package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +24 -2
  210. package/dist/mixins/mixin-chart-source/mixin-chart-source.js +23 -1
  211. package/dist/mixins/mixin-controller-active/mixin-controller-active.js +4 -3
  212. package/dist/mixins/mixin-controller-checked/mixin-controller-checked.d.ts +5 -2
  213. package/dist/mixins/mixin-controller-checked/mixin-controller-checked.js +2 -1
  214. package/dist/mixins/mixin-controller-value/mixin-controller-value.d.ts +4 -2
  215. package/dist/mixins/mixin-controller-value/mixin-controller-value.js +7 -2
  216. package/dist/mixins/mixin-dismissible/mixin-dismissible.js +44 -7
  217. package/dist/mixins/mixin-field/mixin-field.js +2 -2
  218. package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.d.ts +42 -0
  219. package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.js +46 -0
  220. package/dist/mixins/mixin-picker-field/mixin-picker-field.d.ts +7 -4
  221. package/dist/mixins/mixin-picker-field/mixin-picker-field.js +6 -4
  222. package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +19 -9
  223. package/dist/utils/audit-name/audit-name-off.d.ts +10 -0
  224. package/dist/utils/audit-name/audit-name-off.js +1 -0
  225. package/dist/utils/audit-name/audit-name.d.ts +26 -8
  226. package/dist/utils/audit-name/audit-name.js +22 -30
  227. package/dist/utils/audit-source/audit-source-off.d.ts +10 -0
  228. package/dist/utils/audit-source/audit-source-off.js +1 -0
  229. package/dist/utils/audit-source/audit-source.d.ts +19 -0
  230. package/dist/utils/audit-source/audit-source.js +27 -0
  231. package/dist/utils/calendar/calendar.js +7 -7
  232. package/dist/utils/call-listener/call-listener.d.ts +16 -0
  233. package/dist/utils/call-listener/call-listener.js +17 -0
  234. package/dist/utils/chord/chord.d.ts +14 -0
  235. package/dist/utils/chord/chord.js +1 -0
  236. package/dist/utils/clamp/clamp.d.ts +7 -0
  237. package/dist/utils/clamp/clamp.js +1 -0
  238. package/dist/utils/css-color/css-color.js +1 -1
  239. package/dist/utils/draw-tooltip/draw-tooltip.d.ts +1 -1
  240. package/dist/utils/draw-tooltip/draw-tooltip.js +3 -1
  241. package/dist/utils/draw-tooltip/spoken-reading.d.ts +6 -2
  242. package/dist/utils/draw-tooltip/spoken-reading.js +5 -4
  243. package/dist/utils/elapsed-time/elapsed-time.d.ts +1 -1
  244. package/dist/utils/elapsed-time/elapsed-time.js +2 -5
  245. package/dist/utils/heading-level/heading-level.d.ts +8 -0
  246. package/dist/utils/heading-level/heading-level.js +4 -0
  247. package/dist/utils/host-words/host-words.d.ts +16 -0
  248. package/dist/utils/host-words/host-words.js +13 -0
  249. package/dist/utils/implicit-submit/implicit-submit.d.ts +25 -0
  250. package/dist/utils/implicit-submit/implicit-submit.js +52 -0
  251. package/dist/utils/load-more/load-more.d.ts +25 -0
  252. package/dist/utils/load-more/load-more.js +1 -0
  253. package/dist/utils/locale-of/locale-of.d.ts +18 -0
  254. package/dist/utils/locale-of/locale-of.js +26 -0
  255. package/dist/utils/name-text/name-text.d.ts +12 -0
  256. package/dist/utils/name-text/name-text.js +25 -0
  257. package/dist/utils/nearest/nearest.d.ts +9 -0
  258. package/dist/utils/nearest/nearest.js +9 -0
  259. package/dist/utils/number-format/number-format.d.ts +11 -1
  260. package/dist/utils/number-format/number-format.js +17 -5
  261. package/dist/utils/own-rule/own-rule.d.ts +16 -0
  262. package/dist/utils/own-rule/own-rule.js +7 -0
  263. package/dist/utils/plain-click/plain-click.d.ts +10 -0
  264. package/dist/utils/plain-click/plain-click.js +1 -0
  265. package/dist/utils/platform/platform.d.ts +8 -0
  266. package/dist/utils/platform/platform.js +1 -0
  267. package/dist/utils/press-type/press-type.d.ts +20 -0
  268. package/dist/utils/press-type/press-type.js +15 -0
  269. package/dist/utils/read-series/read-series.d.ts +14 -0
  270. package/dist/utils/read-series/read-series.js +15 -0
  271. package/dist/utils/relative-time/relative-time.d.ts +8 -0
  272. package/dist/utils/relative-time/relative-time.js +5 -2
  273. package/dist/utils/report-render/report-render.js +2 -14
  274. package/dist/utils/report-runtime/report-runtime.d.ts +11 -4
  275. package/dist/utils/report-runtime/report-runtime.js +2 -14
  276. package/dist/utils/report-usage/report-usage.js +2 -14
  277. package/dist/utils/row-data/row-data.d.ts +15 -0
  278. package/dist/utils/row-data/row-data.js +17 -0
  279. package/dist/utils/row-order/row-order.d.ts +141 -0
  280. package/dist/utils/row-order/row-order.js +76 -0
  281. package/dist/utils/scroll-item-into-view/scroll-item-into-view.d.ts +33 -0
  282. package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +13 -3
  283. package/dist/utils/slotted-glyph/slotted-glyph.d.ts +33 -0
  284. package/dist/utils/slotted-glyph/slotted-glyph.js +27 -0
  285. package/dist/utils/tell-disclosure/tell-disclosure.d.ts +4 -0
  286. package/dist/utils/tree-arrow/tree-arrow.d.ts +23 -0
  287. package/dist/utils/tree-arrow/tree-arrow.js +9 -0
  288. package/dist/utils/typeahead/typeahead.d.ts +75 -0
  289. package/dist/utils/typeahead/typeahead.js +37 -0
  290. package/dist/utils/value-as/value-as.d.ts +9 -0
  291. package/dist/utils/value-as/value-as.js +9 -1
  292. package/dist/utils/verdict-flags/verdict-flags.d.ts +13 -0
  293. package/dist/utils/verdict-flags/verdict-flags.js +6 -0
  294. package/dist/utils/watch-labels/watch-labels.d.ts +16 -0
  295. package/dist/utils/watch-labels/watch-labels.js +34 -0
  296. package/dist/utils/words-converter/words-converter.d.ts +14 -0
  297. package/dist/utils/words-converter/words-converter.js +15 -0
  298. package/dist/utils/written-list/written-list.d.ts +60 -0
  299. package/dist/utils/written-list/written-list.js +46 -0
  300. package/dist/version.d.ts +1 -1
  301. package/dist/version.js +1 -1
  302. package/package.json +29 -5
@@ -8,6 +8,8 @@ import { html, nothing } from 'lit';
8
8
  import { property, state } from 'lit/decorators.js';
9
9
  import { isPartial, isTwelveHourLayout, segmentKey, segmentLayout, segmentName, segmentRange, segmentsOf, segmentsValue, segmentText, segmentValueText, shownValue, } from '../../utils/date-segments/date-segments.js';
10
10
  import { inlineStep } from '../../utils/inline-step/inline-step.js';
11
+ import { appleTouch } from '../../utils/platform/platform.js';
12
+ import { verdictFlags } from '../../utils/verdict-flags/verdict-flags.js';
11
13
  export const MixinSegmentedField = (Base) => {
12
14
  class SegmentedFieldElement extends Base {
13
15
  constructor() {
@@ -17,6 +19,7 @@ export const MixinSegmentedField = (Base) => {
17
19
  this.parts = {};
18
20
  this.typed = '';
19
21
  this.own = false;
22
+ this.touchApple = appleTouch(typeof navigator === 'undefined' ? undefined : navigator);
20
23
  this.entered = undefined;
21
24
  this.handleSegmentKeydown = (event) => {
22
25
  const element = event.currentTarget;
@@ -169,7 +172,7 @@ export const MixinSegmentedField = (Base) => {
169
172
  }
170
173
  const anchor = this.anchor ?? undefined;
171
174
  const partial = isPartial(this.segmentedKind, this.parts, this.layout);
172
- const message = this.validate();
175
+ const fault = verdictFlags(this.validate());
173
176
  if (partial) {
174
177
  this.internals.setValidity({ badInput: true }, this.badInputMessage ||
175
178
  (this.segmentedKind === 'date' ? 'Enter a whole date.' : 'Enter a whole time.'), anchor);
@@ -178,8 +181,8 @@ export const MixinSegmentedField = (Base) => {
178
181
  this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage ||
179
182
  (this.segmentedKind === 'date' ? 'Enter a date.' : 'Enter a time.'), anchor);
180
183
  }
181
- else if (message !== '') {
182
- this.internals.setValidity({ badInput: true }, message, anchor);
184
+ else if (fault !== null) {
185
+ this.internals.setValidity(fault[0], fault[1], anchor);
183
186
  }
184
187
  else {
185
188
  this.internals.setValidity({});
@@ -210,17 +213,24 @@ export const MixinSegmentedField = (Base) => {
210
213
  const { max, min } = segmentRange(kind, this.parts, twelve);
211
214
  const text = segmentText(kind, this.parts, twelve, locale);
212
215
  const empty = shown === undefined;
216
+ const id = `${this.controlId}-${kind}`;
217
+ const editable = !this.isDisabled && !this.readOnly;
218
+ const spin = !this.touchApple;
213
219
  return html `<span
214
220
  part="segment${empty ? ' segment-placeholder' : ''}"
221
+ id=${id}
215
222
  data-segment=${kind}
216
- role="spinbutton"
223
+ role=${spin ? 'spinbutton' : 'textbox'}
217
224
  tabindex=${this.isDisabled ? '-1' : '0'}
218
225
  inputmode=${kind === 'dayPeriod' ? nothing : 'numeric'}
219
- aria-label=${segmentName(kind, locale)}
220
- aria-valuemin=${min}
221
- aria-valuemax=${max}
222
- aria-valuenow=${shown ?? nothing}
223
- aria-valuetext=${empty ? this.emptySegmentLabel : segmentValueText(kind, this.parts, twelve, locale)}
226
+ enterkeyhint=${editable ? 'next' : nothing}
227
+ aria-label=${this.labeled ? `${segmentName(kind, locale)},` : segmentName(kind, locale)}
228
+ aria-labelledby=${this.labeled ? `${id} ${this.labelId}` : nothing}
229
+ aria-invalid=${this.invalidity ?? nothing}
230
+ aria-valuemin=${spin ? min : nothing}
231
+ aria-valuemax=${spin ? max : nothing}
232
+ aria-valuenow=${spin ? (shown ?? nothing) : nothing}
233
+ aria-valuetext=${spin ? (empty ? this.emptySegmentLabel : segmentValueText(kind, this.parts, twelve, locale)) : nothing}
224
234
  aria-disabled=${this.isDisabled ? 'true' : nothing}
225
235
  aria-readonly=${this.readOnly ? 'true' : nothing}
226
236
  @keydown=${this.handleSegmentKeydown}
@@ -0,0 +1,10 @@
1
+ import type { auditName as audit } from './audit-name.js';
2
+ /**
3
+ * The missing-name warning in a production build: nothing.
4
+ *
5
+ * `#audit-name` resolves here unless the bundler or runtime asks for the
6
+ * `development` condition, so a production build carries none of the audit's
7
+ * code. The signature is the audit's, so a call site reads the same in both
8
+ * builds. See `audit-name.ts`.
9
+ */
10
+ export declare const auditName: typeof audit;
@@ -0,0 +1 @@
1
+ export const auditName = () => { };
@@ -1,13 +1,23 @@
1
1
  /**
2
2
  * Whether an element has an accessible name, by the routes a page names a
3
- * control: its own `aria-label`, `aria-labelledby` or `title`, a `<label>`, a
4
- * `placeholder`, and its content where its role is named by its content.
3
+ * control: its own `aria-label`, `aria-labelledby` or `title`, a `<label>`,
4
+ * and its content where its role is named by its content.
5
+ *
6
+ * **A `placeholder` counts for no route.** A browser names a control by it
7
+ * where nothing else does, and it is gone from the screen once a person
8
+ * types, so a field named by it alone loses its label as it is filled.
9
+ * React Aria's fields warn on the same terms.
5
10
  *
6
11
  * **An estimate, cheap on purpose.** It answers whether any route holds words,
7
12
  * which is what the warning is about, and leaves the order the routes win in
8
13
  * to the browser.
14
+ *
15
+ * **What the control shows as its value is no name**, so the words in
16
+ * `shown` count for no route. A Select with no label names its trigger by the
17
+ * part that shows the choice, and while nothing is chosen that part shows the
18
+ * placeholder, "Choose", which says nothing about what is being chosen.
9
19
  */
10
- export declare const hasName: (element: HTMLElement) => boolean;
20
+ export declare const hasName: (element: HTMLElement, shown?: Element | null) => boolean;
11
21
  /**
12
22
  * Warns once, through the runtime channel, when a control has no accessible
13
23
  * name: none on the host, and none on the control inside it.
@@ -18,11 +28,19 @@ export declare const hasName: (element: HTMLElement) => boolean;
18
28
  * that task, and an element is read once in its life, so a name taken away
19
29
  * later is not reported.
20
30
  *
21
- * **In every build.** Every runtime warning in the library reports through the
22
- * same channel whatever the build, and a project that wants the console quiet
23
- * tells `@fusion.dev/helix-diagnostics` with `core.warnings: false`.
31
+ * **In a development build only.** Every field and Button calls it, so in
32
+ * production it would cost each of them about 450 bytes gzip for a sentence
33
+ * meant for the person writing the page. Core imports it as `#audit-name`,
34
+ * which `package.json` resolves here under the `development` condition (Vite
35
+ * and webpack in development, `bun --conditions development`,
36
+ * `node --conditions=development`) and to `audit-name-off.ts`, which does
37
+ * nothing, everywhere else. Like every runtime warning it reports through the
38
+ * one channel, and a project that wants the console quiet tells
39
+ * `@fusion.dev/helix-diagnostics` with `core.warnings: false`.
24
40
  *
25
41
  * `also` answers for a name the component gave through its internals, which no
26
- * attribute shows. `fix` is the sentence that says how to name it.
42
+ * attribute shows. `fix` is the sentence that says how to name it. `shown` is
43
+ * the part where the control shows its value or its placeholder, whose words
44
+ * are no name.
27
45
  */
28
- export declare const auditName: (host: HTMLElement, control: () => HTMLElement | null, fix: string, also?: () => boolean) => void;
46
+ export declare const auditName: (host: HTMLElement, control: () => HTMLElement | null, fix: string, also?: () => boolean, shown?: () => Element | null) => void;
@@ -1,31 +1,13 @@
1
+ import { nameText } from '../name-text/name-text.js';
1
2
  import { reportRuntime } from '../report-runtime/report-runtime.js';
2
- const nameText = (node) => {
3
- if (node instanceof HTMLSlotElement) {
4
- return node.assignedNodes({ flatten: true }).map(nameText).join('');
5
- }
6
- if (node.nodeType === Node.TEXT_NODE) {
7
- return node.textContent ?? '';
8
- }
9
- if (!(node instanceof Element)) {
10
- return '';
11
- }
12
- if ((node instanceof HTMLElement && node.hidden) || node.getAttribute('aria-hidden') === 'true') {
13
- return '';
14
- }
15
- const said = node.getAttribute('aria-label') ?? node.getAttribute('alt');
16
- if (said?.trim()) {
17
- return said;
18
- }
19
- return [...node.childNodes].map(nameText).join('');
20
- };
21
- const namesWithWords = (ids, from) => {
3
+ const namesWithWords = (ids, from, shown) => {
22
4
  const root = from.getRootNode();
23
5
  return (ids ?? '')
24
6
  .split(/\s+/)
25
7
  .filter(Boolean)
26
8
  .some((id) => {
27
9
  const found = root.getElementById?.(id);
28
- return found ? nameText(found).trim() !== '' : false;
10
+ return found ? nameText(found, shown).trim() !== '' : false;
29
11
  });
30
12
  };
31
13
  const NAMED_BY_CONTENT = new Set([
@@ -40,26 +22,32 @@ const NAMED_BY_CONTENT = new Set([
40
22
  'switch',
41
23
  'tab',
42
24
  ]);
43
- export const hasName = (element) => {
44
- for (const attribute of ['aria-label', 'title', 'placeholder']) {
25
+ export const hasName = (element, shown) => {
26
+ for (const attribute of ['aria-label', 'title']) {
45
27
  if (element.getAttribute(attribute)?.trim()) {
46
28
  return true;
47
29
  }
48
30
  }
49
- if (namesWithWords(element.getAttribute('aria-labelledby'), element)) {
31
+ if (namesWithWords(element.getAttribute('aria-labelledby'), element, shown)) {
50
32
  return true;
51
33
  }
52
34
  const referenced = element
53
35
  .ariaLabelledByElements;
54
- if ((referenced ?? []).some((one) => nameText(one).trim() !== '')) {
36
+ if ((referenced ?? []).some((one) => nameText(one, shown).trim() !== '')) {
55
37
  return true;
56
38
  }
57
39
  const labels = element.labels;
58
40
  if ([...(labels ?? [])].some((label) => nameText(label).trim() !== '')) {
59
41
  return true;
60
42
  }
61
- const role = element.getAttribute('role') ?? (element.localName === 'button' ? 'button' : '');
62
- return NAMED_BY_CONTENT.has(role) && nameText(element).trim() !== '';
43
+ const role = element.getAttribute('role') ?? implicitRole(element);
44
+ return NAMED_BY_CONTENT.has(role) && nameText(element, shown).trim() !== '';
45
+ };
46
+ const implicitRole = (element) => {
47
+ if (element.localName === 'button' || element.localName === 'summary') {
48
+ return 'button';
49
+ }
50
+ return element.localName === 'a' && element.hasAttribute('href') ? 'link' : '';
63
51
  };
64
52
  const audited = new WeakSet();
65
53
  const waiting = new Map();
@@ -70,7 +58,7 @@ const readWaiting = () => {
70
58
  check();
71
59
  }
72
60
  };
73
- export const auditName = (host, control, fix, also) => {
61
+ export const auditName = (host, control, fix, also, shown) => {
74
62
  if (audited.has(host) || waiting.has(host)) {
75
63
  return;
76
64
  }
@@ -83,12 +71,16 @@ export const auditName = (host, control, fix, also) => {
83
71
  }
84
72
  audited.add(host);
85
73
  const inner = control();
86
- if (also?.() || hasName(host) || (inner !== null && hasName(inner))) {
74
+ const value = shown?.();
75
+ if (also?.() || hasName(host) || (inner !== null && hasName(inner, value))) {
87
76
  return;
88
77
  }
78
+ const placeholder = [host, inner].some((one) => one?.getAttribute('placeholder')?.trim());
89
79
  reportRuntime({
90
80
  kind: 'missing-name',
91
- message: `<${host.localName}> has no accessible name, so a screen reader announces it by its role alone. ${fix}`,
81
+ message: placeholder
82
+ ? `<${host.localName}> is named only by its placeholder, which is gone once a person types. ${fix}`
83
+ : `<${host.localName}> has no accessible name, so a screen reader announces it by its role alone. ${fix}`,
92
84
  tag: host.localName,
93
85
  });
94
86
  });
@@ -0,0 +1,10 @@
1
+ import type { auditSource as audit } from './audit-source.js';
2
+ /**
3
+ * The missing-table warning in a production build: nothing.
4
+ *
5
+ * `#audit-source` resolves here unless the bundler or runtime asks for the
6
+ * `development` condition, so a production build carries none of the audit's
7
+ * code. The signature is the audit's, so a call site reads the same in both
8
+ * builds. See `audit-source.ts`.
9
+ */
10
+ export declare const auditSource: typeof audit;
@@ -0,0 +1 @@
1
+ export const auditSource = () => { };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Reports a chart, a legend or a sparkline whose `for` names no table once the
3
+ * page has loaded, the one mistake that leaves it drawing nothing and saying
4
+ * nothing.
5
+ *
6
+ * **Read a task after `load`**, so a table later in the markup, or one a
7
+ * script writes as the page starts, counts. A table a framework renders later
8
+ * than that is reported, and the chart still draws it when it arrives.
9
+ *
10
+ * **In a development build only**, as `missing-name` is: every chart would pay
11
+ * for a sentence meant for the person writing the page. Core imports it as
12
+ * `#audit-source`, which `package.json` resolves here under the `development`
13
+ * condition and to `audit-source-off.ts`, which does nothing, everywhere else.
14
+ *
15
+ * `table` answers what `for` resolves to now: the table, or null.
16
+ */
17
+ export declare const auditSource: (host: HTMLElement & {
18
+ for: string;
19
+ }, table: () => Element | null) => void;
@@ -0,0 +1,27 @@
1
+ import { reportRuntime } from '../report-runtime/report-runtime.js';
2
+ const audited = new WeakSet();
3
+ export const auditSource = (host, table) => {
4
+ if (host.for === '' || audited.has(host) || typeof document === 'undefined') {
5
+ return;
6
+ }
7
+ audited.add(host);
8
+ const read = () => {
9
+ setTimeout(() => {
10
+ if (host.isConnected && host.for !== '' && !table()) {
11
+ reportRuntime({
12
+ kind: 'missing-table',
13
+ message: `<${host.localName} for="${host.for}"> names no table, so it draws nothing. ` +
14
+ 'Point `for` at the id of a <table>, an element with role="table" or "grid", or a ' +
15
+ 'helix-table, in the same tree.',
16
+ tag: host.localName,
17
+ });
18
+ }
19
+ }, 0);
20
+ };
21
+ if (document.readyState === 'complete') {
22
+ read();
23
+ }
24
+ else {
25
+ window.addEventListener('load', read, { once: true });
26
+ }
27
+ };
@@ -1,4 +1,4 @@
1
- import { valueAsDate as asDate, dateAsValue as fromDate } from '../value-as/value-as.js';
1
+ import { valueAsDate as asDate, dateAsValue as fromDate, utcDate } from '../value-as/value-as.js';
2
2
  import { writtenList } from '../written-list/written-list.js';
3
3
  export const localToday = (now = new Date()) => {
4
4
  const month = `${now.getMonth() + 1}`.padStart(2, '0');
@@ -15,13 +15,13 @@ export const weekStartOf = (locale) => {
15
15
  return 0;
16
16
  }
17
17
  };
18
- export const monthOf = (date) => `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`;
19
- export const addDays = (date, days) => new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days));
18
+ export const monthOf = (date) => `${String(date.getUTCFullYear()).padStart(4, '0')}-${String(date.getUTCMonth() + 1).padStart(2, '0')}`;
19
+ export const addDays = (date, days) => utcDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days);
20
20
  export const sameMonth = (left, right) => left.getUTCFullYear() === right.getUTCFullYear() && left.getUTCMonth() === right.getUTCMonth();
21
21
  export const addMonths = (date, months) => {
22
- const target = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, 1));
23
- const last = new Date(Date.UTC(target.getUTCFullYear(), target.getUTCMonth() + 1, 0)).getUTCDate();
24
- return new Date(Date.UTC(target.getUTCFullYear(), target.getUTCMonth(), Math.min(date.getUTCDate(), last)));
22
+ const target = utcDate(date.getUTCFullYear(), date.getUTCMonth() + months, 1);
23
+ const last = utcDate(target.getUTCFullYear(), target.getUTCMonth() + 1, 0).getUTCDate();
24
+ return utcDate(target.getUTCFullYear(), target.getUTCMonth(), Math.min(date.getUTCDate(), last));
25
25
  };
26
26
  export const barredBy = (date, rules) => {
27
27
  const iso = fromDate(date);
@@ -72,7 +72,7 @@ export const periodCells = ({ max, min, page, shown, today, view }) => {
72
72
  const start = years ? yearPageOf(page) : page;
73
73
  return Array.from({ length: 12 }, (_, index) => {
74
74
  const at = years ? start + index : index;
75
- const first = new Date(Date.UTC(years ? at : start, years ? 0 : index, 1));
75
+ const first = utcDate(years ? at : start, years ? 0 : index, 1);
76
76
  return {
77
77
  at,
78
78
  chosen: years ? at === shown.getUTCFullYear() : monthOf(first) === monthOf(shown),
@@ -0,0 +1,16 @@
1
+ /**
2
+ * What the three diagnostics slots share: a listener on `globalThis` under a
3
+ * registered symbol, called where there is one, whose failure is printed once.
4
+ *
5
+ * `reportRuntime`, `reportUsage` and `reportRender` each wrote this out, with
6
+ * a flag and a sentence of its own, and every element carries all three. Kept
7
+ * as one function, the sentence is one template and the flags one set.
8
+ */
9
+ /**
10
+ * Calls the function in `slot` with `args`, and answers what it returned.
11
+ *
12
+ * **A listener that throws never breaks the caller.** The error is printed
13
+ * once per `kind`, saying what happened instead (`after`), and the answer is
14
+ * `undefined`, as it is where nothing listens.
15
+ */
16
+ export declare const callListener: (slot: symbol, kind: string, after: string, ...args: unknown[]) => unknown;
@@ -0,0 +1,17 @@
1
+ const told = new Set();
2
+ export const callListener = (slot, kind, after, ...args) => {
3
+ const listener = globalThis[slot];
4
+ if (typeof listener !== 'function') {
5
+ return undefined;
6
+ }
7
+ try {
8
+ return listener(...args);
9
+ }
10
+ catch (error) {
11
+ if (!told.has(kind)) {
12
+ told.add(kind);
13
+ console.error(`helix: a ${kind} listener threw, and ${after}. Later failures are not printed.`, error);
14
+ }
15
+ return undefined;
16
+ }
17
+ };
@@ -41,3 +41,17 @@ export interface ChordPress {
41
41
  * should go to whatever did want it.
42
42
  */
43
43
  export declare const matchesChord: (press: ChordPress, keys: string, apple: boolean) => boolean;
44
+ /**
45
+ * Whether a key press is Control+A, or Command+A on an Apple keyboard: the
46
+ * press that selects every item of a multiple selection.
47
+ *
48
+ * List, Tree, Listbox, Data Table and Virtual List each wrote the test. Either
49
+ * modifier counts on any platform, as they did, and Alt held is another
50
+ * shortcut.
51
+ */
52
+ export declare const selectsAll: (press: {
53
+ readonly altKey: boolean;
54
+ readonly ctrlKey: boolean;
55
+ readonly key: string;
56
+ readonly metaKey: boolean;
57
+ }) => boolean;
@@ -51,3 +51,4 @@ export const matchesChord = (press, keys, apple) => {
51
51
  (ctrl ? press.ctrlKey : !press.ctrlKey) &&
52
52
  (meta ? press.metaKey : !press.metaKey));
53
53
  };
54
+ export const selectsAll = (press) => (press.ctrlKey || press.metaKey) && !press.altKey && press.key.toLowerCase() === 'a';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `value` held between `low` and `high`.
3
+ *
4
+ * Written four times before: Lightbox's zoom, Scroll Area's scrollbar, Color
5
+ * Picker's channels and core's color reading.
6
+ */
7
+ export declare const clamp: (value: number, low: number, high: number) => number;
@@ -0,0 +1 @@
1
+ export const clamp = (value, low, high) => Math.min(Math.max(value, low), high);
@@ -1,4 +1,4 @@
1
- const clamp = (value, low, high) => Math.min(high, Math.max(low, value));
1
+ import { clamp } from '../clamp/clamp.js';
2
2
  const toAlpha = (token) => {
3
3
  if (token === undefined) {
4
4
  return 100;
@@ -46,7 +46,7 @@ export interface TooltipAt {
46
46
  *
47
47
  * The chart's `pointer` is one, and is what every chart passes.
48
48
  */
49
- export type ReadingCursor = Pick<ChartPointerController, 'column' | 'keyed'>;
49
+ export type ReadingCursor = Pick<ChartPointerController, 'column' | 'keyed'> & Partial<Pick<ChartPointerController, 'position' | 'shows'>>;
50
50
  /**
51
51
  * What a pointer resting on a reading shows, as `Tooltip` pointed at a mark.
52
52
  *
@@ -10,7 +10,9 @@ export const drawTooltip = (rows, at, tag, where, slotOf, reading) => {
10
10
  const row = rows[at];
11
11
  const live = reading === undefined || rows.length === 0
12
12
  ? nothing
13
- : html `<span aria-live="polite" part="live" role="status">${reading.keyed && row ? spokenReading(row, reading.column) : ''}</span>`;
13
+ : html `<span aria-live="polite" part="live" role="status">${reading.keyed && row
14
+ ? spokenReading(row, reading.column, (cell) => reading.shows?.(cell) !== false, reading.position)
15
+ : ''}</span>`;
14
16
  if (!row || rows.length === 0) {
15
17
  return live;
16
18
  }
@@ -5,6 +5,10 @@ import type { Row } from '../read-series/read-series.js';
5
5
  *
6
6
  * The table's own text, as the bubble shows it, so the words and the picture
7
7
  * agree, and nothing in it is English: the names are the table's headings. A
8
- * blank cell says nothing and is left out.
8
+ * blank cell says nothing and is left out, and so is a cell `shows` answers
9
+ * false for, which is a series a legend hid.
10
+ *
11
+ * `position` follows in brackets, such as "2 of 12", where the chart gives
12
+ * one: last, so the reading is heard before where it stands.
9
13
  */
10
- export declare const spokenReading: (row: Row, column?: number) => string;
14
+ export declare const spokenReading: (row: Row, column?: number, shows?: (cell: number) => boolean, position?: string) => string;
@@ -1,10 +1,11 @@
1
- export const spokenReading = (row, column) => {
1
+ export const spokenReading = (row, column, shows = () => true, position = '') => {
2
+ const after = position === '' ? '' : ` (${position})`;
2
3
  const cell = column === undefined ? undefined : row.cells[column];
3
4
  if (cell) {
4
- return `${row.label}, ${cell.name} ${cell.text}`.trim();
5
+ return `${`${row.label}, ${cell.name} ${cell.text}`.trim()}${after}`;
5
6
  }
6
7
  const said = row.cells
7
- .filter((one) => one.text.trim() !== '')
8
+ .filter((one, index) => one.text.trim() !== '' && shows(index))
8
9
  .map((one) => `${one.name} ${one.text}`.trim());
9
- return said.length === 0 ? row.label : `${row.label}: ${said.join(', ')}`;
10
+ return `${said.length === 0 ? row.label : `${row.label}: ${said.join(', ')}`}${after}`;
10
11
  };
@@ -1,4 +1,4 @@
1
- import type { Relative } from '../relative-time/relative-time.js';
1
+ import { type Relative } from '../relative-time/relative-time.js';
2
2
  /**
3
3
  * A formatter for one locale, kept.
4
4
  *
@@ -1,10 +1,7 @@
1
+ import { UNITS as TIME_UNITS } from '../relative-time/relative-time.js';
1
2
  const held = new Map();
2
3
  const dated = new Map();
3
- const UNITS = [
4
- { ms: 60_000, unit: 'minute' },
5
- { ms: 3_600_000, unit: 'hour' },
6
- { ms: 86_400_000, unit: 'day' },
7
- ];
4
+ const UNITS = TIME_UNITS.slice(1, 4);
8
5
  const HORIZON = 604_800_000;
9
6
  const compact = (locale) => {
10
7
  let found = held.get(locale);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A heading level a reader can be told: a whole number from 1 to 6, from
3
+ * the level asked for, or `fallback` where none was.
4
+ *
5
+ * `aria-level` takes a whole number, so a fraction is cut to the level below
6
+ * it, and a level past either end is held at it: `0` is 1 and `9` is 6.
7
+ */
8
+ export declare const headingLevel: (level: number | undefined, fallback?: number) => number;
@@ -0,0 +1,4 @@
1
+ export const headingLevel = (level, fallback = 3) => {
2
+ const asked = level === undefined || Number.isNaN(level) ? fallback : level;
3
+ return Math.min(6, Math.max(1, Math.trunc(asked)));
4
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The words that name a host, for a part inside its shadow root that must
3
+ * carry the same name: the list a Select or a Time Picker opens.
4
+ *
5
+ * **Words rather than a reference**, because the part is inside the host's
6
+ * shadow root, and neither an IDREF on the page nor the host's labels reach
7
+ * it. Read in the order a browser names the host: its `aria-labelledby`, its
8
+ * `aria-label`, then `own`, the name the component draws itself (its `label`),
9
+ * then a `<label>` for it. Each element's words are read as a name reads
10
+ * them, so hidden text is left out and runs of white space are one space.
11
+ *
12
+ * Empty where nothing names the host, which leaves the fallback to the caller.
13
+ */
14
+ export declare const hostWords: (host: HTMLElement & {
15
+ labels?: NodeList | null;
16
+ }, own?: string) => string;
@@ -0,0 +1,13 @@
1
+ import { elementById } from '../element-by-id/element-by-id.js';
2
+ import { nameText } from '../name-text/name-text.js';
3
+ const wordsOf = (named) => named
4
+ .map((one) => (one ? nameText(one).replace(/\s+/g, ' ').trim() : ''))
5
+ .filter(Boolean)
6
+ .join(' ');
7
+ export const hostWords = (host, own = '') => {
8
+ const ids = (host.getAttribute('aria-labelledby') ?? '').split(/\s+/).filter(Boolean);
9
+ return (wordsOf(ids.map((id) => elementById(host, id))) ||
10
+ host.getAttribute('aria-label')?.trim() ||
11
+ own ||
12
+ wordsOf([...(host.labels ?? [])]));
13
+ };
@@ -0,0 +1,25 @@
1
+ /** Whether `element` is a submit button, native or Helix. */
2
+ export declare const submits: (element: Element) => boolean;
3
+ /** The form's default button, the first submit button in it, native or Helix. */
4
+ export declare const defaultButton: (form: HTMLFormElement) => Element | undefined;
5
+ /** Whether `target` is a native field of `form` that Enter submits it from. */
6
+ export declare const submitsOnEnter: (target: EventTarget | undefined, form: HTMLFormElement) => boolean;
7
+ /**
8
+ * Submits a control's form the way pressing Enter in a native text field does.
9
+ *
10
+ * A Helix control's own input is in a shadow root and has no form owner, so
11
+ * the platform never runs implicit submission for it. This runs it: the form's
12
+ * default button is activated, the first submit button in it, a Helix one
13
+ * included. With none, the form is submitted when it holds no more than one
14
+ * field that counts against implicit submission, and nothing happens
15
+ * otherwise.
16
+ *
17
+ * **A module of its own rather than a method on the base**, so its code ships
18
+ * only with the controls that submit on Enter (Input, Number Input, Pin Input,
19
+ * Combobox, the picker fields and Button) and not with Switch, Checkbox or
20
+ * Slider. `form` is the control's `form`, and a control with none submits
21
+ * nothing.
22
+ *
23
+ * @reference https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission implicit submission
24
+ */
25
+ export declare const submitImplicitly: (form: HTMLFormElement | null) => void;
@@ -0,0 +1,52 @@
1
+ import { HelixFormElement } from '../../helix-form-element/helix-form-element.js';
2
+ const BLOCKING_TYPES = new Set([
3
+ 'date',
4
+ 'datetime-local',
5
+ 'email',
6
+ 'month',
7
+ 'number',
8
+ 'password',
9
+ 'search',
10
+ 'tel',
11
+ 'text',
12
+ 'time',
13
+ 'url',
14
+ 'week',
15
+ ]);
16
+ const hooks = (element) => element;
17
+ export const submits = (element) => {
18
+ if (element instanceof HelixFormElement) {
19
+ return hooks(element).submitsForm;
20
+ }
21
+ if (element instanceof HTMLButtonElement) {
22
+ return element.type === 'submit';
23
+ }
24
+ return (element instanceof HTMLInputElement && (element.type === 'submit' || element.type === 'image'));
25
+ };
26
+ export const defaultButton = (form) => [...form.elements].find((element) => submits(element));
27
+ export const submitsOnEnter = (target, form) => target instanceof HTMLInputElement && target.form === form && BLOCKING_TYPES.has(target.type);
28
+ export const submitImplicitly = (form) => {
29
+ if (!form) {
30
+ return;
31
+ }
32
+ const button = defaultButton(form);
33
+ if (button) {
34
+ if (button.matches(':disabled')) {
35
+ return;
36
+ }
37
+ if (button instanceof HelixFormElement) {
38
+ hooks(button).activate();
39
+ }
40
+ else {
41
+ ;
42
+ button.click();
43
+ }
44
+ return;
45
+ }
46
+ const blocking = [...form.elements].filter((element) => element instanceof HelixFormElement
47
+ ? hooks(element).blocksImplicitSubmission
48
+ : element instanceof HTMLInputElement && BLOCKING_TYPES.has(element.type));
49
+ if (blocking.length <= 1) {
50
+ form.requestSubmit();
51
+ }
52
+ };