chore(ui): focus editor when wrapper area is captured (#13525)

* chore(ui): focus editor when wrapper area is captured

* chore: use ref approach for handling editor focus
This commit is contained in:
Sachin Chaurasiya 2023-10-11 21:54:31 +05:30 committed by GitHub
parent 6060c3975d
commit 8d90b54d49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -12,7 +12,12 @@
*/ */
import { Editor, EditorContent, ReactRenderer, useEditor } from '@tiptap/react'; import { Editor, EditorContent, ReactRenderer, useEditor } from '@tiptap/react';
import { isEmpty, isNil } from 'lodash'; import { isEmpty, isNil } from 'lodash';
import React, { FC, useEffect, useState } from 'react'; import React, {
forwardRef,
useEffect,
useImperativeHandle,
useState,
} from 'react';
import tippy, { Instance, Props } from 'tippy.js'; import tippy, { Instance, Props } from 'tippy.js';
import { EDITOR_OPTIONS } from '../../constants/BlockEditor.constants'; import { EDITOR_OPTIONS } from '../../constants/BlockEditor.constants';
import { import {
@ -27,6 +32,9 @@ import ImageModal, { ImageData } from './ImageModal/ImageModal';
import LinkModal, { LinkData } from './LinkModal/LinkModal'; import LinkModal, { LinkData } from './LinkModal/LinkModal';
import LinkPopup from './LinkPopup/LinkPopup'; import LinkPopup from './LinkPopup/LinkPopup';
export interface BlockEditorRef {
onFocus: () => void;
}
export interface BlockEditorProps { export interface BlockEditorProps {
// should be markdown string // should be markdown string
content?: string; content?: string;
@ -35,11 +43,8 @@ export interface BlockEditorProps {
onChange?: (content: string) => void; onChange?: (content: string) => void;
} }
const BlockEditor: FC<BlockEditorProps> = ({ const BlockEditor = forwardRef<BlockEditorRef, BlockEditorProps>(
content = '', ({ content = '', editable = true, onChange }, ref) => {
editable = true,
onChange,
}) => {
const [isLinkModalOpen, setIsLinkModalOpen] = useState<boolean>(false); const [isLinkModalOpen, setIsLinkModalOpen] = useState<boolean>(false);
const [isImageModalOpen, setIsImageModalOpen] = useState<boolean>(false); const [isImageModalOpen, setIsImageModalOpen] = useState<boolean>(false);
@ -108,7 +113,9 @@ const BlockEditor: FC<BlockEditorProps> = ({
editor?.chain().selectTextblockEnd().run(); editor?.chain().selectTextblockEnd().run();
}; };
const handleLinkPopup = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { const handleLinkPopup = (
e: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
let popup: Instance<Props>[] = []; let popup: Instance<Props>[] = [];
let component: ReactRenderer; let component: ReactRenderer;
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
@ -166,6 +173,14 @@ const BlockEditor: FC<BlockEditorProps> = ({
handleImageToggle(); handleImageToggle();
}; };
useImperativeHandle(ref, () => ({
onFocus() {
if (!isNil(editor) && !editor.isFocused) {
editor.commands.focus('end');
}
},
}));
const menus = !isNil(editor) && ( const menus = !isNil(editor) && (
<BubbleMenu editor={editor} toggleLink={handleLinkToggle} /> <BubbleMenu editor={editor} toggleLink={handleLinkToggle} />
); );
@ -188,7 +203,11 @@ const BlockEditor: FC<BlockEditorProps> = ({
}, [content, editor]); }, [content, editor]);
useEffect(() => { useEffect(() => {
if (isNil(editor) || editor.isDestroyed || editor.isEditable === editable) { if (
isNil(editor) ||
editor.isDestroyed ||
editor.isEditable === editable
) {
return; return;
} }
@ -225,6 +244,7 @@ const BlockEditor: FC<BlockEditorProps> = ({
</div> </div>
</> </>
); );
}; }
);
export default BlockEditor; export default BlockEditor;