forked from github/plane
exported tiptap editor with and without ref
This commit is contained in:
parent
7ef1745e38
commit
3b9c29cfd4
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@plane/editor",
|
||||
"name": "plane-editor",
|
||||
"version": "0.0.1",
|
||||
"description": "Rich Text Editor that powers Plane",
|
||||
"main": "./dist/index.js",
|
||||
@ -69,7 +69,7 @@
|
||||
"eslint": "^7.32.0",
|
||||
"postcss": "^8.4.29",
|
||||
"react": "^18.2.0",
|
||||
"tailwind-config": "*",
|
||||
"tailwind-config-custom": "*",
|
||||
"tsconfig": "*",
|
||||
"tsup": "^7.2.0",
|
||||
"typescript": "4.9.5"
|
||||
@ -80,5 +80,12 @@
|
||||
"markdown",
|
||||
"nextjs",
|
||||
"react"
|
||||
]
|
||||
],
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
"src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import "@/styles/tailwind.css";
|
||||
import "@/styles/editor.css";
|
||||
|
||||
export { TipTapEditor } from "@/ui/editor";
|
||||
export { TiptapEditor, TiptapEditorWithRef } from "@/ui/editor";
|
||||
|
@ -10,8 +10,9 @@ import { ImageResizer } from '@/ui/editor/extensions/image/image-resize';
|
||||
import { TiptapEditorProps } from '@/ui/editor/props';
|
||||
import { UploadImage } from '@/types/upload-image';
|
||||
import { DeleteImage } from '@/types/delete-image';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export interface ITipTapRichTextEditor {
|
||||
interface ITiptapEditor {
|
||||
value: string;
|
||||
uploadFile: UploadImage;
|
||||
deleteFile: DeleteImage;
|
||||
@ -28,28 +29,37 @@ export interface ITipTapRichTextEditor {
|
||||
debouncedUpdatesEnabled?: boolean;
|
||||
}
|
||||
|
||||
const Tiptap = (props: ITipTapRichTextEditor) => {
|
||||
const {
|
||||
onChange,
|
||||
debouncedUpdatesEnabled,
|
||||
forwardedRef,
|
||||
editable,
|
||||
setIsSubmitting,
|
||||
setShouldShowAlert,
|
||||
editorContentCustomClassNames,
|
||||
value,
|
||||
uploadFile,
|
||||
deleteFile,
|
||||
noBorder,
|
||||
workspaceSlug,
|
||||
borderOnFocus,
|
||||
customClassName,
|
||||
} = props;
|
||||
interface TiptapProps extends ITiptapEditor {
|
||||
forwardedRef?: React.Ref<EditorHandle>;
|
||||
}
|
||||
|
||||
interface EditorHandle {
|
||||
clearEditor: () => void;
|
||||
setEditorValue: (content: string) => void;
|
||||
}
|
||||
|
||||
const DEBOUNCE_DELAY = 1500;
|
||||
|
||||
const TiptapEditor = ({
|
||||
onChange,
|
||||
debouncedUpdatesEnabled,
|
||||
editable,
|
||||
setIsSubmitting,
|
||||
setShouldShowAlert,
|
||||
editorContentCustomClassNames,
|
||||
value,
|
||||
uploadFile,
|
||||
deleteFile,
|
||||
noBorder,
|
||||
workspaceSlug,
|
||||
borderOnFocus,
|
||||
customClassName,
|
||||
forwardedRef,
|
||||
}: TiptapProps) => {
|
||||
const editor = useEditor({
|
||||
editable: editable ?? true,
|
||||
editorProps: TiptapEditorProps(workspaceSlug, uploadFile, setIsSubmitting),
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
extensions: TiptapExtensions(workspaceSlug, uploadFile, deleteFile, setIsSubmitting),
|
||||
content: (typeof value === "string" && value.trim() !== "") ? value : "<p></p>",
|
||||
onUpdate: async ({ editor }) => {
|
||||
@ -65,6 +75,7 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
|
||||
});
|
||||
|
||||
const editorRef: React.MutableRefObject<Editor | null> = useRef(null);
|
||||
editorRef.current = editor;
|
||||
|
||||
useImperativeHandle(forwardedRef, () => ({
|
||||
clearEditor: () => {
|
||||
@ -76,19 +87,19 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
|
||||
}));
|
||||
|
||||
const debouncedUpdates = useDebouncedCallback(async ({ onChange, editor }) => {
|
||||
setTimeout(async () => {
|
||||
if (onChange) {
|
||||
onChange(editor.getJSON(), editor.getHTML());
|
||||
}
|
||||
}, 500);
|
||||
}, 1000);
|
||||
if (onChange) {
|
||||
onChange(editor.getJSON(), editor.getHTML());
|
||||
}
|
||||
}, DEBOUNCE_DELAY);
|
||||
|
||||
const editorClassNames = `relative w-full max-w-full sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md
|
||||
${noBorder ? "" : "border border-custom-border-200"} ${borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0"
|
||||
} ${customClassName}`;
|
||||
const editorClassNames = cn(
|
||||
'relative w-full max-w-full sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md',
|
||||
noBorder ? '' : 'border border-custom-border-200',
|
||||
borderOnFocus ? 'focus:border border-custom-border-300' : 'focus:border-0',
|
||||
customClassName
|
||||
);
|
||||
|
||||
if (!editor) return null;
|
||||
editorRef.current = editor;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -108,10 +119,10 @@ const Tiptap = (props: ITipTapRichTextEditor) => {
|
||||
);
|
||||
};
|
||||
|
||||
const TipTapEditor = forwardRef<ITipTapRichTextEditor, ITipTapRichTextEditor>((props, ref) => (
|
||||
<Tiptap {...props} forwardedRef={ref} />
|
||||
const TiptapEditorWithRef = forwardRef<EditorHandle, ITiptapEditor>((props, ref) => (
|
||||
<TiptapEditor {...props} forwardedRef={ref} />
|
||||
));
|
||||
|
||||
TipTapEditor.displayName = "TipTapEditor";
|
||||
TiptapEditorWithRef.displayName = "TiptapEditorWithRef";
|
||||
|
||||
export { TipTapEditor };
|
||||
export { TiptapEditor, TiptapEditorWithRef };
|
||||
|
@ -1,4 +1,4 @@
|
||||
const sharedConfig = require("tailwind-config/tailwind.config.js");
|
||||
const sharedConfig = require("tailwind-config-custom/tailwind.config.js");
|
||||
|
||||
module.exports = {
|
||||
// prefix ui lib classes to avoid conflicting with the app
|
||||
|
@ -9,7 +9,7 @@ import { useDebouncedCallback } from "use-debounce";
|
||||
import { TextArea } from "components/ui";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
import { TipTapEditor } from "@plane/editor"
|
||||
import { TiptapEditor } from "plane-editor"
|
||||
import fileService from "services/file.service";
|
||||
|
||||
export interface IssueDescriptionFormValues {
|
||||
@ -134,7 +134,7 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
||||
if (!value) return <></>;
|
||||
|
||||
return (
|
||||
<TipTapEditor
|
||||
<TiptapEditor
|
||||
uploadFile={fileService.uploadFile}
|
||||
deleteFile={fileService.deleteImage}
|
||||
value={
|
||||
|
@ -26,6 +26,7 @@
|
||||
"@nivo/pie": "0.80.0",
|
||||
"@nivo/scatterplot": "0.80.0",
|
||||
"@sentry/nextjs": "^7.36.0",
|
||||
"plane-editor": "*",
|
||||
"@tiptap/extension-code-block-lowlight": "^2.0.4",
|
||||
"@tiptap/extension-color": "^2.0.4",
|
||||
"@tiptap/extension-gapcursor": "^2.1.7",
|
||||
@ -79,8 +80,7 @@
|
||||
"tiptap-markdown": "^0.8.2",
|
||||
"tlds": "^1.238.0",
|
||||
"use-debounce": "^9.0.4",
|
||||
"uuid": "^9.0.0",
|
||||
"@plane/editor": "*"
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
|
@ -1,4 +1,4 @@
|
||||
const sharedConfig = require("tailwind-config/tailwind.config.js");
|
||||
const sharedConfig = require("tailwind-config-custom/tailwind.config.js");
|
||||
|
||||
module.exports = {
|
||||
presets: [sharedConfig],
|
||||
|
Loading…
Reference in New Issue
Block a user