diff --git a/src/components/Holos/PDF/Canvas.vue b/src/components/Holos/PDF/Canvas.vue index d43e9fc..979d854 100644 --- a/src/components/Holos/PDF/Canvas.vue +++ b/src/components/Holos/PDF/Canvas.vue @@ -1,25 +1,26 @@ \ No newline at end of file diff --git a/src/components/Holos/PDF/Draggable.vue b/src/components/Holos/PDF/Draggable.vue index 4bd032c..1b07f89 100644 --- a/src/components/Holos/PDF/Draggable.vue +++ b/src/components/Holos/PDF/Draggable.vue @@ -39,24 +39,24 @@ const handleDragEnd = () => { draggable="true" @dragstart="handleDragStart" @dragend="handleDragEnd" - class="flex items-center gap-3 p-3 rounded-lg border border-gray-200 bg-white cursor-grab hover:bg-gray-50 hover:border-blue-300 transition-colors dark:bg-primary-d dark:border-primary/20 dark:hover:bg-primary/10" + class="flex items-center gap-2 sm:gap-3 p-2 sm:p-3 rounded-lg border border-gray-200 bg-white cursor-grab hover:bg-gray-50 hover:border-blue-300 transition-colors" :class="{ 'opacity-50 cursor-grabbing': isDragging, 'shadow-sm hover:shadow-md': !isDragging }" > -
+
-
+
{{ title }}
-
+
diff --git a/src/components/Holos/PDF/TableEditor.vue b/src/components/Holos/PDF/TableEditor.vue new file mode 100644 index 0000000..7e5a280 --- /dev/null +++ b/src/components/Holos/PDF/TableEditor.vue @@ -0,0 +1,201 @@ + + + \ No newline at end of file diff --git a/src/components/Holos/PDF/TextFormatter.vue b/src/components/Holos/PDF/TextFormatter.vue index 66b98db..ee98acd 100644 --- a/src/components/Holos/PDF/TextFormatter.vue +++ b/src/components/Holos/PDF/TextFormatter.vue @@ -2,111 +2,153 @@ import { ref, computed, watch } from 'vue'; import GoogleIcon from '@Shared/GoogleIcon.vue'; -/** Propiedades */ const props = defineProps({ - element: { + selectedElement: { type: Object, default: null }, visible: { type: Boolean, default: false + }, + activeTextElement: { + type: Object, + default: null } }); -/** Eventos */ -const emit = defineEmits(['update']); +const emit = defineEmits(['update', 'smart-align']); -/** Propiedades computadas */ -const formatting = computed(() => props.element?.formatting || {}); -const hasTextElement = computed(() => props.element?.type === 'text'); +// Determinar si hay un elemento de texto activo (puede ser texto directo o celda de tabla) +const hasActiveText = computed(() => { + return props.visible && ( + props.selectedElement?.type === 'text' || + props.activeTextElement?.type === 'text' || + (props.selectedElement?.type === 'table' && props.activeTextElement) + ); +}); -/** Métodos */ +// Obtener formato del elemento activo +const formatting = computed(() => { + if (props.activeTextElement) { + return props.activeTextElement.formatting || {}; + } + if (props.selectedElement?.type === 'text') { + return props.selectedElement.formatting || {}; + } + return {}; +}); + +// Obtener información del elemento activo +const activeElementInfo = computed(() => { + if (props.activeTextElement) { + return { + type: 'text', + context: props.selectedElement?.type === 'table' ? 'table-cell' : 'text-element' + }; + } + if (props.selectedElement?.type === 'text') { + return { + type: 'text', + context: 'text-element' + }; + } + return null; +}); + +/** Métodos de formato */ const toggleBold = () => { - if (!hasTextElement.value) return; + if (!hasActiveText.value) return; updateFormatting('bold', !formatting.value.bold); }; const toggleItalic = () => { - if (!hasTextElement.value) return; + if (!hasActiveText.value) return; updateFormatting('italic', !formatting.value.italic); }; const toggleUnderline = () => { - if (!hasTextElement.value) return; + if (!hasActiveText.value) return; updateFormatting('underline', !formatting.value.underline); }; const updateFontSize = (size) => { - if (!hasTextElement.value) return; + if (!hasActiveText.value) return; updateFormatting('fontSize', size); }; const updateTextAlign = (align) => { - if (!hasTextElement.value) return; + if (!hasActiveText.value) return; updateFormatting('textAlign', align); }; const updateColor = (color) => { - if (!hasTextElement.value) return; + if (!hasActiveText.value) return; updateFormatting('color', color); }; const updateFormatting = (key, value) => { const newFormatting = { ...formatting.value, [key]: value }; - emit('update', { - id: props.element.id, - formatting: newFormatting - }); -}; - -const updateContainerAlign = (align) => { - if (!hasTextElement.value) return; - updateFormatting('containerAlign', align); -}; - -const updateSmartAlign = (align) => { - if (!hasTextElement.value) return; - // Emitir tanto la alineación del texto como la posición del contenedor - emit('smart-align', { - id: props.element.id, - align: align, - formatting: { - ...formatting.value, - textAlign: align, - containerAlign: align - } - }); + // Determinar qué elemento actualizar + let targetId = null; + if (props.activeTextElement) { + targetId = props.activeTextElement.id; + } else if (props.selectedElement?.type === 'text') { + targetId = props.selectedElement.id; + } + + if (targetId) { + emit('update', { + id: targetId, + formatting: newFormatting, + context: activeElementInfo.value?.context + }); + } }; -/** Colores predefinidos */ +/** Colores y tamaños predefinidos */ const predefinedColors = [ '#000000', '#333333', '#666666', '#999999', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#800080' ]; -/** Tamaños de fuente */ const fontSizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72]; \ No newline at end of file diff --git a/src/pages/Maquetador/Index.vue b/src/pages/Maquetador/Index.vue index a9f2790..6024e36 100644 --- a/src/pages/Maquetador/Index.vue +++ b/src/pages/Maquetador/Index.vue @@ -1,10 +1,11 @@