|
@@ -2,6 +2,7 @@
|
|
|
<div class="choice-combobox" ref="rootRef">
|
|
<div class="choice-combobox" ref="rootRef">
|
|
|
<input
|
|
<input
|
|
|
ref="searchInputRef"
|
|
ref="searchInputRef"
|
|
|
|
|
+ :id="id"
|
|
|
type="text"
|
|
type="text"
|
|
|
class="choice-combobox-input"
|
|
class="choice-combobox-input"
|
|
|
role="combobox"
|
|
role="combobox"
|
|
@@ -11,21 +12,16 @@
|
|
|
:aria-activedescendant="activeDescendantId"
|
|
:aria-activedescendant="activeDescendantId"
|
|
|
:placeholder="placeholderText"
|
|
:placeholder="placeholderText"
|
|
|
:value="query"
|
|
:value="query"
|
|
|
|
|
+ :required="required"
|
|
|
@focus="handleFocus"
|
|
@focus="handleFocus"
|
|
|
@input="handleSearchInput"
|
|
@input="handleSearchInput"
|
|
|
@keydown="handleKeydown"
|
|
@keydown="handleKeydown"
|
|
|
@blur="handleBlur"
|
|
@blur="handleBlur"
|
|
|
/>
|
|
/>
|
|
|
<input
|
|
<input
|
|
|
- :id="id"
|
|
|
|
|
:name="name"
|
|
:name="name"
|
|
|
- type="text"
|
|
|
|
|
- class="choice-combobox-hidden-value"
|
|
|
|
|
- tabindex="-1"
|
|
|
|
|
|
|
+ type="hidden"
|
|
|
:value="modelValue"
|
|
:value="modelValue"
|
|
|
- :required="required"
|
|
|
|
|
- readonly
|
|
|
|
|
- aria-hidden="true"
|
|
|
|
|
/>
|
|
/>
|
|
|
<ul
|
|
<ul
|
|
|
v-if="isOpen && filteredChoices.length > 0"
|
|
v-if="isOpen && filteredChoices.length > 0"
|
|
@@ -38,7 +34,7 @@
|
|
|
:id="`${listboxId}-option-${index}`"
|
|
:id="`${listboxId}-option-${index}`"
|
|
|
:key="choice.value"
|
|
:key="choice.value"
|
|
|
role="option"
|
|
role="option"
|
|
|
- :aria-selected="index === highlightedIndex"
|
|
|
|
|
|
|
+ :aria-selected="choice.value === modelValue"
|
|
|
:class="{
|
|
:class="{
|
|
|
highlighted: index === highlightedIndex,
|
|
highlighted: index === highlightedIndex,
|
|
|
selected: choice.value === modelValue
|
|
selected: choice.value === modelValue
|
|
@@ -193,15 +189,23 @@ function moveHighlight(delta) {
|
|
|
function handleKeydown(event) {
|
|
function handleKeydown(event) {
|
|
|
if (event.key === 'ArrowDown') {
|
|
if (event.key === 'ArrowDown') {
|
|
|
event.preventDefault()
|
|
event.preventDefault()
|
|
|
|
|
+ const wasOpen = isOpen.value
|
|
|
openList()
|
|
openList()
|
|
|
- moveHighlight(1)
|
|
|
|
|
|
|
+ if (wasOpen) {
|
|
|
|
|
+ moveHighlight(1)
|
|
|
|
|
+ }
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (event.key === 'ArrowUp') {
|
|
if (event.key === 'ArrowUp') {
|
|
|
event.preventDefault()
|
|
event.preventDefault()
|
|
|
|
|
+ const wasOpen = isOpen.value
|
|
|
openList()
|
|
openList()
|
|
|
- moveHighlight(-1)
|
|
|
|
|
|
|
+ if (wasOpen) {
|
|
|
|
|
+ moveHighlight(-1)
|
|
|
|
|
+ } else if (filteredChoices.value.length > 0) {
|
|
|
|
|
+ highlightedIndex.value = filteredChoices.value.length - 1
|
|
|
|
|
+ }
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -273,18 +277,6 @@ onBeforeUnmount(() => {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.choice-combobox-hidden-value {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- width: 1px;
|
|
|
|
|
- height: 1px;
|
|
|
|
|
- padding: 0;
|
|
|
|
|
- margin: -1px;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- clip: rect(0, 0, 0, 0);
|
|
|
|
|
- white-space: nowrap;
|
|
|
|
|
- border: 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
.choice-combobox-list {
|
|
.choice-combobox-list {
|
|
|
position: absolute;
|
|
position: absolute;
|
|
|
z-index: 10;
|
|
z-index: 10;
|