Compare commits

...
3 changed files with 26 additions and 23 deletions
@@ -185,13 +185,7 @@ export const PaintSurface = ({
isWithinLeftPanel(stagePoint)
) {
const lineId = `line-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
let opacity;
if (activeTool === "draw") {
opacity = store.brushOpacity
} else {
opacity = 1
}
let opacity = activeTool === "draw" ? store.brushOpacity : 1;
const newLineNode: LineNode = {
id: lineId,
@@ -200,10 +194,10 @@ export const PaintSurface = ({
stroke: activeTool === "draw" ? brushColor : fillColor || "#ffffff",
strokeWidth: brushSize / stage.scaleX(),
draggable: true,
opacity: opacity // Add opacity to the line node
opacity: opacity
};
store.selectNode(null);
store.addLineNode(newLineNode);
store.addLineNode(newLineNode, false); // Don't save state when starting line
setCurrentLineId(lineId);
setIsDrawing(true);
setLastPoint(stagePoint);
@@ -280,7 +274,6 @@ export const PaintSurface = ({
y: (point.y - stage.y()) / stage.scaleY(),
};
// Only add point if it's within the left panel bounds
if (isWithinLeftPanel(stagePoint)) {
const currentLine = store.lineNodes.find(
(line) => line.id === currentLineId,
@@ -291,7 +284,7 @@ export const PaintSurface = ({
stagePoint.x,
stagePoint.y,
];
store.updateLineNode(currentLineId, { points: updatedPoints });
store.updateLineNode(currentLineId, { points: updatedPoints }, false); // Don't save state while drawing
}
setLastPoint(stagePoint);
} else {
@@ -339,6 +332,10 @@ export const PaintSurface = ({
};
const handleStageMouseUp = () => {
if (isDrawing) {
store.saveState(); // Save state only when the stroke is complete
}
if (isSelecting && selectionRect) {
// Calculate the bounds of the selection rectangle
const left = Math.min(selectionRect.startX, selectionRect.endX);
@@ -1,4 +1,5 @@
import React, { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
export interface MenuPosition {
x: number;
@@ -33,14 +34,14 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({ items, onAction, onClo
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [onClose]);
return (
return createPortal(
<div
ref={menuRef}
style={{
left: `${position.x}px`,
top: `${position.y}px`,
}}
className="fixed z-50 min-w-[220px] bg-[#1A1A1A] rounded-lg shadow-xl border border-[#333333] py-1 select-none"
className="fixed z-[9999999] min-w-[220px] bg-[#1A1A1A] rounded-lg shadow-xl border border-[#333333] py-1 select-none"
>
{items.map((item, index) => (
<React.Fragment key={index}>
@@ -59,7 +60,8 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({ items, onAction, onClo
{item.divider && <div className="h-[1px] bg-[#333333] mx-2 my-1" />}
</React.Fragment>
))}
</div>
</div>,
document.body
);
};
@@ -123,7 +125,7 @@ export const ContextMenuContainer: React.FC<ContextMenuContainerProps> = ({
<div
onClick={handleClick}
onContextMenu={handleContextMenu}
className={`w-full h-full ${className}`}
className={`w-full h-full relative z-[99999] ${className}`}
>
{children}
{showMenu && (
@@ -89,9 +89,9 @@ interface SceneState {
saveState: () => void;
// Add new actions for line nodes
addLineNode: (lineNode: LineNode) => void;
addLineNode: (lineNode: LineNode, shouldSaveState: boolean) => void;
removeLineNode: (id: string, shouldSaveState?: boolean) => void;
updateLineNode: (id: string, updates: Partial<LineNode>) => void;
updateLineNode: (id: string, updates: Partial<LineNode>, shouldSaveState: boolean) => void;
moveLineNode: (id: string, dx: number, dy: number) => void;
// Add a specific method for file uploads
@@ -516,17 +516,18 @@ export const useSceneStore = create<SceneState>((set, get) => ({
},
// Add new line node actions
addLineNode: (lineNode: LineNode) => {
addLineNode: (lineNode: LineNode, shouldSaveState: boolean = true) => {
set((state) => {
const nextZ = getNextZIndex(state.nodes, state.lineNodes);
const newLineNode = {
...lineNode,
zIndex: nextZ
};
return { lineNodes: [...state.lineNodes, newLineNode] };
});
get().saveState();
if (shouldSaveState) {
get().saveState();
}
},
removeLineNode: (id: string, shouldSaveState: boolean = true) => {
@@ -547,7 +548,7 @@ export const useSceneStore = create<SceneState>((set, get) => ({
}
},
updateLineNode: (id: string, updates: Partial<LineNode>) => {
updateLineNode: (id: string, updates: Partial<LineNode>, shouldSaveState: boolean = true) => {
set((state) => {
const newLineNodes = state.lineNodes.map(node => {
if (node.id === id) {
@@ -561,7 +562,9 @@ export const useSceneStore = create<SceneState>((set, get) => ({
});
return { lineNodes: newLineNodes };
});
get().saveState();
if (shouldSaveState) {
get().saveState();
}
},
moveLineNode: (id: string, dx: number, dy: number) => {
@@ -593,7 +596,8 @@ export const useSceneStore = create<SceneState>((set, get) => ({
const img = new Image();
img.onload = () => {
const aspectRatio = img.naturalWidth / img.naturalHeight;
const finalWidth = width || Math.min(img.naturalWidth, 300);
// Increase default size to 512px width while maintaining aspect ratio
const finalWidth = width || Math.min(img.naturalWidth, 512);
const finalHeight = height || finalWidth / aspectRatio;
console.log('Image loaded with dimensions:', {
naturalWidth: img.naturalWidth,