mirror of
https://github.com/r2r90/canvas-label.git
synced 2025-12-17 05:29:27 +00:00
update zIndex changes
This commit is contained in:
@@ -1,24 +1,20 @@
|
|||||||
import { TransformableImage } from "@/components/transformable-image";
|
import { TransformableImage } from "@/components/transformable-image";
|
||||||
|
|
||||||
import type { KonvaEventObject } from "konva/lib/Node";
|
import type { KonvaEventObject } from "konva/lib/Node";
|
||||||
|
import { Layer, Rect, Stage } from "react-konva";
|
||||||
import { Layer, Stage } from "react-konva";
|
|
||||||
import TransformableText from "./transformable-text";
|
import TransformableText from "./transformable-text";
|
||||||
import { useAppDispatch, useAppSelector } from "@/hooks";
|
import { useAppDispatch, useAppSelector } from "@/hooks";
|
||||||
import { appSlice, deselectItem } from "@/store/app.slice";
|
import { appSlice, deselectItem } from "@/store/app.slice";
|
||||||
import { TextToolbar } from "./text-toolbar";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { EditableText } from "@/components/editable-resizable-text";
|
|
||||||
import { ImageToolbar } from "@/components/image-toolbar";
|
|
||||||
import { Toolbar } from "@/components/toolbar";
|
import { Toolbar } from "@/components/toolbar";
|
||||||
|
|
||||||
const Canvas = () => {
|
const Canvas = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const stage = useAppSelector((state) => state.app.stage);
|
||||||
const selectedItemId = useAppSelector((state) => state.app.selectedItemId);
|
const selectedItemId = useAppSelector((state) => state.app.selectedItemId);
|
||||||
const selectItem = (id: string) => dispatch(appSlice.actions.selectItem(id));
|
const selectItem = (id: string) => dispatch(appSlice.actions.selectItem(id));
|
||||||
const texts = useAppSelector((state) => state.app.texts);
|
const texts = useAppSelector((state) => state.app.texts);
|
||||||
const images = useAppSelector((state) => state.app.images);
|
const images = useAppSelector((state) => state.app.images);
|
||||||
|
const backgroundRects = useAppSelector((state) => state.app.backgroundRects);
|
||||||
|
|
||||||
const deselectHandler = (
|
const deselectHandler = (
|
||||||
e: KonvaEventObject<MouseEvent> | KonvaEventObject<TouchEvent>,
|
e: KonvaEventObject<MouseEvent> | KonvaEventObject<TouchEvent>,
|
||||||
@@ -32,9 +28,6 @@ const Canvas = () => {
|
|||||||
|
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const [isTransforming, setIsTransforming] = useState(false);
|
const [isTransforming, setIsTransforming] = useState(false);
|
||||||
const [text, setText] = useState("Click to resize. Double click to edit.");
|
|
||||||
const [width, setWidth] = useState(200);
|
|
||||||
const [height, setHeight] = useState(200);
|
|
||||||
const [selected, setSelected] = useState(false);
|
const [selected, setSelected] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -61,8 +54,8 @@ const Canvas = () => {
|
|||||||
|
|
||||||
<Stage
|
<Stage
|
||||||
className="m-[3rem] bg-white"
|
className="m-[3rem] bg-white"
|
||||||
width={600}
|
width={stage.width}
|
||||||
height={500}
|
height={stage.height}
|
||||||
onTouchStart={deselectHandler}
|
onTouchStart={deselectHandler}
|
||||||
onMouseDown={deselectHandler}
|
onMouseDown={deselectHandler}
|
||||||
>
|
>
|
||||||
@@ -94,23 +87,20 @@ const Canvas = () => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{/*<EditableText*/}
|
{backgroundRects.map((rect, i) => {
|
||||||
{/* x={20}*/}
|
return (
|
||||||
{/* y={40}*/}
|
<Rect
|
||||||
{/* text={text}*/}
|
key={i}
|
||||||
{/* width={width}*/}
|
width={rect.width}
|
||||||
{/* height={height}*/}
|
height={rect.width}
|
||||||
{/* onResize={(newWidth, newHeight) => {*/}
|
fill={rect.fill}
|
||||||
{/* setWidth(newWidth);*/}
|
/>
|
||||||
{/* setHeight(newHeight);*/}
|
);
|
||||||
{/* }}*/}
|
})}
|
||||||
{/* isEditing={isEditing}*/}
|
|
||||||
{/* isTransforming={isTransforming}*/}
|
|
||||||
{/* onToggleEdit={toggleEdit}*/}
|
|
||||||
{/* onToggleTransform={toggleTransforming}*/}
|
|
||||||
{/* onChange={setText}*/}
|
|
||||||
{/*/>*/}
|
|
||||||
</Layer>
|
</Layer>
|
||||||
|
{/* <Layer>
|
||||||
|
<Text zIndex={10} x={30} y={200} fontSize={48} text="Hello" />
|
||||||
|
</Layer>*/}
|
||||||
</Stage>
|
</Stage>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import { Separator } from "@/components/ui/separator";
|
|||||||
export function ImageToolbar({ selectedItemId, currentImage }) {
|
export function ImageToolbar({ selectedItemId, currentImage }) {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const flipImageVerticaly = () => {
|
const flipImageVerticaly = () => {
|
||||||
const editOffsetY = currentImage.height / 2;
|
const currentScale = currentImage.scaleY;
|
||||||
|
let editOffsetY = currentImage.height;
|
||||||
|
if (currentScale < 0) editOffsetY = 0;
|
||||||
const editScaleY = -1 * currentImage.scaleY;
|
const editScaleY = -1 * currentImage.scaleY;
|
||||||
dispatch(
|
dispatch(
|
||||||
updateImage({
|
updateImage({
|
||||||
@@ -21,7 +23,9 @@ export function ImageToolbar({ selectedItemId, currentImage }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const flipImageHorizontaly = () => {
|
const flipImageHorizontaly = () => {
|
||||||
const editOffsetX = currentImage.width / 2;
|
const currentScale = currentImage.scaleX;
|
||||||
|
let editOffsetX = currentImage.width;
|
||||||
|
if (currentScale < 0) editOffsetX = 0;
|
||||||
const editScaleX = -1 * currentImage.scaleX;
|
const editScaleX = -1 * currentImage.scaleX;
|
||||||
dispatch(
|
dispatch(
|
||||||
updateImage({
|
updateImage({
|
||||||
|
|||||||
74
src/components/layout/sidebar/background-select.tsx
Normal file
74
src/components/layout/sidebar/background-select.tsx
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "@/components/ui/popover";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { RxLayout } from "react-icons/rx";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { useAppDispatch } from "@/hooks";
|
||||||
|
import { selectBackground } from "@/store/app.slice";
|
||||||
|
|
||||||
|
export const BackgroundSelect = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleBackgroundSelect = (color: string) => {
|
||||||
|
dispatch(selectBackground(color));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSizeSelect = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Popover open={open} onOpenChange={setOpen}>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button
|
||||||
|
onClick={() => setOpen(true)}
|
||||||
|
variant="outline"
|
||||||
|
className="text-xl"
|
||||||
|
>
|
||||||
|
<RxLayout />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent side="right" className="mt-4">
|
||||||
|
<Card className="p-3">
|
||||||
|
<CardHeader className="mb-2 p-2 text-center">
|
||||||
|
<CardTitle>Fond</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<CardContent className="grid grid-cols-2 gap-2">
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-2 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
||||||
|
onClick={() => handleBackgroundSelect("red")}
|
||||||
|
>
|
||||||
|
Red
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label
|
||||||
|
htmlFor="paypal"
|
||||||
|
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
||||||
|
onClick={() => handleBackgroundSelect("blue")}
|
||||||
|
>
|
||||||
|
Blue
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label
|
||||||
|
htmlFor="apple"
|
||||||
|
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary"
|
||||||
|
onClick={() => handleBackgroundSelect("green")}
|
||||||
|
>
|
||||||
|
Green
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -6,11 +6,11 @@ import {
|
|||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { PiImageDuotone } from "react-icons/pi";
|
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { addImage } from "@/store/app.slice";
|
import { addImage } from "@/store/app.slice";
|
||||||
import { useAppDispatch } from "@/hooks";
|
import { useAppDispatch } from "@/hooks";
|
||||||
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { RxImage } from "react-icons/rx";
|
||||||
|
|
||||||
function ImageInput() {
|
function ImageInput() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -32,8 +32,8 @@ function ImageInput() {
|
|||||||
return (
|
return (
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button variant="secondary" className="text-xl">
|
<Button variant="outline" className="text-xl">
|
||||||
<PiImageDuotone />
|
<RxImage />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="right">
|
<PopoverContent side="right">
|
||||||
|
|||||||
31
src/components/layout/sidebar/layers.tsx
Normal file
31
src/components/layout/sidebar/layers.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "@/components/ui/popover";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { RxStack } from "react-icons/rx";
|
||||||
|
|
||||||
|
export const Layers = () => {
|
||||||
|
return (
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button variant="outline" className="text-xl">
|
||||||
|
<RxStack />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent side="right">
|
||||||
|
<Card className="p-2">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="text-center">Layer</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="grid gap-2">
|
||||||
|
<div className="flex h-[2rem] flex-col items-center justify-between rounded-md border-2 border-muted bg-popover"></div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import React, { ChangeEvent } from "react";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { PiFrameCornersDuotone, PiImageDuotone } from "react-icons/pi";
|
import { PiFrameCornersDuotone } from "react-icons/pi";
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { useAppDispatch } from "@/hooks";
|
import { useAppDispatch } from "@/hooks";
|
||||||
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ export function SelectTemplate() {
|
|||||||
|
|
||||||
<Card className="p-2">
|
<Card className="p-2">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-center">Choisissez un cadre</CardTitle>
|
<CardTitle className="text-center">Cadre</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
</Card>
|
</Card>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import { TextInput } from "@/components/layout/sidebar/text-input";
|
import { TextInput } from "@/components/layout/sidebar/text-input";
|
||||||
import ImageInput from "@/components/layout/sidebar/image-input";
|
import ImageInput from "@/components/layout/sidebar/image-input";
|
||||||
import { SelectTemplate } from "@/components/layout/sidebar/select-template";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { useAppDispatch } from "@/hooks";
|
|
||||||
import SizeSelect from "@/components/layout/sidebar/size-select";
|
import SizeSelect from "@/components/layout/sidebar/size-select";
|
||||||
|
import { BackgroundSelect } from "@/components/layout/sidebar/background-select";
|
||||||
|
import { Layers } from "@/components/layout/sidebar/layers";
|
||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-20 flex-col gap-2 p-2">
|
<div className="inline-flex h-full w-20 flex-col items-center justify-center gap-2 p-2">
|
||||||
<SizeSelect />
|
<SizeSelect />
|
||||||
<TextInput />
|
<TextInput />
|
||||||
<ImageInput />
|
<ImageInput />
|
||||||
<SelectTemplate />
|
{/*<SelectTemplate />*/}
|
||||||
|
<BackgroundSelect />
|
||||||
|
<Layers />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,22 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { PiTextT } from "react-icons/pi";
|
|
||||||
import { Card, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { RxMove } from "react-icons/rx";
|
||||||
import { addText } from "@/store/app.slice";
|
import { useAppDispatch } from "@/hooks";
|
||||||
import { SlSizeFullscreen } from "react-icons/sl";
|
import { updateStage } from "@/store/app.slice";
|
||||||
|
|
||||||
const SizeSelect = () => {
|
const SizeSelect = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleStageSizeSelect = (
|
||||||
|
width: number | undefined,
|
||||||
|
height: number | undefined,
|
||||||
|
) => {
|
||||||
|
dispatch(updateStage({ width, height }));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSizeSelect = () => {
|
const handleSizeSelect = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
@@ -22,10 +29,10 @@ const SizeSelect = () => {
|
|||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => setOpen(true)}
|
||||||
variant="secondary"
|
variant="outline"
|
||||||
className="text-xl"
|
className="text-xl"
|
||||||
>
|
>
|
||||||
<SlSizeFullscreen />
|
<RxMove />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="right" className="mt-4">
|
<PopoverContent side="right" className="mt-4">
|
||||||
@@ -35,17 +42,23 @@ const SizeSelect = () => {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<Button>Petit Format</Button>
|
<Button onClick={() => handleStageSizeSelect(350, 400)}>
|
||||||
<Button>Moyen Format</Button>
|
Petit Format
|
||||||
<Button>Grand Format</Button>
|
</Button>
|
||||||
|
<Button onClick={() => handleStageSizeSelect(500, 500)}>
|
||||||
|
Moyen Format
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => handleStageSizeSelect(800, 600)}>
|
||||||
|
Grand Format
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CardFooter className="mt-8 justify-between">
|
{/*<CardFooter className="mt-8 justify-between">*/}
|
||||||
<Button variant="ghost" onClick={() => setOpen(false)}>
|
{/* <Button variant="ghost" onClick={() => setOpen(false)}>*/}
|
||||||
Cancel
|
{/* Cancel*/}
|
||||||
</Button>
|
{/* </Button>*/}
|
||||||
<Button onClick={handleSizeSelect}>Submit</Button>
|
{/* <Button onClick={handleSizeSelect}>Submit</Button>*/}
|
||||||
</CardFooter>
|
{/*</CardFooter>*/}
|
||||||
</Card>
|
</Card>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -8,10 +8,8 @@ import { Textarea } from "@/components/ui/textarea";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { addText } from "@/store/app.slice";
|
import { addText } from "@/store/app.slice";
|
||||||
import { useAppDispatch } from "@/hooks";
|
import { useAppDispatch } from "@/hooks";
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { PiTextT } from "react-icons/pi";
|
|
||||||
import { Card, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Label } from "@/components/ui/label";
|
import { RxText } from "react-icons/rx";
|
||||||
|
|
||||||
export function TextInput() {
|
export function TextInput() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -30,16 +28,16 @@ export function TextInput() {
|
|||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => setOpen(true)}
|
||||||
variant="secondary"
|
variant="outline"
|
||||||
className="text-xl"
|
className="text-xl"
|
||||||
>
|
>
|
||||||
<PiTextT />
|
<RxText />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent side="right" className="mt-4">
|
<PopoverContent side="right" className="mt-4">
|
||||||
<Card className="p-3">
|
<Card className="p-3">
|
||||||
<CardHeader>
|
<CardHeader className="pt-2">
|
||||||
<CardTitle>Ajouter votre text</CardTitle>
|
<CardTitle className="text-center">Text</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<Textarea
|
<Textarea
|
||||||
id="description"
|
id="description"
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import { ImageToolbar } from "@/components/image-toolbar";
|
|||||||
import { TextToolbar } from "@/components/text-toolbar";
|
import { TextToolbar } from "@/components/text-toolbar";
|
||||||
import { useAppDispatch, useAppSelector } from "@/hooks";
|
import { useAppDispatch, useAppSelector } from "@/hooks";
|
||||||
import { updateText } from "@/store/app.slice";
|
import { updateText } from "@/store/app.slice";
|
||||||
import { BsTrash3 } from "react-icons/bs";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { DeleteShapeButton } from "@/components/delete-shape-button";
|
import { DeleteShapeButton } from "@/components/delete-shape-button";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
import type { TransformableImageProps } from "@/components/transformable-image";
|
import type { TransformableImageProps } from "@/components/transformable-image";
|
||||||
import type { TransformableTextProps } from "@/components/transformable-text";
|
import type { TransformableTextProps } from "@/components/transformable-text";
|
||||||
import type { PayloadAction } from "@reduxjs/toolkit";
|
import type { PayloadAction } from "@reduxjs/toolkit";
|
||||||
import type { ChangeEvent } from "react";
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
import { createSlice, current } from "@reduxjs/toolkit";
|
|
||||||
import { v1 } from "uuid";
|
import { v1 } from "uuid";
|
||||||
import type { TextConfig } from "konva/lib/shapes/Text";
|
import { type RectConfig } from "konva/lib/shapes/Rect";
|
||||||
import type { ImageConfig } from "konva/lib/shapes/Image";
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
stage: { width: 500, height: 500 },
|
||||||
selectedItemId: null as string | null,
|
selectedItemId: null as string | null,
|
||||||
images: [] as TransformableImageProps["imageProps"][],
|
images: [] as TransformableImageProps["imageProps"][],
|
||||||
texts: [] as TransformableTextProps["textProps"][],
|
texts: [] as TransformableTextProps["textProps"][],
|
||||||
|
backgroundRects: [] as RectConfig[],
|
||||||
};
|
};
|
||||||
|
|
||||||
type InitialState = typeof initialState;
|
|
||||||
|
|
||||||
const defaultTextConfig = {
|
const defaultTextConfig = {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
align: "center",
|
align: "center",
|
||||||
fontFamily: "Roboto",
|
fontFamily: "Roboto",
|
||||||
|
zIndex: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultImageConfig = {
|
const defaultImageConfig = {
|
||||||
@@ -30,6 +28,7 @@ const defaultImageConfig = {
|
|||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
scaleX: 1,
|
scaleX: 1,
|
||||||
scaleY: 1,
|
scaleY: 1,
|
||||||
|
zIndex: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const appSlice = createSlice({
|
export const appSlice = createSlice({
|
||||||
@@ -45,6 +44,19 @@ export const appSlice = createSlice({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
selectBackground: (state, action: PayloadAction<string>) => {
|
||||||
|
state.backgroundRects = [];
|
||||||
|
state.backgroundRects.push({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
stroke: "black",
|
||||||
|
z_index: 0,
|
||||||
|
width: state.stage.width,
|
||||||
|
height: state.stage.height,
|
||||||
|
fill: action.payload,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
addImage: (
|
addImage: (
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{
|
action: PayloadAction<{
|
||||||
@@ -74,6 +86,13 @@ export const appSlice = createSlice({
|
|||||||
state.selectedItemId = null;
|
state.selectedItemId = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateStage: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<{ width?: number; height?: number }>,
|
||||||
|
) => {
|
||||||
|
state.stage = { ...state.stage, ...action.payload };
|
||||||
|
},
|
||||||
|
|
||||||
updateText: (
|
updateText: (
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{ id: string } & Partial<TransformableTextProps>>,
|
action: PayloadAction<{ id: string } & Partial<TransformableTextProps>>,
|
||||||
@@ -126,4 +145,6 @@ export const {
|
|||||||
updateText,
|
updateText,
|
||||||
updateImage,
|
updateImage,
|
||||||
deleteShape,
|
deleteShape,
|
||||||
|
updateStage,
|
||||||
|
selectBackground,
|
||||||
} = appSlice.actions;
|
} = appSlice.actions;
|
||||||
|
|||||||
Reference in New Issue
Block a user