@fusion.dev/helix-headless 0.142.1 → 0.144.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 +25381 -1202
- package/dist/accordion/item/accordion-item.d.ts +38 -2
- package/dist/accordion/item/accordion-item.js +38 -6
- package/dist/accordion/root/accordion-root.d.ts +23 -1
- package/dist/accordion/root/accordion-root.js +39 -3
- package/dist/announcement/root/announcement-root.d.ts +11 -7
- package/dist/announcement/root/announcement-root.js +1 -1
- package/dist/app-header/root/app-header-root.d.ts +21 -0
- package/dist/app-header/root/app-header-root.js +31 -5
- package/dist/area-chart/root/area-chart-root.d.ts +12 -4
- package/dist/area-chart/root/area-chart-root.js +39 -11
- package/dist/avatar/group/avatar-group.d.ts +24 -3
- package/dist/avatar/group/avatar-group.js +34 -2
- package/dist/avatar/root/avatar-root.d.ts +17 -1
- package/dist/avatar/root/avatar-root.js +31 -10
- package/dist/badge/root/badge-root.d.ts +12 -0
- package/dist/badge/root/badge-root.js +1 -1
- package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
- package/dist/bar-chart/root/bar-chart-root.js +58 -21
- package/dist/blockquote/root/blockquote-root.d.ts +12 -7
- package/dist/blockquote/root/blockquote-root.js +6 -4
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
- package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
- package/dist/button/root/button-root.d.ts +84 -1
- package/dist/button/root/button-root.js +81 -3
- package/dist/callout/root/callout-root.d.ts +32 -6
- package/dist/callout/root/callout-root.js +26 -7
- package/dist/canvas/root/canvas-root.d.ts +1 -0
- package/dist/canvas/root/canvas-root.js +10 -1
- package/dist/card/root/card-root.d.ts +30 -1
- package/dist/card/root/card-root.js +38 -5
- package/dist/carousel/root/carousel-root.d.ts +47 -5
- package/dist/carousel/root/carousel-root.js +53 -21
- package/dist/chat/composer/chat-composer.d.ts +13 -11
- package/dist/chat/composer/chat-composer.js +6 -12
- package/dist/chat/message/chat-message.js +8 -1
- package/dist/chat/root/chat-root.d.ts +1 -0
- package/dist/chat/root/chat-root.js +2 -1
- package/dist/checkbox/root/checkbox-root.d.ts +7 -0
- package/dist/checkbox/root/checkbox-root.js +9 -3
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
- package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
- package/dist/code/root/code-root.d.ts +1 -1
- package/dist/code-block/lines.d.ts +13 -0
- package/dist/code-block/lines.js +2 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -0
- package/dist/code-block/root/code-block-root.js +44 -3
- package/dist/color-input/root/color-input-root.d.ts +60 -2
- package/dist/color-input/root/color-input-root.js +55 -7
- package/dist/color-picker/channels.d.ts +26 -0
- package/dist/color-picker/channels.js +84 -0
- package/dist/color-picker/root/color-picker-root.d.ts +118 -12
- package/dist/color-picker/root/color-picker-root.js +183 -13
- package/dist/combobox/root/combobox-root.d.ts +126 -3
- package/dist/combobox/root/combobox-root.js +224 -21
- package/dist/command/root/command-root.d.ts +47 -10
- package/dist/command/root/command-root.js +45 -4
- package/dist/copy-button/from.d.ts +22 -0
- package/dist/copy-button/from.js +28 -0
- package/dist/copy-button/root/copy-button-root.d.ts +48 -7
- package/dist/copy-button/root/copy-button-root.js +54 -8
- package/dist/data-table/root/data-table-root.d.ts +164 -10
- package/dist/data-table/root/data-table-root.js +488 -57
- package/dist/date-input/root/date-input-root.d.ts +123 -9
- package/dist/date-input/root/date-input-root.js +147 -45
- package/dist/date-picker/root/date-picker-root.d.ts +229 -18
- package/dist/date-picker/root/date-picker-root.js +342 -46
- package/dist/dialog/description.d.ts +9 -0
- package/dist/dialog/description.js +14 -0
- package/dist/dialog/root/dialog-root.d.ts +101 -10
- package/dist/dialog/root/dialog-root.js +83 -4
- package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
- package/dist/donut-chart/root/donut-chart-root.js +48 -13
- package/dist/drawer/root/drawer-root.d.ts +93 -7
- package/dist/drawer/root/drawer-root.js +126 -5
- package/dist/drawer/swipe-start.d.ts +9 -0
- package/dist/drawer/swipe-start.js +12 -0
- package/dist/drilldown/item/drilldown-item.d.ts +16 -13
- package/dist/drilldown/item/drilldown-item.js +6 -2
- package/dist/drilldown/root/drilldown-root.d.ts +21 -5
- package/dist/drilldown/root/drilldown-root.js +26 -10
- package/dist/element-events.generated.js +42 -13
- package/dist/empty/root/empty-root.d.ts +1 -1
- package/dist/file-input/root/file-input-root.d.ts +65 -1
- package/dist/file-input/root/file-input-root.js +76 -12
- package/dist/file-input/screen.d.ts +35 -0
- package/dist/file-input/screen.js +49 -0
- package/dist/filter-input/menu/filter-menu.d.ts +9 -0
- package/dist/filter-input/menu/filter-menu.js +8 -0
- package/dist/filter-input/root/filter-input-root.d.ts +43 -6
- package/dist/filter-input/root/filter-input-root.js +89 -10
- package/dist/filter-input/suggest.d.ts +17 -0
- package/dist/filter-input/suggest.js +23 -0
- package/dist/format-date/options.d.ts +33 -0
- package/dist/format-date/options.js +42 -0
- package/dist/format-date/root/format-date-root.d.ts +62 -3
- package/dist/format-date/root/format-date-root.js +78 -37
- package/dist/graph/root/graph-root.d.ts +24 -3
- package/dist/graph/root/graph-root.js +66 -12
- package/dist/heatmap/root/buckets.d.ts +2 -1
- package/dist/heatmap/root/buckets.js +5 -1
- package/dist/heatmap/root/heatmap-root.d.ts +47 -9
- package/dist/heatmap/root/heatmap-root.js +46 -18
- package/dist/icon/index.d.ts +2 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon/registry.d.ts +37 -0
- package/dist/icon/registry.js +83 -0
- package/dist/icon/root/icon-root.d.ts +53 -6
- package/dist/icon/root/icon-root.js +72 -4
- package/dist/icon/root/index.d.ts +2 -0
- package/dist/icon/root/index.js +2 -0
- package/dist/icon/set.d.ts +1 -0
- package/dist/icon/set.js +3 -0
- package/dist/icon-button/root/icon-button-root.d.ts +1 -1
- package/dist/image/root/image-root.d.ts +23 -2
- package/dist/image/root/image-root.js +23 -4
- package/dist/input/root/input-root.d.ts +62 -9
- package/dist/input/root/input-root.js +61 -5
- package/dist/kbd/root/kbd-root.d.ts +26 -11
- package/dist/kbd/root/kbd-root.js +35 -38
- package/dist/kbd/shortcut.d.ts +18 -0
- package/dist/kbd/shortcut.js +35 -0
- package/dist/legend/hidden-series.d.ts +8 -0
- package/dist/legend/hidden-series.js +13 -0
- package/dist/legend/root/legend-root.d.ts +63 -0
- package/dist/legend/root/legend-root.js +61 -7
- package/dist/lightbox/item/lightbox-item.d.ts +17 -1
- package/dist/lightbox/item/lightbox-item.js +10 -1
- package/dist/lightbox/root/lightbox-root.d.ts +77 -6
- package/dist/lightbox/root/lightbox-root.js +116 -5
- package/dist/line-chart/root/line-chart-root.d.ts +29 -4
- package/dist/line-chart/root/line-chart-root.js +58 -17
- package/dist/list/item/list-item.d.ts +11 -5
- package/dist/list/item/list-item.js +5 -6
- package/dist/listbox/range.d.ts +17 -0
- package/dist/listbox/range.js +5 -0
- package/dist/listbox/root/listbox-root.d.ts +184 -4
- package/dist/listbox/root/listbox-root.js +229 -23
- package/dist/loader/busy.d.ts +17 -0
- package/dist/loader/busy.js +24 -0
- package/dist/loader/root/loader-root.d.ts +37 -0
- package/dist/loader/root/loader-root.js +52 -3
- package/dist/map/root/map-root.d.ts +19 -4
- package/dist/map/root/map-root.js +36 -7
- package/dist/megamenu/root/megamenu-root.d.ts +10 -1
- package/dist/megamenu/root/megamenu-root.js +10 -1
- package/dist/menu/item/menu-item.d.ts +41 -12
- package/dist/menu/item/menu-item.js +46 -3
- package/dist/menu/root/menu-root.d.ts +32 -2
- package/dist/menu/root/menu-root.js +48 -8
- package/dist/meter/root/meter-root.d.ts +13 -0
- package/dist/meter/root/meter-root.js +24 -5
- package/dist/navigation/root/navigation-root.d.ts +10 -2
- package/dist/navigation/root/navigation-root.js +13 -2
- package/dist/notifications/feed-keys.d.ts +10 -0
- package/dist/notifications/feed-keys.js +14 -0
- package/dist/notifications/group/notification-group.d.ts +1 -0
- package/dist/notifications/notification/notification.d.ts +29 -0
- package/dist/notifications/notification/notification.js +51 -3
- package/dist/notifications/root/notifications-root.d.ts +49 -0
- package/dist/notifications/root/notifications-root.js +76 -2
- package/dist/number-input/root/number-input-root.d.ts +109 -7
- package/dist/number-input/root/number-input-root.js +109 -21
- package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
- package/dist/object-inspector/root/object-inspector-root.js +92 -12
- package/dist/option/root/option-root.d.ts +58 -6
- package/dist/option/root/option-root.js +35 -5
- package/dist/outline/root/outline-root.d.ts +13 -2
- package/dist/outline/root/outline-root.js +4 -2
- package/dist/pagination/root/pagination-root.d.ts +19 -1
- package/dist/pagination/root/pagination-root.js +49 -9
- package/dist/pagination/size/pagination-size.d.ts +13 -3
- package/dist/pagination/size/pagination-size.js +7 -0
- package/dist/pin-input/format.d.ts +7 -0
- package/dist/pin-input/format.js +16 -0
- package/dist/pin-input/root/pin-input-root.d.ts +37 -0
- package/dist/pin-input/root/pin-input-root.js +48 -7
- package/dist/popover/root/popover-root.d.ts +78 -3
- package/dist/popover/root/popover-root.js +74 -5
- package/dist/progress/root/progress-root.d.ts +23 -1
- package/dist/progress/root/progress-root.js +40 -10
- package/dist/qr-code/export.d.ts +31 -0
- package/dist/qr-code/export.js +10 -0
- package/dist/qr-code/root/qr-code-root.d.ts +45 -0
- package/dist/qr-code/root/qr-code-root.js +78 -3
- package/dist/radio/group/radio-group.d.ts +64 -0
- package/dist/radio/group/radio-group.js +66 -12
- package/dist/radio/root/radio-root.d.ts +8 -5
- package/dist/radio/root/radio-root.js +1 -2
- package/dist/rating/root/rating-root.d.ts +49 -1
- package/dist/rating/root/rating-root.js +69 -10
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
- package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
- package/dist/select/root/select-root.d.ts +93 -3
- package/dist/select/root/select-root.js +111 -13
- package/dist/skeleton/root/skeleton-root.d.ts +39 -3
- package/dist/skeleton/root/skeleton-root.js +33 -4
- package/dist/skip-link/root/skip-link-root.d.ts +10 -0
- package/dist/skip-link/root/skip-link-root.js +15 -1
- package/dist/slider/root/slider-root.d.ts +59 -2
- package/dist/slider/root/slider-root.js +82 -8
- package/dist/sparkline/root/sparkline-root.d.ts +9 -10
- package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
- package/dist/speed-dial/item/speed-dial-item.js +7 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
- package/dist/speed-dial/root/speed-dial-root.js +19 -5
- package/dist/splitter/root/splitter-root.d.ts +28 -6
- package/dist/splitter/root/splitter-root.js +35 -1
- package/dist/stat/root/stat-root.d.ts +9 -1
- package/dist/stat/root/stat-root.js +15 -2
- package/dist/steps/root/steps-root.js +1 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/switch/root/switch-root.d.ts +14 -2
- package/dist/switch/root/switch-root.js +7 -1
- package/dist/table/cell/table-cell.d.ts +24 -4
- package/dist/table/cell/table-cell.js +21 -1
- package/dist/table/column/table-column.d.ts +32 -6
- package/dist/table/column/table-column.js +36 -6
- package/dist/table/root/table-root.d.ts +94 -3
- package/dist/table/root/table-root.js +128 -5
- package/dist/table/row/table-row.d.ts +7 -0
- package/dist/table/row/table-row.js +9 -1
- package/dist/tabs/root/tabs-root.d.ts +6 -1
- package/dist/tabs/root/tabs-root.js +6 -2
- package/dist/tag/group/tag-group.d.ts +107 -0
- package/dist/tag/group/tag-group.js +157 -0
- package/dist/tag/index.d.ts +1 -0
- package/dist/tag/index.js +1 -0
- package/dist/tag/root/tag-root.d.ts +83 -1
- package/dist/tag/root/tag-root.js +87 -17
- package/dist/tag/selection.d.ts +10 -0
- package/dist/tag/selection.js +12 -0
- package/dist/textarea/grow.d.ts +22 -0
- package/dist/textarea/grow.js +20 -0
- package/dist/textarea/root/textarea-root.d.ts +13 -0
- package/dist/textarea/root/textarea-root.js +10 -2
- package/dist/time-input/root/time-input-root.d.ts +71 -6
- package/dist/time-input/root/time-input-root.js +110 -44
- package/dist/time-picker/root/time-picker-root.d.ts +155 -26
- package/dist/time-picker/root/time-picker-root.js +192 -63
- package/dist/toast/hotkey.d.ts +22 -0
- package/dist/toast/hotkey.js +23 -0
- package/dist/toast/item/toast-item.d.ts +16 -1
- package/dist/toast/item/toast-item.js +41 -13
- package/dist/toast/root/toast-root.d.ts +105 -8
- package/dist/toast/root/toast-root.js +209 -4
- package/dist/toggle/group/toggle-group.d.ts +95 -16
- package/dist/toggle/group/toggle-group.js +99 -13
- package/dist/toggle/root/toggle-root.d.ts +26 -11
- package/dist/toggle/root/toggle-root.js +14 -6
- package/dist/toolbar/root/toolbar-root.d.ts +55 -15
- package/dist/toolbar/root/toolbar-root.js +99 -16
- package/dist/tooltip/focus-target.d.ts +6 -0
- package/dist/tooltip/focus-target.js +9 -0
- package/dist/tooltip/root/tooltip-root.d.ts +73 -15
- package/dist/tooltip/root/tooltip-root.js +96 -7
- package/dist/tour/naming.d.ts +30 -0
- package/dist/tour/naming.js +10 -0
- package/dist/tour/root/tour-root.d.ts +67 -3
- package/dist/tour/root/tour-root.js +105 -17
- package/dist/tour/stop/tour-stop.d.ts +65 -3
- package/dist/tour/stop/tour-stop.js +61 -11
- package/dist/tour/wait.d.ts +11 -0
- package/dist/tour/wait.js +19 -0
- package/dist/tree/item/tree-item.d.ts +21 -5
- package/dist/tree/item/tree-item.js +14 -4
- package/dist/tree/root/tree-root.d.ts +29 -5
- package/dist/tree/root/tree-root.js +64 -8
- package/dist/trend/root/trend-root.d.ts +36 -1
- package/dist/trend/root/trend-root.js +41 -15
- package/dist/video/root/keys.d.ts +5 -0
- package/dist/video/root/keys.js +13 -1
- package/dist/video/root/video-root.d.ts +19 -0
- package/dist/video/root/video-root.js +48 -4
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
- package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
- package/dist/video-playlist/root/video-playlist-root.js +6 -3
- package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
- package/dist/virtual-list/root/virtual-list-root.js +103 -21
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +9140 -1149
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +2089 -267
|
@@ -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 { AriaForwardController, customElement, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, afterLinkFollowed, customElement, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretDown } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -21,6 +21,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
21
21
|
this.aria = new AriaForwardController(this, {
|
|
22
22
|
target: () => this.partNamed('control'),
|
|
23
23
|
});
|
|
24
|
+
this.allowsCustomValue = false;
|
|
24
25
|
this.autocomplete = 'off';
|
|
25
26
|
this.creatable = false;
|
|
26
27
|
this.createLabel = 'Add';
|
|
@@ -30,10 +31,18 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
30
31
|
this.loadingText = 'Loading';
|
|
31
32
|
this.multiple = false;
|
|
32
33
|
this.placeholder = '';
|
|
34
|
+
this.readOnly = false;
|
|
33
35
|
this.removeLabel = 'Remove {name}';
|
|
36
|
+
this.resultLabel = '{count} result';
|
|
37
|
+
this.resultsLabel = '{count} results';
|
|
34
38
|
this.suggest = false;
|
|
35
39
|
this.typed = '';
|
|
36
40
|
this.suggestion = '';
|
|
41
|
+
this.editing = false;
|
|
42
|
+
this.onCreate = false;
|
|
43
|
+
this.emptied = false;
|
|
44
|
+
this.opening = undefined;
|
|
45
|
+
this.watcher = undefined;
|
|
37
46
|
this.panel = new PopoverController(this, {
|
|
38
47
|
anchor: () => this.partNamed('field'),
|
|
39
48
|
boundary: () => [
|
|
@@ -41,7 +50,10 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
41
50
|
this.partNamed('field'),
|
|
42
51
|
],
|
|
43
52
|
offset: () => 4,
|
|
44
|
-
onDismiss: () =>
|
|
53
|
+
onDismiss: () => {
|
|
54
|
+
this.commitEmptied();
|
|
55
|
+
this.close();
|
|
56
|
+
},
|
|
45
57
|
open: () => this.open,
|
|
46
58
|
placement: 'bottom-start',
|
|
47
59
|
surface: () => this.partNamed('surface'),
|
|
@@ -50,6 +62,9 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
50
62
|
event.stopPropagation();
|
|
51
63
|
const typed = event.target.value;
|
|
52
64
|
this.typed = typed;
|
|
65
|
+
this.editing = true;
|
|
66
|
+
this.onCreate = false;
|
|
67
|
+
this.emptied = typed.trim() === '';
|
|
53
68
|
const narrowing = new HelixFilterEvent({ value: typed });
|
|
54
69
|
if (this.dispatchEvent(narrowing)) {
|
|
55
70
|
this.listbox?.requestFilter(typed);
|
|
@@ -65,13 +80,21 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
65
80
|
return;
|
|
66
81
|
}
|
|
67
82
|
if (event.key === 'Escape') {
|
|
83
|
+
this.emptied = false;
|
|
68
84
|
if (this.open) {
|
|
69
85
|
event.preventDefault();
|
|
70
86
|
this.close();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!this.multiple && this.value !== '' && !this.readOnly) {
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
event.stopPropagation();
|
|
92
|
+
this.requestValue('');
|
|
71
93
|
}
|
|
72
94
|
return;
|
|
73
95
|
}
|
|
74
96
|
if (event.key === 'Tab') {
|
|
97
|
+
this.commitEmptied();
|
|
75
98
|
if (this.open) {
|
|
76
99
|
this.requestOpen(false);
|
|
77
100
|
}
|
|
@@ -80,23 +103,49 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
80
103
|
if (this.multiple && this.tokenKeydown(event, this.typed)) {
|
|
81
104
|
return;
|
|
82
105
|
}
|
|
83
|
-
if (event.key === 'Enter' && this.creation !== '' && !this.showing) {
|
|
106
|
+
if (event.key === 'Enter' && this.creation !== '' && (this.onCreate || !this.showing)) {
|
|
84
107
|
event.preventDefault();
|
|
85
108
|
this.create();
|
|
86
109
|
return;
|
|
87
110
|
}
|
|
88
|
-
if (
|
|
89
|
-
this.
|
|
111
|
+
if (event.key === 'Enter' &&
|
|
112
|
+
this.allowsCustomValue &&
|
|
113
|
+
!this.reachable.some((option) => option.active) &&
|
|
114
|
+
this.commitTyped()) {
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
if (!this.multiple) {
|
|
117
|
+
this.close();
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (!this.open) {
|
|
122
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
const fallback = event.key === 'ArrowDown' ? 'first' : 'last';
|
|
125
|
+
this.opening = this.values.length > 0 ? 'selected' : fallback;
|
|
126
|
+
this.requestOpen(true);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (this.moveAroundCreate(event)) {
|
|
131
|
+
void this.updateComplete.then(() => this.linkActive());
|
|
132
|
+
return;
|
|
90
133
|
}
|
|
91
134
|
this.listbox?.navigate(event);
|
|
92
135
|
void this.listbox?.updateComplete.then(() => this.linkActive());
|
|
93
136
|
};
|
|
137
|
+
this.handleKeypress = (event) => {
|
|
138
|
+
if (event.key === 'Enter' && !this.open && !event.defaultPrevented) {
|
|
139
|
+
this.submitImplicitly();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
94
142
|
this.handleChange = (event) => {
|
|
95
143
|
event.stopPropagation();
|
|
96
144
|
const { value } = event.detail;
|
|
97
145
|
if (!this.requestValue(value)) {
|
|
98
146
|
return;
|
|
99
147
|
}
|
|
148
|
+
this.emptied = false;
|
|
100
149
|
this.typed = '';
|
|
101
150
|
this.suggestion = '';
|
|
102
151
|
this.listbox?.requestFilter('');
|
|
@@ -121,15 +170,27 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
121
170
|
const tag = event.currentTarget;
|
|
122
171
|
this.drop(tag.dataset.value ?? '');
|
|
123
172
|
};
|
|
173
|
+
this.handleLinkFollowed = (event) => {
|
|
174
|
+
afterLinkFollowed(event, () => this.requestOpen(false));
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
requestValue(next) {
|
|
178
|
+
if (this.readOnly) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return super.requestValue(next);
|
|
182
|
+
}
|
|
183
|
+
requestOpen(next) {
|
|
184
|
+
if (next && this.readOnly) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
return super.requestOpen(next);
|
|
124
188
|
}
|
|
125
189
|
get selectedIndex() {
|
|
126
190
|
return this.listbox?.selectedIndex ?? -1;
|
|
127
191
|
}
|
|
128
192
|
set selectedIndex(at) {
|
|
129
|
-
|
|
130
|
-
if (listbox) {
|
|
131
|
-
listbox.selectedIndex = at;
|
|
132
|
-
}
|
|
193
|
+
this.value = this.listbox?.options[at]?.value ?? '';
|
|
133
194
|
}
|
|
134
195
|
get type() {
|
|
135
196
|
return this.multiple ? 'select-multiple' : 'select-one';
|
|
@@ -202,6 +263,59 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
202
263
|
this.requestOpen(false);
|
|
203
264
|
this.partNamed('control')?.focus();
|
|
204
265
|
}
|
|
266
|
+
commitEmptied() {
|
|
267
|
+
if (this.emptied && !this.multiple && this.value !== '') {
|
|
268
|
+
this.requestValue('');
|
|
269
|
+
}
|
|
270
|
+
this.emptied = false;
|
|
271
|
+
this.commitTyped();
|
|
272
|
+
}
|
|
273
|
+
commitTyped() {
|
|
274
|
+
const typed = this.typed.trim();
|
|
275
|
+
if (!this.allowsCustomValue || !this.editing || typed === '') {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
const named = (this.listbox?.options ?? []).find((option) => option.text.trim().toLowerCase() === typed.toLowerCase());
|
|
279
|
+
const answer = named?.value ?? typed;
|
|
280
|
+
if (this.multiple) {
|
|
281
|
+
if (!this.values.includes(answer)) {
|
|
282
|
+
this.requestValue([...this.values, answer].join(','));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else if (answer !== this.value) {
|
|
286
|
+
this.requestValue(answer);
|
|
287
|
+
}
|
|
288
|
+
this.typed = '';
|
|
289
|
+
this.suggestion = '';
|
|
290
|
+
this.editing = false;
|
|
291
|
+
this.listbox?.requestFilter('');
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
get reachable() {
|
|
295
|
+
return (this.listbox?.options ?? []).filter((option) => !option.hidden && !option.disabled);
|
|
296
|
+
}
|
|
297
|
+
moveAroundCreate(event) {
|
|
298
|
+
if (this.creation === '' || (event.key !== 'ArrowDown' && event.key !== 'ArrowUp')) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
const down = event.key === 'ArrowDown';
|
|
302
|
+
if (this.onCreate) {
|
|
303
|
+
event.preventDefault();
|
|
304
|
+
this.onCreate = false;
|
|
305
|
+
this.listbox?.highlight(down ? 'first' : 'last');
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
const reachable = this.reachable;
|
|
309
|
+
const at = reachable.findIndex((option) => option.active);
|
|
310
|
+
const edge = down ? reachable.length - 1 : 0;
|
|
311
|
+
if (reachable.length === 0 || at === edge) {
|
|
312
|
+
event.preventDefault();
|
|
313
|
+
this.onCreate = true;
|
|
314
|
+
this.listbox?.highlight('none');
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
205
319
|
completionFor(typed) {
|
|
206
320
|
if (typed === '') {
|
|
207
321
|
return '';
|
|
@@ -210,14 +324,19 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
210
324
|
const match = (this.listbox?.options ?? []).find((option) => !option.hidden && !option.disabled && option.text.toLowerCase().startsWith(needle));
|
|
211
325
|
return match && match.text.length > typed.length ? match.text : '';
|
|
212
326
|
}
|
|
327
|
+
get blocksImplicitSubmission() {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
213
330
|
linkActive() {
|
|
214
331
|
const control = this.partNamed('control');
|
|
215
332
|
if (!control || !('ariaActiveDescendantElement' in control)) {
|
|
216
333
|
return;
|
|
217
334
|
}
|
|
218
|
-
const active = this.open
|
|
219
|
-
?
|
|
220
|
-
:
|
|
335
|
+
const active = !this.open
|
|
336
|
+
? undefined
|
|
337
|
+
: this.onCreate
|
|
338
|
+
? this.partNamed('create')
|
|
339
|
+
: (this.listbox?.options ?? []).find((option) => option.active && !option.hidden);
|
|
221
340
|
control.ariaActiveDescendantElement = active ?? null;
|
|
222
341
|
}
|
|
223
342
|
removeLastToken() {
|
|
@@ -235,6 +354,37 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
235
354
|
}
|
|
236
355
|
this.reportRequired(this.value === '', 'Choose one to continue.', 'control');
|
|
237
356
|
}
|
|
357
|
+
connectedCallback() {
|
|
358
|
+
super.connectedCallback();
|
|
359
|
+
this.addEventListener('helix-select', this.handleLinkFollowed);
|
|
360
|
+
this.watcher = new MutationObserver(() => this.requestUpdate());
|
|
361
|
+
this.watcher.observe(this, {
|
|
362
|
+
attributeFilter: ['label', 'value'],
|
|
363
|
+
characterData: true,
|
|
364
|
+
childList: true,
|
|
365
|
+
subtree: true,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
disconnectedCallback() {
|
|
369
|
+
super.disconnectedCallback();
|
|
370
|
+
this.removeEventListener('helix-select', this.handleLinkFollowed);
|
|
371
|
+
this.watcher?.disconnect();
|
|
372
|
+
this.watcher = undefined;
|
|
373
|
+
}
|
|
374
|
+
willUpdate(changed) {
|
|
375
|
+
super.willUpdate(changed);
|
|
376
|
+
if (this.childrenKnown && this.defaultValue === '' && !this.hasAttribute('default-value')) {
|
|
377
|
+
const declared = optionsAmong(this.knownChildren)
|
|
378
|
+
.filter((option) => option.defaultSelected)
|
|
379
|
+
.map((option) => option.value);
|
|
380
|
+
if (declared.length > 0) {
|
|
381
|
+
this.defaultValue = this.multiple ? declared.join(',') : (declared.at(-1) ?? '');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (this.creation === '') {
|
|
385
|
+
this.onCreate = false;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
238
388
|
firstUpdated(changed) {
|
|
239
389
|
super.firstUpdated(changed);
|
|
240
390
|
this.finishHydration();
|
|
@@ -244,7 +394,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
244
394
|
this.sync();
|
|
245
395
|
this.linkActive();
|
|
246
396
|
const control = this.partNamed('control');
|
|
247
|
-
const wanted = this.
|
|
397
|
+
const wanted = this.fieldText;
|
|
248
398
|
if (control && control.value !== wanted) {
|
|
249
399
|
control.value = wanted;
|
|
250
400
|
}
|
|
@@ -254,8 +404,26 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
254
404
|
if (!this.open) {
|
|
255
405
|
this.typed = '';
|
|
256
406
|
this.suggestion = '';
|
|
407
|
+
this.editing = false;
|
|
408
|
+
this.onCreate = false;
|
|
257
409
|
this.listbox?.requestFilter('');
|
|
258
410
|
}
|
|
411
|
+
else if (changed.has('open')) {
|
|
412
|
+
if (this.opening !== undefined) {
|
|
413
|
+
this.listbox?.highlight(this.opening);
|
|
414
|
+
this.opening = undefined;
|
|
415
|
+
void this.listbox?.updateComplete.then(() => this.linkActive());
|
|
416
|
+
}
|
|
417
|
+
if (control && !this.editing && !this.multiple && control.value !== '') {
|
|
418
|
+
control.select();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
get fieldText() {
|
|
423
|
+
if (this.multiple || (this.open && this.editing)) {
|
|
424
|
+
return this.suggestion || this.typed;
|
|
425
|
+
}
|
|
426
|
+
return this.word;
|
|
259
427
|
}
|
|
260
428
|
renderListbox() {
|
|
261
429
|
return html `<${this.tag('listbox')}
|
|
@@ -268,6 +436,8 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
268
436
|
aria-label=${this.listLabel}
|
|
269
437
|
empty-text=${this.emptyText}
|
|
270
438
|
loading-text=${this.loadingText}
|
|
439
|
+
result-label=${this.resultLabel}
|
|
440
|
+
results-label=${this.resultsLabel}
|
|
271
441
|
?loading=${this.loading}
|
|
272
442
|
?multiple=${this.multiple}
|
|
273
443
|
.value=${this.value}
|
|
@@ -282,15 +452,20 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
282
452
|
property, so nothing else would schedule the update that fixes
|
|
283
453
|
it. -->
|
|
284
454
|
<slot @slotchange=${() => this.requestUpdate()}></slot>
|
|
455
|
+
<!-- Handed on to the list's own, with the text as this slot's fallback:
|
|
456
|
+
a slot passed into another is assigned there whether or not anything
|
|
457
|
+
fills it, so the list's fallback would never show. -->
|
|
458
|
+
<slot name="empty" slot="empty">${this.emptyText}</slot>
|
|
459
|
+
<slot name="loading" slot="loading">${this.loadingText}</slot>
|
|
285
460
|
</${this.tag('listbox')}>`;
|
|
286
461
|
}
|
|
287
462
|
renderTag(option) {
|
|
288
463
|
return html `<${this.tag('tag')}
|
|
289
464
|
part="tag"
|
|
290
|
-
exportparts="dismiss: tag-dismiss, dismiss-mark: tag-dismiss-mark, label: tag-label, start: tag-start"
|
|
465
|
+
exportparts="cell: tag-cell, dismiss: tag-dismiss, dismiss-mark: tag-dismiss-mark, label: tag-label, link: tag-link, start: tag-start"
|
|
291
466
|
data-value=${option.value}
|
|
292
467
|
dismiss-label=${fillTemplate(this.removeLabel, { name: option.text })}
|
|
293
|
-
?dismissible=${!this.isDisabled}
|
|
468
|
+
?dismissible=${!this.isDisabled && !this.readOnly}
|
|
294
469
|
@helix-dismiss=${this.handleDismiss}
|
|
295
470
|
>${option.text}</${this.tag('tag')}
|
|
296
471
|
>`;
|
|
@@ -302,6 +477,18 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
302
477
|
</svg>
|
|
303
478
|
</slot>`;
|
|
304
479
|
}
|
|
480
|
+
renderCreate() {
|
|
481
|
+
if (this.creation === '') {
|
|
482
|
+
return nothing;
|
|
483
|
+
}
|
|
484
|
+
return this.onCreate
|
|
485
|
+
? html `<button part="create create-active" id="create" type="button" @click=${() => this.create()}>
|
|
486
|
+
${this.createLabel} "${this.creation}"
|
|
487
|
+
</button>`
|
|
488
|
+
: html `<button part="create" id="create" type="button" @click=${() => this.create()}>
|
|
489
|
+
${this.createLabel} "${this.creation}"
|
|
490
|
+
</button>`;
|
|
491
|
+
}
|
|
305
492
|
render() {
|
|
306
493
|
return html `${this.renderLabel()}
|
|
307
494
|
<div part="field" @click=${this.handleFieldClick}>
|
|
@@ -323,24 +510,25 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
323
510
|
aria-invalid=${this.invalidity ?? nothing}
|
|
324
511
|
placeholder=${(this.chosen.length > 0 || this.unresolved ? '' : this.placeholder) || nothing}
|
|
325
512
|
?disabled=${this.isDisabled}
|
|
326
|
-
|
|
513
|
+
?readonly=${this.readOnly}
|
|
514
|
+
.value=${this.fieldText}
|
|
327
515
|
@input=${this.handleInput}
|
|
328
516
|
@keydown=${this.handleKeydown}
|
|
517
|
+
@keypress=${this.handleKeypress}
|
|
329
518
|
/>
|
|
330
519
|
<slot name="end"></slot>
|
|
331
520
|
${this.renderIndicator()}
|
|
332
521
|
</div>
|
|
333
522
|
<div part="surface" popover="manual" ?hidden=${!this.open}>
|
|
334
523
|
${this.renderListbox()}
|
|
335
|
-
${this.
|
|
336
|
-
? nothing
|
|
337
|
-
: html `<button part="create" type="button" @click=${() => this.create()}>
|
|
338
|
-
${this.createLabel} "${this.creation}"
|
|
339
|
-
</button>`}
|
|
524
|
+
${this.renderCreate()}
|
|
340
525
|
</div>
|
|
341
526
|
${this.renderHint()}${this.renderFeedback()}`;
|
|
342
527
|
}
|
|
343
528
|
};
|
|
529
|
+
__decorate([
|
|
530
|
+
property({ attribute: 'allows-custom-value', type: Boolean })
|
|
531
|
+
], HelixHeadlessCombobox.prototype, "allowsCustomValue", void 0);
|
|
344
532
|
__decorate([
|
|
345
533
|
property()
|
|
346
534
|
], HelixHeadlessCombobox.prototype, "autocomplete", void 0);
|
|
@@ -368,9 +556,18 @@ __decorate([
|
|
|
368
556
|
__decorate([
|
|
369
557
|
property()
|
|
370
558
|
], HelixHeadlessCombobox.prototype, "placeholder", void 0);
|
|
559
|
+
__decorate([
|
|
560
|
+
property({ attribute: 'readonly', reflect: true, type: Boolean })
|
|
561
|
+
], HelixHeadlessCombobox.prototype, "readOnly", void 0);
|
|
371
562
|
__decorate([
|
|
372
563
|
property({ attribute: 'remove-label' })
|
|
373
564
|
], HelixHeadlessCombobox.prototype, "removeLabel", void 0);
|
|
565
|
+
__decorate([
|
|
566
|
+
property({ attribute: 'result-label' })
|
|
567
|
+
], HelixHeadlessCombobox.prototype, "resultLabel", void 0);
|
|
568
|
+
__decorate([
|
|
569
|
+
property({ attribute: 'results-label' })
|
|
570
|
+
], HelixHeadlessCombobox.prototype, "resultsLabel", void 0);
|
|
374
571
|
__decorate([
|
|
375
572
|
property({ type: Boolean })
|
|
376
573
|
], HelixHeadlessCombobox.prototype, "suggest", void 0);
|
|
@@ -380,6 +577,12 @@ __decorate([
|
|
|
380
577
|
__decorate([
|
|
381
578
|
state()
|
|
382
579
|
], HelixHeadlessCombobox.prototype, "suggestion", void 0);
|
|
580
|
+
__decorate([
|
|
581
|
+
state()
|
|
582
|
+
], HelixHeadlessCombobox.prototype, "editing", void 0);
|
|
583
|
+
__decorate([
|
|
584
|
+
state()
|
|
585
|
+
], HelixHeadlessCombobox.prototype, "onCreate", void 0);
|
|
383
586
|
HelixHeadlessCombobox = __decorate([
|
|
384
587
|
customElement('helix-headless-combobox')
|
|
385
588
|
], HelixHeadlessCombobox);
|
|
@@ -14,7 +14,8 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
14
14
|
*
|
|
15
15
|
* The palette keeps no value. It is not a form control and submits nothing.
|
|
16
16
|
* Choosing an option dispatches `helix-select` once. To remember the last
|
|
17
|
-
* command, store it yourself.
|
|
17
|
+
* command, store it yourself. An option with `href` is a link to a page, which
|
|
18
|
+
* the browser follows once the palette has closed.
|
|
18
19
|
*
|
|
19
20
|
* The hotkey listener is on the document, so the hotkey works from anywhere on
|
|
20
21
|
* the page, including inside another control's text field, whether or not the
|
|
@@ -22,7 +23,8 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
22
23
|
* write one binding.
|
|
23
24
|
*
|
|
24
25
|
* The filter is cleared when the palette closes, so each opening starts from
|
|
25
|
-
* the full list. Combobox and Select do the same.
|
|
26
|
+
* the full list. Combobox and Select do the same. As typing narrows the list, a
|
|
27
|
+
* screen reader hears how many commands are left, such as "3 commands".
|
|
26
28
|
*
|
|
27
29
|
* @since 0.1.0
|
|
28
30
|
* @status stable
|
|
@@ -31,14 +33,22 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
31
33
|
* @documentation https://fusion.dev/helix/components/command
|
|
32
34
|
*
|
|
33
35
|
* @slot - The commands, and any groups of them.
|
|
36
|
+
* @slot empty - What the palette shows when typing matches no commands, for content richer than `empty-text`.
|
|
34
37
|
* @slot footer - Content under the list, such as the keys that work in the palette.
|
|
38
|
+
* @slot loading - What the palette shows while the commands load, for content richer than `loading-text`.
|
|
35
39
|
*
|
|
36
40
|
* @event {HelixBeforeCloseEvent} helix-before-close - The palette is about to close. Cancelable: cancel it to keep it open.
|
|
37
41
|
* @event {HelixBeforeOpenEvent} helix-before-open - The palette is about to open. Cancelable: cancel it to keep it closed.
|
|
38
|
-
* @event {
|
|
39
|
-
* @event {
|
|
42
|
+
* @event {HelixFilterEvent} helix-filter - Fired as the user types, with the text the list is filtered by. Cancelable: cancel it to leave the list unfiltered and filter the commands yourself, for example on a server while `loading` is set.
|
|
43
|
+
* @event {HelixSelectEvent} helix-select - A command was chosen, with its `href` where the option is a link. Cancelable: cancel it to keep the palette open, and to keep the browser from following the link.
|
|
44
|
+
* @event {ToggleEvent} toggle - The palette opened or closed. The event carries `newState` and `oldState`.
|
|
40
45
|
*
|
|
41
46
|
* @csspart dialog - The box of the dialog the palette opens in, forwarded from `Dialog`.
|
|
47
|
+
* @csspart dialog-body - The dialog's slot for its content, which holds the list. It draws no box until you give it one.
|
|
48
|
+
* @csspart dialog-dismiss - The dialog's close control, drawn when the dialog is `dismissible`.
|
|
49
|
+
* @csspart dialog-dismiss-mark - The glyph on the dialog's close control, where none is slotted.
|
|
50
|
+
* @csspart dialog-footer - The dialog's slot for its actions, which holds the `footer` row. It draws no box until you give it one.
|
|
51
|
+
* @csspart dialog-header - The dialog's slot for its title. It draws no box until you give it one.
|
|
42
52
|
* @csspart footer - The row under the list.
|
|
43
53
|
* @csspart listbox - The listbox inside the palette.
|
|
44
54
|
* @csspart listbox-empty - The text shown when the filter matches no commands.
|
|
@@ -48,7 +58,7 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
48
58
|
* @csspart listbox-hint - Help text under the list.
|
|
49
59
|
* @csspart listbox-items - The list of commands.
|
|
50
60
|
* @csspart listbox-label - The label above the list.
|
|
51
|
-
* @csspart listbox-live - The listbox's `live` part, a live region that holds the empty and loading text for screen readers.
|
|
61
|
+
* @csspart listbox-live - The listbox's `live` part, a live region that holds the empty and loading text, and how many commands typing left, for screen readers.
|
|
52
62
|
* @csspart listbox-loading - The text shown while the commands are loading.
|
|
53
63
|
* @csspart listbox-search - The region that holds the filter field.
|
|
54
64
|
* @csspart listbox-search-field - The filter field.
|
|
@@ -60,6 +70,12 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
|
|
|
60
70
|
* The text shown when the filter matches no commands.
|
|
61
71
|
*/
|
|
62
72
|
emptyText: string;
|
|
73
|
+
/**
|
|
74
|
+
* How long typing rests before the commands are filtered, in milliseconds,
|
|
75
|
+
* so a palette filtered on a server sends one `helix-filter` for a word.
|
|
76
|
+
* `0` filters on every keystroke. See Listbox's `filter-delay`.
|
|
77
|
+
*/
|
|
78
|
+
filterDelay: number;
|
|
63
79
|
/**
|
|
64
80
|
* The key that opens the palette, written as `mod+k`, `shift+p`, or `k`.
|
|
65
81
|
*
|
|
@@ -72,10 +88,32 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
|
|
|
72
88
|
* Accessible name for the overlay, which has no visible heading.
|
|
73
89
|
*/
|
|
74
90
|
label: string;
|
|
91
|
+
/**
|
|
92
|
+
* Whether the commands are still loading, for a palette that asks a server
|
|
93
|
+
* for them as the user types.
|
|
94
|
+
*
|
|
95
|
+
* Passed to the list, which shows `loading-text` and tells screen readers.
|
|
96
|
+
*/
|
|
97
|
+
loading: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* The text shown while the commands load.
|
|
100
|
+
*/
|
|
101
|
+
loadingText: string;
|
|
75
102
|
/**
|
|
76
103
|
* The text shown in the filter field before anything is typed.
|
|
77
104
|
*/
|
|
78
105
|
placeholder: string;
|
|
106
|
+
/**
|
|
107
|
+
* What a screen reader hears when typing leaves one command. `{count}` is
|
|
108
|
+
* the count.
|
|
109
|
+
*/
|
|
110
|
+
resultLabel: string;
|
|
111
|
+
/**
|
|
112
|
+
* What a screen reader hears when typing leaves any other number of
|
|
113
|
+
* commands. `{count}` is the count, and `Intl.PluralRules` picks between the
|
|
114
|
+
* two.
|
|
115
|
+
*/
|
|
116
|
+
resultsLabel: string;
|
|
79
117
|
/**
|
|
80
118
|
* Whether the consumer put anything under the list.
|
|
81
119
|
*
|
|
@@ -119,12 +157,11 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
|
|
|
119
157
|
*/
|
|
120
158
|
private readonly handleChange;
|
|
121
159
|
/**
|
|
122
|
-
* The row under the keyboard, read from the
|
|
160
|
+
* The row under the keyboard, read from the `active` property the listbox
|
|
161
|
+
* writes on each option.
|
|
123
162
|
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* already published: asking the listbox would mean a second channel saying
|
|
127
|
-
* what the markup says.
|
|
163
|
+
* Off the options rather than a reference the listbox hands over, because
|
|
164
|
+
* they are this element's own light DOM children and already say it.
|
|
128
165
|
*/
|
|
129
166
|
private get activeOption();
|
|
130
167
|
/**
|
|
@@ -22,9 +22,14 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
|
|
|
22
22
|
constructor() {
|
|
23
23
|
super(...arguments);
|
|
24
24
|
this.emptyText = 'No commands';
|
|
25
|
+
this.filterDelay = 0;
|
|
25
26
|
this.hotkey = 'mod+k';
|
|
26
27
|
this.label = 'Commands';
|
|
28
|
+
this.loading = false;
|
|
29
|
+
this.loadingText = 'Loading';
|
|
27
30
|
this.placeholder = 'Search commands';
|
|
31
|
+
this.resultLabel = '{count} command';
|
|
32
|
+
this.resultsLabel = '{count} commands';
|
|
28
33
|
this.footed = false;
|
|
29
34
|
this.handleHotkey = (event) => {
|
|
30
35
|
if (this.hotkey === '') {
|
|
@@ -71,16 +76,27 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
|
|
|
71
76
|
}
|
|
72
77
|
};
|
|
73
78
|
this.swallowOptionSelect = (event) => {
|
|
74
|
-
if (event.target
|
|
75
|
-
|
|
79
|
+
if (event.target === this) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
event.stopImmediatePropagation();
|
|
83
|
+
const { href, value } = event.detail;
|
|
84
|
+
if (href === undefined) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!this.dispatchEvent(new HelixSelectEvent({ href, value }))) {
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
return;
|
|
76
90
|
}
|
|
91
|
+
this.requestOpen(false);
|
|
77
92
|
};
|
|
78
93
|
}
|
|
79
94
|
get listbox() {
|
|
80
95
|
return this.partNamed('listbox');
|
|
81
96
|
}
|
|
82
97
|
get activeOption() {
|
|
83
|
-
return this.
|
|
98
|
+
return (this.listbox?.options.find((option) => option.active && !option.hidden) ??
|
|
99
|
+
this.querySelector('[data-active]'));
|
|
84
100
|
}
|
|
85
101
|
connectedCallback() {
|
|
86
102
|
super.connectedCallback();
|
|
@@ -122,7 +138,8 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
|
|
|
122
138
|
}
|
|
123
139
|
renderDialog() {
|
|
124
140
|
return html `<${this.tag('dialog')}
|
|
125
|
-
exportparts="dialog
|
|
141
|
+
exportparts="body: dialog-body, dialog, dismiss: dialog-dismiss, dismiss-mark: dialog-dismiss-mark,
|
|
142
|
+
footer: dialog-footer, header: dialog-header"
|
|
126
143
|
label=${this.label}
|
|
127
144
|
.open=${this.open}
|
|
128
145
|
@helix-before-close=${() => {
|
|
@@ -139,13 +156,22 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
|
|
|
139
156
|
search-field: listbox-search-field"
|
|
140
157
|
aria-label=${this.label}
|
|
141
158
|
empty-text=${this.emptyText}
|
|
159
|
+
filter-delay=${this.filterDelay}
|
|
142
160
|
filter-label=${this.placeholder}
|
|
161
|
+
loading-text=${this.loadingText}
|
|
162
|
+
result-label=${this.resultLabel}
|
|
163
|
+
results-label=${this.resultsLabel}
|
|
164
|
+
?loading=${this.loading}
|
|
143
165
|
filterable
|
|
144
166
|
@helix-before-change=${this.handleChange}
|
|
145
167
|
@change=${this.stopInner}
|
|
146
168
|
@input=${this.stopInner}
|
|
147
169
|
>
|
|
148
170
|
<slot></slot>
|
|
171
|
+
<!-- Handed on with the text as the fallback, for the reason Combobox
|
|
172
|
+
gives: the list's own fallback never shows behind a passed slot. -->
|
|
173
|
+
<slot name="empty" slot="empty">${this.emptyText}</slot>
|
|
174
|
+
<slot name="loading" slot="loading">${this.loadingText}</slot>
|
|
149
175
|
</${this.tag('listbox')}>
|
|
150
176
|
<div ?hidden=${!this.footed} part="footer" slot="footer">
|
|
151
177
|
<slot
|
|
@@ -164,15 +190,30 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
|
|
|
164
190
|
__decorate([
|
|
165
191
|
property({ attribute: 'empty-text' })
|
|
166
192
|
], HelixHeadlessCommand.prototype, "emptyText", void 0);
|
|
193
|
+
__decorate([
|
|
194
|
+
property({ attribute: 'filter-delay', type: Number })
|
|
195
|
+
], HelixHeadlessCommand.prototype, "filterDelay", void 0);
|
|
167
196
|
__decorate([
|
|
168
197
|
property()
|
|
169
198
|
], HelixHeadlessCommand.prototype, "hotkey", void 0);
|
|
170
199
|
__decorate([
|
|
171
200
|
property()
|
|
172
201
|
], HelixHeadlessCommand.prototype, "label", void 0);
|
|
202
|
+
__decorate([
|
|
203
|
+
property({ reflect: true, type: Boolean })
|
|
204
|
+
], HelixHeadlessCommand.prototype, "loading", void 0);
|
|
205
|
+
__decorate([
|
|
206
|
+
property({ attribute: 'loading-text' })
|
|
207
|
+
], HelixHeadlessCommand.prototype, "loadingText", void 0);
|
|
173
208
|
__decorate([
|
|
174
209
|
property()
|
|
175
210
|
], HelixHeadlessCommand.prototype, "placeholder", void 0);
|
|
211
|
+
__decorate([
|
|
212
|
+
property({ attribute: 'result-label' })
|
|
213
|
+
], HelixHeadlessCommand.prototype, "resultLabel", void 0);
|
|
214
|
+
__decorate([
|
|
215
|
+
property({ attribute: 'results-label' })
|
|
216
|
+
], HelixHeadlessCommand.prototype, "resultsLabel", void 0);
|
|
176
217
|
__decorate([
|
|
177
218
|
state()
|
|
178
219
|
], HelixHeadlessCommand.prototype, "footed", void 0);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** What a `from` reference names: an element by its id, and what to read from it. */
|
|
2
|
+
export interface FromReference {
|
|
3
|
+
/** An attribute to read, written `id[attribute]`. */
|
|
4
|
+
readonly attribute?: string;
|
|
5
|
+
/** The id of the element. */
|
|
6
|
+
readonly id: string;
|
|
7
|
+
/** A property to read, written `id.property`. */
|
|
8
|
+
readonly property?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Reads a `from` reference: `id` for the element's text, `id[attribute]` for
|
|
12
|
+
* an attribute, and `id.property` for a property. Web Awesome's Copy Button
|
|
13
|
+
* takes the same three shapes.
|
|
14
|
+
*
|
|
15
|
+
* `null` for a reference with no id, or with anything after the brackets.
|
|
16
|
+
*/
|
|
17
|
+
export declare const parseFrom: (reference: string) => FromReference | null;
|
|
18
|
+
/**
|
|
19
|
+
* The text a `from` reference names, looked up in the tree `scope` is in, or
|
|
20
|
+
* `null` where the element or its attribute is not there.
|
|
21
|
+
*/
|
|
22
|
+
export declare const readFrom: (reference: string, scope: Element) => string | null;
|