@fusion.dev/helix-headless 0.145.0 → 0.146.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 +7373 -3849
- package/dist/accordion/item/accordion-item.d.ts +14 -0
- package/dist/accordion/item/accordion-item.js +16 -6
- package/dist/accordion/root/accordion-root.d.ts +8 -5
- package/dist/announcement/root/announcement-root.d.ts +3 -2
- package/dist/announcement/root/announcement-root.js +3 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +25 -3
- package/dist/chat/root/chat-root.js +22 -5
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -1
- package/dist/code-block/root/code-block-root.js +58 -3
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +5 -0
- package/dist/copy-button/root/copy-button-root.js +10 -3
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +20 -52
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +21 -3
- package/dist/element-events.generated.js +31 -5
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +1 -1
- package/dist/input/root/input-root.d.ts +12 -2
- package/dist/input/root/input-root.js +11 -2
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +62 -13
- package/dist/list/root/list-root.js +70 -13
- package/dist/list/selection.d.ts +37 -7
- package/dist/list/selection.js +16 -7
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -3
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/root/megamenu-root.d.ts +51 -10
- package/dist/megamenu/root/megamenu-root.js +76 -5
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +47 -23
- package/dist/menu/root/menu-root.d.ts +14 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +10 -3
- package/dist/notifications/root/notifications-root.js +19 -7
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
- package/dist/object-inspector/root/object-inspector-root.js +117 -76
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/root/outline-root.d.ts +18 -0
- package/dist/outline/root/outline-root.js +23 -5
- package/dist/pagination/size/pagination-size.d.ts +1 -0
- package/dist/pagination/size/pagination-size.js +1 -1
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +9 -4
- package/dist/rating/root/rating-root.js +31 -7
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -0
- package/dist/scroll-area/scrollbar.js +9 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +7 -12
- package/dist/splitter/root/splitter-root.js +209 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +49 -3
- package/dist/steps/root/steps-root.js +44 -5
- package/dist/steps/step/step.d.ts +7 -0
- package/dist/steps/step/step.js +7 -2
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +0 -10
- package/dist/table/column/table-column.js +3 -19
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +2 -13
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +12 -0
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +14 -1
- package/dist/toast/item/toast-item.js +22 -5
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/video-root.d.ts +18 -5
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
- package/dist/virtual-list/fill.d.ts +0 -8
- package/dist/virtual-list/fill.js +1 -17
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
- package/dist/virtual-list/root/virtual-list-root.js +183 -40
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +4577 -835
- package/types/vue.d.ts +926 -168
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -4,11 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { commaList, customElement, HelixBeforeChangeEvent, HelixElement, hostAria, KeyboardNavigationController, requestChange, rovingStop, slottedWords, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html } from 'lit';
|
|
7
|
+
import { commaList, customElement, deepActiveElement, deepContains, HelixBeforeChangeEvent, HelixElement, hostAria, KeyboardNavigationController, pressedValue, prunedValue, requestChange, rovingStop, slottedWords, typeaheadBy, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessTag } from '../root/tag-root.js';
|
|
11
|
-
import { pressedValue } from '../selection.js';
|
|
12
11
|
let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
13
12
|
constructor() {
|
|
14
13
|
super(...arguments);
|
|
@@ -18,7 +17,7 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
18
17
|
items: () => this.reachable.map((tag) => this.navigable(tag)),
|
|
19
18
|
origin: 'focus',
|
|
20
19
|
selects: () => false,
|
|
21
|
-
typeahead: (item) => item.words,
|
|
20
|
+
typeahead: typeaheadBy((item) => item.words),
|
|
22
21
|
wrap: false,
|
|
23
22
|
});
|
|
24
23
|
this.handleKeydown = (event) => {
|
|
@@ -53,6 +52,37 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
53
52
|
this.press(tag);
|
|
54
53
|
}
|
|
55
54
|
};
|
|
55
|
+
this.handleDismiss = (event) => {
|
|
56
|
+
const tag = this.tagOf(event);
|
|
57
|
+
if (!tag) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const had = deepContains(this, deepActiveElement());
|
|
61
|
+
const settle = async () => {
|
|
62
|
+
if (event.defaultPrevented || tag.isConnected) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const left = this.tags.map((one) => this.valueFor(one));
|
|
66
|
+
const pruned = prunedValue(this.value, this.valueFor(tag), left);
|
|
67
|
+
if (pruned !== this.value) {
|
|
68
|
+
this.value = pruned;
|
|
69
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
70
|
+
}
|
|
71
|
+
const active = document.activeElement;
|
|
72
|
+
if (!had || this.tags.length > 0 || (active !== null && active !== document.body)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this.requestUpdate();
|
|
76
|
+
await this.updateComplete;
|
|
77
|
+
this.renderRoot.querySelector('[part~="empty"]')?.focus();
|
|
78
|
+
};
|
|
79
|
+
queueMicrotask(() => void settle());
|
|
80
|
+
requestAnimationFrame(() => void settle());
|
|
81
|
+
};
|
|
82
|
+
this.handleSlotchange = () => {
|
|
83
|
+
this.sync();
|
|
84
|
+
this.requestUpdate();
|
|
85
|
+
};
|
|
56
86
|
this.handleFocusin = (event) => {
|
|
57
87
|
const tag = this.tagOf(event);
|
|
58
88
|
if (tag && tag !== this.last) {
|
|
@@ -122,24 +152,33 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
122
152
|
this.addEventListener('keydown', this.handleKeydown);
|
|
123
153
|
this.addEventListener('click', this.handleClick);
|
|
124
154
|
this.addEventListener('focusin', this.handleFocusin);
|
|
155
|
+
this.addEventListener('helix-dismiss', this.handleDismiss);
|
|
125
156
|
}
|
|
126
157
|
disconnectedCallback() {
|
|
127
158
|
super.disconnectedCallback();
|
|
128
159
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
129
160
|
this.removeEventListener('click', this.handleClick);
|
|
130
161
|
this.removeEventListener('focusin', this.handleFocusin);
|
|
162
|
+
this.removeEventListener('helix-dismiss', this.handleDismiss);
|
|
163
|
+
}
|
|
164
|
+
get empty() {
|
|
165
|
+
return this.childrenKnown && this.tags.length === 0;
|
|
131
166
|
}
|
|
132
167
|
willUpdate(changed) {
|
|
133
168
|
super.willUpdate(changed);
|
|
134
|
-
|
|
135
|
-
this.internals
|
|
169
|
+
const empty = this.empty;
|
|
170
|
+
hostAria(this.internals, { label: this.label, role: empty ? 'group' : 'grid' });
|
|
171
|
+
this.internals.ariaMultiSelectable = this.selectionMode === 'multiple' && !empty ? 'true' : null;
|
|
136
172
|
}
|
|
137
173
|
updated(changed) {
|
|
138
174
|
super.updated(changed);
|
|
139
175
|
this.sync();
|
|
140
176
|
}
|
|
141
177
|
render() {
|
|
142
|
-
|
|
178
|
+
const empty = this.empty
|
|
179
|
+
? html `<div part="empty" tabindex="-1"><slot name="empty"></slot></div>`
|
|
180
|
+
: nothing;
|
|
181
|
+
return html `<slot @slotchange=${this.handleSlotchange}></slot>${empty}`;
|
|
143
182
|
}
|
|
144
183
|
};
|
|
145
184
|
__decorate([
|
|
@@ -36,7 +36,10 @@ let HelixHeadlessTag = class HelixHeadlessTag extends MixinDismissible(HelixElem
|
|
|
36
36
|
}
|
|
37
37
|
willUpdate(changed) {
|
|
38
38
|
super.willUpdate(changed);
|
|
39
|
-
hostAria(this.internals, {
|
|
39
|
+
hostAria(this.internals, {
|
|
40
|
+
label: this.grouped ? this.words : '',
|
|
41
|
+
role: this.grouped ? 'row' : '',
|
|
42
|
+
});
|
|
40
43
|
this.internals.ariaSelected = this.selected === undefined ? null : String(this.selected);
|
|
41
44
|
this.internals.ariaDisabled = this.disabled ? 'true' : null;
|
|
42
45
|
this.toggleState('selected', this.selected === true);
|
|
@@ -58,7 +61,11 @@ let HelixHeadlessTag = class HelixHeadlessTag extends MixinDismissible(HelixElem
|
|
|
58
61
|
render() {
|
|
59
62
|
const content = html `<slot name="start" part="start"></slot>${this.renderLabel()}${this.dismissible ? this.renderDismiss() : nothing}`;
|
|
60
63
|
return this.grouped
|
|
61
|
-
? html `<span
|
|
64
|
+
? html `<span
|
|
65
|
+
aria-label=${this.words || nothing}
|
|
66
|
+
part="cell"
|
|
67
|
+
role="gridcell"
|
|
68
|
+
tabindex=${this.focusable ? '0' : '-1'}
|
|
62
69
|
>${content}</span
|
|
63
70
|
>`
|
|
64
71
|
: content;
|
|
@@ -17,6 +17,11 @@ declare const HelixHeadlessTextarea_base: (new (...args: any[]) => import("@fusi
|
|
|
17
17
|
* `max-rows` stops the growth at that many lines, and the field scrolls past
|
|
18
18
|
* them.
|
|
19
19
|
*
|
|
20
|
+
* `clearable` draws a button that empties the field while it holds text, and
|
|
21
|
+
* sends `helix-clear`, as `Input` does. `validate` adds your own rule, run on
|
|
22
|
+
* every change once the browser finds nothing wrong, as React Aria's
|
|
23
|
+
* TextField `validate` does.
|
|
24
|
+
*
|
|
20
25
|
* @since 0.1.0
|
|
21
26
|
* @status stable
|
|
22
27
|
* @category forms
|
|
@@ -31,15 +36,18 @@ declare const HelixHeadlessTextarea_base: (new (...args: any[]) => import("@fusi
|
|
|
31
36
|
*
|
|
32
37
|
* @event {Event} change - Sent from the textarea when the user finishes an edit.
|
|
33
38
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired as the text changes, and cancelable.
|
|
39
|
+
* @event {HelixClearEvent} helix-clear - Fired after the clear button has emptied the field, after `input` and `change`.
|
|
34
40
|
* @event {Event} input - Fired after the value changes.
|
|
35
41
|
*
|
|
42
|
+
* @csspart clear - The button that empties the field, under `clearable`.
|
|
36
43
|
* @csspart control - The textarea itself.
|
|
37
44
|
* @csspart feedback - The message that says what is wrong.
|
|
38
45
|
* @csspart field - The box that holds the textarea.
|
|
39
46
|
* @csspart hint - Help under the field, while nothing is wrong.
|
|
40
47
|
* @csspart label - The label above the field.
|
|
41
48
|
*
|
|
42
|
-
* @cssstate
|
|
49
|
+
* @cssstate blank - The field holds no text.
|
|
50
|
+
* @cssstate invalid - The control has an error to show, from the browser's validation, `validate`, or your `feedback`.
|
|
43
51
|
*/
|
|
44
52
|
export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
45
53
|
protected readonly aria: AriaForwardController;
|
|
@@ -57,6 +65,14 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
|
57
65
|
* Grows the box to fit its content, so it does not scroll.
|
|
58
66
|
*/
|
|
59
67
|
autoGrow: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Draws a button that empties the field while it holds text.
|
|
70
|
+
*/
|
|
71
|
+
clearable: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* The accessible name of the clear button, which shows only an icon.
|
|
74
|
+
*/
|
|
75
|
+
clearLabel: string;
|
|
60
76
|
/**
|
|
61
77
|
* How many characters wide the box is, when the layout does not set its
|
|
62
78
|
* width.
|
|
@@ -194,6 +210,11 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
|
194
210
|
focus(options?: FocusOptions): void;
|
|
195
211
|
/** Reports the value and the validity the host stands behind. */
|
|
196
212
|
private sync;
|
|
213
|
+
/**
|
|
214
|
+
* Empties the field and puts the caret back in it, through `requestValue`,
|
|
215
|
+
* so a consumer who owns the value can refuse. `Input` clears the same way.
|
|
216
|
+
*/
|
|
217
|
+
private readonly handleClear;
|
|
197
218
|
connectedCallback(): void;
|
|
198
219
|
disconnectedCallback(): void;
|
|
199
220
|
protected firstUpdated(changed: PropertyValues): void;
|
|
@@ -212,6 +233,12 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
|
212
233
|
* How many lines the box is before anything is typed.
|
|
213
234
|
*/
|
|
214
235
|
rows: number;
|
|
236
|
+
/**
|
|
237
|
+
* Your own rule for the value, run on every change once the browser finds
|
|
238
|
+
* nothing wrong. Return a message, or a list of them, to mark the field
|
|
239
|
+
* invalid, and `true`, `null`, or nothing to accept the value.
|
|
240
|
+
*/
|
|
241
|
+
validate?: (value: string) => string | string[] | true | null | undefined;
|
|
215
242
|
/**
|
|
216
243
|
* How the browser wraps the text, and whether the breaks are submitted with
|
|
217
244
|
* it.
|
|
@@ -4,7 +4,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, customElement, HelixFormElement, holdCaret, isRtl, MixinControllerValue, MixinField, restoreValue, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, drawIcon, HelixClearEvent, HelixFormElement, holdCaret, isRtl, MixinControllerValue, MixinField, restoreValue, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { x } from '@fusion.dev/helix-icons';
|
|
8
9
|
import { html, nothing } from 'lit';
|
|
9
10
|
import { property } from 'lit/decorators.js';
|
|
10
11
|
import { grownHeight, lineMetrics } from '../grow.js';
|
|
@@ -17,6 +18,8 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
17
18
|
this.announcesInput = true;
|
|
18
19
|
this.autocomplete = '';
|
|
19
20
|
this.autoGrow = false;
|
|
21
|
+
this.clearable = false;
|
|
22
|
+
this.clearLabel = 'Clear';
|
|
20
23
|
this.dirName = '';
|
|
21
24
|
this.placeholder = '';
|
|
22
25
|
this.readOnly = false;
|
|
@@ -32,6 +35,17 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
32
35
|
event.stopPropagation();
|
|
33
36
|
this.announceChange();
|
|
34
37
|
};
|
|
38
|
+
this.handleClear = () => {
|
|
39
|
+
if (this.value !== '' && this.requestValue('')) {
|
|
40
|
+
this.announceChange();
|
|
41
|
+
this.dispatchEvent(new HelixClearEvent());
|
|
42
|
+
}
|
|
43
|
+
const control = this.control;
|
|
44
|
+
if (control) {
|
|
45
|
+
restoreValue(control, this.value);
|
|
46
|
+
control.focus();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
35
49
|
this.rows = 3;
|
|
36
50
|
this.wrap = 'soft';
|
|
37
51
|
}
|
|
@@ -112,6 +126,11 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
112
126
|
return;
|
|
113
127
|
}
|
|
114
128
|
this.copyValidity(control);
|
|
129
|
+
const own = control.validity.valid ? this.validate?.(this.value) : undefined;
|
|
130
|
+
const message = Array.isArray(own) ? own.join(' ') : typeof own === 'string' ? own : '';
|
|
131
|
+
if (message !== '') {
|
|
132
|
+
this.internals.setValidity({ customError: true }, message, control);
|
|
133
|
+
}
|
|
115
134
|
this.refreshFeedback();
|
|
116
135
|
}
|
|
117
136
|
connectedCallback() {
|
|
@@ -140,6 +159,7 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
140
159
|
}
|
|
141
160
|
willUpdate(changed) {
|
|
142
161
|
super.willUpdate(changed);
|
|
162
|
+
this.toggleState('blank', this.value === '');
|
|
143
163
|
if (!this.hasUpdated) {
|
|
144
164
|
return;
|
|
145
165
|
}
|
|
@@ -180,6 +200,16 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
180
200
|
@change=${this.handleChange}
|
|
181
201
|
></textarea>
|
|
182
202
|
<slot name="end"></slot>
|
|
203
|
+
${this.clearable && this.value !== '' && !this.isDisabled && !this.readOnly
|
|
204
|
+
? html `<button
|
|
205
|
+
part="clear"
|
|
206
|
+
type="button"
|
|
207
|
+
aria-label=${this.clearLabel}
|
|
208
|
+
@click=${this.handleClear}
|
|
209
|
+
>
|
|
210
|
+
${drawIcon(x)}
|
|
211
|
+
</button>`
|
|
212
|
+
: nothing}
|
|
183
213
|
</div>
|
|
184
214
|
${this.renderHint()}${this.renderFeedback()}`;
|
|
185
215
|
}
|
|
@@ -190,6 +220,12 @@ __decorate([
|
|
|
190
220
|
__decorate([
|
|
191
221
|
property({ attribute: 'auto-grow', reflect: true, type: Boolean })
|
|
192
222
|
], HelixHeadlessTextarea.prototype, "autoGrow", void 0);
|
|
223
|
+
__decorate([
|
|
224
|
+
property({ type: Boolean })
|
|
225
|
+
], HelixHeadlessTextarea.prototype, "clearable", void 0);
|
|
226
|
+
__decorate([
|
|
227
|
+
property({ attribute: 'clear-label' })
|
|
228
|
+
], HelixHeadlessTextarea.prototype, "clearLabel", void 0);
|
|
193
229
|
__decorate([
|
|
194
230
|
property({ type: Number })
|
|
195
231
|
], HelixHeadlessTextarea.prototype, "cols", void 0);
|
|
@@ -214,6 +250,9 @@ __decorate([
|
|
|
214
250
|
__decorate([
|
|
215
251
|
property({ type: Number })
|
|
216
252
|
], HelixHeadlessTextarea.prototype, "rows", void 0);
|
|
253
|
+
__decorate([
|
|
254
|
+
property({ attribute: false })
|
|
255
|
+
], HelixHeadlessTextarea.prototype, "validate", void 0);
|
|
217
256
|
__decorate([
|
|
218
257
|
property()
|
|
219
258
|
], HelixHeadlessTextarea.prototype, "wrap", void 0);
|
|
@@ -42,6 +42,8 @@ declare const HelixHeadlessTimeInput_base: (new (...args: any[]) => import("@fus
|
|
|
42
42
|
*
|
|
43
43
|
* @slot feedback - The message that says what is wrong with the value.
|
|
44
44
|
* @slot hint - Help under the field.
|
|
45
|
+
* @slot panel-footer - Content in the panel under the times, such as a note or an action.
|
|
46
|
+
* @slot panel-header - Content in the panel above the times, such as a heading or a shortcut.
|
|
45
47
|
* @slot trigger - The icon on the field that shows a list opens.
|
|
46
48
|
*
|
|
47
49
|
* @event {Event} change - Fired after the value changes.
|
|
@@ -60,6 +62,7 @@ declare const HelixHeadlessTimeInput_base: (new (...args: any[]) => import("@fus
|
|
|
60
62
|
* @csspart picker - The time picker inside the panel.
|
|
61
63
|
* @csspart picker-column - One column of the picker.
|
|
62
64
|
* @csspart picker-column-empty - The text shown when the filter hides every option.
|
|
65
|
+
* @csspart picker-column-error - A wheel's `error` part, which the list never sets: its times do not load.
|
|
63
66
|
* @csspart picker-column-feedback - The column's message that says what is wrong with the value.
|
|
64
67
|
* @csspart picker-column-filter-icon - The icon beside the filter field.
|
|
65
68
|
* @csspart picker-column-filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -73,6 +76,7 @@ declare const HelixHeadlessTimeInput_base: (new (...args: any[]) => import("@fus
|
|
|
73
76
|
* @csspart picker-columns - The row of columns, in `wheels`.
|
|
74
77
|
* @csspart picker-list - The listbox holding the times, in `list`.
|
|
75
78
|
* @csspart picker-list-empty - The text shown when the filter hides every option.
|
|
79
|
+
* @csspart picker-list-error - The list's `error` part, which the list never sets: its times do not load.
|
|
76
80
|
* @csspart picker-list-feedback - The inner list's message that says what is wrong with the value.
|
|
77
81
|
* @csspart picker-list-filter-icon - The icon beside the filter field.
|
|
78
82
|
* @csspart picker-list-filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -272,7 +276,7 @@ export declare class HelixHeadlessTimeInput extends HelixHeadlessTimeInput_base
|
|
|
272
276
|
/** Each time, where `mode` holds several, sent one entry each. */
|
|
273
277
|
protected get answers(): readonly string[] | undefined;
|
|
274
278
|
/** What is wrong with the times, which the text input cannot say. */
|
|
275
|
-
protected validate(): string;
|
|
279
|
+
protected validate(): string | readonly [keyof ValidityStateFlags, string];
|
|
276
280
|
/**
|
|
277
281
|
* Whether the panel shows one list of times or a column for each part of the
|
|
278
282
|
* time.
|
|
@@ -152,14 +152,20 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
|
|
|
152
152
|
const rules = { disableTimes: this.disableTimes, max: this.max, min: this.min };
|
|
153
153
|
const faults = held.map((one) => timeFault(one, rules));
|
|
154
154
|
if (faults.includes('rangeUnderflow')) {
|
|
155
|
-
return
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
return [
|
|
156
|
+
'rangeUnderflow',
|
|
157
|
+
fillTemplate(this.rangeUnderflowMessage || 'Choose a time at or after {min}.', {
|
|
158
|
+
min: writeClock(this.min, clockLocale(this.locale, this.hourCycle), this.seconds),
|
|
159
|
+
}),
|
|
160
|
+
];
|
|
158
161
|
}
|
|
159
162
|
if (faults.includes('rangeOverflow')) {
|
|
160
|
-
return
|
|
161
|
-
|
|
162
|
-
|
|
163
|
+
return [
|
|
164
|
+
'rangeOverflow',
|
|
165
|
+
fillTemplate(this.rangeOverflowMessage || 'Choose a time at or before {max}.', {
|
|
166
|
+
max: writeClock(this.max, clockLocale(this.locale, this.hourCycle), this.seconds),
|
|
167
|
+
}),
|
|
168
|
+
];
|
|
163
169
|
}
|
|
164
170
|
if (faults.includes('unavailable')) {
|
|
165
171
|
return this.unavailableMessage || 'Choose a time that is available.';
|
|
@@ -178,13 +184,13 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
|
|
|
178
184
|
renderPicker() {
|
|
179
185
|
return html `<${this.tag('time-picker')}
|
|
180
186
|
part="picker"
|
|
181
|
-
exportparts="column: picker-column, column-empty: picker-column-empty,
|
|
187
|
+
exportparts="column: picker-column, column-empty: picker-column-empty, column-error: picker-column-error,
|
|
182
188
|
column-feedback: picker-column-feedback, column-filter-icon: picker-column-filter-icon,
|
|
183
189
|
column-filter-mark: picker-column-filter-mark, column-hint: picker-column-hint,
|
|
184
190
|
column-items: picker-column-items, column-label: picker-column-label,
|
|
185
191
|
column-live: picker-column-live, column-loading: picker-column-loading, column-search: picker-column-search,
|
|
186
192
|
column-search-field: picker-column-search-field, columns: picker-columns, list: picker-list,
|
|
187
|
-
list-empty: picker-list-empty, list-feedback: picker-list-feedback,
|
|
193
|
+
list-empty: picker-list-empty, list-error: picker-list-error, list-feedback: picker-list-feedback,
|
|
188
194
|
list-filter-icon: picker-list-filter-icon, list-filter-mark: picker-list-filter-mark,
|
|
189
195
|
list-hint: picker-list-hint, list-items: picker-list-items, list-label: picker-list-label,
|
|
190
196
|
list-live: picker-list-live, list-loading: picker-list-loading, list-search: picker-list-search,
|
|
@@ -285,7 +291,9 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
|
|
|
285
291
|
?hidden=${!this.open}
|
|
286
292
|
@keydown=${this.handleWheelEnter}
|
|
287
293
|
>
|
|
294
|
+
<slot name="panel-header"></slot>
|
|
288
295
|
${this.renderPicker()}
|
|
296
|
+
<slot name="panel-footer"></slot>
|
|
289
297
|
</div>
|
|
290
298
|
${this.renderHint()}${this.renderFeedback()}`;
|
|
291
299
|
}
|
|
@@ -47,6 +47,7 @@ declare const HelixHeadlessTimePicker_base: (new (...args: any[]) => import("@fu
|
|
|
47
47
|
*
|
|
48
48
|
* @csspart column - One column of the wheels.
|
|
49
49
|
* @csspart column-empty - The text shown when the filter hides every option.
|
|
50
|
+
* @csspart column-error - A wheel's `error` part, which Time Picker never sets: its times do not load.
|
|
50
51
|
* @csspart column-feedback - The message that says what is wrong with the value.
|
|
51
52
|
* @csspart column-filter-icon - The icon beside the filter field.
|
|
52
53
|
* @csspart column-filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -60,6 +61,7 @@ declare const HelixHeadlessTimePicker_base: (new (...args: any[]) => import("@fu
|
|
|
60
61
|
* @csspart columns - The row of columns, in `wheels`.
|
|
61
62
|
* @csspart list - The listbox holding the times, in `list`.
|
|
62
63
|
* @csspart list-empty - The text shown when the filter hides every option.
|
|
64
|
+
* @csspart list-error - The list's `error` part, which Time Picker never sets: its times do not load.
|
|
63
65
|
* @csspart list-feedback - The message that says what is wrong with the value.
|
|
64
66
|
* @csspart list-filter-icon - The icon beside the filter field.
|
|
65
67
|
* @csspart list-filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -112,8 +114,11 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
|
|
|
112
114
|
hourCycle?: HourCycle;
|
|
113
115
|
/**
|
|
114
116
|
* What the wheel of hours is called, read by screen readers.
|
|
117
|
+
*
|
|
118
|
+
* Absent is the locale's own word, from `Intl.DisplayNames`: "Hour" in
|
|
119
|
+
* English, "Stunde" in German.
|
|
115
120
|
*/
|
|
116
|
-
hourLabel
|
|
121
|
+
hourLabel?: string;
|
|
117
122
|
/**
|
|
118
123
|
* Whether the current selection fails validation.
|
|
119
124
|
*
|
|
@@ -151,16 +156,22 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
|
|
|
151
156
|
/**
|
|
152
157
|
* What the wheel of the half of the day is called, read by screen readers.
|
|
153
158
|
* Its two options are written as the locale writes them, such as AM and PM.
|
|
159
|
+
*
|
|
160
|
+
* Absent is the locale's own word, from `Intl.DisplayNames`: "AM/PM" in
|
|
161
|
+
* English, "Tageshälfte" in German.
|
|
154
162
|
*/
|
|
155
|
-
meridiemLabel
|
|
163
|
+
meridiemLabel?: string;
|
|
156
164
|
/**
|
|
157
165
|
* Earliest time offered, as `HH:mm`.
|
|
158
166
|
*/
|
|
159
167
|
min: string;
|
|
160
168
|
/**
|
|
161
169
|
* What the wheel of minutes is called, read by screen readers.
|
|
170
|
+
*
|
|
171
|
+
* Absent is the locale's own word, from `Intl.DisplayNames`: "Minute" in
|
|
172
|
+
* English and German, "分" in Japanese.
|
|
162
173
|
*/
|
|
163
|
-
minuteLabel
|
|
174
|
+
minuteLabel?: string;
|
|
164
175
|
/**
|
|
165
176
|
* How many times can be held at once.
|
|
166
177
|
*
|
|
@@ -322,8 +333,11 @@ export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_bas
|
|
|
322
333
|
required: boolean;
|
|
323
334
|
/**
|
|
324
335
|
* What the wheel of seconds is called, read by screen readers.
|
|
336
|
+
*
|
|
337
|
+
* Absent is the locale's own word, from `Intl.DisplayNames`: "Second" in
|
|
338
|
+
* English, "Sekunde" in German.
|
|
325
339
|
*/
|
|
326
|
-
secondLabel
|
|
340
|
+
secondLabel?: string;
|
|
327
341
|
/**
|
|
328
342
|
* Whether times carry their seconds.
|
|
329
343
|
*
|
|
@@ -8,21 +8,19 @@ import { clockLocale, commaList, customElement, dayPeriod, elementById, fillTemp
|
|
|
8
8
|
import { nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { html } from 'lit/static-html.js';
|
|
11
|
+
import { wheelName } from '../wheel-name.js';
|
|
11
12
|
import '../../listbox/index.js';
|
|
12
13
|
import '../../option/index.js';
|
|
13
14
|
let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControllerValue(HelixFormElement) {
|
|
14
15
|
constructor() {
|
|
15
16
|
super(...arguments);
|
|
16
17
|
this.disableTimes = '';
|
|
17
|
-
this.hourLabel = 'Hour';
|
|
18
18
|
this.invalid = false;
|
|
19
19
|
this.label = 'Time';
|
|
20
20
|
this.locale = '';
|
|
21
21
|
this.manual = false;
|
|
22
22
|
this.max = '23:59';
|
|
23
|
-
this.meridiemLabel = 'Before or after noon';
|
|
24
23
|
this.min = '00:00';
|
|
25
|
-
this.minuteLabel = 'Minute';
|
|
26
24
|
this.handleListInput = (event) => {
|
|
27
25
|
event.stopPropagation();
|
|
28
26
|
};
|
|
@@ -77,7 +75,6 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
|
|
|
77
75
|
};
|
|
78
76
|
this.readOnly = false;
|
|
79
77
|
this.required = false;
|
|
80
|
-
this.secondLabel = 'Second';
|
|
81
78
|
this.seconds = false;
|
|
82
79
|
this.step = 15;
|
|
83
80
|
this.listRevealed = false;
|
|
@@ -286,7 +283,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
|
|
|
286
283
|
part="column"
|
|
287
284
|
data-column=${part}
|
|
288
285
|
aria-invalid=${this.invalid ? 'true' : nothing}
|
|
289
|
-
exportparts="empty: column-empty, feedback: column-feedback, filter-icon: column-filter-icon,
|
|
286
|
+
exportparts="empty: column-empty, error: column-error, feedback: column-feedback, filter-icon: column-filter-icon,
|
|
290
287
|
filter-mark: column-filter-mark, hint: column-hint, items: column-items, label: column-label,
|
|
291
288
|
live: column-live, loading: column-loading, search: column-search, search-field: column-search-field"
|
|
292
289
|
aria-label=${label}
|
|
@@ -323,13 +320,13 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
|
|
|
323
320
|
data-unset=${this.value === '' ? '' : nothing}
|
|
324
321
|
@keydown=${this.handleColumnsKeydown}
|
|
325
322
|
>
|
|
326
|
-
${this.renderColumn('hour', this.hourLabel, hours.map(String), (one) => (twelve ? one : one.padStart(2, '0')), String(shown), (one) => this.wholeHourBarred(Number(one), twelve ? meridiem : undefined))}
|
|
327
|
-
${this.renderColumn('minute', this.minuteLabel, this.minutes.map(String), (one) => one.padStart(2, '0'), String(minute), (one) => this.barredAt(hour * 3600 + Number(one) * 60))}
|
|
323
|
+
${this.renderColumn('hour', this.hourLabel ?? wheelName('hour', this.locale), hours.map(String), (one) => (twelve ? one : one.padStart(2, '0')), String(shown), (one) => this.wholeHourBarred(Number(one), twelve ? meridiem : undefined))}
|
|
324
|
+
${this.renderColumn('minute', this.minuteLabel ?? wheelName('minute', this.locale), this.minutes.map(String), (one) => one.padStart(2, '0'), String(minute), (one) => this.barredAt(hour * 3600 + Number(one) * 60))}
|
|
328
325
|
${this.seconds
|
|
329
|
-
? this.renderColumn('second', this.secondLabel, this.secondsShown.map(String), (one) => one.padStart(2, '0'), String(second), (one) => this.barredAt(hour * 3600 + minute * 60 + Number(one)))
|
|
326
|
+
? this.renderColumn('second', this.secondLabel ?? wheelName('second', this.locale), this.secondsShown.map(String), (one) => one.padStart(2, '0'), String(second), (one) => this.barredAt(hour * 3600 + minute * 60 + Number(one)))
|
|
330
327
|
: nothing}
|
|
331
328
|
${twelve
|
|
332
|
-
? this.renderColumn('meridiem', this.meridiemLabel, ['AM', 'PM'], (one) => dayPeriod(one, this.clock), meridiem, (one) => this.halfBarred(one))
|
|
329
|
+
? this.renderColumn('meridiem', this.meridiemLabel ?? wheelName('dayPeriod', this.locale), ['AM', 'PM'], (one) => dayPeriod(one, this.clock), meridiem, (one) => this.halfBarred(one))
|
|
333
330
|
: nothing}
|
|
334
331
|
</div>`;
|
|
335
332
|
}
|
|
@@ -337,7 +334,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinControl
|
|
|
337
334
|
return html `<${this.tag('listbox')}
|
|
338
335
|
part="list"
|
|
339
336
|
aria-invalid=${this.invalid ? 'true' : nothing}
|
|
340
|
-
exportparts="empty: list-empty, feedback: list-feedback, filter-icon: list-filter-icon,
|
|
337
|
+
exportparts="empty: list-empty, error: list-error, feedback: list-feedback, filter-icon: list-filter-icon,
|
|
341
338
|
filter-mark: list-filter-mark, hint: list-hint, items: list-items, label: list-label,
|
|
342
339
|
live: list-live, loading: list-loading, search: list-search, search-field: list-search-field"
|
|
343
340
|
aria-label=${this.listName}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A part of the time a Time Picker wheel sets. */
|
|
2
|
+
export type WheelField = 'dayPeriod' | 'hour' | 'minute' | 'second';
|
|
3
|
+
/**
|
|
4
|
+
* What a locale calls a wheel, core's `segmentName`, with its first letter in
|
|
5
|
+
* capitals as a name standing on its own: "Hour" in English, "Stunde" in
|
|
6
|
+
* German, "時" in Japanese, and "AM/PM" for the half of the day, React Aria's
|
|
7
|
+
* name for it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const wheelName: (field: WheelField, locale: string) => string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { segmentName } from '@fusion.dev/helix-core';
|
|
2
|
+
const ENGLISH = {
|
|
3
|
+
dayPeriod: 'AM/PM',
|
|
4
|
+
hour: 'Hour',
|
|
5
|
+
minute: 'Minute',
|
|
6
|
+
second: 'Second',
|
|
7
|
+
};
|
|
8
|
+
export const wheelName = (field, locale) => {
|
|
9
|
+
const name = segmentName(field, locale);
|
|
10
|
+
if (name === field || name === '') {
|
|
11
|
+
return ENGLISH[field];
|
|
12
|
+
}
|
|
13
|
+
const lead = String.fromCodePoint(name.codePointAt(0));
|
|
14
|
+
return `${lead.toLocaleUpperCase(locale || undefined)}${name.slice(lead.length)}`;
|
|
15
|
+
};
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, headingLevel, hostAria } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
const HEADING_ID = 'heading';
|
|
@@ -18,7 +18,7 @@ let HelixHeadlessTimelineGroup = class HelixHeadlessTimelineGroup extends HelixE
|
|
|
18
18
|
hostAria(this.internals, { role: 'listitem' });
|
|
19
19
|
}
|
|
20
20
|
render() {
|
|
21
|
-
const level =
|
|
21
|
+
const level = headingLevel(this.headingLevel);
|
|
22
22
|
return html `<div part="heading" id=${HEADING_ID} role="heading" aria-level=${level}>
|
|
23
23
|
<slot name="heading">${this.label}</slot>
|
|
24
24
|
</div>
|
|
@@ -13,7 +13,9 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
|
|
|
13
13
|
* seconds.
|
|
14
14
|
*
|
|
15
15
|
* **Each message is an `alertdialog` named by its words**, which is how a reader
|
|
16
|
-
* who moves into the stack hears which message they are on.
|
|
16
|
+
* who moves into the stack hears which message they are on. Give it a
|
|
17
|
+
* `heading` and a `description`, and the heading names it and the description
|
|
18
|
+
* describes it, for a message with a title and a line of detail. A `danger` message
|
|
17
19
|
* is its own assertive live region, so it is announced at once; every other one
|
|
18
20
|
* is announced politely by the region.
|
|
19
21
|
*
|
|
@@ -31,7 +33,9 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
|
|
|
31
33
|
*
|
|
32
34
|
* @slot - The message.
|
|
33
35
|
* @slot actions - Actions for the message, usually a button or a link.
|
|
36
|
+
* @slot description - A line of detail under the heading, which describes the message.
|
|
34
37
|
* @slot dismiss-icon - Replaces the glyph inside the dismiss control.
|
|
38
|
+
* @slot heading - The message's title, which names it.
|
|
35
39
|
* @slot icon - Replaces the tone mark. The name matches `Callout`. The dismiss
|
|
36
40
|
* control's glyph uses `dismiss-icon`, because two slots cannot share a name:
|
|
37
41
|
* content goes to whichever slot comes first in the tree, and the tone mark is
|
|
@@ -41,8 +45,10 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
|
|
|
41
45
|
*
|
|
42
46
|
* @csspart actions - The region that holds the actions.
|
|
43
47
|
* @csspart content - The message.
|
|
48
|
+
* @csspart description - The slot the description is in. It draws no box until you give it one.
|
|
44
49
|
* @csspart dismiss - The control that dismisses the message.
|
|
45
50
|
* @csspart dismiss-mark - The glyph on the dismiss control, where none is slotted.
|
|
51
|
+
* @csspart heading - The slot the heading is in. It draws no box until you give it one.
|
|
46
52
|
* @csspart icon - The tone mark, where the message has one.
|
|
47
53
|
* @csspart icon-mark - The tone glyph, where none is slotted.
|
|
48
54
|
* @csspart item - The message's own surface.
|
|
@@ -114,6 +120,13 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
|
|
|
114
120
|
connectedCallback(): void;
|
|
115
121
|
protected willUpdate(changed: PropertyValues): void;
|
|
116
122
|
protected updated(changed: PropertyValues): void;
|
|
123
|
+
/** The elements assigned to one of the message's named slots. */
|
|
124
|
+
private assigned;
|
|
125
|
+
/**
|
|
126
|
+
* Names the message by its heading and describes it by its description,
|
|
127
|
+
* where it has them, and otherwise names it by all its words.
|
|
128
|
+
*/
|
|
129
|
+
private readonly name;
|
|
117
130
|
protected firstUpdated(changed: PropertyValues): void;
|
|
118
131
|
/**
|
|
119
132
|
* The mark for the message's tone, behind a seam.
|
|
@@ -46,6 +46,17 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
46
46
|
this.handleResume = () => {
|
|
47
47
|
this.countdown.release();
|
|
48
48
|
};
|
|
49
|
+
this.name = () => {
|
|
50
|
+
const words = this.partNamed('content');
|
|
51
|
+
if (!words) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const heading = this.assigned('heading');
|
|
55
|
+
hostAria(this.internals, {
|
|
56
|
+
describedBy: this.assigned('description'),
|
|
57
|
+
labelledBy: heading.length > 0 ? heading : [words],
|
|
58
|
+
});
|
|
59
|
+
};
|
|
49
60
|
}
|
|
50
61
|
get open() {
|
|
51
62
|
return this.openState ?? true;
|
|
@@ -97,10 +108,12 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
97
108
|
}
|
|
98
109
|
updated(changed) {
|
|
99
110
|
super.updated(changed);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
111
|
+
this.name();
|
|
112
|
+
}
|
|
113
|
+
assigned(name) {
|
|
114
|
+
return (this.renderRoot
|
|
115
|
+
?.querySelector(`slot[name="${name}"]`)
|
|
116
|
+
?.assignedElements({ flatten: true }) ?? []);
|
|
104
117
|
}
|
|
105
118
|
firstUpdated(changed) {
|
|
106
119
|
super.firstUpdated(changed);
|
|
@@ -137,7 +150,11 @@ let HelixHeadlessToastItem = class HelixHeadlessToastItem extends MixinDismissib
|
|
|
137
150
|
${this.renderIcon(mark)}
|
|
138
151
|
</span>`
|
|
139
152
|
: nothing}
|
|
140
|
-
<div part="content"
|
|
153
|
+
<div part="content">
|
|
154
|
+
<slot name="heading" part="heading" @slotchange=${this.name}></slot>
|
|
155
|
+
<slot name="description" part="description" @slotchange=${this.name}></slot>
|
|
156
|
+
<slot></slot>
|
|
157
|
+
</div>
|
|
141
158
|
<div part="actions"><slot name="actions"></slot></div>
|
|
142
159
|
${this.dismissible
|
|
143
160
|
? drawDismiss({
|