From cb7b4de9fec4d81baec1dc8fe2b1ad7b7e1fa769 Mon Sep 17 00:00:00 2001 From: hudy9x <95471659+hudy9x@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:06:43 +0700 Subject: [PATCH] refactor: enable bubble menu for text editor in task detail (#166) --- .../TextEditorControl/BubbleEditorMenu.tsx | 119 ++++++++++++++++++ .../Controls/TextEditorControl/index.tsx | 23 ++-- .../Controls/TextEditorControl/style.css | 29 +++++ 3 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 packages/shared-ui/src/components/Controls/TextEditorControl/BubbleEditorMenu.tsx diff --git a/packages/shared-ui/src/components/Controls/TextEditorControl/BubbleEditorMenu.tsx b/packages/shared-ui/src/components/Controls/TextEditorControl/BubbleEditorMenu.tsx new file mode 100644 index 00000000..79294eff --- /dev/null +++ b/packages/shared-ui/src/components/Controls/TextEditorControl/BubbleEditorMenu.tsx @@ -0,0 +1,119 @@ +import { BubbleMenu, Editor } from "@tiptap/react"; +import { LuBold, LuItalic, LuStrikethrough, LuList, LuListOrdered, LuHeading1, LuHeading2, LuHeading3, LuCode2, LuCornerUpLeft, LuImage } from "react-icons/lu"; +import Tooltip from "../../Tooltip"; +import { useCallback } from "react"; + +export default function BubbleEditorMenu({ editor }: { editor: Editor }) { + const getClasses = (isActive: boolean) => { + const classes = [] + + classes.push('bubble-action-btn') + + isActive && classes.push('is-active') + return classes.join(' ') + } + + + const setImage = useCallback(() => { + const url = window.prompt('Image url:') + if (url) { + editor.chain().focus().setImage({ src: url }).run() + } + + }, [editor]) + + return +
+ editor.chain().focus().toggleHeading({ level: 1 }).run()} + className={getClasses(editor.isActive('heading', { level: 1 }))} + > + + + editor.chain().focus().toggleHeading({ level: 2 }).run()} + className={getClasses(editor.isActive('heading', { level: 2 }))} + > + + + + editor.chain().focus().toggleHeading({ level: 3 }).run()} + className={getClasses(editor.isActive('heading', { level: 3 }))} + > + + + + + editor.chain().focus().toggleCodeBlock().run()} + className={getClasses(editor.isActive('codeBlock'))} + > + + + + + + + editor.chain().focus().toggleBulletList().run()} + className={getClasses(editor.isActive('bulletList'))} + > + + + + + + + editor.chain().focus().toggleOrderedList().run()} + className={getClasses(editor.isActive('orderedList'))} + > + + + + + + editor.chain().focus().toggleBold().run()} + className={getClasses(editor.isActive('bold'))} + > + + + + + + editor.chain().focus().toggleItalic().run()} + className={getClasses(editor.isActive('italic'))} + > + + + + + + editor.chain().focus().toggleStrike().run()} + className={getClasses(editor.isActive('strike'))} + > + + + + + + + + + editor.chain().focus().setHardBreak().run()} + className="bubble-action-btn" + > + + + +
+
+} diff --git a/packages/shared-ui/src/components/Controls/TextEditorControl/index.tsx b/packages/shared-ui/src/components/Controls/TextEditorControl/index.tsx index 46a23bd5..9f9625b9 100644 --- a/packages/shared-ui/src/components/Controls/TextEditorControl/index.tsx +++ b/packages/shared-ui/src/components/Controls/TextEditorControl/index.tsx @@ -1,12 +1,15 @@ import { ChangeEvent, useEffect, useState } from 'react' -import { useEditor, EditorContent } from '@tiptap/react' +import { useEditor, EditorContent, BubbleMenu } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import Link from '@tiptap/extension-link' +import Image from "@tiptap/extension-image"; +import { TextareaProps, TexteditorProps } from '../type' +import { LuBold, LuItalic, LuStrikethrough, LuListOrdered, LuList } from "react-icons/lu"; import './style.css' +import BubbleEditorMenu from './BubbleEditorMenu' -import { TextareaProps, TexteditorProps } from '../type' export default function TextareaControl({ title, @@ -28,7 +31,7 @@ export default function TextareaControl({ // }; const editor = useEditor({ - extensions: [StarterKit, Link.configure({ openOnClick: false })], + extensions: [StarterKit, Image, Link.configure({ openOnClick: false })], content: val, editable: !disabled, onUpdate: ({ editor }) => { @@ -51,24 +54,16 @@ export default function TextareaControl({ readOnly && classes.push('readonly') error && classes.push('error') + return (
{title ? : null}
+ {editor && + }
- {/*