+
{{ 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 @@
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+ {{ rows }}x{{ cols }}
+
+
+
+ Cerrar
+
+
+
+
+
+
+
\ 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];
-
-
-
Estilo:
-
+
+
+
+
+
+ {{ activeElementInfo?.context === 'table-cell' ? 'Celda de tabla' : 'Texto' }}
+
+
+
+
+
@@ -119,7 +161,7 @@ const fontSizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];
'w-8 h-8 rounded flex items-center justify-center text-sm italic transition-colors',
formatting.italic
? 'bg-blue-500 text-white shadow-sm'
- : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200 dark:bg-primary-d dark:text-primary-dt dark:hover:bg-primary/10 dark:border-primary/20'
+ : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200'
]"
title="Cursiva (Ctrl+I)"
>
@@ -132,38 +174,32 @@ const fontSizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];
'w-8 h-8 rounded flex items-center justify-center text-sm underline transition-colors',
formatting.underline
? 'bg-blue-500 text-white shadow-sm'
- : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200 dark:bg-primary-d dark:text-primary-dt dark:hover:bg-primary/10 dark:border-primary/20'
+ : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200'
]"
title="Subrayado (Ctrl+U)"
>
U
-
-
-
+
+
-
-
- Tamaño:
+
{{ size }}px
-
-
-
+
+
-
-
-
Alinear:
+
@@ -184,7 +220,7 @@ const fontSizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];
'w-8 h-8 rounded flex items-center justify-center transition-colors',
formatting.textAlign === 'center'
? 'bg-blue-500 text-white shadow-sm'
- : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200 dark:bg-primary-d dark:text-primary-dt dark:hover:bg-primary/10 dark:border-primary/20'
+ : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200'
]"
title="Centrar"
>
@@ -197,27 +233,23 @@ const fontSizes = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];
'w-8 h-8 rounded flex items-center justify-center transition-colors',
formatting.textAlign === 'right'
? 'bg-blue-500 text-white shadow-sm'
- : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200 dark:bg-primary-d dark:text-primary-dt dark:hover:bg-primary/10 dark:border-primary/20'
+ : 'bg-white text-gray-700 hover:bg-blue-50 border border-gray-200'
]"
title="Alinear derecha"
>
-
-
-
+
+
-
-
-
-
-
-
Elemento de texto seleccionado
+
+
+ {{ activeElementInfo?.context === 'table-cell' ? 'Formateando celda de tabla' : 'Formateando texto' }}
+
\ 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 @@
-
-
-
+
+
+
-
-
-
-
+
+
+
+
Diseñador de Documentos
@@ -540,7 +606,7 @@ onMounted(() => {
@@ -548,12 +614,8 @@ onMounted(() => {
{{ isExporting ? 'Generando PDF...' : 'Exportar PDF' }}
@@ -561,15 +623,16 @@ onMounted(() => {
-
-
+
+
Elementos
-
+
Arrastra elementos al canvas para crear tu documento
-
+
+
{
/>
-
-
- Agregar rápido
-
-
-
-
-
- {{ element.title }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Agregar rápido
+
+
+
+
+
+ {{ element.title }}
-
-
- {{ totalElements }} elemento{{ totalElements !== 1 ? 's' : '' }} • {{ pages.length }} página{{ pages.length !== 1 ? 's' : '' }}
-
-
+
+
Limpiar Todo
+
+
+
+
+
+
+
+
+ {{ documentTitle }}
+
+
+
+
+
+ {{ totalElements }} elemento{{ totalElements !== 1 ? 's' : '' }} • {{ pages.length }} página{{ pages.length !== 1 ? 's' : '' }}
+
+
+
+
+
+
{
@add-page="addPage"
@delete-page="deletePage"
@page-change="(page) => currentPage = page"
+ @page-size-change="handlePageSizeChange"
>
{
@delete="deleteElement"
@update="updateElement"
@move="moveElement"
+ @text-selected="handleTextSelected"
/>