From c51931af9c475cd00ecf38296be9410d98c7d07b Mon Sep 17 00:00:00 2001 From: Michael Mainguy Date: Thu, 21 Aug 2025 09:45:24 -0500 Subject: [PATCH] Add image upload functionality for slide editing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create ImageUploadField component with file upload and URL input - Support base64 encoding for local IndexedDB storage - Add image preview, replacement, and removal functionality - Update SlideEditor to use ImageUploadField for image slots - Include file validation (5MB limit, image types only) - Add responsive design and error handling - Integrate with existing theme system and slot detection 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- USERFLOWS.md | 7 +- public/themes-manifest.json | 2 +- .../themes/default/layouts/image-slide.html | 2 +- public/themes/default/style.css | 4 +- src/components/presentations/SlideEditor.css | 11 + src/components/presentations/SlideEditor.tsx | 15 +- src/components/ui/ImageUploadField.css | 258 ++++++++++++++++++ src/components/ui/ImageUploadField.tsx | 173 ++++++++++++ 8 files changed, 463 insertions(+), 9 deletions(-) create mode 100644 src/components/ui/ImageUploadField.css create mode 100644 src/components/ui/ImageUploadField.tsx diff --git a/USERFLOWS.md b/USERFLOWS.md index 3ffaa2c..c225021 100644 --- a/USERFLOWS.md +++ b/USERFLOWS.md @@ -45,6 +45,7 @@ - [x] User can edit presentation notes - [x] Changes auto-save to presentation - [ ] User can edit slide content without preview if desired by clicking inside content slot areas +- [ ] When template has an image slot, slide editor allows user to upload an image (that will be stored based64 encoded in indexdb) ### Remove Slide - [x] User can delete slides from presentation @@ -60,8 +61,8 @@ - [ ] Slide order automatically saves when changed ## Flow #3 - Present to oudience -- [ ] User can start presentation mode from presentation editor -- [ ] User can navigate slides in presentation mode -- [ ] User can exit presentation mode +- [x] User can start presentation mode from presentation editor +- [x] User can navigate slides in presentation mode +- [x] User can exit presentation mode - [ ] User can see slide notes in presenter view - [ ] User can control slide transitions and animations \ No newline at end of file diff --git a/public/themes-manifest.json b/public/themes-manifest.json index 4052630..0a6e107 100644 --- a/public/themes-manifest.json +++ b/public/themes-manifest.json @@ -12,5 +12,5 @@ "hasMasterSlide": true } }, - "generated": "2025-08-21T14:20:36.144Z" + "generated": "2025-08-21T14:43:50.916Z" } \ No newline at end of file diff --git a/public/themes/default/layouts/image-slide.html b/public/themes/default/layouts/image-slide.html index 466f44e..859b9c8 100644 --- a/public/themes/default/layouts/image-slide.html +++ b/public/themes/default/layouts/image-slide.html @@ -4,7 +4,7 @@
{{#image}} - {{imageAlt}} + {{imageAlt}} {{/image}}
diff --git a/public/themes/default/style.css b/public/themes/default/style.css index 414e1c4..c2311a8 100644 --- a/public/themes/default/style.css +++ b/public/themes/default/style.css @@ -69,7 +69,9 @@ /* Ensure slot content inherits proper centering */ text-align: inherit; } - +#main-image { + scale: .7; +} .slot:hover, .slot.editing { border-color: var(--theme-accent); diff --git a/src/components/presentations/SlideEditor.css b/src/components/presentations/SlideEditor.css index 4e1d88b..3c5309a 100644 --- a/src/components/presentations/SlideEditor.css +++ b/src/components/presentations/SlideEditor.css @@ -726,4 +726,15 @@ .preview-container { min-height: 200px; } +} + +/* Image slot field integration */ +.content-field .image-slot-field { + margin-top: 0.5rem; + border: 1px solid #e2e8f0; + background: white; +} + +.content-field .image-slot-field:focus-within { + border-color: #3b82f6; } \ No newline at end of file diff --git a/src/components/presentations/SlideEditor.tsx b/src/components/presentations/SlideEditor.tsx index 4c46d32..cc99992 100644 --- a/src/components/presentations/SlideEditor.tsx +++ b/src/components/presentations/SlideEditor.tsx @@ -8,6 +8,7 @@ import { renderTemplateWithSampleData } from '../../utils/templateRenderer.ts'; import { sanitizeSlideTemplate } from '../../utils/htmlSanitizer.ts'; import { loggers } from '../../utils/logger.ts'; import { SlidePreviewModal } from './SlidePreviewModal.tsx'; +import { ImageUploadField } from '../ui/ImageUploadField.tsx'; import './SlideEditor.css'; export const SlideEditor: React.FC = () => { @@ -328,7 +329,15 @@ export const SlideEditor: React.FC = () => { {slot.required && *} - {slot.type === 'text' && slot.id.includes('content') ? ( + {slot.type === 'image' ? ( + updateSlotContent(slot.id, value)} + placeholder={slot.placeholder || `Upload image or enter URL for ${slot.id}`} + className="image-slot-field" + /> + ) : slot.type === 'text' && slot.id.includes('content') ? (