Create all components

This commit is contained in:
hamid zarghami
2025-11-18 14:38:08 +03:30
parent 1a0c869101
commit 8070a3f837
16 changed files with 181 additions and 64 deletions
+1 -25
View File
@@ -15,30 +15,6 @@ const EditorSidebar = () => {
setTool(selectedTool); setTool(selectedTool);
}; };
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const imageUrl = event.target?.result as string;
const img = new Image();
img.onload = () => {
const newImage = {
id: `image-${Date.now()}`,
type: "image" as ToolType,
x: 100,
y: 100,
width: img.width,
height: img.height,
imageUrl,
};
useEditorStore.getState().addObject(newImage);
};
img.src = imageUrl;
};
reader.readAsDataURL(file);
};
return ( return (
<> <>
@@ -72,7 +48,7 @@ const EditorSidebar = () => {
onDelete={deleteObject} onDelete={deleteObject}
/> />
) : ( ) : (
<ToolInstructions tool={tool} onImageUpload={handleImageUpload} /> <ToolInstructions tool={tool} />
)} )}
</div> </div>
</div> </div>
@@ -8,6 +8,7 @@ import {
LinkSettings, LinkSettings,
VideoSettings, VideoSettings,
TransformSettings, TransformSettings,
GridSettings,
} from "./settings"; } from "./settings";
type ObjectSettingsProps = { type ObjectSettingsProps = {
@@ -60,6 +61,10 @@ const ObjectSettings = ({ selectedObject, onUpdate, onDelete }: ObjectSettingsPr
/> />
)} )}
{selectedObject.type === "grid" && (
<GridSettings selectedObject={selectedObject} onUpdate={onUpdate} />
)}
<TransformSettings selectedObject={selectedObject} onUpdate={onUpdate} /> <TransformSettings selectedObject={selectedObject} onUpdate={onUpdate} />
</div> </div>
); );
@@ -1,14 +1,53 @@
import type { ToolType } from "../../store/editorStore"; import { useEditorStore, type ToolType } from "../../store/editorStore";
import { ImageUpload, DocumentUpload, VideoInput, LinkInput, SimpleInstruction } from "./instructions"; import {
ImageUpload,
DocumentUpload,
VideoInput,
LinkInput,
SelectInstruction,
RectangleInstruction,
CircleInstruction,
TextInstruction,
LineInstruction,
ArrowInstruction,
StickerInstruction,
GridInstruction,
} from "./instructions";
type ToolInstructionsProps = { type ToolInstructionsProps = {
tool: ToolType; tool: ToolType;
onImageUpload: (e: React.ChangeEvent<HTMLInputElement>) => void;
}; };
const ToolInstructions = ({ tool, onImageUpload }: ToolInstructionsProps) => { const ToolInstructions = ({ tool }: ToolInstructionsProps) => {
const { addObject } = useEditorStore();
const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
const imageUrl = event.target?.result as string;
const img = new Image();
img.onload = () => {
const newImage = {
id: `image-${Date.now()}`,
type: "image" as ToolType,
x: 100,
y: 100,
width: img.width,
height: img.height,
imageUrl,
};
addObject(newImage);
};
img.src = imageUrl;
};
reader.readAsDataURL(file);
}
};
if (tool === "image") { if (tool === "image") {
return <ImageUpload onImageUpload={onImageUpload} />; return <ImageUpload onImageUpload={handleImageUpload} />;
} }
if (tool === "document") { if (tool === "document") {
@@ -23,7 +62,18 @@ const ToolInstructions = ({ tool, onImageUpload }: ToolInstructionsProps) => {
return <LinkInput />; return <LinkInput />;
} }
return <SimpleInstruction tool={tool} />; const simpleInstructions: Partial<Record<ToolType, React.ReactElement>> = {
select: <SelectInstruction />,
rectangle: <RectangleInstruction />,
circle: <CircleInstruction />,
text: <TextInstruction />,
line: <LineInstruction />,
arrow: <ArrowInstruction />,
sticker: <StickerInstruction />,
grid: <GridInstruction />,
};
return simpleInstructions[tool] ?? null;
}; };
export default ToolInstructions; export default ToolInstructions;
@@ -0,0 +1,9 @@
const ArrowInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای رسم پیکان، روی کانوس کلیک کرده و بکشید</p>
</div>
);
export default ArrowInstruction;
@@ -0,0 +1,9 @@
const CircleInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای رسم دایره، روی کانوس کلیک کرده و بکشید</p>
</div>
);
export default CircleInstruction;
@@ -0,0 +1,9 @@
const GridInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای افزودن گرید، روی کانوس کلیک کنید</p>
</div>
);
export default GridInstruction;
@@ -0,0 +1,9 @@
const LineInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای رسم خط، روی کانوس کلیک کرده و بکشید</p>
</div>
);
export default LineInstruction;
@@ -0,0 +1,9 @@
const RectangleInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای رسم مستطیل، روی کانوس کلیک کرده و بکشید</p>
</div>
);
export default RectangleInstruction;
@@ -0,0 +1,9 @@
const SelectInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای انتخاب و جابجایی اشیاء، روی آنها کلیک کنید</p>
</div>
);
export default SelectInstruction;
@@ -1,31 +0,0 @@
import type { ToolType } from "../../../store/editorStore";
type SimpleInstructionProps = {
tool: ToolType;
};
const SimpleInstruction = ({ tool }: SimpleInstructionProps) => {
const instructions: Record<ToolType, string> = {
select: "برای انتخاب و جابجایی اشیاء، روی آن‌ها کلیک کنید",
rectangle: "برای رسم مستطیل، روی کانوس کلیک کرده و بکشید",
circle: "برای رسم دایره، روی کانوس کلیک کرده و بکشید",
text: "برای افزودن متن، روی کانوس کلیک کنید",
line: "برای رسم خط، روی کانوس کلیک کرده و بکشید",
arrow: "برای رسم پیکان، روی کانوس کلیک کرده و بکشید",
sticker: "برای افزودن استیکر، روی کانوس کلیک کنید",
grid: "برای افزودن گرید، روی کانوس کلیک کنید",
image: "",
document: "",
video: "",
link: "",
};
return (
<div className="text-sm text-gray-600">
<p>{instructions[tool]}</p>
</div>
);
};
export default SimpleInstruction;
@@ -0,0 +1,9 @@
const StickerInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای افزودن استیکر، روی کانوس کلیک کنید</p>
</div>
);
export default StickerInstruction;
@@ -0,0 +1,9 @@
const TextInstruction = () => (
<div className="text-sm text-gray-600">
<p>برای افزودن متن، روی کانوس کلیک کنید</p>
</div>
);
export default TextInstruction;
@@ -2,5 +2,12 @@ export { default as ImageUpload } from "./ImageUpload";
export { default as DocumentUpload } from "./DocumentUpload"; export { default as DocumentUpload } from "./DocumentUpload";
export { default as VideoInput } from "./VideoInput"; export { default as VideoInput } from "./VideoInput";
export { default as LinkInput } from "./LinkInput"; export { default as LinkInput } from "./LinkInput";
export { default as SimpleInstruction } from "./SimpleInstruction"; export { default as SelectInstruction } from "./SelectInstruction";
export { default as RectangleInstruction } from "./RectangleInstruction";
export { default as CircleInstruction } from "./CircleInstruction";
export { default as TextInstruction } from "./TextInstruction";
export { default as LineInstruction } from "./LineInstruction";
export { default as ArrowInstruction } from "./ArrowInstruction";
export { default as StickerInstruction } from "./StickerInstruction";
export { default as GridInstruction } from "./GridInstruction";
@@ -0,0 +1,37 @@
import type { EditorObject } from "../../../store/editorStore";
import Input from "@/components/Input";
type GridSettingsProps = {
selectedObject: EditorObject;
onUpdate: (id: string, updates: Partial<EditorObject>) => void;
};
const GridSettings = ({ selectedObject, onUpdate }: GridSettingsProps) => {
return (
<>
<Input
label="عرض"
type="number"
value={selectedObject.width || 200}
onChange={(e) =>
onUpdate(selectedObject.id, {
width: parseInt(e.target.value) || 200,
})
}
/>
<Input
label="ارتفاع"
type="number"
value={selectedObject.height || 200}
onChange={(e) =>
onUpdate(selectedObject.id, {
height: parseInt(e.target.value) || 200,
})
}
/>
</>
);
};
export default GridSettings;
@@ -5,4 +5,5 @@ export { default as SizeSettings } from "./SizeSettings";
export { default as LinkSettings } from "./LinkSettings"; export { default as LinkSettings } from "./LinkSettings";
export { default as VideoSettings } from "./VideoSettings"; export { default as VideoSettings } from "./VideoSettings";
export { default as TransformSettings } from "./TransformSettings"; export { default as TransformSettings } from "./TransformSettings";
export { default as GridSettings } from "./GridSettings";
+1 -1
View File
@@ -1,5 +1,5 @@
import Konva from "konva"; import Konva from "konva";
import { EditorObject } from "../../store/editorStore"; import type { EditorObject } from "../../store/editorStore";
export type ShapeProps = { export type ShapeProps = {
obj: EditorObject; obj: EditorObject;