text edit finition

This commit is contained in:
Artur AGH
2023-10-23 21:08:34 +02:00
parent 2abea89a2e
commit 7ea8779942
7 changed files with 141 additions and 61 deletions

View File

@@ -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<string>("Roboto");
useEffect(() => {
fonts.items.map((font): void => {
@@ -73,8 +69,8 @@ export function FontFamilyPicker({}: Props) {
<CommandItem
key={font.family}
onSelect={() => {
setSelectedFont(font.family);
setOpen(false);
handleTextFontFamilyChange(font.family);
}}
className="text-sm"
style={{ fontFamily: font.family }}

View File

@@ -22,7 +22,7 @@ export function FontSizeSelector({ value, fontSizeHandler }: FontSizeSelector) {
<Slider
id="fontSize"
min={1}
max={48}
max={100}
defaultValue={[value ?? 16]}
step={1}
onValueChange={(e) => {
@@ -33,13 +33,6 @@ export function FontSizeSelector({ value, fontSizeHandler }: FontSizeSelector) {
/>
</div>
</HoverCardTrigger>
{/* <HoverCardContent
align="start"
className="w-[260px] text-sm"
side="left"
>
Select font
</HoverCardContent> */}
</HoverCard>
</>
);

View File

@@ -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 (
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">
<GiSettingsKnobs />
</Button>
</PopoverTrigger>
<PopoverContent className="w-80">
<div className="grid gap-4">
<div className="grid gap-2">
<div className="grid grid-cols-3 items-center gap-4">
<Label htmlFor="width">Width</Label>
<Slider
id="fontSize"
min={1}
max={100}
step={1}
className="[&_[role=slider]]:h-4 [&_[role=slider]]:w-4"
aria-label="fontSize"
/>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<Label htmlFor="maxWidth">Letter Spacing</Label>
<Slider
id="fontSize"
min={1}
max={100}
step={1}
className="[&_[role=slider]]:h-4 [&_[role=slider]]:w-4"
aria-label="fontSize"
/>
</div>
</div>
</div>
</PopoverContent>
</Popover>
);
};

View File

@@ -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<HTMLInputElement>) => {
if (!selectedItemId) return;
dispatch(
updateText({
id: selectedItemId,
fill: e.target.value,
}),
);
};
const handleTextAlignChange = (e: ChangeEvent<HTMLInputElement>) => {
if (!selectedItemId) return;
dispatch(
updateText({
id: selectedItemId,
align: e.target.value,
}),
);
};
const handleAlignmentChange = (newAlignment: string | undefined) => {};
return (
<div className="flex h-[5rem] w-full gap-6 border bg-white p-[1rem] transition">
<Toggle
@@ -73,8 +110,22 @@ export const Toolbar = () => {
value={currentText.fontSize ?? 16}
fontSizeHandler={handleTextFontSizeChange}
/>
<input type="color" />
<FontFamilyPicker />
<input
type="color"
onChange={handleTextColorChange}
value={currentText.fill}
/>
<FontFamilyPicker
handleTextFontFamilyChange={handleTextFontFamilyChange}
selectedFont={currentText.fontFamily}
/>
<Toggle
className="data-[state=on]:font-bold"
onClick={handleAlignmentChange("left")}
></Toggle>
<SpacingSettings />
</div>
);
};

View File

@@ -6,7 +6,7 @@ type TransformableTextConfig = Omit<TextConfig, "text"> & {
text?: TextConfig["text"];
id: string;
direction?: string;
fontFamily?: string;
fontFamily: string;
fontSize?: number;
fontStyle?: string;
fontVariant?: string;

View File

@@ -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<Omit<TextConfig, "id"> & { id: string }>,
action: PayloadAction<{ id: string } & Partial<TextConfig>>,
) => {
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<Omit<TextConfig, "id"> & { 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<Omit<TextConfig, "id"> & { 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;

View File

@@ -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