can shape edit + when add shape is default selected

This commit is contained in:
hamid zarghami
2025-11-26 14:16:52 +03:30
parent 3454129dca
commit aacf209894
7 changed files with 120 additions and 29 deletions
@@ -10,7 +10,7 @@ export const useDrawingHandlers = () => {
const [tempObject, setTempObject] = useState<EditorObject | null>(null);
const transformerRef = useRef<Konva.Transformer>(null);
const { tool, addObject, updateObject, setSelectedObjectId, selectedObjectId } = useEditorStore();
const { tool, addObject, updateObject, setSelectedObjectId, selectedObjectId, setTool } = useEditorStore();
const { defaults } = useTextDefaultsStore();
useEffect(() => {
@@ -71,6 +71,7 @@ export const useDrawingHandlers = () => {
};
addObject(newText);
setSelectedObjectId(newText.id);
setTool("select");
}
};
@@ -104,8 +105,13 @@ export const useDrawingHandlers = () => {
};
const handleStageMouseUp = () => {
const lastObjectId = tempObject?.id;
setIsDrawing(false);
setTempObject(null);
if (lastObjectId) {
setSelectedObjectId(lastObjectId);
setTool("select");
}
};
return {
@@ -1,4 +1,4 @@
import { useEditorStore, type ToolType } from "../../store/editorStore";
import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore";
import {
ImageUpload,
DocumentUpload,
@@ -19,7 +19,7 @@ type ToolInstructionsProps = {
};
const ToolInstructions = ({ tool }: ToolInstructionsProps) => {
const { addObject } = useEditorStore();
const { addObject, setSelectedObjectId, setTool } = useEditorStore();
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
@@ -39,6 +39,8 @@ const ToolInstructions = ({ tool }: ToolInstructionsProps) => {
imageUrl,
};
addObject(newImage);
setSelectedObjectId(newImage.id);
setTool("select");
};
img.src = imageUrl;
};
@@ -1,5 +1,5 @@
import { DocumentUpload } from "iconsax-react";
import { useEditorStore, type ToolType } from "../../../store/editorStore";
import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore";
import Button from "@/components/Button";
const DocumentUploadComponent = () => {
@@ -25,8 +25,10 @@ const DocumentUploadComponent = () => {
height: 250,
imageUrl: fileUrl,
};
const { addObject } = useEditorStore.getState();
const { addObject, setSelectedObjectId, setTool } = useEditorStore.getState();
addObject(newDocument);
setSelectedObjectId(newDocument.id);
setTool("select");
};
reader.readAsDataURL(file);
}
@@ -1,4 +1,4 @@
import { useEditorStore, type ToolType } from "../../../store/editorStore";
import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore";
import Input from "@/components/Input";
const LinkInput = () => {
@@ -21,8 +21,10 @@ const LinkInput = () => {
fontSize: 24,
fill: "#0000ff",
};
const { addObject } = useEditorStore.getState();
const { addObject, setSelectedObjectId, setTool } = useEditorStore.getState();
addObject(newLink);
setSelectedObjectId(newLink.id);
setTool("select");
input.value = "";
}
}}
@@ -1,4 +1,4 @@
import { useEditorStore, type ToolType } from "../../../store/editorStore";
import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore";
import Input from "@/components/Input";
const VideoInput = () => {
@@ -20,8 +20,10 @@ const VideoInput = () => {
height: 300,
videoUrl: input.value,
};
const { addObject } = useEditorStore.getState();
const { addObject, setSelectedObjectId, setTool } = useEditorStore.getState();
addObject(newVideo);
setSelectedObjectId(newVideo.id);
setTool("select");
input.value = "";
}
}}
@@ -1,57 +1,130 @@
import type { EditorObject } from "../../../store/editorStore";
import { useEffect, useState } from "react";
import Button from "@/components/Button";
import Input from "@/components/Input";
import type { EditorObject } from "@/pages/editor/store/editorStore";
type ShapeSettingsProps = {
selectedObject: EditorObject;
onUpdate: (id: string, updates: Partial<EditorObject>) => void;
};
type ShapeFormState = {
width: string;
height: string;
fill: string;
stroke: string;
strokeWidth: string;
};
const ShapeSettings = ({ selectedObject, onUpdate }: ShapeSettingsProps) => {
const baseWidth = selectedObject.width ?? 100;
const baseHeight = selectedObject.height ?? 100;
const baseFill = selectedObject.fill ?? "#3b82f6";
const baseStroke = selectedObject.stroke ?? "#1e40af";
const baseStrokeWidth = selectedObject.strokeWidth ?? 2;
const [formState, setFormState] = useState<ShapeFormState>({
width: String(baseWidth),
height: String(baseHeight),
fill: baseFill,
stroke: baseStroke,
strokeWidth: String(baseStrokeWidth),
});
useEffect(() => {
setFormState({
width: String(baseWidth),
height: String(baseHeight),
fill: baseFill,
stroke: baseStroke,
strokeWidth: String(baseStrokeWidth),
});
}, [baseWidth, baseHeight, baseFill, baseStroke, baseStrokeWidth]);
const parseNumber = (value: string, fallback: number) => {
const parsed = parseInt(value, 10);
return Number.isNaN(parsed) ? fallback : parsed;
};
const handleSave = () => {
onUpdate(selectedObject.id, {
width: parseNumber(formState.width, baseWidth),
height: parseNumber(formState.height, baseHeight),
fill: formState.fill || baseFill,
stroke: formState.stroke || baseStroke,
strokeWidth: parseNumber(formState.strokeWidth, baseStrokeWidth),
});
};
const isDirty =
formState.width !== String(baseWidth) ||
formState.height !== String(baseHeight) ||
formState.fill !== baseFill ||
formState.stroke !== baseStroke ||
formState.strokeWidth !== String(baseStrokeWidth);
return (
<>
<div className="space-y-4">
<Input
label="عرض"
type="number"
value={selectedObject.width || 100}
value={formState.width}
onChange={(e) =>
onUpdate(selectedObject.id, {
width: parseInt(e.target.value) || 100,
})
setFormState((prev) => ({
...prev,
width: e.target.value,
}))
}
/>
<Input
label="ارتفاع"
type="number"
value={selectedObject.height || 100}
value={formState.height}
onChange={(e) =>
onUpdate(selectedObject.id, {
height: parseInt(e.target.value) || 100,
})
setFormState((prev) => ({
...prev,
height: e.target.value,
}))
}
/>
<Input
label="رنگ پس‌زمینه"
type="color"
value={selectedObject.fill || "#3b82f6"}
onChange={(e) => onUpdate(selectedObject.id, { fill: e.target.value })}
value={formState.fill}
onChange={(e) =>
setFormState((prev) => ({
...prev,
fill: e.target.value,
}))
}
/>
<Input
label="رنگ خط"
type="color"
value={selectedObject.stroke || "#1e40af"}
onChange={(e) => onUpdate(selectedObject.id, { stroke: e.target.value })}
value={formState.stroke}
onChange={(e) =>
setFormState((prev) => ({
...prev,
stroke: e.target.value,
}))
}
/>
<Input
label="ضخامت خط"
type="number"
value={selectedObject.strokeWidth || 2}
value={formState.strokeWidth}
onChange={(e) =>
onUpdate(selectedObject.id, {
strokeWidth: parseInt(e.target.value) || 2,
})
setFormState((prev) => ({
...prev,
strokeWidth: e.target.value,
}))
}
min={1}
/>
</>
<Button type="button" onClick={handleSave} disabled={!isDirty} className="w-full">
ذخیره تغییرات
</Button>
</div>
);
};