45 lines
1 KiB
Vue
45 lines
1 KiB
Vue
<script setup lang="ts">
|
|
import { computed, provide, reactive, ref, useId } from 'vue'
|
|
import { useVModel } from '@vueuse/core'
|
|
import { SelectContextKey } from './context'
|
|
|
|
const props = defineProps<{
|
|
modelValue?: string
|
|
defaultValue?: string
|
|
disabled?: boolean
|
|
open?: boolean
|
|
defaultOpen?: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
'update:modelValue': [value: string]
|
|
'update:open': [value: boolean]
|
|
}>()
|
|
|
|
const modelValue = useVModel(props, 'modelValue', emit, {
|
|
passive: true,
|
|
defaultValue: props.defaultValue,
|
|
})
|
|
const open = useVModel(props, 'open', emit, {
|
|
passive: true,
|
|
defaultValue: props.defaultOpen ?? false,
|
|
})
|
|
|
|
const disabled = computed(() => props.disabled ?? false)
|
|
const triggerRef = ref<HTMLElement | null>(null)
|
|
const itemLabels = reactive(new Map<string, string>())
|
|
|
|
provide(SelectContextKey, {
|
|
open,
|
|
modelValue,
|
|
disabled,
|
|
triggerRef,
|
|
contentId: `select-content-${useId()}`,
|
|
itemLabels,
|
|
registerLabel: (value: string, label: string) => { itemLabels.set(value, label) },
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<slot />
|
|
</template>
|