diff --git a/components/Canvas.tsx b/components/Canvas.tsx index d09222e..87a4445 100644 --- a/components/Canvas.tsx +++ b/components/Canvas.tsx @@ -20,7 +20,12 @@ import { updateSelectedTool, } from "../redux/canvasSlice"; import { SHAPE_DEFAULT_HEIGHT, SHAPE_DEFAULT_WIDTH } from "./shapes/shapeUtils"; -import { TEXT_DEFAULT_HEIGHT, TEXT_DEFAULT_WIDTH } from "./text/textUtils"; +import { + getFontStyleStringFromTextStyleArray, + getTextDecorationStringFromTextStyleArray, + TEXT_DEFAULT_HEIGHT, + TEXT_DEFAULT_WIDTH, +} from "./text/textUtils"; import ShapePanel from "./toolbar/ShapePanel"; import TextPanel from "./toolbar/TextPanel"; import { @@ -83,6 +88,9 @@ export default function Canvas() { (state: RootState) => state.shape, ); + const { textSize, textStyle, textColor, textAlignment, lineSpacing } = + useSelector((state: RootState) => state.text); + const [isInProgress, setIsInProgress] = useState(false); const [newObject, setNewObject] = useState(null); // new text/shape object to be added to the canvas @@ -260,10 +268,13 @@ export default function Canvas() { y: y, width: TEXT_DEFAULT_WIDTH, height: TEXT_DEFAULT_HEIGHT, - fill: strokeColor, // use strokeColor for fill for now - // strokeWidth not applied to text field for now + fill: textColor, text: "Double click to edit.", - fontSize: 28, + fontSize: textSize, + align: textAlignment, + lineHeight: lineSpacing, + fontStyle: getFontStyleStringFromTextStyleArray(textStyle), + textDecoration: getTextDecorationStringFromTextStyleArray(textStyle), fontFamily: "Arial", }; diff --git a/components/text/TextLayer.tsx b/components/text/TextLayer.tsx index f05aa18..e382ba4 100644 --- a/components/text/TextLayer.tsx +++ b/components/text/TextLayer.tsx @@ -2,7 +2,16 @@ import { Layer } from "react-konva"; import { CanvasObjectType } from "../Canvas"; import TextField from "./TextField"; import { RootState } from "@/redux/store"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; +import { updateCanvasObject } from "@/redux/canvasSlice"; +import { + setLineSpacing, + setTextAlignment, + setTextColor, + setTextSize, + setTextStyle, +} from "@/redux/textSlice"; +import { convertTextPropertiesToTextStyleArray } from "./textUtils"; type Props = { objects: CanvasObjectType[]; @@ -24,6 +33,8 @@ export default function TextLayer({ onChange, setSidePanelVisible, }: Props) { + const dispatch = useDispatch(); + const { selectedTool } = useSelector((state: RootState) => state.canvas); const texts = [ @@ -46,6 +57,18 @@ export default function TextLayer({ setSidePanelVisible(true); // update settings to match selected text's + dispatch(setTextSize(text.fontSize || 28)); + dispatch(setTextColor(text.fill || "#000")); + dispatch(setTextAlignment(text.align || "left")); + dispatch(setLineSpacing(text.lineHeight || 1.5)); + dispatch( + setTextStyle( + convertTextPropertiesToTextStyleArray( + text.fontStyle, + text.textDecoration, + ), + ), + ); // Update cursor style const stage = e.target.getStage(); diff --git a/components/text/textUtils.ts b/components/text/textUtils.ts index 980c377..547e30f 100644 --- a/components/text/textUtils.ts +++ b/components/text/textUtils.ts @@ -2,3 +2,43 @@ export const TEXT_DEFAULT_WIDTH = 200; export const TEXT_DEFAULT_HEIGHT = 50; export const TEXT_MIN_WIDTH = 5; export const TEXT_MIN_HEIGHT = 5; + +export function convertTextPropertiesToTextStyleArray( + fontStyle: string | undefined, + textDecoration: string | undefined, +): string[] { + let textStyle = []; + if (fontStyle?.includes("bold")) { + textStyle.push("bold"); + } + if (fontStyle?.includes("italic")) { + textStyle.push("italic"); + } + if (textDecoration?.includes("underline")) { + textStyle.push("underline"); + } + return textStyle; +} + +export function getFontStyleStringFromTextStyleArray( + textStyle: string[], +): string { + let fontStyle = ""; + if (textStyle.includes("bold")) { + fontStyle += "bold"; + } + if (textStyle.includes("italic")) { + fontStyle += " italic"; + } + return fontStyle; +} + +export function getTextDecorationStringFromTextStyleArray( + textStyle: string[], +): string { + let textDecoration = ""; + if (textStyle.includes("underline")) { + textDecoration += "underline"; + } + return textDecoration; +} diff --git a/components/toolbar/ShapePanel.tsx b/components/toolbar/ShapePanel.tsx index 00b5e73..ca58c36 100644 --- a/components/toolbar/ShapePanel.tsx +++ b/components/toolbar/ShapePanel.tsx @@ -89,7 +89,7 @@ export default function ShapePanel({ }} aria-label="Border width" onChange={(_, value) => setStrokeWidth(value as number)} - sx={{ flex: 1 }} + sx={{ flex: 1, mr: 2 }} /> diff --git a/components/toolbar/TextPanel.tsx b/components/toolbar/TextPanel.tsx index 283f52d..be5a721 100644 --- a/components/toolbar/TextPanel.tsx +++ b/components/toolbar/TextPanel.tsx @@ -32,6 +32,10 @@ import { setTextStyle, } from "@/redux/textSlice"; import { updateCanvasObject } from "@/redux/canvasSlice"; +import { + getFontStyleStringFromTextStyleArray, + getTextDecorationStringFromTextStyleArray, +} from "../text/textUtils"; type Props = { onClose: () => void; @@ -58,33 +62,25 @@ export default function TextPanel({ event: React.MouseEvent, newStyle: string[], ) => { - console.log("newStyle = ", newStyle); + // update textStyle in redux store dispatch(setTextStyle(newStyle)); + // update selected object // fontStyle (bold / italic) - let newFontStyle = ""; - if (newStyle.includes("bold")) { - newFontStyle += "bold"; - } - if (newStyle.includes("italic")) { - newFontStyle += " italic"; - } dispatch( updateCanvasObject({ id: selectedObjectId, - updates: { fontStyle: newFontStyle }, + updates: { fontStyle: getFontStyleStringFromTextStyleArray(newStyle) }, }), ); // textDecoration (underline) - let newTextDecoration = ""; - if (newStyle.includes("underline")) { - newTextDecoration += "underline"; - } dispatch( updateCanvasObject({ id: selectedObjectId, - updates: { textDecoration: newTextDecoration }, + updates: { + textDecoration: getTextDecorationStringFromTextStyleArray(newStyle), + }, }), ); }; diff --git a/redux/textSlice.ts b/redux/textSlice.ts index ccdec6f..d927ac5 100644 --- a/redux/textSlice.ts +++ b/redux/textSlice.ts @@ -4,12 +4,12 @@ interface TextState { textSize: number; textStyle: string[]; textColor: string; - textAlignment: "left" | "center" | "right"; + textAlignment: string; lineSpacing: number; } const initialState: TextState = { - textSize: 16, + textSize: 28, textStyle: [], textColor: "#000000", textAlignment: "left", @@ -29,10 +29,7 @@ const textSlice = createSlice({ setTextColor: (state, action: PayloadAction) => { state.textColor = action.payload; }, - setTextAlignment: ( - state, - action: PayloadAction<"left" | "center" | "right">, - ) => { + setTextAlignment: (state, action: PayloadAction) => { state.textAlignment = action.payload; }, setLineSpacing: (state, action: PayloadAction) => {