@fusion.dev/helix-core 0.146.0 → 0.148.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 (132) hide show
  1. package/custom-elements.json +3129 -282
  2. package/dist/controllers/aria-forward-controller/aria-forward-controller.js +5 -3
  3. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +6 -0
  4. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +13 -0
  5. package/dist/controllers/children-controller/children-controller.d.ts +28 -0
  6. package/dist/controllers/children-controller/children-controller.js +18 -0
  7. package/dist/controllers/copy-controller/copy-controller.d.ts +4 -1
  8. package/dist/controllers/copy-controller/copy-controller.js +2 -1
  9. package/dist/controllers/countdown-controller/countdown-controller.d.ts +19 -2
  10. package/dist/controllers/countdown-controller/countdown-controller.js +30 -3
  11. package/dist/controllers/floating-controller/floating-controller.d.ts +12 -1
  12. package/dist/controllers/floating-controller/floating-controller.js +2 -1
  13. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +30 -0
  14. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.js +8 -0
  15. package/dist/controllers/open-phase-controller/open-phase-controller.d.ts +10 -0
  16. package/dist/controllers/open-phase-controller/open-phase-controller.js +7 -4
  17. package/dist/controllers/option-window-controller/option-window-controller.d.ts +96 -0
  18. package/dist/controllers/option-window-controller/option-window-controller.js +81 -0
  19. package/dist/controllers/popover-controller/popover-controller.js +1 -1
  20. package/dist/controllers/source-controller/source-controller.js +2 -0
  21. package/dist/controllers/swipe-controller/swipe-controller.d.ts +10 -1
  22. package/dist/controllers/swipe-controller/swipe-controller.js +1 -1
  23. package/dist/controllers/virtualize-controller/virtualize-controller.js +8 -6
  24. package/dist/events/band.d.ts +13 -0
  25. package/dist/events/band.js +11 -0
  26. package/dist/events/details.d.ts +5 -0
  27. package/dist/events/events.d.ts +4 -2
  28. package/dist/events/events.js +3 -1
  29. package/dist/events/names.d.ts +3 -0
  30. package/dist/events/names.js +13 -88
  31. package/dist/helix-element/helix-element.d.ts +14 -5
  32. package/dist/helix-element/helix-element.js +13 -45
  33. package/dist/helix-element/react-bridge.d.ts +13 -0
  34. package/dist/helix-element/react-bridge.js +1 -1
  35. package/dist/index.d.ts +40 -17
  36. package/dist/index.js +38 -15
  37. package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +12 -0
  38. package/dist/mixins/mixin-chart-source/mixin-chart-source.js +4 -0
  39. package/dist/mixins/mixin-dismissible/mixin-dismissible.js +25 -4
  40. package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.d.ts +42 -0
  41. package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.js +46 -0
  42. package/dist/mixins/mixin-picker-field/mixin-picker-field.d.ts +2 -11
  43. package/dist/mixins/mixin-picker-field/mixin-picker-field.js +1 -6
  44. package/dist/mixins/mixin-segmented-field/mixin-segmented-field.d.ts +1 -1
  45. package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +10 -6
  46. package/dist/mixins/mixin-viewport/mixin-viewport.js +8 -7
  47. package/dist/utils/assign-slots/assign-slots.d.ts +18 -0
  48. package/dist/utils/assign-slots/assign-slots.js +14 -0
  49. package/dist/utils/audit-name/audit-name.d.ts +7 -2
  50. package/dist/utils/audit-name/audit-name.js +12 -3
  51. package/dist/utils/audit-source/audit-source-off.d.ts +10 -0
  52. package/dist/utils/audit-source/audit-source-off.js +1 -0
  53. package/dist/utils/audit-source/audit-source.d.ts +19 -0
  54. package/dist/utils/audit-source/audit-source.js +27 -0
  55. package/dist/utils/autofill-select/autofill-select.d.ts +40 -0
  56. package/dist/utils/autofill-select/autofill-select.js +14 -0
  57. package/dist/utils/call-listener/call-listener.d.ts +16 -0
  58. package/dist/utils/call-listener/call-listener.js +17 -0
  59. package/dist/utils/center-in-view/center-in-view.d.ts +18 -0
  60. package/dist/utils/center-in-view/center-in-view.js +14 -0
  61. package/dist/utils/chord/chord.d.ts +14 -0
  62. package/dist/utils/chord/chord.js +1 -0
  63. package/dist/utils/chord/key-names.d.ts +30 -0
  64. package/dist/utils/chord/key-names.js +52 -0
  65. package/dist/utils/clamp/clamp.d.ts +7 -0
  66. package/dist/utils/clamp/clamp.js +1 -0
  67. package/dist/utils/column-step/column-step.d.ts +13 -0
  68. package/dist/utils/column-step/column-step.js +9 -0
  69. package/dist/utils/css-color/css-color.js +1 -1
  70. package/dist/utils/data-options/data-options.d.ts +60 -0
  71. package/dist/utils/data-options/data-options.js +46 -0
  72. package/dist/utils/draw-tooltip/draw-tooltip.d.ts +7 -2
  73. package/dist/utils/draw-tooltip/draw-tooltip.js +1 -1
  74. package/dist/utils/draw-tooltip/spoken-reading.d.ts +3 -2
  75. package/dist/utils/draw-tooltip/spoken-reading.js +3 -2
  76. package/dist/utils/elapsed-time/elapsed-time.d.ts +1 -1
  77. package/dist/utils/elapsed-time/elapsed-time.js +2 -5
  78. package/dist/utils/export-parts/export-parts.d.ts +14 -0
  79. package/dist/utils/export-parts/export-parts.js +1 -0
  80. package/dist/utils/fill-template/fill-template.d.ts +9 -0
  81. package/dist/utils/fill-template/fill-template.js +3 -0
  82. package/dist/utils/filter-marks/filter-marks.d.ts +36 -0
  83. package/dist/utils/filter-marks/filter-marks.js +41 -0
  84. package/dist/utils/focus-target/focus-target.d.ts +12 -0
  85. package/dist/utils/focus-target/focus-target.js +9 -0
  86. package/dist/utils/focusable-elements/focusable-elements.d.ts +17 -0
  87. package/dist/utils/focusable-elements/focusable-elements.js +8 -0
  88. package/dist/utils/grid-move/grid-move.d.ts +56 -0
  89. package/dist/utils/grid-move/grid-move.js +28 -0
  90. package/dist/utils/host-words/host-words.d.ts +16 -0
  91. package/dist/utils/host-words/host-words.js +13 -0
  92. package/dist/utils/load-more/load-more.d.ts +25 -0
  93. package/dist/utils/load-more/load-more.js +1 -0
  94. package/dist/utils/locale-of/locale-of.d.ts +18 -0
  95. package/dist/utils/locale-of/locale-of.js +26 -0
  96. package/dist/utils/nearest/nearest.d.ts +9 -0
  97. package/dist/utils/nearest/nearest.js +9 -0
  98. package/dist/utils/number-format/number-format.d.ts +16 -0
  99. package/dist/utils/number-format/number-format.js +5 -0
  100. package/dist/utils/own-rule/own-rule.d.ts +16 -0
  101. package/dist/utils/own-rule/own-rule.js +7 -0
  102. package/dist/utils/platform/platform.d.ts +8 -0
  103. package/dist/utils/platform/platform.js +1 -0
  104. package/dist/utils/read-series/read-series.d.ts +14 -0
  105. package/dist/utils/read-series/read-series.js +15 -0
  106. package/dist/utils/relative-time/relative-time.d.ts +8 -0
  107. package/dist/utils/relative-time/relative-time.js +5 -2
  108. package/dist/utils/report-render/report-render.js +2 -14
  109. package/dist/utils/report-runtime/report-runtime.d.ts +11 -1
  110. package/dist/utils/report-runtime/report-runtime.js +2 -14
  111. package/dist/utils/report-usage/report-usage.js +2 -14
  112. package/dist/utils/report-values/report-values.d.ts +16 -4
  113. package/dist/utils/report-values/report-values.js +2 -2
  114. package/dist/utils/request-change/request-change.d.ts +11 -0
  115. package/dist/utils/request-change/request-change.js +10 -0
  116. package/dist/utils/scroll-item-into-view/scroll-item-into-view.d.ts +50 -0
  117. package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +14 -3
  118. package/dist/utils/slot-filled/slot-filled.d.ts +8 -0
  119. package/dist/utils/slot-filled/slot-filled.js +1 -0
  120. package/dist/utils/slotted-glyph/slotted-glyph.d.ts +33 -0
  121. package/dist/utils/slotted-glyph/slotted-glyph.js +27 -0
  122. package/dist/utils/toolbar-around/toolbar-around.d.ts +18 -0
  123. package/dist/utils/toolbar-around/toolbar-around.js +5 -0
  124. package/dist/utils/typeahead/typeahead.d.ts +8 -0
  125. package/dist/utils/typeahead/typeahead.js +1 -0
  126. package/dist/utils/verdict-flags/verdict-flags.d.ts +13 -0
  127. package/dist/utils/verdict-flags/verdict-flags.js +6 -0
  128. package/dist/utils/written-list/written-list.d.ts +31 -0
  129. package/dist/utils/written-list/written-list.js +16 -0
  130. package/dist/version.d.ts +1 -1
  131. package/dist/version.js +1 -1
  132. package/package.json +15 -4
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export { auditName } from '#audit-name';
2
2
  export { AriaForwardController, } from './controllers/aria-forward-controller/aria-forward-controller.js';
3
3
  export { ArrivalController, } from './controllers/arrival-controller/arrival-controller.js';
4
4
  export { ChartPointerController, } from './controllers/chart-pointer-controller/chart-pointer-controller.js';
5
+ export { ChildrenController } from './controllers/children-controller/children-controller.js';
5
6
  export { CommandController, HelixFallbackCommandEvent, supportsInvokers, } from './controllers/command-controller/command-controller.js';
6
7
  export { CopyController, } from './controllers/copy-controller/copy-controller.js';
7
8
  export { CountdownController, } from './controllers/countdown-controller/countdown-controller.js';
@@ -16,9 +17,10 @@ export { FullscreenController } from './controllers/fullscreen-controller/fullsc
16
17
  export { HostClickController } from './controllers/host-click-controller/host-click-controller.js';
17
18
  export { IdleController } from './controllers/idle-controller/idle-controller.js';
18
19
  export { IndicatorController, } from './controllers/indicator-controller/indicator-controller.js';
19
- export { KeyboardNavigationController, } from './controllers/keyboard-navigation-controller/keyboard-navigation-controller.js';
20
+ export { focusItemOf, KeyboardNavigationController, } from './controllers/keyboard-navigation-controller/keyboard-navigation-controller.js';
20
21
  export { MediaSessionController, SKIP_SECONDS, } from './controllers/media-session-controller/media-session-controller.js';
21
- export { animationsSettled, OpenPhaseController, } from './controllers/open-phase-controller/open-phase-controller.js';
22
+ export { animationsFinished, animationsSettled, OpenPhaseController, } from './controllers/open-phase-controller/open-phase-controller.js';
23
+ export { OptionWindowController, } from './controllers/option-window-controller/option-window-controller.js';
22
24
  export { MAX_FRAME_STEP, PaintGateController, } from './controllers/paint-gate-controller/paint-gate-controller.js';
23
25
  export { PlacementController } from './controllers/placement-controller/placement-controller.js';
24
26
  export { PopoverController, } from './controllers/popover-controller/popover-controller.js';
@@ -30,10 +32,10 @@ export { SwipeController, } from './controllers/swipe-controller/swipe-controlle
30
32
  export { TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
31
33
  export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
32
34
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
33
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/events.js';
35
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/events.js';
34
36
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
35
37
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
36
- export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
38
+ export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
37
39
  export { MixinCollection, } from './mixins/mixin-collection/mixin-collection.js';
38
40
  export { MixinControllerActive, } from './mixins/mixin-controller-active/mixin-controller-active.js';
39
41
  export { MixinControllerChecked, } from './mixins/mixin-controller-checked/mixin-controller-checked.js';
@@ -42,6 +44,7 @@ export { MixinControllerValue, } from './mixins/mixin-controller-value/mixin-con
42
44
  export { MixinDismissible, } from './mixins/mixin-dismissible/mixin-dismissible.js';
43
45
  export { MixinField } from './mixins/mixin-field/mixin-field.js';
44
46
  export { MixinPickerEditing, } from './mixins/mixin-picker-editing/mixin-picker-editing.js';
47
+ export { MixinPickerFeedback, } from './mixins/mixin-picker-feedback/mixin-picker-feedback.js';
45
48
  export { MixinPickerField, } from './mixins/mixin-picker-field/mixin-picker-field.js';
46
49
  export { MixinSegmentedField, } from './mixins/mixin-segmented-field/mixin-segmented-field.js';
47
50
  export { MixinSelectableItem, } from './mixins/mixin-selectable-item/mixin-selectable-item.js';
@@ -49,52 +52,69 @@ export { MixinTokens } from './mixins/mixin-tokens/mixin-tokens.js';
49
52
  export { MixinViewport, } from './mixins/mixin-viewport/mixin-viewport.js';
50
53
  export { anchorElement } from './utils/anchor-element/anchor-element.js';
51
54
  export { arrowReach, sideOf } from './utils/arrow/arrow.js';
55
+ export { assignSlots } from './utils/assign-slots/assign-slots.js';
56
+ export { drawAutofill, } from './utils/autofill-select/autofill-select.js';
52
57
  export { addDays, addMonths, barredBy, localToday, monthOf, monthOut, periodCells, periodKey, periodMove, sameMonth, weekStartOf, YEARS_SHOWN, yearOut, yearPageOf, } from './utils/calendar/calendar.js';
53
58
  export { capturePointer } from './utils/capture-pointer/capture-pointer.js';
54
- export { ariaChord, chordParts, matchesChord, printableChord, } from './utils/chord/chord.js';
59
+ export { centerInView } from './utils/center-in-view/center-in-view.js';
60
+ export { ariaChord, chordParts, matchesChord, printableChord, selectsAll, } from './utils/chord/chord.js';
61
+ export { keyNames } from './utils/chord/key-names.js';
62
+ export { clamp } from './utils/clamp/clamp.js';
55
63
  export { clockLocale, dayPeriod, isTwelveHour, nearestTime, offeredTimes, timeBarred, timeFault, wheelParts, wholeHour, } from './utils/clock/clock.js';
56
64
  export { closestInstance } from './utils/closest-instance/closest-instance.js';
57
65
  export { colorName, hueName } from './utils/color-name/color-name.js';
66
+ export { columnStep } from './utils/column-step/column-step.js';
58
67
  export { countLabel } from './utils/count-label/count-label.js';
59
68
  export { createSheet } from './utils/create-sheet/create-sheet.js';
60
69
  export { formatColor, parseColor, toCss, toHsl, toRgb, } from './utils/css-color/css-color.js';
61
70
  export { customElement, definedTags, duplicateRegistrations, } from './utils/custom-element/custom-element.js';
71
+ export { dataOptions, drawOptions, windowOf, } from './utils/data-options/data-options.js';
62
72
  export { segmentName } from './utils/date-segments/date-segments.js';
63
73
  export { drawDismiss, drawDismissGlyph, } from './utils/draw-dismiss/draw-dismiss.js';
64
74
  export { drawIcon } from './utils/draw-icon/draw-icon.js';
65
75
  export { CHART_PLOT, drawTooltip } from './utils/draw-tooltip/draw-tooltip.js';
66
76
  export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
67
77
  export { elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
68
- export { fillTemplate } from './utils/fill-template/fill-template.js';
69
- export { deepActiveElement, deepContains, focusableElements, } from './utils/focusable-elements/focusable-elements.js';
78
+ export { exportParts } from './utils/export-parts/export-parts.js';
79
+ export { fillTemplate, labelWith } from './utils/fill-template/fill-template.js';
80
+ export { FILTER_MARK, markMatches, rangeOf } from './utils/filter-marks/filter-marks.js';
81
+ export { focusTarget } from './utils/focus-target/focus-target.js';
82
+ export { deepActiveElement, deepContains, focusableElements, PRESSABLE, pressedOwnControl, } from './utils/focusable-elements/focusable-elements.js';
70
83
  export { afterLinkFollowed, followLink, } from './utils/follow-link/follow-link.js';
71
84
  export { formatNumbers } from './utils/format-numbers/format-numbers.js';
85
+ export { gridMove, pageRows, } from './utils/grid-move/grid-move.js';
72
86
  export { headingIn, headingsIn } from './utils/heading-in/heading-in.js';
73
87
  export { headingLevel } from './utils/heading-level/heading-level.js';
74
88
  export { hostAria } from './utils/host-aria/host-aria.js';
89
+ export { hostWords } from './utils/host-words/host-words.js';
75
90
  export { defaultButton, submitImplicitly, submits, submitsOnEnter, } from './utils/implicit-submit/implicit-submit.js';
76
91
  export { forgetDisabled, inheritDisabled, } from './utils/inherit-disabled/inherit-disabled.js';
77
92
  export { inlineStep } from './utils/inline-step/inline-step.js';
78
93
  export { isRtl } from './utils/is-rtl/is-rtl.js';
79
94
  export { keyClaimed } from './utils/key-claimed/key-claimed.js';
80
95
  export { linePath } from './utils/line-path/line-path.js';
96
+ export { endInSight } from './utils/load-more/load-more.js';
97
+ export { localeOf } from './utils/locale-of/locale-of.js';
81
98
  export { markRegion } from './utils/mark-region/mark-region.js';
82
99
  export { copiesOf, sameCopies, } from './utils/media-copy/media-copy.js';
83
- export { formatNumber, parseNumber } from './utils/number-format/number-format.js';
100
+ export { nameText } from './utils/name-text/name-text.js';
101
+ export { nearest } from './utils/nearest/nearest.js';
102
+ export { formatNumber, formatPercent, parseNumber, readingText, } from './utils/number-format/number-format.js';
84
103
  export { onUnlessFalse } from './utils/on-unless-false/on-unless-false.js';
104
+ export { applyOwnRule } from './utils/own-rule/own-rule.js';
85
105
  export { plainClick } from './utils/plain-click/plain-click.js';
86
- export { appleTouch, onApple } from './utils/platform/platform.js';
106
+ export { appleTouch, onAndroid, onApple } from './utils/platform/platform.js';
87
107
  export { pressType } from './utils/press-type/press-type.js';
88
108
  export { rangeAdd } from './utils/range-add/range-add.js';
89
109
  export { readColor, rgbOf } from './utils/read-color/read-color.js';
90
- export { byRow, readRows, readSeries, seriesKey, unbroken, } from './utils/read-series/read-series.js';
110
+ export { byRow, extremesOf, readRows, readSeries, seriesKey, unbroken, } from './utils/read-series/read-series.js';
91
111
  export { linkDescription, reflectElements, unlinkDescription, } from './utils/reflect-elements/reflect-elements.js';
92
112
  export { relativeTime, } from './utils/relative-time/relative-time.js';
93
113
  export { measuring, RENDER_SLOT, reportRender } from './utils/report-render/report-render.js';
94
114
  export { RUNTIME_LOG, RUNTIME_SLOT, reportRuntime, } from './utils/report-runtime/report-runtime.js';
95
115
  export { noteVersion, reportUsage, USAGE_SLOT, VERSIONS_SLOT, } from './utils/report-usage/report-usage.js';
96
116
  export { reportValues } from './utils/report-values/report-values.js';
97
- export { requestChange, } from './utils/request-change/request-change.js';
117
+ export { requestChange, requestValue, } from './utils/request-change/request-change.js';
98
118
  export { resolveActiveItem, } from './utils/resolve-active-item/resolve-active-item.js';
99
119
  export { holdCaret, restoreValue } from './utils/restore-value/restore-value.js';
100
120
  export { rovingStop } from './utils/roving-stop/roving-stop.js';
@@ -102,20 +122,23 @@ export { valueAt } from './utils/row-data/row-data.js';
102
122
  export { arranged, cycle, filter, format, ordered, parse, sort, window_, } from './utils/row-order/row-order.js';
103
123
  export { extent, linear } from './utils/scale/scale.js';
104
124
  export { ticks } from './utils/scale/ticks.js';
105
- export { scrollItemIntoView, } from './utils/scroll-item-into-view/scroll-item-into-view.js';
125
+ export { scrollItemIntoView, scrollingAncestor, scrollRoom, } from './utils/scroll-item-into-view/scroll-item-into-view.js';
106
126
  export { lockScroll, scrollHolders, unlockScroll } from './utils/scroll-lock/scroll-lock.js';
107
- export { slotFilled } from './utils/slot-filled/slot-filled.js';
127
+ export { slotFilled, slotNamed } from './utils/slot-filled/slot-filled.js';
128
+ export { SlottedGlyph } from './utils/slotted-glyph/slotted-glyph.js';
108
129
  export { slottedWords } from './utils/slotted-words/slotted-words.js';
109
130
  export { splitValues } from './utils/split-values/split-values.js';
110
131
  export { edgeOffset, FLING, parseSnapPoints, settleSwipe, snapTravel, swipeAxis, swipeEdge, swipeStep, towardEdge, } from './utils/swipe/swipe.js';
111
132
  export { tellDisclosure } from './utils/tell-disclosure/tell-disclosure.js';
112
133
  export { subscribe } from './utils/ticker/ticker.js';
113
134
  export { TONE_MARKS, toneMark, } from './utils/tone-marks/tone-marks.js';
135
+ export { toolbarAround, toolbarAxis } from './utils/toolbar-around/toolbar-around.js';
114
136
  export { treeArrow } from './utils/tree-arrow/tree-arrow.js';
115
- export { Typeahead, typeaheadBy, typesCharacter, } from './utils/typeahead/typeahead.js';
137
+ export { Typeahead, typeaheadBy, typeaheadByWords, typesCharacter, } from './utils/typeahead/typeahead.js';
116
138
  export { dateAsValue, isClockValue, isDateValue, isTimeValue, minutesAsValue, numberAsValue, secondsAsValue, timeAsValue, valueAsDate, valueAsMinutes, valueAsNumber, valueAsSeconds, valueAsTime, } from './utils/value-as/value-as.js';
139
+ export { verdictFlags } from './utils/verdict-flags/verdict-flags.js';
117
140
  export { watchTheme } from './utils/watch-theme/watch-theme.js';
118
141
  export { wordsConverter } from './utils/words-converter/words-converter.js';
119
142
  export { writeClock, writeTime } from './utils/write-time/write-time.js';
120
- export { commaList, pressedValue, prunedValue, toggleEvery, toggleValue, writtenList, writtenNumbers, } from './utils/written-list/written-list.js';
143
+ export { anchorAt, commaList, everyState, inRowOrder, pressedValue, prunedValue, toggleEvery, toggleValue, writtenList, writtenNumbers, } from './utils/written-list/written-list.js';
121
144
  export { VERSION } from './version.js';
@@ -178,6 +178,11 @@ export declare class MixinChartSourceInterface {
178
178
  * hid.
179
179
  */
180
180
  showsColumn(cell: number): boolean;
181
+ /**
182
+ * The heading of the column at this place in a row, read from the first row
183
+ * that has a cell there, or `''` where none has.
184
+ */
185
+ columnName(cell: number): string;
181
186
  /**
182
187
  * The number of readings, which the pointer position maps onto.
183
188
  */
@@ -187,6 +192,13 @@ export declare class MixinChartSourceInterface {
187
192
  */
188
193
  pointer: ChartPointerController;
189
194
  }
195
+ /**
196
+ * The words a chart says a reading's place in by default, such as "2 of 12":
197
+ * every chart's `position-label`, and Sparkline's, which is no chart source.
198
+ * The property keeps the words written out, which is what its reference page
199
+ * shows as the default; a spec holds the two together.
200
+ */
201
+ export declare const POSITION_LABEL = "{position} of {count}";
190
202
  /**
191
203
  * The half of a chart that is about finding its numbers rather than drawing.
192
204
  *
@@ -14,6 +14,7 @@ export const seriesIndex = (depth) => (depth % PALETTE) + 1;
14
14
  export const PLOT_WIDTH = 100;
15
15
  export const PLOT_HEIGHT = 100;
16
16
  export const seriesNames = (list) => writtenList(list).map(seriesKey);
17
+ export const POSITION_LABEL = '{position} of {count}';
17
18
  export const MixinChartSource = (Base) => {
18
19
  class ChartSourceElement extends Base {
19
20
  constructor() {
@@ -69,6 +70,9 @@ export const MixinChartSource = (Base) => {
69
70
  const name = this.sourceRows[0]?.cells[cell]?.name;
70
71
  return name === undefined || this.showsSeries(name);
71
72
  }
73
+ columnName(cell) {
74
+ return this.sourceRows.find((row) => row.cells[cell])?.cells[cell]?.name ?? '';
75
+ }
72
76
  get readings() {
73
77
  return this.sourceRows.length;
74
78
  }
@@ -14,6 +14,8 @@ export const MixinDismissible = (Base) => {
14
14
  super(...arguments);
15
15
  this.dismissible = false;
16
16
  this.dismissLabel = 'Dismiss';
17
+ this.handOff = undefined;
18
+ this.forgetFocus = undefined;
17
19
  }
18
20
  dismissEvent() {
19
21
  const own = [...this.childNodes]
@@ -63,7 +65,8 @@ export const MixinDismissible = (Base) => {
63
65
  return [...after, ...before];
64
66
  }
65
67
  keepFocus(neighbors, beside) {
66
- const settle = () => {
68
+ this.forgetFocus?.();
69
+ const settle = (late) => {
67
70
  const active = document.activeElement;
68
71
  if (this.isConnected || (active !== null && active !== document.body)) {
69
72
  return;
@@ -77,12 +80,30 @@ export const MixinDismissible = (Base) => {
77
80
  }
78
81
  }
79
82
  }
80
- if (beside?.isConnected) {
83
+ if (late && beside?.isConnected) {
81
84
  beside.focus();
82
85
  }
83
86
  };
84
- settle();
85
- requestAnimationFrame(settle);
87
+ settle(false);
88
+ requestAnimationFrame(() => settle(true));
89
+ if (this.isConnected) {
90
+ const forget = () => {
91
+ this.handOff = undefined;
92
+ this.forgetFocus = undefined;
93
+ document.removeEventListener('focusin', forget, true);
94
+ };
95
+ this.handOff = settle;
96
+ this.forgetFocus = forget;
97
+ document.addEventListener('focusin', forget, true);
98
+ }
99
+ }
100
+ disconnectedCallback() {
101
+ super.disconnectedCallback();
102
+ const settle = this.handOff;
103
+ if (settle) {
104
+ this.forgetFocus?.();
105
+ requestAnimationFrame(() => settle(true));
106
+ }
86
107
  }
87
108
  }
88
109
  __decorate([
@@ -0,0 +1,42 @@
1
+ import { nothing, type TemplateResult } from 'lit';
2
+ import type { HelixFormElement } from '../../helix-form-element/helix-form-element.js';
3
+ type Constructor<T> = new (...args: any[]) => T;
4
+ export declare class MixinPickerFeedbackInterface {
5
+ /**
6
+ * A message under the picker, such as what is wrong with the answer.
7
+ *
8
+ * While set, the picker is invalid and does not submit, as a field's
9
+ * `feedback` is, it is marked invalid to a reader and to CSS, and the
10
+ * controls a reader answers with are described by it.
11
+ */
12
+ feedback: string;
13
+ /**
14
+ * Whether the answer fails validation, marked on the controls a reader
15
+ * answers with and as `:state(invalid)`.
16
+ *
17
+ * A flag a field that wraps the picker sets, since that field owns the
18
+ * label, the hint and the message; on its own, `feedback` both marks the
19
+ * picker and says why.
20
+ */
21
+ invalid: boolean;
22
+ /** Whether a reader is told the answer is wrong: `invalid`, or `feedback`. */
23
+ protected get marked(): boolean;
24
+ /** The `feedback` line, or nothing while there is none. */
25
+ protected renderPickerFeedback(): TemplateResult | typeof nothing;
26
+ }
27
+ /**
28
+ * `feedback` and `invalid` for a picker that stands on its own as a form
29
+ * control: Color Picker, Date Picker and Time Picker.
30
+ *
31
+ * **One mark for both.** `invalid` is the flag a wrapping field sets, and
32
+ * `feedback` is the message a picker on its own shows; either one marks the
33
+ * picker invalid on its internals (`aria-invalid` on the host) and as
34
+ * `:state(invalid)`, and each picker marks the controls it draws by `marked`.
35
+ * Measured on Color Picker before this: `feedback` set `customError` in its
36
+ * validity while every control reported `invalid: false`.
37
+ *
38
+ * The message is the validity's too, as a field's `feedback` is, through
39
+ * `HelixFormElement`'s `validityFeedback`, so a form with one does not submit.
40
+ */
41
+ export declare const MixinPickerFeedback: <T extends Constructor<HelixFormElement>>(Base: T) => Constructor<MixinPickerFeedbackInterface> & T;
42
+ export {};
@@ -0,0 +1,46 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, nothing } from 'lit';
8
+ import { property } from 'lit/decorators.js';
9
+ import { hostAria } from '../../utils/host-aria/host-aria.js';
10
+ export const MixinPickerFeedback = (Base) => {
11
+ class PickerFeedbackElement extends Base {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.feedback = '';
15
+ this.invalid = false;
16
+ }
17
+ get marked() {
18
+ return this.invalid || this.feedback !== '';
19
+ }
20
+ get validityFeedback() {
21
+ return this.feedback;
22
+ }
23
+ willUpdate(changed) {
24
+ super.willUpdate(changed);
25
+ this.internals.ariaInvalid = this.marked ? 'true' : null;
26
+ this.toggleState('invalid', this.marked);
27
+ }
28
+ updated(changed) {
29
+ super.updated(changed);
30
+ const line = this.partNamed('feedback');
31
+ hostAria(this.internals, { describedBy: line ? [line] : [] });
32
+ }
33
+ renderPickerFeedback() {
34
+ return this.feedback === ''
35
+ ? nothing
36
+ : html `<p part="feedback" id="feedback">${this.feedback}</p>`;
37
+ }
38
+ }
39
+ __decorate([
40
+ property()
41
+ ], PickerFeedbackElement.prototype, "feedback", void 0);
42
+ __decorate([
43
+ property({ reflect: true, type: Boolean })
44
+ ], PickerFeedbackElement.prototype, "invalid", void 0);
45
+ return PickerFeedbackElement;
46
+ };
@@ -1,8 +1,10 @@
1
1
  import { PopoverController } from '../../controllers/popover-controller/popover-controller.js';
2
2
  import type { HelixFormElement } from '../../helix-form-element/helix-form-element.js';
3
+ import { type PickerVerdict } from '../../utils/verdict-flags/verdict-flags.js';
3
4
  import type { MixinControllerOpenInterface } from '../mixin-controller-open/mixin-controller-open.js';
4
5
  import type { MixinControllerValueInterface } from '../mixin-controller-value/mixin-controller-value.js';
5
6
  import type { MixinFieldInterface } from '../mixin-field/mixin-field.js';
7
+ export type { PickerVerdict } from '../../utils/verdict-flags/verdict-flags.js';
6
8
  type Constructor<T> = new (...args: any[]) => T;
7
9
  /**
8
10
  * What this is applied over: a form field that opens, holds a value and has a
@@ -99,16 +101,6 @@ export declare class MixinPickerFieldInterface {
99
101
  */
100
102
  protected validate(): PickerVerdict;
101
103
  }
102
- /**
103
- * What a picker field finds wrong: a message, reported as `badInput`, or the
104
- * validity flag to set and its message. Empty means nothing is wrong.
105
- */
106
- export type PickerVerdict = string | readonly [flag: keyof ValidityStateFlags, message: string];
107
- /**
108
- * A verdict as the flags and the message `setValidity` takes, or `null` where
109
- * there is nothing wrong.
110
- */
111
- export declare const verdictFlags: (verdict: PickerVerdict) => [flags: ValidityStateFlags, message: string] | null;
112
104
  /**
113
105
  * Grafts a floating picker onto a text field, and the protocol between them.
114
106
  *
@@ -166,4 +158,3 @@ export declare const verdictFlags: (verdict: PickerVerdict) => [flags: ValidityS
166
158
  * `sync`, which is not a protocol.
167
159
  */
168
160
  export declare const MixinPickerField: <T extends Constructor<PickerBase>>(Base: T) => Constructor<MixinPickerFieldInterface> & T;
169
- export {};
@@ -9,12 +9,7 @@ import { PopoverController } from '../../controllers/popover-controller/popover-
9
9
  import { submitImplicitly } from '../../utils/implicit-submit/implicit-submit.js';
10
10
  import { reportValues } from '../../utils/report-values/report-values.js';
11
11
  import { tabStops } from '../../utils/tab-stops/tab-stops.js';
12
- export const verdictFlags = (verdict) => {
13
- if (typeof verdict === 'string') {
14
- return verdict === '' ? null : [{ badInput: true }, verdict];
15
- }
16
- return [{ [verdict[0]]: true }, verdict[1]];
17
- };
12
+ import { verdictFlags } from '../../utils/verdict-flags/verdict-flags.js';
18
13
  export const MixinPickerField = (Base) => {
19
14
  class PickerFieldElement extends Base {
20
15
  constructor() {
@@ -4,7 +4,7 @@ import { type SegmentedKind, type SegmentOptions } from '../../utils/date-segmen
4
4
  import type { MixinControllerOpenInterface } from '../mixin-controller-open/mixin-controller-open.js';
5
5
  import type { MixinControllerValueInterface } from '../mixin-controller-value/mixin-controller-value.js';
6
6
  import type { MixinFieldInterface } from '../mixin-field/mixin-field.js';
7
- import { type MixinPickerFieldInterface } from '../mixin-picker-field/mixin-picker-field.js';
7
+ import type { MixinPickerFieldInterface } from '../mixin-picker-field/mixin-picker-field.js';
8
8
  type Constructor<T> = new (...args: any[]) => T;
9
9
  /** What this is applied over: a picker field, which `MixinPickerField` makes. */
10
10
  type SegmentedBase = HelixFormElement & MixinControllerOpenInterface & MixinControllerValueInterface & MixinFieldInterface & MixinPickerFieldInterface;
@@ -8,7 +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 { verdictFlags, } from '../mixin-picker-field/mixin-picker-field.js';
11
+ import { appleTouch } from '../../utils/platform/platform.js';
12
+ import { verdictFlags } from '../../utils/verdict-flags/verdict-flags.js';
12
13
  export const MixinSegmentedField = (Base) => {
13
14
  class SegmentedFieldElement extends Base {
14
15
  constructor() {
@@ -18,6 +19,7 @@ export const MixinSegmentedField = (Base) => {
18
19
  this.parts = {};
19
20
  this.typed = '';
20
21
  this.own = false;
22
+ this.touchApple = appleTouch(typeof navigator === 'undefined' ? undefined : navigator);
21
23
  this.entered = undefined;
22
24
  this.handleSegmentKeydown = (event) => {
23
25
  const element = event.currentTarget;
@@ -213,20 +215,22 @@ export const MixinSegmentedField = (Base) => {
213
215
  const empty = shown === undefined;
214
216
  const id = `${this.controlId}-${kind}`;
215
217
  const editable = !this.isDisabled && !this.readOnly;
218
+ const spin = !this.touchApple;
216
219
  return html `<span
217
220
  part="segment${empty ? ' segment-placeholder' : ''}"
218
221
  id=${id}
219
222
  data-segment=${kind}
220
- role="spinbutton"
223
+ role=${spin ? 'spinbutton' : 'textbox'}
221
224
  tabindex=${this.isDisabled ? '-1' : '0'}
222
225
  inputmode=${kind === 'dayPeriod' ? nothing : 'numeric'}
223
226
  enterkeyhint=${editable ? 'next' : nothing}
224
227
  aria-label=${this.labeled ? `${segmentName(kind, locale)},` : segmentName(kind, locale)}
225
228
  aria-labelledby=${this.labeled ? `${id} ${this.labelId}` : nothing}
226
- aria-valuemin=${min}
227
- aria-valuemax=${max}
228
- aria-valuenow=${shown ?? nothing}
229
- aria-valuetext=${empty ? this.emptySegmentLabel : segmentValueText(kind, this.parts, twelve, locale)}
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}
230
234
  aria-disabled=${this.isDisabled ? 'true' : nothing}
231
235
  aria-readonly=${this.readOnly ? 'true' : nothing}
232
236
  @keydown=${this.handleSegmentKeydown}
@@ -286,27 +286,28 @@ export const MixinViewport = (Base) => {
286
286
  if (!pan && !zoom && !fullscreen && more === nothing) {
287
287
  return nothing;
288
288
  }
289
+ const [up, start, end, down] = ['up', 'start', 'end', 'down'].map((way) => this.panGlyph(way));
289
290
  return html `<div part="controls" role="group" aria-label=${this.controlsLabel ?? this.restingControlsLabel}>
290
291
  ${pan
291
292
  ? html `<button part="pan-up" aria-label=${this.panLabel('up')} type="button" @click=${() => this.pan('up')}>
292
- ${this.panGlyph('up')}
293
+ <slot name="pan-up-icon">${up}</slot>
293
294
  </button>
294
295
  <button part="pan-start" aria-label=${this.panLabel('start')} type="button" @click=${() => this.pan('start')}>
295
- ${this.panGlyph('start')}
296
+ <slot name="pan-start-icon">${start}</slot>
296
297
  </button>
297
298
  <button part="pan-end" aria-label=${this.panLabel('end')} type="button" @click=${() => this.pan('end')}>
298
- ${this.panGlyph('end')}
299
+ <slot name="pan-end-icon">${end}</slot>
299
300
  </button>
300
301
  <button part="pan-down" aria-label=${this.panLabel('down')} type="button" @click=${() => this.pan('down')}>
301
- ${this.panGlyph('down')}
302
+ <slot name="pan-down-icon">${down}</slot>
302
303
  </button>`
303
304
  : nothing}
304
305
  ${zoom
305
306
  ? html `<button part="zoom-in" aria-label=${this.zoomInLabel} type="button" @click=${() => this.zoom(1)}>
306
- +
307
+ <slot name="zoom-in-icon">+</slot>
307
308
  </button>
308
309
  <button part="zoom-out" aria-label=${this.zoomOutLabel} type="button" @click=${() => this.zoom(-1)}>
309
- −
310
+ <slot name="zoom-out-icon">−</slot>
310
311
  </button>`
311
312
  : nothing}
312
313
  ${more}
@@ -318,7 +319,7 @@ export const MixinViewport = (Base) => {
318
319
  type="button"
319
320
  @click=${this.toggleFullscreen}
320
321
  >
321
- ⤢
322
+ <slot name="fullscreen-icon">⤢</slot>
322
323
  </button>`
323
324
  : nothing}
324
325
  </div>`;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Sends each child to the slot it names, and every other child to the default
3
+ * slot, in a shadow root that assigns its slots by hand.
4
+ *
5
+ * **A root that assigns by hand routes nothing by itself**, its named slots
6
+ * included, so a header, a footer or an empty state slotted by name reaches
7
+ * nothing unless it is assigned here too. `place` says where a child goes when
8
+ * the host decides it, a row to its list or a card to the slot the layout drew
9
+ * for it, and a child it gives no slot to goes where its `slot` attribute says,
10
+ * as it would under the default assignment.
11
+ *
12
+ * **A slot already holding exactly what it would be given is left alone**, so
13
+ * calling this after every update fires no `slotchange` that nothing changed.
14
+ *
15
+ * Pair it with `ChildrenController`, which calls back when a child arrives
16
+ * after the first render, the case no `slotchange` reports.
17
+ */
18
+ export declare const assignSlots: (root: ParentNode | null | undefined, children: Iterable<Element>, place?: (child: Element) => string | undefined) => void;
@@ -0,0 +1,14 @@
1
+ export const assignSlots = (root, children, place = () => undefined) => {
2
+ const named = new Map();
3
+ for (const child of children) {
4
+ const name = place(child) ?? child.getAttribute('slot') ?? '';
5
+ named.set(name, [...(named.get(name) ?? []), child]);
6
+ }
7
+ for (const slot of root?.querySelectorAll?.('slot') ?? []) {
8
+ const wanted = named.get(slot.name) ?? [];
9
+ const had = slot.assignedNodes();
10
+ if (had.length !== wanted.length || had.some((one, at) => one !== wanted[at])) {
11
+ slot.assign?.(...wanted);
12
+ }
13
+ }
14
+ };
@@ -1,7 +1,12 @@
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
@@ -23,7 +23,7 @@ const NAMED_BY_CONTENT = new Set([
23
23
  'tab',
24
24
  ]);
25
25
  export const hasName = (element, shown) => {
26
- for (const attribute of ['aria-label', 'title', 'placeholder']) {
26
+ for (const attribute of ['aria-label', 'title']) {
27
27
  if (element.getAttribute(attribute)?.trim()) {
28
28
  return true;
29
29
  }
@@ -40,9 +40,15 @@ export const hasName = (element, shown) => {
40
40
  if ([...(labels ?? [])].some((label) => nameText(label).trim() !== '')) {
41
41
  return true;
42
42
  }
43
- const role = element.getAttribute('role') ?? (element.localName === 'button' ? 'button' : '');
43
+ const role = element.getAttribute('role') ?? implicitRole(element);
44
44
  return NAMED_BY_CONTENT.has(role) && nameText(element, shown).trim() !== '';
45
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' : '';
51
+ };
46
52
  const audited = new WeakSet();
47
53
  const waiting = new Map();
48
54
  const readWaiting = () => {
@@ -69,9 +75,12 @@ export const auditName = (host, control, fix, also, shown) => {
69
75
  if (also?.() || hasName(host) || (inner !== null && hasName(inner, value))) {
70
76
  return;
71
77
  }
78
+ const placeholder = [host, inner].some((one) => one?.getAttribute('placeholder')?.trim());
72
79
  reportRuntime({
73
80
  kind: 'missing-name',
74
- 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}`,
75
84
  tag: host.localName,
76
85
  });
77
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;