mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat(UI): BaseSelect option list scrolls automatically using up/down keys
This commit is contained in:
@ -26,17 +26,22 @@
|
|||||||
@focus.prevent="activate()"
|
@focus.prevent="activate()"
|
||||||
@blur.prevent="deactivate()"
|
@blur.prevent="deactivate()"
|
||||||
@keyup.esc="deactivate()"
|
@keyup.esc="deactivate()"
|
||||||
@keydown.down.prevent="moveDown()"
|
@keydown.down.prevent="keyArrows('down')"
|
||||||
@keydown.up.prevent="moveUp()"
|
@keydown.up.prevent="keyArrows('up')"
|
||||||
@keypress.enter.prevent.stop.self="select(filteredOptions[hightlightedIndex])"
|
@keypress.enter.prevent.stop.self="select(filteredOptions[hightlightedIndex])"
|
||||||
>
|
>
|
||||||
<span v-if="searchable && !isOpen || !searchable">{{ currentOptionLabel }}</span>
|
<span v-if="searchable && !isOpen || !searchable">{{ currentOptionLabel }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isOpen" class="select__list-wrapper">
|
<div
|
||||||
|
v-if="isOpen"
|
||||||
|
ref="optionList"
|
||||||
|
class="select__list-wrapper"
|
||||||
|
>
|
||||||
<ul class="select__list" @mousedown.prevent>
|
<ul class="select__list" @mousedown.prevent>
|
||||||
<li
|
<li
|
||||||
v-for="(opt, index) of filteredOptions"
|
v-for="(opt, index) of filteredOptions"
|
||||||
:key="getOptionValue(opt)"
|
:key="getOptionValue(opt)"
|
||||||
|
:ref="(el) => optionRefs[index] = el"
|
||||||
:class="{
|
:class="{
|
||||||
'select__option--highlight': index === hightlightedIndex,
|
'select__option--highlight': index === hightlightedIndex,
|
||||||
'select__option--selected': isSelected(opt)
|
'select__option--selected': isSelected(opt)
|
||||||
@ -101,6 +106,8 @@ export default defineComponent({
|
|||||||
const isOpen = ref(false);
|
const isOpen = ref(false);
|
||||||
const el = ref(null);
|
const el = ref(null);
|
||||||
const searchInput = ref(null);
|
const searchInput = ref(null);
|
||||||
|
const optionList = ref(null);
|
||||||
|
const optionRefs = [];
|
||||||
const searchText = ref('');
|
const searchText = ref('');
|
||||||
const filteredOptions = computed(() => {
|
const filteredOptions = computed(() => {
|
||||||
const normalizedSearch = (searchText.value || '').toLowerCase().trim();
|
const normalizedSearch = (searchText.value || '').toLowerCase().trim();
|
||||||
@ -187,13 +194,21 @@ export default defineComponent({
|
|||||||
emit('close');
|
emit('close');
|
||||||
};
|
};
|
||||||
|
|
||||||
const moveUp = () => {
|
const keyArrows = (direction) => {
|
||||||
if (hightlightedIndex.value > 0)
|
const sum = direction === 'down' ? +1 : -1;
|
||||||
hightlightedIndex.value--;
|
const index = hightlightedIndex.value + sum;
|
||||||
};
|
hightlightedIndex.value = Math.max(0, index > filteredOptions.value.length - 1 ? filteredOptions.value.length - 1 : index);
|
||||||
const moveDown = () => {
|
|
||||||
if (hightlightedIndex.value < filteredOptions.value.length -1)
|
const optEl = optionRefs[hightlightedIndex.value];
|
||||||
hightlightedIndex.value++;
|
|
||||||
|
const visMin = optionList.value.scrollTop;
|
||||||
|
const visMax = optionList.value.scrollTop + optionList.value.clientHeight - optEl.clientHeight;
|
||||||
|
|
||||||
|
if (optEl.offsetTop < visMin)
|
||||||
|
optionList.value.scrollTop = optEl.offsetTop;
|
||||||
|
|
||||||
|
else if (optEl.offsetTop >= visMax)
|
||||||
|
optionList.value.scrollTop = optEl.offsetTop - optionList.value.clientHeight + optEl.clientHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -209,10 +224,11 @@ export default defineComponent({
|
|||||||
deactivate,
|
deactivate,
|
||||||
select,
|
select,
|
||||||
isSelected,
|
isSelected,
|
||||||
moveUp,
|
keyArrows,
|
||||||
moveDown,
|
|
||||||
isOpen,
|
isOpen,
|
||||||
hightlightedIndex
|
hightlightedIndex,
|
||||||
|
optionList,
|
||||||
|
optionRefs
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user