diff --git a/packages/client/src/tiptap/core/wrappers/title/index.tsx b/packages/client/src/tiptap/core/wrappers/title/index.tsx index b05fba2d..8c3f152a 100644 --- a/packages/client/src/tiptap/core/wrappers/title/index.tsx +++ b/packages/client/src/tiptap/core/wrappers/title/index.tsx @@ -1,9 +1,10 @@ -import { Button, ButtonGroup } from '@douyinfe/semi-ui'; +import { Button } from '@douyinfe/semi-ui'; import { DOCUMENT_COVERS } from '@think/constants'; import { NodeViewContent, NodeViewWrapper } from '@tiptap/react'; import cls from 'classnames'; import { ImageUploader } from 'components/image-uploader'; -import { useCallback } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; +import { createPortal } from 'react-dom'; import { LazyLoadImage } from 'react-lazy-load-image-component'; import styles from './index.module.scss'; @@ -17,6 +18,7 @@ const images = [ ]; export const TitleWrapper = ({ editor, node }) => { + const toolbarRef = useRef(null); const isEditable = editor.isEditable; const { cover } = node.attrs; @@ -39,11 +41,34 @@ export const TitleWrapper = ({ editor, node }) => { setCover(DOCUMENT_COVERS[~~(Math.random() * DOCUMENT_COVERS.length)]); }, [setCover]); + const portals = useMemo(() => { + if (!editor.isEditable) return null; + + if (!toolbarRef.current) { + const editorDOM = editor.view.dom as HTMLDivElement; + const parent = editorDOM.parentElement; + const el = window.document.createElement('div'); + + parent.style.position = 'relative'; + editorDOM.parentNode.insertBefore(el, editorDOM); + toolbarRef.current = el; + } + + return createPortal( +
+ +
, + toolbarRef.current + ); + }, [editor, addRandomCover, cover]); + return ( {cover ? (
- cover + {isEditable ? (
@@ -55,13 +80,7 @@ export const TitleWrapper = ({ editor, node }) => { ) : null}
) : null} - {isEditable && !cover ? ( -
- - {!cover ? : null} - -
- ) : null} + {portals} );