95 lines
2.6 KiB
Vue
95 lines
2.6 KiB
Vue
<script setup>
|
|
const props = defineProps({
|
|
type: {
|
|
type: String,
|
|
default: "single"
|
|
},
|
|
defaultValue: {
|
|
type: String || Array,
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
const toggleGroup = ref(null);
|
|
const selected = ref((props.type === "single") ? props.defaultValue : [].concat(props.defaultValue));
|
|
|
|
watch(selected, (newValue) => {
|
|
emit('update:modelValue', newValue);
|
|
})
|
|
emit('update:modelValue', selected.value);
|
|
|
|
const items = ref([]);
|
|
|
|
function registerToggleItem(value) {
|
|
const item = { value, tabIndex: (props.defaultValue.includes(value)) ? ref('0') : ref('-1') }
|
|
const itemIndex = (items.value.push(item)) - 1
|
|
return { item, index: itemIndex };
|
|
}
|
|
|
|
function toggleItem(index) {
|
|
if (props.type === "single") {
|
|
selected.value = items.value[index].value;
|
|
return;
|
|
}
|
|
if (selected.value.indexOf(items.value[index].value) > -1) {
|
|
selected.value = selected.value.filter((e) => e !== items.value[index].value)
|
|
return;
|
|
}
|
|
selected.value.push(items.value[index].value);
|
|
}
|
|
|
|
function keydown(event) {
|
|
const elements = Array.from(toggleGroup.value.children).filter(
|
|
(el) => el.nodeName.toLowerCase() === 'button'
|
|
);
|
|
|
|
if (event.key === "Home") {
|
|
event.preventDefault();
|
|
items.value.forEach((el, i) => {
|
|
if (i === 0) return items.value[i].tabIndex = '0';
|
|
return items.value[i].tabIndex = '-1';
|
|
});
|
|
elements[0].focus();
|
|
}
|
|
|
|
if (event.key === "End") {
|
|
event.preventDefault();
|
|
items.value.forEach((el, i) => {
|
|
if (i === items.value.length - 1) return items.value[i].tabIndex = '0';
|
|
return items.value[i].tabIndex = '-1';
|
|
});
|
|
elements[items.value.length-1].focus();
|
|
}
|
|
|
|
const focusedElement = document.activeElement;
|
|
const currentIndex = elements.indexOf(focusedElement);
|
|
if (event.key === "ArrowRight" || event.key === "ArrowDown") {
|
|
event.preventDefault();
|
|
const nextIndex = currentIndex < elements.length - 1 ? currentIndex + 1 : 0;
|
|
items.value.forEach((el, i) => {
|
|
if (i === nextIndex) return items.value[i].tabIndex = '0';
|
|
return items.value[i].tabIndex = '-1';
|
|
});
|
|
elements[nextIndex].focus();
|
|
}
|
|
|
|
if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
|
|
event.preventDefault();
|
|
const nextIndex = currentIndex > 0 ? currentIndex - 1 : elements.length - 1;
|
|
items.value.forEach((el, i) => {
|
|
if (i === nextIndex) return items.value[i].tabIndex = '0';
|
|
return items.value[i].tabIndex = '-1';
|
|
});
|
|
elements[nextIndex].focus();
|
|
}
|
|
}
|
|
|
|
provide('toggleGroup', { registerToggleItem, toggleItem, selected })
|
|
</script>
|
|
|
|
<template>
|
|
<div role="group" ref="toggleGroup" class="vl-toggle-group" @keydown="keydown($event)">
|
|
<slot />
|
|
</div>
|
|
</template> |