diff --git a/templates/content/app/components/editor/BubbleToolbar.test.tsx b/templates/content/app/components/editor/BubbleToolbar.test.tsx index 08ee68c75d..80b2cec168 100644 --- a/templates/content/app/components/editor/BubbleToolbar.test.tsx +++ b/templates/content/app/components/editor/BubbleToolbar.test.tsx @@ -34,7 +34,43 @@ vi.mock("@/components/ui/tooltip", () => ({ TooltipTrigger: ({ children }: { children: ReactNode }) => children, })); -describe("BubbleToolbar link shortcut", () => { +vi.mock("@/components/ui/popover", () => ({ + Popover: ({ children }: { children: ReactNode }) => children, + PopoverTrigger: ({ children }: { children: ReactNode }) => children, + PopoverContent: ({ + children, + onCloseAutoFocus, + onEscapeKeyDown, + }: { + children: ReactNode; + onCloseAutoFocus?: (event: Event) => void; + onEscapeKeyDown?: (event: KeyboardEvent) => void; + }) => ( +
Selected heading
"); + expect(editor.getHTML()).not.toContain("First block
First block
Second block
"); + expect(editor.getHTML()).not.toContain("Selected paragraph
", + }); + editor.commands.setTextSelection({ from: 1, to: 9 }); + + root = createRoot(toolbarElement); + act(() => root!.render(Selected paragraph
", + }); + editor.commands.setTextSelection({ from: 1, to: 9 }); + + root = createRoot(toolbarElement); + act(() => root!.render(Selected heading
"); + expect(editor.getHTML()).not.toContain( + `Selected heading
", + }); + editor.commands.setTextSelection({ from: 1, to: 9 }); + + root = createRoot(toolbarElement); + act(() => root!.render(Stable heading
"); + const closeAutoFocus = toolbarElement.querySelectorSelected paragraph
", + }); + editor.commands.setTextSelection({ from: 1, to: 9 }); + + root = createRoot(toolbarElement); + act(() => root!.render(Selected paragraph
"); + }); }); diff --git a/templates/content/app/components/editor/BubbleToolbar.tsx b/templates/content/app/components/editor/BubbleToolbar.tsx index 2cccf27e0f..b7731d920f 100644 --- a/templates/content/app/components/editor/BubbleToolbar.tsx +++ b/templates/content/app/components/editor/BubbleToolbar.tsx @@ -1,15 +1,13 @@ import { useT } from "@agent-native/core/client/i18n"; import { IconBold, + IconCheck, + IconChevronDown, IconItalic, IconStrikethrough, IconCode, IconLink, IconMessageCircle, - IconH1, - IconH2, - IconH3, - IconH4, } from "@tabler/icons-react"; import { NodeSelection, @@ -20,8 +18,13 @@ import { import { Decoration, DecorationSet } from "@tiptap/pm/view"; import type { Editor } from "@tiptap/react"; import { BubbleMenu } from "@tiptap/react/menus"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; import { Tooltip, TooltipContent, @@ -56,6 +59,15 @@ type SelectionFillRange = { to: number; }; +type TextStyle = "paragraph" | 1 | 2 | 3 | 4 | 5 | 6; + +function activeTextStyle(editor: Editor): TextStyle { + for (const level of [1, 2, 3, 4, 5, 6] as const) { + if (editor.isActive("heading", { level })) return level; + } + return "paragraph"; +} + const selectionFillPluginKey = new PluginKey