feat(phase-6): implement comprehensive file operations system
This commit completes Phase 6 of the paint-ui implementation, adding full file import/export capabilities with drag-drop and clipboard support. **New Files:** - lib/file-utils.ts: Core file operations (open, save, export, project format) - hooks/use-file-operations.ts: React hook for file operations - hooks/use-drag-drop.ts: Drag & drop state management - hooks/use-clipboard.ts: Clipboard paste event handling - components/editor/file-menu.tsx: File menu dropdown component - components/modals/export-dialog.tsx: Export dialog with format/quality options - components/modals/new-image-dialog.tsx: New image dialog with presets - components/modals/index.ts: Modals barrel export **Updated Files:** - components/editor/editor-layout.tsx: Integrated FileMenu, drag-drop overlay, clipboard paste - components/editor/index.ts: Added file-menu export **Features:** - ✨ Create new images with dimension presets (Full HD, HD, 800x600, custom) - ✨ Open image files (PNG, JPG, WEBP) as new layers - ✨ Save/load .paint project files (JSON with base64 layer data) - ✨ Export as PNG/JPEG/WEBP with quality control - ✨ Drag & drop file upload with visual overlay - ✨ Clipboard paste support (Ctrl+V) - ✨ File type validation and error handling - ✨ DataTransfer API integration for unified file handling **Project File Format (.paint):** - JSON structure with version, dimensions, layer metadata - Base64-encoded PNG data for each layer - Preserves layer properties (opacity, blend mode, order, visibility) Build verified: ✓ Compiled successfully in 1233ms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
35
hooks/use-drag-drop.ts
Normal file
35
hooks/use-drag-drop.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export function useDragDrop(onDrop: (dataTransfer: DataTransfer) => void) {
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
||||
const handleDragOver = useCallback((e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(true);
|
||||
}, []);
|
||||
|
||||
const handleDragLeave = useCallback((e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(false);
|
||||
}, []);
|
||||
|
||||
const handleDrop = useCallback(
|
||||
(e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setIsDragging(false);
|
||||
|
||||
onDrop(e.dataTransfer);
|
||||
},
|
||||
[onDrop]
|
||||
);
|
||||
|
||||
return {
|
||||
isDragging,
|
||||
handleDragOver,
|
||||
handleDragLeave,
|
||||
handleDrop,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user