141 lines
5.0 KiB
Vue
141 lines
5.0 KiB
Vue
<script setup>
|
|
import { ref, computed } from 'vue';
|
|
import GoogleIcon from '@Shared/GoogleIcon.vue';
|
|
|
|
/** Propiedades */
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: String,
|
|
default: 'A4'
|
|
}
|
|
});
|
|
|
|
/** Eventos */
|
|
const emit = defineEmits(['update:modelValue']);
|
|
|
|
/** Referencias */
|
|
const isOpen = ref(false);
|
|
|
|
/** Tamaños de página disponibles */
|
|
const pageSizes = [
|
|
{
|
|
name: 'A4',
|
|
label: 'A4 (210 x 297 mm)',
|
|
width: 794,
|
|
height: 1123,
|
|
description: 'Estándar internacional'
|
|
},
|
|
{
|
|
name: 'A3',
|
|
label: 'A3 (297 x 420 mm)',
|
|
width: 1123,
|
|
height: 1587,
|
|
description: 'Doble de A4'
|
|
},
|
|
{
|
|
name: 'Letter',
|
|
label: 'Carta (216 x 279 mm)',
|
|
width: 816,
|
|
height: 1056,
|
|
description: 'Estándar US'
|
|
},
|
|
{
|
|
name: 'Legal',
|
|
label: 'Oficio (216 x 356 mm)',
|
|
width: 816,
|
|
height: 1344,
|
|
description: 'Legal US'
|
|
},
|
|
{
|
|
name: 'Tabloid',
|
|
label: 'Tabloide (279 x 432 mm)',
|
|
width: 1056,
|
|
height: 1632,
|
|
description: 'Doble carta'
|
|
}
|
|
];
|
|
|
|
/** Propiedades computadas */
|
|
const selectedSize = computed(() => {
|
|
return pageSizes.find(size => size.name === props.modelValue) || pageSizes[0];
|
|
});
|
|
|
|
/** Métodos */
|
|
const selectSize = (size) => {
|
|
emit('update:modelValue', size.name);
|
|
isOpen.value = false;
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="relative">
|
|
<!-- Selector principal -->
|
|
<button
|
|
@click="isOpen = !isOpen"
|
|
class="flex items-center gap-2 px-3 py-2 text-sm bg-white dark:bg-primary-d border border-gray-200 dark:border-primary/20 rounded-md hover:bg-gray-50 dark:hover:bg-primary/10 transition-colors"
|
|
>
|
|
<GoogleIcon name="aspect_ratio" class="text-gray-500 dark:text-primary-dt/70" />
|
|
<span class="text-gray-700 dark:text-primary-dt">{{ selectedSize.name }}</span>
|
|
<GoogleIcon
|
|
name="expand_more"
|
|
class="text-gray-400 dark:text-primary-dt/50 transition-transform"
|
|
:class="{ 'rotate-180': isOpen }"
|
|
/>
|
|
</button>
|
|
|
|
<!-- Dropdown -->
|
|
<div
|
|
v-if="isOpen"
|
|
@click.away="isOpen = false"
|
|
class="absolute top-full left-0 mt-1 w-72 bg-white dark:bg-primary-d border border-gray-200 dark:border-primary/20 rounded-lg shadow-lg z-50 py-2"
|
|
>
|
|
<div class="px-3 py-2 text-xs font-semibold text-gray-500 dark:text-primary-dt/70 uppercase tracking-wider border-b border-gray-100 dark:border-primary/20">
|
|
Tamaños de página
|
|
</div>
|
|
|
|
<div class="max-h-64 overflow-y-auto">
|
|
<button
|
|
v-for="size in pageSizes"
|
|
:key="size.name"
|
|
@click="selectSize(size)"
|
|
class="w-full flex items-center gap-3 px-3 py-3 hover:bg-gray-50 dark:hover:bg-primary/10 transition-colors text-left"
|
|
:class="{
|
|
'bg-blue-50 dark:bg-blue-900/20': selectedSize.name === size.name
|
|
}"
|
|
>
|
|
<div class="flex-shrink-0">
|
|
<div
|
|
class="w-8 h-10 border border-gray-300 dark:border-primary/30 rounded-sm bg-white dark:bg-primary-d flex items-center justify-center"
|
|
:class="{
|
|
'border-blue-500 dark:border-blue-400': selectedSize.name === size.name
|
|
}"
|
|
>
|
|
<div
|
|
class="bg-gray-200 dark:bg-primary/20 rounded-sm"
|
|
:style="{
|
|
width: `${Math.min(20, (size.width / size.height) * 32)}px`,
|
|
height: `${Math.min(32, (size.height / size.width) * 20)}px`
|
|
}"
|
|
:class="{
|
|
'bg-blue-200 dark:bg-blue-800': selectedSize.name === size.name
|
|
}"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex-1 min-w-0">
|
|
<div class="font-medium text-gray-900 dark:text-primary-dt">{{ size.label }}</div>
|
|
<div class="text-xs text-gray-500 dark:text-primary-dt/70">{{ size.description }}</div>
|
|
<div class="text-xs text-gray-400 dark:text-primary-dt/50 mt-1">
|
|
{{ size.width }} x {{ size.height }} px
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="selectedSize.name === size.name" class="flex-shrink-0">
|
|
<GoogleIcon name="check" class="text-blue-500 dark:text-blue-400" />
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template> |