streaming, markdown, model selecting, and lots more
This commit is contained in:
+30
-35
@@ -2,71 +2,66 @@
|
||||
import type { DropdownItem } from '~/types/dropdown';
|
||||
|
||||
interface Props {
|
||||
items: DropdownItem[];
|
||||
modelValue?: boolean;
|
||||
items?: DropdownItem[];
|
||||
placement?: 'right' | 'left' | 'center';
|
||||
verticality?: 'asscending' | 'descending';
|
||||
width?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
placement: 'right',
|
||||
verticality: 'descending',
|
||||
width: 'auto'
|
||||
})
|
||||
width: 'auto',
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: boolean): void;
|
||||
(e: 'select', item: DropdownItem): void;
|
||||
}>()
|
||||
const emit = defineEmits<(e: 'select', item: DropdownItem) => void>();
|
||||
|
||||
const triggerRef = ref<HTMLElement | null>(null)
|
||||
const isOpen = defineModel<boolean>({ required: true })
|
||||
const triggerRef = ref<HTMLElement | null>(null);
|
||||
const isOpen = defineModel<boolean>({ required: false });
|
||||
|
||||
const toggle = () => {
|
||||
isOpen.value = !isOpen.value
|
||||
}
|
||||
isOpen.value = !isOpen.value;
|
||||
};
|
||||
|
||||
const select = (item: DropdownItem) => {
|
||||
if (item.disabled || item.divider) return
|
||||
emit('select', item)
|
||||
isOpen.value = false
|
||||
}
|
||||
if (item.disabled || item.divider) return;
|
||||
emit('select', item);
|
||||
isOpen.value = false;
|
||||
};
|
||||
|
||||
const placementClasses = computed(() => {
|
||||
let classes = ''
|
||||
let classes = '';
|
||||
|
||||
switch (props.placement) {
|
||||
case 'right':
|
||||
classes += 'right-0 '
|
||||
break
|
||||
classes += 'right-0 ';
|
||||
break;
|
||||
case 'left':
|
||||
classes += 'left-0 '
|
||||
break
|
||||
classes += 'left-0 ';
|
||||
break;
|
||||
case 'center':
|
||||
classes += 'left-1/2 -translate-x-1/2 '
|
||||
break
|
||||
classes += 'left-1/2 -translate-x-1/2 ';
|
||||
break;
|
||||
default:
|
||||
classes += 'left-0 '
|
||||
break
|
||||
classes += 'left-0 ';
|
||||
break;
|
||||
}
|
||||
|
||||
switch (props.verticality) {
|
||||
case 'asscending':
|
||||
classes += 'bottom-full mb-1.5'
|
||||
break
|
||||
classes += 'bottom-full mb-1.5';
|
||||
break;
|
||||
case 'descending':
|
||||
classes += 'top-full mt-1.5'
|
||||
break
|
||||
classes += 'top-full mt-1.5';
|
||||
break;
|
||||
}
|
||||
|
||||
return classes
|
||||
})
|
||||
return classes;
|
||||
});
|
||||
|
||||
useClickOutside(triggerRef, () => {
|
||||
isOpen.value = false
|
||||
})
|
||||
isOpen.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -88,7 +83,7 @@ useClickOutside(triggerRef, () => {
|
||||
:class="[
|
||||
item.disabled
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: 'hover:bg-[var(--color-highlight)] cursor-pointer'
|
||||
: 'hover:bg-[var(--color-highlight)] focus-visible:bg-[var(--color-highlight)] cursor-pointer'
|
||||
]">
|
||||
<Icon v-if="item.icon" :name="item.icon" class="w-4 h-4 flex-shrink-0" />
|
||||
<span class="text-sm whitespace-nowrap">{{ item.label }}</span>
|
||||
|
||||
Reference in New Issue
Block a user