Vue 3 + TS + Vite + Tailwind with self-built UI components. Landing, auth, user dashboard (keys/usage/settings), and admin console (overview/models/channels/users/usage/config). Theme system (light/dark/system) with pre-paint boot script, theme-aware ECharts, and a channel editor with multi-format (Anthropic/OpenAI) selection. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
36 lines
1.3 KiB
Vue
36 lines
1.3 KiB
Vue
<script setup lang="ts">
|
|
export interface SelectOption {
|
|
label: string
|
|
value: string
|
|
}
|
|
|
|
withDefaults(
|
|
defineProps<{
|
|
modelValue: string
|
|
label?: string
|
|
options: SelectOption[]
|
|
disabled?: boolean
|
|
}>(),
|
|
{ label: '', disabled: false },
|
|
)
|
|
|
|
const emit = defineEmits<{ (e: 'update:modelValue', v: string): void }>()
|
|
|
|
const cls =
|
|
'w-full appearance-none rounded border border-line bg-bg px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-brand/40 disabled:opacity-60'
|
|
</script>
|
|
|
|
<template>
|
|
<label class="block">
|
|
<span v-if="label" class="mb-1.5 block text-xs font-medium text-ink-soft">{{ label }}</span>
|
|
<div class="relative">
|
|
<select :value="modelValue" :disabled="disabled" :class="cls" @change="emit('update:modelValue', ($event.target as HTMLSelectElement).value)">
|
|
<option v-for="o in options" :key="o.value" :value="o.value">{{ o.label }}</option>
|
|
</select>
|
|
<svg class="pointer-events-none absolute right-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-ink-mute" viewBox="0 0 20 20" fill="currentColor">
|
|
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.17l3.71-3.94a.75.75 0 1 1 1.08 1.04l-4.25 4.5a.75.75 0 0 1-1.08 0l-4.25-4.5a.75.75 0 0 1 .02-1.06z" clip-rule="evenodd" />
|
|
</svg>
|
|
</div>
|
|
</label>
|
|
</template>
|