@fusion.dev/helix-headless 0.145.0 → 0.147.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +12286 -4281
- package/dist/accordion/item/accordion-item.d.ts +51 -18
- package/dist/accordion/item/accordion-item.js +45 -13
- package/dist/accordion/root/accordion-root.d.ts +16 -7
- package/dist/accordion/root/accordion-root.js +3 -3
- package/dist/announcement/root/announcement-root.d.ts +16 -6
- package/dist/announcement/root/announcement-root.js +37 -7
- 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/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +11 -3
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/root/badge-root.d.ts +60 -7
- package/dist/badge/root/badge-root.js +89 -6
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +48 -20
- package/dist/bar-chart/stack.d.ts +25 -0
- package/dist/bar-chart/stack.js +27 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
- package/dist/button/root/button-root.d.ts +50 -38
- package/dist/button/root/button-root.js +42 -53
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- 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 +36 -4
- package/dist/card/root/card-root.js +29 -10
- 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 +40 -4
- package/dist/chat/root/chat-root.js +32 -6
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +18 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
- package/dist/checkbox-group/select-all.d.ts +21 -0
- package/dist/checkbox-group/select-all.js +7 -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 +79 -10
- package/dist/code-block/root/code-block-root.js +74 -5
- package/dist/color-input/root/color-input-root.d.ts +14 -0
- package/dist/color-input/root/color-input-root.js +17 -7
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +53 -16
- package/dist/color-picker/root/color-picker-root.js +155 -46
- package/dist/color-picker/wheel.d.ts +17 -0
- package/dist/color-picker/wheel.js +6 -0
- package/dist/combobox/root/combobox-root.d.ts +56 -0
- package/dist/combobox/root/combobox-root.js +92 -15
- package/dist/command/root/command-root.d.ts +19 -2
- package/dist/command/root/command-root.js +24 -23
- package/dist/copy-button/root/copy-button-root.d.ts +21 -1
- package/dist/copy-button/root/copy-button-root.js +16 -4
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +6 -0
- package/dist/data-table/keys.js +14 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +31 -57
- 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 +11 -2
- package/dist/date-input/root/date-input-root.js +26 -12
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +33 -22
- package/dist/description-list/item/description-list-item.d.ts +18 -4
- package/dist/description-list/item/description-list-item.js +8 -4
- 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 +55 -1
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +63 -2
- package/dist/drawer/root/drawer-root.js +75 -4
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +40 -5
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +22 -3
- package/dist/element-events.generated.js +35 -6
- package/dist/empty/root/empty-root.d.ts +34 -2
- package/dist/empty/root/empty-root.js +26 -4
- package/dist/file-input/root/file-input-root.d.ts +99 -8
- package/dist/file-input/root/file-input-root.js +120 -22
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +10 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +11 -2
- 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 +38 -6
- package/dist/filter-input/root/filter-input-root.js +18 -28
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/options.d.ts +3 -4
- package/dist/format-date/options.js +2 -2
- package/dist/format-date/root/format-date-root.d.ts +27 -17
- package/dist/format-date/root/format-date-root.js +27 -48
- package/dist/heatmap/root/buckets.d.ts +21 -0
- package/dist/heatmap/root/buckets.js +34 -0
- package/dist/heatmap/root/heatmap-root.d.ts +83 -11
- package/dist/heatmap/root/heatmap-root.js +104 -12
- package/dist/icon/index.d.ts +1 -1
- package/dist/icon/index.js +1 -1
- package/dist/icon/registry.d.ts +26 -1
- package/dist/icon/registry.js +12 -1
- package/dist/icon/root/icon-root.d.ts +25 -1
- package/dist/icon/root/icon-root.js +44 -12
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- 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 +14 -1
- package/dist/image/root/image-root.js +7 -2
- package/dist/input/root/input-root.d.ts +34 -3
- package/dist/input/root/input-root.js +17 -4
- package/dist/kbd/keys.d.ts +29 -0
- package/dist/kbd/keys.js +52 -0
- package/dist/kbd/root/kbd-root.d.ts +52 -1
- package/dist/kbd/root/kbd-root.js +40 -47
- package/dist/legend/hidden-series.d.ts +10 -2
- package/dist/legend/hidden-series.js +5 -2
- package/dist/legend/root/legend-root.d.ts +77 -12
- package/dist/legend/root/legend-root.js +71 -17
- package/dist/lightbox/root/lightbox-root.d.ts +98 -10
- package/dist/lightbox/root/lightbox-root.js +153 -18
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +24 -0
- package/dist/lightbox/zoom.js +18 -0
- package/dist/line-chart/root/line-chart-root.d.ts +38 -1
- package/dist/line-chart/root/line-chart-root.js +31 -3
- 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 +70 -13
- package/dist/list/root/list-root.js +91 -13
- package/dist/list/selection.d.ts +54 -7
- package/dist/list/selection.js +32 -7
- package/dist/listbox/root/listbox-root.d.ts +44 -4
- package/dist/listbox/root/listbox-root.js +72 -34
- 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/hand-over.d.ts +75 -0
- package/dist/megamenu/hand-over.js +67 -0
- package/dist/megamenu/root/megamenu-root.d.ts +80 -15
- package/dist/megamenu/root/megamenu-root.js +76 -19
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +50 -26
- package/dist/menu/root/menu-root.d.ts +17 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +62 -1
- package/dist/meter/root/meter-root.js +38 -16
- 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 +20 -4
- package/dist/notifications/root/notifications-root.js +30 -8
- package/dist/number-input/grain.d.ts +28 -0
- package/dist/number-input/grain.js +14 -0
- package/dist/number-input/root/number-input-root.d.ts +34 -9
- package/dist/number-input/root/number-input-root.js +31 -25
- package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
- package/dist/object-inspector/root/object-inspector-root.js +134 -92
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/option/separator/option-separator.d.ts +30 -0
- package/dist/option/separator/option-separator.js +21 -0
- package/dist/outline/root/outline-root.d.ts +30 -0
- package/dist/outline/root/outline-root.js +17 -13
- package/dist/pagination/size/pagination-size.d.ts +6 -0
- package/dist/pagination/size/pagination-size.js +5 -3
- package/dist/pin-input/code.d.ts +37 -0
- package/dist/pin-input/code.js +25 -0
- package/dist/pin-input/root/pin-input-root.d.ts +116 -115
- package/dist/pin-input/root/pin-input-root.js +163 -155
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +34 -0
- package/dist/popover/root/popover-root.d.ts +64 -8
- package/dist/popover/root/popover-root.js +67 -4
- package/dist/progress/root/progress-root.d.ts +47 -0
- package/dist/progress/root/progress-root.js +34 -16
- package/dist/qr-code/export.d.ts +45 -1
- package/dist/qr-code/export.js +28 -0
- package/dist/qr-code/name.d.ts +11 -0
- package/dist/qr-code/name.js +7 -0
- package/dist/qr-code/root/qr-code-root.d.ts +36 -11
- package/dist/qr-code/root/qr-code-root.js +58 -11
- 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/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +7 -2
- package/dist/rating/root/rating-root.d.ts +30 -12
- package/dist/rating/root/rating-root.js +27 -27
- 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 +51 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
- 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 -8
- package/dist/scroll-area/scrollbar.js +10 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +71 -0
- package/dist/select/root/select-root.js +78 -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 +59 -5
- package/dist/slider/root/slider-root.js +45 -3
- package/dist/sparkline/readings.d.ts +36 -0
- package/dist/sparkline/readings.js +36 -0
- package/dist/sparkline/root/sparkline-root.d.ts +121 -7
- package/dist/sparkline/root/sparkline-root.js +160 -26
- package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
- package/dist/speed-dial/item/speed-dial-item.js +2 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
- package/dist/speed-dial/root/speed-dial-root.js +11 -3
- package/dist/splitter/root/splitter-root.d.ts +10 -12
- package/dist/splitter/root/splitter-root.js +211 -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 +56 -3
- package/dist/steps/root/steps-root.js +50 -6
- package/dist/steps/step/step.d.ts +8 -0
- package/dist/steps/step/step.js +8 -3
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +6 -10
- package/dist/table/column/table-column.js +8 -20
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +14 -18
- package/dist/table/row/table-row.d.ts +24 -0
- package/dist/table/row/table-row.js +37 -1
- 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 +17 -3
- 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 +44 -5
- package/dist/tag/group/tag-group.js +60 -9
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +41 -2
- package/dist/textarea/root/textarea-root.js +39 -1
- package/dist/time-input/root/time-input-root.d.ts +10 -2
- package/dist/time-input/root/time-input-root.js +24 -13
- package/dist/time-picker/root/time-picker-root.d.ts +28 -17
- package/dist/time-picker/root/time-picker-root.js +18 -29
- 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 +16 -3
- package/dist/toast/item/toast-item.js +22 -6
- package/dist/toast/root/toast-root.d.ts +34 -4
- package/dist/toast/root/toast-root.js +74 -13
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +52 -7
- package/dist/toggle/group/toggle-group.js +58 -44
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +21 -5
- package/dist/toolbar/root/toolbar-root.js +52 -8
- package/dist/tooltip/root/tooltip-root.d.ts +20 -3
- package/dist/tooltip/root/tooltip-root.js +18 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +45 -2
- package/dist/tour/root/tour-root.js +53 -8
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- 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/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +83 -19
- package/dist/trend/root/trend-root.js +59 -8
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/extra-controls.d.ts +12 -0
- package/dist/video/root/extra-controls.js +6 -2
- package/dist/video/root/video-root.d.ts +23 -6
- 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 +17 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -8
- package/dist/virtual-list/fill.js +10 -17
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +65 -0
- package/dist/virtual-list/plan.js +27 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
- package/dist/virtual-list/root/virtual-list-root.js +218 -51
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +7441 -1458
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +1501 -326
- 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,15 +4,41 @@ 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';
|
|
8
|
-
import { html } from 'lit';
|
|
9
|
-
import { property } from 'lit/decorators.js';
|
|
7
|
+
import { customElement, focusableElements, HelixElement, hostAria } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.label = '';
|
|
14
14
|
this.selected = false;
|
|
15
15
|
this.value = '';
|
|
16
|
+
this.holdsStop = false;
|
|
17
|
+
this.watcher = typeof MutationObserver === 'undefined'
|
|
18
|
+
? undefined
|
|
19
|
+
: new MutationObserver(() => this.readStops());
|
|
20
|
+
this.readStops = () => {
|
|
21
|
+
this.holdsStop = this.selected && focusableElements(this).length > 0;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
connectedCallback() {
|
|
25
|
+
super.connectedCallback();
|
|
26
|
+
this.watcher?.observe(this, {
|
|
27
|
+
attributeFilter: ['contenteditable', 'disabled', 'hidden', 'href', 'tabindex'],
|
|
28
|
+
attributes: true,
|
|
29
|
+
childList: true,
|
|
30
|
+
subtree: true,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
disconnectedCallback() {
|
|
34
|
+
super.disconnectedCallback();
|
|
35
|
+
this.watcher?.disconnect();
|
|
36
|
+
}
|
|
37
|
+
updated(changed) {
|
|
38
|
+
super.updated(changed);
|
|
39
|
+
if (changed.has('selected')) {
|
|
40
|
+
this.readStops();
|
|
41
|
+
}
|
|
16
42
|
}
|
|
17
43
|
willUpdate(changed) {
|
|
18
44
|
super.willUpdate(changed);
|
|
@@ -23,9 +49,9 @@ let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
|
|
|
23
49
|
return html `<div
|
|
24
50
|
part="panel"
|
|
25
51
|
?hidden=${!this.selected}
|
|
26
|
-
tabindex
|
|
52
|
+
tabindex=${this.holdsStop ? nothing : '0'}
|
|
27
53
|
>
|
|
28
|
-
<slot></slot>
|
|
54
|
+
<slot @slotchange=${this.readStops}></slot>
|
|
29
55
|
</div>`;
|
|
30
56
|
}
|
|
31
57
|
};
|
|
@@ -38,6 +64,9 @@ __decorate([
|
|
|
38
64
|
__decorate([
|
|
39
65
|
property()
|
|
40
66
|
], HelixHeadlessTabPanel.prototype, "value", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
state()
|
|
69
|
+
], HelixHeadlessTabPanel.prototype, "holdsStop", void 0);
|
|
41
70
|
HelixHeadlessTabPanel = __decorate([
|
|
42
71
|
customElement('helix-headless-tab-panel')
|
|
43
72
|
], HelixHeadlessTabPanel);
|
|
@@ -21,13 +21,26 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
|
|
|
21
21
|
* between tabs either way.
|
|
22
22
|
*
|
|
23
23
|
* A tab with an `href` is a link, for tabs that are pages of a site. Pressing
|
|
24
|
-
* it follows the link,
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* it follows the link. Where any tab is a link, the arrow keys move focus
|
|
25
|
+
* without choosing on every tab of the list, as under `manual`, so arrowing
|
|
26
|
+
* past a tab never leaves the page and the list answers the keys one way.
|
|
27
|
+
* Mark the tab of the page you are on with `selected`, or set `active` to its
|
|
28
|
+
* value.
|
|
27
29
|
*
|
|
28
30
|
* Each tab says which panel it controls through `aria-controls`, set as an
|
|
29
31
|
* element reference to the panel's host, where the engine has reflection.
|
|
30
32
|
*
|
|
33
|
+
* Keys, on the tab list: Left and Right Arrow move between tabs, and so do Up
|
|
34
|
+
* and Down; Home and End go to the first and the last. The horizontal arrows
|
|
35
|
+
* follow the reading direction, so on a right-to-left page Left moves on.
|
|
36
|
+
* Disabled tabs are passed over. Tab leaves the list for the selected panel,
|
|
37
|
+
* which is a tab stop only while it holds nothing focusable.
|
|
38
|
+
*
|
|
39
|
+
* The `indicator` part moves to the selected tab and carries its place and
|
|
40
|
+
* size, so a mark of your own can be drawn there: style the part, or slot an
|
|
41
|
+
* element into `indicator`, which sits inside the part and reads the same
|
|
42
|
+
* properties.
|
|
43
|
+
*
|
|
31
44
|
* @since 0.1.0
|
|
32
45
|
* @status stable
|
|
33
46
|
* @category navigation
|
|
@@ -35,6 +48,7 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
|
|
|
35
48
|
* @documentation https://fusion.dev/helix/components/tabs
|
|
36
49
|
*
|
|
37
50
|
* @slot - The tabs, as direct children of this element.
|
|
51
|
+
* @slot indicator - A mark of your own, drawn inside the `indicator` part, where `--indicator-x`, `--indicator-y`, `--indicator-inline-size` and `--indicator-block-size` reach it.
|
|
38
52
|
* @slot panels - The panels, as direct children of this element. Panels inside a wrapper are not paired with tabs, because pairing reads only the direct children.
|
|
39
53
|
*
|
|
40
54
|
* @event {HelixActivateEvent} helix-activate - Fired after the active tab changes, so the element already holds the new value.
|
|
@@ -105,7 +105,7 @@ let HelixHeadlessTabs = class HelixHeadlessTabs extends MixinControllerActive(He
|
|
|
105
105
|
aria-orientation=${this.orientation === 'vertical' ? 'vertical' : nothing}
|
|
106
106
|
>
|
|
107
107
|
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
108
|
-
<span part="indicator" aria-hidden="true"></span>
|
|
108
|
+
<span part="indicator" aria-hidden="true"><slot name="indicator"></slot></span>
|
|
109
109
|
</div>
|
|
110
110
|
<div part="panels"><slot name="panels" @slotchange=${this.handleSlotChange}></slot></div>`;
|
|
111
111
|
}
|
package/dist/tabs/tab/tab.d.ts
CHANGED
|
@@ -47,6 +47,11 @@ export declare class HelixHeadlessTab extends HelixHeadlessTab_base {
|
|
|
47
47
|
* Where the link opens, such as `_blank`, for a tab with an `href`.
|
|
48
48
|
*/
|
|
49
49
|
target?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Moves focus to the tab's control, the button or the link inside it, so a
|
|
52
|
+
* script can focus the tab the way it focuses a native one.
|
|
53
|
+
*/
|
|
54
|
+
focus(options?: FocusOptions): void;
|
|
50
55
|
/**
|
|
51
56
|
* Chooses the tab before the browser follows its link, and keeps the browser
|
|
52
57
|
* from following where the choice was refused. A press with a modifier, or
|
package/dist/tabs/tab/tab.js
CHANGED
|
@@ -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, MixinSelectableItem, reflectElements, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, MixinSelectableItem, plainClick, reflectElements, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessTab = class HelixHeadlessTab extends MixinSelectableItem(HelixElement) {
|
|
@@ -13,7 +13,7 @@ let HelixHeadlessTab = class HelixHeadlessTab extends MixinSelectableItem(HelixE
|
|
|
13
13
|
this.itemPart = 'tab';
|
|
14
14
|
this.controls = undefined;
|
|
15
15
|
this.handleLinkClick = (event) => {
|
|
16
|
-
if (event
|
|
16
|
+
if (!plainClick(event)) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
if (!this.select()) {
|
|
@@ -21,6 +21,9 @@ let HelixHeadlessTab = class HelixHeadlessTab extends MixinSelectableItem(HelixE
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
focus(options) {
|
|
25
|
+
this.partNamed('tab')?.focus(options);
|
|
26
|
+
}
|
|
24
27
|
updated(changed) {
|
|
25
28
|
super.updated(changed);
|
|
26
29
|
const control = this.renderRoot.querySelector('[part="tab"]');
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { HelixElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
|
|
1
|
+
import { HelixElement, KeyboardNavigationController, type SelectionMode } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import { HelixHeadlessTag } from '../root/tag-root.js';
|
|
4
|
-
|
|
4
|
+
/** How many tags a group lets a reader select: core's `SelectionMode`. */
|
|
5
|
+
export type TagSelectionMode = SelectionMode;
|
|
5
6
|
/**
|
|
6
7
|
* @summary A set of tags that the arrow keys move through, and that can be removed and selected from the keyboard.
|
|
7
8
|
*
|
|
@@ -17,9 +18,18 @@ import { type TagSelectionMode } from '../selection.js';
|
|
|
17
18
|
* `single` selects one at a time and `multiple` any number. `value` holds the
|
|
18
19
|
* selected tags' values, separated by commas, and a change asks with
|
|
19
20
|
* `helix-before-change` and tells with `change`. Enter on a tag with an
|
|
20
|
-
* `href` follows its link. A `disabled` tag is passed over.
|
|
21
|
+
* `href` follows its link. A `disabled` tag is passed over. A selected tag
|
|
22
|
+
* that is removed leaves `value`, which then sends `change`.
|
|
21
23
|
*
|
|
22
|
-
* Name the set with `label`.
|
|
24
|
+
* Name the set with `label`. Each tag is named by its words alone, without
|
|
25
|
+
* its remove button. `value` takes an array of values on the property as
|
|
26
|
+
* well, as React sets `value={['Apple']}`; a press writes it back as a
|
|
27
|
+
* string.
|
|
28
|
+
*
|
|
29
|
+
* **Removing the last tag keeps focus in the group.** With no tags left the
|
|
30
|
+
* set is a `group`, and focus moves to its `empty` part,
|
|
31
|
+
* which holds the `empty` slot: put words there such as "No filters" for a
|
|
32
|
+
* reader to hear. With nothing slotted it says `empty-label`, "No tags".
|
|
23
33
|
*
|
|
24
34
|
* @since 0.1.0
|
|
25
35
|
* @status stable
|
|
@@ -27,12 +37,20 @@ import { type TagSelectionMode } from '../selection.js';
|
|
|
27
37
|
* @documentation https://fusion.dev/helix/components/tag
|
|
28
38
|
*
|
|
29
39
|
* @slot - The tags, in the order they are read.
|
|
40
|
+
* @slot empty - Shown in place of the tags while there are none, such as "No filters". Its fallback is `empty-label`.
|
|
30
41
|
*
|
|
31
42
|
* @event {Event} change - Fired once a press has changed which tags are selected.
|
|
32
43
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before a press changes which tags are selected, with the `value` it would leave. Cancelable.
|
|
33
44
|
* @event {HelixDismissEvent} helix-dismiss - A tag's remove button was pressed, or Delete or Backspace on the focused tag. Bubbles from that tag, which is its `target`; remove the tag in response. Cancelable.
|
|
45
|
+
*
|
|
46
|
+
* @csspart empty - Holds the `empty` slot while the group has no tags, rendered only then. Takes focus when the last tag is removed.
|
|
34
47
|
*/
|
|
35
48
|
export declare class HelixHeadlessTagGroup extends HelixElement {
|
|
49
|
+
/**
|
|
50
|
+
* The words the group shows and says once its last tag is removed, where
|
|
51
|
+
* nothing is in the `empty` slot.
|
|
52
|
+
*/
|
|
53
|
+
emptyLabel: string;
|
|
36
54
|
/**
|
|
37
55
|
* The name of the set, such as "Filters", which a screen reader announces
|
|
38
56
|
* before its tags.
|
|
@@ -51,7 +69,7 @@ export declare class HelixHeadlessTagGroup extends HelixElement {
|
|
|
51
69
|
* Set it to start with tags selected. A tag's value is its `value`, or its
|
|
52
70
|
* words where it has none.
|
|
53
71
|
*/
|
|
54
|
-
value: string;
|
|
72
|
+
value: string | readonly string[];
|
|
55
73
|
/** The tag the reader was last on, which keeps the tab stop. */
|
|
56
74
|
private last;
|
|
57
75
|
/**
|
|
@@ -61,6 +79,11 @@ export declare class HelixHeadlessTagGroup extends HelixElement {
|
|
|
61
79
|
* a list of tags has a first and a last.
|
|
62
80
|
*/
|
|
63
81
|
protected readonly keys: KeyboardNavigationController;
|
|
82
|
+
/**
|
|
83
|
+
* `value` as one written list, separated by commas, however it was set:
|
|
84
|
+
* an array of values is joined.
|
|
85
|
+
*/
|
|
86
|
+
private get written();
|
|
64
87
|
/** The tags the group holds, in order. */
|
|
65
88
|
get tags(): HelixHeadlessTag[];
|
|
66
89
|
/** The tags a key can land on, which are the ones that are not disabled. */
|
|
@@ -93,9 +116,25 @@ export declare class HelixHeadlessTagGroup extends HelixElement {
|
|
|
93
116
|
protected press(tag: HelixHeadlessTag): void;
|
|
94
117
|
private readonly handleKeydown;
|
|
95
118
|
private readonly handleClick;
|
|
119
|
+
/**
|
|
120
|
+
* What happens once a tag has asked to be removed and the page has had its
|
|
121
|
+
* turn: a selected tag that left takes its value out of `value`, and focus
|
|
122
|
+
* that the last tag took with it comes to the group's `empty` part.
|
|
123
|
+
*
|
|
124
|
+
* Asked after the event and again a frame later, as `MixinDismissible`
|
|
125
|
+
* asks, because a framework removes the tag on its next render, after the
|
|
126
|
+
* handler. A canceled dismissal changes nothing.
|
|
127
|
+
*/
|
|
128
|
+
private readonly handleDismiss;
|
|
129
|
+
private readonly handleSlotchange;
|
|
96
130
|
private readonly handleFocusin;
|
|
97
131
|
connectedCallback(): void;
|
|
98
132
|
disconnectedCallback(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Whether the group is known to hold no tags, which a server and a
|
|
135
|
+
* hydrating render cannot know: there it holds whatever it was given.
|
|
136
|
+
*/
|
|
137
|
+
private get empty();
|
|
99
138
|
protected willUpdate(changed: PropertyValues<this>): void;
|
|
100
139
|
protected updated(changed: PropertyValues<this>): void;
|
|
101
140
|
protected render(): TemplateResult;
|
|
@@ -4,21 +4,21 @@ 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, typeaheadByWords, 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);
|
|
14
|
+
this.emptyLabel = 'No tags';
|
|
15
15
|
this.label = '';
|
|
16
16
|
this.value = '';
|
|
17
17
|
this.keys = new KeyboardNavigationController(this, {
|
|
18
18
|
items: () => this.reachable.map((tag) => this.navigable(tag)),
|
|
19
19
|
origin: 'focus',
|
|
20
20
|
selects: () => false,
|
|
21
|
-
typeahead: (
|
|
21
|
+
typeahead: typeaheadByWords(),
|
|
22
22
|
wrap: false,
|
|
23
23
|
});
|
|
24
24
|
this.handleKeydown = (event) => {
|
|
@@ -53,6 +53,37 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
53
53
|
this.press(tag);
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
+
this.handleDismiss = (event) => {
|
|
57
|
+
const tag = this.tagOf(event);
|
|
58
|
+
if (!tag) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const had = deepContains(this, deepActiveElement());
|
|
62
|
+
const settle = async () => {
|
|
63
|
+
if (event.defaultPrevented || tag.isConnected) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const left = this.tags.map((one) => this.valueFor(one));
|
|
67
|
+
const pruned = prunedValue(this.written, this.valueFor(tag), left);
|
|
68
|
+
if (pruned !== this.written) {
|
|
69
|
+
this.value = pruned;
|
|
70
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
71
|
+
}
|
|
72
|
+
const active = document.activeElement;
|
|
73
|
+
if (!had || this.tags.length > 0 || (active !== null && active !== document.body)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.requestUpdate();
|
|
77
|
+
await this.updateComplete;
|
|
78
|
+
this.renderRoot.querySelector('[part~="empty"]')?.focus();
|
|
79
|
+
};
|
|
80
|
+
queueMicrotask(() => void settle());
|
|
81
|
+
requestAnimationFrame(() => void settle());
|
|
82
|
+
};
|
|
83
|
+
this.handleSlotchange = () => {
|
|
84
|
+
this.sync();
|
|
85
|
+
this.requestUpdate();
|
|
86
|
+
};
|
|
56
87
|
this.handleFocusin = (event) => {
|
|
57
88
|
const tag = this.tagOf(event);
|
|
58
89
|
if (tag && tag !== this.last) {
|
|
@@ -61,6 +92,14 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
61
92
|
}
|
|
62
93
|
};
|
|
63
94
|
}
|
|
95
|
+
get written() {
|
|
96
|
+
return typeof this.value === 'string'
|
|
97
|
+
? this.value
|
|
98
|
+
: this.value
|
|
99
|
+
.map((one) => String(one).trim())
|
|
100
|
+
.filter((one) => one !== '')
|
|
101
|
+
.join(', ');
|
|
102
|
+
}
|
|
64
103
|
get tags() {
|
|
65
104
|
return [...(this.children ?? [])].filter((child) => child instanceof HelixHeadlessTag);
|
|
66
105
|
}
|
|
@@ -82,7 +121,7 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
82
121
|
}
|
|
83
122
|
sync() {
|
|
84
123
|
const mode = this.selectionMode ?? 'none';
|
|
85
|
-
const chosen = new Set(commaList(this.
|
|
124
|
+
const chosen = new Set(commaList(this.written));
|
|
86
125
|
const tags = this.tags;
|
|
87
126
|
const items = tags.map((tag) => ({
|
|
88
127
|
disabled: tag.disabled,
|
|
@@ -114,7 +153,7 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
114
153
|
},
|
|
115
154
|
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
116
155
|
host: this,
|
|
117
|
-
next: pressedValue(mode, this.
|
|
156
|
+
next: pressedValue(mode, this.written, this.valueFor(tag)),
|
|
118
157
|
});
|
|
119
158
|
}
|
|
120
159
|
connectedCallback() {
|
|
@@ -122,26 +161,38 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
122
161
|
this.addEventListener('keydown', this.handleKeydown);
|
|
123
162
|
this.addEventListener('click', this.handleClick);
|
|
124
163
|
this.addEventListener('focusin', this.handleFocusin);
|
|
164
|
+
this.addEventListener('helix-dismiss', this.handleDismiss);
|
|
125
165
|
}
|
|
126
166
|
disconnectedCallback() {
|
|
127
167
|
super.disconnectedCallback();
|
|
128
168
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
129
169
|
this.removeEventListener('click', this.handleClick);
|
|
130
170
|
this.removeEventListener('focusin', this.handleFocusin);
|
|
171
|
+
this.removeEventListener('helix-dismiss', this.handleDismiss);
|
|
172
|
+
}
|
|
173
|
+
get empty() {
|
|
174
|
+
return this.childrenKnown && this.tags.length === 0;
|
|
131
175
|
}
|
|
132
176
|
willUpdate(changed) {
|
|
133
177
|
super.willUpdate(changed);
|
|
134
|
-
|
|
135
|
-
this.internals
|
|
178
|
+
const empty = this.empty;
|
|
179
|
+
hostAria(this.internals, { label: this.label, role: empty ? 'group' : 'grid' });
|
|
180
|
+
this.internals.ariaMultiSelectable = this.selectionMode === 'multiple' && !empty ? 'true' : null;
|
|
136
181
|
}
|
|
137
182
|
updated(changed) {
|
|
138
183
|
super.updated(changed);
|
|
139
184
|
this.sync();
|
|
140
185
|
}
|
|
141
186
|
render() {
|
|
142
|
-
|
|
187
|
+
const empty = this.empty
|
|
188
|
+
? html `<div part="empty" tabindex="-1"><slot name="empty">${this.emptyLabel}</slot></div>`
|
|
189
|
+
: nothing;
|
|
190
|
+
return html `<slot @slotchange=${this.handleSlotchange}></slot>${empty}`;
|
|
143
191
|
}
|
|
144
192
|
};
|
|
193
|
+
__decorate([
|
|
194
|
+
property({ attribute: 'empty-label' })
|
|
195
|
+
], HelixHeadlessTagGroup.prototype, "emptyLabel", void 0);
|
|
145
196
|
__decorate([
|
|
146
197
|
property()
|
|
147
198
|
], HelixHeadlessTagGroup.prototype, "label", void 0);
|
|
@@ -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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, HelixFormElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixFormElement, type OwnRule } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessTextarea_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
|
|
4
4
|
/**
|
|
@@ -17,12 +17,27 @@ 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
|
+
*
|
|
25
|
+
* **Keyboard.** The field's own keys are the platform's, and Enter starts a
|
|
26
|
+
* new line. The clear button under `clearable` is a tab stop of its own after
|
|
27
|
+
* the field.
|
|
28
|
+
*
|
|
29
|
+
* The inner textarea is named by `label`, or by a host `aria-label`,
|
|
30
|
+
* `aria-labelledby` or `<label for>`, and is described by the hint and the
|
|
31
|
+
* message, with `aria-invalid` while a message shows. The clear button is
|
|
32
|
+
* named `clear-label`.
|
|
33
|
+
*
|
|
20
34
|
* @since 0.1.0
|
|
21
35
|
* @status stable
|
|
22
36
|
* @category forms
|
|
23
37
|
* @aliases Multiline, TextArea
|
|
24
38
|
* @documentation https://fusion.dev/helix/components/textarea
|
|
25
39
|
*
|
|
40
|
+
* @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
|
|
26
41
|
* @slot end - After the text, for an icon or an action beside it.
|
|
27
42
|
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
28
43
|
* @slot hint - Help under the control, for content richer than the `hint` text.
|
|
@@ -31,15 +46,18 @@ declare const HelixHeadlessTextarea_base: (new (...args: any[]) => import("@fusi
|
|
|
31
46
|
*
|
|
32
47
|
* @event {Event} change - Sent from the textarea when the user finishes an edit.
|
|
33
48
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired as the text changes, and cancelable.
|
|
49
|
+
* @event {HelixClearEvent} helix-clear - Fired after the clear button has emptied the field, after `input` and `change`.
|
|
34
50
|
* @event {Event} input - Fired after the value changes.
|
|
35
51
|
*
|
|
52
|
+
* @csspart clear - The button that empties the field, under `clearable`.
|
|
36
53
|
* @csspart control - The textarea itself.
|
|
37
54
|
* @csspart feedback - The message that says what is wrong.
|
|
38
55
|
* @csspart field - The box that holds the textarea.
|
|
39
56
|
* @csspart hint - Help under the field, while nothing is wrong.
|
|
40
57
|
* @csspart label - The label above the field.
|
|
41
58
|
*
|
|
42
|
-
* @cssstate
|
|
59
|
+
* @cssstate blank - The field holds no text.
|
|
60
|
+
* @cssstate invalid - The control has an error to show, from the browser's validation, `validate`, or your `feedback`.
|
|
43
61
|
*/
|
|
44
62
|
export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
45
63
|
protected readonly aria: AriaForwardController;
|
|
@@ -57,6 +75,14 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
|
57
75
|
* Grows the box to fit its content, so it does not scroll.
|
|
58
76
|
*/
|
|
59
77
|
autoGrow: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Draws a button that empties the field while it holds text.
|
|
80
|
+
*/
|
|
81
|
+
clearable: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The accessible name of the clear button, which shows only an icon.
|
|
84
|
+
*/
|
|
85
|
+
clearLabel: string;
|
|
60
86
|
/**
|
|
61
87
|
* How many characters wide the box is, when the layout does not set its
|
|
62
88
|
* width.
|
|
@@ -194,6 +220,11 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
|
194
220
|
focus(options?: FocusOptions): void;
|
|
195
221
|
/** Reports the value and the validity the host stands behind. */
|
|
196
222
|
private sync;
|
|
223
|
+
/**
|
|
224
|
+
* Empties the field and puts the caret back in it, through `requestValue`,
|
|
225
|
+
* so a consumer who owns the value can refuse. `Input` clears the same way.
|
|
226
|
+
*/
|
|
227
|
+
private readonly handleClear;
|
|
197
228
|
connectedCallback(): void;
|
|
198
229
|
disconnectedCallback(): void;
|
|
199
230
|
protected firstUpdated(changed: PropertyValues): void;
|
|
@@ -212,11 +243,19 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
|
|
|
212
243
|
* How many lines the box is before anything is typed.
|
|
213
244
|
*/
|
|
214
245
|
rows: number;
|
|
246
|
+
/**
|
|
247
|
+
* Your own rule for the value, run on every change once the browser finds
|
|
248
|
+
* nothing wrong. Return a message, or a list of them, to mark the field
|
|
249
|
+
* invalid, and `true`, `null`, or nothing to accept the value.
|
|
250
|
+
*/
|
|
251
|
+
validate?: OwnRule;
|
|
215
252
|
/**
|
|
216
253
|
* How the browser wraps the text, and whether the breaks are submitted with
|
|
217
254
|
* it.
|
|
218
255
|
*/
|
|
219
256
|
wrap: 'hard' | 'off' | 'soft';
|
|
257
|
+
/** The cross on the clear button, behind a seam a tier can move. */
|
|
258
|
+
protected renderClearIcon(): TemplateResult;
|
|
220
259
|
protected render(): TemplateResult;
|
|
221
260
|
}
|
|
222
261
|
declare global {
|
|
@@ -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, applyOwnRule, 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,7 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
112
126
|
return;
|
|
113
127
|
}
|
|
114
128
|
this.copyValidity(control);
|
|
129
|
+
applyOwnRule(this.internals, control, this.validate, this.value);
|
|
115
130
|
this.refreshFeedback();
|
|
116
131
|
}
|
|
117
132
|
connectedCallback() {
|
|
@@ -140,6 +155,7 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
140
155
|
}
|
|
141
156
|
willUpdate(changed) {
|
|
142
157
|
super.willUpdate(changed);
|
|
158
|
+
this.toggleState('blank', this.value === '');
|
|
143
159
|
if (!this.hasUpdated) {
|
|
144
160
|
return;
|
|
145
161
|
}
|
|
@@ -155,6 +171,9 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
155
171
|
this.sync();
|
|
156
172
|
this.grow();
|
|
157
173
|
}
|
|
174
|
+
renderClearIcon() {
|
|
175
|
+
return html `<slot name="clear-icon">${drawIcon(x)}</slot>`;
|
|
176
|
+
}
|
|
158
177
|
render() {
|
|
159
178
|
return html `${this.renderLabel()}
|
|
160
179
|
<div part="field">
|
|
@@ -180,6 +199,16 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
|
|
|
180
199
|
@change=${this.handleChange}
|
|
181
200
|
></textarea>
|
|
182
201
|
<slot name="end"></slot>
|
|
202
|
+
${this.clearable && this.value !== '' && !this.isDisabled && !this.readOnly
|
|
203
|
+
? html `<button
|
|
204
|
+
part="clear"
|
|
205
|
+
type="button"
|
|
206
|
+
aria-label=${this.clearLabel}
|
|
207
|
+
@click=${this.handleClear}
|
|
208
|
+
>
|
|
209
|
+
${this.renderClearIcon()}
|
|
210
|
+
</button>`
|
|
211
|
+
: nothing}
|
|
183
212
|
</div>
|
|
184
213
|
${this.renderHint()}${this.renderFeedback()}`;
|
|
185
214
|
}
|
|
@@ -190,6 +219,12 @@ __decorate([
|
|
|
190
219
|
__decorate([
|
|
191
220
|
property({ attribute: 'auto-grow', reflect: true, type: Boolean })
|
|
192
221
|
], HelixHeadlessTextarea.prototype, "autoGrow", void 0);
|
|
222
|
+
__decorate([
|
|
223
|
+
property({ type: Boolean })
|
|
224
|
+
], HelixHeadlessTextarea.prototype, "clearable", void 0);
|
|
225
|
+
__decorate([
|
|
226
|
+
property({ attribute: 'clear-label' })
|
|
227
|
+
], HelixHeadlessTextarea.prototype, "clearLabel", void 0);
|
|
193
228
|
__decorate([
|
|
194
229
|
property({ type: Number })
|
|
195
230
|
], HelixHeadlessTextarea.prototype, "cols", void 0);
|
|
@@ -214,6 +249,9 @@ __decorate([
|
|
|
214
249
|
__decorate([
|
|
215
250
|
property({ type: Number })
|
|
216
251
|
], HelixHeadlessTextarea.prototype, "rows", void 0);
|
|
252
|
+
__decorate([
|
|
253
|
+
property({ attribute: false })
|
|
254
|
+
], HelixHeadlessTextarea.prototype, "validate", void 0);
|
|
217
255
|
__decorate([
|
|
218
256
|
property()
|
|
219
257
|
], HelixHeadlessTextarea.prototype, "wrap", void 0);
|