From 5798bcdbdf365d0d1104f50255be319c3d8c357b Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Fri, 18 Jul 2025 15:20:32 +0545 Subject: [PATCH] feat(nextjs): Icon editor & refactor image editor --- .../components/IconsEditor.tsx | 9 ++- .../components/ImageEditor.tsx | 33 ++--------- .../components/SmartEditableWrapper.tsx | 59 +------------------ servers/nextjs/app/api/upload-image/route.ts | 2 +- 4 files changed, 16 insertions(+), 87 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/components/IconsEditor.tsx b/servers/nextjs/app/(presentation-generator)/components/IconsEditor.tsx index 1fe60fb0..ca8d6e17 100644 --- a/servers/nextjs/app/(presentation-generator)/components/IconsEditor.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/IconsEditor.tsx @@ -104,6 +104,7 @@ const IconsEditor = ({ side="right" className="w-[400px]" onOpenAutoFocus={(e) => e.preventDefault()} + onClick={(e) => e.stopPropagation()} > Choose Icon @@ -112,6 +113,7 @@ const IconsEditor = ({
{ e.preventDefault(); + e.stopPropagation(); handleIconSearch(); }} > @@ -122,6 +124,7 @@ const IconsEditor = ({ placeholder="Search icons..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} + onClick={(e) => e.stopPropagation()} className="pl-10" /> @@ -129,6 +132,7 @@ const IconsEditor = ({ type="submit" variant="outline" className="w-full text-semibold text-[#51459e]" + onClick={(e) => e.stopPropagation()} > Search @@ -147,7 +151,10 @@ const IconsEditor = ({ {icons.map((iconSrc, idx) => (
handleIconChange(iconSrc)} + onClick={(e) => { + e.stopPropagation(); + handleIconChange(iconSrc); + }} className="w-12 h-12 cursor-pointer group relative rounded-lg overflow-hidden hover:bg-gray-100 p-2" > (""); const [isGenerating, setIsGenerating] = useState(false); const [error, setError] = useState(null); @@ -110,7 +97,7 @@ const ImageEditor = ({ !toolbarRef.current.contains(event.target as Node) && !popoverContentRef.current ) { - setIsToolbarOpen(false); + if (isFocusPointMode) { // saveFocusPoint(); // Save focus point before closing saveImageProperties(objectFit, focusPoint); @@ -125,16 +112,7 @@ const ImageEditor = ({ }; }, [isFocusPointMode, focusPoint]); - const handleImageClick = () => { - if (!isFocusPointMode) { - setIsToolbarOpen(true); - } - }; - const handleOpenEditor = () => { - setIsToolbarOpen(false); - setIsEditorOpen(true); - }; const handleImageChange = (newImage: string) => { setImage(newImage); @@ -145,7 +123,6 @@ const ImageEditor = ({ image: newImage, }) ); - setIsEditorOpen(false); }; const handleFocusPointClick = (e: React.MouseEvent) => { @@ -600,7 +577,7 @@ const ImageEditor = ({ className="cursor-pointer group w-full h-full" > Uploaded preview diff --git a/servers/nextjs/app/(presentation-generator)/components/SmartEditableWrapper.tsx b/servers/nextjs/app/(presentation-generator)/components/SmartEditableWrapper.tsx index 08ac5989..c4fd8d9d 100644 --- a/servers/nextjs/app/(presentation-generator)/components/SmartEditableWrapper.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/SmartEditableWrapper.tsx @@ -70,9 +70,7 @@ export const SmartEditableProvider: React.FC = ({ dataPath: path, props: { slideIndex, - elementId: `image-${path.replace(/[^\w]/g, '-')}`, initialImage: data.__image_url__, - title: imgElement.alt || 'Image', promptContent: data.__image_prompt__ || '', imageIdx: elements.filter(e => e.type === 'image').length } @@ -155,55 +153,6 @@ export const SmartEditableProvider: React.FC = ({ return getFilename(domSrc) === getFilename(dataSrc) && getFilename(domSrc) !== ''; }; - // Add event delegation for clicks - const handleClick = (event: MouseEvent) => { - const target = event.target as HTMLElement; - if (target.tagName === 'IMG') { - const imgElement = target as HTMLImageElement; - const editableElement = editableElements.find(el => el.element === imgElement); - - if (editableElement) { - event.preventDefault(); - event.stopPropagation(); - - const rect = imgElement.getBoundingClientRect(); - setActiveEditor({ - type: editableElement.type, - element: imgElement, - props: editableElement.props, - rect - }); - } - } - }; - - // Add hover effects - const handleMouseEnter = (event: MouseEvent) => { - const target = event.target as HTMLElement; - if (target.tagName === 'IMG') { - const imgElement = target as HTMLImageElement; - const isEditable = editableElements.some(el => el.element === imgElement); - - if (isEditable) { - imgElement.style.cursor = 'pointer'; - imgElement.style.filter = 'brightness(0.9)'; - imgElement.style.transition = 'filter 0.2s ease'; - } - } - }; - - const handleMouseLeave = (event: MouseEvent) => { - const target = event.target as HTMLElement; - if (target.tagName === 'IMG') { - const imgElement = target as HTMLImageElement; - const isEditable = editableElements.some(el => el.element === imgElement); - - if (isEditable) { - imgElement.style.filter = ''; - } - } - }; - // Set up event listeners after elements are found const timer = setTimeout(() => { findEditableElements(); @@ -211,11 +160,8 @@ export const SmartEditableProvider: React.FC = ({ return () => { clearTimeout(timer); - container.removeEventListener('click', handleClick); - container.removeEventListener('mouseenter', handleMouseEnter, true); - container.removeEventListener('mouseleave', handleMouseLeave, true); }; - }, [slideIndex, slideId, slideData, isEditMode, editableElements]); + }, [slideIndex, slideId, slideData, isEditMode]); // Set up event listeners when editableElements change useEffect(() => { @@ -298,7 +244,7 @@ export const SmartEditableProvider: React.FC = ({ ); }; -// Simple overlay component for editors +// overlay component for editors const EditorOverlay: React.FC<{ activeEditor: { type: 'image' | 'icon'; @@ -320,7 +266,6 @@ const EditorOverlay: React.FC<{ onClose(); } }; - document.addEventListener('keydown', handleEscape); document.addEventListener('click', handleClickOutside); diff --git a/servers/nextjs/app/api/upload-image/route.ts b/servers/nextjs/app/api/upload-image/route.ts index c354ec7c..af58449d 100644 --- a/servers/nextjs/app/api/upload-image/route.ts +++ b/servers/nextjs/app/api/upload-image/route.ts @@ -35,7 +35,7 @@ export async function POST(request: NextRequest) { // Return the relative path that can be used in the frontend return NextResponse.json({ success: true, - filePath: `/app/user_data/uploads/${filename}` + filePath: `${userDataDir}/uploads/${filename}` }); } catch (error) { console.error("Error saving image:", error);