diff --git a/src/components/font-family-picker.tsx b/src/components/font-family-picker.tsx index f2b89a5..c732e8e 100644 --- a/src/components/font-family-picker.tsx +++ b/src/components/font-family-picker.tsx @@ -2,10 +2,7 @@ import * as React from "react"; import fonts from "../assets/fonts.json"; -import { - CaretSortIcon, - CheckIcon, -} from "@radix-ui/react-icons"; +import { CaretSortIcon, CheckIcon } from "@radix-ui/react-icons"; import { cn } from "@/lib/utils"; @@ -26,15 +23,14 @@ import { import { useEffect } from "react"; -type PopoverTriggerProps = React.ComponentPropsWithoutRef< - typeof PopoverTrigger ->; +type Props = { + handleTextFontFamilyChange: (fontFamiy: string | undefined) => void; + selectedFont: string; +}; -type Props = PopoverTriggerProps; - -export function FontFamilyPicker({}: Props) { +export function FontFamilyPicker({ handleTextFontFamilyChange, selectedFont }: Props) { const [open, setOpen] = React.useState(false); - const [selectedFont, setSelectedFont] = React.useState("Roboto"); + useEffect(() => { fonts.items.map((font): void => { @@ -73,8 +69,8 @@ export function FontFamilyPicker({}: Props) { { - setSelectedFont(font.family); setOpen(false); + handleTextFontFamilyChange(font.family); }} className="text-sm" style={{ fontFamily: font.family }} diff --git a/src/components/font-size-selector.tsx b/src/components/font-size-selector.tsx index a752a9c..118576f 100644 --- a/src/components/font-size-selector.tsx +++ b/src/components/font-size-selector.tsx @@ -22,7 +22,7 @@ export function FontSizeSelector({ value, fontSizeHandler }: FontSizeSelector) { { @@ -33,13 +33,6 @@ export function FontSizeSelector({ value, fontSizeHandler }: FontSizeSelector) { /> - {/* - Select font - */} ); diff --git a/src/components/spacing-settings.tsx b/src/components/spacing-settings.tsx new file mode 100644 index 0000000..cf8e319 --- /dev/null +++ b/src/components/spacing-settings.tsx @@ -0,0 +1,50 @@ +import { GiSettingsKnobs } from "react-icons/gi"; +import { Button } from "./ui/button"; +import { Input } from "./ui/input"; +import { Label } from "./ui/label"; +import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; +import { Slider } from "./ui/slider"; + +export const SpacingSettings = () => { + return ( + + + + + +
+
+
+ + +
+
+ + +
+
+ +
+
+ +
+ ); +}; diff --git a/src/components/toolbar.tsx b/src/components/toolbar.tsx index 917dc9c..21b202e 100644 --- a/src/components/toolbar.tsx +++ b/src/components/toolbar.tsx @@ -1,11 +1,13 @@ import { useAppDispatch, useAppSelector } from "@/hooks"; import { updateText } from "@/store/app.slice"; import { Toggle } from "@/components/ui/toggle"; -import { Select } from "@/components/ui/select"; import { FontFamilyPicker } from "./font-family-picker"; import { FontSizeSelector } from "./font-size-selector"; +import { useState, type ChangeEvent } from "react"; +import { SpacingSettings } from "./spacing-settings"; export const Toolbar = () => { + const [alignment, setAlignment] = useState("left"); const dispatch = useAppDispatch(); const selectedItemId = useAppSelector((state) => state.app.selectedItemId); const texts = useAppSelector((state) => state.app.texts); @@ -15,9 +17,10 @@ export const Toolbar = () => { if (!currentText) return null; const handleFontStyleToggle = (button: "bold" | "italic") => () => { + if (!selectedItemId) return; dispatch( updateText({ - ...currentText, + id: selectedItemId, fontStyle: getFontStyle(currentText.fontStyle, button), }), ); @@ -25,23 +28,57 @@ export const Toolbar = () => { const handleTextDecorationToggle = (button: "underline" | "line-through") => () => { + if (!selectedItemId) return; + dispatch( updateText({ - ...currentText, + id: selectedItemId, textDecoration: getFontStyle(currentText.textDecoration, button), }), ); }; const handleTextFontSizeChange = (e: number | undefined) => { + if (!selectedItemId) return; dispatch( updateText({ - ...currentText, + id: selectedItemId, fontSize: e, }), ); }; + const handleTextFontFamilyChange = (e: string | undefined) => { + if (!selectedItemId) return; + dispatch( + updateText({ + id: selectedItemId, + fontFamily: e, + }), + ); + }; + const handleTextColorChange = (e: ChangeEvent) => { + if (!selectedItemId) return; + dispatch( + updateText({ + id: selectedItemId, + fill: e.target.value, + }), + ); + }; + + const handleTextAlignChange = (e: ChangeEvent) => { + if (!selectedItemId) return; + dispatch( + updateText({ + id: selectedItemId, + align: e.target.value, + }), + ); + }; + + const handleAlignmentChange = (newAlignment: string | undefined) => {}; + return (
{ value={currentText.fontSize ?? 16} fontSizeHandler={handleTextFontSizeChange} /> - - + + + + + +
); }; diff --git a/src/components/transformable-text.tsx b/src/components/transformable-text.tsx index 8dc13be..07d84d7 100644 --- a/src/components/transformable-text.tsx +++ b/src/components/transformable-text.tsx @@ -6,7 +6,7 @@ type TransformableTextConfig = Omit & { text?: TextConfig["text"]; id: string; direction?: string; - fontFamily?: string; + fontFamily: string; fontSize?: number; fontStyle?: string; fontVariant?: string; diff --git a/src/store/app.slice.ts b/src/store/app.slice.ts index 678d4cd..a75dcb4 100644 --- a/src/store/app.slice.ts +++ b/src/store/app.slice.ts @@ -1,12 +1,12 @@ import type { TransformableImageProps } from "@/components/transformable-image"; import type { TransformableTextProps } from "@/components/transformable-text"; import type { PayloadAction } from "@reduxjs/toolkit"; -import type { KonvaEventObject } from "konva/lib/Node"; import type { ChangeEvent } from "react"; import { createSlice } from "@reduxjs/toolkit"; import { v1 } from "uuid"; -import { TextConfig } from "konva/lib/shapes/Text"; +import type { TextConfig } from "konva/lib/shapes/Text"; +import { RootState } from "./store"; const initialState = { selectedItemId: null as string | null, @@ -14,9 +14,12 @@ const initialState = { texts: [] as TransformableTextProps["textProps"][], }; +type InitialState = typeof initialState; + const defaultTextConfig = { fontSize: 16, align: "center", + fontFamily: "Roboto", }; export const appSlice = createSlice({ @@ -51,40 +54,22 @@ export const appSlice = createSlice({ updateText: ( state, - action: PayloadAction & { id: string }>, + action: PayloadAction<{ id: string } & Partial>, ) => { - const textToUpdate = state.texts.findIndex( + const textToUpdateIndex = state.texts.findIndex( (t) => t.id === action.payload.id, ); - state.texts[textToUpdate] = action.payload; - }, - updateTextFontSize: ( - state, - action: PayloadAction & { id: string }>, - ) => { - const textToUpdate = state.texts.findIndex( - (t) => t.id === action.payload.id, - ); - state.texts[textToUpdate] = action.payload; - }, + const textToUpdate = state.texts[textToUpdateIndex]; - // updateTextFontFamily: ( - // state, - // action: PayloadAction & { id: string }>, - // ) => { - // const textToUpdate = state.texts.findIndex( - // (t) => t.id === action.payload.id, - // ); - // state.texts[textToUpdate] = action.payload; - // }, + if (!textToUpdate) return; + + state.texts[textToUpdateIndex] = { + ...textToUpdate, + ...action.payload, + }; + }, }, }); -export const { - addImage, - addText, - selectItem, - deselectItem, - updateText, - updateTextFontSize, -} = appSlice.actions; +export const { addImage, addText, selectItem, deselectItem, updateText } = + appSlice.actions; diff --git a/todo.md b/todo.md index 1c78435..86afbb5 100644 --- a/todo.md +++ b/todo.md @@ -1,2 +1,7 @@ -[ ] image toolbar -[ ] text toolbar +Property 'PopoverTriggerProps' is missing in type '{ handleTextFontFamilyChange: (e: string | undefined) => void; }' but required in type 'Props'.ts(2741) +font-family-picker.tsx(31, 3): 'PopoverTriggerProps' is declared here. +(alias) function FontFamilyPicker({ handleTextFontFamilyChange }: Props): React.JSX.Element +import FontFamilyPicker + + +