mirror of
https://github.com/r2r90/canvas-label.git
synced 2025-12-18 05:29:26 +00:00
layer block function DONE!
Started legacy function
This commit is contained in:
@@ -109,6 +109,7 @@ const Canvas = () => {
|
|||||||
}}
|
}}
|
||||||
imageProps={item.params}
|
imageProps={item.params}
|
||||||
key={item.id}
|
key={item.id}
|
||||||
|
isBlocked={item.isBlocked}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -116,6 +117,7 @@ const Canvas = () => {
|
|||||||
return (
|
return (
|
||||||
<TransformableText
|
<TransformableText
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
|
isBlocked={item.isBlocked}
|
||||||
onEditChange={toggleEdit}
|
onEditChange={toggleEdit}
|
||||||
onSelect={() => selectItem(item.id)}
|
onSelect={() => selectItem(item.id)}
|
||||||
isSelected={item.id === selectedItemId}
|
isSelected={item.id === selectedItemId}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useSortable } from "@dnd-kit/sortable";
|
import { useSortable } from "@dnd-kit/sortable";
|
||||||
import { CSS } from "@dnd-kit/utilities";
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
import { type StageItem, StageItemType } from "@/store/app.slice";
|
import {
|
||||||
|
setBlockedItem,
|
||||||
|
type StageItem,
|
||||||
|
StageItemType,
|
||||||
|
} from "@/store/app.slice";
|
||||||
import { useAppDispatch } from "@/hooks";
|
import { useAppDispatch } from "@/hooks";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { HiOutlineLockClosed, HiOutlineLockOpen } from "react-icons/hi2";
|
import { HiOutlineLockClosed, HiOutlineLockOpen } from "react-icons/hi2";
|
||||||
|
import { IconButton } from "@radix-ui/themes";
|
||||||
|
import { GripVertical } from "lucide-react";
|
||||||
|
|
||||||
export default function LayerItem({ item }: { item: StageItem }) {
|
export default function LayerItem({ item }: { item: StageItem }) {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -17,14 +23,21 @@ export default function LayerItem({ item }: { item: StageItem }) {
|
|||||||
transform: CSS.Transform.toString(transform),
|
transform: CSS.Transform.toString(transform),
|
||||||
transition,
|
transition,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBlockItemClicked = () => {
|
||||||
|
dispatch(setBlockedItem({ id: item.id, blocked: !item.isBlocked }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={style}
|
style={style}
|
||||||
ref={setNodeRef}
|
ref={setNodeRef}
|
||||||
{...attributes}
|
{...attributes}
|
||||||
{...listeners}
|
|
||||||
className="m-2 flex items-center justify-between rounded-md border p-2 text-black"
|
className="m-2 flex items-center justify-between rounded-md border p-2 text-black"
|
||||||
>
|
>
|
||||||
|
<IconButton {...listeners}>
|
||||||
|
<GripVertical />
|
||||||
|
</IconButton>
|
||||||
<span className="">{item.type}</span>
|
<span className="">{item.type}</span>
|
||||||
|
|
||||||
{item.type === StageItemType.Text ? (
|
{item.type === StageItemType.Text ? (
|
||||||
@@ -40,9 +53,8 @@ export default function LayerItem({ item }: { item: StageItem }) {
|
|||||||
src={item.params.imageUrl}
|
src={item.params.imageUrl}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button>
|
<Button onClick={handleBlockItemClicked}>
|
||||||
<HiOutlineLockClosed />
|
{item.isBlocked ? <HiOutlineLockClosed /> : <HiOutlineLockOpen />}
|
||||||
<HiOutlineLockOpen />
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export type TransformableImageProps = {
|
|||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
onSelect: () => void;
|
onSelect: () => void;
|
||||||
onChange: (newAttrs: TransformableImageConfig) => void;
|
onChange: (newAttrs: TransformableImageConfig) => void;
|
||||||
|
isBlocked: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TransformableImage = ({
|
export const TransformableImage = ({
|
||||||
@@ -21,6 +22,7 @@ export const TransformableImage = ({
|
|||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
onChange,
|
onChange,
|
||||||
|
isBlocked,
|
||||||
}: TransformableImageProps) => {
|
}: TransformableImageProps) => {
|
||||||
const imageRef = useRef<ElementRef<typeof Image>>(null);
|
const imageRef = useRef<ElementRef<typeof Image>>(null);
|
||||||
const trRef = useRef<ElementRef<typeof Transformer>>(null);
|
const trRef = useRef<ElementRef<typeof Transformer>>(null);
|
||||||
@@ -46,8 +48,11 @@ export const TransformableImage = ({
|
|||||||
ref={imageRef}
|
ref={imageRef}
|
||||||
{...imageProps}
|
{...imageProps}
|
||||||
image={image}
|
image={image}
|
||||||
draggable
|
draggable={!isBlocked}
|
||||||
onDragEnd={(e) => {
|
onDragEnd={(e) => {
|
||||||
|
if (isBlocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
onChange({
|
onChange({
|
||||||
...imageProps,
|
...imageProps,
|
||||||
image,
|
image,
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export type TransformableTextProps = {
|
|||||||
id: string;
|
id: string;
|
||||||
isEditing?: boolean;
|
isEditing?: boolean;
|
||||||
onEditChange?: (isEditing: boolean) => void;
|
onEditChange?: (isEditing: boolean) => void;
|
||||||
|
isBlocked: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TransformableText = ({
|
const TransformableText = ({
|
||||||
@@ -48,6 +49,7 @@ const TransformableText = ({
|
|||||||
id,
|
id,
|
||||||
isEditing,
|
isEditing,
|
||||||
onEditChange,
|
onEditChange,
|
||||||
|
isBlocked,
|
||||||
}: TransformableTextProps) => {
|
}: TransformableTextProps) => {
|
||||||
console.log(textProps);
|
console.log(textProps);
|
||||||
const [value, setText] = useState<string | undefined>("");
|
const [value, setText] = useState<string | undefined>("");
|
||||||
@@ -70,6 +72,7 @@ const TransformableText = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDblClick = () => {
|
const handleDblClick = () => {
|
||||||
|
if (isBlocked) return;
|
||||||
setText(text);
|
setText(text);
|
||||||
onEditChange?.(true);
|
onEditChange?.(true);
|
||||||
};
|
};
|
||||||
@@ -121,8 +124,9 @@ const TransformableText = ({
|
|||||||
align={"center"}
|
align={"center"}
|
||||||
{...textProps}
|
{...textProps}
|
||||||
text={text}
|
text={text}
|
||||||
draggable
|
draggable={!isBlocked}
|
||||||
onDragEnd={(e) => {
|
onDragEnd={(e) => {
|
||||||
|
if (isBlocked) return;
|
||||||
onChange({
|
onChange({
|
||||||
...textProps,
|
...textProps,
|
||||||
text,
|
text,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export enum StageItemType {
|
|||||||
|
|
||||||
type StageItemCommon = {
|
type StageItemCommon = {
|
||||||
id: string;
|
id: string;
|
||||||
|
isBlocked: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StageTextItem = {
|
export type StageTextItem = {
|
||||||
@@ -77,9 +78,9 @@ export const appSlice = createSlice({
|
|||||||
state.items.push({
|
state.items.push({
|
||||||
type: StageItemType.Text,
|
type: StageItemType.Text,
|
||||||
id: textId,
|
id: textId,
|
||||||
|
isBlocked: false,
|
||||||
params: {
|
params: {
|
||||||
text: action.payload.initialValue,
|
text: action.payload.initialValue,
|
||||||
|
|
||||||
...defaultTextConfig,
|
...defaultTextConfig,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -98,6 +99,7 @@ export const appSlice = createSlice({
|
|||||||
state.items.push({
|
state.items.push({
|
||||||
type: StageItemType.Image,
|
type: StageItemType.Image,
|
||||||
id: imageId,
|
id: imageId,
|
||||||
|
isBlocked: false,
|
||||||
params: {
|
params: {
|
||||||
imageUrl: action.payload.imageUrl,
|
imageUrl: action.payload.imageUrl,
|
||||||
width: action.payload.width,
|
width: action.payload.width,
|
||||||
@@ -106,6 +108,21 @@ export const appSlice = createSlice({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
setBlockedItem: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<{ id: string; blocked: boolean }>,
|
||||||
|
) => {
|
||||||
|
const itemToUpdate = state.items.find(
|
||||||
|
(item) => item.id === action.payload.id,
|
||||||
|
);
|
||||||
|
if (!itemToUpdate) return;
|
||||||
|
|
||||||
|
if (state.selectedItemId === itemToUpdate.id) {
|
||||||
|
state.selectedItemId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemToUpdate.isBlocked = action.payload.blocked;
|
||||||
|
},
|
||||||
|
|
||||||
selectBackground: (state, action: PayloadAction<string>) => {
|
selectBackground: (state, action: PayloadAction<string>) => {
|
||||||
state.background = {
|
state.background = {
|
||||||
@@ -114,6 +131,14 @@ export const appSlice = createSlice({
|
|||||||
},
|
},
|
||||||
|
|
||||||
selectItem: (state, action: PayloadAction<string>) => {
|
selectItem: (state, action: PayloadAction<string>) => {
|
||||||
|
const itemToSelect = state.items.find(
|
||||||
|
(item) => item.id === action.payload,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!itemToSelect || itemToSelect.isBlocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
state.selectedItemId = action.payload;
|
state.selectedItemId = action.payload;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -136,7 +161,12 @@ export const appSlice = createSlice({
|
|||||||
const textToUpdateIndex = state.items.findIndex((t) => t.id === id);
|
const textToUpdateIndex = state.items.findIndex((t) => t.id === id);
|
||||||
const textToUpdate = state.items[textToUpdateIndex];
|
const textToUpdate = state.items[textToUpdateIndex];
|
||||||
|
|
||||||
if (!textToUpdate || textToUpdate.type !== StageItemType.Text) return;
|
if (
|
||||||
|
!textToUpdate ||
|
||||||
|
textToUpdate.type !== StageItemType.Text ||
|
||||||
|
textToUpdate.isBlocked
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
state.items[textToUpdateIndex] = {
|
state.items[textToUpdateIndex] = {
|
||||||
...textToUpdate,
|
...textToUpdate,
|
||||||
@@ -155,7 +185,12 @@ export const appSlice = createSlice({
|
|||||||
const imageToUpdateIndex = state.items.findIndex((img) => img.id === id);
|
const imageToUpdateIndex = state.items.findIndex((img) => img.id === id);
|
||||||
const imageToUpdate = state.items[imageToUpdateIndex];
|
const imageToUpdate = state.items[imageToUpdateIndex];
|
||||||
|
|
||||||
if (!imageToUpdate || imageToUpdate.type !== StageItemType.Image) return;
|
if (
|
||||||
|
!imageToUpdate ||
|
||||||
|
imageToUpdate.type !== StageItemType.Image ||
|
||||||
|
imageToUpdate.isBlocked
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
(state.items[imageToUpdateIndex] as WritableDraft<StageImageItem>) = {
|
(state.items[imageToUpdateIndex] as WritableDraft<StageImageItem>) = {
|
||||||
...imageToUpdate,
|
...imageToUpdate,
|
||||||
@@ -186,4 +221,5 @@ export const {
|
|||||||
selectBackground,
|
selectBackground,
|
||||||
setStageItems,
|
setStageItems,
|
||||||
selectItem,
|
selectItem,
|
||||||
|
setBlockedItem,
|
||||||
} = appSlice.actions;
|
} = appSlice.actions;
|
||||||
|
|||||||
Reference in New Issue
Block a user