Spaces:
Running
Running
| // 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(); | |
| } | |
| } | |