refactor: remove react-hook-form

This commit is contained in:
Aaryan Khandelwal 2024-05-13 01:28:59 +05:30
parent 52fddaec15
commit d131939dfd
9 changed files with 73 additions and 133 deletions

View File

@ -12,12 +12,17 @@ import { insertContentAtSavedSelection } from "src/helpers/insert-content-at-cur
import { EditorMenuItemNames, getEditorMenuItems } from "src/ui/menus/menu-items"; import { EditorMenuItemNames, getEditorMenuItems } from "src/ui/menus/menu-items";
import { EditorRefApi } from "src/types/editor-ref-api"; import { EditorRefApi } from "src/types/editor-ref-api";
import { IMarking, scrollSummary } from "src/helpers/scroll-to-node"; import { IMarking, scrollSummary } from "src/helpers/scroll-to-node";
export type TFileHandler = {
cancel: () => void;
delete: DeleteImage;
upload: UploadImage;
restore: RestoreImage;
};
export interface CustomEditorProps { export interface CustomEditorProps {
id?: string; id?: string;
uploadFile: UploadImage; fileHandler: TFileHandler;
restoreFile: RestoreImage;
deleteFile: DeleteImage;
cancelUploadImage?: () => void;
initialValue?: string; initialValue?: string;
editorClassName: string; editorClassName: string;
// undefined when prop is not passed, null if intentionally passed to stop // undefined when prop is not passed, null if intentionally passed to stop
@ -37,19 +42,16 @@ export interface CustomEditorProps {
} }
export const useEditor = ({ export const useEditor = ({
uploadFile,
id = "", id = "",
deleteFile,
cancelUploadImage,
editorProps = {}, editorProps = {},
initialValue, initialValue,
editorClassName, editorClassName,
value, value,
extensions = [], extensions = [],
fileHandler,
onChange, onChange,
forwardedRef, forwardedRef,
tabIndex, tabIndex,
restoreFile,
handleEditorReady, handleEditorReady,
mentionHandler, mentionHandler,
placeholder, placeholder,
@ -66,10 +68,10 @@ export const useEditor = ({
mentionHighlights: mentionHandler.highlights ?? [], mentionHighlights: mentionHandler.highlights ?? [],
}, },
fileConfig: { fileConfig: {
deleteFile, uploadFile: fileHandler.upload,
restoreFile, deleteFile: fileHandler.delete,
cancelUploadImage, restoreFile: fileHandler.restore,
uploadFile, cancelUploadImage: fileHandler.cancel,
}, },
placeholder, placeholder,
tabIndex, tabIndex,
@ -138,7 +140,7 @@ export const useEditor = ({
} }
}, },
executeMenuItemCommand: (itemName: EditorMenuItemNames) => { executeMenuItemCommand: (itemName: EditorMenuItemNames) => {
const editorItems = getEditorMenuItems(editorRef.current, uploadFile); const editorItems = getEditorMenuItems(editorRef.current, fileHandler.upload);
const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName); const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName);
@ -154,7 +156,7 @@ export const useEditor = ({
} }
}, },
isMenuItemActive: (itemName: EditorMenuItemNames): boolean => { isMenuItemActive: (itemName: EditorMenuItemNames): boolean => {
const editorItems = getEditorMenuItems(editorRef.current, uploadFile); const editorItems = getEditorMenuItems(editorRef.current, fileHandler.upload);
const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName); const getEditorMenuItem = (itemName: EditorMenuItemNames) => editorItems.find((item) => item.key === itemName);
const item = getEditorMenuItem(itemName); const item = getEditorMenuItem(itemName);
@ -198,7 +200,7 @@ export const useEditor = ({
} }
}, },
}), }),
[editorRef, savedSelection, uploadFile] [editorRef, savedSelection, fileHandler.upload]
); );
if (!editor) { if (!editor) {

View File

@ -24,7 +24,7 @@ export * from "src/ui/menus/menu-items";
export * from "src/lib/editor-commands"; export * from "src/lib/editor-commands";
// types // types
export type { CustomEditorProps } from "src/hooks/use-editor"; export type { CustomEditorProps, TFileHandler } from "src/hooks/use-editor";
export type { DeleteImage } from "src/types/delete-image"; export type { DeleteImage } from "src/types/delete-image";
export type { UploadImage } from "src/types/upload-image"; export type { UploadImage } from "src/types/upload-image";
export type { EditorRefApi, EditorReadOnlyRefApi } from "src/types/editor-ref-api"; export type { EditorRefApi, EditorReadOnlyRefApi } from "src/types/editor-ref-api";

View File

@ -1,25 +1,17 @@
import { useLayoutEffect, useMemo } from "react"; import { useLayoutEffect, useMemo } from "react";
import {
DeleteImage,
EditorRefApi,
IMentionHighlight,
IMentionSuggestion,
RestoreImage,
UploadImage,
useEditor,
} from "@plane/editor-core";
import * as Y from "yjs";
import { CollaborationProvider } from "src/providers/collaboration-provider";
import { DocumentEditorExtensions } from "src/ui/extensions";
import { IndexeddbPersistence } from "y-indexeddb";
import { EditorProps } from "@tiptap/pm/view"; import { EditorProps } from "@tiptap/pm/view";
import { IndexeddbPersistence } from "y-indexeddb";
import * as Y from "yjs";
// editor-core
import { EditorRefApi, IMentionHighlight, IMentionSuggestion, TFileHandler, useEditor } from "@plane/editor-core";
// custom provider
import { CollaborationProvider } from "src/providers/collaboration-provider";
// extensions
import { DocumentEditorExtensions } from "src/ui/extensions";
type DocumentEditorProps = { type DocumentEditorProps = {
id?: string; id?: string;
uploadFile: UploadImage; fileHandler: TFileHandler;
restoreFile: RestoreImage;
deleteFile: DeleteImage;
cancelUploadImage?: () => void;
value: Uint8Array; value: Uint8Array;
editorClassName: string; editorClassName: string;
onChange: (binaryString: string, html: string) => void; onChange: (binaryString: string, html: string) => void;
@ -37,17 +29,14 @@ type DocumentEditorProps = {
}; };
export const useDocumentEditor = ({ export const useDocumentEditor = ({
uploadFile,
id = "", id = "",
deleteFile,
cancelUploadImage,
editorProps = {}, editorProps = {},
value, value,
editorClassName, editorClassName,
fileHandler,
onChange, onChange,
forwardedRef, forwardedRef,
tabIndex, tabIndex,
restoreFile,
handleEditorReady, handleEditorReady,
mentionHandler, mentionHandler,
placeholder, placeholder,
@ -81,15 +70,12 @@ export const useDocumentEditor = ({
id, id,
editorProps, editorProps,
editorClassName, editorClassName,
restoreFile, fileHandler,
uploadFile,
deleteFile,
cancelUploadImage,
handleEditorReady, handleEditorReady,
forwardedRef, forwardedRef,
mentionHandler, mentionHandler,
extensions: DocumentEditorExtensions({ extensions: DocumentEditorExtensions({
uploadFile, uploadFile: fileHandler.upload,
setHideDragHandle: setHideDragHandleFunction, setHideDragHandle: setHideDragHandleFunction,
provider, provider,
}), }),

View File

@ -26,11 +26,7 @@ export class CollaborationProvider {
onChange: () => {}, onChange: () => {},
}; };
intervals: any = { timeoutId: NodeJS.Timeout | null;
forceSync: null,
};
timeoutId: any;
constructor(configuration: CollaborationProviderConfiguration) { constructor(configuration: CollaborationProviderConfiguration) {
this.setConfiguration(configuration); this.setConfiguration(configuration);
@ -53,6 +49,7 @@ export class CollaborationProvider {
} }
documentUpdateHandler(update: Uint8Array, origin: any) { documentUpdateHandler(update: Uint8Array, origin: any) {
// return if the update is from the provider itself
if (origin === this) return; if (origin === this) return;
// debounce onChange call // debounce onChange call

View File

@ -1,25 +1,21 @@
import React, { useState } from "react"; import React, { useState } from "react";
// editor-core
import { import {
UploadImage,
DeleteImage,
RestoreImage,
getEditorClassNames, getEditorClassNames,
EditorRefApi, EditorRefApi,
IMentionHighlight, IMentionHighlight,
IMentionSuggestion, IMentionSuggestion,
TFileHandler,
} from "@plane/editor-core"; } from "@plane/editor-core";
// components
import { PageRenderer } from "src/ui/components/page-renderer"; import { PageRenderer } from "src/ui/components/page-renderer";
// hooks
import { useDocumentEditor } from "src/hooks/use-document-editor"; import { useDocumentEditor } from "src/hooks/use-document-editor";
interface IDocumentEditor { interface IDocumentEditor {
id: string; id: string;
value: Uint8Array; value: Uint8Array;
fileHandler: { fileHandler: TFileHandler;
cancel: () => void;
delete: DeleteImage;
upload: UploadImage;
restore: RestoreImage;
};
handleEditorReady?: (value: boolean) => void; handleEditorReady?: (value: boolean) => void;
containerClassName?: string; containerClassName?: string;
editorClassName?: string; editorClassName?: string;
@ -61,10 +57,7 @@ const DocumentEditor = (props: IDocumentEditor) => {
const editor = useDocumentEditor({ const editor = useDocumentEditor({
id, id,
editorClassName, editorClassName,
restoreFile: fileHandler.restore, fileHandler,
uploadFile: fileHandler.upload,
deleteFile: fileHandler.delete,
cancelUploadImage: fileHandler.cancel,
value, value,
onChange, onChange,
handleEditorReady, handleEditorReady,

View File

@ -1,27 +1,22 @@
import * as React from "react"; import * as React from "react";
// editor-core
import { import {
UploadImage,
DeleteImage,
IMentionSuggestion, IMentionSuggestion,
RestoreImage,
EditorContainer, EditorContainer,
EditorContentWrapper, EditorContentWrapper,
getEditorClassNames, getEditorClassNames,
useEditor, useEditor,
IMentionHighlight, IMentionHighlight,
EditorRefApi, EditorRefApi,
TFileHandler,
} from "@plane/editor-core"; } from "@plane/editor-core";
// extensions
import { LiteTextEditorExtensions } from "src/ui/extensions"; import { LiteTextEditorExtensions } from "src/ui/extensions";
export interface ILiteTextEditor { export interface ILiteTextEditor {
initialValue: string; initialValue: string;
value?: string | null; value?: string | null;
fileHandler: { fileHandler: TFileHandler;
cancel: () => void;
delete: DeleteImage;
upload: UploadImage;
restore: RestoreImage;
};
containerClassName?: string; containerClassName?: string;
editorClassName?: string; editorClassName?: string;
onChange?: (json: object, html: string) => void; onChange?: (json: object, html: string) => void;
@ -58,10 +53,7 @@ const LiteTextEditor = (props: ILiteTextEditor) => {
value, value,
id, id,
editorClassName, editorClassName,
restoreFile: fileHandler.restore, fileHandler,
uploadFile: fileHandler.upload,
deleteFile: fileHandler.delete,
cancelUploadImage: fileHandler.cancel,
forwardedRef, forwardedRef,
extensions: LiteTextEditorExtensions(onEnterKeyPress), extensions: LiteTextEditorExtensions(onEnterKeyPress),
mentionHandler, mentionHandler,

View File

@ -1,30 +1,26 @@
"use client"; "use client";
import * as React from "react";
// editor-core
import { import {
DeleteImage,
EditorContainer, EditorContainer,
EditorContentWrapper, EditorContentWrapper,
getEditorClassNames, getEditorClassNames,
IMentionHighlight, IMentionHighlight,
IMentionSuggestion, IMentionSuggestion,
RestoreImage,
UploadImage,
useEditor, useEditor,
EditorRefApi, EditorRefApi,
TFileHandler,
} from "@plane/editor-core"; } from "@plane/editor-core";
import * as React from "react"; // extensions
import { RichTextEditorExtensions } from "src/ui/extensions"; import { RichTextEditorExtensions } from "src/ui/extensions";
// components
import { EditorBubbleMenu } from "src/ui/menus/bubble-menu"; import { EditorBubbleMenu } from "src/ui/menus/bubble-menu";
export type IRichTextEditor = { export type IRichTextEditor = {
initialValue: string; initialValue: string;
value?: string | null; value?: string | null;
dragDropEnabled?: boolean; dragDropEnabled?: boolean;
fileHandler: { fileHandler: TFileHandler;
cancel: () => void;
delete: DeleteImage;
upload: UploadImage;
restore: RestoreImage;
};
id?: string; id?: string;
containerClassName?: string; containerClassName?: string;
editorClassName?: string; editorClassName?: string;
@ -67,10 +63,7 @@ const RichTextEditor = (props: IRichTextEditor) => {
const editor = useEditor({ const editor = useEditor({
id, id,
editorClassName, editorClassName,
restoreFile: fileHandler.restore, fileHandler,
uploadFile: fileHandler.upload,
deleteFile: fileHandler.delete,
cancelUploadImage: fileHandler.cancel,
onChange, onChange,
initialValue, initialValue,
value, value,

View File

@ -1,7 +1,6 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { Control, Controller } from "react-hook-form";
import useSWR from "swr"; import useSWR from "swr";
// document editor // document editor
import { import {
@ -12,7 +11,7 @@ import {
IMarking, IMarking,
} from "@plane/document-editor"; } from "@plane/document-editor";
// types // types
import { IUserLite, TPage } from "@plane/types"; import { IUserLite } from "@plane/types";
// components // components
import { PageContentBrowser, PageContentLoader, PageEditorTitle } from "@/components/pages"; import { PageContentBrowser, PageContentLoader, PageEditorTitle } from "@/components/pages";
// helpers // helpers
@ -31,7 +30,6 @@ import { IPageStore } from "@/store/pages/page.store";
const fileService = new FileService(); const fileService = new FileService();
type Props = { type Props = {
control: Control<TPage, any>;
editorRef: React.RefObject<EditorRefApi>; editorRef: React.RefObject<EditorRefApi>;
readOnlyEditorRef: React.RefObject<EditorReadOnlyRefApi>; readOnlyEditorRef: React.RefObject<EditorReadOnlyRefApi>;
handleDescriptionUpdate: (binaryString: string, descriptionHTML: string) => Promise<void>; handleDescriptionUpdate: (binaryString: string, descriptionHTML: string) => Promise<void>;
@ -45,7 +43,6 @@ type Props = {
export const PageEditorBody: React.FC<Props> = observer((props) => { export const PageEditorBody: React.FC<Props> = observer((props) => {
const { const {
control,
handleReadOnlyEditorReady, handleReadOnlyEditorReady,
handleDescriptionUpdate, handleDescriptionUpdate,
handleEditorReady, handleEditorReady,
@ -135,30 +132,24 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
/> />
</div> </div>
{isContentEditable ? ( {isContentEditable ? (
<Controller <DocumentEditorWithRef
name="description_html" id={pageId}
control={control} fileHandler={{
render={() => ( cancel: fileService.cancelUpload,
<DocumentEditorWithRef delete: fileService.getDeleteImageFunction(workspaceId),
id={pageId} restore: fileService.getRestoreImageFunction(workspaceId),
fileHandler={{ upload: fileService.getUploadFileFunction(workspaceSlug as string, setIsSubmitting),
cancel: fileService.cancelUpload, }}
delete: fileService.getDeleteImageFunction(workspaceId), handleEditorReady={handleEditorReady}
restore: fileService.getRestoreImageFunction(workspaceId), value={pageDescriptionYJS}
upload: fileService.getUploadFileFunction(workspaceSlug as string, setIsSubmitting), ref={editorRef}
}} containerClassName="p-0 pb-64"
handleEditorReady={handleEditorReady} editorClassName="pl-10"
value={pageDescriptionYJS} onChange={handleDescriptionUpdate}
ref={editorRef} mentionHandler={{
containerClassName="p-0 pb-64" highlights: mentionHighlights,
editorClassName="lg:px-10 pl-8" suggestions: mentionSuggestions,
onChange={handleDescriptionUpdate} }}
mentionHandler={{
highlights: mentionHighlights,
suggestions: mentionSuggestions,
}}
/>
)}
/> />
) : ( ) : (
<DocumentReadOnlyEditorWithRef <DocumentReadOnlyEditorWithRef
@ -166,7 +157,7 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
initialValue={pageDescription ?? "<p></p>"} initialValue={pageDescription ?? "<p></p>"}
handleEditorReady={handleReadOnlyEditorReady} handleEditorReady={handleReadOnlyEditorReady}
containerClassName="p-0 pb-64 border-none" containerClassName="p-0 pb-64 border-none"
editorClassName="lg:px-10 pl-8" editorClassName="pl-10"
mentionHandler={{ mentionHandler={{
highlights: mentionHighlights, highlights: mentionHighlights,
}} }}

View File

@ -2,7 +2,6 @@ import { ReactElement, useCallback, useRef, useState } from "react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useForm } from "react-hook-form";
import useSWR from "swr"; import useSWR from "swr";
// document-editor // document-editor
import { EditorRefApi, useEditorMarkings } from "@plane/document-editor"; import { EditorRefApi, useEditorMarkings } from "@plane/document-editor";
@ -41,15 +40,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const { description_html, id, name, setIsSubmitting, updateDescription } = pageStore; const { description_html, id, name, setIsSubmitting, updateDescription } = pageStore;
// editor markings hook // editor markings hook
const { markings, updateMarkings } = useEditorMarkings(); const { markings, updateMarkings } = useEditorMarkings();
// form info // fetch page details
const { getValues, control } = useForm<TPage>({
defaultValues: {
name: "",
description_html: "",
},
});
// fetching page details
const { error: pageDetailsError } = useSWR( const { error: pageDetailsError } = useSWR(
pageId ? `PAGE_DETAILS_${pageId}` : null, pageId ? `PAGE_DETAILS_${pageId}` : null,
pageId ? () => getPageById(pageId.toString()) : null, pageId ? () => getPageById(pageId.toString()) : null,
@ -70,7 +61,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
if ((!pageStore || !id) && !pageDetailsError) if ((!pageStore || !id) && !pageDetailsError)
return ( return (
<div className="h-full w-full grid place-items-center"> <div className="size-full grid place-items-center">
<Spinner /> <Spinner />
</div> </div>
); );
@ -94,13 +85,9 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const handleCreatePage = async (payload: Partial<TPage>) => await createPage(payload); const handleCreatePage = async (payload: Partial<TPage>) => await createPage(payload);
const handleDuplicatePage = async () => { const handleDuplicatePage = async () => {
const currentPageValues = getValues();
if (!currentPageValues?.description_html) currentPageValues.description_html = description_html;
const formData: Partial<TPage> = { const formData: Partial<TPage> = {
name: "Copy of " + name, name: "Copy of " + name,
description_html: currentPageValues.description_html, description_html: description_html ?? "<p></p>",
}; };
await handleCreatePage(formData) await handleCreatePage(formData)
@ -134,7 +121,6 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
/> />
)} )}
<PageEditorBody <PageEditorBody
control={control}
editorRef={editorRef} editorRef={editorRef}
handleEditorReady={(val) => setEditorReady(val)} handleEditorReady={(val) => setEditorReady(val)}
readOnlyEditorRef={readOnlyEditorRef} readOnlyEditorRef={readOnlyEditorRef}