@threadlabs/looma 0.5.1 → 0.5.2
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/README.md +1 -1
- package/components/ui-button/ui-button.html +13 -0
- package/components/ui-combobox/ui-combobox.html +12 -4
- package/components/ui-dialog/ui-dialog.html +13 -0
- package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +1 -1
- package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +1 -1
- package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +6 -2
- package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +20 -4
- package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +8 -4
- package/components/ui-form-field/ui-form-field.html +18 -7
- package/components/ui-icon/ui-icon.html +5 -1
- package/components/ui-icon-button/ui-icon-button.html +30 -0
- package/components/ui-popover/ui-popover.js +10 -2
- package/components/ui-search-shell/ui-search-shell.html +7 -0
- package/components/ui-search-shell/ui-search-shell.js +9 -0
- package/components/ui-tabs/ui-tabs.html +1 -1
- package/components/ui-toast-region/ui-toast-region.html +1 -1
- package/components/ui-tree-item/ui-tree-item.html +6 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/styles/ui-affordance-scope.css +1 -1
- package/styles/ui-avatar-group.css +1 -1
- package/styles/ui-avatar.css +1 -1
- package/styles/ui-badge.css +1 -1
- package/styles/ui-button.css +11 -1
- package/styles/ui-callout.css +1 -1
- package/styles/ui-checkbox.css +1 -1
- package/styles/ui-cluster.css +1 -1
- package/styles/ui-combobox.css +1 -1
- package/styles/ui-container.css +1 -1
- package/styles/ui-context-menu.css +1 -1
- package/styles/ui-dialog.css +18 -1
- package/styles/ui-disclosure.css +1 -1
- package/styles/ui-editable.css +1 -1
- package/styles/ui-editor-insert-table-grid.css +1 -1
- package/styles/ui-editor-mention-menu.css +1 -1
- package/styles/ui-editor-slash-menu.css +1 -1
- package/styles/ui-editor-table-context-menu.css +1 -1
- package/styles/ui-editor-table-overlay.css +1 -1
- package/styles/ui-editor-table-toolbar.css +1 -1
- package/styles/ui-editor-toolbar.css +1 -1
- package/styles/ui-floating-action-button.css +1 -1
- package/styles/ui-form-field.css +24 -10
- package/styles/ui-grid.css +1 -1
- package/styles/ui-icon-button.css +36 -1
- package/styles/ui-icon.css +1 -1
- package/styles/ui-input.css +1 -1
- package/styles/ui-menu-item.css +1 -1
- package/styles/ui-menu.css +1 -1
- package/styles/ui-popover.css +1 -1
- package/styles/ui-radio-group.css +1 -1
- package/styles/ui-radio.css +1 -1
- package/styles/ui-reel.css +1 -1
- package/styles/ui-search-result-row.css +1 -1
- package/styles/ui-search-shell.css +11 -2
- package/styles/ui-select.css +1 -1
- package/styles/ui-separator.css +1 -1
- package/styles/ui-sidebar.css +1 -1
- package/styles/ui-stack.css +1 -1
- package/styles/ui-switch.css +1 -1
- package/styles/ui-switcher.css +1 -1
- package/styles/ui-tabs.css +1 -1
- package/styles/ui-textarea.css +1 -1
- package/styles/ui-toast-region.css +1 -1
- package/styles/ui-tooltip.css +1 -1
- package/styles/ui-top-bar.css +1 -1
- package/styles/ui-tree-item.css +10 -2
- package/styles/ui-tree.css +1 -1
- package/vanilla/UiAffordanceScope.d.ts +1 -1
- package/vanilla/UiAffordanceScope.js +2 -2
- package/vanilla/UiAvatar.d.ts +1 -1
- package/vanilla/UiAvatar.js +2 -2
- package/vanilla/UiAvatarGroup.d.ts +1 -1
- package/vanilla/UiAvatarGroup.js +2 -2
- package/vanilla/UiBadge.d.ts +1 -1
- package/vanilla/UiBadge.js +2 -2
- package/vanilla/UiButton.d.ts +3 -1
- package/vanilla/UiButton.js +3 -3
- package/vanilla/UiCallout.d.ts +1 -1
- package/vanilla/UiCallout.js +2 -2
- package/vanilla/UiCheckbox.d.ts +1 -1
- package/vanilla/UiCheckbox.js +2 -2
- package/vanilla/UiCluster.d.ts +1 -1
- package/vanilla/UiCluster.js +2 -2
- package/vanilla/UiCombobox.d.ts +1 -1
- package/vanilla/UiCombobox.js +3 -3
- package/vanilla/UiContainer.d.ts +1 -1
- package/vanilla/UiContainer.js +2 -2
- package/vanilla/UiContextMenu.d.ts +1 -1
- package/vanilla/UiContextMenu.js +2 -2
- package/vanilla/UiDialog.d.ts +1 -1
- package/vanilla/UiDialog.js +2 -2
- package/vanilla/UiDisclosure.d.ts +1 -1
- package/vanilla/UiDisclosure.js +2 -2
- package/vanilla/UiEditable.d.ts +1 -1
- package/vanilla/UiEditable.js +2 -2
- package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
- package/vanilla/UiEditorInsertTableGrid.js +3 -3
- package/vanilla/UiEditorMentionMenu.d.ts +1 -1
- package/vanilla/UiEditorMentionMenu.js +3 -3
- package/vanilla/UiEditorSlashMenu.d.ts +1 -1
- package/vanilla/UiEditorSlashMenu.js +2 -2
- package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
- package/vanilla/UiEditorTableContextMenu.js +3 -3
- package/vanilla/UiEditorTableOverlay.d.ts +1 -1
- package/vanilla/UiEditorTableOverlay.js +3 -3
- package/vanilla/UiEditorTableToolbar.d.ts +1 -1
- package/vanilla/UiEditorTableToolbar.js +3 -3
- package/vanilla/UiEditorToolbar.d.ts +1 -1
- package/vanilla/UiEditorToolbar.js +2 -2
- package/vanilla/UiFloatingActionButton.d.ts +1 -1
- package/vanilla/UiFloatingActionButton.js +2 -2
- package/vanilla/UiFormField.d.ts +1 -1
- package/vanilla/UiFormField.js +15 -6
- package/vanilla/UiGrid.d.ts +1 -1
- package/vanilla/UiGrid.js +2 -2
- package/vanilla/UiIcon.d.ts +1 -1
- package/vanilla/UiIcon.js +3 -3
- package/vanilla/UiIconButton.d.ts +1 -1
- package/vanilla/UiIconButton.js +2 -2
- package/vanilla/UiInput.d.ts +1 -1
- package/vanilla/UiInput.js +2 -2
- package/vanilla/UiMenu.d.ts +1 -1
- package/vanilla/UiMenu.js +2 -2
- package/vanilla/UiMenuItem.d.ts +1 -1
- package/vanilla/UiMenuItem.js +2 -2
- package/vanilla/UiPopover.d.ts +1 -1
- package/vanilla/UiPopover.js +2 -2
- package/vanilla/UiRadio.d.ts +1 -1
- package/vanilla/UiRadio.js +2 -2
- package/vanilla/UiRadioGroup.d.ts +1 -1
- package/vanilla/UiRadioGroup.js +2 -2
- package/vanilla/UiReel.d.ts +1 -1
- package/vanilla/UiReel.js +2 -2
- package/vanilla/UiSearchResultRow.d.ts +1 -1
- package/vanilla/UiSearchResultRow.js +2 -2
- package/vanilla/UiSearchShell.d.ts +1 -1
- package/vanilla/UiSearchShell.js +2 -2
- package/vanilla/UiSelect.d.ts +1 -1
- package/vanilla/UiSelect.js +2 -2
- package/vanilla/UiSeparator.d.ts +1 -1
- package/vanilla/UiSeparator.js +2 -2
- package/vanilla/UiSidebar.d.ts +1 -1
- package/vanilla/UiSidebar.js +2 -2
- package/vanilla/UiStack.d.ts +1 -1
- package/vanilla/UiStack.js +2 -2
- package/vanilla/UiSwitch.d.ts +1 -1
- package/vanilla/UiSwitch.js +2 -2
- package/vanilla/UiSwitcher.d.ts +1 -1
- package/vanilla/UiSwitcher.js +2 -2
- package/vanilla/UiTabs.d.ts +1 -1
- package/vanilla/UiTabs.js +3 -3
- package/vanilla/UiTextarea.d.ts +1 -1
- package/vanilla/UiTextarea.js +2 -2
- package/vanilla/UiToastRegion.d.ts +1 -1
- package/vanilla/UiToastRegion.js +3 -3
- package/vanilla/UiTooltip.d.ts +1 -1
- package/vanilla/UiTooltip.js +2 -2
- package/vanilla/UiTopBar.d.ts +1 -1
- package/vanilla/UiTopBar.js +1 -1
- package/vanilla/UiTree.d.ts +1 -1
- package/vanilla/UiTree.js +2 -2
- package/vanilla/UiTreeItem.d.ts +1 -1
- package/vanilla/UiTreeItem.js +2 -2
- package/vue/UiAffordanceScope.d.ts +2 -2
- package/vue/UiAffordanceScope.vue +92 -73
- package/vue/UiAvatar.d.ts +7 -7
- package/vue/UiAvatar.vue +145 -105
- package/vue/UiAvatarGroup.d.ts +4 -4
- package/vue/UiAvatarGroup.vue +134 -118
- package/vue/UiBadge.d.ts +4 -4
- package/vue/UiBadge.vue +113 -114
- package/vue/UiButton.d.ts +10 -6
- package/vue/UiButton.vue +289 -248
- package/vue/UiCallout.d.ts +2 -2
- package/vue/UiCallout.vue +154 -87
- package/vue/UiCheckbox.d.ts +14 -10
- package/vue/UiCheckbox.vue +228 -162
- package/vue/UiCluster.d.ts +2 -2
- package/vue/UiCluster.vue +53 -60
- package/vue/UiCombobox.d.ts +36 -32
- package/vue/UiCombobox.vue +1005 -416
- package/vue/UiContainer.d.ts +2 -2
- package/vue/UiContainer.vue +48 -51
- package/vue/UiContextMenu.d.ts +6 -4
- package/vue/UiContextMenu.vue +205 -116
- package/vue/UiDialog.d.ts +11 -9
- package/vue/UiDialog.vue +287 -212
- package/vue/UiDisclosure.d.ts +8 -6
- package/vue/UiDisclosure.vue +248 -159
- package/vue/UiEditable.d.ts +16 -12
- package/vue/UiEditable.vue +325 -205
- package/vue/UiEditorInsertTableGrid.d.ts +8 -8
- package/vue/UiEditorInsertTableGrid.vue +216 -157
- package/vue/UiEditorMentionMenu.d.ts +9 -9
- package/vue/UiEditorMentionMenu.vue +265 -222
- package/vue/UiEditorSlashMenu.d.ts +7 -7
- package/vue/UiEditorSlashMenu.vue +286 -240
- package/vue/UiEditorTableContextMenu.d.ts +5 -5
- package/vue/UiEditorTableContextMenu.vue +306 -193
- package/vue/UiEditorTableOverlay.d.ts +2 -2
- package/vue/UiEditorTableOverlay.vue +609 -369
- package/vue/UiEditorTableToolbar.d.ts +7 -7
- package/vue/UiEditorTableToolbar.vue +443 -268
- package/vue/UiEditorToolbar.d.ts +2 -2
- package/vue/UiEditorToolbar.vue +134 -121
- package/vue/UiFloatingActionButton.d.ts +6 -6
- package/vue/UiFloatingActionButton.vue +100 -99
- package/vue/UiFormField.d.ts +6 -6
- package/vue/UiFormField.vue +112 -80
- package/vue/UiGrid.d.ts +2 -2
- package/vue/UiGrid.vue +51 -57
- package/vue/UiIcon.d.ts +2 -2
- package/vue/UiIcon.vue +118 -89
- package/vue/UiIconButton.d.ts +11 -11
- package/vue/UiIconButton.vue +283 -217
- package/vue/UiInput.d.ts +9 -9
- package/vue/UiInput.vue +153 -127
- package/vue/UiMenu.d.ts +8 -6
- package/vue/UiMenu.vue +217 -143
- package/vue/UiMenuItem.d.ts +4 -4
- package/vue/UiMenuItem.vue +52 -46
- package/vue/UiPopover.d.ts +8 -6
- package/vue/UiPopover.vue +197 -137
- package/vue/UiRadio.d.ts +14 -10
- package/vue/UiRadio.vue +183 -117
- package/vue/UiRadioGroup.d.ts +14 -12
- package/vue/UiRadioGroup.vue +172 -111
- package/vue/UiReel.d.ts +3 -3
- package/vue/UiReel.vue +77 -77
- package/vue/UiSearchResultRow.d.ts +4 -4
- package/vue/UiSearchResultRow.vue +124 -115
- package/vue/UiSearchShell.d.ts +10 -8
- package/vue/UiSearchShell.vue +245 -176
- package/vue/UiSelect.d.ts +9 -9
- package/vue/UiSelect.vue +162 -134
- package/vue/UiSeparator.d.ts +2 -2
- package/vue/UiSeparator.vue +22 -27
- package/vue/UiSidebar.d.ts +20 -18
- package/vue/UiSidebar.vue +312 -224
- package/vue/UiStack.d.ts +3 -3
- package/vue/UiStack.vue +64 -70
- package/vue/UiSwitch.d.ts +12 -8
- package/vue/UiSwitch.vue +218 -150
- package/vue/UiSwitcher.d.ts +3 -3
- package/vue/UiSwitcher.vue +73 -75
- package/vue/UiTabs.d.ts +10 -8
- package/vue/UiTabs.vue +251 -210
- package/vue/UiTextarea.d.ts +11 -11
- package/vue/UiTextarea.vue +155 -128
- package/vue/UiToastRegion.d.ts +10 -8
- package/vue/UiToastRegion.vue +261 -198
- package/vue/UiTooltip.d.ts +14 -12
- package/vue/UiTooltip.vue +241 -177
- package/vue/UiTopBar.vue +51 -42
- package/vue/UiTree.d.ts +8 -6
- package/vue/UiTree.vue +157 -70
- package/vue/UiTreeItem.d.ts +24 -22
- package/vue/UiTreeItem.vue +456 -339
- package/vue/chunks/UiAffordanceScope.js +9 -16
- package/vue/chunks/UiAvatar.js +23 -29
- package/vue/chunks/UiAvatarGroup.js +16 -39
- package/vue/chunks/UiBadge.js +3 -12
- package/vue/chunks/UiButton.js +15 -18
- package/vue/chunks/UiCallout.js +8 -17
- package/vue/chunks/UiCheckbox.js +37 -40
- package/vue/chunks/UiCluster.js +3 -12
- package/vue/chunks/UiCombobox.js +224 -266
- package/vue/chunks/UiContainer.js +3 -12
- package/vue/chunks/UiContextMenu.js +39 -34
- package/vue/chunks/UiDialog.js +36 -39
- package/vue/chunks/UiDisclosure.js +43 -48
- package/vue/chunks/UiEditable.js +55 -57
- package/vue/chunks/UiEditorInsertTableGrid.js +55 -73
- package/vue/chunks/UiEditorMentionMenu.js +40 -81
- package/vue/chunks/UiEditorSlashMenu.js +28 -52
- package/vue/chunks/UiEditorTableContextMenu.js +32 -56
- package/vue/chunks/UiEditorTableOverlay.js +58 -82
- package/vue/chunks/UiEditorTableToolbar.js +61 -85
- package/vue/chunks/UiEditorToolbar.js +4 -13
- package/vue/chunks/UiFloatingActionButton.js +7 -21
- package/vue/chunks/UiFormField.js +15 -12
- package/vue/chunks/UiGrid.js +3 -12
- package/vue/chunks/UiIcon.js +20 -43
- package/vue/chunks/UiIconButton.js +16 -28
- package/vue/chunks/UiInput.js +20 -25
- package/vue/chunks/UiMenu.js +29 -33
- package/vue/chunks/UiMenuItem.js +4 -10
- package/vue/chunks/UiPopover.js +28 -29
- package/vue/chunks/UiRadio.js +36 -39
- package/vue/chunks/UiRadioGroup.js +30 -34
- package/vue/chunks/UiReel.js +6 -15
- package/vue/chunks/UiSearchResultRow.js +6 -19
- package/vue/chunks/UiSearchShell.js +25 -28
- package/vue/chunks/UiSelect.js +20 -23
- package/vue/chunks/UiSeparator.js +2 -8
- package/vue/chunks/UiSidebar.js +39 -44
- package/vue/chunks/UiStack.js +6 -15
- package/vue/chunks/UiSwitch.js +35 -38
- package/vue/chunks/UiSwitcher.js +6 -15
- package/vue/chunks/UiTabs.js +47 -85
- package/vue/chunks/UiTextarea.js +21 -26
- package/vue/chunks/UiToastRegion.js +38 -72
- package/vue/chunks/UiTooltip.js +34 -35
- package/vue/chunks/UiTopBar.js +1 -1
- package/vue/chunks/UiTree.js +20 -15
- package/vue/chunks/UiTreeItem.js +85 -102
- package/vue/components.css +3994 -3801
package/vue/UiCombobox.vue
CHANGED
|
@@ -1,466 +1,1055 @@
|
|
|
1
|
-
<!-- Generated by HTML Next 1.0.0-alpha.
|
|
1
|
+
<!-- Generated by HTML Next 1.0.0-alpha.2 for Vue 3.5. Do not edit. -->
|
|
2
2
|
<script setup lang="ts">
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import {
|
|
4
|
+
computed,
|
|
5
|
+
onBeforeUnmount,
|
|
6
|
+
onMounted,
|
|
7
|
+
ref,
|
|
8
|
+
shallowRef,
|
|
9
|
+
useTemplateRef,
|
|
10
|
+
watchEffect,
|
|
11
|
+
} from 'vue'
|
|
12
|
+
import * as controllerModule from '../components/ui-combobox/ui-combobox.js'
|
|
13
|
+
import UiBadge from './UiBadge.vue'
|
|
14
|
+
import UiTooltip from './UiTooltip.vue'
|
|
7
15
|
|
|
8
|
-
defineOptions({ inheritAttrs: false })
|
|
16
|
+
defineOptions({ inheritAttrs: false })
|
|
9
17
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
18
|
+
const props = withDefaults(
|
|
19
|
+
defineProps<{
|
|
20
|
+
allowCreate?: boolean
|
|
21
|
+
allowFreeText?: boolean
|
|
22
|
+
clearable?: boolean
|
|
23
|
+
disabled?: boolean
|
|
24
|
+
disclosure?: boolean
|
|
25
|
+
help?: string
|
|
26
|
+
items?:
|
|
27
|
+
readonly ({
|
|
28
|
+
readonly id: string
|
|
29
|
+
readonly value: string
|
|
30
|
+
readonly label: string
|
|
31
|
+
readonly group?: string
|
|
32
|
+
readonly disabled?: boolean
|
|
33
|
+
})[]
|
|
34
|
+
label?: string
|
|
35
|
+
labelVisibility?: 'visible' | 'sr-only'
|
|
36
|
+
multiple?: boolean
|
|
37
|
+
name?: string
|
|
38
|
+
placeholder?: string
|
|
39
|
+
query?: string
|
|
40
|
+
readonly?: boolean
|
|
41
|
+
required?: boolean
|
|
42
|
+
size?: 'sm' | 'md'
|
|
43
|
+
tokenSeparators?: readonly (string)[]
|
|
44
|
+
value?: string | null
|
|
45
|
+
}>(),
|
|
46
|
+
{
|
|
47
|
+
allowCreate: false,
|
|
48
|
+
allowFreeText: false,
|
|
49
|
+
clearable: false,
|
|
50
|
+
disabled: false,
|
|
51
|
+
disclosure: false,
|
|
52
|
+
help: '',
|
|
53
|
+
label: '',
|
|
54
|
+
labelVisibility: 'visible',
|
|
55
|
+
multiple: false,
|
|
56
|
+
name: '',
|
|
57
|
+
placeholder: '',
|
|
58
|
+
readonly: false,
|
|
59
|
+
required: false,
|
|
60
|
+
size: 'md',
|
|
41
61
|
},
|
|
42
|
-
|
|
43
|
-
let list = Array.isArray(items) ? items.slice() : [];
|
|
44
|
-
if (where !== undefined) list = list.filter((item) => hn.t(where(item)));
|
|
45
|
-
if (sort.length > 0) {
|
|
46
|
-
const field = (item: unknown, path: string): unknown => item !== null && typeof item === "object" && !Array.isArray(item)
|
|
47
|
-
? path.split(".").reduce<unknown>((value, key) => (value as Record<string, unknown> | undefined)?.[key], item)
|
|
48
|
-
: item;
|
|
49
|
-
const compare = (a: unknown, b: unknown): number => typeof a === "number" && typeof b === "number" ? a - b : hn.text(a).localeCompare(hn.text(b));
|
|
50
|
-
list.sort((a, b) => {
|
|
51
|
-
for (const key of sort) {
|
|
52
|
-
const descending = key.startsWith("-");
|
|
53
|
-
const order = compare(field(a, descending ? key.slice(1) : key), field(b, descending ? key.slice(1) : key));
|
|
54
|
-
if (order !== 0) return descending ? -order : order;
|
|
55
|
-
}
|
|
56
|
-
return 0;
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return typeof limit === "number" ? list.slice(0, Math.max(0, Math.trunc(limit))) : list;
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const props = withDefaults(defineProps<{
|
|
64
|
-
allowCreate?: boolean | null;
|
|
65
|
-
allowFreeText?: boolean | null;
|
|
66
|
-
clearable?: boolean | null;
|
|
67
|
-
disabled?: boolean | null;
|
|
68
|
-
disclosure?: boolean | null;
|
|
69
|
-
help?: string | null;
|
|
70
|
-
items?: readonly ({ readonly id: string; readonly value: string; readonly label: string; readonly group?: string; readonly disabled?: boolean })[] | null;
|
|
71
|
-
label?: string | null;
|
|
72
|
-
labelVisibility?: "visible" | "sr-only" | null;
|
|
73
|
-
multiple?: boolean | null;
|
|
74
|
-
name?: string | null;
|
|
75
|
-
placeholder?: string | null;
|
|
76
|
-
query?: string | null;
|
|
77
|
-
readonly?: boolean | null;
|
|
78
|
-
required?: boolean | null;
|
|
79
|
-
size?: "sm" | "md" | null;
|
|
80
|
-
tokenSeparators?: readonly (string)[] | null;
|
|
81
|
-
value?: string | null;
|
|
82
|
-
}>(), {
|
|
83
|
-
allowCreate: false,
|
|
84
|
-
allowFreeText: false,
|
|
85
|
-
clearable: false,
|
|
86
|
-
disabled: false,
|
|
87
|
-
disclosure: false,
|
|
88
|
-
help: "",
|
|
89
|
-
label: "",
|
|
90
|
-
labelVisibility: "visible",
|
|
91
|
-
multiple: false,
|
|
92
|
-
name: "",
|
|
93
|
-
placeholder: "",
|
|
94
|
-
readonly: false,
|
|
95
|
-
required: false,
|
|
96
|
-
size: "md",
|
|
97
|
-
});
|
|
62
|
+
)
|
|
98
63
|
const emit = defineEmits<{
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
64
|
+
'update:query': [value: string]
|
|
65
|
+
'update:value': [value: string | null]
|
|
66
|
+
'query-change': [
|
|
67
|
+
detail: {
|
|
68
|
+
readonly query: string
|
|
69
|
+
readonly display: string
|
|
70
|
+
readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
'value-change': [
|
|
74
|
+
detail:
|
|
75
|
+
| {
|
|
76
|
+
readonly value: string | null
|
|
77
|
+
readonly query: string
|
|
78
|
+
readonly option: {
|
|
79
|
+
readonly id: string
|
|
80
|
+
readonly value: string
|
|
81
|
+
readonly label: string
|
|
82
|
+
readonly group?: string
|
|
83
|
+
readonly disabled?: boolean
|
|
84
|
+
} | null
|
|
85
|
+
readonly kind: 'selection' | 'clear' | 'free-entry' | 'create'
|
|
86
|
+
readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
|
|
87
|
+
}
|
|
88
|
+
| readonly ({
|
|
89
|
+
readonly id: string
|
|
90
|
+
readonly value: string
|
|
91
|
+
readonly label: string
|
|
92
|
+
readonly group?: string
|
|
93
|
+
readonly disabled?: boolean
|
|
94
|
+
})[],
|
|
95
|
+
]
|
|
96
|
+
'free-entry': [
|
|
97
|
+
detail: {
|
|
98
|
+
readonly value: string | null
|
|
99
|
+
readonly query: string
|
|
100
|
+
readonly option: {
|
|
101
|
+
readonly id: string
|
|
102
|
+
readonly value: string
|
|
103
|
+
readonly label: string
|
|
104
|
+
readonly group?: string
|
|
105
|
+
readonly disabled?: boolean
|
|
106
|
+
} | null
|
|
107
|
+
readonly kind: 'selection' | 'clear' | 'free-entry' | 'create'
|
|
108
|
+
readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
|
|
109
|
+
},
|
|
110
|
+
]
|
|
111
|
+
'create-entry': [
|
|
112
|
+
detail: {
|
|
113
|
+
readonly value: string | null
|
|
114
|
+
readonly query: string
|
|
115
|
+
readonly option: {
|
|
116
|
+
readonly id: string
|
|
117
|
+
readonly value: string
|
|
118
|
+
readonly label: string
|
|
119
|
+
readonly group?: string
|
|
120
|
+
readonly disabled?: boolean
|
|
121
|
+
} | null
|
|
122
|
+
readonly kind: 'selection' | 'clear' | 'free-entry' | 'create'
|
|
123
|
+
readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
|
|
124
|
+
},
|
|
125
|
+
]
|
|
126
|
+
'validation-change': [
|
|
127
|
+
detail: {
|
|
128
|
+
readonly status: 'pristine' | 'pending' | 'valid' | 'warning' | 'error'
|
|
129
|
+
readonly touched: boolean
|
|
130
|
+
readonly dirty: boolean
|
|
131
|
+
readonly issues:
|
|
132
|
+
readonly ({
|
|
133
|
+
readonly message: string
|
|
134
|
+
readonly path?: readonly (unknown)[]
|
|
135
|
+
readonly severity?: 'error' | 'warning'
|
|
136
|
+
})[]
|
|
137
|
+
readonly output?: unknown
|
|
138
|
+
},
|
|
139
|
+
]
|
|
140
|
+
'options-change': [
|
|
141
|
+
detail:
|
|
142
|
+
readonly ({
|
|
143
|
+
readonly id: string
|
|
144
|
+
readonly value: string
|
|
145
|
+
readonly label: string
|
|
146
|
+
readonly group?: string
|
|
147
|
+
readonly disabled?: boolean
|
|
148
|
+
})[],
|
|
149
|
+
]
|
|
150
|
+
'add-item': [
|
|
151
|
+
detail: {
|
|
152
|
+
readonly item: {
|
|
153
|
+
readonly id: string
|
|
154
|
+
readonly value: string
|
|
155
|
+
readonly label: string
|
|
156
|
+
readonly group?: string
|
|
157
|
+
readonly disabled?: boolean
|
|
158
|
+
}
|
|
159
|
+
readonly index: number
|
|
160
|
+
readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
|
|
161
|
+
},
|
|
162
|
+
]
|
|
163
|
+
'remove-item': [
|
|
164
|
+
detail: {
|
|
165
|
+
readonly item: {
|
|
166
|
+
readonly id: string
|
|
167
|
+
readonly value: string
|
|
168
|
+
readonly label: string
|
|
169
|
+
readonly group?: string
|
|
170
|
+
readonly disabled?: boolean
|
|
171
|
+
}
|
|
172
|
+
readonly index: number
|
|
173
|
+
readonly trigger: 'keyboard' | 'pointer' | 'programmatic'
|
|
174
|
+
},
|
|
175
|
+
]
|
|
176
|
+
'create-item': [
|
|
177
|
+
detail: { readonly query: string; readonly trigger: 'keyboard' | 'pointer' | 'programmatic' },
|
|
178
|
+
]
|
|
179
|
+
}>()
|
|
180
|
+
|
|
181
|
+
const root = ref<HTMLElement | null>(null)
|
|
182
|
+
const fieldElement = useTemplateRef<HTMLElement>('field')
|
|
183
|
+
const inputElement = useTemplateRef<HTMLElement>('input')
|
|
184
|
+
const popupElement = useTemplateRef<HTMLElement>('popup')
|
|
185
|
+
const listboxElement = useTemplateRef<HTMLElement>('listbox')
|
|
186
|
+
const optionsElement = useTemplateRef<HTMLElement>('options')
|
|
187
|
+
const raw = ref('')
|
|
188
|
+
const display = ref('')
|
|
189
|
+
const selected = ref<string | null>(null)
|
|
190
|
+
const expanded = ref(false)
|
|
191
|
+
const rows = ref<{ id: string; value: string; label: string; group?: string; disabled: boolean }[]>(
|
|
192
|
+
[],
|
|
193
|
+
)
|
|
194
|
+
const active = ref<number | null>(-1)
|
|
195
|
+
const loading = ref(false)
|
|
196
|
+
const helpOpen = ref(false)
|
|
197
|
+
const lookupError = ref('')
|
|
198
|
+
const validation = ref<
|
|
199
|
+
{
|
|
200
|
+
status: 'pristine' | 'pending' | 'valid' | 'warning' | 'error'
|
|
201
|
+
touched: boolean
|
|
202
|
+
dirty: boolean
|
|
203
|
+
issues: { message: string }[]
|
|
204
|
+
[name: string]: any
|
|
205
|
+
}
|
|
206
|
+
>({ status: 'pristine', touched: false, dirty: false, issues: [] })
|
|
207
|
+
const uid = ref('')
|
|
208
|
+
const groups = ref<
|
|
209
|
+
{
|
|
210
|
+
name: string
|
|
211
|
+
role: 'group' | 'presentation'
|
|
212
|
+
label: string | null
|
|
213
|
+
rows: {
|
|
214
|
+
id: string
|
|
215
|
+
value: string
|
|
216
|
+
label: string
|
|
217
|
+
group?: string
|
|
218
|
+
disabled: boolean
|
|
219
|
+
index: number
|
|
220
|
+
}[]
|
|
221
|
+
}[]
|
|
222
|
+
>([])
|
|
223
|
+
const creatable = ref(false)
|
|
224
|
+
const createIndex = ref(0)
|
|
225
|
+
const message = ref('')
|
|
226
|
+
const statusText = ref('')
|
|
227
|
+
const validationStatus = ref('pristine')
|
|
228
|
+
|
|
229
|
+
/** The values the styles' :host-state() rules test. */
|
|
230
|
+
const hostState = computed(() =>
|
|
231
|
+
[
|
|
232
|
+
props.size && `size size=${props.size}`,
|
|
233
|
+
validationStatus.value && 'validationStatus',
|
|
234
|
+
`validationStatus=${encodeURIComponent(validationStatus.value)}`,
|
|
235
|
+
props.multiple && 'multiple',
|
|
236
|
+
].filter(Boolean).join(' ')
|
|
237
|
+
)
|
|
128
238
|
|
|
129
239
|
/** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
|
|
130
|
-
|
|
131
|
-
const declared
|
|
240
|
+
function dispatch(name: string, detail?: unknown): boolean {
|
|
241
|
+
const declared: Record<string, EventInit | undefined> = {
|
|
242
|
+
'query-change': { bubbles: true, composed: true, cancelable: false },
|
|
243
|
+
'value-change': { bubbles: true, composed: true, cancelable: false },
|
|
244
|
+
'free-entry': { bubbles: true, composed: true, cancelable: false },
|
|
245
|
+
'create-entry': { bubbles: true, composed: true, cancelable: false },
|
|
246
|
+
'validation-change': { bubbles: true, composed: true, cancelable: false },
|
|
247
|
+
'options-change': { bubbles: true, composed: true, cancelable: false },
|
|
248
|
+
'add-item': { bubbles: true, composed: true, cancelable: false },
|
|
249
|
+
'remove-item': { bubbles: true, composed: true, cancelable: false },
|
|
250
|
+
'create-item': { bubbles: true, composed: true, cancelable: false },
|
|
251
|
+
}
|
|
132
252
|
const checks: Record<string, (detail: unknown) => boolean> = {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
253
|
+
'query-change': (detail) =>
|
|
254
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
255
|
+
&& typeof (detail as Record<string, unknown>)['query'] === 'string'
|
|
256
|
+
&& typeof (detail as Record<string, unknown>)['display'] === 'string'
|
|
257
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
258
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
259
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
260
|
+
&& Object.keys(detail as object).every((key) =>
|
|
261
|
+
['query', 'display', 'trigger'].includes(key)
|
|
262
|
+
),
|
|
263
|
+
'value-change': (detail) =>
|
|
264
|
+
(detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
265
|
+
&& (typeof (detail as Record<string, unknown>)['value'] === 'string'
|
|
266
|
+
|| (detail as Record<string, unknown>)['value'] === null)
|
|
267
|
+
&& typeof (detail as Record<string, unknown>)['query'] === 'string'
|
|
268
|
+
&& (((detail as Record<string, unknown>)['option'] !== null
|
|
269
|
+
&& typeof (detail as Record<string, unknown>)['option'] === 'object'
|
|
270
|
+
&& !Array.isArray((detail as Record<string, unknown>)['option'])
|
|
271
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['id']
|
|
272
|
+
=== 'string'
|
|
273
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
274
|
+
'value'
|
|
275
|
+
] === 'string'
|
|
276
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
277
|
+
'label'
|
|
278
|
+
] === 'string'
|
|
279
|
+
&& (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['group']
|
|
280
|
+
=== undefined
|
|
281
|
+
|| typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
282
|
+
'group'
|
|
283
|
+
] === 'string')
|
|
284
|
+
&& (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['disabled']
|
|
285
|
+
=== undefined
|
|
286
|
+
|| typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
287
|
+
'disabled'
|
|
288
|
+
] === 'boolean')
|
|
289
|
+
&& Object.keys((detail as Record<string, unknown>)['option'] as object).every((key) =>
|
|
290
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
291
|
+
)) || (detail as Record<string, unknown>)['option'] === null)
|
|
292
|
+
&& ((detail as Record<string, unknown>)['kind'] === 'selection'
|
|
293
|
+
|| (detail as Record<string, unknown>)['kind'] === 'clear'
|
|
294
|
+
|| (detail as Record<string, unknown>)['kind'] === 'free-entry'
|
|
295
|
+
|| (detail as Record<string, unknown>)['kind'] === 'create')
|
|
296
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
297
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
298
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
299
|
+
&& Object.keys(detail as object).every((key) =>
|
|
300
|
+
['value', 'query', 'option', 'kind', 'trigger'].includes(key)
|
|
301
|
+
))
|
|
302
|
+
|| (Array.isArray(detail)
|
|
303
|
+
&& (detail as unknown[]).every((
|
|
304
|
+
item: unknown,
|
|
305
|
+
) => (item !== null && typeof item === 'object' && !Array.isArray(item)
|
|
306
|
+
&& typeof (item as Record<string, unknown>)['id'] === 'string'
|
|
307
|
+
&& typeof (item as Record<string, unknown>)['value'] === 'string'
|
|
308
|
+
&& typeof (item as Record<string, unknown>)['label'] === 'string'
|
|
309
|
+
&& ((item as Record<string, unknown>)['group'] === undefined
|
|
310
|
+
|| typeof (item as Record<string, unknown>)['group'] === 'string')
|
|
311
|
+
&& ((item as Record<string, unknown>)['disabled'] === undefined
|
|
312
|
+
|| typeof (item as Record<string, unknown>)['disabled'] === 'boolean')
|
|
313
|
+
&& Object.keys(item as object).every((key) =>
|
|
314
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
315
|
+
))
|
|
316
|
+
)),
|
|
317
|
+
'free-entry': (detail) =>
|
|
318
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
319
|
+
&& (typeof (detail as Record<string, unknown>)['value'] === 'string'
|
|
320
|
+
|| (detail as Record<string, unknown>)['value'] === null)
|
|
321
|
+
&& typeof (detail as Record<string, unknown>)['query'] === 'string'
|
|
322
|
+
&& (((detail as Record<string, unknown>)['option'] !== null
|
|
323
|
+
&& typeof (detail as Record<string, unknown>)['option'] === 'object'
|
|
324
|
+
&& !Array.isArray((detail as Record<string, unknown>)['option'])
|
|
325
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['id']
|
|
326
|
+
=== 'string'
|
|
327
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
328
|
+
'value'
|
|
329
|
+
] === 'string'
|
|
330
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
331
|
+
'label'
|
|
332
|
+
] === 'string'
|
|
333
|
+
&& (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['group']
|
|
334
|
+
=== undefined
|
|
335
|
+
|| typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
336
|
+
'group'
|
|
337
|
+
] === 'string')
|
|
338
|
+
&& (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['disabled']
|
|
339
|
+
=== undefined
|
|
340
|
+
|| typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
341
|
+
'disabled'
|
|
342
|
+
] === 'boolean')
|
|
343
|
+
&& Object.keys((detail as Record<string, unknown>)['option'] as object).every((key) =>
|
|
344
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
345
|
+
)) || (detail as Record<string, unknown>)['option'] === null)
|
|
346
|
+
&& ((detail as Record<string, unknown>)['kind'] === 'selection'
|
|
347
|
+
|| (detail as Record<string, unknown>)['kind'] === 'clear'
|
|
348
|
+
|| (detail as Record<string, unknown>)['kind'] === 'free-entry'
|
|
349
|
+
|| (detail as Record<string, unknown>)['kind'] === 'create')
|
|
350
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
351
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
352
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
353
|
+
&& Object.keys(detail as object).every((key) =>
|
|
354
|
+
['value', 'query', 'option', 'kind', 'trigger'].includes(key)
|
|
355
|
+
),
|
|
356
|
+
'create-entry': (detail) =>
|
|
357
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
358
|
+
&& (typeof (detail as Record<string, unknown>)['value'] === 'string'
|
|
359
|
+
|| (detail as Record<string, unknown>)['value'] === null)
|
|
360
|
+
&& typeof (detail as Record<string, unknown>)['query'] === 'string'
|
|
361
|
+
&& (((detail as Record<string, unknown>)['option'] !== null
|
|
362
|
+
&& typeof (detail as Record<string, unknown>)['option'] === 'object'
|
|
363
|
+
&& !Array.isArray((detail as Record<string, unknown>)['option'])
|
|
364
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['id']
|
|
365
|
+
=== 'string'
|
|
366
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
367
|
+
'value'
|
|
368
|
+
] === 'string'
|
|
369
|
+
&& typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
370
|
+
'label'
|
|
371
|
+
] === 'string'
|
|
372
|
+
&& (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['group']
|
|
373
|
+
=== undefined
|
|
374
|
+
|| typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
375
|
+
'group'
|
|
376
|
+
] === 'string')
|
|
377
|
+
&& (((detail as Record<string, unknown>)['option'] as Record<string, unknown>)['disabled']
|
|
378
|
+
=== undefined
|
|
379
|
+
|| typeof ((detail as Record<string, unknown>)['option'] as Record<string, unknown>)[
|
|
380
|
+
'disabled'
|
|
381
|
+
] === 'boolean')
|
|
382
|
+
&& Object.keys((detail as Record<string, unknown>)['option'] as object).every((key) =>
|
|
383
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
384
|
+
)) || (detail as Record<string, unknown>)['option'] === null)
|
|
385
|
+
&& ((detail as Record<string, unknown>)['kind'] === 'selection'
|
|
386
|
+
|| (detail as Record<string, unknown>)['kind'] === 'clear'
|
|
387
|
+
|| (detail as Record<string, unknown>)['kind'] === 'free-entry'
|
|
388
|
+
|| (detail as Record<string, unknown>)['kind'] === 'create')
|
|
389
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
390
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
391
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
392
|
+
&& Object.keys(detail as object).every((key) =>
|
|
393
|
+
['value', 'query', 'option', 'kind', 'trigger'].includes(key)
|
|
394
|
+
),
|
|
395
|
+
'validation-change': (detail) =>
|
|
396
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
397
|
+
&& ((detail as Record<string, unknown>)['status'] === 'pristine'
|
|
398
|
+
|| (detail as Record<string, unknown>)['status'] === 'pending'
|
|
399
|
+
|| (detail as Record<string, unknown>)['status'] === 'valid'
|
|
400
|
+
|| (detail as Record<string, unknown>)['status'] === 'warning'
|
|
401
|
+
|| (detail as Record<string, unknown>)['status'] === 'error')
|
|
402
|
+
&& typeof (detail as Record<string, unknown>)['touched'] === 'boolean'
|
|
403
|
+
&& typeof (detail as Record<string, unknown>)['dirty'] === 'boolean'
|
|
404
|
+
&& (Array.isArray((detail as Record<string, unknown>)['issues'])
|
|
405
|
+
&& ((detail as Record<string, unknown>)['issues'] as unknown[]).every((
|
|
406
|
+
item: unknown,
|
|
407
|
+
) => (item !== null && typeof item === 'object' && !Array.isArray(item)
|
|
408
|
+
&& typeof (item as Record<string, unknown>)['message'] === 'string'
|
|
409
|
+
&& ((item as Record<string, unknown>)['path'] === undefined
|
|
410
|
+
|| (Array.isArray((item as Record<string, unknown>)['path'])
|
|
411
|
+
&& ((item as Record<string, unknown>)['path'] as unknown[]).every((item: unknown) =>
|
|
412
|
+
true
|
|
413
|
+
)))
|
|
414
|
+
&& ((item as Record<string, unknown>)['severity'] === undefined
|
|
415
|
+
|| ((item as Record<string, unknown>)['severity'] === 'error'
|
|
416
|
+
|| (item as Record<string, unknown>)['severity'] === 'warning'))
|
|
417
|
+
&& Object.keys(item as object).every((key) =>
|
|
418
|
+
['message', 'path', 'severity'].includes(key)
|
|
419
|
+
))
|
|
420
|
+
))
|
|
421
|
+
&& ((detail as Record<string, unknown>)['output'] === undefined || true)
|
|
422
|
+
&& Object.keys(detail as object).every((key) =>
|
|
423
|
+
['status', 'touched', 'dirty', 'issues', 'output'].includes(key)
|
|
424
|
+
),
|
|
425
|
+
'options-change': (detail) =>
|
|
426
|
+
Array.isArray(detail)
|
|
427
|
+
&& (detail as unknown[]).every((
|
|
428
|
+
item: unknown,
|
|
429
|
+
) => (item !== null && typeof item === 'object' && !Array.isArray(item)
|
|
430
|
+
&& typeof (item as Record<string, unknown>)['id'] === 'string'
|
|
431
|
+
&& typeof (item as Record<string, unknown>)['value'] === 'string'
|
|
432
|
+
&& typeof (item as Record<string, unknown>)['label'] === 'string'
|
|
433
|
+
&& ((item as Record<string, unknown>)['group'] === undefined
|
|
434
|
+
|| typeof (item as Record<string, unknown>)['group'] === 'string')
|
|
435
|
+
&& ((item as Record<string, unknown>)['disabled'] === undefined
|
|
436
|
+
|| typeof (item as Record<string, unknown>)['disabled'] === 'boolean')
|
|
437
|
+
&& Object.keys(item as object).every((key) =>
|
|
438
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
439
|
+
))
|
|
440
|
+
),
|
|
441
|
+
'add-item': (detail) =>
|
|
442
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
443
|
+
&& ((detail as Record<string, unknown>)['item'] !== null
|
|
444
|
+
&& typeof (detail as Record<string, unknown>)['item'] === 'object'
|
|
445
|
+
&& !Array.isArray((detail as Record<string, unknown>)['item'])
|
|
446
|
+
&& typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['id']
|
|
447
|
+
=== 'string'
|
|
448
|
+
&& typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['value']
|
|
449
|
+
=== 'string'
|
|
450
|
+
&& typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['label']
|
|
451
|
+
=== 'string'
|
|
452
|
+
&& (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['group']
|
|
453
|
+
=== undefined
|
|
454
|
+
|| typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
|
|
455
|
+
'group'
|
|
456
|
+
] === 'string')
|
|
457
|
+
&& (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['disabled']
|
|
458
|
+
=== undefined
|
|
459
|
+
|| typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
|
|
460
|
+
'disabled'
|
|
461
|
+
] === 'boolean')
|
|
462
|
+
&& Object.keys((detail as Record<string, unknown>)['item'] as object).every((key) =>
|
|
463
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
464
|
+
))
|
|
465
|
+
&& Number.isInteger((detail as Record<string, unknown>)['index'])
|
|
466
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
467
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
468
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
469
|
+
&& Object.keys(detail as object).every((key) =>
|
|
470
|
+
['item', 'index', 'trigger'].includes(key)
|
|
471
|
+
),
|
|
472
|
+
'remove-item': (detail) =>
|
|
473
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
474
|
+
&& ((detail as Record<string, unknown>)['item'] !== null
|
|
475
|
+
&& typeof (detail as Record<string, unknown>)['item'] === 'object'
|
|
476
|
+
&& !Array.isArray((detail as Record<string, unknown>)['item'])
|
|
477
|
+
&& typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['id']
|
|
478
|
+
=== 'string'
|
|
479
|
+
&& typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['value']
|
|
480
|
+
=== 'string'
|
|
481
|
+
&& typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['label']
|
|
482
|
+
=== 'string'
|
|
483
|
+
&& (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['group']
|
|
484
|
+
=== undefined
|
|
485
|
+
|| typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
|
|
486
|
+
'group'
|
|
487
|
+
] === 'string')
|
|
488
|
+
&& (((detail as Record<string, unknown>)['item'] as Record<string, unknown>)['disabled']
|
|
489
|
+
=== undefined
|
|
490
|
+
|| typeof ((detail as Record<string, unknown>)['item'] as Record<string, unknown>)[
|
|
491
|
+
'disabled'
|
|
492
|
+
] === 'boolean')
|
|
493
|
+
&& Object.keys((detail as Record<string, unknown>)['item'] as object).every((key) =>
|
|
494
|
+
['id', 'value', 'label', 'group', 'disabled'].includes(key)
|
|
495
|
+
))
|
|
496
|
+
&& Number.isInteger((detail as Record<string, unknown>)['index'])
|
|
497
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
498
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
499
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
500
|
+
&& Object.keys(detail as object).every((key) =>
|
|
501
|
+
['item', 'index', 'trigger'].includes(key)
|
|
502
|
+
),
|
|
503
|
+
'create-item': (detail) =>
|
|
504
|
+
detail !== null && typeof detail === 'object' && !Array.isArray(detail)
|
|
505
|
+
&& typeof (detail as Record<string, unknown>)['query'] === 'string'
|
|
506
|
+
&& ((detail as Record<string, unknown>)['trigger'] === 'keyboard'
|
|
507
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'pointer'
|
|
508
|
+
|| (detail as Record<string, unknown>)['trigger'] === 'programmatic')
|
|
509
|
+
&& Object.keys(detail as object).every((key) => ['query', 'trigger'].includes(key)),
|
|
510
|
+
}
|
|
143
511
|
if (detail !== undefined && checks[name] !== undefined && !checks[name]!(detail)) {
|
|
144
|
-
throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
|
|
512
|
+
throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
|
|
145
513
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
514
|
+
const emitEvent = emit as (name: string, detail: unknown) => void
|
|
515
|
+
emitEvent(name, detail)
|
|
516
|
+
if (detail !== null && typeof detail === 'object' && 'query' in detail) {
|
|
517
|
+
emitEvent('update:query', (detail as Record<string, unknown>)['query'])
|
|
518
|
+
}
|
|
519
|
+
if (detail !== null && typeof detail === 'object' && 'value' in detail) {
|
|
520
|
+
emitEvent('update:value', (detail as Record<string, unknown>)['value'])
|
|
521
|
+
}
|
|
522
|
+
return root.value?.dispatchEvent(
|
|
523
|
+
new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
|
|
524
|
+
) ?? true
|
|
525
|
+
}
|
|
157
526
|
|
|
158
527
|
function read(name: string): unknown {
|
|
159
|
-
if (name ===
|
|
160
|
-
if (name ===
|
|
161
|
-
if (name ===
|
|
162
|
-
if (name ===
|
|
163
|
-
if (name ===
|
|
164
|
-
if (name ===
|
|
165
|
-
if (name ===
|
|
166
|
-
if (name ===
|
|
167
|
-
if (name ===
|
|
168
|
-
if (name ===
|
|
169
|
-
if (name ===
|
|
170
|
-
if (name ===
|
|
171
|
-
if (name ===
|
|
172
|
-
if (name ===
|
|
173
|
-
if (name ===
|
|
174
|
-
if (name ===
|
|
175
|
-
if (name ===
|
|
176
|
-
return (props as Record<string, unknown>)[name]
|
|
528
|
+
if (name === 'raw') return raw.value
|
|
529
|
+
if (name === 'display') return display.value
|
|
530
|
+
if (name === 'selected') return selected.value
|
|
531
|
+
if (name === 'expanded') return expanded.value
|
|
532
|
+
if (name === 'rows') return rows.value
|
|
533
|
+
if (name === 'active') return active.value
|
|
534
|
+
if (name === 'loading') return loading.value
|
|
535
|
+
if (name === 'helpOpen') return helpOpen.value
|
|
536
|
+
if (name === 'lookupError') return lookupError.value
|
|
537
|
+
if (name === 'validation') return validation.value
|
|
538
|
+
if (name === 'uid') return uid.value
|
|
539
|
+
if (name === 'groups') return groups.value
|
|
540
|
+
if (name === 'creatable') return creatable.value
|
|
541
|
+
if (name === 'createIndex') return createIndex.value
|
|
542
|
+
if (name === 'message') return message.value
|
|
543
|
+
if (name === 'statusText') return statusText.value
|
|
544
|
+
if (name === 'validationStatus') return validationStatus.value
|
|
545
|
+
return (props as Record<string, unknown>)[name]
|
|
177
546
|
}
|
|
178
547
|
|
|
179
548
|
function write(name: string, value: unknown): boolean {
|
|
180
|
-
if (name ===
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (name ===
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (name ===
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (name ===
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (name ===
|
|
197
|
-
|
|
549
|
+
if (name === 'raw') {
|
|
550
|
+
raw.value = value as never
|
|
551
|
+
return true
|
|
552
|
+
}
|
|
553
|
+
if (name === 'display') {
|
|
554
|
+
display.value = value as never
|
|
555
|
+
return true
|
|
556
|
+
}
|
|
557
|
+
if (name === 'selected') {
|
|
558
|
+
selected.value = value as never
|
|
559
|
+
return true
|
|
560
|
+
}
|
|
561
|
+
if (name === 'expanded') {
|
|
562
|
+
expanded.value = value as never
|
|
563
|
+
return true
|
|
564
|
+
}
|
|
565
|
+
if (name === 'rows') {
|
|
566
|
+
rows.value = value as never
|
|
567
|
+
return true
|
|
568
|
+
}
|
|
569
|
+
if (name === 'active') {
|
|
570
|
+
active.value = value as never
|
|
571
|
+
return true
|
|
572
|
+
}
|
|
573
|
+
if (name === 'loading') {
|
|
574
|
+
loading.value = value as never
|
|
575
|
+
return true
|
|
576
|
+
}
|
|
577
|
+
if (name === 'helpOpen') {
|
|
578
|
+
helpOpen.value = value as never
|
|
579
|
+
return true
|
|
580
|
+
}
|
|
581
|
+
if (name === 'lookupError') {
|
|
582
|
+
lookupError.value = value as never
|
|
583
|
+
return true
|
|
584
|
+
}
|
|
585
|
+
if (name === 'validation') {
|
|
586
|
+
validation.value = value as never
|
|
587
|
+
return true
|
|
588
|
+
}
|
|
589
|
+
if (name === 'uid') {
|
|
590
|
+
uid.value = value as never
|
|
591
|
+
return true
|
|
592
|
+
}
|
|
593
|
+
if (name === 'groups') {
|
|
594
|
+
groups.value = value as never
|
|
595
|
+
return true
|
|
596
|
+
}
|
|
597
|
+
if (name === 'creatable') {
|
|
598
|
+
creatable.value = value as never
|
|
599
|
+
return true
|
|
600
|
+
}
|
|
601
|
+
if (name === 'createIndex') {
|
|
602
|
+
createIndex.value = value as never
|
|
603
|
+
return true
|
|
604
|
+
}
|
|
605
|
+
if (name === 'message') {
|
|
606
|
+
message.value = value as never
|
|
607
|
+
return true
|
|
608
|
+
}
|
|
609
|
+
if (name === 'statusText') {
|
|
610
|
+
statusText.value = value as never
|
|
611
|
+
return true
|
|
612
|
+
}
|
|
613
|
+
if (name === 'validationStatus') {
|
|
614
|
+
validationStatus.value = value as never
|
|
615
|
+
return true
|
|
616
|
+
}
|
|
617
|
+
throw new TypeError(`Only declared state is writable; \`${name}\` is not.`)
|
|
198
618
|
}
|
|
199
619
|
|
|
200
|
-
const stops: Array<() => void> = []
|
|
620
|
+
const stops: Array<() => void> = []
|
|
201
621
|
const host = {
|
|
202
|
-
get element(): Element {
|
|
622
|
+
get element(): Element {
|
|
623
|
+
return root.value as Element
|
|
624
|
+
},
|
|
203
625
|
state: new Proxy({} as Record<string, unknown>, {
|
|
204
|
-
get: (_target, name) => typeof name ===
|
|
205
|
-
set: (_target, name, value) => typeof name ===
|
|
626
|
+
get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
|
|
627
|
+
set: (_target, name, value) => typeof name === 'string' && write(name, value),
|
|
206
628
|
}),
|
|
207
|
-
refs:
|
|
629
|
+
refs: {
|
|
630
|
+
get field(): Element {
|
|
631
|
+
return fieldElement.value as Element
|
|
632
|
+
},
|
|
633
|
+
get input(): Element {
|
|
634
|
+
return inputElement.value as Element
|
|
635
|
+
},
|
|
636
|
+
get popup(): Element {
|
|
637
|
+
return popupElement.value as Element
|
|
638
|
+
},
|
|
639
|
+
get listbox(): Element {
|
|
640
|
+
return listboxElement.value as Element
|
|
641
|
+
},
|
|
642
|
+
get options(): Element {
|
|
643
|
+
return optionsElement.value as Element
|
|
644
|
+
},
|
|
645
|
+
} as Readonly<Record<string, Element>>,
|
|
208
646
|
elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
|
|
209
647
|
get: (_target, name) => {
|
|
210
|
-
if (typeof name !==
|
|
211
|
-
const form = root.value instanceof HTMLFormElement
|
|
212
|
-
|
|
648
|
+
if (typeof name !== 'string' || root.value === null) return undefined
|
|
649
|
+
const form = root.value instanceof HTMLFormElement
|
|
650
|
+
? root.value
|
|
651
|
+
: root.value.querySelector('form')
|
|
652
|
+
return form?.elements.namedItem(name)
|
|
653
|
+
?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
|
|
213
654
|
},
|
|
214
655
|
}),
|
|
215
656
|
signal<T>(initialValue: T) {
|
|
216
|
-
const value = shallowRef(initialValue)
|
|
657
|
+
const value = shallowRef(initialValue)
|
|
217
658
|
return {
|
|
218
659
|
get: (): T => value.value,
|
|
219
|
-
set: (next: T): void => {
|
|
220
|
-
|
|
221
|
-
|
|
660
|
+
set: (next: T): void => {
|
|
661
|
+
if (!Object.is(value.value, next)) value.value = next
|
|
662
|
+
},
|
|
663
|
+
update: (next: (current: T) => T): void => {
|
|
664
|
+
const updated = next(value.value)
|
|
665
|
+
if (!Object.is(value.value, updated)) value.value = updated
|
|
666
|
+
},
|
|
667
|
+
}
|
|
222
668
|
},
|
|
223
669
|
computed<T>(compute: () => T) {
|
|
224
|
-
const value = computed(compute)
|
|
225
|
-
return { get: (): T => value.value }
|
|
670
|
+
const value = computed(compute)
|
|
671
|
+
return { get: (): T => value.value }
|
|
226
672
|
},
|
|
227
673
|
effect(run: () => void | (() => void)): () => void {
|
|
228
674
|
const stop = watchEffect((onCleanup) => {
|
|
229
|
-
const cleanup = run()
|
|
230
|
-
if (typeof cleanup ===
|
|
231
|
-
}, { flush:
|
|
232
|
-
stops.push(stop)
|
|
233
|
-
return stop
|
|
675
|
+
const cleanup = run()
|
|
676
|
+
if (typeof cleanup === 'function') onCleanup(cleanup)
|
|
677
|
+
}, { flush: 'post' })
|
|
678
|
+
stops.push(stop)
|
|
679
|
+
return stop
|
|
234
680
|
},
|
|
235
681
|
on(event: string, listener: EventListener): () => void {
|
|
236
|
-
const element = root.value
|
|
237
|
-
element?.addEventListener(event, listener)
|
|
238
|
-
const off = (): void => element?.removeEventListener(event, listener)
|
|
239
|
-
stops.push(off)
|
|
240
|
-
return off
|
|
682
|
+
const element = root.value
|
|
683
|
+
element?.addEventListener(event, listener)
|
|
684
|
+
const off = (): void => element?.removeEventListener(event, listener)
|
|
685
|
+
stops.push(off)
|
|
686
|
+
return off
|
|
241
687
|
},
|
|
242
688
|
dispatch,
|
|
243
|
-
}
|
|
689
|
+
}
|
|
244
690
|
|
|
245
|
-
let cleanup: void | (() => void)
|
|
246
|
-
let ready: Promise<void> | undefined
|
|
691
|
+
let cleanup: void | (() => void)
|
|
692
|
+
let ready: Promise<void> | undefined
|
|
247
693
|
onMounted(() => {
|
|
248
|
-
ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
|
|
249
|
-
|
|
694
|
+
ready = Promise.resolve(controllerModule.default(host as never)).then((result) => {
|
|
695
|
+
cleanup = result
|
|
696
|
+
})
|
|
697
|
+
})
|
|
250
698
|
onBeforeUnmount(() => {
|
|
251
|
-
for (const stop of stops.splice(0)) stop()
|
|
252
|
-
if (typeof cleanup ===
|
|
253
|
-
})
|
|
699
|
+
for (const stop of stops.splice(0)) stop()
|
|
700
|
+
if (typeof cleanup === 'function') cleanup()
|
|
701
|
+
})
|
|
254
702
|
defineExpose({
|
|
255
|
-
validate: async (...args: unknown[]) => {
|
|
256
|
-
|
|
257
|
-
|
|
703
|
+
validate: async (...args: unknown[]) => {
|
|
704
|
+
await ready
|
|
705
|
+
return (controllerModule as Record<string, (...values: unknown[]) => unknown>)['validate']!(
|
|
706
|
+
host,
|
|
707
|
+
...args,
|
|
708
|
+
)
|
|
709
|
+
},
|
|
710
|
+
focusInput: async (...args: unknown[]) => {
|
|
711
|
+
await ready
|
|
712
|
+
return (controllerModule as Record<string, (...values: unknown[]) => unknown>)['focusInput']!(
|
|
713
|
+
host,
|
|
714
|
+
...args,
|
|
715
|
+
)
|
|
716
|
+
},
|
|
717
|
+
})
|
|
258
718
|
</script>
|
|
259
719
|
|
|
260
720
|
<template>
|
|
261
|
-
<div
|
|
262
|
-
|
|
721
|
+
<div
|
|
722
|
+
data-component="ui-combobox"
|
|
723
|
+
v-bind="$attrs"
|
|
724
|
+
:data-ui-combobox-state="hostState || undefined"
|
|
725
|
+
ref="root"
|
|
726
|
+
>
|
|
727
|
+
<label :for="`${uid}-input`" :class="{ 'sr-only': labelVisibility === 'sr-only' }">{{ label }}
|
|
728
|
+
<template v-if="required">
|
|
729
|
+
*</template></label>
|
|
730
|
+
<div class="field" ref="field">
|
|
731
|
+
<slot name="start" />
|
|
732
|
+
<template v-if="multiple"><button
|
|
733
|
+
v-for="(item, index) in items"
|
|
734
|
+
:key="item.id"
|
|
735
|
+
class="item"
|
|
736
|
+
type="button"
|
|
737
|
+
tabindex="-1"
|
|
738
|
+
:data-index="index"
|
|
739
|
+
:disabled="disabled || readonly || item.disabled"
|
|
740
|
+
:aria-label="`${item.label}, press Delete or Backspace to remove`"
|
|
741
|
+
>
|
|
742
|
+
<slot :name="`item-${item.id}`"><UiBadge>{{ item.label }}</UiBadge></slot>
|
|
743
|
+
</button></template>
|
|
744
|
+
<input
|
|
745
|
+
role="combobox"
|
|
746
|
+
aria-autocomplete="list"
|
|
747
|
+
autocomplete="off"
|
|
748
|
+
:id="`${uid}-input`"
|
|
749
|
+
:aria-controls="`${uid}-listbox`"
|
|
750
|
+
:aria-expanded="expanded"
|
|
751
|
+
:aria-invalid="validationStatus === 'error'"
|
|
752
|
+
:aria-busy="validationStatus === 'pending'"
|
|
753
|
+
:value.prop="display"
|
|
754
|
+
:placeholder="placeholder"
|
|
755
|
+
:name="name"
|
|
756
|
+
:disabled="disabled"
|
|
757
|
+
:readonly="readonly"
|
|
758
|
+
:required="required"
|
|
759
|
+
ref="input"
|
|
760
|
+
>
|
|
761
|
+
<button v-if="clearable" type="button" data-combobox-action="clear" aria-label="Clear">
|
|
762
|
+
<svg
|
|
763
|
+
class="affordance-icon"
|
|
764
|
+
aria-hidden="true"
|
|
765
|
+
viewBox="0 0 24 24"
|
|
766
|
+
fill="none"
|
|
767
|
+
stroke="currentColor"
|
|
768
|
+
stroke-width="2"
|
|
769
|
+
stroke-linecap="round"
|
|
770
|
+
>
|
|
771
|
+
<path d="M7 7l10 10M17 7 7 17"></path>
|
|
772
|
+
</svg>
|
|
773
|
+
</button>
|
|
774
|
+
<button v-if="help" type="button" aria-label="Help" :id="`${uid}-help`" :disabled="disabled">
|
|
775
|
+
<span aria-hidden="true">?</span>
|
|
776
|
+
</button>
|
|
777
|
+
<button
|
|
778
|
+
v-if="disclosure"
|
|
779
|
+
type="button"
|
|
780
|
+
data-combobox-action="disclosure"
|
|
781
|
+
tabindex="-1"
|
|
782
|
+
aria-label="Show suggestions"
|
|
783
|
+
:aria-controls="`${uid}-listbox`"
|
|
784
|
+
>
|
|
785
|
+
<svg
|
|
786
|
+
class="affordance-icon"
|
|
787
|
+
aria-hidden="true"
|
|
788
|
+
viewBox="0 0 24 24"
|
|
789
|
+
fill="none"
|
|
790
|
+
stroke="currentColor"
|
|
791
|
+
stroke-width="2.25"
|
|
792
|
+
stroke-linecap="round"
|
|
793
|
+
stroke-linejoin="round"
|
|
794
|
+
>
|
|
795
|
+
<path d="m6 9 6 6 6-6"></path>
|
|
796
|
+
</svg>
|
|
797
|
+
</button>
|
|
798
|
+
</div>
|
|
799
|
+
<UiTooltip v-if="help" :id="`${uid}-help-text`" :for="`${uid}-help`">{{ help }}</UiTooltip>
|
|
800
|
+
<div class="popup" :hidden="!expanded" ref="popup">
|
|
801
|
+
<div
|
|
802
|
+
role="listbox"
|
|
803
|
+
:id="`${uid}-listbox`"
|
|
804
|
+
:aria-label="`${label} suggestions`"
|
|
805
|
+
:aria-busy="loading"
|
|
806
|
+
ref="listbox"
|
|
807
|
+
>
|
|
808
|
+
<div
|
|
809
|
+
v-for="group in groups"
|
|
810
|
+
:key="group.name"
|
|
811
|
+
:role="group.role"
|
|
812
|
+
:aria-label="group.label ?? undefined"
|
|
813
|
+
>
|
|
814
|
+
<div v-if="group.name" class="group">{{ group.name }}</div>
|
|
815
|
+
<div
|
|
816
|
+
v-for="row in group.rows"
|
|
817
|
+
:key="row.id"
|
|
818
|
+
class="option"
|
|
819
|
+
role="option"
|
|
820
|
+
:id="`${uid}-option-${row.index}`"
|
|
821
|
+
:aria-selected="row.value === selected"
|
|
822
|
+
:aria-disabled="row.disabled"
|
|
823
|
+
:data-index="row.index"
|
|
824
|
+
:class="{ active: row.index === active }"
|
|
825
|
+
>
|
|
826
|
+
<slot :name="`option-${row.id}`"><span class="primary">{{ row.label }}</span></slot>
|
|
827
|
+
</div>
|
|
828
|
+
</div>
|
|
829
|
+
<div
|
|
830
|
+
v-if="creatable"
|
|
831
|
+
class="option"
|
|
832
|
+
role="option"
|
|
833
|
+
aria-selected="false"
|
|
834
|
+
:id="`${uid}-option-${createIndex}`"
|
|
835
|
+
:data-index="createIndex"
|
|
836
|
+
:class="{ active: createIndex === active }"
|
|
837
|
+
>
|
|
838
|
+
{{ `Create “${raw}”` }}
|
|
839
|
+
</div>
|
|
840
|
+
<div v-if="message" class="message">{{ message }}</div>
|
|
841
|
+
</div>
|
|
842
|
+
<slot name="footer" />
|
|
843
|
+
</div>
|
|
844
|
+
<div class="message" :id="`${uid}-validation`" :hidden="!validation.issues.length">
|
|
845
|
+
<div v-for="(issue, index) in validation.issues" :key="index">{{ issue.message }}</div>
|
|
846
|
+
</div>
|
|
847
|
+
<div class="sr-only" role="status" aria-live="polite" aria-atomic="true">{{ statusText }}</div>
|
|
848
|
+
<div class="authored-options" hidden="" aria-hidden="true" ref="options"><slot /></div>
|
|
849
|
+
</div>
|
|
263
850
|
</template>
|
|
264
851
|
|
|
265
852
|
<style scoped>
|
|
266
853
|
[data-component~="ui-combobox"] {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
854
|
+
display: grid;
|
|
855
|
+
gap: var(--ui-space-1);
|
|
856
|
+
min-inline-size: 0;
|
|
857
|
+
color: var(--ui-text-primary);
|
|
858
|
+
font: inherit;
|
|
859
|
+
}
|
|
860
|
+
label {
|
|
861
|
+
color: var(--ui-field-label-color, var(--ui-text-primary));
|
|
862
|
+
font-size: var(--ui-field-label-size, 0.875rem);
|
|
863
|
+
font-weight: var(--ui-field-label-weight, 500);
|
|
864
|
+
}
|
|
865
|
+
.field {
|
|
866
|
+
display: flex;
|
|
867
|
+
min-inline-size: 0;
|
|
868
|
+
border: 1px solid var(--ui-control-border, var(--ui-border-default));
|
|
869
|
+
border-radius: var(--ui-radius-2);
|
|
870
|
+
background: var(--ui-control-surface, var(--ui-surface-default));
|
|
871
|
+
box-shadow: var(--ui-control-inset);
|
|
872
|
+
transition:
|
|
873
|
+
border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
874
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
875
|
+
}
|
|
876
|
+
.field:focus-within {
|
|
877
|
+
border-color: var(--ui-control-focus, var(--ui-accent-solid));
|
|
878
|
+
box-shadow:
|
|
879
|
+
var(--ui-control-inset),
|
|
880
|
+
var(--ui-control-focus-halo-shadow);
|
|
881
|
+
}
|
|
882
|
+
input::selection {
|
|
883
|
+
background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
|
|
884
|
+
color: inherit;
|
|
885
|
+
}
|
|
886
|
+
input {
|
|
887
|
+
appearance: none;
|
|
888
|
+
width: 100%;
|
|
889
|
+
min-inline-size: 0;
|
|
890
|
+
min-block-size: calc(var(--ui-control-size-md, 2.5rem) - 2px);
|
|
891
|
+
box-sizing: border-box;
|
|
892
|
+
border: 0;
|
|
893
|
+
border-radius: inherit;
|
|
894
|
+
background: transparent;
|
|
895
|
+
color: inherit;
|
|
896
|
+
font: inherit;
|
|
897
|
+
line-height: var(--ui-line-height-md);
|
|
898
|
+
padding: var(--ui-space-2) var(--ui-space-3);
|
|
899
|
+
margin: 0;
|
|
900
|
+
outline: none;
|
|
901
|
+
}
|
|
902
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input {
|
|
903
|
+
min-block-size: calc(var(--ui-field-compact-size, var(--ui-control-size-sm, 2rem)) - 2px);
|
|
904
|
+
padding: var(--ui-space-1) var(--ui-space-2);
|
|
905
|
+
}
|
|
906
|
+
button {
|
|
907
|
+
appearance: none;
|
|
908
|
+
display: inline-grid;
|
|
909
|
+
place-items: center;
|
|
910
|
+
align-self: stretch;
|
|
911
|
+
border: 0;
|
|
912
|
+
border-radius: var(--ui-radius-2);
|
|
913
|
+
background: transparent;
|
|
914
|
+
color: var(--ui-field-affordance-color, var(--ui-text-secondary));
|
|
915
|
+
font: inherit;
|
|
916
|
+
font-weight: var(--ui-field-affordance-weight, 400);
|
|
917
|
+
min-inline-size: 2rem;
|
|
918
|
+
padding: 0 var(--ui-space-1);
|
|
919
|
+
cursor: pointer;
|
|
920
|
+
}
|
|
921
|
+
.affordance-icon {
|
|
922
|
+
display: block;
|
|
923
|
+
inline-size: var(--ui-icon-size-sm, 1rem);
|
|
924
|
+
block-size: var(--ui-icon-size-sm, 1rem);
|
|
925
|
+
}
|
|
926
|
+
button:hover:enabled {
|
|
927
|
+
background: var(--ui-surface-muted);
|
|
928
|
+
color: var(--ui-text-primary);
|
|
929
|
+
}
|
|
930
|
+
button:focus-visible {
|
|
931
|
+
outline: none;
|
|
932
|
+
background: var(--ui-surface-muted);
|
|
933
|
+
box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);
|
|
934
|
+
}
|
|
935
|
+
input:disabled, button:disabled {
|
|
936
|
+
color: var(--ui-text-muted);
|
|
937
|
+
cursor: not-allowed;
|
|
938
|
+
}
|
|
939
|
+
.field:has(input:disabled) {
|
|
940
|
+
background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
|
|
941
|
+
}
|
|
942
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field {
|
|
943
|
+
border-color: var(--ui-danger-solid, var(--ui-accent-active));
|
|
944
|
+
}
|
|
945
|
+
.popup {
|
|
946
|
+
box-sizing: border-box;
|
|
947
|
+
min-inline-size: 12rem;
|
|
948
|
+
max-inline-size: calc(100vw - 1rem);
|
|
949
|
+
max-block-size: var(--ui-combobox-max-block-size, 18rem);
|
|
950
|
+
overflow: auto;
|
|
951
|
+
margin: 0;
|
|
952
|
+
padding: var(--ui-space-1);
|
|
953
|
+
border: 1px solid var(--ui-border-default);
|
|
954
|
+
border-radius: var(--ui-radius-2);
|
|
955
|
+
background: var(--ui-surface-elevated);
|
|
956
|
+
color: var(--ui-text-primary);
|
|
957
|
+
box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
|
|
958
|
+
}
|
|
959
|
+
[hidden] {
|
|
960
|
+
display: none;
|
|
961
|
+
}
|
|
962
|
+
.option {
|
|
963
|
+
padding: var(--ui-space-2) var(--ui-space-3);
|
|
964
|
+
border-radius: var(--ui-radius-1);
|
|
965
|
+
cursor: pointer;
|
|
966
|
+
overflow-wrap: anywhere;
|
|
967
|
+
}
|
|
968
|
+
.option:hover, .option.active {
|
|
969
|
+
background: var(--ui-surface-muted);
|
|
970
|
+
outline: 1px solid var(--ui-focus-ring, currentColor);
|
|
971
|
+
outline-offset: -1px;
|
|
972
|
+
}
|
|
973
|
+
.option[aria-disabled="true"] {
|
|
974
|
+
color: var(--ui-text-muted);
|
|
975
|
+
cursor: not-allowed;
|
|
976
|
+
}
|
|
977
|
+
.primary {
|
|
978
|
+
display: block;
|
|
979
|
+
color: var(--ui-option-primary-color, var(--ui-text-primary));
|
|
980
|
+
font-weight: var(--ui-option-primary-weight, 500);
|
|
981
|
+
}
|
|
982
|
+
.message, .group {
|
|
983
|
+
color: var(--ui-field-message-color, var(--ui-text-secondary));
|
|
984
|
+
font-weight: var(--ui-field-message-weight, 400);
|
|
985
|
+
font-size: var(--ui-font-size-sm);
|
|
986
|
+
line-height: var(--ui-line-height-md);
|
|
987
|
+
overflow-wrap: anywhere;
|
|
988
|
+
}
|
|
989
|
+
.group, .popup .message {
|
|
990
|
+
padding: var(--ui-space-2) var(--ui-space-3);
|
|
991
|
+
}
|
|
992
|
+
.sr-only {
|
|
993
|
+
position: absolute;
|
|
994
|
+
inline-size: 1px;
|
|
995
|
+
block-size: 1px;
|
|
996
|
+
overflow: hidden;
|
|
997
|
+
clip-path: inset(50%);
|
|
998
|
+
white-space: nowrap;
|
|
999
|
+
}
|
|
1000
|
+
@media (pointer: coarse) {
|
|
1001
|
+
button {
|
|
1002
|
+
min-inline-size: 2.75rem;
|
|
1003
|
+
min-block-size: 2.75rem;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
@media (forced-colors: active) {
|
|
1007
|
+
.field, .popup {
|
|
1008
|
+
border-color: CanvasText;
|
|
1009
|
+
}
|
|
1010
|
+
.option.active {
|
|
1011
|
+
outline-color: Highlight;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
425
1014
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
1015
|
+
/* Multiple mode: chips wrap before the cursor on one flexible field line. */
|
|
1016
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field {
|
|
1017
|
+
flex-wrap: wrap;
|
|
1018
|
+
align-items: center;
|
|
1019
|
+
gap: var(--ui-space-1);
|
|
1020
|
+
min-block-size: var(--ui-multi-combobox-min-block-size, 2.5rem);
|
|
1021
|
+
padding: var(--ui-space-1);
|
|
1022
|
+
}
|
|
1023
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input {
|
|
1024
|
+
flex: 1 0 var(--ui-multi-combobox-input-min-inline-size, 5rem);
|
|
1025
|
+
width: auto;
|
|
1026
|
+
min-block-size: 1.75rem;
|
|
1027
|
+
padding: var(--ui-space-0-5) var(--ui-space-1);
|
|
1028
|
+
}
|
|
1029
|
+
.item {
|
|
1030
|
+
appearance: none;
|
|
1031
|
+
display: inline-flex;
|
|
1032
|
+
min-inline-size: 0;
|
|
1033
|
+
max-inline-size: min(100%, var(--ui-multi-combobox-item-max-inline-size, 12rem));
|
|
1034
|
+
overflow: hidden;
|
|
1035
|
+
padding: 0;
|
|
1036
|
+
border: 0;
|
|
1037
|
+
border-radius: var(--ui-radius-1);
|
|
1038
|
+
background: transparent;
|
|
1039
|
+
color: inherit;
|
|
1040
|
+
font: inherit;
|
|
1041
|
+
cursor: default;
|
|
1042
|
+
}
|
|
1043
|
+
.item:focus-visible {
|
|
1044
|
+
outline: 2px solid var(--ui-focus-ring, currentColor);
|
|
1045
|
+
outline-offset: 1px;
|
|
1046
|
+
}
|
|
1047
|
+
.item:disabled {
|
|
1048
|
+
opacity: 0.6;
|
|
1049
|
+
}
|
|
461
1050
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
1051
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
1052
|
+
[data-component~="ui-combobox"][hidden] {
|
|
1053
|
+
display: none;
|
|
1054
|
+
}
|
|
466
1055
|
</style>
|