Merge pull request #1367 from Gadha2311/keyboard-entrydropdown

feat:  enable keyboard support for dropdown selection
This commit is contained in:
Able k Saju
2025-10-16 09:29:47 +05:30
committed by GitHub
2 changed files with 79 additions and 32 deletions
+64 -27
View File
@@ -28,13 +28,17 @@
:tabindex="isReadOnly ? '-1' : '0'"
@focus="(e) => !isReadOnly && onInputFocus(e)"
@click="(e) => !isReadOnly && onClick(e, toggleDropdown)"
@blur="(e) => !isReadOnly && onBlur(e.target.value)"
@input="onInput"
@keydown.up="highlightItemUp"
@keydown.down="highlightItemDown"
@keydown.enter="selectHighlightedItem"
@keydown.tab="toggleDropdown(false)"
@keydown.esc="toggleDropdown(false)"
@blur="(e) => !isReadOnly && onBlur(e.target.value, toggleDropdown)"
@input="(e) => onInput(e, toggleDropdown)"
@keydown.up="onKeyDownUp($event, toggleDropdown, highlightItemUp)"
@keydown.down="
onKeyDownDown($event, toggleDropdown, highlightItemDown)
"
@keydown.enter="
onPressEnter($event, toggleDropdown, selectHighlightedItem)
"
@keydown.tab="closeDropdown($event, toggleDropdown)"
@keydown.esc="closeDropdown($event, toggleDropdown)"
/>
<svg
@@ -130,6 +134,7 @@ export default {
suggestions: [],
highlightedIndex: -1,
isFocused: false,
isDropdownOpen: false,
};
},
computed: {
@@ -231,11 +236,10 @@ export default {
getLinkValue(value) {
const oldValue = this.linkValue;
let option = this.options.find((o) => o.value === value);
if (option === undefined) {
if (!option) {
option = this.options.find((o) => o.label === value);
}
if (!value && option === undefined) {
if (!value && !option) {
return null;
}
@@ -254,13 +258,9 @@ export default {
setSetSuggestionAction(suggestions) {
for (const option of suggestions) {
if (option.action) {
continue;
if (!option.action) {
option.action = () => this.setSuggestion(option);
}
option.action = () => {
this.setSuggestion(option);
};
}
return suggestions;
@@ -287,29 +287,28 @@ export default {
this.setLinkValue(suggestion.label);
this.triggerChange(suggestion.value);
}
this.toggleDropdown(false);
},
onInputFocus(e) {
this.isFocused = true;
},
onClick(e, toggleDropdown) {
if (this.isFocused) {
this.toggleDropdown = toggleDropdown;
this.toggleDropdown(true);
toggleDropdown(true);
this.updateSuggestions();
this.isDropdownOpen = true;
this.$emit('focus', e);
}
},
onFocus(e, toggleDropdown) {
this.isFocused = true;
this.toggleDropdown = toggleDropdown;
this.toggleDropdown(true);
toggleDropdown(true);
this.updateSuggestions();
this.isDropdownOpen = true;
this.$emit('focus', e);
},
async onBlur(label) {
async onBlur(label, toggleDropdown) {
this.isFocused = false;
this.isDropdownOpen = false;
if (!label && !this.value) {
return;
}
@@ -331,7 +330,8 @@ export default {
this.setSuggestion(suggestions[0]);
}
},
onInput(e) {
onInput(e, toggleDropdown) {
if (this.isReadOnly) {
return;
}
@@ -339,15 +339,52 @@ export default {
if (!e.target.value || this.focInp) {
e.target.value = null;
this.focInp = false;
this.toggleDropdown(false);
toggleDropdown(false);
return;
}
this.triggerChange(e.target.value);
this.toggleDropdown(true);
this.updateSuggestions(e.target.value);
},
async onPressEnter(e, toggleDropdown, selectHighlightedItem) {
e.preventDefault();
if (
this.suggestions.length > 0 &&
this.isFocused &&
this.isDropdownOpen
) {
await selectHighlightedItem();
this.closeDropdown(e, toggleDropdown);
return;
}
await this.updateSuggestions(this.linkValue || e.target.value);
toggleDropdown(true);
this.isDropdownOpen = true;
},
onKeyDownUp(e, toggleDropdown, highlightItemUp) {
if (this.suggestions.length === 0) {
this.updateSuggestions();
toggleDropdown(true);
this.isDropdownOpen = true;
}
highlightItemUp();
},
onKeyDownDown(e, toggleDropdown, highlightItemDown) {
if (this.suggestions.length === 0) {
this.updateSuggestions();
toggleDropdown(true);
this.isDropdownOpen = true;
}
highlightItemDown();
},
closeDropdown(e, toggleDropdown) {
toggleDropdown(false);
this.isDropdownOpen = false;
},
},
};
</script>
+15 -5
View File
@@ -190,10 +190,12 @@ export default defineComponent({
}
if (this.doc) {
return await d.action(this.doc, this.$router);
await d.action(this.doc, this.$router);
} else {
await d.action();
}
await d.action();
this.toggleDropdown(false);
},
toggleDropdown(flag?: boolean): void {
if (typeof flag !== 'boolean') {
@@ -203,9 +205,17 @@ export default defineComponent({
this.isShown = flag;
},
async selectHighlightedItem(): Promise<void> {
let item = this.items[this.highlightedIndex];
if (!item && this.dropdownItems.length === 1) {
item = this.dropdownItems[0];
let item = this.dropdownItems[this.highlightedIndex];
if (!item) {
if (this.dropdownItems.length === 1) {
item = this.dropdownItems[0];
} else {
return;
}
}
if (item.isGroup) {
return;
}
return await this.selectItem(item);