can shape edit + when add shape is default selected
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user