exported tiptap editor with and without ref

This commit is contained in:
Palanikannan1437 2023-09-20 11:26:16 +05:30
parent 7ef1745e38
commit 3b9c29cfd4
7 changed files with 61 additions and 43 deletions

View File

@ -1,5 +1,5 @@
{ {
"name": "@plane/editor", "name": "plane-editor",
"version": "0.0.1", "version": "0.0.1",
"description": "Rich Text Editor that powers Plane", "description": "Rich Text Editor that powers Plane",
"main": "./dist/index.js", "main": "./dist/index.js",
@ -69,7 +69,7 @@
"eslint": "^7.32.0", "eslint": "^7.32.0",
"postcss": "^8.4.29", "postcss": "^8.4.29",
"react": "^18.2.0", "react": "^18.2.0",
"tailwind-config": "*", "tailwind-config-custom": "*",
"tsconfig": "*", "tsconfig": "*",
"tsup": "^7.2.0", "tsup": "^7.2.0",
"typescript": "4.9.5" "typescript": "4.9.5"
@ -80,5 +80,12 @@
"markdown", "markdown",
"nextjs", "nextjs",
"react" "react"
],
"typesVersions": {
"*": {
"*": [
"src/*"
] ]
}
}
} }

View File

@ -1,4 +1,4 @@
import "@/styles/tailwind.css"; import "@/styles/tailwind.css";
import "@/styles/editor.css"; import "@/styles/editor.css";
export { TipTapEditor } from "@/ui/editor"; export { TiptapEditor, TiptapEditorWithRef } from "@/ui/editor";

View File

@ -10,8 +10,9 @@ import { ImageResizer } from '@/ui/editor/extensions/image/image-resize';
import { TiptapEditorProps } from '@/ui/editor/props'; import { TiptapEditorProps } from '@/ui/editor/props';
import { UploadImage } from '@/types/upload-image'; import { UploadImage } from '@/types/upload-image';
import { DeleteImage } from '@/types/delete-image'; import { DeleteImage } from '@/types/delete-image';
import { cn } from '@/lib/utils';
export interface ITipTapRichTextEditor { interface ITiptapEditor {
value: string; value: string;
uploadFile: UploadImage; uploadFile: UploadImage;
deleteFile: DeleteImage; deleteFile: DeleteImage;
@ -28,11 +29,20 @@ export interface ITipTapRichTextEditor {
debouncedUpdatesEnabled?: boolean; debouncedUpdatesEnabled?: boolean;
} }
const Tiptap = (props: ITipTapRichTextEditor) => { interface TiptapProps extends ITiptapEditor {
const { forwardedRef?: React.Ref<EditorHandle>;
}
interface EditorHandle {
clearEditor: () => void;
setEditorValue: (content: string) => void;
}
const DEBOUNCE_DELAY = 1500;
const TiptapEditor = ({
onChange, onChange,
debouncedUpdatesEnabled, debouncedUpdatesEnabled,
forwardedRef,
editable, editable,
setIsSubmitting, setIsSubmitting,
setShouldShowAlert, setShouldShowAlert,
@ -44,12 +54,12 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
workspaceSlug, workspaceSlug,
borderOnFocus, borderOnFocus,
customClassName, customClassName,
} = props; forwardedRef,
}: TiptapProps) => {
const editor = useEditor({ const editor = useEditor({
editable: editable ?? true, editable: editable ?? true,
editorProps: TiptapEditorProps(workspaceSlug, uploadFile, setIsSubmitting), editorProps: TiptapEditorProps(workspaceSlug, uploadFile, setIsSubmitting),
// @ts-ignore // @ts-expect-error
extensions: TiptapExtensions(workspaceSlug, uploadFile, deleteFile, setIsSubmitting), extensions: TiptapExtensions(workspaceSlug, uploadFile, deleteFile, setIsSubmitting),
content: (typeof value === "string" && value.trim() !== "") ? value : "<p></p>", content: (typeof value === "string" && value.trim() !== "") ? value : "<p></p>",
onUpdate: async ({ editor }) => { onUpdate: async ({ editor }) => {
@ -65,6 +75,7 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
}); });
const editorRef: React.MutableRefObject<Editor | null> = useRef(null); const editorRef: React.MutableRefObject<Editor | null> = useRef(null);
editorRef.current = editor;
useImperativeHandle(forwardedRef, () => ({ useImperativeHandle(forwardedRef, () => ({
clearEditor: () => { clearEditor: () => {
@ -76,19 +87,19 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
})); }));
const debouncedUpdates = useDebouncedCallback(async ({ onChange, editor }) => { const debouncedUpdates = useDebouncedCallback(async ({ onChange, editor }) => {
setTimeout(async () => {
if (onChange) { if (onChange) {
onChange(editor.getJSON(), editor.getHTML()); onChange(editor.getJSON(), editor.getHTML());
} }
}, 500); }, DEBOUNCE_DELAY);
}, 1000);
const editorClassNames = `relative w-full max-w-full sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md const editorClassNames = cn(
${noBorder ? "" : "border border-custom-border-200"} ${borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0" 'relative w-full max-w-full sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md',
} ${customClassName}`; noBorder ? '' : 'border border-custom-border-200',
borderOnFocus ? 'focus:border border-custom-border-300' : 'focus:border-0',
customClassName
);
if (!editor) return null; if (!editor) return null;
editorRef.current = editor;
return ( return (
<div <div
@ -108,10 +119,10 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
); );
}; };
const TipTapEditor = forwardRef<ITipTapRichTextEditor, ITipTapRichTextEditor>((props, ref) => ( const TiptapEditorWithRef = forwardRef<EditorHandle, ITiptapEditor>((props, ref) => (
<Tiptap {...props} forwardedRef={ref} /> <TiptapEditor {...props} forwardedRef={ref} />
)); ));
TipTapEditor.displayName = "TipTapEditor"; TiptapEditorWithRef.displayName = "TiptapEditorWithRef";
export { TipTapEditor }; export { TiptapEditor, TiptapEditorWithRef };

View File

@ -1,4 +1,4 @@
const sharedConfig = require("tailwind-config/tailwind.config.js"); const sharedConfig = require("tailwind-config-custom/tailwind.config.js");
module.exports = { module.exports = {
// prefix ui lib classes to avoid conflicting with the app // prefix ui lib classes to avoid conflicting with the app

View File

@ -9,7 +9,7 @@ import { useDebouncedCallback } from "use-debounce";
import { TextArea } from "components/ui"; import { TextArea } from "components/ui";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
import { TipTapEditor } from "@plane/editor" import { TiptapEditor } from "plane-editor"
import fileService from "services/file.service"; import fileService from "services/file.service";
export interface IssueDescriptionFormValues { export interface IssueDescriptionFormValues {
@ -134,7 +134,7 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
if (!value) return <></>; if (!value) return <></>;
return ( return (
<TipTapEditor <TiptapEditor
uploadFile={fileService.uploadFile} uploadFile={fileService.uploadFile}
deleteFile={fileService.deleteImage} deleteFile={fileService.deleteImage}
value={ value={

View File

@ -26,6 +26,7 @@
"@nivo/pie": "0.80.0", "@nivo/pie": "0.80.0",
"@nivo/scatterplot": "0.80.0", "@nivo/scatterplot": "0.80.0",
"@sentry/nextjs": "^7.36.0", "@sentry/nextjs": "^7.36.0",
"plane-editor": "*",
"@tiptap/extension-code-block-lowlight": "^2.0.4", "@tiptap/extension-code-block-lowlight": "^2.0.4",
"@tiptap/extension-color": "^2.0.4", "@tiptap/extension-color": "^2.0.4",
"@tiptap/extension-gapcursor": "^2.1.7", "@tiptap/extension-gapcursor": "^2.1.7",
@ -79,8 +80,7 @@
"tiptap-markdown": "^0.8.2", "tiptap-markdown": "^0.8.2",
"tlds": "^1.238.0", "tlds": "^1.238.0",
"use-debounce": "^9.0.4", "use-debounce": "^9.0.4",
"uuid": "^9.0.0", "uuid": "^9.0.0"
"@plane/editor": "*"
}, },
"devDependencies": { "devDependencies": {
"@types/js-cookie": "^3.0.2", "@types/js-cookie": "^3.0.2",

View File

@ -1,4 +1,4 @@
const sharedConfig = require("tailwind-config/tailwind.config.js"); const sharedConfig = require("tailwind-config-custom/tailwind.config.js");
module.exports = { module.exports = {
presets: [sharedConfig], presets: [sharedConfig],