// Global state management const state = { currentProject: null, selectedElement: null, elements: [], history: [], historyIndex: -1, canvasSize: { width: 800, height: 600 }, colorPalette: ['#6366F1', '#F59E0B', '#10B981', '#EF4444', '#3B82F6', '#8B5CF6', '#EC4899'], fonts: ['Inter', 'Arial', 'Helvetica', 'Times New Roman', 'Courier New', 'Georgia', 'Verdana'], darkMode: window.matchMedia('(prefers-color-scheme: dark)').matches }; // Initialize dark mode function initDarkMode() { if (state.darkMode) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } } // Save project to localStorage function saveProject() { if (state.currentProject) { const projectData = { id: state.currentProject.id, name: state.currentProject.name, elements: state.elements, canvasSize: state.canvasSize, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; localStorage.setItem(`project_${state.currentProject.id}`, JSON.stringify(projectData)); } } // Load project from localStorage function loadProject(projectId) { const projectData = localStorage.getItem(`project_${projectId}`); if (projectData) { const parsedData = JSON.parse(projectData); state.currentProject = { id: parsedData.id, name: parsedData.name, createdAt: parsedData.createdAt, updatedAt: parsedData.updatedAt }; state.elements = parsedData.elements || []; state.canvasSize = parsedData.canvasSize || { width: 800, height: 600 }; // Render elements on canvas renderElements(); } } // Render elements on canvas function renderElements() { const stage = window.designStage; const layer = window.designLayer; // Clear existing elements layer.destroyChildren(); // Set canvas size stage.width(state.canvasSize.width); stage.height(state.canvasSize.height); // Render each element state.elements.forEach(element => { let konvaElement; switch (element.type) { case 'text': konvaElement = new Konva.Text({ x: element.x, y: element.y, text: element.text, fontSize: element.fontSize, fontFamily: element.fontFamily, fill: element.color, align: element.align, width: element.width, draggable: true }); break; case 'image': // Image rendering logic break; case 'shape': // Shape rendering logic break; } if (konvaElement) { layer.add(konvaElement); } }); stage.add(layer); } // Initialize app document.addEventListener('DOMContentLoaded', () => { initDarkMode(); // Listen for dark mode changes window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { state.darkMode = e.matches; initDarkMode(); }); // Create new project if none exists if (!state.currentProject) { state.currentProject = { id: Date.now().toString(), name: 'Novo Projeto', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; } // Initialize stage events setupStageEvents(); }); function setupStageEvents() { const stage = window.designStage; const layer = window.designLayer; stage.on('click tap', (e) => { // Deselect previous element if (state.selectedElement) { state.selectedElement.stroke(null); state.selectedElement = null; } // If clicked on empty space, return if (e.target === stage) return; // Select clicked element state.selectedElement = e.target; e.target.stroke('#6366f1'); // Update properties panel updatePropertiesPanel(e.target); stage.batchDraw(); }); } function updatePropertiesPanel(element) { const panel = document.querySelector('custom-properties-panel').shadowRoot; if (element instanceof Konva.Text) { panel.getElementById('text-content').value = element.text(); panel.getElementById('text-font').value = element.fontFamily(); panel.getElementById('text-size').value = element.fontSize(); } }