Spaces:
Running
Running
make drastic improvements on every element of this application. make it a 10/10 enterprise application: "<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Slide Builder Plus</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: Arial, sans-serif; background: #f0f0f0; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; background: white; padding: 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h1 { color: #333; margin-bottom: 20px; text-align: center; } .controls { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; } button { padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; } button:hover { background: #0056b3; } button.danger { background: #dc3545; } button.danger:hover { background: #c82333; } button.success { background: #28a745; } button.success:hover { background: #218838; } button.secondary { background: #6c757d; } button.secondary:hover { background: #5a6268; } .preview { border: 2px solid #ddd; border-radius: 10px; padding: 40px; min-height: 400px; background: #fff; margin-bottom: 20px; } .preview.dark { background: #2d2d2d; color: white; } .preview.blue { background: #e3f2fd; } .slide-element { margin-bottom: 20px; padding: 10px; border: 1px dashed transparent; cursor: pointer; position: relative; } .slide-element:hover { border-color: #007bff; background: #f8f9fa; } .slide-element.selected { border: 2px solid #007bff; background: #e7f3ff; } .element-controls { position: absolute; top: 5px; right: 5px; display: none; gap: 5px; } .slide-element.selected .element-controls { display: flex; } .element-title { font-size: 48px; text-align: center; font-weight: bold; color: #333; } .preview.dark .element-title { color: white; } .element-heading { font-size: 32px; color: #444; margin-bottom: 10px; } .preview.dark .element-heading { color: #f0f0f0; } .element-text { font-size: 18px; line-height: 1.6; color: #666; } .preview.dark .element-text { color: #ccc; } .element-list { font-size: 18px; line-height: 1.8; color: #666; padding-left: 30px; } .preview.dark .element-list { color: #ccc; } .element-quote { font-size: 24px; font-style: italic; text-align: center; padding: 20px; border-left: 4px solid #007bff; background: rgba(0,123,255,0.05); } .element-divider { height: 2px; background: #ddd; margin: 20px 0; } .edit-panel { display: none; background: #f8f9fa; padding: 20px; border-radius: 10px; margin-bottom: 20px; } .edit-panel.active { display: block; } .edit-panel h3 { margin-bottom: 15px; color: #333; } textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px; resize: vertical; } .export-panel { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 30px; border-radius: 10px; box-shadow: 0 5px 30px rgba(0,0,0,0.3); z-index: 1000; max-width: 90%; width: 800px; } .export-panel.active { display: block; } .overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 999; } .overlay.active { display: block; } .close-btn { float: right; background: #dc3545; padding: 5px 15px; } .close-btn:hover { background: #c82333; } #exportCode { width: 100%; height: 300px; margin: 20px 0; font-family: monospace; font-size: 12px; } .button-group { display: flex; gap: 10px; } .button-group button { flex: 1; } .info-box { background: #d1ecf1; border: 1px solid #bee5eb; padding: 15px; border-radius: 5px; margin-bottom: 20px; color: #0c5460; } .theme-buttons { display: flex; gap: 10px; margin-bottom: 20px; } .align-left { text-align: left; } .align-center { text-align: center; } .align-right { text-align: right; } .control-btn { padding: 5px 10px; font-size: 12px; background: white; color: #333; border: 1px solid #ddd; } .control-btn:hover { background: #f8f9fa; } select { padding: 5px; margin: 0 10px; border: 1px solid #ddd; border-radius: 3px; } </style> </head> <body> <div class="container"> <h1>📝 Slide Builder Plus</h1> <div class="info-box"> <strong>Quick Start:</strong> Click buttons to add elements, click elements to edit, apply themes, then export! </div> <div class="controls"> <button onclick="addTitle()">Add Title</button> <button onclick="addHeading()">Add Heading</button> <button onclick="addText()">Add Text</button> <button onclick="addList()">Add List</button> <button onclick="addQuote()">Add Quote</button> <button onclick="addDivider()">Add Divider</button> <button onclick="clearAll()" class="danger">Clear All</button> <button onclick="showExport()" class="success">Export HTML</button> </div> <div class="theme-buttons"> <strong>Theme:</strong> <button onclick="setTheme('default')" class="secondary">Default</button> <button onclick="setTheme('dark')" class="secondary">Dark</button> <button onclick="setTheme('blue')" class="secondary">Blue</button> </div> <div class="edit-panel" id="editPanel"> <button class="close-btn" onclick="closeEdit()">×</button> <h3>Edit Element</h3> <textarea id="editInput" rows="4" placeholder="Edit your content here..."></textarea> <div style="margin-top: 10px;"> <strong>Alignment:</strong> <button onclick="setAlign('left')">Left</button> <button onclick="setAlign('center')">Center</button> <button onclick="setAlign('right')">Right</button> </div> <button onclick="saveEdit()" style="margin-top: 10px;" class="success">Save Changes</button> </div> <div class="preview" id="preview"> <p style="text-align: center; color: #999;">Click buttons above to add content to your slide</p> </div> </div> <div class="overlay" id="overlay" onclick="closeExport()"></div> <div class="export-panel" id="exportPanel"> <button class="close-btn" onclick="closeExport()">×</button> <h3>Export Your Slide</h3> <p>Copy the HTML code below or download as a file:</p> <textarea id="exportCode" readonly></textarea> <div class="button-group"> <button onclick="copyCode()" class="success">Copy to Clipboard</button> <button onclick="downloadHTML()">Download HTML File</button> </div> </div> <script> // Global variables let elements = []; let selectedElement = null; let elementIdCounter = 0; let currentTheme = 'default'; // Add Title function addTitle() { const element = { id: elementIdCounter++, type: 'title', content: 'Your Awesome Title', align: 'center' }; elements.push(element); renderPreview(); } // Add Heading function addHeading() { const element = { id: elementIdCounter++, type: 'heading', content: 'Section Heading', align: 'left' }; elements.push(element); renderPreview(); } // Add Text function addText() { const element = { id: elementIdCounter++, type: 'text', content: 'Your paragraph text goes here. Click to edit and add your own content.', align: 'left' }; elements.push(element); renderPreview(); } // Add List function addList() { const element = { id: elementIdCounter++, type: 'list', content: 'First item\nSecond item\nThird item', align: 'left' }; elements.push(element); renderPreview(); } // Add Quote function addQuote() { const element = { id: elementIdCounter++, type: 'quote', content: 'The only way to do great work is to love what you do. - Steve Jobs', align: 'center' }; elements.push(element); renderPreview(); } // Add Divider function addDivider() { const element = { id: elementIdCounter++, type: 'divider', align: 'center' }; elements.push(element); renderPreview(); } // Clear All function clearAll() { if (confirm('Are you sure you want to clear all elements?')) { elements = []; renderPreview(); } } // Set Theme function setTheme(theme) { currentTheme = theme; const preview = document.getElementById('preview'); preview.className = 'preview ' + (theme !== 'default' ? theme : ''); } // Render Preview function renderPreview() { const preview = document.getElementById('preview'); if (elements.length === 0) { preview.innerHTML = '<p style="text-align: center; color: #999;">Click buttons above to add content to your slide</p>'; return; } preview.innerHTML = ''; elements.forEach(element => { const div = document.createElement('div'); div.className = 'slide-element'; div.onclick = () => selectElement(element.id); // Add controls const controls = document.createElement('div'); controls.className = 'element-controls'; controls.innerHTML = ` <button class="control-btn" onclick="event.stopPropagation(); moveUp(${element.id})">↑</button> <button class="control-btn" onclick="event.stopPropagation(); moveDown(${element.id})">↓</button> <button class="control-btn" onclick="event.stopPropagation(); deleteElement(${element.id})">×</button> `; div.appendChild(controls); // Add content wrapper with alignment const contentWrapper = document.createElement('div'); contentWrapper.className = 'align-' + element.align; switch(element.type) { case 'title': contentWrapper.innerHTML = `<h1 class="element-title">${element.content}</h1>`; break; case 'heading': contentWrapper.innerHTML = `<h2 class="element-heading">${element.content}</h2>`; break; case 'text': contentWrapper.innerHTML = `<p class="element-text">${element.content.replace(/\n/g, '<br>')}</p>`; break; case 'list': const items = element.content.split('\n').map(item => `<li>${item}</li>`).join(''); contentWrapper.innerHTML = `<ul class="element-list">${items}</ul>`; break; case 'quote': contentWrapper.innerHTML = `<blockquote class="element-quote">${element.content}</blockquote>`; break; case 'divider': contentWrapper.innerHTML = `<hr class="element-divider">`; break; } div.appendChild(contentWrapper); preview.appendChild(div); }); } // Select Element function selectElement(id) { selectedElement = elements.find(el => el.id === id); // Remove previous selection document.querySelectorAll('.slide-element').forEach(el => { el.classList.remove('selected'); }); // Add selection to clicked element event.currentTarget.classList.add('selected'); // Show edit panel for editable types if (selectedElement.type !== 'divider') { document.getElementById('editPanel').classList.add('active'); document.getElementById('editInput').value = selectedElement.content; } } // Close Edit function closeEdit() { document.getElementById('editPanel').classList.remove('active'); document.querySelectorAll('.slide-element').forEach(el => { el.classList.remove('selected'); }); selectedElement = null; } // Save Edit function saveEdit() { if (selectedElement) { selectedElement.content = document.getElementById('editInput').value; renderPreview(); closeEdit(); } } // Set Alignment function setAlign(alignment) { if (selectedElement) { selectedElement.align = alignment; renderPreview(); selectElement(selectedElement.id); } } // Delete Element function deleteElement(id) { elements = elements.filter(el => el.id !== id); renderPreview(); } // Move Up function moveUp(id) { const index = elements.findIndex(el => el.id === id); if (index > 0) { [elements[index], elements[index - 1]] = [elements[index - 1], elements[index]]; renderPreview(); } } // Move Down function moveDown(id) { const index = elements.findIndex(el => el.id === id); if (index < elements.length - 1) { [elements[index], elements[index + 1]] = [elements[index + 1], elements[index]]; renderPreview(); } } // Show Export function showExport() { const html = generateHTML(); document.getElementById('exportCode').value = html; document.getElementById('exportPanel').classList.add('active'); document.getElementById('overlay').classList.add('active'); } // Close Export function closeExport() { document.getElementById('exportPanel').classList.remove('active'); document.getElementById('overlay').classList.remove('active'); } // Generate HTML function generateHTML() { let content = ''; elements.forEach(element => { const alignClass = element.align !== 'left' ? ` style="text-align: ${element.align};"` : ''; switch(element.type) { case 'title': content += `<h1 style="font-size: 48px; text-align: ${element.align}; margin: 40px 0; color: ${currentTheme === 'dark' ? 'white' : '#333'};">${element.content}</h1>\n`; break; case 'heading': content += `<h2 style="font-size: 32px; text-align: ${element.align}; margin: 30px 0; color: ${currentTheme === 'dark' ? '#f0f0f0' : '#444'};">${element.content}</h2>\n`; break; case 'text': content += `<p style="font-size: 18px; line-height: 1.6; text-align: ${element.align}; margin: 20px 0; color: ${currentTheme === 'dark' ? '#ccc' : '#666'};">${element.content.replace(/\n/g, '<br>')}</p>\n`; break; case 'list': const items = element.content.split('\n').map(item => `<li>${item}</li>`).join('\n'); content += `<ul style="font-size: 18px; line-height: 1.8; text-align: ${element.align}; margin: 20px 0; padding-left: 30px; color: ${currentTheme === 'dark' ? '#ccc' : '#666'};">\n${items}\n</ul>\n`; break; case 'quote': content += `<blockquote style="font-size: 24px; font-style: italic; text-align: center; padding: 20px 40px; border-left: 4px solid #007bff; background: rgba(0,123,255,0.05); margin: 30px 0;">${element.content}</blockquote>\n`; break; case 'divider': content += `<hr style="border: none; height: 2px; background: #ddd; margin: 30px 0;">\n`; break; } }); const bgColor = currentTheme === 'dark' ? '#2d2d2d' : currentTheme === 'blue' ? '#e3f2fd' : '#f5f5f5'; const textColor = currentTheme === 'dark' ? 'white' : '#333'; return `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My Presentation Slide</title> <style> body { font-family: Arial, sans-serif; max-width: 1000px; margin: 0 auto; padding: 60px 40px; background: ${bgColor}; color: ${textColor}; } .slide { background: ${currentTheme === 'dark' ? '#1a1a1a' : 'white'}; padding: 60px; border-radius: 10px; box-shadow: 0 5px 30px rgba(0,0,0,0.1); min-height: 600px; display: flex; flex-direction: column; justify-content: center; } </style> </head> <body> <div class="slide"> ${content} </div> </body> </html>`; } // Copy Code function copyCode() { const textarea = document.getElementById('exportCode'); textarea.select(); document.execCommand('copy'); // Show feedback const button = event.target; const originalText = button.textContent; button.textContent = 'Copied!'; setTimeout(() => { button.textContent = originalText; }, 2000); } // Download HTML function downloadHTML() { const html = document.getElementById('exportCode').value; const blob = new Blob([html], { type: 'text/html' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'my-slide.html'; a.click(); window.URL.revokeObjectURL(url); } // Test on load window.onload = function() { console.log('Slide Builder Plus: Ready'); }; </script> </body> </html>" - Initial Deployment
a0eda66 verified | <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Slide Builder Pro | Enterprise Presentation Tool</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: { | |
| 50: '#f0f9ff', | |
| 100: '#e0f2fe', | |
| 200: '#bae6fd', | |
| 300: '#7dd3fc', | |
| 400: '#38bdf8', | |
| 500: '#0ea5e9', | |
| 600: '#0284c7', | |
| 700: '#0369a1', | |
| 800: '#075985', | |
| 900: '#0c4a6e', | |
| }, | |
| secondary: { | |
| 50: '#f8fafc', | |
| 100: '#f1f5f9', | |
| 200: '#e2e8f0', | |
| 300: '#cbd5e1', | |
| 400: '#94a3b8', | |
| 500: '#64748b', | |
| 600: '#475569', | |
| 700: '#334155', | |
| 800: '#1e293b', | |
| 900: '#0f172a', | |
| }, | |
| success: { | |
| 50: '#f0fdf4', | |
| 100: '#dcfce7', | |
| 200: '#bbf7d0', | |
| 300: '#86efac', | |
| 400: '#4ade80', | |
| 500: '#22c55e', | |
| 600: '#16a34a', | |
| 700: '#15803d', | |
| 800: '#166534', | |
| 900: '#14532d', | |
| }, | |
| danger: { | |
| 50: '#fff1f2', | |
| 100: '#ffe4e6', | |
| 200: '#fecdd3', | |
| 300: '#fda4af', | |
| 400: '#fb7185', | |
| 500: '#f43f5e', | |
| 600: '#e11d48', | |
| 700: '#be123c', | |
| 800: '#9f1239', | |
| 900: '#881337', | |
| }, | |
| warning: { | |
| 50: '#fffbeb', | |
| 100: '#fef3c7', | |
| 200: '#fde68a', | |
| 300: '#fcd34d', | |
| 400: '#fbbf24', | |
| 500: '#f59e0b', | |
| 600: '#d97706', | |
| 700: '#b45309', | |
| 800: '#92400e', | |
| 900: '#78350f', | |
| }, | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| .slide-element { | |
| transition: all 0.2s ease; | |
| } | |
| .slide-element:hover { | |
| transform: translateY(-2px); | |
| } | |
| .element-controls { | |
| opacity: 0; | |
| transition: opacity 0.2s ease; | |
| } | |
| .slide-element:hover .element-controls { | |
| opacity: 1; | |
| } | |
| .preview-container { | |
| min-height: 500px; | |
| background-size: 40px 40px; | |
| background-image: linear-gradient(to right, rgba(0, 0, 0, 0.03) 1px, transparent 1px), | |
| linear-gradient(to bottom, rgba(0, 0, 0, 0.03) 1px, transparent 1px); | |
| } | |
| .dark .preview-container { | |
| background-image: linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px), | |
| linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px); | |
| } | |
| .export-code { | |
| font-family: 'Fira Code', monospace; | |
| } | |
| .slide-element.selected { | |
| box-shadow: 0 0 0 2px theme('colors.primary.500'); | |
| } | |
| .element-title { | |
| background: linear-gradient(to right, theme('colors.primary.600'), theme('colors.primary.400')); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .dark .element-title { | |
| background: linear-gradient(to right, theme('colors.primary.400'), theme('colors.primary.200')); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .element-quote { | |
| border-left: 4px solid theme('colors.primary.500'); | |
| } | |
| .dark .element-quote { | |
| border-left: 4px solid theme('colors.primary.400'); | |
| } | |
| .element-divider { | |
| height: 2px; | |
| background: linear-gradient(to right, transparent, theme('colors.primary.500'), transparent); | |
| } | |
| .dark .element-divider { | |
| background: linear-gradient(to right, transparent, theme('colors.primary.400'), transparent); | |
| } | |
| .theme-preview { | |
| width: 24px; | |
| height: 24px; | |
| border-radius: 4px; | |
| } | |
| .theme-preview.default { | |
| background: linear-gradient(135deg, #ffffff 50%, #f3f4f6 50%); | |
| } | |
| .theme-preview.dark { | |
| background: linear-gradient(135deg, #1e293b 50%, #0f172a 50%); | |
| } | |
| .theme-preview.blue { | |
| background: linear-gradient(135deg, #e0f2fe 50%, #bae6fd 50%); | |
| } | |
| .theme-preview.gradient { | |
| background: linear-gradient(135deg, #4f46e5 50%, #7c3aed 50%); | |
| } | |
| .theme-preview.modern { | |
| background: linear-gradient(135deg, #f5f5f5 50%, #e5e5e5 50%); | |
| } | |
| .theme-preview.warm { | |
| background: linear-gradient(135deg, #fef3c7 50%, #fde68a 50%); | |
| } | |
| .element-image-placeholder { | |
| background-color: theme('colors.gray.100'); | |
| border: 2px dashed theme('colors.gray.300'); | |
| } | |
| .dark .element-image-placeholder { | |
| background-color: theme('colors.gray.800'); | |
| border: 2px dashed theme('colors.gray.700'); | |
| } | |
| .tabs button.active { | |
| position: relative; | |
| } | |
| .tabs button.active:after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -1px; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background-color: theme('colors.primary.500'); | |
| } | |
| .animate-pulse { | |
| animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { | |
| opacity: 1; | |
| } | |
| 50% { | |
| opacity: 0.5; | |
| } | |
| } | |
| .toast { | |
| animation: slideIn 0.3s ease-out, fadeOut 0.3s ease-out 2.7s forwards; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| transform: translateY(20px); | |
| opacity: 0; | |
| } | |
| to { | |
| transform: translateY(0); | |
| opacity: 1; | |
| } | |
| } | |
| @keyframes fadeOut { | |
| to { | |
| opacity: 0; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 dark:bg-gray-900 transition-colors duration-200"> | |
| <div class="fixed inset-0 overflow-y-auto"> | |
| <!-- Toast Notification --> | |
| <div id="toast" class="fixed top-4 right-4 z-50 hidden"> | |
| <div class="toast bg-green-500 text-white px-4 py-3 rounded-lg shadow-lg flex items-center"> | |
| <i class="fas fa-check-circle mr-2"></i> | |
| <span id="toast-message">Copied to clipboard!</span> | |
| </div> | |
| </div> | |
| <!-- Main Container --> | |
| <div class="min-h-screen flex flex-col"> | |
| <!-- Header --> | |
| <header class="bg-white dark:bg-gray-800 shadow-sm"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4"> | |
| <div class="flex justify-between items-center"> | |
| <div class="flex items-center space-x-4"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-sliders-h text-primary-500 text-2xl mr-2"></i> | |
| <h1 class="text-xl font-bold text-gray-900 dark:text-white">Slide Builder Pro</h1> | |
| </div> | |
| <div class="hidden md:flex items-center space-x-1 text-sm"> | |
| <span class="text-gray-500 dark:text-gray-400">File</span> | |
| <span class="text-gray-500 dark:text-gray-400">Edit</span> | |
| <span class="text-gray-500 dark:text-gray-400">View</span> | |
| <span class="text-gray-500 dark:text-gray-400">Help</span> | |
| </div> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <button id="darkModeToggle" class="text-gray-500 dark:text-gray-400 hover:text-primary-500 dark:hover:text-primary-400"> | |
| <i class="fas fa-moon dark:hidden"></i> | |
| <i class="fas fa-sun hidden dark:block"></i> | |
| </button> | |
| <button class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center"> | |
| <i class="fas fa-user-plus mr-2"></i> | |
| <span>Share</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="flex-1"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6"> | |
| <div class="grid grid-cols-1 lg:grid-cols-12 gap-6"> | |
| <!-- Left Sidebar --> | |
| <div class="lg:col-span-3 space-y-6"> | |
| <!-- Elements Panel --> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4 flex items-center"> | |
| <i class="fas fa-shapes mr-2 text-primary-500"></i> | |
| Elements | |
| </h2> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <button onclick="addTitle()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-heading text-primary-500 mb-1 text-lg"></i> | |
| Title | |
| </button> | |
| <button onclick="addHeading()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-heading text-primary-500 mb-1 text-lg"></i> | |
| Heading | |
| </button> | |
| <button onclick="addText()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-paragraph text-primary-500 mb-1 text-lg"></i> | |
| Text | |
| </button> | |
| <button onclick="addList()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-list-ul text-primary-500 mb-1 text-lg"></i> | |
| List | |
| </button> | |
| <button onclick="addQuote()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-quote-right text-primary-500 mb-1 text-lg"></i> | |
| Quote | |
| </button> | |
| <button onclick="addDivider()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-grip-lines text-primary-500 mb-1 text-lg"></i> | |
| Divider | |
| </button> | |
| <button onclick="addImage()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-image text-primary-500 mb-1 text-lg"></i> | |
| Image | |
| </button> | |
| <button onclick="addCode()" class="bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <i class="fas fa-code text-primary-500 mb-1 text-lg"></i> | |
| Code | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Themes Panel --> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4 flex items-center"> | |
| <i class="fas fa-palette mr-2 text-primary-500"></i> | |
| Themes | |
| </h2> | |
| <div class="grid grid-cols-3 gap-3"> | |
| <button onclick="setTheme('default')" class="bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-200 dark:border-gray-600 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <div class="theme-preview default mb-1"></div> | |
| Default | |
| </button> | |
| <button onclick="setTheme('dark')" class="bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-200 dark:border-gray-600 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <div class="theme-preview dark mb-1"></div> | |
| Dark | |
| </button> | |
| <button onclick="setTheme('blue')" class="bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-200 dark:border-gray-600 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <div class="theme-preview blue mb-1"></div> | |
| Blue | |
| </button> | |
| <button onclick="setTheme('gradient')" class="bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-200 dark:border-gray-600 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <div class="theme-preview gradient mb-1"></div> | |
| Gradient | |
| </button> | |
| <button onclick="setTheme('modern')" class="bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-200 dark:border-gray-600 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <div class="theme-preview modern mb-1"></div> | |
| Modern | |
| </button> | |
| <button onclick="setTheme('warm')" class="bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-200 dark:border-gray-600 p-3 rounded-lg flex flex-col items-center text-sm font-medium transition-colors"> | |
| <div class="theme-preview warm mb-1"></div> | |
| Warm | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Export Panel --> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4 flex items-center"> | |
| <i class="fas fa-file-export mr-2 text-primary-500"></i> | |
| Export | |
| </h2> | |
| <div class="space-y-3"> | |
| <button onclick="showExport()" class="w-full bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-file-code mr-2"></i> | |
| Export HTML | |
| </button> | |
| <button onclick="showExportPPT()" class="w-full bg-gray-800 hover:bg-gray-900 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-file-powerpoint mr-2"></i> | |
| Export PPT | |
| </button> | |
| <button onclick="clearAll()" class="w-full bg-danger-500 hover:bg-danger-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-trash-alt mr-2"></i> | |
| Clear All | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Editor Area --> | |
| <div class="lg:col-span-6"> | |
| <!-- Edit Panel --> | |
| <div id="editPanel" class="bg-white dark:bg-gray-800 rounded-lg shadow-sm mb-6 hidden"> | |
| <div class="border-b border-gray-200 dark:border-gray-700 px-4 py-3 flex justify-between items-center"> | |
| <h3 class="text-lg font-medium text-gray-900 dark:text-white">Edit Element</h3> | |
| <button onclick="closeEdit()" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-4"> | |
| <textarea id="editInput" rows="4" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:text-white" placeholder="Edit your content here..."></textarea> | |
| <div class="mt-4"> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Alignment</label> | |
| <div class="flex space-x-2"> | |
| <button onclick="setAlign('left')" class="flex-1 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 py-2 px-4 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-align-left mr-2"></i> Left | |
| </button> | |
| <button onclick="setAlign('center')" class="flex-1 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 py-2 px-4 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-align-center mr-2"></i> Center | |
| </button> | |
| <button onclick="setAlign('right')" class="flex-1 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 py-2 px-4 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-align-right mr-2"></i> Right | |
| </button> | |
| </div> | |
| </div> | |
| <div class="mt-4"> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Text Style</label> | |
| <div class="flex space-x-2"> | |
| <button onclick="toggleTextStyle('bold')" class="p-2 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-lg"> | |
| <i class="fas fa-bold"></i> | |
| </button> | |
| <button onclick="toggleTextStyle('italic')" class="p-2 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-lg"> | |
| <i class="fas fa-italic"></i> | |
| </button> | |
| <button onclick="toggleTextStyle('underline')" class="p-2 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 rounded-lg"> | |
| <i class="fas fa-underline"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <button onclick="saveEdit()" class="mt-4 w-full bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-save mr-2"></i> | |
| Save Changes | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Preview Area --> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm overflow-hidden"> | |
| <div class="border-b border-gray-200 dark:border-gray-700 px-4 py-3 flex justify-between items-center"> | |
| <h3 class="text-lg font-medium text-gray-900 dark:text-white">Slide Preview</h3> | |
| <div class="flex items-center space-x-2"> | |
| <button onclick="zoomOut()" class="p-1 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"> | |
| <i class="fas fa-search-minus"></i> | |
| </button> | |
| <span class="text-sm text-gray-500">100%</span> | |
| <button onclick="zoomIn()" class="p-1 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"> | |
| <i class="fas fa-search-plus"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="p-6 preview-container bg-white dark:bg-gray-900" id="preview"> | |
| <p class="text-center text-gray-400 dark:text-gray-500 py-20">Click elements on the left to add content to your slide</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right Sidebar --> | |
| <div class="lg:col-span-3 space-y-6"> | |
| <!-- Properties Panel --> | |
| <div id="propertiesPanel" class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4 flex items-center"> | |
| <i class="fas fa-sliders-h mr-2 text-primary-500"></i> | |
| Properties | |
| </h2> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Slide Title</label> | |
| <input type="text" id="slideTitle" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:text-white" placeholder="Presentation Title"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Slide Size</label> | |
| <select id="slideSize" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:text-white"> | |
| <option value="16:9">16:9 (Widescreen)</option> | |
| <option value="4:3">4:3 (Standard)</option> | |
| <option value="A4">A4 (Print)</option> | |
| <option value="custom">Custom</option> | |
| </select> | |
| </div> | |
| <div class="grid grid-cols-2 gap-3 hidden" id="customSizeFields"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Width (px)</label> | |
| <input type="number" id="slideWidth" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:text-white" value="1200"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Height (px)</label> | |
| <input type="number" id="slideHeight" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:text-white" value="675"> | |
| </div> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Background</label> | |
| <div class="flex space-x-2"> | |
| <button onclick="setBackground('color')" class="flex-1 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 py-2 px-4 rounded-lg text-sm"> | |
| Color | |
| </button> | |
| <button onclick="setBackground('gradient')" class="flex-1 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 py-2 px-4 rounded-lg text-sm"> | |
| Gradient | |
| </button> | |
| <button onclick="setBackground('image')" class="flex-1 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-200 py-2 px-4 rounded-lg text-sm"> | |
| Image | |
| </button> | |
| </div> | |
| </div> | |
| <div id="bgColorPicker" class="mt-2"> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Background Color</label> | |
| <input type="color" id="backgroundColor" class="w-full h-10 rounded-lg border border-gray-300 dark:border-gray-600" value="#ffffff"> | |
| </div> | |
| <div id="bgGradientPicker" class="mt-2 hidden"> | |
| <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Gradient</label> | |
| <select id="gradientType" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:text-white mb-2"> | |
| <option value="linear">Linear</option> | |
| <option value="radial">Radial</option> | |
| </select> | |
| <div class="grid grid-cols-2 gap-2 mb-2"> | |
| <input type="color" id="gradientColor1" class="w-full h-10 rounded-lg border border-gray-300 dark:border-gray-600" value="#4f46e5"> | |
| <input type="color" id="gradientColor2" class="w-full h-10 rounded-lg border border-gray-300 dark:border-gray-600" value="#7c3aed"> | |
| </div> | |
| <button onclick="applyGradient()" class="w-full bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium"> | |
| Apply Gradient | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- History Panel --> | |
| <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4"> | |
| <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4 flex items-center"> | |
| <i class="fas fa-history mr-2 text-primary-500"></i> | |
| History | |
| </h2> | |
| <div class="space-y-2"> | |
| <div class="flex items-center justify-between p-2 bg-gray-50 dark:bg-gray-700 rounded-lg"> | |
| <span class="text-sm text-gray-700 dark:text-gray-300">Added Title</span> | |
| <button class="text-primary-500 hover:text-primary-600 text-sm font-medium">Undo</button> | |
| </div> | |
| <div class="flex items-center justify-between p-2 bg-gray-50 dark:bg-gray-700 rounded-lg"> | |
| <span class="text-sm text-gray-700 dark:text-gray-300">Changed Theme</span> | |
| <button class="text-primary-500 hover:text-primary-600 text-sm font-medium">Undo</button> | |
| </div> | |
| <div class="flex items-center justify-between p-2 bg-gray-50 dark:bg-gray-700 rounded-lg"> | |
| <span class="text-sm text-gray-700 dark:text-gray-300">Added Image</span> | |
| <button class="text-primary-500 hover:text-primary-600 text-sm font-medium">Undo</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Export Modal --> | |
| <div id="exportModal" class="fixed inset-0 z-50 hidden flex items-center justify-center p-4"> | |
| <div class="absolute inset-0 bg-black bg-opacity-50" onclick="closeExport()"></div> | |
| <div class="relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] flex flex-col"> | |
| <div class="border-b border-gray-200 dark:border-gray-700 px-6 py-4 flex justify-between items-center"> | |
| <h3 class="text-xl font-semibold text-gray-900 dark:text-white">Export Slide</h3> | |
| <button onclick="closeExport()" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-6 overflow-auto flex-1"> | |
| <div class="tabs flex border-b border-gray-200 dark:border-gray-700 mb-4"> | |
| <button onclick="showExportTab('html')" class="px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 active">HTML</button> | |
| <button onclick="showExportTab('ppt')" class="px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700 dark:hover:text-gray-300">PowerPoint</button> | |
| <button onclick="showExportTab('pdf')" class="px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700 dark:hover:text-gray-300">PDF</button> | |
| <button onclick="showExportTab('image')" class="px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700 dark:hover:text-gray-300">Image</button> | |
| </div> | |
| <div id="htmlExportTab" class="export-tab"> | |
| <p class="text-gray-600 dark:text-gray-400 mb-4">Copy the HTML code below or download as a file:</p> | |
| <textarea id="exportCode" class="w-full h-64 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg font-mono text-sm dark:bg-gray-700 dark:text-white" readonly></textarea> | |
| <div class="flex space-x-3 mt-4"> | |
| <button onclick="copyCode()" class="flex-1 bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-copy mr-2"></i> Copy to Clipboard | |
| </button> | |
| <button onclick="downloadHTML()" class="flex-1 bg-gray-800 hover:bg-gray-900 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-download mr-2"></i> Download HTML | |
| </button> | |
| </div> | |
| </div> | |
| <div id="pptExportTab" class="export-tab hidden"> | |
| <p class="text-gray-600 dark:text-gray-400 mb-4">Export your slide as a PowerPoint presentation:</p> | |
| <div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg mb-4"> | |
| <div class="flex items-center mb-3"> | |
| <input type="checkbox" id="includeNotes" class="h-4 w-4 text-primary-500 focus:ring-primary-500 border-gray-300 rounded dark:bg-gray-600 dark:border-gray-500"> | |
| <label for="includeNotes" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">Include speaker notes</label> | |
| </div> | |
| <div class="flex items-center mb-3"> | |
| <input type="checkbox" id="includeTemplate" class="h-4 w-4 text-primary-500 focus:ring-primary-500 border-gray-300 rounded dark:bg-gray-600 dark:border-gray-500" checked> | |
| <label for="includeTemplate" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">Include template design</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="optimizeImages" class="h-4 w-4 text-primary-500 focus:ring-primary-500 border-gray-300 rounded dark:bg-gray-600 dark:border-gray-500" checked> | |
| <label for="optimizeImages" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">Optimize images for PPT</label> | |
| </div> | |
| </div> | |
| <button onclick="exportPPT()" class="w-full bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-file-powerpoint mr-2"></i> Export PowerPoint | |
| </button> | |
| </div> | |
| <div id="pdfExportTab" class="export-tab hidden"> | |
| <p class="text-gray-600 dark:text-gray-400 mb-4">Export your slide as a PDF document:</p> | |
| <div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg mb-4"> | |
| <div class="grid grid-cols-2 gap-4 mb-3"> | |
| <div> | |
| <label class="block text-sm text-gray-700 dark:text-gray-300 mb-1">Page Size</label> | |
| <select class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-600 dark:text-white"> | |
| <option>A4</option> | |
| <option>Letter</option> | |
| <option>A3</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-700 dark:text-gray-300 mb-1">Orientation</label> | |
| <select class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-600 dark:text-white"> | |
| <option>Portrait</option> | |
| <option>Landscape</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="flex items-center mb-3"> | |
| <input type="checkbox" id="includePageNumbers" class="h-4 w-4 text-primary-500 focus:ring-primary-500 border-gray-300 rounded dark:bg-gray-600 dark:border-gray-500"> | |
| <label for="includePageNumbers" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">Include page numbers</label> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="highQuality" class="h-4 w-4 text-primary-500 focus:ring-primary-500 border-gray-300 rounded dark:bg-gray-600 dark:border-gray-500" checked> | |
| <label for="highQuality" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">High quality (slower)</label> | |
| </div> | |
| </div> | |
| <button onclick="exportPDF()" class="w-full bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-file-pdf mr-2"></i> Export PDF | |
| </button> | |
| </div> | |
| <div id="imageExportTab" class="export-tab hidden"> | |
| <p class="text-gray-600 dark:text-gray-400 mb-4">Export your slide as an image:</p> | |
| <div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg mb-4"> | |
| <div class="grid grid-cols-2 gap-4 mb-3"> | |
| <div> | |
| <label class="block text-sm text-gray-700 dark:text-gray-300 mb-1">Format</label> | |
| <select class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-600 dark:text-white"> | |
| <option>PNG</option> | |
| <option>JPEG</option> | |
| <option>SVG</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-700 dark:text-gray-300 mb-1">Quality</label> | |
| <select class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-600 dark:text-white"> | |
| <option>High (100%)</option> | |
| <option>Medium (80%)</option> | |
| <option>Low (60%)</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <input type="checkbox" id="transparentBg" class="h-4 w-4 text-primary-500 focus:ring-primary-500 border-gray-300 rounded dark:bg-gray-600 dark:border-gray-500"> | |
| <label for="transparentBg" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">Transparent background</label> | |
| </div> | |
| </div> | |
| <button onclick="exportImage()" class="w-full bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center"> | |
| <i class="fas fa-image mr-2"></i> Export Image | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Global variables | |
| let elements = []; | |
| let selectedElement = null; | |
| let elementIdCounter = 0; | |
| let currentTheme = 'default'; | |
| let currentBackground = 'color'; | |
| let zoomLevel = 1; | |
| let history = []; | |
| let historyIndex = -1; | |
| // Initialize the application | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Set up dark mode toggle | |
| const darkModeToggle = document.getElementById('darkModeToggle'); | |
| const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | |
| if (prefersDark) { | |
| document.documentElement.classList.add('dark'); | |
| localStorage.setItem('darkMode', 'enabled'); | |
| } | |
| darkModeToggle.addEventListener('click', function() { | |
| document.documentElement.classList.toggle('dark'); | |
| if (document.documentElement.classList.contains('dark')) { | |
| localStorage.setItem('darkMode', 'enabled'); | |
| } else { | |
| localStorage.setItem('darkMode', 'disabled'); | |
| } | |
| }); | |
| // Set up slide size selector | |
| const slideSize = document.getElementById('slideSize'); | |
| slideSize.addEventListener('change', function() { | |
| if (this.value === 'custom') { | |
| document.getElementById('customSizeFields').classList.remove('hidden'); | |
| } else { | |
| document.getElementById('customSizeFields').classList.add('hidden'); | |
| } | |
| }); | |
| // Set up background type selector | |
| document.getElementById('backgroundColor').addEventListener('input', function() { | |
| document.getElementById('preview').style.backgroundColor = this.value; | |
| }); | |
| // Initialize with a default title | |
| addTitle(); | |
| }); | |
| // Add Title | |
| function addTitle() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'title', | |
| content: 'Your Presentation Title', | |
| align: 'center', | |
| styles: {} | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add Heading | |
| function addHeading() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'heading', | |
| content: 'Section Heading', | |
| align: 'left', | |
| styles: {} | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add Text | |
| function addText() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'text', | |
| content: 'Your paragraph text goes here. Click to edit and add your own content.', | |
| align: 'left', | |
| styles: {} | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add List | |
| function addList() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'list', | |
| content: 'First item\nSecond item\nThird item', | |
| align: 'left', | |
| styles: {} | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add Quote | |
| function addQuote() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'quote', | |
| content: 'The only way to do great work is to love what you do. - Steve Jobs', | |
| align: 'center', | |
| styles: {} | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add Divider | |
| function addDivider() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'divider', | |
| align: 'center', | |
| styles: {} | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add Image | |
| function addImage() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'image', | |
| content: 'https://via.placeholder.com/800x400?text=Click+to+upload+image', | |
| align: 'center', | |
| styles: { | |
| width: '100%', | |
| maxWidth: '800px' | |
| } | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Add Code | |
| function addCode() { | |
| const element = { | |
| id: elementIdCounter++, | |
| type: 'code', | |
| content: '// Your code here\nfunction helloWorld() {\n console.log("Hello, world!");\n}', | |
| align: 'left', | |
| styles: {}, | |
| language: 'javascript' | |
| }; | |
| elements.push(element); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Clear All | |
| function clearAll() { | |
| if (confirm('Are you sure you want to clear all elements? This cannot be undone.')) { | |
| elements = []; | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| } | |
| // Set Theme | |
| function setTheme(theme) { | |
| currentTheme = theme; | |
| const preview = document.getElementById('preview'); | |
| // Remove all theme classes | |
| preview.classList.remove('default', 'dark', 'blue', 'gradient', 'modern', 'warm'); | |
| // Add the selected theme class | |
| if (theme !== 'default') { | |
| preview.classList.add(theme); | |
| } | |
| // Update background based on theme | |
| switch(theme) { | |
| case 'dark': | |
| preview.style.backgroundColor = '#1a1a1a'; | |
| break; | |
| case 'blue': | |
| preview.style.backgroundColor = '#e0f2fe'; | |
| break; | |
| case 'gradient': | |
| preview.style.background = 'linear-gradient(135deg, #4f46e5, #7c3aed)'; | |
| break; | |
| case 'modern': | |
| preview.style.backgroundColor = '#f5f5f5'; | |
| break; | |
| case 'warm': | |
| preview.style.backgroundColor = '#fef3c7'; | |
| break; | |
| default: | |
| preview.style.backgroundColor = '#ffffff'; | |
| } | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Set Background | |
| function setBackground(type) { | |
| currentBackground = type; | |
| const bgColorPicker = document.getElementById('bgColorPicker'); | |
| const bgGradientPicker = document.getElementById('bgGradientPicker'); | |
| if (type === 'color') { | |
| bgColorPicker.classList.remove('hidden'); | |
| bgGradientPicker.classList.add('hidden'); | |
| } else if (type === 'gradient') { | |
| bgColorPicker.classList.add('hidden'); | |
| bgGradientPicker.classList.remove('hidden'); | |
| } else { | |
| bgColorPicker.classList.add('hidden'); | |
| bgGradientPicker.classList.add('hidden'); | |
| // Handle image background | |
| } | |
| } | |
| // Apply Gradient | |
| function applyGradient() { | |
| const gradientType = document.getElementById('gradientType').value; | |
| const color1 = document.getElementById('gradientColor1').value; | |
| const color2 = document.getElementById('gradientColor2').value; | |
| if (gradientType === 'linear') { | |
| document.getElementById('preview').style.background = `linear-gradient(135deg, ${color1}, ${color2})`; | |
| } else { | |
| document.getElementById('preview').style.background = `radial-gradient(circle, ${color1}, ${color2})`; | |
| } | |
| saveHistory(); | |
| } | |
| // Render Preview | |
| function renderPreview() { | |
| const preview = document.getElementById('preview'); | |
| if (elements.length === 0) { | |
| preview.innerHTML = '<p class="text-center text-gray-400 dark:text-gray-500 py-20">Click elements on the left to add content to your slide</p>'; | |
| return; | |
| } | |
| preview.innerHTML = ''; | |
| elements.forEach(element => { | |
| const div = document.createElement('div'); | |
| div.className = `slide-element bg-white dark:bg-gray-800 rounded-lg p-4 mb-4 shadow-sm relative ${element.id === (selectedElement?.id) ? 'selected' : ''}`; | |
| div.onclick = (e) => { | |
| if (!e.target.closest('.element-controls button')) { | |
| selectElement(element.id); | |
| } | |
| }; | |
| // Add controls | |
| const controls = document.createElement('div'); | |
| controls.className = 'element-controls absolute top-2 right-2 flex space-x-1'; | |
| controls.innerHTML = ` | |
| <button class="bg-gray-200 hover:bg-gray-300 dark:bg-gray-600 dark:hover:bg-gray-500 text-gray-800 dark:text-gray-200 p-1 rounded" onclick="event.stopPropagation(); moveUp(${element.id})" title="Move up"> | |
| <i class="fas fa-arrow-up text-xs"></i> | |
| </button> | |
| <button class="bg-gray-200 hover:bg-gray-300 dark:bg-gray-600 dark:hover:bg-gray-500 text-gray-800 dark:text-gray-200 p-1 rounded" onclick="event.stopPropagation(); moveDown(${element.id})" title="Move down"> | |
| <i class="fas fa-arrow-down text-xs"></i> | |
| </button> | |
| <button class="bg-gray-200 hover:bg-gray-300 dark:bg-gray-600 dark:hover:bg-gray-500 text-gray-800 dark:text-gray-200 p-1 rounded" onclick="event.stopPropagation(); deleteElement(${element.id})" title="Delete"> | |
| <i class="fas fa-trash text-xs"></i> | |
| </button> | |
| `; | |
| div.appendChild(controls); | |
| // Add content wrapper with alignment | |
| const contentWrapper = document.createElement('div'); | |
| contentWrapper.className = `text-${element.align}`; | |
| switch(element.type) { | |
| case 'title': | |
| contentWrapper.innerHTML = `<h1 class="element-title text-4xl md:text-5xl font-bold mb-4">${element.content}</h1>`; | |
| break; | |
| case 'heading': | |
| contentWrapper.innerHTML = `<h2 class="element-heading text-2xl md:text-3xl font-semibold mb-3 text-gray-800 dark:text-gray-200">${element.content}</h2>`; | |
| break; | |
| case 'text': | |
| contentWrapper.innerHTML = `<p class="element-text text-base md:text-lg text-gray-700 dark:text-gray-300 mb-2">${element.content.replace(/\n/g, '<br>')}</p>`; | |
| break; | |
| case 'list': | |
| const items = element.content.split('\n').filter(item => item.trim() !== '').map(item => `<li class="text-base md:text-lg text-gray-700 dark:text-gray-300 mb-1">${item}</li>`).join(''); | |
| contentWrapper.innerHTML = `<ul class="element-list space-y-1">${items}</ul>`; | |
| break; | |
| case 'quote': | |
| contentWrapper.innerHTML = `<blockquote class="element-quote text-xl md:text-2xl text-gray-700 dark:text-gray-300 my-4 px-6 py-4 rounded-lg bg-gray-50 dark:bg-gray-700">${element.content}</blockquote>`; | |
| break; | |
| case 'divider': | |
| contentWrapper.innerHTML = `<div class="element-divider my-6 w-full"></div>`; | |
| break; | |
| case 'image': | |
| contentWrapper.innerHTML = ` | |
| <div class="flex justify-${element.align}"> | |
| <div class="element-image-placeholder rounded-lg overflow-hidden" style="width: ${element.styles.width || '100%'}; max-width: ${element.styles.maxWidth || '800px'};"> | |
| <img src="${element.content}" alt="Slide image" class="w-full h-auto"> | |
| </div> | |
| </div> | |
| `; | |
| break; | |
| case 'code': | |
| contentWrapper.innerHTML = ` | |
| <div class="flex justify-${element.align}"> | |
| <pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto text-sm md:text-base" style="width: ${element.styles.width || '100%'};"> | |
| <code>${element.content}</code> | |
| </pre> | |
| </div> | |
| `; | |
| break; | |
| } | |
| // Apply custom styles | |
| for (const [property, value] of Object.entries(element.styles)) { | |
| if (property === 'fontWeight' && value === 'bold') { | |
| contentWrapper.querySelector('h1, h2, p, li, blockquote, pre')?.classList.add('font-bold'); | |
| } else if (property === 'fontStyle' && value === 'italic') { | |
| contentWrapper.querySelector('h1, h2, p, li, blockquote, pre')?.classList.add('italic'); | |
| } else if (property === 'textDecoration' && value === 'underline') { | |
| contentWrapper.querySelector('h1, h2, p, li, blockquote, pre')?.classList.add('underline'); | |
| } else { | |
| contentWrapper.querySelector('h1, h2, p, ul, li, blockquote, div, pre')?.style.setProperty(property, value); | |
| } | |
| } | |
| div.appendChild(contentWrapper); | |
| preview.appendChild(div); | |
| }); | |
| } | |
| // Select Element | |
| function selectElement(id) { | |
| selectedElement = elements.find(el => el.id === id); | |
| // Remove previous selection | |
| document.querySelectorAll('.slide-element').forEach(el => { | |
| el.classList.remove('selected'); | |
| }); | |
| // Add selection to clicked element | |
| event.currentTarget.classList.add('selected'); | |
| // Show edit panel for editable types | |
| if (selectedElement.type !== 'divider') { | |
| document.getElementById('editPanel').classList.remove('hidden'); | |
| document.getElementById('editInput').value = selectedElement.content; | |
| } else { | |
| document.getElementById('editPanel').classList.add('hidden'); | |
| } | |
| } | |
| // Close Edit | |
| function closeEdit() { | |
| document.getElementById('editPanel').classList.add('hidden'); | |
| document.querySelectorAll('.slide-element').forEach(el => { | |
| el.classList.remove('selected'); | |
| }); | |
| selectedElement = null; | |
| } | |
| // Save Edit | |
| function saveEdit() { | |
| if (selectedElement) { | |
| selectedElement.content = document.getElementById('editInput').value; | |
| saveHistory(); | |
| renderPreview(); | |
| closeEdit(); | |
| } | |
| } | |
| // Set Alignment | |
| function setAlign(alignment) { | |
| if (selectedElement) { | |
| selectedElement.align = alignment; | |
| saveHistory(); | |
| renderPreview(); | |
| selectElement(selectedElement.id); | |
| } | |
| } | |
| // Toggle Text Style | |
| function toggleTextStyle(style) { | |
| if (selectedElement) { | |
| switch(style) { | |
| case 'bold': | |
| if (selectedElement.styles.fontWeight === 'bold') { | |
| delete selectedElement.styles.fontWeight; | |
| } else { | |
| selectedElement.styles.fontWeight = 'bold'; | |
| } | |
| break; | |
| case 'italic': | |
| if (selectedElement.styles.fontStyle === 'italic') { | |
| delete selectedElement.styles.fontStyle; | |
| } else { | |
| selectedElement.styles.fontStyle = 'italic'; | |
| } | |
| break; | |
| case 'underline': | |
| if (selectedElement.styles.textDecoration === 'underline') { | |
| delete selectedElement.styles.textDecoration; | |
| } else { | |
| selectedElement.styles.textDecoration = 'underline'; | |
| } | |
| break; | |
| } | |
| saveHistory(); | |
| renderPreview(); | |
| selectElement(selectedElement.id); | |
| } | |
| } | |
| // Delete Element | |
| function deleteElement(id) { | |
| elements = elements.filter(el => el.id !== id); | |
| saveHistory(); | |
| renderPreview(); | |
| } | |
| // Move Up | |
| function moveUp(id) { | |
| const index = elements.findIndex(el => el.id === id); | |
| if (index > 0) { | |
| [elements[index], elements[index - 1]] = [elements[index - 1], elements[index]]; | |
| saveHistory(); | |
| renderPreview(); | |
| selectElement(id); | |
| } | |
| } | |
| // Move Down | |
| function moveDown(id) { | |
| const index = elements.findIndex(el => el.id === id); | |
| if (index < elements.length - 1) { | |
| [elements[index], elements[index + 1]] = [elements[index + 1], elements[index]]; | |
| saveHistory(); | |
| renderPreview(); | |
| selectElement(id); | |
| } | |
| } | |
| // Zoom In | |
| function zoomIn() { | |
| if (zoomLevel < 1.5) { | |
| zoomLevel += 0.1; | |
| document.getElementById('preview').style.transform = `scale(${zoomLevel})`; | |
| document.querySelector('#preview').parentElement.style.overflow = 'auto'; | |
| updateZoomDisplay(); | |
| } | |
| } | |
| // Zoom Out | |
| function zoomOut() { | |
| if (zoomLevel > 0.7) { | |
| zoomLevel -= 0.1; | |
| document.getElementById('preview').style.transform = `scale(${zoomLevel})`; | |
| if (zoomLevel === 1) { | |
| document.querySelector('#preview').parentElement.style.overflow = 'hidden'; | |
| } | |
| updateZoomDisplay(); | |
| } | |
| } | |
| // Update Zoom Display | |
| function updateZoomDisplay() { | |
| document.querySelector('#preview').parentElement.querySelector('span').textContent = `${Math.round(zoomLevel * 100)}%`; | |
| } | |
| // Show Export | |
| function showExport() { | |
| const html = generateHTML(); | |
| document.getElementById('exportCode').value = html; | |
| document.getElementById('exportModal').classList.remove('hidden'); | |
| showExportTab('html'); | |
| } | |
| // Show Export PPT | |
| function showExportPPT() { | |
| const html = generateHTML(); | |
| document.getElementById('exportCode').value = html; | |
| document.getElementById('exportModal').classList.remove('hidden'); | |
| showExportTab('ppt'); | |
| } | |
| // Close Export | |
| function closeExport() { | |
| document.getElementById('exportModal').classList.add('hidden'); | |
| } | |
| // Show Export Tab | |
| function showExportTab(tabName) { | |
| document.querySelectorAll('.export-tab').forEach(tab => { | |
| tab.classList.add('hidden'); | |
| }); | |
| document.getElementById(`${tabName}ExportTab`).classList.remove('hidden'); | |
| document.querySelectorAll('.tabs button').forEach(button => { | |
| button.classList.remove('active'); | |
| }); | |
| event.currentTarget.classList.add('active'); | |
| } | |
| // Generate HTML | |
| function generateHTML() { | |
| let content = ''; | |
| elements.forEach(element => { | |
| const alignStyle = element.align !== 'left' ? ` style="text-align: ${element.align};"` : ''; | |
| switch(element.type) { | |
| case 'title': | |
| content += `<h1${alignStyle} class="text-5xl font-bold mb-8" style="color: ${currentTheme === 'dark' ? 'white' : '#1e293b'}; background: linear-gradient(to right, ${currentTheme === 'dark' ? '#38bdf8, #7dd3fc' : '#0ea5e9, #38bdf8'}); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">${element.content}</h1>\n`; | |
| break; | |
| case 'heading': | |
| content += `<h2${alignStyle} class="text-3xl font-semibold mb-6" style="color: ${currentTheme === 'dark' ? '#f1f5f9' : '#1e293b'};">${element.content}</h2>\n`; | |
| break; | |
| case 'text': | |
| content += `<p${alignStyle} class="text-lg mb-4" style="color: ${currentTheme === 'dark' ? '#cbd5e1' : '#475569'};">${element.content.replace(/\n/g, '<br>')}</p>\n`; | |
| break; | |
| case 'list': | |
| const items = element.content.split('\n').filter(item => item.trim() !== '').map(item => `<li class="mb-2" style="color: ${currentTheme === 'dark' ? '#cbd5e1' : '#475569'};">${item}</li>`).join('\n'); | |
| content += `<ul${alignStyle} class="list-disc pl-6 mb-6">\n${items}\n</ul>\n`; | |
| break; | |
| case 'quote': | |
| content += `<blockquote${alignStyle} class="text-xl italic px-8 py-4 my-6 border-l-4" style="border-color: ${currentTheme === 'dark' ? '#7dd3fc' : '#0ea5e9'}; color: ${currentTheme === 'dark' ? '#e2e8f0' : '#334155'}; background-color: ${currentTheme === 'dark' ? 'rgba(30, 41, 59, 0.5)' : 'rgba(226, 232, 240, 0.5)'};">${element.content}</blockquote>\n`; | |
| break; | |
| case 'divider': | |
| content += `<div${alignStyle} class="my-8"><hr style="border: none; height: 2px; background: linear-gradient(to right, transparent, ${currentTheme === 'dark' ? '#7dd3fc' : '#0ea5e9'}, transparent);"></div>\n`; | |
| break; | |
| case 'image': | |
| content += `<div${alignStyle}><img src="${element.content}" alt="Slide image" style="max-width: 100%; height: auto; border-radius: 0.5rem;"></div>\n`; | |
| break; | |
| case 'code': | |
| content += `<div${alignStyle}><pre class="bg-gray-800 text-gray-100 p-4 rounded-lg overflow-x-auto"><code>${element.content}</code></pre></div>\n`; | |
| break; | |
| } | |
| }); | |
| const bgColor = currentTheme === 'dark' ? '#1a1a1a' : | |
| currentTheme === 'blue' ? '#e0f2fe' : | |
| currentTheme === 'gradient' ? 'linear-gradient(135deg, #4f46e5, #7c3aed)' : | |
| currentTheme === 'modern' ? '#f5f5f5' : | |
| currentTheme === 'warm' ? '#fef3c7' : '#ffffff'; | |
| const textColor = currentTheme === 'dark' ? 'white' : '#1e293b'; | |
| return `<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>${document.getElementById('slideTitle').value || 'My Presentation Slide'}</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <style> | |
| body { | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; | |
| background: ${bgColor}; | |
| color: ${textColor}; | |
| padding: 2rem; | |
| min-height: 100vh; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| .slide { | |
| background: ${currentTheme === 'dark' ? '#0f172a' : 'white'}; | |
| padding: 4rem; | |
| border-radius: 1rem; | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |
| max-width: 1200px; | |
| width: 100%; | |
| min-height: 600px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="slide"> | |
| ${content} | |
| </div> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=resumesearch/slide-builder" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |