[WEB-462] refactor: editor props structure (#7233)

* refactor: editor props structure

* chore: add missing prop

* fix: space app build

* chore: export ce types
This commit is contained in:
Aaryan Khandelwal 2025-06-19 16:25:52 +05:30 committed by GitHub
parent eb5ffebcc6
commit 8988cf9a85
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 348 additions and 347 deletions

View file

@ -1,13 +1,13 @@
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;
};
export type TCoreAdditionalExtensionsProps = Pick<
IEditorProps,
"disabledExtensions" | "flaggedExtensions" | "fileHandler"
>;
export const CoreEditorAdditionalExtensions = (props: Props): Extensions => {
export const CoreEditorAdditionalExtensions = (props: TCoreAdditionalExtensionsProps): Extensions => {
const {} = props;
return [];
};

View file

@ -1,12 +1,15 @@
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[];
};
export type TCoreReadOnlyEditorAdditionalExtensionsProps = Pick<
IReadOnlyEditorProps,
"disabledExtensions" | "flaggedExtensions"
>;
export const CoreReadOnlyEditorAdditionalExtensions = (props: Props): Extensions => {
export const CoreReadOnlyEditorAdditionalExtensions = (
props: TCoreReadOnlyEditorAdditionalExtensionsProps
): Extensions => {
const {} = props;
return [];
};

View file

@ -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;
};

View file

@ -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);

View file

@ -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

View file

@ -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<IEditorProps, "disabledExtensions" | "flaggedExtensions">;
export const coreEditorAdditionalSlashCommandOptions = (props: Props): TSlashCommandAdditionalOption[] => {
const {} = props;

View file

@ -13,10 +13,11 @@ 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<ICollaborativeDocumentEditorProps> = (props) => {
const {
onChange,
onTransaction,
aiHandler,
bubbleMenuEnabled = true,
@ -27,6 +28,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
editorClassName = "",
embedHandler,
fileHandler,
flaggedExtensions,
forwardedRef,
handleEditorReady,
id,
@ -56,10 +58,12 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
embedHandler,
extensions,
fileHandler,
flaggedExtensions,
forwardedRef,
handleEditorReady,
id,
mentionHandler,
onChange,
onTransaction,
placeholder,
realtimeConfig,
@ -95,7 +99,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
);
};
const CollaborativeDocumentEditorWithRef = React.forwardRef<EditorRefApi, ICollaborativeDocumentEditor>(
const CollaborativeDocumentEditorWithRef = React.forwardRef<EditorRefApi, ICollaborativeDocumentEditorProps>(
(props, ref) => (
<CollaborativeDocumentEditor {...props} forwardedRef={ref as React.MutableRefObject<EditorRefApi | null>} />
)

View file

@ -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 (

View file

@ -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<EditorReadOnlyRefApi | null>;
}
const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => {
const DocumentReadOnlyEditor: React.FC<IDocumentReadOnlyEditorProps> = (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<EditorReadOnlyRefApi, IDocumentReadOnlyEditor>((props, ref) => (
const DocumentReadOnlyEditorWithRef = forwardRef<EditorReadOnlyRefApi, IDocumentReadOnlyEditorProps>((props, ref) => (
<DocumentReadOnlyEditor {...props} forwardedRef={ref as MutableRefObject<EditorReadOnlyRefApi | null>} />
));

View file

@ -26,6 +26,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
id,
initialValue,
fileHandler,
flaggedExtensions,
forwardedRef,
mentionHandler,
onChange,
@ -44,6 +45,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
enableHistory: true,
extensions,
fileHandler,
flaggedExtensions,
forwardedRef,
id,
initialValue,

View file

@ -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<ILiteTextEditorProps> = (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 <EditorWrapper {...props} extensions={extensions} />;
};
const LiteTextEditorWithRef = forwardRef<EditorRefApi, ILiteTextEditor>((props, ref) => (
const LiteTextEditorWithRef = forwardRef<EditorRefApi, ILiteTextEditorProps>((props, ref) => (
<LiteTextEditor {...props} forwardedRef={ref as React.MutableRefObject<EditorRefApi | null>} />
));

View file

@ -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<EditorReadOnlyRefApi, ILiteTextReadOnlyEditor>((props, ref) => (
const LiteTextReadOnlyEditorWithRef = forwardRef<EditorReadOnlyRefApi, ILiteTextReadOnlyEditorProps>((props, ref) => (
<ReadOnlyEditorWrapper {...props} forwardedRef={ref as React.MutableRefObject<EditorReadOnlyRefApi | null>} />
));

View file

@ -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,

View file

@ -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<IRichTextEditorProps> = (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 (
<EditorWrapper {...props} extensions={getExtensions()}>
@ -41,7 +43,7 @@ const RichTextEditor = (props: IRichTextEditor) => {
);
};
const RichTextEditorWithRef = forwardRef<EditorRefApi, IRichTextEditor>((props, ref) => (
const RichTextEditorWithRef = forwardRef<EditorRefApi, IRichTextEditorProps>((props, ref) => (
<RichTextEditor {...props} forwardedRef={ref as React.MutableRefObject<EditorRefApi | null>} />
));

View file

@ -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<EditorReadOnlyRefApi, IRichTextReadOnlyEditor>((props, ref) => {
const { disabledExtensions, fileHandler } = props;
const RichTextReadOnlyEditorWithRef = forwardRef<EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps>((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 (
<ReadOnlyEditorWrapper

View file

@ -37,20 +37,27 @@ import { getExtensionStorage } from "@/helpers/get-extension-storage";
// plane editor extensions
import { CoreEditorAdditionalExtensions } from "@/plane-editor/extensions";
// types
import { TExtensions, TFileHandler, TMentionHandler } from "@/types";
import type { IEditorProps } from "@/types";
type TArguments = {
disabledExtensions: TExtensions[];
type TArguments = Pick<
IEditorProps,
"disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler" | "placeholder" | "tabIndex"
> & {
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,
}),
];

View file

@ -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<IReadOnlyEditorProps, "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler">;
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,
}),
];

View file

@ -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];

View file

@ -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<IEditorProps, "disabledExtensions" | "flaggedExtensions"> & {
additionalOptions?: TSlashCommandAdditionalOption[];
disabledExtensions?: TExtensions[];
};
export const SlashCommands = (props: TExtensionProps) =>

View file

@ -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<IEditorProps, "disabledExtensions"> & {
fileHandler: TFileHandler | TReadOnlyFileHandler;
isEditable: boolean;
};

View file

@ -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,

View file

@ -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<EditorRefApi | null>;
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,

View file

@ -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";
import type { TReadOnlyEditorHookProps } from "@/types";
interface CustomReadOnlyEditorProps {
disabledExtensions: TExtensions[];
editorClassName: string;
editorProps?: EditorProps;
extensions?: Extensions;
forwardedRef?: MutableRefObject<EditorReadOnlyRefApi | null>;
initialValue?: string;
fileHandler: TReadOnlyFileHandler;
handleEditorReady?: (value: boolean) => void;
mentionHandler: TReadOnlyMentionHandler;
provider?: HocuspocusProvider;
}
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,
],

View file

@ -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<EditorRefApi | null>;
mentionHandler: TMentionHandler;
placeholder?: string | ((isFocused: boolean, value: string) => string);
tabIndex?: number;
};
export type TReadOnlyCollaborativeEditorProps = TCollaborativeEditorHookProps & {
fileHandler: TReadOnlyFileHandler;
forwardedRef?: React.MutableRefObject<EditorReadOnlyRefApi | null>;
mentionHandler: TReadOnlyMentionHandler;
};

View file

@ -1,3 +1,6 @@
// plane imports
import { TWebhookConnectionQueryParams } from "@plane/types";
export type TReadOnlyFileHandler = {
checkIfAssetExists: (assetId: string) => Promise<boolean>;
getAssetSrc: (path: string) => Promise<string>;
@ -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;
};

View file

@ -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<EditorRefApi | null>;
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<IEditorProps, "initialValue" | "onChange" | "onEnterKeyPress" | "value"> {
export interface ICollaborativeDocumentEditorProps
extends Omit<IEditorProps, "extensions" | "initialValue" | "onEnterKeyPress" | "value"> {
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<EditorReadOnlyRefApi | null>;
id: string;
initialValue: string;
mentionHandler: TReadOnlyMentionHandler;
}
export type ILiteTextReadOnlyEditor = IReadOnlyEditorProps;
export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps;
export type IRichTextReadOnlyEditor = IReadOnlyEditorProps;
export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps;
export interface ICollaborativeDocumentReadOnlyEditor extends Omit<IReadOnlyEditorProps, "initialValue"> {
export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps {
embedHandler: TEmbedConfig;
handleEditorReady?: (value: boolean) => void;
id: string;
realtimeConfig: TRealtimeConfig;
serverHandler?: TServerHandler;
user: TUserDetails;
}
export interface IDocumentReadOnlyEditor 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;

View file

@ -0,0 +1,50 @@
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"
| "onChange"
| "onTransaction"
| "placeholder"
| "tabIndex"
> &
Pick<ICollaborativeDocumentEditorProps, "embedHandler" | "realtimeConfig" | "serverHandler" | "user">;
export type TReadOnlyEditorHookProps = TCoreHookProps &
Pick<TEditorHookProps, "initialValue" | "provider"> &
Pick<IReadOnlyEditorProps, "fileHandler" | "forwardedRef" | "mentionHandler">;

View file

@ -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";

View file

@ -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";

View file

@ -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<Omit<ILiteTextEditor, "fileHandler" | "mentionHandler">, "disabledExtensions"> {
extends MakeOptional<
Omit<ILiteTextEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> {
anchor: string;
workspaceId: string;
isSubmitting?: boolean;
@ -27,6 +30,7 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
showSubmitButton = true,
uploadFile,
disabledExtensions,
flaggedExtensions,
...rest
} = props;
function isMutableRefObject<T>(ref: React.ForwardedRef<T>): ref is React.MutableRefObject<T | null> {
@ -41,6 +45,7 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
<LiteTextEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
flaggedExtensions={flaggedExtensions ?? []}
fileHandler={getEditorFileHandlers({
anchor,
uploadFile,

View file

@ -1,6 +1,6 @@
import React from "react";
// plane imports
import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "@plane/editor";
import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditorProps, LiteTextReadOnlyEditorWithRef } from "@plane/editor";
import { MakeOptional } from "@plane/types";
import { cn } from "@plane/utils";
// components
@ -11,21 +11,22 @@ import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
import { useMember } from "@/hooks/store";
type LiteTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<ILiteTextReadOnlyEditor, "fileHandler" | "mentionHandler">,
"disabledExtensions"
Omit<ILiteTextReadOnlyEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> & {
anchor: string;
workspaceId: string;
};
export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>(
({ anchor, workspaceId, disabledExtensions, ...props }, ref) => {
({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => {
const { getMemberById } = useMember();
return (
<LiteTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
flaggedExtensions={flaggedExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,

View file

@ -1,6 +1,6 @@
import React, { forwardRef } from "react";
// plane imports
import { EditorRefApi, IRichTextEditor, RichTextEditorWithRef, TFileHandler } from "@plane/editor";
import { EditorRefApi, IRichTextEditorProps, RichTextEditorWithRef, TFileHandler } from "@plane/editor";
import { MakeOptional } from "@plane/types";
// components
import { EditorMentionsRoot } from "@/components/editor";
@ -10,14 +10,17 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper";
import { useMember } from "@/hooks/store";
interface RichTextEditorWrapperProps
extends MakeOptional<Omit<IRichTextEditor, "fileHandler" | "mentionHandler">, "disabledExtensions"> {
extends MakeOptional<
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> {
anchor: string;
uploadFile: TFileHandler["upload"];
workspaceId: string;
}
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, ...rest } = props;
const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props;
const { getMemberById } = useMember();
return (
<RichTextEditorWithRef
@ -34,6 +37,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
uploadFile,
workspaceId,
})}
flaggedExtensions={flaggedExtensions ?? []}
{...rest}
containerClassName={containerClassName}
editorClassName="min-h-[100px] max-h-[200px] border-[0.5px] border-custom-border-300 rounded-md pl-3 py-2 overflow-hidden"

View file

@ -1,6 +1,6 @@
import React from "react";
// plane imports
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/editor";
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor";
import { MakeOptional } from "@plane/types";
import { cn } from "@plane/utils";
// components
@ -11,21 +11,22 @@ import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
import { useMember } from "@/hooks/store";
type RichTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<IRichTextReadOnlyEditor, "fileHandler" | "mentionHandler">,
"disabledExtensions"
Omit<IRichTextReadOnlyEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> & {
anchor: string;
workspaceId: string;
};
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ anchor, workspaceId, disabledExtensions, ...props }, ref) => {
({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => {
const { getMemberById } = useMember();
return (
<RichTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
flaggedExtensions={flaggedExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,

View file

@ -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: [],
},
});

View file

@ -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<Omit<ILiteTextEditor, "fileHandler" | "mentionHandler">, "disabledExtensions"> {
extends MakeOptional<
Omit<ILiteTextEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> {
workspaceSlug: string;
workspaceId: string;
projectId?: string;
@ -55,13 +58,13 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
parentClassName = "",
placeholder = t("issue.comments.placeholder"),
uploadFile,
disabledExtensions: additionalDisabledExtensions,
disabledExtensions: additionalDisabledExtensions = [],
...rest
} = props;
// states
const [isFocused, setIsFocused] = useState(showToolbarInitially);
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
const { liteText: liteTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// store hooks
const { getUserDetails } = useMember();
// use editor mention
@ -90,7 +93,8 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
>
<LiteTextEditorWithRef
ref={ref}
disabledExtensions={[...disabledExtensions, ...(additionalDisabledExtensions ?? [])]}
disabledExtensions={[...liteTextEditorExtensions.disabled, ...additionalDisabledExtensions]}
flaggedExtensions={liteTextEditorExtensions.flagged}
fileHandler={getEditorFileHandlers({
projectId,
uploadFile,

View file

@ -1,6 +1,6 @@
import React from "react";
// plane imports
import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "@plane/editor";
import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditorProps, LiteTextReadOnlyEditorWithRef } from "@plane/editor";
import { MakeOptional } from "@plane/types";
// components
import { cn } from "@plane/utils";
@ -14,8 +14,8 @@ import { useMember } from "@/hooks/store";
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
type LiteTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<ILiteTextReadOnlyEditor, "fileHandler" | "mentionHandler">,
"disabledExtensions"
Omit<ILiteTextReadOnlyEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> & {
workspaceId: string;
workspaceSlug: string;
@ -28,14 +28,15 @@ export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Lit
const { getUserDetails } = useMember();
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
const { liteText: liteTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// editor config
const { getReadOnlyEditorFileHandlers } = useEditorConfig();
return (
<LiteTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={[...disabledExtensions, ...(additionalDisabledExtensions ?? [])]}
disabledExtensions={[...liteTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
flaggedExtensions={liteTextEditorExtensions.flagged}
fileHandler={getReadOnlyEditorFileHandlers({
projectId,
workspaceId,

View file

@ -1,6 +1,6 @@
import React, { forwardRef } from "react";
// plane imports
import { EditorRefApi, IRichTextEditor, RichTextEditorWithRef, TFileHandler } from "@plane/editor";
import { EditorRefApi, IRichTextEditorProps, RichTextEditorWithRef, TFileHandler } from "@plane/editor";
import { MakeOptional, TSearchEntityRequestPayload, TSearchResponse } from "@plane/types";
// components
import { cn } from "@plane/utils";
@ -14,7 +14,10 @@ import { useMember } from "@/hooks/store";
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
interface RichTextEditorWrapperProps
extends MakeOptional<Omit<IRichTextEditor, "fileHandler" | "mentionHandler">, "disabledExtensions"> {
extends MakeOptional<
Omit<IRichTextEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> {
searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
workspaceSlug: string;
workspaceId: string;
@ -36,7 +39,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
// store hooks
const { getUserDetails } = useMember();
// editor flaggings
const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// use editor mention
const { fetchMentions } = useEditorMention({
searchEntity: async (payload) => await searchMentionCallback(payload),
@ -47,7 +50,8 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
return (
<RichTextEditorWithRef
ref={ref}
disabledExtensions={[...disabledExtensions, ...(additionalDisabledExtensions ?? [])]}
disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
flaggedExtensions={richTextEditorExtensions.flagged}
fileHandler={getEditorFileHandlers({
projectId,
uploadFile,

View file

@ -2,7 +2,7 @@
import React from "react";
// plane imports
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/editor";
import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor";
import { MakeOptional } from "@plane/types";
// components
import { cn } from "@plane/utils";
@ -16,8 +16,8 @@ import { useMember } from "@/hooks/store";
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
type RichTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<IRichTextReadOnlyEditor, "fileHandler" | "mentionHandler">,
"disabledExtensions"
Omit<IRichTextReadOnlyEditorProps, "fileHandler" | "mentionHandler">,
"disabledExtensions" | "flaggedExtensions"
> & {
workspaceId: string;
workspaceSlug: string;
@ -30,14 +30,15 @@ export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Ric
const { getUserDetails } = useMember();
// editor flaggings
const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
const { richText: richTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// editor config
const { getReadOnlyEditorFileHandlers } = useEditorConfig();
return (
<RichTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={[...disabledExtensions, ...(additionalDisabledExtensions ?? [])]}
disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
flaggedExtensions={richTextEditorExtensions.flagged}
fileHandler={getReadOnlyEditorFileHandlers({
projectId,
workspaceId,

View file

@ -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";
// components
import { TSticky } from "@plane/types";
// helpers
@ -14,7 +14,7 @@ import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
import { StickyEditorToolbar } from "./toolbar";
interface StickyEditorWrapperProps
extends Omit<ILiteTextEditor, "disabledExtensions" | "fileHandler" | "mentionHandler"> {
extends Omit<ILiteTextEditorProps, "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler"> {
workspaceSlug: string;
workspaceId: string;
projectId?: string;
@ -48,7 +48,7 @@ export const StickyEditor = React.forwardRef<EditorRefApi, StickyEditorWrapperPr
// states
const [isFocused, setIsFocused] = useState(showToolbarInitially);
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
const { liteText: liteTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
// editor config
const { getEditorFileHandlers } = useEditorConfig();
function isMutableRefObject<T>(ref: React.ForwardedRef<T>): ref is React.MutableRefObject<T | null> {
@ -65,7 +65,8 @@ export const StickyEditor = React.forwardRef<EditorRefApi, StickyEditorWrapperPr
>
<LiteTextEditorWithRef
ref={ref}
disabledExtensions={[...disabledExtensions, "enter-key"]}
disabledExtensions={[...liteTextEditorExtensions.disabled, "enter-key"]}
flaggedExtensions={liteTextEditorExtensions.flagged}
fileHandler={getEditorFileHandlers({
projectId,
uploadFile,

View file

@ -81,7 +81,7 @@ export const PageEditorBody: React.FC<Props> = 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<Props> = observer((props) => {
realtimeConfig={realtimeConfig}
serverHandler={serverHandler}
user={userConfig}
disabledExtensions={disabledExtensions}
disabledExtensions={documentEditorExtensions.disabled}
flaggedExtensions={documentEditorExtensions.flagged}
aiHandler={{
menu: getAIMenu,
}}

View file

@ -32,7 +32,7 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = 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<TVersionEditorProps> = observer((props
id={activeVersion ?? ""}
initialValue={description ?? "<p></p>"}
containerClassName="p-0 pb-64 border-none"
disabledExtensions={disabledExtensions}
disabledExtensions={documentEditorExtensions.disabled}
flaggedExtensions={documentEditorExtensions.flagged}
displayConfig={displayConfig}
editorClassName="pl-10"
fileHandler={getReadOnlyEditorFileHandlers({