From d3f4786408257114a0bed18c5cba65143cbd84b7 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Wed, 18 Jun 2025 14:53:45 +0530 Subject: [PATCH 1/4] refactor: editor props structure --- .../src/ce/extensions/core/extensions.ts | 9 +- .../extensions/core/read-only-extensions.ts | 8 +- .../src/ce/extensions/document-extensions.tsx | 28 +++--- .../ce/extensions/rich-text/extensions.tsx | 19 ++-- .../rich-text/read-only-extensions.tsx | 10 +-- .../src/ce/extensions/slash-commands.tsx | 8 +- .../editors/document/collaborative-editor.tsx | 8 +- .../editors/document/page-renderer.tsx | 4 +- .../editors/document/read-only-editor.tsx | 31 ++----- .../components/editors/editor-wrapper.tsx | 2 + .../components/editors/lite-text/editor.tsx | 22 ++--- .../editors/lite-text/read-only-editor.tsx | 4 +- .../editors/read-only-editor-wrapper.tsx | 2 + .../components/editors/rich-text/editor.tsx | 14 +-- .../editors/rich-text/read-only-editor.tsx | 19 ++-- .../editor/src/core/extensions/extensions.ts | 24 +++-- .../core/extensions/read-only-extensions.ts | 11 +-- .../slash-commands/command-items-list.tsx | 3 +- .../core/extensions/slash-commands/root.tsx | 5 +- .../editor/src/core/extensions/utility.ts | 5 +- .../core/hooks/use-collaborative-editor.ts | 13 +-- packages/editor/src/core/hooks/use-editor.ts | 51 +++-------- .../src/core/hooks/use-read-only-editor.ts | 38 +++----- .../editor/src/core/types/collaboration.ts | 46 ---------- packages/editor/src/core/types/config.ts | 15 ++++ packages/editor/src/core/types/editor.ts | 88 +++++++------------ packages/editor/src/core/types/hook.ts | 42 +++++++++ packages/editor/src/core/types/index.ts | 1 + packages/editor/src/index.ts | 1 - web/ce/hooks/use-editor-flagging.ts | 38 +++++--- .../lite-text-editor/lite-text-editor.tsx | 14 +-- .../lite-text-read-only-editor.tsx | 11 +-- .../rich-text-editor/rich-text-editor.tsx | 12 ++- .../rich-text-read-only-editor.tsx | 11 +-- .../editor/sticky-editor/editor.tsx | 9 +- .../components/pages/editor/editor-body.tsx | 5 +- web/core/components/pages/version/editor.tsx | 5 +- 37 files changed, 304 insertions(+), 332 deletions(-) create mode 100644 packages/editor/src/core/types/hook.ts diff --git a/packages/editor/src/ce/extensions/core/extensions.ts b/packages/editor/src/ce/extensions/core/extensions.ts index cecfb38b475..5d1f5c9b598 100644 --- a/packages/editor/src/ce/extensions/core/extensions.ts +++ b/packages/editor/src/ce/extensions/core/extensions.ts @@ -1,11 +1,8 @@ -import { Extensions } from "@tiptap/core"; +import type { Extensions } from "@tiptap/core"; // types -import { TExtensions, TFileHandler } from "@/types"; +import type { IEditorProps } from "@/types"; -type Props = { - disabledExtensions: TExtensions[]; - fileHandler: TFileHandler; -}; +type Props = Pick; export const CoreEditorAdditionalExtensions = (props: Props): Extensions => { const {} = props; diff --git a/packages/editor/src/ce/extensions/core/read-only-extensions.ts b/packages/editor/src/ce/extensions/core/read-only-extensions.ts index 398848e31d8..87868d955ef 100644 --- a/packages/editor/src/ce/extensions/core/read-only-extensions.ts +++ b/packages/editor/src/ce/extensions/core/read-only-extensions.ts @@ -1,10 +1,8 @@ -import { Extensions } from "@tiptap/core"; +import type { Extensions } from "@tiptap/core"; // types -import { TExtensions } from "@/types"; +import type { IReadOnlyEditorProps } from "@/types"; -type Props = { - disabledExtensions: TExtensions[]; -}; +type Props = Pick; export const CoreReadOnlyEditorAdditionalExtensions = (props: Props): Extensions => { const {} = props; diff --git a/packages/editor/src/ce/extensions/document-extensions.tsx b/packages/editor/src/ce/extensions/document-extensions.tsx index da2790b2a4f..8815e2d26e9 100644 --- a/packages/editor/src/ce/extensions/document-extensions.tsx +++ b/packages/editor/src/ce/extensions/document-extensions.tsx @@ -1,37 +1,39 @@ -import { HocuspocusProvider } from "@hocuspocus/provider"; -import { AnyExtension } from "@tiptap/core"; +import type { HocuspocusProvider } from "@hocuspocus/provider"; +import type { AnyExtension } from "@tiptap/core"; import { SlashCommands } from "@/extensions"; // plane editor types -import { TEmbedConfig } from "@/plane-editor/types"; +import type { TEmbedConfig } from "@/plane-editor/types"; // types -import { TExtensions, TFileHandler, TUserDetails } from "@/types"; +import type { IEditorProps, TExtensions, TUserDetails } from "@/types"; -export type TDocumentEditorAdditionalExtensionsProps = { - disabledExtensions: TExtensions[]; +export type TDocumentEditorAdditionalExtensionsProps = Pick< + IEditorProps, + "disabledExtensions" | "flaggedExtensions" | "fileHandler" +> & { embedConfig: TEmbedConfig | undefined; - fileHandler: TFileHandler; provider?: HocuspocusProvider; userDetails: TUserDetails; }; export type TDocumentEditorAdditionalExtensionsRegistry = { - isEnabled: (disabledExtensions: TExtensions[]) => boolean; + isEnabled: (disabledExtensions: TExtensions[], flaggedExtensions: TExtensions[]) => boolean; getExtension: (props: TDocumentEditorAdditionalExtensionsProps) => AnyExtension; }; const extensionRegistry: TDocumentEditorAdditionalExtensionsRegistry[] = [ { isEnabled: (disabledExtensions) => !disabledExtensions.includes("slash-commands"), - getExtension: ({ disabledExtensions }) => SlashCommands({ disabledExtensions }), + getExtension: ({ disabledExtensions, flaggedExtensions }) => + SlashCommands({ disabledExtensions, flaggedExtensions }), }, ]; -export const DocumentEditorAdditionalExtensions = (_props: TDocumentEditorAdditionalExtensionsProps) => { - const { disabledExtensions = [] } = _props; +export const DocumentEditorAdditionalExtensions = (props: TDocumentEditorAdditionalExtensionsProps) => { + const { disabledExtensions, flaggedExtensions } = props; const documentExtensions = extensionRegistry - .filter((config) => config.isEnabled(disabledExtensions)) - .map((config) => config.getExtension(_props)); + .filter((config) => config.isEnabled(disabledExtensions, flaggedExtensions)) + .map((config) => config.getExtension(props)); return documentExtensions; }; diff --git a/packages/editor/src/ce/extensions/rich-text/extensions.tsx b/packages/editor/src/ce/extensions/rich-text/extensions.tsx index 0eedd1e87fe..520dfa10e87 100644 --- a/packages/editor/src/ce/extensions/rich-text/extensions.tsx +++ b/packages/editor/src/ce/extensions/rich-text/extensions.tsx @@ -2,19 +2,19 @@ import { AnyExtension, Extensions } from "@tiptap/core"; // extensions import { SlashCommands } from "@/extensions/slash-commands/root"; // types -import { TExtensions, TFileHandler } from "@/types"; +import { IEditorProps, TExtensions } from "@/types"; -export type TRichTextEditorAdditionalExtensionsProps = { - disabledExtensions: TExtensions[]; - fileHandler: TFileHandler; -}; +export type TRichTextEditorAdditionalExtensionsProps = Pick< + IEditorProps, + "disabledExtensions" | "flaggedExtensions" | "fileHandler" +>; /** * Registry entry configuration for extensions */ export type TRichTextEditorAdditionalExtensionsRegistry = { /** Determines if the extension should be enabled based on disabled extensions */ - isEnabled: (disabledExtensions: TExtensions[]) => boolean; + isEnabled: (disabledExtensions: TExtensions[], flaggedExtensions: TExtensions[]) => boolean; /** Returns the extension instance(s) when enabled */ getExtension: (props: TRichTextEditorAdditionalExtensionsProps) => AnyExtension | undefined; }; @@ -22,18 +22,19 @@ export type TRichTextEditorAdditionalExtensionsRegistry = { const extensionRegistry: TRichTextEditorAdditionalExtensionsRegistry[] = [ { isEnabled: (disabledExtensions) => !disabledExtensions.includes("slash-commands"), - getExtension: ({ disabledExtensions }) => + getExtension: ({ disabledExtensions, flaggedExtensions }) => SlashCommands({ disabledExtensions, + flaggedExtensions, }), }, ]; export const RichTextEditorAdditionalExtensions = (props: TRichTextEditorAdditionalExtensionsProps) => { - const { disabledExtensions } = props; + const { disabledExtensions, flaggedExtensions } = props; const extensions: Extensions = extensionRegistry - .filter((config) => config.isEnabled(disabledExtensions)) + .filter((config) => config.isEnabled(disabledExtensions, flaggedExtensions)) .map((config) => config.getExtension(props)) .filter((extension): extension is AnyExtension => extension !== undefined); diff --git a/packages/editor/src/ce/extensions/rich-text/read-only-extensions.tsx b/packages/editor/src/ce/extensions/rich-text/read-only-extensions.tsx index 01563011707..0b7cbc7306d 100644 --- a/packages/editor/src/ce/extensions/rich-text/read-only-extensions.tsx +++ b/packages/editor/src/ce/extensions/rich-text/read-only-extensions.tsx @@ -1,11 +1,11 @@ import { AnyExtension, Extensions } from "@tiptap/core"; // types -import { TExtensions, TReadOnlyFileHandler } from "@/types"; +import { IReadOnlyEditorProps, TExtensions } from "@/types"; -export type TRichTextReadOnlyEditorAdditionalExtensionsProps = { - disabledExtensions: TExtensions[]; - fileHandler: TReadOnlyFileHandler; -}; +export type TRichTextReadOnlyEditorAdditionalExtensionsProps = Pick< + IReadOnlyEditorProps, + "disabledExtensions" | "flaggedExtensions" | "fileHandler" +>; /** * Registry entry configuration for extensions diff --git a/packages/editor/src/ce/extensions/slash-commands.tsx b/packages/editor/src/ce/extensions/slash-commands.tsx index faefa74523c..d61d056c8db 100644 --- a/packages/editor/src/ce/extensions/slash-commands.tsx +++ b/packages/editor/src/ce/extensions/slash-commands.tsx @@ -1,11 +1,9 @@ // extensions -import { TSlashCommandAdditionalOption } from "@/extensions"; +import type { TSlashCommandAdditionalOption } from "@/extensions"; // types -import { TExtensions } from "@/types"; +import type { IEditorProps } from "@/types"; -type Props = { - disabledExtensions?: TExtensions[]; -}; +type Props = Pick; export const coreEditorAdditionalSlashCommandOptions = (props: Props): TSlashCommandAdditionalOption[] => { const {} = props; diff --git a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx index d1398ff5ae1..2fa9f3a5688 100644 --- a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx +++ b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx @@ -13,9 +13,9 @@ import { getEditorClassNames } from "@/helpers/common"; // hooks import { useCollaborativeEditor } from "@/hooks/use-collaborative-editor"; // types -import { EditorRefApi, ICollaborativeDocumentEditor } from "@/types"; +import { EditorRefApi, ICollaborativeDocumentEditorProps } from "@/types"; -const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => { +const CollaborativeDocumentEditor: React.FC = (props) => { const { onTransaction, aiHandler, @@ -27,6 +27,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => { editorClassName = "", embedHandler, fileHandler, + flaggedExtensions, forwardedRef, handleEditorReady, id, @@ -56,6 +57,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => { embedHandler, extensions, fileHandler, + flaggedExtensions, forwardedRef, handleEditorReady, id, @@ -95,7 +97,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => { ); }; -const CollaborativeDocumentEditorWithRef = React.forwardRef( +const CollaborativeDocumentEditorWithRef = React.forwardRef( (props, ref) => ( } /> ) diff --git a/packages/editor/src/core/components/editors/document/page-renderer.tsx b/packages/editor/src/core/components/editors/document/page-renderer.tsx index 0be3c17c134..62613b0a13e 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -5,7 +5,7 @@ import { AIFeaturesMenu, BlockMenu, EditorBubbleMenu } from "@/components/menus" // types import { TAIHandler, TDisplayConfig } from "@/types"; -type IPageRenderer = { +type Props = { aiHandler?: TAIHandler; bubbleMenuEnabled: boolean; displayConfig: TDisplayConfig; @@ -15,7 +15,7 @@ type IPageRenderer = { tabIndex?: number; }; -export const PageRenderer = (props: IPageRenderer) => { +export const PageRenderer = (props: Props) => { const { aiHandler, bubbleMenuEnabled, displayConfig, editor, editorContainerClassName, id, tabIndex } = props; return ( diff --git a/packages/editor/src/core/components/editors/document/read-only-editor.tsx b/packages/editor/src/core/components/editors/document/read-only-editor.tsx index 2d2e3083016..8f0d67ddc0d 100644 --- a/packages/editor/src/core/components/editors/document/read-only-editor.tsx +++ b/packages/editor/src/core/components/editors/document/read-only-editor.tsx @@ -1,5 +1,5 @@ import { Extensions } from "@tiptap/core"; -import { forwardRef, MutableRefObject } from "react"; +import React, { forwardRef, MutableRefObject } from "react"; // plane imports import { cn } from "@plane/utils"; // components @@ -13,30 +13,9 @@ import { getEditorClassNames } from "@/helpers/common"; // hooks import { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; // types -import { - EditorReadOnlyRefApi, - TDisplayConfig, - TExtensions, - TReadOnlyFileHandler, - TReadOnlyMentionHandler, -} from "@/types"; +import { EditorReadOnlyRefApi, IDocumentReadOnlyEditorProps } from "@/types"; -interface IDocumentReadOnlyEditor { - disabledExtensions: TExtensions[]; - id: string; - initialValue: string; - containerClassName: string; - displayConfig?: TDisplayConfig; - editorClassName?: string; - embedHandler: any; - fileHandler: TReadOnlyFileHandler; - tabIndex?: number; - handleEditorReady?: (value: boolean) => void; - mentionHandler: TReadOnlyMentionHandler; - forwardedRef?: React.MutableRefObject; -} - -const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { +const DocumentReadOnlyEditor: React.FC = (props) => { const { containerClassName, disabledExtensions, @@ -44,6 +23,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { editorClassName = "", embedHandler, fileHandler, + flaggedExtensions, id, forwardedRef, handleEditorReady, @@ -64,6 +44,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { editorClassName, extensions, fileHandler, + flaggedExtensions, forwardedRef, handleEditorReady, initialValue, @@ -87,7 +68,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { ); }; -const DocumentReadOnlyEditorWithRef = forwardRef((props, ref) => ( +const DocumentReadOnlyEditorWithRef = forwardRef((props, ref) => ( } /> )); diff --git a/packages/editor/src/core/components/editors/editor-wrapper.tsx b/packages/editor/src/core/components/editors/editor-wrapper.tsx index 9d1297e239e..2c1ef52b757 100644 --- a/packages/editor/src/core/components/editors/editor-wrapper.tsx +++ b/packages/editor/src/core/components/editors/editor-wrapper.tsx @@ -26,6 +26,7 @@ export const EditorWrapper: React.FC = (props) => { id, initialValue, fileHandler, + flaggedExtensions, forwardedRef, mentionHandler, onChange, @@ -44,6 +45,7 @@ export const EditorWrapper: React.FC = (props) => { enableHistory: true, extensions, fileHandler, + flaggedExtensions, forwardedRef, id, initialValue, diff --git a/packages/editor/src/core/components/editors/lite-text/editor.tsx b/packages/editor/src/core/components/editors/lite-text/editor.tsx index 849a3c3e234..df89521ae68 100644 --- a/packages/editor/src/core/components/editors/lite-text/editor.tsx +++ b/packages/editor/src/core/components/editors/lite-text/editor.tsx @@ -4,23 +4,25 @@ import { EditorWrapper } from "@/components/editors/editor-wrapper"; // extensions import { EnterKeyExtension } from "@/extensions"; // types -import { EditorRefApi, ILiteTextEditor } from "@/types"; +import { EditorRefApi, ILiteTextEditorProps } from "@/types"; -const LiteTextEditor = (props: ILiteTextEditor) => { +const LiteTextEditor: React.FC = (props) => { const { onEnterKeyPress, disabledExtensions, extensions: externalExtensions = [] } = props; - const extensions = useMemo( - () => [ - ...externalExtensions, - ...(disabledExtensions?.includes("enter-key") ? [] : [EnterKeyExtension(onEnterKeyPress)]), - ], - [externalExtensions, disabledExtensions, onEnterKeyPress] - ); + const extensions = useMemo(() => { + const resolvedExtensions = [...externalExtensions]; + + if (!disabledExtensions?.includes("enter-key")) { + resolvedExtensions.push(EnterKeyExtension(onEnterKeyPress)); + } + + return resolvedExtensions; + }, [externalExtensions, disabledExtensions, onEnterKeyPress]); return ; }; -const LiteTextEditorWithRef = forwardRef((props, ref) => ( +const LiteTextEditorWithRef = forwardRef((props, ref) => ( } /> )); diff --git a/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx b/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx index b721c84c5df..75e02791de2 100644 --- a/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx +++ b/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx @@ -2,9 +2,9 @@ import { forwardRef } from "react"; // components import { ReadOnlyEditorWrapper } from "@/components/editors"; // types -import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor } from "@/types"; +import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditorProps } from "@/types"; -const LiteTextReadOnlyEditorWithRef = forwardRef((props, ref) => ( +const LiteTextReadOnlyEditorWithRef = forwardRef((props, ref) => ( } /> )); diff --git a/packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx b/packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx index ffed8ba8bd3..b6abd1a6a50 100644 --- a/packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx +++ b/packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx @@ -17,6 +17,7 @@ export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => { editorClassName = "", extensions, fileHandler, + flaggedExtensions, forwardedRef, id, initialValue, @@ -28,6 +29,7 @@ export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => { editorClassName, extensions, fileHandler, + flaggedExtensions, forwardedRef, initialValue, mentionHandler, diff --git a/packages/editor/src/core/components/editors/rich-text/editor.tsx b/packages/editor/src/core/components/editors/rich-text/editor.tsx index 2334d9babaf..8544dcc8323 100644 --- a/packages/editor/src/core/components/editors/rich-text/editor.tsx +++ b/packages/editor/src/core/components/editors/rich-text/editor.tsx @@ -7,15 +7,16 @@ import { SideMenuExtension } from "@/extensions"; // plane editor imports import { RichTextEditorAdditionalExtensions } from "@/plane-editor/extensions/rich-text/extensions"; // types -import { EditorRefApi, IRichTextEditor } from "@/types"; +import { EditorRefApi, IRichTextEditorProps } from "@/types"; -const RichTextEditor = (props: IRichTextEditor) => { +const RichTextEditor: React.FC = (props) => { const { + bubbleMenuEnabled = true, disabledExtensions, dragDropEnabled, - fileHandler, - bubbleMenuEnabled = true, extensions: externalExtensions = [], + fileHandler, + flaggedExtensions, } = props; const getExtensions = useCallback(() => { @@ -28,11 +29,12 @@ const RichTextEditor = (props: IRichTextEditor) => { ...RichTextEditorAdditionalExtensions({ disabledExtensions, fileHandler, + flaggedExtensions, }), ]; return extensions; - }, [dragDropEnabled, disabledExtensions, externalExtensions, fileHandler]); + }, [dragDropEnabled, disabledExtensions, externalExtensions, fileHandler, flaggedExtensions]); return ( @@ -41,7 +43,7 @@ const RichTextEditor = (props: IRichTextEditor) => { ); }; -const RichTextEditorWithRef = forwardRef((props, ref) => ( +const RichTextEditorWithRef = forwardRef((props, ref) => ( } /> )); diff --git a/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx b/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx index 18d960ca53f..efad3d6ac1b 100644 --- a/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx +++ b/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx @@ -2,23 +2,22 @@ import { forwardRef, useCallback } from "react"; // plane editor extensions import { RichTextReadOnlyEditorAdditionalExtensions } from "@/plane-editor/extensions/rich-text/read-only-extensions"; // types -import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor } from "@/types"; +import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps } from "@/types"; // local imports import { ReadOnlyEditorWrapper } from "../read-only-editor-wrapper"; -const RichTextReadOnlyEditorWithRef = forwardRef((props, ref) => { - const { disabledExtensions, fileHandler } = props; +const RichTextReadOnlyEditorWithRef = forwardRef((props, ref) => { + const { disabledExtensions, fileHandler, flaggedExtensions } = props; const getExtensions = useCallback(() => { - const extensions = [ - ...RichTextReadOnlyEditorAdditionalExtensions({ - disabledExtensions, - fileHandler, - }), - ]; + const extensions = RichTextReadOnlyEditorAdditionalExtensions({ + disabledExtensions, + fileHandler, + flaggedExtensions, + }); return extensions; - }, [disabledExtensions, fileHandler]); + }, [disabledExtensions, fileHandler, flaggedExtensions]); return ( & { enableHistory: boolean; - fileHandler: TFileHandler; - mentionHandler: TMentionHandler; - placeholder?: string | ((isFocused: boolean, value: string) => string); - tabIndex?: number; editable: boolean; }; export const CoreEditorExtensions = (args: TArguments): Extensions => { - const { disabledExtensions, enableHistory, fileHandler, mentionHandler, placeholder, tabIndex, editable } = args; + const { + disabledExtensions, + enableHistory, + fileHandler, + flaggedExtensions, + mentionHandler, + placeholder, + tabIndex, + editable, + } = args; const extensions = [ StarterKit.configure({ @@ -177,6 +184,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { CustomColorExtension, ...CoreEditorAdditionalExtensions({ disabledExtensions, + flaggedExtensions, fileHandler, }), ]; diff --git a/packages/editor/src/core/extensions/read-only-extensions.ts b/packages/editor/src/core/extensions/read-only-extensions.ts index b28e8a67aba..0f422c620ba 100644 --- a/packages/editor/src/core/extensions/read-only-extensions.ts +++ b/packages/editor/src/core/extensions/read-only-extensions.ts @@ -31,16 +31,12 @@ import { isValidHttpUrl } from "@/helpers/common"; // plane editor extensions import { CoreReadOnlyEditorAdditionalExtensions } from "@/plane-editor/extensions"; // types -import { TExtensions, TReadOnlyFileHandler, TReadOnlyMentionHandler } from "@/types"; +import type { IReadOnlyEditorProps } from "@/types"; -type Props = { - disabledExtensions: TExtensions[]; - fileHandler: TReadOnlyFileHandler; - mentionHandler: TReadOnlyMentionHandler; -}; +type Props = Pick; export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { - const { disabledExtensions, fileHandler, mentionHandler } = props; + const { disabledExtensions, fileHandler, flaggedExtensions, mentionHandler } = props; const extensions = [ StarterKit.configure({ @@ -133,6 +129,7 @@ export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { }), ...CoreReadOnlyEditorAdditionalExtensions({ disabledExtensions, + flaggedExtensions, }), ]; diff --git a/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx b/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx index fe9ec06a6d9..d3ca4856e1c 100644 --- a/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx +++ b/packages/editor/src/core/extensions/slash-commands/command-items-list.tsx @@ -49,7 +49,7 @@ export type TSlashCommandSection = { export const getSlashCommandFilteredSections = (args: TExtensionProps) => ({ query }: { query: string }): TSlashCommandSection[] => { - const { additionalOptions: externalAdditionalOptions, disabledExtensions } = args; + const { additionalOptions: externalAdditionalOptions, disabledExtensions, flaggedExtensions } = args; const SLASH_COMMAND_SECTIONS: TSlashCommandSection[] = [ { key: "general", @@ -290,6 +290,7 @@ export const getSlashCommandFilteredSections = ...(externalAdditionalOptions ?? []), ...coreEditorAdditionalSlashCommandOptions({ disabledExtensions, + flaggedExtensions, }), ]?.forEach((item) => { const sectionToPushTo = SLASH_COMMAND_SECTIONS.find((s) => s.key === item.section) ?? SLASH_COMMAND_SECTIONS[0]; diff --git a/packages/editor/src/core/extensions/slash-commands/root.tsx b/packages/editor/src/core/extensions/slash-commands/root.tsx index 828149d5027..3a29e932c67 100644 --- a/packages/editor/src/core/extensions/slash-commands/root.tsx +++ b/packages/editor/src/core/extensions/slash-commands/root.tsx @@ -7,7 +7,7 @@ import { CORE_EXTENSIONS } from "@/constants/extension"; // helpers import { CommandListInstance } from "@/helpers/tippy"; // types -import { ISlashCommandItem, TEditorCommands, TExtensions, TSlashCommandSectionKeys } from "@/types"; +import { IEditorProps, ISlashCommandItem, TEditorCommands, TSlashCommandSectionKeys } from "@/types"; // components import { getSlashCommandFilteredSections } from "./command-items-list"; import { SlashCommandsMenu, SlashCommandsMenuProps } from "./command-menu"; @@ -106,9 +106,8 @@ const renderItems = () => { }; }; -export type TExtensionProps = { +export type TExtensionProps = Pick & { additionalOptions?: TSlashCommandAdditionalOption[]; - disabledExtensions?: TExtensions[]; }; export const SlashCommands = (props: TExtensionProps) => diff --git a/packages/editor/src/core/extensions/utility.ts b/packages/editor/src/core/extensions/utility.ts index 9252e300c7d..758c742411a 100644 --- a/packages/editor/src/core/extensions/utility.ts +++ b/packages/editor/src/core/extensions/utility.ts @@ -8,7 +8,7 @@ import { DropHandlerPlugin } from "@/plugins/drop"; import { FilePlugins } from "@/plugins/file/root"; import { MarkdownClipboardPlugin } from "@/plugins/markdown-clipboard"; // types -import { TExtensions, TFileHandler, TReadOnlyFileHandler } from "@/types"; +import type { IEditorProps, TFileHandler, TReadOnlyFileHandler } from "@/types"; declare module "@tiptap/core" { interface Commands { @@ -23,8 +23,7 @@ export interface UtilityExtensionStorage { uploadInProgress: boolean; } -type Props = { - disabledExtensions: TExtensions[]; +type Props = Pick & { fileHandler: TFileHandler | TReadOnlyFileHandler; isEditable: boolean; }; diff --git a/packages/editor/src/core/hooks/use-collaborative-editor.ts b/packages/editor/src/core/hooks/use-collaborative-editor.ts index 11e7ba3208e..570315d757b 100644 --- a/packages/editor/src/core/hooks/use-collaborative-editor.ts +++ b/packages/editor/src/core/hooks/use-collaborative-editor.ts @@ -9,18 +9,19 @@ import { useEditor } from "@/hooks/use-editor"; // plane editor extensions import { DocumentEditorAdditionalExtensions } from "@/plane-editor/extensions"; // types -import { TCollaborativeEditorProps } from "@/types"; +import { TCollaborativeEditorHookProps } from "@/types"; -export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => { +export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) => { const { onTransaction, disabledExtensions, editable, - editorClassName, + editorClassName = "", editorProps = {}, embedHandler, - extensions, + extensions = [], fileHandler, + flaggedExtensions, forwardedRef, handleEditorReady, id, @@ -89,16 +90,18 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => { Collaboration.configure({ document: provider.document, }), - ...(extensions ?? []), + ...extensions, ...DocumentEditorAdditionalExtensions({ disabledExtensions, embedConfig: embedHandler, fileHandler, + flaggedExtensions, provider, userDetails: user, }), ], fileHandler, + flaggedExtensions, forwardedRef, handleEditorReady, mentionHandler, diff --git a/packages/editor/src/core/hooks/use-editor.ts b/packages/editor/src/core/hooks/use-editor.ts index ce3cdbe5fb5..4c1b93d84aa 100644 --- a/packages/editor/src/core/hooks/use-editor.ts +++ b/packages/editor/src/core/hooks/use-editor.ts @@ -1,13 +1,12 @@ -import { HocuspocusProvider } from "@hocuspocus/provider"; import { DOMSerializer } from "@tiptap/pm/model"; -import { EditorProps } from "@tiptap/pm/view"; -import { useEditor as useTiptapEditor, Extensions } from "@tiptap/react"; -import { useImperativeHandle, MutableRefObject, useEffect } from "react"; +import { useEditor as useTiptapEditor } from "@tiptap/react"; +import { useImperativeHandle, useEffect } from "react"; import * as Y from "yjs"; // components import { getEditorMenuItems } from "@/components/menus"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +import { CORE_EDITOR_META } from "@/constants/meta"; // extensions import { CoreEditorExtensions } from "@/extensions"; // helpers @@ -18,49 +17,19 @@ import { IMarking, scrollSummary, scrollToNodeViaDOMCoordinates } from "@/helper // props import { CoreEditorProps } from "@/props"; // types -import type { - TDocumentEventsServer, - EditorRefApi, - TEditorCommands, - TFileHandler, - TExtensions, - TMentionHandler, -} from "@/types"; -import { CORE_EDITOR_META } from "@/constants/meta"; +import type { TDocumentEventsServer, TEditorCommands, TEditorHookProps } from "@/types"; -export interface CustomEditorProps { - editable: boolean; - editorClassName: string; - editorProps?: EditorProps; - enableHistory: boolean; - disabledExtensions: TExtensions[]; - extensions?: Extensions; - fileHandler: TFileHandler; - forwardedRef?: MutableRefObject; - handleEditorReady?: (value: boolean) => void; - id?: string; - initialValue?: string; - mentionHandler: TMentionHandler; - onChange?: (json: object, html: string) => void; - onTransaction?: () => void; - autofocus?: boolean; - placeholder?: string | ((isFocused: boolean, value: string) => string); - provider?: HocuspocusProvider; - tabIndex?: number; - // undefined when prop is not passed, null if intentionally passed to stop - // swr syncing - value?: string | null | undefined; -} - -export const useEditor = (props: CustomEditorProps) => { +export const useEditor = (props: TEditorHookProps) => { const { + autofocus = false, disabledExtensions, editable = true, - editorClassName, + editorClassName = "", editorProps = {}, enableHistory, extensions = [], fileHandler, + flaggedExtensions, forwardedRef, handleEditorReady, id = "", @@ -69,10 +38,9 @@ export const useEditor = (props: CustomEditorProps) => { onChange, onTransaction, placeholder, + provider, tabIndex, value, - provider, - autofocus = false, } = props; const editor = useTiptapEditor( @@ -94,6 +62,7 @@ export const useEditor = (props: CustomEditorProps) => { disabledExtensions, enableHistory, fileHandler, + flaggedExtensions, mentionHandler, placeholder, tabIndex, diff --git a/packages/editor/src/core/hooks/use-read-only-editor.ts b/packages/editor/src/core/hooks/use-read-only-editor.ts index 6a6e25d9fd5..d259470ac96 100644 --- a/packages/editor/src/core/hooks/use-read-only-editor.ts +++ b/packages/editor/src/core/hooks/use-read-only-editor.ts @@ -1,8 +1,8 @@ -import { HocuspocusProvider } from "@hocuspocus/provider"; -import { EditorProps } from "@tiptap/pm/view"; -import { useEditor as useTiptapEditor, Extensions } from "@tiptap/react"; -import { useImperativeHandle, MutableRefObject, useEffect } from "react"; +import { useEditor as useTiptapEditor } from "@tiptap/react"; +import { useImperativeHandle, useEffect } from "react"; import * as Y from "yjs"; +// constants +import { CORE_EDITOR_META } from "@/constants/meta"; // extensions import { CoreReadOnlyEditorExtensions } from "@/extensions"; // helpers @@ -11,32 +11,19 @@ import { IMarking, scrollSummary } from "@/helpers/scroll-to-node"; // props import { CoreReadOnlyEditorProps } from "@/props"; // types -import type { EditorReadOnlyRefApi, TExtensions, TReadOnlyFileHandler, TReadOnlyMentionHandler } from "@/types"; -import { CORE_EDITOR_META } from "@/constants/meta"; - -interface CustomReadOnlyEditorProps { - disabledExtensions: TExtensions[]; - editorClassName: string; - editorProps?: EditorProps; - extensions?: Extensions; - forwardedRef?: MutableRefObject; - initialValue?: string; - fileHandler: TReadOnlyFileHandler; - handleEditorReady?: (value: boolean) => void; - mentionHandler: TReadOnlyMentionHandler; - provider?: HocuspocusProvider; -} +import type { TReadOnlyEditorHookProps } from "@/types"; -export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => { +export const useReadOnlyEditor = (props: TReadOnlyEditorHookProps) => { const { disabledExtensions, - initialValue, - editorClassName, - forwardedRef, - extensions = [], + editorClassName = "", editorProps = {}, + extensions = [], fileHandler, + flaggedExtensions, + forwardedRef, handleEditorReady, + initialValue, mentionHandler, provider, } = props; @@ -59,8 +46,9 @@ export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => { extensions: [ ...CoreReadOnlyEditorExtensions({ disabledExtensions, - mentionHandler, fileHandler, + flaggedExtensions, + mentionHandler, }), ...extensions, ], diff --git a/packages/editor/src/core/types/collaboration.ts b/packages/editor/src/core/types/collaboration.ts index 55608623204..8921e8f052d 100644 --- a/packages/editor/src/core/types/collaboration.ts +++ b/packages/editor/src/core/types/collaboration.ts @@ -1,50 +1,4 @@ -import { Extensions } from "@tiptap/core"; -import { EditorProps } from "@tiptap/pm/view"; -// plane editor types -import { TEmbedConfig } from "@/plane-editor/types"; -// types -import { - EditorReadOnlyRefApi, - EditorRefApi, - TExtensions, - TFileHandler, - TMentionHandler, - TReadOnlyFileHandler, - TReadOnlyMentionHandler, - TRealtimeConfig, - TUserDetails, -} from "@/types"; - export type TServerHandler = { onConnect?: () => void; onServerError?: () => void; }; - -type TCollaborativeEditorHookProps = { - disabledExtensions: TExtensions[]; - editable: boolean; - editorClassName: string; - editorProps?: EditorProps; - extensions?: Extensions; - handleEditorReady?: (value: boolean) => void; - id: string; - realtimeConfig: TRealtimeConfig; - serverHandler?: TServerHandler; - user: TUserDetails; -}; - -export type TCollaborativeEditorProps = TCollaborativeEditorHookProps & { - onTransaction?: () => void; - embedHandler?: TEmbedConfig; - fileHandler: TFileHandler; - forwardedRef?: React.MutableRefObject; - mentionHandler: TMentionHandler; - placeholder?: string | ((isFocused: boolean, value: string) => string); - tabIndex?: number; -}; - -export type TReadOnlyCollaborativeEditorProps = TCollaborativeEditorHookProps & { - fileHandler: TReadOnlyFileHandler; - forwardedRef?: React.MutableRefObject; - mentionHandler: TReadOnlyMentionHandler; -}; diff --git a/packages/editor/src/core/types/config.ts b/packages/editor/src/core/types/config.ts index ace2220ed00..60ccfa84123 100644 --- a/packages/editor/src/core/types/config.ts +++ b/packages/editor/src/core/types/config.ts @@ -1,3 +1,6 @@ +// plane imports +import { TWebhookConnectionQueryParams } from "@plane/types"; + export type TReadOnlyFileHandler = { checkIfAssetExists: (assetId: string) => Promise; getAssetSrc: (path: string) => Promise; @@ -30,3 +33,15 @@ export type TDisplayConfig = { lineSpacing?: TEditorLineSpacing; wideLayout?: boolean; }; + +export type TUserDetails = { + color: string; + id: string; + name: string; + cookie?: string; +}; + +export type TRealtimeConfig = { + url: string; + queryParams: TWebhookConnectionQueryParams; +}; diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index ace1048ce8c..f8a1facad8e 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -1,13 +1,11 @@ -import { Extensions, JSONContent } from "@tiptap/core"; -import { Selection } from "@tiptap/pm/state"; -// plane types -import { TWebhookConnectionQueryParams } from "@plane/types"; +import type { Extensions, JSONContent } from "@tiptap/core"; +import type { Selection } from "@tiptap/pm/state"; // extension types -import { TTextAlign } from "@/extensions"; +import type { TTextAlign } from "@/extensions"; // helpers -import { IMarking } from "@/helpers/scroll-to-node"; +import type { IMarking } from "@/helpers/scroll-to-node"; // types -import { +import type { TAIHandler, TDisplayConfig, TDocumentEventEmitter, @@ -18,7 +16,9 @@ import { TMentionHandler, TReadOnlyFileHandler, TReadOnlyMentionHandler, + TRealtimeConfig, TServerHandler, + TUserDetails, } from "@/types"; export type TEditorCommands = @@ -114,90 +114,70 @@ export interface EditorRefApi extends EditorReadOnlyRefApi { // editor props export interface IEditorProps { + autofocus?: boolean; + bubbleMenuEnabled?: boolean; containerClassName?: string; displayConfig?: TDisplayConfig; disabledExtensions: TExtensions[]; editorClassName?: string; + extensions?: Extensions; + flaggedExtensions: TExtensions[]; fileHandler: TFileHandler; forwardedRef?: React.MutableRefObject; + handleEditorReady?: (value: boolean) => void; id: string; initialValue: string; mentionHandler: TMentionHandler; onChange?: (json: object, html: string) => void; - onTransaction?: () => void; - handleEditorReady?: (value: boolean) => void; - autofocus?: boolean; onEnterKeyPress?: (e?: any) => void; + onTransaction?: () => void; placeholder?: string | ((isFocused: boolean, value: string) => string); tabIndex?: number; value?: string | null; - bubbleMenuEnabled?: boolean; } -export interface ILiteTextEditor extends IEditorProps { - extensions?: Extensions; -} -export interface IRichTextEditor extends IEditorProps { - extensions?: Extensions; + +export type ILiteTextEditorProps = IEditorProps; +export interface IRichTextEditorProps extends IEditorProps { dragDropEnabled?: boolean; } -export interface ICollaborativeDocumentEditor - extends Omit { +export interface ICollaborativeDocumentEditorProps + extends Omit { aiHandler?: TAIHandler; - bubbleMenuEnabled?: boolean; editable: boolean; embedHandler: TEmbedConfig; - handleEditorReady?: (value: boolean) => void; - id: string; realtimeConfig: TRealtimeConfig; serverHandler?: TServerHandler; user: TUserDetails; } // read only editor props -export interface IReadOnlyEditorProps { - containerClassName?: string; - disabledExtensions: TExtensions[]; - displayConfig?: TDisplayConfig; - editorClassName?: string; - extensions?: Extensions; +export interface IReadOnlyEditorProps + extends Pick< + IEditorProps, + | "containerClassName" + | "disabledExtensions" + | "flaggedExtensions" + | "displayConfig" + | "editorClassName" + | "extensions" + | "handleEditorReady" + | "id" + | "initialValue" + > { fileHandler: TReadOnlyFileHandler; forwardedRef?: React.MutableRefObject; - id: string; - initialValue: string; mentionHandler: TReadOnlyMentionHandler; } -export type ILiteTextReadOnlyEditor = IReadOnlyEditorProps; - -export type IRichTextReadOnlyEditor = IReadOnlyEditorProps; +export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps; -export interface ICollaborativeDocumentReadOnlyEditor extends Omit { - embedHandler: TEmbedConfig; - handleEditorReady?: (value: boolean) => void; - id: string; - realtimeConfig: TRealtimeConfig; - serverHandler?: TServerHandler; - user: TUserDetails; -} +export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps; -export interface IDocumentReadOnlyEditor extends IReadOnlyEditorProps { +export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps { embedHandler: TEmbedConfig; - handleEditorReady?: (value: boolean) => void; } -export type TUserDetails = { - color: string; - id: string; - name: string; - cookie?: string; -}; - -export type TRealtimeConfig = { - url: string; - queryParams: TWebhookConnectionQueryParams; -}; - export interface EditorEvents { beforeCreate: never; create: never; diff --git a/packages/editor/src/core/types/hook.ts b/packages/editor/src/core/types/hook.ts new file mode 100644 index 00000000000..be84d2d9e89 --- /dev/null +++ b/packages/editor/src/core/types/hook.ts @@ -0,0 +1,42 @@ +import type { HocuspocusProvider } from "@hocuspocus/provider"; +import type { EditorProps } from "@tiptap/pm/view"; +// local imports +import type { ICollaborativeDocumentEditorProps, IEditorProps, IReadOnlyEditorProps } from "./editor"; + +type TCoreHookProps = Pick< + IEditorProps, + "disabledExtensions" | "editorClassName" | "extensions" | "flaggedExtensions" | "handleEditorReady" +> & { + editorProps?: EditorProps; +}; + +export type TEditorHookProps = TCoreHookProps & + Pick< + IEditorProps, + | "autofocus" + | "fileHandler" + | "forwardedRef" + | "id" + | "mentionHandler" + | "onChange" + | "onTransaction" + | "placeholder" + | "tabIndex" + | "value" + > & { + editable: boolean; + enableHistory: boolean; + initialValue?: string; + provider?: HocuspocusProvider; + }; + +export type TCollaborativeEditorHookProps = TCoreHookProps & + Pick< + TEditorHookProps, + "editable" | "fileHandler" | "forwardedRef" | "id" | "mentionHandler" | "onTransaction" | "placeholder" | "tabIndex" + > & + Pick; + +export type TReadOnlyEditorHookProps = TCoreHookProps & + Pick & + Pick; diff --git a/packages/editor/src/core/types/index.ts b/packages/editor/src/core/types/index.ts index 66cb249425b..619fa0c784c 100644 --- a/packages/editor/src/core/types/index.ts +++ b/packages/editor/src/core/types/index.ts @@ -4,6 +4,7 @@ export * from "./config"; export * from "./editor"; export * from "./embed"; export * from "./extensions"; +export * from "./hook"; export * from "./mention"; export * from "./slash-commands-suggestion"; export * from "@/plane-editor/types"; diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index a2a9afaf92a..fec933f910b 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -36,5 +36,4 @@ export { type IMarking, useEditorMarkings } from "@/hooks/use-editor-markings"; export { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; // types -export type { CustomEditorProps } from "@/hooks/use-editor"; export * from "@/types"; diff --git a/web/ce/hooks/use-editor-flagging.ts b/web/ce/hooks/use-editor-flagging.ts index 05fdff91fa5..7e04919ce6f 100644 --- a/web/ce/hooks/use-editor-flagging.ts +++ b/web/ce/hooks/use-editor-flagging.ts @@ -1,17 +1,35 @@ // editor import { TExtensions } from "@plane/editor"; +export type TEditorFlaggingHookReturnType = { + document: { + disabled: TExtensions[]; + flagged: TExtensions[]; + }; + liteText: { + disabled: TExtensions[]; + flagged: TExtensions[]; + }; + richText: { + disabled: TExtensions[]; + flagged: TExtensions[]; + }; +}; + /** * @description extensions disabled in various editors */ -export const useEditorFlagging = ( - workspaceSlug: string -): { - documentEditor: TExtensions[]; - liteTextEditor: TExtensions[]; - richTextEditor: TExtensions[]; -} => ({ - documentEditor: ["ai", "collaboration-cursor"], - liteTextEditor: ["ai", "collaboration-cursor"], - richTextEditor: ["ai", "collaboration-cursor"], +export const useEditorFlagging = (workspaceSlug: string): TEditorFlaggingHookReturnType => ({ + document: { + disabled: ["ai", "collaboration-cursor"], + flagged: [], + }, + liteText: { + disabled: ["ai", "collaboration-cursor"], + flagged: [], + }, + richText: { + disabled: ["ai", "collaboration-cursor"], + flagged: [], + }, }); diff --git a/web/core/components/editor/lite-text-editor/lite-text-editor.tsx b/web/core/components/editor/lite-text-editor/lite-text-editor.tsx index a29f84a6352..088676358ee 100644 --- a/web/core/components/editor/lite-text-editor/lite-text-editor.tsx +++ b/web/core/components/editor/lite-text-editor/lite-text-editor.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; // plane constants import { EIssueCommentAccessSpecifier } from "@plane/constants"; // plane editor -import { EditorRefApi, ILiteTextEditor, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; +import { EditorRefApi, ILiteTextEditorProps, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; // i18n import { useTranslation } from "@plane/i18n"; // components @@ -21,7 +21,10 @@ import { WorkspaceService } from "@/plane-web/services"; const workspaceService = new WorkspaceService(); interface LiteTextEditorWrapperProps - extends MakeOptional, "disabledExtensions"> { + extends MakeOptional< + Omit, + "disabledExtensions" | "flaggedExtensions" + > { workspaceSlug: string; workspaceId: string; projectId?: string; @@ -55,13 +58,13 @@ export const LiteTextEditor = React.forwardRef , - "disabledExtensions" + Omit, + "disabledExtensions" | "flaggedExtensions" > & { workspaceId: string; workspaceSlug: string; @@ -28,14 +28,15 @@ export const LiteTextReadOnlyEditor = React.forwardRef, "disabledExtensions"> { + extends MakeOptional< + Omit, + "disabledExtensions" | "flaggedExtensions" + > { searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise; workspaceSlug: string; workspaceId: string; @@ -36,7 +39,7 @@ export const RichTextEditor = forwardRef await searchMentionCallback(payload), @@ -47,7 +50,8 @@ export const RichTextEditor = forwardRef, - "disabledExtensions" + Omit, + "disabledExtensions" | "flaggedExtensions" > & { workspaceId: string; workspaceSlug: string; @@ -30,14 +30,15 @@ export const RichTextReadOnlyEditor = React.forwardRef { + extends Omit { workspaceSlug: string; workspaceId: string; projectId?: string; @@ -48,7 +48,7 @@ export const StickyEditor = React.forwardRef(ref: React.ForwardedRef): ref is React.MutableRefObject { @@ -65,7 +65,8 @@ export const StickyEditor = React.forwardRef = observer((props) => { searchEntity: handlers.fetchEntity, }); // editor flaggings - const { documentEditor: disabledExtensions } = useEditorFlagging(workspaceSlug); + const { document: documentEditorExtensions } = useEditorFlagging(workspaceSlug); // page filters const { fontSize, fontStyle, isFullWidth } = usePageFilters(); // derived values @@ -213,7 +213,8 @@ export const PageEditorBody: React.FC = observer((props) => { realtimeConfig={realtimeConfig} serverHandler={serverHandler} user={userConfig} - disabledExtensions={disabledExtensions} + disabledExtensions={documentEditorExtensions.disabled} + flaggedExtensions={documentEditorExtensions.flagged} aiHandler={{ menu: getAIMenu, }} diff --git a/web/core/components/pages/version/editor.tsx b/web/core/components/pages/version/editor.tsx index f0b28e24e59..8491408ac8c 100644 --- a/web/core/components/pages/version/editor.tsx +++ b/web/core/components/pages/version/editor.tsx @@ -32,7 +32,7 @@ export const PagesVersionEditor: React.FC = observer((props // derived values const workspaceDetails = getWorkspaceBySlug(workspaceSlug?.toString() ?? ""); // editor flaggings - const { documentEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString() ?? ""); + const { document: documentEditorExtensions } = useEditorFlagging(workspaceSlug?.toString() ?? ""); // editor config const { getReadOnlyEditorFileHandlers } = useEditorConfig(); // issue-embed @@ -99,7 +99,8 @@ export const PagesVersionEditor: React.FC = observer((props id={activeVersion ?? ""} initialValue={description ?? "

"} containerClassName="p-0 pb-64 border-none" - disabledExtensions={disabledExtensions} + disabledExtensions={documentEditorExtensions.disabled} + flaggedExtensions={documentEditorExtensions.flagged} displayConfig={displayConfig} editorClassName="pl-10" fileHandler={getReadOnlyEditorFileHandlers({ From 9c4faca45a6477c68cf801f4e05a731297495754 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Wed, 18 Jun 2025 16:44:33 +0530 Subject: [PATCH 2/4] chore: add missing prop --- .../editors/document/collaborative-editor.tsx | 2 ++ packages/editor/src/core/types/editor.ts | 2 +- packages/editor/src/core/types/hook.ts | 10 +++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx index 2fa9f3a5688..8bbf2e7cea5 100644 --- a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx +++ b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx @@ -17,6 +17,7 @@ import { EditorRefApi, ICollaborativeDocumentEditorProps } from "@/types"; const CollaborativeDocumentEditor: React.FC = (props) => { const { + onChange, onTransaction, aiHandler, bubbleMenuEnabled = true, @@ -62,6 +63,7 @@ const CollaborativeDocumentEditor: React.FC = handleEditorReady, id, mentionHandler, + onChange, onTransaction, placeholder, realtimeConfig, diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index f8a1facad8e..cf3d7d2c7f8 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -142,7 +142,7 @@ export interface IRichTextEditorProps extends IEditorProps { } export interface ICollaborativeDocumentEditorProps - extends Omit { + extends Omit { aiHandler?: TAIHandler; editable: boolean; embedHandler: TEmbedConfig; diff --git a/packages/editor/src/core/types/hook.ts b/packages/editor/src/core/types/hook.ts index be84d2d9e89..2224935ca91 100644 --- a/packages/editor/src/core/types/hook.ts +++ b/packages/editor/src/core/types/hook.ts @@ -33,7 +33,15 @@ export type TEditorHookProps = TCoreHookProps & export type TCollaborativeEditorHookProps = TCoreHookProps & Pick< TEditorHookProps, - "editable" | "fileHandler" | "forwardedRef" | "id" | "mentionHandler" | "onTransaction" | "placeholder" | "tabIndex" + | "editable" + | "fileHandler" + | "forwardedRef" + | "id" + | "mentionHandler" + | "onChange" + | "onTransaction" + | "placeholder" + | "tabIndex" > & Pick; From b9f46d1548218d92249d777091eaeb780eb6e3e5 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Wed, 18 Jun 2025 17:59:29 +0530 Subject: [PATCH 3/4] fix: space app build --- space/core/components/editor/lite-text-editor.tsx | 9 +++++++-- .../components/editor/lite-text-read-only-editor.tsx | 9 +++++---- space/core/components/editor/rich-text-editor.tsx | 10 +++++++--- .../components/editor/rich-text-read-only-editor.tsx | 9 +++++---- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/space/core/components/editor/lite-text-editor.tsx b/space/core/components/editor/lite-text-editor.tsx index 5c62d14f82d..6342d934479 100644 --- a/space/core/components/editor/lite-text-editor.tsx +++ b/space/core/components/editor/lite-text-editor.tsx @@ -1,6 +1,6 @@ import React from "react"; // plane imports -import { EditorRefApi, ILiteTextEditor, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; +import { EditorRefApi, ILiteTextEditorProps, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; import { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; // components @@ -10,7 +10,10 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper"; import { isCommentEmpty } from "@/helpers/string.helper"; interface LiteTextEditorWrapperProps - extends MakeOptional, "disabledExtensions"> { + extends MakeOptional< + Omit, + "disabledExtensions" | "flaggedExtensions" + > { anchor: string; workspaceId: string; isSubmitting?: boolean; @@ -27,6 +30,7 @@ export const LiteTextEditor = React.forwardRef(ref: React.ForwardedRef): ref is React.MutableRefObject { @@ -41,6 +45,7 @@ export const LiteTextEditor = React.forwardRef, - "disabledExtensions" + Omit, + "disabledExtensions" | "flaggedExtensions" > & { anchor: string; workspaceId: string; }; export const LiteTextReadOnlyEditor = React.forwardRef( - ({ anchor, workspaceId, disabledExtensions, ...props }, ref) => { + ({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => { const { getMemberById } = useMember(); return ( , "disabledExtensions"> { + extends MakeOptional< + Omit, + "disabledExtensions" | "flaggedExtensions" + > { anchor: string; uploadFile: TFileHandler["upload"]; workspaceId: string; } export const RichTextEditor = forwardRef((props, ref) => { - const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, ...rest } = props; + const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props; const { getMemberById } = useMember(); return ( , - "disabledExtensions" + Omit, + "disabledExtensions" | "flaggedExtensions" > & { anchor: string; workspaceId: string; }; export const RichTextReadOnlyEditor = React.forwardRef( - ({ anchor, workspaceId, disabledExtensions, ...props }, ref) => { + ({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => { const { getMemberById } = useMember(); return ( Date: Wed, 18 Jun 2025 18:37:43 +0530 Subject: [PATCH 4/4] chore: export ce types --- packages/editor/src/ce/extensions/core/extensions.ts | 7 +++++-- .../src/ce/extensions/core/read-only-extensions.ts | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/ce/extensions/core/extensions.ts b/packages/editor/src/ce/extensions/core/extensions.ts index 5d1f5c9b598..a72bcc2159d 100644 --- a/packages/editor/src/ce/extensions/core/extensions.ts +++ b/packages/editor/src/ce/extensions/core/extensions.ts @@ -2,9 +2,12 @@ import type { Extensions } from "@tiptap/core"; // types import type { IEditorProps } from "@/types"; -type Props = Pick; +export type TCoreAdditionalExtensionsProps = Pick< + IEditorProps, + "disabledExtensions" | "flaggedExtensions" | "fileHandler" +>; -export const CoreEditorAdditionalExtensions = (props: Props): Extensions => { +export const CoreEditorAdditionalExtensions = (props: TCoreAdditionalExtensionsProps): Extensions => { const {} = props; return []; }; diff --git a/packages/editor/src/ce/extensions/core/read-only-extensions.ts b/packages/editor/src/ce/extensions/core/read-only-extensions.ts index 87868d955ef..4f9306da302 100644 --- a/packages/editor/src/ce/extensions/core/read-only-extensions.ts +++ b/packages/editor/src/ce/extensions/core/read-only-extensions.ts @@ -2,9 +2,14 @@ import type { Extensions } from "@tiptap/core"; // types import type { IReadOnlyEditorProps } from "@/types"; -type Props = Pick; +export type TCoreReadOnlyEditorAdditionalExtensionsProps = Pick< + IReadOnlyEditorProps, + "disabledExtensions" | "flaggedExtensions" +>; -export const CoreReadOnlyEditorAdditionalExtensions = (props: Props): Extensions => { +export const CoreReadOnlyEditorAdditionalExtensions = ( + props: TCoreReadOnlyEditorAdditionalExtensionsProps +): Extensions => { const {} = props; return []; };