dpage
This commit is contained in:
@@ -23,6 +23,11 @@ import ZoomControls from "./ZoomControls";
|
||||
import EditorCanvasToolbar from "./EditorCanvasToolbar";
|
||||
import { createScopedId } from "../store/editorStore.helpers";
|
||||
import { getKonvaGradientProps } from "../utils/gradient";
|
||||
import { STICKER_DRAG_MIME } from "../types/IconTypes";
|
||||
import {
|
||||
createStickerObject,
|
||||
scaleStickerDimensions,
|
||||
} from "../utils/stickerUtils";
|
||||
|
||||
type EditorCanvasProps = {
|
||||
catalogSize?: string;
|
||||
@@ -50,6 +55,9 @@ const EditorCanvas = ({ catalogSize }: EditorCanvasProps) => {
|
||||
setLayerRef,
|
||||
setGuides,
|
||||
zoom,
|
||||
addObject,
|
||||
setSelectedObjectId,
|
||||
setTool,
|
||||
} = useEditorStore();
|
||||
const isSmartGuideEnabled = documentSettings.smartGuide;
|
||||
const currentPage = pages.find((page) => page.id === currentPageId);
|
||||
@@ -360,6 +368,39 @@ const EditorCanvas = ({ catalogSize }: EditorCanvasProps) => {
|
||||
|
||||
const scaledW = stageSize.width * finalScale;
|
||||
const scaledH = stageSize.height * finalScale;
|
||||
|
||||
const handleStickerDragOver = (e: React.DragEvent) => {
|
||||
if (!e.dataTransfer.types.includes(STICKER_DRAG_MIME)) return;
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = "copy";
|
||||
};
|
||||
|
||||
const placeStickerAt = (imageUrl: string, stageX: number, stageY: number, width: number, height: number) => {
|
||||
const sticker = createStickerObject(imageUrl, stageX, stageY, width, height);
|
||||
addObject(sticker);
|
||||
setSelectedObjectId(sticker.id);
|
||||
setTool("select");
|
||||
};
|
||||
|
||||
const handleStickerDrop = (e: React.DragEvent) => {
|
||||
const imageUrl = e.dataTransfer.getData(STICKER_DRAG_MIME);
|
||||
if (!imageUrl || !stageWrapRef.current) return;
|
||||
e.preventDefault();
|
||||
|
||||
const rect = stageWrapRef.current.getBoundingClientRect();
|
||||
const stageX = (e.clientX - rect.left) / finalScale;
|
||||
const stageY = (e.clientY - rect.top) / finalScale;
|
||||
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
const { width, height } = scaleStickerDimensions(img.naturalWidth, img.naturalHeight);
|
||||
placeStickerAt(imageUrl, stageX, stageY, width, height);
|
||||
};
|
||||
img.onerror = () => {
|
||||
placeStickerAt(imageUrl, stageX, stageY, 100, 100);
|
||||
};
|
||||
img.src = imageUrl;
|
||||
};
|
||||
const backgroundGradientProps = getKonvaGradientProps(
|
||||
currentPage?.backgroundType === "gradient" ? "gradient" : "solid",
|
||||
bgGradient,
|
||||
@@ -410,7 +451,12 @@ const EditorCanvas = ({ catalogSize }: EditorCanvasProps) => {
|
||||
title="Drag to create horizontal guide"
|
||||
/>
|
||||
<div className="absolute -top-6 -left-6 w-6 h-6 bg-slate-200 border border-slate-300" />
|
||||
<div ref={stageWrapRef} className="shadow-lg">
|
||||
<div
|
||||
ref={stageWrapRef}
|
||||
className="shadow-lg"
|
||||
onDragOver={handleStickerDragOver}
|
||||
onDrop={handleStickerDrop}
|
||||
>
|
||||
<Stage
|
||||
ref={stageRef}
|
||||
width={stageSize.width * finalScale}
|
||||
|
||||
@@ -218,6 +218,9 @@ const ObjectRenderer = ({
|
||||
case "document":
|
||||
shapeElement = <ImageObject key={obj.id} {...commonProps} />;
|
||||
break;
|
||||
case "sticker":
|
||||
shapeElement = <ImageObject key={obj.id} {...commonProps} />;
|
||||
break;
|
||||
case "grid":
|
||||
shapeElement = (
|
||||
<Table
|
||||
|
||||
@@ -1,9 +1,59 @@
|
||||
const StickerInstruction = () => (
|
||||
<div className="text-sm text-gray-600">
|
||||
<p>برای افزودن استیکر، روی کانوس کلیک کنید</p>
|
||||
import { useMemo } from "react";
|
||||
import { useGetIconGroups } from "@/pages/editor/hooks/useIconData";
|
||||
import { STICKER_DRAG_MIME } from "@/pages/editor/types/IconTypes";
|
||||
|
||||
const StickerInstruction = () => {
|
||||
const { data, isLoading, isError } = useGetIconGroups();
|
||||
|
||||
const stickers = useMemo(() => {
|
||||
const groups = data?.data ?? [];
|
||||
return groups.flatMap((group) => group.icons);
|
||||
}, [data]);
|
||||
|
||||
const handleDragStart = (e: React.DragEvent<HTMLImageElement>, url: string) => {
|
||||
e.dataTransfer.setData(STICKER_DRAG_MIME, url);
|
||||
e.dataTransfer.effectAllowed = "copy";
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="text-base font-bold">استیکر</div>
|
||||
<p className="text-sm text-gray-600">
|
||||
استیکر را بکشید و روی صفحه رها کنید
|
||||
</p>
|
||||
|
||||
{isLoading && (
|
||||
<p className="text-sm text-gray-500">در حال بارگذاری استیکرها...</p>
|
||||
)}
|
||||
|
||||
{isError && (
|
||||
<p className="text-sm text-red-500">خطا در بارگذاری استیکرها</p>
|
||||
)}
|
||||
|
||||
{!isLoading && !isError && stickers.length === 0 && (
|
||||
<p className="text-sm text-gray-500">استیکری یافت نشد</p>
|
||||
)}
|
||||
|
||||
{stickers.length > 0 && (
|
||||
<div className="grid grid-cols-3 gap-2 max-h-[320px] overflow-y-auto">
|
||||
{stickers.map((icon) => (
|
||||
<div
|
||||
key={icon.id}
|
||||
className="flex aspect-square items-center justify-center rounded-lg border border-gray-200 bg-gray-50 p-1 hover:border-blue-300 hover:bg-blue-50 transition-colors"
|
||||
>
|
||||
<img
|
||||
src={icon.url}
|
||||
alt=""
|
||||
draggable
|
||||
onDragStart={(e) => handleDragStart(e, icon.url)}
|
||||
className="max-h-full max-w-full object-contain cursor-grab active:cursor-grabbing"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default StickerInstruction;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user