아래에서 영상으로 보여주겠지만 드래그를 한 상태에서 아무것도 없는 영역을 클릭했을때 사용자는 드래그한 영역이 풀리는 것을 기대한다.
하지만 드래그한 영역이 풀리지 않고 계속 드래그 한 곳을 포커스 해주는 상태를 발견하였다.
우선 코드는 바깥 영역을 클릭해도 input 영역에 포커스가 일어나게 해야했기 때문에 아래와 같이 코드를 작성하였었다.
export default function Tiptap({ text, setText }) {
const editor = useEditor({
extensions: [
StarterKit.configure({
codeBlock: false,
}),
Placeholder.configure({
emptyEditorClass: "is-editor-empty",
placeholder: "회의록을 입력해주세요...",
}),
TextAlign.configure({
types: ["heading", "paragraph"],
}),
Highlight,
Typography,
Indent,
CustomCodeBlockLowlight,
],
content: text,
onUpdate({ editor }) {
setText(editor.getHTML());
},
});
//이쪽 부분을 확인
return (
<>
<div
className="h-full cursor-text overflow-hidden rounded-[20px] border border-solid border-grayscale-500 p-3"
onClick={() => {
editor?.commands.focus();
}
}}
>
<MenuBar editor={editor} />
<EditorContent editor={editor}} />
</div>
</>
);
}
위와 같이 코드를 짜니 바깥 영역을 클릭하니 input이 활성화는 되지만 계속 그 상태를 유지하고 있어 드래그한 요소가 취소되지 않았다.
그래서 이 문제를 해결하기 위해 처음에는 아래와 같이 구현해 보았는데 또 아래와 같이 구현하면 둘다 비동기적으로 작동하기 때문에 blur처리가 되기 전에 focus가 되고 blur처리가 되서 포커스가 사라지는 것을 확인하였다. 그래서 setTimeout으로 감싸거나 그런방식으로 focus가 되게 할 수는 있는데 또 여기서 문제가 blur처리를 한다고 드래그 했던 요소가 취소되는게 아니라 그냥 포커스만 떠나는 거라는 것을 알게되었다.. 그래서 또 다른 방법을 찾아보았..
editor?.commands.blur();
editor?.commands.focus();
먼가 추가적으로 editor의 기능들이 더 있을 것 같아 찾아보다가 https://tiptap.dev/docs/editor/api/commands 위의 문서를 찾을 수 있었다.
우선 blur로는 해결할 수 없기 때문에 제거하고 아래의 방식으로 구현할 수 있었다. 우선 editor를 까보니 엄청나게 많은 변수들과 함수들을 담고 있었고 그 중 드래그한 요소의 시작점과 끝 커서의 위치를 닮고 있는 editor.state.selection의 (from, to)를 활용해 드래그가 끝난 커서의 위치로 돌릴 수 있도록 구현하였다.
그리고 input 쪽에서도 계속 상위의 이벤트가 발생하기 때문에 e.stopPropagation을 통해 발생되지 않도록 막아주었다. 이렇게 해결~~!! 생각보다 많은 것들이 있고 이런것들을 찾으며 해결하다보니 재밌네 :)
return (
<>
<div
className="h-full cursor-text overflow-hidden rounded-[20px] border border-solid border-grayscale-500 p-3"
onClick={(e) => {
if (editor) {
const endPoint = editor.state.selection.to;
editor.chain().focus().setTextSelection(endPoint).run();
}
}}
>
<MenuBar editor={editor} />
<EditorContent editor={editor} onClick={(e) => e.stopPropagation()} />
</div>
</>
);