Nychthemeron/packages/library/src/components/ui/select/Select.vue
Matthew L McPeak f69a3b0c65 refactor: rewrite the Select root family without reka-ui
Root/Value/Label/Group/Separator/ItemText now share a small
provide/inject context. SelectValue's label lookup is backed by an
itemLabels map that SelectItem populates on mount (next commit) --
matching the existing behavior where the trigger's displayed label
only resolves once the dropdown has opened at least once.
2026-07-13 18:16:17 -04:00

46 lines
1.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) },
unregisterLabel: (value: string) => { itemLabels.delete(value) },
})
</script>
<template>
<slot />
</template>