@fusion.dev/helix-core 0.146.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.
- package/custom-elements.json +1299 -60
- package/dist/controllers/aria-forward-controller/aria-forward-controller.js +5 -3
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +6 -0
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +13 -0
- package/dist/controllers/copy-controller/copy-controller.d.ts +4 -1
- package/dist/controllers/copy-controller/copy-controller.js +2 -1
- package/dist/controllers/countdown-controller/countdown-controller.d.ts +4 -1
- package/dist/controllers/countdown-controller/countdown-controller.js +3 -1
- package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +5 -0
- package/dist/controllers/source-controller/source-controller.js +2 -0
- package/dist/controllers/swipe-controller/swipe-controller.d.ts +10 -1
- package/dist/controllers/swipe-controller/swipe-controller.js +1 -1
- package/dist/controllers/virtualize-controller/virtualize-controller.js +8 -6
- package/dist/events/band.d.ts +13 -0
- package/dist/events/band.js +11 -0
- package/dist/events/details.d.ts +5 -0
- package/dist/events/events.d.ts +4 -2
- package/dist/events/events.js +3 -1
- package/dist/events/names.d.ts +3 -0
- package/dist/events/names.js +13 -88
- package/dist/helix-element/helix-element.js +9 -43
- package/dist/helix-element/react-bridge.d.ts +13 -0
- package/dist/helix-element/react-bridge.js +1 -1
- package/dist/index.d.ts +18 -9
- package/dist/index.js +18 -9
- package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +7 -0
- package/dist/mixins/mixin-chart-source/mixin-chart-source.js +1 -0
- package/dist/mixins/mixin-dismissible/mixin-dismissible.js +25 -4
- package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.d.ts +42 -0
- package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.js +46 -0
- package/dist/mixins/mixin-picker-field/mixin-picker-field.d.ts +2 -11
- package/dist/mixins/mixin-picker-field/mixin-picker-field.js +1 -6
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.d.ts +1 -1
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +10 -6
- package/dist/utils/audit-name/audit-name.d.ts +7 -2
- package/dist/utils/audit-name/audit-name.js +12 -3
- package/dist/utils/audit-source/audit-source-off.d.ts +10 -0
- package/dist/utils/audit-source/audit-source-off.js +1 -0
- package/dist/utils/audit-source/audit-source.d.ts +19 -0
- package/dist/utils/audit-source/audit-source.js +27 -0
- package/dist/utils/call-listener/call-listener.d.ts +16 -0
- package/dist/utils/call-listener/call-listener.js +17 -0
- package/dist/utils/chord/chord.d.ts +14 -0
- package/dist/utils/chord/chord.js +1 -0
- package/dist/utils/clamp/clamp.d.ts +7 -0
- package/dist/utils/clamp/clamp.js +1 -0
- package/dist/utils/css-color/css-color.js +1 -1
- package/dist/utils/elapsed-time/elapsed-time.d.ts +1 -1
- package/dist/utils/elapsed-time/elapsed-time.js +2 -5
- package/dist/utils/host-words/host-words.d.ts +16 -0
- package/dist/utils/host-words/host-words.js +13 -0
- package/dist/utils/load-more/load-more.d.ts +25 -0
- package/dist/utils/load-more/load-more.js +1 -0
- package/dist/utils/locale-of/locale-of.d.ts +18 -0
- package/dist/utils/locale-of/locale-of.js +26 -0
- package/dist/utils/nearest/nearest.d.ts +9 -0
- package/dist/utils/nearest/nearest.js +9 -0
- package/dist/utils/number-format/number-format.d.ts +9 -0
- package/dist/utils/number-format/number-format.js +4 -0
- package/dist/utils/own-rule/own-rule.d.ts +16 -0
- package/dist/utils/own-rule/own-rule.js +7 -0
- package/dist/utils/platform/platform.d.ts +8 -0
- package/dist/utils/platform/platform.js +1 -0
- package/dist/utils/read-series/read-series.d.ts +14 -0
- package/dist/utils/read-series/read-series.js +15 -0
- package/dist/utils/relative-time/relative-time.d.ts +8 -0
- package/dist/utils/relative-time/relative-time.js +5 -2
- package/dist/utils/report-render/report-render.js +2 -14
- package/dist/utils/report-runtime/report-runtime.d.ts +5 -1
- package/dist/utils/report-runtime/report-runtime.js +2 -14
- package/dist/utils/report-usage/report-usage.js +2 -14
- package/dist/utils/scroll-item-into-view/scroll-item-into-view.d.ts +33 -0
- package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +13 -3
- package/dist/utils/slotted-glyph/slotted-glyph.d.ts +33 -0
- package/dist/utils/slotted-glyph/slotted-glyph.js +27 -0
- package/dist/utils/typeahead/typeahead.d.ts +8 -0
- package/dist/utils/typeahead/typeahead.js +1 -0
- package/dist/utils/verdict-flags/verdict-flags.d.ts +13 -0
- package/dist/utils/verdict-flags/verdict-flags.js +6 -0
- package/dist/utils/written-list/written-list.d.ts +31 -0
- package/dist/utils/written-list/written-list.js +16 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +15 -4
package/dist/index.js
CHANGED
|
@@ -30,10 +30,10 @@ export { SwipeController, } from './controllers/swipe-controller/swipe-controlle
|
|
|
30
30
|
export { TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
|
|
31
31
|
export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
|
|
32
32
|
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';
|
|
33
|
+
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
34
|
export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
|
|
35
35
|
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';
|
|
36
|
+
export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
|
|
37
37
|
export { MixinCollection, } from './mixins/mixin-collection/mixin-collection.js';
|
|
38
38
|
export { MixinControllerActive, } from './mixins/mixin-controller-active/mixin-controller-active.js';
|
|
39
39
|
export { MixinControllerChecked, } from './mixins/mixin-controller-checked/mixin-controller-checked.js';
|
|
@@ -42,6 +42,7 @@ export { MixinControllerValue, } from './mixins/mixin-controller-value/mixin-con
|
|
|
42
42
|
export { MixinDismissible, } from './mixins/mixin-dismissible/mixin-dismissible.js';
|
|
43
43
|
export { MixinField } from './mixins/mixin-field/mixin-field.js';
|
|
44
44
|
export { MixinPickerEditing, } from './mixins/mixin-picker-editing/mixin-picker-editing.js';
|
|
45
|
+
export { MixinPickerFeedback, } from './mixins/mixin-picker-feedback/mixin-picker-feedback.js';
|
|
45
46
|
export { MixinPickerField, } from './mixins/mixin-picker-field/mixin-picker-field.js';
|
|
46
47
|
export { MixinSegmentedField, } from './mixins/mixin-segmented-field/mixin-segmented-field.js';
|
|
47
48
|
export { MixinSelectableItem, } from './mixins/mixin-selectable-item/mixin-selectable-item.js';
|
|
@@ -51,7 +52,8 @@ export { anchorElement } from './utils/anchor-element/anchor-element.js';
|
|
|
51
52
|
export { arrowReach, sideOf } from './utils/arrow/arrow.js';
|
|
52
53
|
export { addDays, addMonths, barredBy, localToday, monthOf, monthOut, periodCells, periodKey, periodMove, sameMonth, weekStartOf, YEARS_SHOWN, yearOut, yearPageOf, } from './utils/calendar/calendar.js';
|
|
53
54
|
export { capturePointer } from './utils/capture-pointer/capture-pointer.js';
|
|
54
|
-
export { ariaChord, chordParts, matchesChord, printableChord, } from './utils/chord/chord.js';
|
|
55
|
+
export { ariaChord, chordParts, matchesChord, printableChord, selectsAll, } from './utils/chord/chord.js';
|
|
56
|
+
export { clamp } from './utils/clamp/clamp.js';
|
|
55
57
|
export { clockLocale, dayPeriod, isTwelveHour, nearestTime, offeredTimes, timeBarred, timeFault, wheelParts, wholeHour, } from './utils/clock/clock.js';
|
|
56
58
|
export { closestInstance } from './utils/closest-instance/closest-instance.js';
|
|
57
59
|
export { colorName, hueName } from './utils/color-name/color-name.js';
|
|
@@ -72,22 +74,28 @@ export { formatNumbers } from './utils/format-numbers/format-numbers.js';
|
|
|
72
74
|
export { headingIn, headingsIn } from './utils/heading-in/heading-in.js';
|
|
73
75
|
export { headingLevel } from './utils/heading-level/heading-level.js';
|
|
74
76
|
export { hostAria } from './utils/host-aria/host-aria.js';
|
|
77
|
+
export { hostWords } from './utils/host-words/host-words.js';
|
|
75
78
|
export { defaultButton, submitImplicitly, submits, submitsOnEnter, } from './utils/implicit-submit/implicit-submit.js';
|
|
76
79
|
export { forgetDisabled, inheritDisabled, } from './utils/inherit-disabled/inherit-disabled.js';
|
|
77
80
|
export { inlineStep } from './utils/inline-step/inline-step.js';
|
|
78
81
|
export { isRtl } from './utils/is-rtl/is-rtl.js';
|
|
79
82
|
export { keyClaimed } from './utils/key-claimed/key-claimed.js';
|
|
80
83
|
export { linePath } from './utils/line-path/line-path.js';
|
|
84
|
+
export { endInSight } from './utils/load-more/load-more.js';
|
|
85
|
+
export { localeOf } from './utils/locale-of/locale-of.js';
|
|
81
86
|
export { markRegion } from './utils/mark-region/mark-region.js';
|
|
82
87
|
export { copiesOf, sameCopies, } from './utils/media-copy/media-copy.js';
|
|
83
|
-
export {
|
|
88
|
+
export { nameText } from './utils/name-text/name-text.js';
|
|
89
|
+
export { nearest } from './utils/nearest/nearest.js';
|
|
90
|
+
export { formatNumber, parseNumber, readingText } from './utils/number-format/number-format.js';
|
|
84
91
|
export { onUnlessFalse } from './utils/on-unless-false/on-unless-false.js';
|
|
92
|
+
export { applyOwnRule } from './utils/own-rule/own-rule.js';
|
|
85
93
|
export { plainClick } from './utils/plain-click/plain-click.js';
|
|
86
|
-
export { appleTouch, onApple } from './utils/platform/platform.js';
|
|
94
|
+
export { appleTouch, onAndroid, onApple } from './utils/platform/platform.js';
|
|
87
95
|
export { pressType } from './utils/press-type/press-type.js';
|
|
88
96
|
export { rangeAdd } from './utils/range-add/range-add.js';
|
|
89
97
|
export { readColor, rgbOf } from './utils/read-color/read-color.js';
|
|
90
|
-
export { byRow, readRows, readSeries, seriesKey, unbroken, } from './utils/read-series/read-series.js';
|
|
98
|
+
export { byRow, extremesOf, readRows, readSeries, seriesKey, unbroken, } from './utils/read-series/read-series.js';
|
|
91
99
|
export { linkDescription, reflectElements, unlinkDescription, } from './utils/reflect-elements/reflect-elements.js';
|
|
92
100
|
export { relativeTime, } from './utils/relative-time/relative-time.js';
|
|
93
101
|
export { measuring, RENDER_SLOT, reportRender } from './utils/report-render/report-render.js';
|
|
@@ -102,9 +110,10 @@ export { valueAt } from './utils/row-data/row-data.js';
|
|
|
102
110
|
export { arranged, cycle, filter, format, ordered, parse, sort, window_, } from './utils/row-order/row-order.js';
|
|
103
111
|
export { extent, linear } from './utils/scale/scale.js';
|
|
104
112
|
export { ticks } from './utils/scale/ticks.js';
|
|
105
|
-
export { scrollItemIntoView, } from './utils/scroll-item-into-view/scroll-item-into-view.js';
|
|
113
|
+
export { scrollItemIntoView, scrollingAncestor, } from './utils/scroll-item-into-view/scroll-item-into-view.js';
|
|
106
114
|
export { lockScroll, scrollHolders, unlockScroll } from './utils/scroll-lock/scroll-lock.js';
|
|
107
115
|
export { slotFilled } from './utils/slot-filled/slot-filled.js';
|
|
116
|
+
export { SlottedGlyph } from './utils/slotted-glyph/slotted-glyph.js';
|
|
108
117
|
export { slottedWords } from './utils/slotted-words/slotted-words.js';
|
|
109
118
|
export { splitValues } from './utils/split-values/split-values.js';
|
|
110
119
|
export { edgeOffset, FLING, parseSnapPoints, settleSwipe, snapTravel, swipeAxis, swipeEdge, swipeStep, towardEdge, } from './utils/swipe/swipe.js';
|
|
@@ -112,10 +121,10 @@ export { tellDisclosure } from './utils/tell-disclosure/tell-disclosure.js';
|
|
|
112
121
|
export { subscribe } from './utils/ticker/ticker.js';
|
|
113
122
|
export { TONE_MARKS, toneMark, } from './utils/tone-marks/tone-marks.js';
|
|
114
123
|
export { treeArrow } from './utils/tree-arrow/tree-arrow.js';
|
|
115
|
-
export { Typeahead, typeaheadBy, typesCharacter, } from './utils/typeahead/typeahead.js';
|
|
124
|
+
export { Typeahead, typeaheadBy, typeaheadByWords, typesCharacter, } from './utils/typeahead/typeahead.js';
|
|
116
125
|
export { dateAsValue, isClockValue, isDateValue, isTimeValue, minutesAsValue, numberAsValue, secondsAsValue, timeAsValue, valueAsDate, valueAsMinutes, valueAsNumber, valueAsSeconds, valueAsTime, } from './utils/value-as/value-as.js';
|
|
117
126
|
export { watchTheme } from './utils/watch-theme/watch-theme.js';
|
|
118
127
|
export { wordsConverter } from './utils/words-converter/words-converter.js';
|
|
119
128
|
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';
|
|
129
|
+
export { anchorAt, commaList, everyState, inRowOrder, pressedValue, prunedValue, toggleEvery, toggleValue, writtenList, writtenNumbers, } from './utils/written-list/written-list.js';
|
|
121
130
|
export { VERSION } from './version.js';
|
|
@@ -187,6 +187,13 @@ export declare class MixinChartSourceInterface {
|
|
|
187
187
|
*/
|
|
188
188
|
pointer: ChartPointerController;
|
|
189
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* The words a chart says a reading's place in by default, such as "2 of 12":
|
|
192
|
+
* every chart's `position-label`, and Sparkline's, which is no chart source.
|
|
193
|
+
* The property keeps the words written out, which is what its reference page
|
|
194
|
+
* shows as the default; a spec holds the two together.
|
|
195
|
+
*/
|
|
196
|
+
export declare const POSITION_LABEL = "{position} of {count}";
|
|
190
197
|
/**
|
|
191
198
|
* The half of a chart that is about finding its numbers rather than drawing.
|
|
192
199
|
*
|
|
@@ -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() {
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
|
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-
|
|
227
|
-
aria-
|
|
228
|
-
aria-
|
|
229
|
-
aria-
|
|
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}
|
|
@@ -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>`,
|
|
4
|
-
*
|
|
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'
|
|
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
|
|
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:
|
|
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;
|
|
@@ -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
|
+
};
|
|
@@ -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 @@
|
|
|
1
|
+
export const clamp = (value, low, high) => Math.min(Math.max(value, low), high);
|
|
@@ -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,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
|
+
};
|