forked from github/plane
fixed editor mounting with custom hook
This commit is contained in:
parent
5136f3b329
commit
d714079c1c
@ -1,18 +1,22 @@
|
|||||||
import { useEditor as useCustomEditor, Editor } from "@tiptap/react";
|
import { useEditor as useCustomEditor, Editor } from "@tiptap/react";
|
||||||
import { useImperativeHandle, useRef, MutableRefObject } from "react";
|
import {
|
||||||
import { useDebouncedCallback } from "use-debounce";
|
useImperativeHandle,
|
||||||
import { DeleteImage } from '../../types/delete-image';
|
useRef,
|
||||||
|
MutableRefObject,
|
||||||
|
useEffect,
|
||||||
|
} from "react";
|
||||||
|
import { DeleteImage } from "../../types/delete-image";
|
||||||
import { CoreEditorProps } from "../props";
|
import { CoreEditorProps } from "../props";
|
||||||
import { CoreEditorExtensions } from "../extensions";
|
import { CoreEditorExtensions } from "../extensions";
|
||||||
import { EditorProps } from '@tiptap/pm/view';
|
import { EditorProps } from "@tiptap/pm/view";
|
||||||
import { getTrimmedHTML } from "../../lib/utils";
|
import { getTrimmedHTML } from "../../lib/utils";
|
||||||
import { UploadImage } from "../../types/upload-image";
|
import { UploadImage } from "../../types/upload-image";
|
||||||
|
|
||||||
const DEBOUNCE_DELAY = 1500;
|
|
||||||
|
|
||||||
interface CustomEditorProps {
|
interface CustomEditorProps {
|
||||||
uploadFile: UploadImage;
|
uploadFile: UploadImage;
|
||||||
setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void;
|
setIsSubmitting?: (
|
||||||
|
isSubmitting: "submitting" | "submitted" | "saved",
|
||||||
|
) => void;
|
||||||
setShouldShowAlert?: (showAlert: boolean) => void;
|
setShouldShowAlert?: (showAlert: boolean) => void;
|
||||||
value: string;
|
value: string;
|
||||||
deleteFile: DeleteImage;
|
deleteFile: DeleteImage;
|
||||||
@ -23,26 +27,44 @@ interface CustomEditorProps {
|
|||||||
forwardedRef?: any;
|
forwardedRef?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useEditor = ({ uploadFile, deleteFile, editorProps = {}, value, extensions = [], onChange, setIsSubmitting, debouncedUpdatesEnabled, forwardedRef, setShouldShowAlert, }: CustomEditorProps) => {
|
export const useEditor = ({
|
||||||
|
uploadFile,
|
||||||
|
deleteFile,
|
||||||
|
editorProps = {},
|
||||||
|
value,
|
||||||
|
extensions = [],
|
||||||
|
onChange,
|
||||||
|
setIsSubmitting,
|
||||||
|
forwardedRef,
|
||||||
|
setShouldShowAlert,
|
||||||
|
}: CustomEditorProps) => {
|
||||||
const editor = useCustomEditor({
|
const editor = useCustomEditor({
|
||||||
editorProps: {
|
editorProps: {
|
||||||
...CoreEditorProps(uploadFile, setIsSubmitting),
|
...CoreEditorProps(uploadFile, setIsSubmitting),
|
||||||
...editorProps,
|
...editorProps,
|
||||||
},
|
},
|
||||||
extensions: [...CoreEditorExtensions(deleteFile), ...extensions],
|
extensions: [...CoreEditorExtensions(deleteFile), ...extensions],
|
||||||
content: (typeof value === "string" && value.trim() !== "") ? value : "<p></p>",
|
content:
|
||||||
|
typeof value === "string" && value.trim() !== "" ? value : "<p></p>",
|
||||||
onUpdate: async ({ editor }) => {
|
onUpdate: async ({ editor }) => {
|
||||||
// for instant feedback loop
|
// for instant feedback loop
|
||||||
setIsSubmitting?.("submitting");
|
setIsSubmitting?.("submitting");
|
||||||
setShouldShowAlert?.(true);
|
setShouldShowAlert?.(true);
|
||||||
if (debouncedUpdatesEnabled) {
|
onChange?.(editor.getJSON(), getTrimmedHTML(editor.getHTML()));
|
||||||
debouncedUpdates({ onChange: onChange, editor });
|
|
||||||
} else {
|
|
||||||
onChange?.(editor.getJSON(), getTrimmedHTML(editor.getHTML()));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hasIntiliazedContent = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editor && value!=="" && !hasIntiliazedContent.current) {
|
||||||
|
editor.commands.setContent(
|
||||||
|
typeof value === "string" && value.trim() !== "" ? value : "<p></p>",
|
||||||
|
);
|
||||||
|
hasIntiliazedContent.current = true;
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
const editorRef: MutableRefObject<Editor | null> = useRef(null);
|
const editorRef: MutableRefObject<Editor | null> = useRef(null);
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
|
|
||||||
@ -55,12 +77,6 @@ export const useEditor = ({ uploadFile, deleteFile, editorProps = {}, value, ext
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const debouncedUpdates = useDebouncedCallback(async ({ onChange, editor }) => {
|
|
||||||
if (onChange) {
|
|
||||||
onChange(editor.getJSON(), getTrimmedHTML(editor.getHTML()));
|
|
||||||
}
|
|
||||||
}, DEBOUNCE_DELAY);
|
|
||||||
|
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useEditor as useCustomEditor, Editor } from "@tiptap/react";
|
import { useEditor as useCustomEditor, Editor } from "@tiptap/react";
|
||||||
import { useImperativeHandle, useRef, MutableRefObject } from "react";
|
import { useImperativeHandle, useRef, MutableRefObject, useEffect } from "react";
|
||||||
import { CoreReadOnlyEditorExtensions } from "../../ui/read-only/extensions";
|
import { CoreReadOnlyEditorExtensions } from "../../ui/read-only/extensions";
|
||||||
import { CoreReadOnlyEditorProps } from "../../ui/read-only/props";
|
import { CoreReadOnlyEditorProps } from "../../ui/read-only/props";
|
||||||
import { EditorProps } from '@tiptap/pm/view';
|
import { EditorProps } from "@tiptap/pm/view";
|
||||||
|
|
||||||
interface CustomReadOnlyEditorProps {
|
interface CustomReadOnlyEditorProps {
|
||||||
value: string;
|
value: string;
|
||||||
@ -11,10 +11,16 @@ interface CustomReadOnlyEditorProps {
|
|||||||
editorProps?: EditorProps;
|
editorProps?: EditorProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useReadOnlyEditor = ({ value, forwardedRef, extensions = [], editorProps = {} }: CustomReadOnlyEditorProps) => {
|
export const useReadOnlyEditor = ({
|
||||||
|
value,
|
||||||
|
forwardedRef,
|
||||||
|
extensions = [],
|
||||||
|
editorProps = {},
|
||||||
|
}: CustomReadOnlyEditorProps) => {
|
||||||
const editor = useCustomEditor({
|
const editor = useCustomEditor({
|
||||||
editable: false,
|
editable: false,
|
||||||
content: (typeof value === "string" && value.trim() !== "") ? value : "<p></p>",
|
content:
|
||||||
|
typeof value === "string" && value.trim() !== "" ? value : "<p></p>",
|
||||||
editorProps: {
|
editorProps: {
|
||||||
...CoreReadOnlyEditorProps,
|
...CoreReadOnlyEditorProps,
|
||||||
...editorProps,
|
...editorProps,
|
||||||
@ -22,6 +28,16 @@ export const useReadOnlyEditor = ({ value, forwardedRef, extensions = [], editor
|
|||||||
extensions: [...CoreReadOnlyEditorExtensions, ...extensions],
|
extensions: [...CoreReadOnlyEditorExtensions, ...extensions],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hasIntiliazedContent = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editor && !value && !hasIntiliazedContent.current) {
|
||||||
|
console.log("setting content");
|
||||||
|
editor.commands.setContent(value);
|
||||||
|
hasIntiliazedContent.current = true;
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
const editorRef: MutableRefObject<Editor | null> = useRef(null);
|
const editorRef: MutableRefObject<Editor | null> = useRef(null);
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
|
|
||||||
@ -34,7 +50,6 @@ export const useReadOnlyEditor = ({ value, forwardedRef, extensions = [], editor
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
if (!editor) {
|
if (!editor) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user