diff --git a/.env.example b/.env.example index a2ab1826..ae4a3763 100644 --- a/.env.example +++ b/.env.example @@ -22,4 +22,4 @@ FROM_EMAIL="hello@usesend.com" API_RATE_LIMIT=2 AUTH_EMAIL_RATE_LIMIT=5 -NEXT_PUBLIC_IS_CLOUD=true +NEXT_PUBLIC_IS_CLOUD=true \ No newline at end of file diff --git a/packages/email-editor/src/menus/TextMenu.tsx b/packages/email-editor/src/menus/TextMenu.tsx index f7df6871..5d439794 100644 --- a/packages/email-editor/src/menus/TextMenu.tsx +++ b/packages/email-editor/src/menus/TextMenu.tsx @@ -1,4 +1,9 @@ -import { BubbleMenu, BubbleMenuProps, isTextSelection } from "@tiptap/react"; +import { + BubbleMenu, + BubbleMenuProps, + Editor, + isTextSelection, +} from "@tiptap/react"; import { AlignCenterIcon, AlignLeftIcon, @@ -20,16 +25,13 @@ import { TextQuoteIcon, UnderlineIcon, } from "lucide-react"; -import { TextMenuButton } from "./TextMenuButton"; -import { Button } from "@usesend/ui/src/button"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@usesend/ui/src/popover"; -import { Separator } from "@usesend/ui/src/separator"; -import { useMemo, useState } from "react"; -import { LinkEditorPanel } from "../components/panels/LinkEditorPanel"; +import {TextMenuButton} from "./TextMenuButton"; +import {Button} from "@usesend/ui/src/button"; +import {Popover, PopoverContent, PopoverTrigger} from "@usesend/ui/src/popover"; +import {Separator} from "@usesend/ui/src/separator"; +import {useMemo, useState} from "react"; +import {LinkEditorPanel} from "../components/panels/LinkEditorPanel"; +import {EditorState} from "@tiptap/pm/state"; // import { allowedLogoAlignment } from "../nodes/logo"; export interface TextMenuItem { @@ -92,15 +94,15 @@ const textColors = [ ]; export function TextMenu(props: TextMenuProps) { - const { editor } = props; + const {editor} = props; const icons = [AlignLeftIcon, AlignCenterIcon, AlignRightIcon]; const alignmentItems: TextMenuItem[] = ["left", "center", "right"].map( (alignment, index) => ({ name: alignment, - isActive: () => editor?.isActive({ textAlign: alignment })!, + isActive: () => editor?.isActive({textAlign: alignment})!, command: () => { - if (props?.editor?.isActive({ textAlign: alignment })) { + if (props?.editor?.isActive({textAlign: alignment})) { props?.editor?.chain()?.focus().unsetTextAlign().run(); } else { props?.editor?.chain().focus().setTextAlign(alignment).run()!; @@ -185,11 +187,11 @@ export function TextMenu(props: TextMenuProps) { .focus() .lift("taskItem") .liftListItem("listItem") - .setHeading({ level: 1 }) + .setHeading({level: 1}) .run(), id: "heading1", - disabled: () => !editor?.can().setHeading({ level: 1 }), - isActive: () => editor?.isActive("heading", { level: 1 }), + disabled: () => !editor?.can().setHeading({level: 1}), + isActive: () => editor?.isActive("heading", {level: 1}), label: "Heading 1", type: "option", }, @@ -201,11 +203,11 @@ export function TextMenu(props: TextMenuProps) { ?.focus() ?.lift("taskItem") .liftListItem("listItem") - .setHeading({ level: 2 }) + .setHeading({level: 2}) .run(), id: "heading2", - disabled: () => !editor?.can().setHeading({ level: 2 }), - isActive: () => editor?.isActive("heading", { level: 2 }), + disabled: () => !editor?.can().setHeading({level: 2}), + isActive: () => editor?.isActive("heading", {level: 2}), label: "Heading 2", type: "option", }, @@ -217,11 +219,11 @@ export function TextMenu(props: TextMenuProps) { ?.focus() ?.lift("taskItem") .liftListItem("listItem") - .setHeading({ level: 3 }) + .setHeading({level: 3}) .run(), id: "heading3", - disabled: () => !editor?.can().setHeading({ level: 3 }), - isActive: () => editor?.isActive("heading", { level: 3 }), + disabled: () => !editor?.can().setHeading({level: 3}), + isActive: () => editor?.isActive("heading", {level: 3}), label: "Heading 3", type: "option", }, @@ -249,9 +251,9 @@ export function TextMenu(props: TextMenuProps) { const bubbleMenuProps: TextMenuProps = { ...props, - shouldShow: ({ editor, state, from, to }) => { - const { doc, selection } = state; - const { empty } = selection; + shouldShow: ({editor, state, from, to}) => { + const {doc, selection} = state; + const {empty} = selection; // Sometime check for `empty` is not enough. // Doubleclick an empty paragraph returns a node size of 2. @@ -300,11 +302,7 @@ export function TextMenu(props: TextMenuProps) { { - editor - ?.chain() - .focus() - .setLink({ href: url, target: "_blank" }) - .run(); + editor?.chain().focus().setLink({href: url, target: "_blank"}).run(); // editor?.commands.blur(); }} @@ -320,7 +318,7 @@ export function TextMenu(props: TextMenuProps) { variant="ghost" className="hover:bg-slate-100 hover:text-slate-900" > - A + A @@ -341,7 +339,7 @@ export function TextMenu(props: TextMenuProps) { : "" }`} > - A + A {color.name} ))} @@ -355,7 +353,7 @@ type ContentTypePickerProps = { options: ContentTypePickerOption[]; }; -function ContentTypePicker({ options }: ContentTypePickerProps) { +function ContentTypePicker({options}: ContentTypePickerProps) { const activeOption = useMemo( () => options.find((option) => option.isActive()), [options] @@ -401,7 +399,7 @@ type EditLinkPopoverType = { onSetLink: (url: string) => void; }; -function EditLinkPopover({ onSetLink }: EditLinkPopoverType) { +function EditLinkPopover({onSetLink}: EditLinkPopoverType) { return ( diff --git a/packages/email-editor/src/nodes/variable.tsx b/packages/email-editor/src/nodes/variable.tsx index 0788da5b..84f3ed7b 100644 --- a/packages/email-editor/src/nodes/variable.tsx +++ b/packages/email-editor/src/nodes/variable.tsx @@ -1,16 +1,12 @@ -import { NodeViewProps, NodeViewWrapper, ReactRenderer } from "@tiptap/react"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@usesend/ui/src/popover"; -import { cn } from "@usesend/ui/lib/utils"; -import { Input } from "@usesend/ui/src/input"; -import { Button } from "@usesend/ui/src/button"; -import { forwardRef, useEffect, useImperativeHandle, useState } from "react"; -import { SuggestionOptions } from "@tiptap/suggestion"; -import tippy, { GetReferenceClientRect } from "tippy.js"; -import { CheckIcon, TriangleAlert } from "lucide-react"; +import {NodeViewProps, NodeViewWrapper, ReactRenderer} from "@tiptap/react"; +import {Popover, PopoverContent, PopoverTrigger} from "@usesend/ui/src/popover"; +import {cn} from "@usesend/ui/lib/utils"; +import {Input} from "@usesend/ui/src/input"; +import {Button} from "@usesend/ui/src/button"; +import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; +import {SuggestionOptions} from "@tiptap/suggestion"; +import tippy, {GetReferenceClientRect} from "tippy.js"; +import {CheckIcon, TriangleAlert} from "lucide-react"; export interface VariableOptions { name: string; @@ -26,14 +22,14 @@ export const VariableList = forwardRef((props: any, ref) => { console.log("item: ", item); if (item) { - props.command({ id: item, name: item, fallback: "" }); + props.command({id: item, name: item, fallback: ""}); } }; useEffect(() => setSelectedIndex(0), [props.items]); useImperativeHandle(ref, () => ({ - onKeyDown: ({ event }: { event: KeyboardEvent }) => { + onKeyDown: ({event}: {event: KeyboardEvent}) => { if (event.key === "ArrowUp") { setSelectedIndex( (selectedIndex + props.items.length - 1) % props.items.length @@ -85,7 +81,7 @@ export function getVariableSuggestions( variables: Array = [] ): Omit { return { - items: ({ query }) => { + items: ({query}) => { return variables .concat(query.length > 0 ? [query] : []) .filter((item) => item.toLowerCase().startsWith(query.toLowerCase())) @@ -154,9 +150,10 @@ export function getVariableSuggestions( } export function VariableComponent(props: NodeViewProps) { - const { name, fallback } = props.node.attrs as VariableOptions; + const [isEditing, setIsEditing] = useState(false); + const {name, fallback} = props.node.attrs as VariableOptions; const [fallbackValue, setFallbackValue] = useState(fallback); - const { getPos, editor } = props; + const {getPos, editor} = props; console.log(props.selected); @@ -165,6 +162,8 @@ export function VariableComponent(props: NodeViewProps) { props.updateAttributes({ fallback: fallbackValue, }); + + setIsEditing(false); }; return ( @@ -175,17 +174,26 @@ export function VariableComponent(props: NodeViewProps) { draggable="false" data-drag-handle="" > - + !open && setIsEditing(false)} + >