|
@@ -2,14 +2,21 @@
|
|
|
<div ref="raiz" class="relative shrink-0">
|
|
<div ref="raiz" class="relative shrink-0">
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
- class="flex items-center gap-1 rounded-full border border-gray-200 px-3 py-1 text-xs font-medium text-gray-600 transition-colors hover:border-gray-300 dark:border-gray-700 dark:text-gray-300 dark:hover:border-gray-600"
|
|
|
|
|
- :class="modelValue ? 'border-primary/40 bg-primary/10 text-primary dark:border-primary/40 dark:bg-primary/10 dark:text-primary' : ''"
|
|
|
|
|
|
|
+ class="flex items-center gap-1.5 rounded-lg border border-gray-300 bg-background px-3 py-1.5 text-sm text-gray-700 shadow-sm transition-colors hover:border-gray-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-gray-600 dark:text-gray-200 dark:hover:border-gray-500"
|
|
|
:aria-expanded="aberto"
|
|
:aria-expanded="aberto"
|
|
|
aria-haspopup="listbox"
|
|
aria-haspopup="listbox"
|
|
|
@click="alternar"
|
|
@click="alternar"
|
|
|
>
|
|
>
|
|
|
- <span class="max-w-[120px] truncate">{{ rotuloAtual }}</span>
|
|
|
|
|
- <svg class="h-3 w-3 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
|
|
|
|
+ <span class="text-gray-500 dark:text-gray-400">{{ rotulo }}</span>
|
|
|
|
|
+ <span class="max-w-[110px] truncate font-medium text-gray-900 dark:text-gray-100">{{ valorAtual }}</span>
|
|
|
|
|
+ <svg
|
|
|
|
|
+ class="h-3.5 w-3.5 shrink-0 text-gray-400 transition-transform dark:text-gray-500"
|
|
|
|
|
+ :class="aberto ? 'rotate-180' : ''"
|
|
|
|
|
+ viewBox="0 0 24 24"
|
|
|
|
|
+ fill="none"
|
|
|
|
|
+ stroke="currentColor"
|
|
|
|
|
+ stroke-width="2"
|
|
|
|
|
+ >
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
|
|
|
</svg>
|
|
</svg>
|
|
|
</button>
|
|
</button>
|
|
@@ -25,28 +32,18 @@
|
|
|
<ul
|
|
<ul
|
|
|
v-if="aberto"
|
|
v-if="aberto"
|
|
|
role="listbox"
|
|
role="listbox"
|
|
|
- class="absolute left-0 top-full z-20 mt-2 max-h-72 w-56 origin-top-left overflow-auto rounded-xl border border-gray-200 bg-background py-1 text-sm shadow-lg dark:border-gray-700"
|
|
|
|
|
|
|
+ class="absolute left-0 top-full z-20 mt-2 w-56 origin-top-left rounded-xl border border-gray-200 bg-background py-1.5 text-sm shadow-xl dark:border-gray-700"
|
|
|
>
|
|
>
|
|
|
- <li v-for="opt in opcoesComPadrao" :key="opt.value">
|
|
|
|
|
|
|
+ <li v-for="opt in opcoesComPadrao" :key="opt.value" class="px-1.5">
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
role="option"
|
|
role="option"
|
|
|
:aria-selected="opt.value === modelValue"
|
|
:aria-selected="opt.value === modelValue"
|
|
|
- class="flex w-full items-center justify-between gap-2 px-3 py-1.5 text-left hover:bg-black/[0.04] dark:hover:bg-white/[0.06]"
|
|
|
|
|
- :class="opt.value === modelValue ? 'font-medium text-primary' : 'text-gray-700 dark:text-gray-200'"
|
|
|
|
|
|
|
+ class="w-full rounded-lg border-0 bg-transparent px-2.5 py-2 text-left text-gray-700 hover:bg-gray-200 dark:text-gray-200 dark:hover:bg-white/5"
|
|
|
|
|
+ :class="opt.value === modelValue ? 'bg-gray-200 dark:bg-white/5' : ''"
|
|
|
@click="selecionar(opt.value)"
|
|
@click="selecionar(opt.value)"
|
|
|
>
|
|
>
|
|
|
<span class="truncate">{{ opt.label }}</span>
|
|
<span class="truncate">{{ opt.label }}</span>
|
|
|
- <svg
|
|
|
|
|
- v-if="opt.value === modelValue"
|
|
|
|
|
- class="h-3.5 w-3.5 shrink-0"
|
|
|
|
|
- viewBox="0 0 24 24"
|
|
|
|
|
- fill="none"
|
|
|
|
|
- stroke="currentColor"
|
|
|
|
|
- stroke-width="2"
|
|
|
|
|
- >
|
|
|
|
|
- <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
|
|
|
|
|
- </svg>
|
|
|
|
|
</button>
|
|
</button>
|
|
|
</li>
|
|
</li>
|
|
|
</ul>
|
|
</ul>
|
|
@@ -68,14 +65,18 @@ const emit = defineEmits(["update:modelValue", "change"]);
|
|
|
const aberto = ref(false);
|
|
const aberto = ref(false);
|
|
|
const raiz = ref(null);
|
|
const raiz = ref(null);
|
|
|
|
|
|
|
|
|
|
+const rotuloPadraoCapitalizado = computed(
|
|
|
|
|
+ () => props.rotuloPadrao.charAt(0).toUpperCase() + props.rotuloPadrao.slice(1),
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
const opcoesComPadrao = computed(() => [
|
|
const opcoesComPadrao = computed(() => [
|
|
|
- { value: "", label: `${props.rotulo}: ${props.rotuloPadrao}` },
|
|
|
|
|
|
|
+ { value: "", label: rotuloPadraoCapitalizado.value },
|
|
|
...props.opcoes,
|
|
...props.opcoes,
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
-const rotuloAtual = computed(() => {
|
|
|
|
|
- const selecionada = opcoesComPadrao.value.find((o) => o.value === props.modelValue);
|
|
|
|
|
- return selecionada ? selecionada.label : `${props.rotulo}: ${props.rotuloPadrao}`;
|
|
|
|
|
|
|
+const valorAtual = computed(() => {
|
|
|
|
|
+ const selecionada = props.opcoes.find((o) => o.value === props.modelValue);
|
|
|
|
|
+ return selecionada ? selecionada.label : rotuloPadraoCapitalizado.value;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
function alternar() {
|
|
function alternar() {
|