From dc8c2dca95bba19c7dc1da8b70359ecb9f87e36d Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Mon, 2 Jun 2025 19:48:39 +0530 Subject: [PATCH 01/26] chore: refactor editor --- .../editor/src/ce/components/link-container.tsx | 14 ++++++++++++++ .../editors/document/collaborative-editor.tsx | 1 + .../editors/document/page-renderer.tsx | 16 +++++++++++++--- .../editors/document/read-only-editor.tsx | 1 + .../core/components/editors/editor-container.tsx | 4 ++-- .../components/editors/link-view-container.tsx | 5 +++-- .../src/core/components/menus/block-menu.tsx | 2 ++ .../core/extensions/custom-link/extension.tsx | 1 + 8 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 packages/editor/src/ce/components/link-container.tsx diff --git a/packages/editor/src/ce/components/link-container.tsx b/packages/editor/src/ce/components/link-container.tsx new file mode 100644 index 00000000000..dcbedc0880d --- /dev/null +++ b/packages/editor/src/ce/components/link-container.tsx @@ -0,0 +1,14 @@ +import { Editor } from "@tiptap/core"; +import { LinkViewContainer } from "@/components/editors/link-view-container"; + +export const LinkContainer = ({ + editor, + containerRef, +}: { + editor: Editor; + containerRef: React.RefObject; +}) => ( + <> + + +); 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..c072614cecd 100644 --- a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx +++ b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx @@ -91,6 +91,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => { editorContainerClassName={cn(editorContainerClassNames, "document-editor")} id={id} tabIndex={tabIndex} + disabledExtensions={disabledExtensions} /> ); }; 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..c65ed5c0fb6 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -3,7 +3,7 @@ import { Editor } from "@tiptap/react"; import { EditorContainer, EditorContentWrapper } from "@/components/editors"; import { AIFeaturesMenu, BlockMenu, EditorBubbleMenu } from "@/components/menus"; // types -import { TAIHandler, TDisplayConfig } from "@/types"; +import { TAIHandler, TDisplayConfig, TExtensions } from "@/types"; type IPageRenderer = { aiHandler?: TAIHandler; @@ -13,10 +13,20 @@ type IPageRenderer = { editorContainerClassName: string; id: string; tabIndex?: number; + disabledExtensions: TExtensions[]; }; export const PageRenderer = (props: IPageRenderer) => { - const { aiHandler, bubbleMenuEnabled, displayConfig, editor, editorContainerClassName, id, tabIndex } = props; + const { + aiHandler, + bubbleMenuEnabled, + displayConfig, + editor, + editorContainerClassName, + id, + tabIndex, + disabledExtensions, + } = props; return (
@@ -30,7 +40,7 @@ export const PageRenderer = (props: IPageRenderer) => { {editor.isEditable && (
{bubbleMenuEnabled && } - +
)} 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..33759c703ee 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 @@ -83,6 +83,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { editor={editor} editorContainerClassName={cn(editorContainerClassName, "document-editor")} id={id} + disabledExtensions={disabledExtensions} /> ); }; diff --git a/packages/editor/src/core/components/editors/editor-container.tsx b/packages/editor/src/core/components/editors/editor-container.tsx index 6daa0719a0f..c1b92e09575 100644 --- a/packages/editor/src/core/components/editors/editor-container.tsx +++ b/packages/editor/src/core/components/editors/editor-container.tsx @@ -6,9 +6,9 @@ import { cn } from "@plane/utils"; import { DEFAULT_DISPLAY_CONFIG } from "@/constants/config"; import { CORE_EXTENSIONS } from "@/constants/extension"; // types +import { LinkContainer } from "@/plane-editor/components/link-container"; import { TDisplayConfig } from "@/types"; // components -import { LinkViewContainer } from "./link-view-container"; interface EditorContainerProps { children: ReactNode; @@ -96,7 +96,7 @@ export const EditorContainer: FC = (props) => { )} > {children} - +
); diff --git a/packages/editor/src/core/components/editors/link-view-container.tsx b/packages/editor/src/core/components/editors/link-view-container.tsx index 68fa33dde4f..0ace55d19ba 100644 --- a/packages/editor/src/core/components/editors/link-view-container.tsx +++ b/packages/editor/src/core/components/editors/link-view-container.tsx @@ -3,6 +3,7 @@ import { Editor, useEditorState } from "@tiptap/react"; import { FC, useCallback, useEffect, useState } from "react"; // components import { LinkView, LinkViewProps } from "@/components/links"; +import { getExtensionStorage } from "@/helpers/get-extension-storage"; interface LinkViewContainerProps { editor: Editor; @@ -17,7 +18,7 @@ export const LinkViewContainer: FC = ({ editor, containe const editorState = useEditorState({ editor, selector: ({ editor }: { editor: Editor }) => ({ - linkExtensionStorage: editor.storage.link, + linkExtensionStorage: getExtensionStorage(editor, "link"), }), }); @@ -46,7 +47,7 @@ export const LinkViewContainer: FC = ({ editor, containe const handleLinkHover = useCallback( (event: MouseEvent) => { - if (!editor || editorState.linkExtensionStorage.isBubbleMenuOpen) return; + if (!editor || editorState.linkExtensionStorage?.isBubbleMenuOpen) return; // Find the closest anchor tag from the event target const target = (event.target as HTMLElement)?.closest("a"); diff --git a/packages/editor/src/core/components/menus/block-menu.tsx b/packages/editor/src/core/components/menus/block-menu.tsx index bd86628cb32..ecdacc47896 100644 --- a/packages/editor/src/core/components/menus/block-menu.tsx +++ b/packages/editor/src/core/components/menus/block-menu.tsx @@ -4,9 +4,11 @@ import { useCallback, useEffect, useRef } from "react"; import tippy, { Instance } from "tippy.js"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; +import { TExtensions } from "@/types"; interface BlockMenuProps { editor: Editor; + disabledExtensions?: TExtensions[]; } export const BlockMenu = (props: BlockMenuProps) => { diff --git a/packages/editor/src/core/extensions/custom-link/extension.tsx b/packages/editor/src/core/extensions/custom-link/extension.tsx index 182afc9f8fe..d794a646da9 100644 --- a/packages/editor/src/core/extensions/custom-link/extension.tsx +++ b/packages/editor/src/core/extensions/custom-link/extension.tsx @@ -79,6 +79,7 @@ declare module "@tiptap/core" { export type CustomLinkStorage = { isPreviewOpen: boolean; posToInsert: { from: number; to: number }; + isBubbleMenuOpen: boolean; }; export const CustomLinkExtension = Mark.create({ From d9bcc1e12d52de7093a01537a2ddac6713072bc5 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 12:29:25 +0530 Subject: [PATCH 02/26] sync changes --- live/src/core/services/api.service.ts | 1 + .../editor/src/ce/components/link-container.tsx | 14 -------------- .../core/components/editors/editor-container.tsx | 4 ++-- .../components/editors/link-view-container.tsx | 6 ++++-- 4 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 packages/editor/src/ce/components/link-container.tsx diff --git a/live/src/core/services/api.service.ts b/live/src/core/services/api.service.ts index 1aa5cf9e53c..def19f65add 100644 --- a/live/src/core/services/api.service.ts +++ b/live/src/core/services/api.service.ts @@ -14,6 +14,7 @@ export abstract class APIService { this.axiosInstance = axios.create({ baseURL, withCredentials: true, + timeout: 20000, }); } diff --git a/packages/editor/src/ce/components/link-container.tsx b/packages/editor/src/ce/components/link-container.tsx deleted file mode 100644 index dcbedc0880d..00000000000 --- a/packages/editor/src/ce/components/link-container.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Editor } from "@tiptap/core"; -import { LinkViewContainer } from "@/components/editors/link-view-container"; - -export const LinkContainer = ({ - editor, - containerRef, -}: { - editor: Editor; - containerRef: React.RefObject; -}) => ( - <> - - -); diff --git a/packages/editor/src/core/components/editors/editor-container.tsx b/packages/editor/src/core/components/editors/editor-container.tsx index c1b92e09575..4cd149a915c 100644 --- a/packages/editor/src/core/components/editors/editor-container.tsx +++ b/packages/editor/src/core/components/editors/editor-container.tsx @@ -3,10 +3,10 @@ import { FC, ReactNode, useRef } from "react"; // plane utils import { cn } from "@plane/utils"; // constants +import { LinkViewContainer } from "@/components/editors/link-view-container"; import { DEFAULT_DISPLAY_CONFIG } from "@/constants/config"; import { CORE_EXTENSIONS } from "@/constants/extension"; // types -import { LinkContainer } from "@/plane-editor/components/link-container"; import { TDisplayConfig } from "@/types"; // components @@ -96,7 +96,7 @@ export const EditorContainer: FC = (props) => { )} > {children} - + ); diff --git a/packages/editor/src/core/components/editors/link-view-container.tsx b/packages/editor/src/core/components/editors/link-view-container.tsx index 0ace55d19ba..4d75fd16d9f 100644 --- a/packages/editor/src/core/components/editors/link-view-container.tsx +++ b/packages/editor/src/core/components/editors/link-view-container.tsx @@ -1,8 +1,10 @@ import { autoUpdate, flip, hide, shift, useDismiss, useFloating, useInteractions } from "@floating-ui/react"; import { Editor, useEditorState } from "@tiptap/react"; import { FC, useCallback, useEffect, useState } from "react"; -// components + import { LinkView, LinkViewProps } from "@/components/links"; +import { CORE_EXTENSIONS } from "@/constants/extension"; +// components import { getExtensionStorage } from "@/helpers/get-extension-storage"; interface LinkViewContainerProps { @@ -18,7 +20,7 @@ export const LinkViewContainer: FC = ({ editor, containe const editorState = useEditorState({ editor, selector: ({ editor }: { editor: Editor }) => ({ - linkExtensionStorage: getExtensionStorage(editor, "link"), + linkExtensionStorage: getExtensionStorage(editor, CORE_EXTENSIONS.CUSTOM_LINK), }), }); From 0d7b5cbfdf224151f17e90c038669b3a4896a108 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 14:55:31 +0530 Subject: [PATCH 03/26] feat: api service update --- space/core/services/api.service.ts | 57 +++++++++++++++++++++++++ space/core/services/iframely.service.ts | 25 +++++++++++ web/core/services/iframely.service.ts | 25 +++++++++++ 3 files changed, 107 insertions(+) create mode 100644 space/core/services/api.service.ts create mode 100644 space/core/services/iframely.service.ts create mode 100644 web/core/services/iframely.service.ts diff --git a/space/core/services/api.service.ts b/space/core/services/api.service.ts new file mode 100644 index 00000000000..944990a05c2 --- /dev/null +++ b/space/core/services/api.service.ts @@ -0,0 +1,57 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import axios, { AxiosInstance, AxiosRequestConfig } from "axios"; + +export abstract class APIService { + protected baseURL: string; + private axiosInstance: AxiosInstance; + + constructor(baseURL: string) { + this.baseURL = baseURL; + this.axiosInstance = axios.create({ + baseURL, + withCredentials: true, + }); + + this.setupInterceptors(); + } + + private setupInterceptors() { + this.axiosInstance.interceptors.response.use( + (response) => response, + (error) => { + if (error.response && error.response.status === 401) { + const currentPath = window.location.pathname; + window.location.replace(`/${currentPath ? `?next_path=${currentPath}` : ``}`); + } + return Promise.reject(error); + } + ); + } + + get(url: string, params = {}, config: AxiosRequestConfig = {}) { + return this.axiosInstance.get(url, { + ...params, + ...config, + }); + } + + post(url: string, data = {}, config: AxiosRequestConfig = {}) { + return this.axiosInstance.post(url, data, config); + } + + put(url: string, data = {}, config: AxiosRequestConfig = {}) { + return this.axiosInstance.put(url, data, config); + } + + patch(url: string, data = {}, config: AxiosRequestConfig = {}) { + return this.axiosInstance.patch(url, data, config); + } + + delete(url: string, data?: any, config: AxiosRequestConfig = {}) { + return this.axiosInstance.delete(url, { data, ...config }); + } + + request(config = {}) { + return this.axiosInstance(config); + } +} diff --git a/space/core/services/iframely.service.ts b/space/core/services/iframely.service.ts new file mode 100644 index 00000000000..fc5517764d2 --- /dev/null +++ b/space/core/services/iframely.service.ts @@ -0,0 +1,25 @@ +import { LIVE_URL } from "@plane/constants"; +import { APIService } from "./api.service"; + +export class IframelyService extends APIService { + constructor() { + super(LIVE_URL); + } + + /** + * Fetches embed data for a URL from the iframely service + */ + async getEmbedData(url: string, isDarkTheme: boolean = false): Promise { + const response = await this.get( + `/iframely?url=${encodeURIComponent(url)}${isDarkTheme ? "&_theme=dark" : ""}`, + {}, + { + withCredentials: false, + } + ); + return response.data; + } +} + +// Create a singleton instance +export const iframelyService = new IframelyService(); diff --git a/web/core/services/iframely.service.ts b/web/core/services/iframely.service.ts new file mode 100644 index 00000000000..34a9148f845 --- /dev/null +++ b/web/core/services/iframely.service.ts @@ -0,0 +1,25 @@ +import { LIVE_URL } from "@plane/constants"; +import { APIService } from "./api.service"; + +export class IframelyService extends APIService { + constructor() { + super(LIVE_URL); + } + + /** + * Fetches embed data for a URL from the iframely service + */ + async getEmbedData(url: string, isDarkTheme: boolean = false, workspaceSlug: string, userId: string): Promise { + const response = await this.get( + `/iframely?url=${encodeURIComponent(url)}${isDarkTheme ? "&_theme=dark" : "&_theme=light"}&workspaceSlug=${workspaceSlug}&userId=${userId}`, + {}, + { + withCredentials: true, + } + ); + return response.data; + } +} + +// Create a singleton instance +export const iframelyService = new IframelyService(); From 98386a029589828df0a4de24da97d41a5f9debfc Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 16:00:59 +0530 Subject: [PATCH 04/26] refactor : update sync --- .../editors/document/page-renderer.tsx | 3 +- .../editor/src/core/plugins/drag-handle.ts | 5 ++ packages/editor/src/core/types/editor.ts | 5 +- packages/editor/src/core/types/extensions.ts | 9 ++- packages/editor/src/styles/drag-drop.css | 6 +- space/core/services/api.service.ts | 57 ------------------- space/core/services/iframely.service.ts | 25 -------- space/helpers/string.helper.ts | 8 ++- .../editor/external-embed/embed-handler.tsx | 3 + web/core/services/iframely.service.ts | 25 -------- 10 files changed, 31 insertions(+), 115 deletions(-) delete mode 100644 space/core/services/api.service.ts delete mode 100644 space/core/services/iframely.service.ts create mode 100644 web/ce/components/pages/editor/external-embed/embed-handler.tsx delete mode 100644 web/core/services/iframely.service.ts 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 ec75db0ff85..d1e11d4a974 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -16,7 +16,7 @@ type Props = { disabledExtensions: TExtensions[]; }; -export const PageRenderer = (props: IPageRenderer) => { +export const PageRenderer = (props: Props) => { const { aiHandler, bubbleMenuEnabled, @@ -28,7 +28,6 @@ export const PageRenderer = (props: IPageRenderer) => { disabledExtensions, } = props; - return (
{ continue; } + // Skip elements inside .data-embed + if (elem.closest(".data-embed") && !elem.matches(".data-embed")) { + continue; + } + // apply general selector if (elem.matches(generalSelectors)) { return elem; diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index cf3d7d2c7f8..418884871f7 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -46,8 +46,9 @@ export type TEditorCommands = | "background-color" | "text-align" | "callout" - | "attachment"; - + | "attachment" + | "external-embed" + | "rich-card"; export type TCommandExtraProps = { image: { savedSelection: Selection | null; diff --git a/packages/editor/src/core/types/extensions.ts b/packages/editor/src/core/types/extensions.ts index 8c1c0a48038..b30409c1261 100644 --- a/packages/editor/src/core/types/extensions.ts +++ b/packages/editor/src/core/types/extensions.ts @@ -1 +1,8 @@ -export type TExtensions = "ai" | "collaboration-cursor" | "issue-embed" | "slash-commands" | "enter-key" | "image"; +export type TExtensions = + | "ai" + | "collaboration-cursor" + | "issue-embed" + | "slash-commands" + | "enter-key" + | "image" + | "external-embed"; diff --git a/packages/editor/src/styles/drag-drop.css b/packages/editor/src/styles/drag-drop.css index 7db6ed87554..ea01b7be33f 100644 --- a/packages/editor/src/styles/drag-drop.css +++ b/packages/editor/src/styles/drag-drop.css @@ -35,7 +35,8 @@ } /* end ai handle */ -.ProseMirror:not(.dragging) .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image) { +.ProseMirror:not(.dragging) + .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image):not(.node-externalEmbedComponent) { position: relative; cursor: grab; outline: none !important; @@ -61,7 +62,8 @@ } &.node-imageComponent, - &.node-image { + &.node-image, + &.node-externalEmbedComponent { --horizontal-offset: 0px; &::after { diff --git a/space/core/services/api.service.ts b/space/core/services/api.service.ts deleted file mode 100644 index 944990a05c2..00000000000 --- a/space/core/services/api.service.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import axios, { AxiosInstance, AxiosRequestConfig } from "axios"; - -export abstract class APIService { - protected baseURL: string; - private axiosInstance: AxiosInstance; - - constructor(baseURL: string) { - this.baseURL = baseURL; - this.axiosInstance = axios.create({ - baseURL, - withCredentials: true, - }); - - this.setupInterceptors(); - } - - private setupInterceptors() { - this.axiosInstance.interceptors.response.use( - (response) => response, - (error) => { - if (error.response && error.response.status === 401) { - const currentPath = window.location.pathname; - window.location.replace(`/${currentPath ? `?next_path=${currentPath}` : ``}`); - } - return Promise.reject(error); - } - ); - } - - get(url: string, params = {}, config: AxiosRequestConfig = {}) { - return this.axiosInstance.get(url, { - ...params, - ...config, - }); - } - - post(url: string, data = {}, config: AxiosRequestConfig = {}) { - return this.axiosInstance.post(url, data, config); - } - - put(url: string, data = {}, config: AxiosRequestConfig = {}) { - return this.axiosInstance.put(url, data, config); - } - - patch(url: string, data = {}, config: AxiosRequestConfig = {}) { - return this.axiosInstance.patch(url, data, config); - } - - delete(url: string, data?: any, config: AxiosRequestConfig = {}) { - return this.axiosInstance.delete(url, { data, ...config }); - } - - request(config = {}) { - return this.axiosInstance(config); - } -} diff --git a/space/core/services/iframely.service.ts b/space/core/services/iframely.service.ts deleted file mode 100644 index fc5517764d2..00000000000 --- a/space/core/services/iframely.service.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { LIVE_URL } from "@plane/constants"; -import { APIService } from "./api.service"; - -export class IframelyService extends APIService { - constructor() { - super(LIVE_URL); - } - - /** - * Fetches embed data for a URL from the iframely service - */ - async getEmbedData(url: string, isDarkTheme: boolean = false): Promise { - const response = await this.get( - `/iframely?url=${encodeURIComponent(url)}${isDarkTheme ? "&_theme=dark" : ""}`, - {}, - { - withCredentials: false, - } - ); - return response.data; - } -} - -// Create a singleton instance -export const iframelyService = new IframelyService(); diff --git a/space/helpers/string.helper.ts b/space/helpers/string.helper.ts index dc838596a67..d816e9933e5 100644 --- a/space/helpers/string.helper.ts +++ b/space/helpers/string.helper.ts @@ -71,7 +71,13 @@ export const isCommentEmpty = (comment: string | undefined): boolean => { return ( comment?.trim() === "" || comment === "

" || - isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"]) + isEmptyHtmlString(comment ?? "", [ + "img", + "mention-component", + "image-component", + "embed-component", + `div[data-embed]`, + ]) ); }; diff --git a/web/ce/components/pages/editor/external-embed/embed-handler.tsx b/web/ce/components/pages/editor/external-embed/embed-handler.tsx new file mode 100644 index 00000000000..8d1da017ac0 --- /dev/null +++ b/web/ce/components/pages/editor/external-embed/embed-handler.tsx @@ -0,0 +1,3 @@ +import { NodeViewProps } from "@tiptap/react"; + +export const EmbedHandler: React.FC = () =>
; diff --git a/web/core/services/iframely.service.ts b/web/core/services/iframely.service.ts deleted file mode 100644 index 34a9148f845..00000000000 --- a/web/core/services/iframely.service.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { LIVE_URL } from "@plane/constants"; -import { APIService } from "./api.service"; - -export class IframelyService extends APIService { - constructor() { - super(LIVE_URL); - } - - /** - * Fetches embed data for a URL from the iframely service - */ - async getEmbedData(url: string, isDarkTheme: boolean = false, workspaceSlug: string, userId: string): Promise { - const response = await this.get( - `/iframely?url=${encodeURIComponent(url)}${isDarkTheme ? "&_theme=dark" : "&_theme=light"}&workspaceSlug=${workspaceSlug}&userId=${userId}`, - {}, - { - withCredentials: true, - } - ); - return response.data; - } -} - -// Create a singleton instance -export const iframelyService = new IframelyService(); From a435baaeed135743c7ba989f26cc2f449bec3be9 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 16:46:40 +0530 Subject: [PATCH 05/26] fix : package sync --- .../src/core/components/editors/link-view-container.tsx | 2 +- packages/editor/src/core/types/editor.ts | 2 ++ packages/editor/src/core/types/hook.ts | 3 ++- space/ce/components/editor/external-embed/embed-handler.tsx | 6 ++++++ 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 space/ce/components/editor/external-embed/embed-handler.tsx diff --git a/packages/editor/src/core/components/editors/link-view-container.tsx b/packages/editor/src/core/components/editors/link-view-container.tsx index 4d75fd16d9f..2a15acb996b 100644 --- a/packages/editor/src/core/components/editors/link-view-container.tsx +++ b/packages/editor/src/core/components/editors/link-view-container.tsx @@ -112,7 +112,7 @@ export const LinkViewContainer: FC = ({ editor, containe // Close link view when bubble menu opens useEffect(() => { - if (editorState.linkExtensionStorage.isBubbleMenuOpen && isOpen) { + if (editorState.linkExtensionStorage?.isBubbleMenuOpen && isOpen) { setIsOpen(false); } }, [editorState.linkExtensionStorage, isOpen]); diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index 418884871f7..3be00d6f4ae 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -129,6 +129,7 @@ export interface IEditorProps { id: string; initialValue: string; mentionHandler: TMentionHandler; + embedHandler?: TEmbedConfig; onChange?: (json: object, html: string) => void; onEnterKeyPress?: (e?: any) => void; onTransaction?: () => void; @@ -159,6 +160,7 @@ export interface IReadOnlyEditorProps | "containerClassName" | "disabledExtensions" | "flaggedExtensions" + | "embedHandler" | "displayConfig" | "editorClassName" | "extensions" diff --git a/packages/editor/src/core/types/hook.ts b/packages/editor/src/core/types/hook.ts index 2224935ca91..09f5df8c280 100644 --- a/packages/editor/src/core/types/hook.ts +++ b/packages/editor/src/core/types/hook.ts @@ -23,6 +23,7 @@ export type TEditorHookProps = TCoreHookProps & | "placeholder" | "tabIndex" | "value" + | "embedHandler" > & { editable: boolean; enableHistory: boolean; @@ -47,4 +48,4 @@ export type TCollaborativeEditorHookProps = TCoreHookProps & export type TReadOnlyEditorHookProps = TCoreHookProps & Pick & - Pick; + Pick; diff --git a/space/ce/components/editor/external-embed/embed-handler.tsx b/space/ce/components/editor/external-embed/embed-handler.tsx new file mode 100644 index 00000000000..35c52c6a9eb --- /dev/null +++ b/space/ce/components/editor/external-embed/embed-handler.tsx @@ -0,0 +1,6 @@ +import { NodeViewProps } from "@tiptap/react"; + +interface EmbedHandlerProps extends NodeViewProps { + anchor?: string; +} +export const EmbedHandler: React.FC = () =>
; From a92b48254a27c3dab9f40685f17fb77af43414af Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 19:21:03 +0530 Subject: [PATCH 06/26] fix: requested changes --- .../components/editors/document/page-renderer.tsx | 4 ++-- .../editor/src/core/components/menus/block-menu.tsx | 4 ++-- packages/editor/src/core/plugins/drag-handle.ts | 4 ++-- packages/editor/src/core/types/editor.ts | 12 ++++++------ .../editor/external-embed/embed-handler.tsx | 2 +- space/helpers/string.helper.ts | 8 +------- .../pages/editor/external-embed/embed-handler.tsx | 2 +- 7 files changed, 15 insertions(+), 21 deletions(-) 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 d1e11d4a974..861dc9f3288 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -3,7 +3,7 @@ import { Editor } from "@tiptap/react"; import { EditorContainer, EditorContentWrapper } from "@/components/editors"; import { AIFeaturesMenu, BlockMenu, EditorBubbleMenu } from "@/components/menus"; // types -import { TAIHandler, TDisplayConfig, TExtensions } from "@/types"; +import { IEditorProps, TAIHandler, TDisplayConfig } from "@/types"; type Props = { aiHandler?: TAIHandler; @@ -13,7 +13,7 @@ type Props = { editorContainerClassName: string; id: string; tabIndex?: number; - disabledExtensions: TExtensions[]; + disabledExtensions: IEditorProps["disabledExtensions"]; }; export const PageRenderer = (props: Props) => { diff --git a/packages/editor/src/core/components/menus/block-menu.tsx b/packages/editor/src/core/components/menus/block-menu.tsx index ecdacc47896..abb2495a7e7 100644 --- a/packages/editor/src/core/components/menus/block-menu.tsx +++ b/packages/editor/src/core/components/menus/block-menu.tsx @@ -4,11 +4,11 @@ import { useCallback, useEffect, useRef } from "react"; import tippy, { Instance } from "tippy.js"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; -import { TExtensions } from "@/types"; +import { IEditorProps } from "@/types"; interface BlockMenuProps { editor: Editor; - disabledExtensions?: TExtensions[]; + disabledExtensions: IEditorProps["disabledExtensions"]; } export const BlockMenu = (props: BlockMenuProps) => { diff --git a/packages/editor/src/core/plugins/drag-handle.ts b/packages/editor/src/core/plugins/drag-handle.ts index 226efc6d709..800b66c7bf7 100644 --- a/packages/editor/src/core/plugins/drag-handle.ts +++ b/packages/editor/src/core/plugins/drag-handle.ts @@ -103,8 +103,8 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => { continue; } - // Skip elements inside .data-embed - if (elem.closest(".data-embed") && !elem.matches(".data-embed")) { + // Skip elements inside .editor-embed-component + if (elem.closest(".editor-embed-component") && !elem.matches(".editor-embed-component")) { continue; } diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index 3be00d6f4ae..267ca469fa6 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -113,8 +113,12 @@ export interface EditorRefApi extends EditorReadOnlyRefApi { listenToRealTimeUpdate: () => TDocumentEventEmitter | undefined; } +type TEmbedHandlerProps = { + embedHandler?: TEmbedConfig; +}; + // editor props -export interface IEditorProps { +export interface IEditorProps extends TEmbedHandlerProps { autofocus?: boolean; bubbleMenuEnabled?: boolean; containerClassName?: string; @@ -129,7 +133,6 @@ export interface IEditorProps { id: string; initialValue: string; mentionHandler: TMentionHandler; - embedHandler?: TEmbedConfig; onChange?: (json: object, html: string) => void; onEnterKeyPress?: (e?: any) => void; onTransaction?: () => void; @@ -147,7 +150,6 @@ export interface ICollaborativeDocumentEditorProps extends Omit { aiHandler?: TAIHandler; editable: boolean; - embedHandler: TEmbedConfig; realtimeConfig: TRealtimeConfig; serverHandler?: TServerHandler; user: TUserDetails; @@ -177,9 +179,7 @@ export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps; export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps; -export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps { - embedHandler: TEmbedConfig; -} +export type IDocumentReadOnlyEditorProps = IReadOnlyEditorProps; export interface EditorEvents { beforeCreate: never; diff --git a/space/ce/components/editor/external-embed/embed-handler.tsx b/space/ce/components/editor/external-embed/embed-handler.tsx index 35c52c6a9eb..5eb7bb0b781 100644 --- a/space/ce/components/editor/external-embed/embed-handler.tsx +++ b/space/ce/components/editor/external-embed/embed-handler.tsx @@ -3,4 +3,4 @@ import { NodeViewProps } from "@tiptap/react"; interface EmbedHandlerProps extends NodeViewProps { anchor?: string; } -export const EmbedHandler: React.FC = () =>
; +export const EmbedHandler: React.FC = () => null; diff --git a/space/helpers/string.helper.ts b/space/helpers/string.helper.ts index d816e9933e5..879ecc3660b 100644 --- a/space/helpers/string.helper.ts +++ b/space/helpers/string.helper.ts @@ -71,13 +71,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => { return ( comment?.trim() === "" || comment === "

" || - isEmptyHtmlString(comment ?? "", [ - "img", - "mention-component", - "image-component", - "embed-component", - `div[data-embed]`, - ]) + isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component", "embed-component"]) ); }; diff --git a/web/ce/components/pages/editor/external-embed/embed-handler.tsx b/web/ce/components/pages/editor/external-embed/embed-handler.tsx index 8d1da017ac0..2652cb35561 100644 --- a/web/ce/components/pages/editor/external-embed/embed-handler.tsx +++ b/web/ce/components/pages/editor/external-embed/embed-handler.tsx @@ -1,3 +1,3 @@ import { NodeViewProps } from "@tiptap/react"; -export const EmbedHandler: React.FC = () =>
; +export const EmbedHandler: React.FC = () => null; From 13f08bb186ae8c3623d9b9e97c3aa7502285decd Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 20:07:31 +0530 Subject: [PATCH 07/26] fix : embedhandler type --- packages/editor/src/core/types/editor.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index 267ca469fa6..3f28a0537a6 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -113,12 +113,8 @@ export interface EditorRefApi extends EditorReadOnlyRefApi { listenToRealTimeUpdate: () => TDocumentEventEmitter | undefined; } -type TEmbedHandlerProps = { - embedHandler?: TEmbedConfig; -}; - // editor props -export interface IEditorProps extends TEmbedHandlerProps { +export interface IEditorProps { autofocus?: boolean; bubbleMenuEnabled?: boolean; containerClassName?: string; @@ -126,6 +122,7 @@ export interface IEditorProps extends TEmbedHandlerProps { disabledExtensions: TExtensions[]; editorClassName?: string; extensions?: Extensions; + embedHandler?: TEmbedConfig; flaggedExtensions: TExtensions[]; fileHandler: TFileHandler; forwardedRef?: React.MutableRefObject; From 4e87603d9a84cff1aa749c9f56f86646d85b8fc1 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 20 Jun 2025 20:11:37 +0530 Subject: [PATCH 08/26] fix : remove commands --- packages/editor/src/core/types/editor.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index 3f28a0537a6..5143d4ecb8f 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -46,9 +46,8 @@ export type TEditorCommands = | "background-color" | "text-align" | "callout" - | "attachment" - | "external-embed" - | "rich-card"; + | "attachment"; + export type TCommandExtraProps = { image: { savedSelection: Selection | null; From c2df565b9df4a8c4c5376948eb46a136d7c7a7c2 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Wed, 25 Jun 2025 14:16:17 +0530 Subject: [PATCH 09/26] refactor : space --- .../editor/src/ce/extensions/core/extensions.ts | 2 +- packages/editor/src/ce/types/issue-embed.ts | 5 +++++ .../core/components/editors/editor-container.tsx | 5 +++-- .../core/components/editors/editor-wrapper.tsx | 2 ++ .../editors/read-only-editor-wrapper.tsx | 2 ++ packages/editor/src/core/extensions/extensions.ts | 15 ++++++++++++--- .../src/core/extensions/read-only-extensions.ts | 5 ++++- .../src/core/hooks/use-collaborative-editor.ts | 1 + packages/editor/src/core/hooks/use-editor.ts | 2 ++ .../editor/src/core/hooks/use-read-only-editor.ts | 2 ++ packages/editor/src/core/plugins/drag-handle.ts | 5 +++++ packages/editor/src/core/types/editor.ts | 10 ++++++++-- space/core/components/editor/lite-text-editor.tsx | 9 +++++++-- .../editor/lite-text-read-only-editor.tsx | 9 +++++++-- space/core/components/editor/rich-text-editor.tsx | 9 ++++++++- .../editor/rich-text-read-only-editor.tsx | 9 ++++++++- 16 files changed, 77 insertions(+), 15 deletions(-) diff --git a/packages/editor/src/ce/extensions/core/extensions.ts b/packages/editor/src/ce/extensions/core/extensions.ts index a72bcc2159d..da03ba38615 100644 --- a/packages/editor/src/ce/extensions/core/extensions.ts +++ b/packages/editor/src/ce/extensions/core/extensions.ts @@ -4,7 +4,7 @@ import type { IEditorProps } from "@/types"; export type TCoreAdditionalExtensionsProps = Pick< IEditorProps, - "disabledExtensions" | "flaggedExtensions" | "fileHandler" + "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "embedHandler" >; export const CoreEditorAdditionalExtensions = (props: TCoreAdditionalExtensionsProps): Extensions => { diff --git a/packages/editor/src/ce/types/issue-embed.ts b/packages/editor/src/ce/types/issue-embed.ts index d68d182a043..324969ff50b 100644 --- a/packages/editor/src/ce/types/issue-embed.ts +++ b/packages/editor/src/ce/types/issue-embed.ts @@ -1,7 +1,12 @@ +import { NodeViewProps } from "@tiptap/react"; + export type TEmbedConfig = { issue?: TIssueEmbedConfig; + externalEmbedComponent?: TExternalEmbedConfig; }; +export type TExternalEmbedConfig = { widgetCallback: (props: NodeViewProps) => React.ReactNode }; + export type TReadOnlyEmbedConfig = TEmbedConfig; export type TIssueEmbedConfig = { diff --git a/packages/editor/src/core/components/editors/editor-container.tsx b/packages/editor/src/core/components/editors/editor-container.tsx index ab1bb5f2f78..c649acb0388 100644 --- a/packages/editor/src/core/components/editors/editor-container.tsx +++ b/packages/editor/src/core/components/editors/editor-container.tsx @@ -3,7 +3,7 @@ import { FC, ReactNode, useRef } from "react"; // plane utils import { cn } from "@plane/utils"; // constants -import { LinkViewContainer } from "@/components/editors/link-view-container"; +import { LinkViewContainer } from "./link-view-container"; import { DEFAULT_DISPLAY_CONFIG } from "@/constants/config"; import { CORE_EXTENSIONS } from "@/constants/extension"; // types @@ -55,7 +55,8 @@ export const EditorContainer: FC = (props) => { // Check if its last node and add new node if (lastNode) { - const isLastNodeEmptyParagraph = lastNode.type.name === CORE_EXTENSIONS.PARAGRAPH && lastNode.content.size === 0; + const isLastNodeEmptyParagraph = + lastNode.type.name === CORE_EXTENSIONS.PARAGRAPH && lastNode.content.size === 0; // Only insert a new paragraph if the last node is not an empty paragraph and not a doc node if (!isLastNodeEmptyParagraph && lastNode.type.name !== "doc") { const endPosition = editor?.state.doc.content.size; diff --git a/packages/editor/src/core/components/editors/editor-wrapper.tsx b/packages/editor/src/core/components/editors/editor-wrapper.tsx index 2c1ef52b757..dee64aa91e5 100644 --- a/packages/editor/src/core/components/editors/editor-wrapper.tsx +++ b/packages/editor/src/core/components/editors/editor-wrapper.tsx @@ -36,6 +36,7 @@ export const EditorWrapper: React.FC = (props) => { placeholder, tabIndex, value, + embedHandler, } = props; const editor = useEditor({ @@ -57,6 +58,7 @@ export const EditorWrapper: React.FC = (props) => { placeholder, tabIndex, value, + embedHandler, }); const editorContainerClassName = getEditorClassNames({ 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 b6abd1a6a50..ae303292583 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 @@ -22,6 +22,7 @@ export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => { id, initialValue, mentionHandler, + embedHandler, } = props; const editor = useReadOnlyEditor({ @@ -33,6 +34,7 @@ export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => { forwardedRef, initialValue, mentionHandler, + embedHandler, }); const editorContainerClassName = getEditorClassNames({ diff --git a/packages/editor/src/core/extensions/extensions.ts b/packages/editor/src/core/extensions/extensions.ts index 0807fa62d43..a49a9a72713 100644 --- a/packages/editor/src/core/extensions/extensions.ts +++ b/packages/editor/src/core/extensions/extensions.ts @@ -37,14 +37,21 @@ import { getExtensionStorage } from "@/helpers/get-extension-storage"; // plane editor extensions import { CoreEditorAdditionalExtensions } from "@/plane-editor/extensions"; // types -import type { IEditorProps } from "@/types"; +import type { IEditorProps, TEmbedConfig } from "@/types"; type TArguments = Pick< IEditorProps, - "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler" | "placeholder" | "tabIndex" + | "disabledExtensions" + | "flaggedExtensions" + | "fileHandler" + | "mentionHandler" + | "placeholder" + | "tabIndex" + | "embedHandler" > & { enableHistory: boolean; editable: boolean; + embedHandler?: TEmbedConfig; }; export const CoreEditorExtensions = (args: TArguments): Extensions => { @@ -56,6 +63,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { mentionHandler, placeholder, tabIndex, + embedHandler, editable, } = args; @@ -184,8 +192,9 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { CustomColorExtension, ...CoreEditorAdditionalExtensions({ disabledExtensions, - flaggedExtensions, fileHandler, + flaggedExtensions, + embedHandler, }), ]; diff --git a/packages/editor/src/core/extensions/read-only-extensions.ts b/packages/editor/src/core/extensions/read-only-extensions.ts index 0f422c620ba..2900d2f1ddf 100644 --- a/packages/editor/src/core/extensions/read-only-extensions.ts +++ b/packages/editor/src/core/extensions/read-only-extensions.ts @@ -33,7 +33,10 @@ import { CoreReadOnlyEditorAdditionalExtensions } from "@/plane-editor/extension // types import type { IReadOnlyEditorProps } from "@/types"; -type Props = Pick; +type Props = Pick< + IReadOnlyEditorProps, + "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler" | "embedHandler" +>; export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { const { disabledExtensions, fileHandler, flaggedExtensions, mentionHandler } = props; diff --git a/packages/editor/src/core/hooks/use-collaborative-editor.ts b/packages/editor/src/core/hooks/use-collaborative-editor.ts index 570315d757b..251a03a4e8b 100644 --- a/packages/editor/src/core/hooks/use-collaborative-editor.ts +++ b/packages/editor/src/core/hooks/use-collaborative-editor.ts @@ -75,6 +75,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) => ); const editor = useEditor({ + embedHandler, disabledExtensions, id, editable, diff --git a/packages/editor/src/core/hooks/use-editor.ts b/packages/editor/src/core/hooks/use-editor.ts index 4c1b93d84aa..00e39bdda93 100644 --- a/packages/editor/src/core/hooks/use-editor.ts +++ b/packages/editor/src/core/hooks/use-editor.ts @@ -36,6 +36,7 @@ export const useEditor = (props: TEditorHookProps) => { initialValue, mentionHandler, onChange, + embedHandler, onTransaction, placeholder, provider, @@ -66,6 +67,7 @@ export const useEditor = (props: TEditorHookProps) => { mentionHandler, placeholder, tabIndex, + embedHandler, }), ...extensions, ], 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 d259470ac96..92325bf8ab6 100644 --- a/packages/editor/src/core/hooks/use-read-only-editor.ts +++ b/packages/editor/src/core/hooks/use-read-only-editor.ts @@ -25,6 +25,7 @@ export const useReadOnlyEditor = (props: TReadOnlyEditorHookProps) => { handleEditorReady, initialValue, mentionHandler, + embedHandler, provider, } = props; @@ -49,6 +50,7 @@ export const useReadOnlyEditor = (props: TReadOnlyEditorHookProps) => { fileHandler, flaggedExtensions, mentionHandler, + embedHandler, }), ...extensions, ], diff --git a/packages/editor/src/core/plugins/drag-handle.ts b/packages/editor/src/core/plugins/drag-handle.ts index 800b66c7bf7..347715b4c6f 100644 --- a/packages/editor/src/core/plugins/drag-handle.ts +++ b/packages/editor/src/core/plugins/drag-handle.ts @@ -21,6 +21,7 @@ const generalSelectors = [ ".image-component", ".image-upload-component", ".editor-callout-component", + ".editor-embed-component", ].join(", "); const maxScrollSpeed = 20; @@ -108,6 +109,10 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => { continue; } + // Skip elements inside .editor-embed-component + if (elem.closest(".editor-embed-component") && !elem.matches(".editor-embed-component")) { + continue; + } // apply general selector if (elem.matches(generalSelectors)) { return elem; diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index 5143d4ecb8f..058038aa07b 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -137,9 +137,13 @@ export interface IEditorProps { value?: string | null; } -export type ILiteTextEditorProps = IEditorProps; +export type ILiteTextEditorProps = IEditorProps & { + embedHandler?: TEmbedConfig; +}; + export interface IRichTextEditorProps extends IEditorProps { dragDropEnabled?: boolean; + embedHandler?: TEmbedConfig; } export interface ICollaborativeDocumentEditorProps @@ -175,7 +179,9 @@ export type ILiteTextReadOnlyEditorProps = IReadOnlyEditorProps; export type IRichTextReadOnlyEditorProps = IReadOnlyEditorProps; -export type IDocumentReadOnlyEditorProps = IReadOnlyEditorProps; +export interface IDocumentReadOnlyEditorProps extends IReadOnlyEditorProps { + embedHandler: TEmbedConfig; +} export interface EditorEvents { beforeCreate: never; diff --git a/space/core/components/editor/lite-text-editor.tsx b/space/core/components/editor/lite-text-editor.tsx index 6342d934479..75ce7b51d3d 100644 --- a/space/core/components/editor/lite-text-editor.tsx +++ b/space/core/components/editor/lite-text-editor.tsx @@ -1,5 +1,6 @@ import React from "react"; // plane imports +import { NodeViewProps } from "@tiptap/react"; import { EditorRefApi, ILiteTextEditorProps, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; import { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; @@ -8,10 +9,11 @@ import { EditorMentionsRoot, IssueCommentToolbar } from "@/components/editor"; // helpers import { getEditorFileHandlers } from "@/helpers/editor.helper"; import { isCommentEmpty } from "@/helpers/string.helper"; +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; interface LiteTextEditorWrapperProps extends MakeOptional< - Omit, + Omit, "disabledExtensions" | "flaggedExtensions" > { anchor: string; @@ -39,7 +41,9 @@ export const LiteTextEditor = React.forwardRef(ref) ? ref.current : null; - + const embedHandlerConfig = { + externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, + }; return (
, }} {...rest} + embedHandler={embedHandlerConfig} // overriding the containerClassName to add relative class passed containerClassName={cn(containerClassName, "relative")} /> diff --git a/space/core/components/editor/lite-text-read-only-editor.tsx b/space/core/components/editor/lite-text-read-only-editor.tsx index 34662b7fc37..c71ed9f9c1e 100644 --- a/space/core/components/editor/lite-text-read-only-editor.tsx +++ b/space/core/components/editor/lite-text-read-only-editor.tsx @@ -1,5 +1,6 @@ import React from "react"; // plane imports +import { NodeViewProps } from "@tiptap/react"; import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditorProps, LiteTextReadOnlyEditorWithRef } from "@plane/editor"; import { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; @@ -9,9 +10,10 @@ import { EditorMentionsRoot } from "@/components/editor"; import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; // store hooks import { useMember } from "@/hooks/store"; +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; type LiteTextReadOnlyEditorWrapperProps = MakeOptional< - Omit, + Omit, "disabledExtensions" | "flaggedExtensions" > & { anchor: string; @@ -21,7 +23,9 @@ type LiteTextReadOnlyEditorWrapperProps = MakeOptional< export const LiteTextReadOnlyEditor = React.forwardRef( ({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => { const { getMemberById } = useMember(); - + const embedHandlerConfig = { + externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, + }; return ( , + Omit, "disabledExtensions" | "flaggedExtensions" > { anchor: string; @@ -39,6 +41,11 @@ export const RichTextEditor = forwardRef , + }, + }} containerClassName={containerClassName} editorClassName="min-h-[100px] max-h-[200px] border-[0.5px] border-custom-border-300 rounded-md pl-3 py-2 overflow-hidden" displayConfig={{ fontSize: "large-font" }} diff --git a/space/core/components/editor/rich-text-read-only-editor.tsx b/space/core/components/editor/rich-text-read-only-editor.tsx index dd9d371901c..99d9ecd798d 100644 --- a/space/core/components/editor/rich-text-read-only-editor.tsx +++ b/space/core/components/editor/rich-text-read-only-editor.tsx @@ -1,5 +1,6 @@ import React from "react"; // plane imports +import { NodeViewProps } from "@tiptap/react"; import { EditorReadOnlyRefApi, IRichTextReadOnlyEditorProps, RichTextReadOnlyEditorWithRef } from "@plane/editor"; import { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; @@ -9,9 +10,10 @@ import { EditorMentionsRoot } from "@/components/editor"; import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper"; // store hooks import { useMember } from "@/hooks/store"; +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; type RichTextReadOnlyEditorWrapperProps = MakeOptional< - Omit, + Omit, "disabledExtensions" | "flaggedExtensions" > & { anchor: string; @@ -38,6 +40,11 @@ export const RichTextReadOnlyEditor = React.forwardRef , + }, + }} // overriding the customClassName to add relative class passed containerClassName={cn("relative p-0 border-none", props.containerClassName)} /> From 96071bffe9ab42bf08d4d1d219ee633107c208bc Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Wed, 25 Jun 2025 15:26:51 +0530 Subject: [PATCH 10/26] refactor : rich lite editors --- .../editor/lite-text-editor/lite-text-editor.tsx | 9 +++++++-- .../lite-text-editor/lite-text-read-only-editor.tsx | 9 +++++++-- .../editor/rich-text-editor/rich-text-editor.tsx | 7 +++++-- .../rich-text-editor/rich-text-read-only-editor.tsx | 3 +++ web/core/components/pages/version/editor.tsx | 3 +++ web/next.config.js | 2 +- 6 files changed, 26 insertions(+), 7 deletions(-) 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 088676358ee..59c274b0eb3 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 @@ -1,5 +1,6 @@ import React, { useState } from "react"; // plane constants +import { NodeViewProps } from "@tiptap/react"; import { EIssueCommentAccessSpecifier } from "@plane/constants"; // plane editor import { EditorRefApi, ILiteTextEditorProps, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; @@ -18,11 +19,12 @@ import { useMember } from "@/hooks/store"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; // plane web services import { WorkspaceService } from "@/plane-web/services"; +import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; const workspaceService = new WorkspaceService(); interface LiteTextEditorWrapperProps extends MakeOptional< - Omit, + Omit, "disabledExtensions" | "flaggedExtensions" > { workspaceSlug: string; @@ -84,7 +86,9 @@ export const LiteTextEditor = React.forwardRef(ref) ? ref.current : null; - + const embedHandlerConfig = { + externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, + }; return (
{showToolbar && (
, + Omit, "disabledExtensions" | "flaggedExtensions" > & { workspaceId: string; @@ -31,7 +33,9 @@ export const LiteTextReadOnlyEditor = React.forwardRef }, + }; return ( ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} {...props} + embedHandler={embedHandlerConfig} // overriding the containerClassName to add relative class passed containerClassName={cn(props.containerClassName, "relative p-2")} /> diff --git a/web/core/components/editor/rich-text-editor/rich-text-editor.tsx b/web/core/components/editor/rich-text-editor/rich-text-editor.tsx index fdb5a3bfd5c..30d6fbc989d 100644 --- a/web/core/components/editor/rich-text-editor/rich-text-editor.tsx +++ b/web/core/components/editor/rich-text-editor/rich-text-editor.tsx @@ -1,5 +1,6 @@ import React, { forwardRef } from "react"; // plane imports +import { NodeViewProps } from "@tiptap/react"; import { EditorRefApi, IRichTextEditorProps, RichTextEditorWithRef, TFileHandler } from "@plane/editor"; import { MakeOptional, TSearchEntityRequestPayload, TSearchResponse } from "@plane/types"; // components @@ -12,11 +13,12 @@ import { useEditorConfig, useEditorMention } from "@/hooks/editor"; import { useMember } from "@/hooks/store"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; +import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; interface RichTextEditorWrapperProps extends MakeOptional< - Omit, - "disabledExtensions" | "flaggedExtensions" + Omit, + "disabledExtensions" > { searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise; workspaceSlug: string; @@ -67,6 +69,7 @@ export const RichTextEditor = forwardRef , getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} + embedHandler={{ externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => } }} {...rest} containerClassName={cn("relative pl-3 pb-3", containerClassName)} /> diff --git a/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx b/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx index b89804e015f..f9658c9852e 100644 --- a/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx +++ b/web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx @@ -12,8 +12,10 @@ import { EditorMentionsRoot } from "@/components/editor"; import { useEditorConfig } from "@/hooks/editor"; // store hooks import { useMember } from "@/hooks/store"; +import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; +import { NodeViewProps } from "@tiptap/react"; type RichTextReadOnlyEditorWrapperProps = MakeOptional< Omit, @@ -49,6 +51,7 @@ export const RichTextReadOnlyEditor = React.forwardRef ({ display_name: getUserDetails(id)?.display_name ?? "" }), }} {...props} + embedHandler={{ externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => } }} // overriding the containerClassName to add relative class passed containerClassName={cn(props.containerClassName, "relative pl-3")} /> diff --git a/web/core/components/pages/version/editor.tsx b/web/core/components/pages/version/editor.tsx index 8491408ac8c..041b30f77fd 100644 --- a/web/core/components/pages/version/editor.tsx +++ b/web/core/components/pages/version/editor.tsx @@ -1,5 +1,6 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; +import { NodeViewProps } from "@tiptap/react"; // plane imports import { DocumentReadOnlyEditorWithRef, TDisplayConfig } from "@plane/editor"; import { TPageVersion } from "@plane/types"; @@ -13,6 +14,7 @@ import { usePageFilters } from "@/hooks/use-page-filters"; // plane web hooks import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed"; +import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; export type TVersionEditorProps = { activeVersion: string | null; @@ -116,6 +118,7 @@ export const PagesVersionEditor: React.FC = observer((props issue: { widgetCallback: issueEmbedProps.widgetCallback, }, + externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, }} /> ); diff --git a/web/next.config.js b/web/next.config.js index 41ed049c558..66628a051f8 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -12,7 +12,7 @@ const nextConfig = { return [ { source: "/(.*)?", - headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], + headers: [{ key: "X-Frame-Options", value: "DENY" }], }, ]; }, From 0f820852b955dd98325ec5ae17b0f85ebf114a47 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Thu, 24 Jul 2025 14:21:58 +0530 Subject: [PATCH 11/26] refactor : minor ce changes --- .../ce/components/editor/external-embed/embed-handler.tsx | 0 apps/space/ce/components/editor/external-embed/index.ts | 1 + apps/space/ce/components/editor/index.ts | 1 + apps/web/ce/components/editor/external-embed/embed-handler.tsx | 3 +++ 4 files changed, 5 insertions(+) rename {space => apps/space}/ce/components/editor/external-embed/embed-handler.tsx (100%) create mode 100644 apps/space/ce/components/editor/external-embed/index.ts create mode 100644 apps/space/ce/components/editor/index.ts create mode 100644 apps/web/ce/components/editor/external-embed/embed-handler.tsx diff --git a/space/ce/components/editor/external-embed/embed-handler.tsx b/apps/space/ce/components/editor/external-embed/embed-handler.tsx similarity index 100% rename from space/ce/components/editor/external-embed/embed-handler.tsx rename to apps/space/ce/components/editor/external-embed/embed-handler.tsx diff --git a/apps/space/ce/components/editor/external-embed/index.ts b/apps/space/ce/components/editor/external-embed/index.ts new file mode 100644 index 00000000000..781518d6cfa --- /dev/null +++ b/apps/space/ce/components/editor/external-embed/index.ts @@ -0,0 +1 @@ +export * from "./embed-handler"; diff --git a/apps/space/ce/components/editor/index.ts b/apps/space/ce/components/editor/index.ts new file mode 100644 index 00000000000..af7018a26f6 --- /dev/null +++ b/apps/space/ce/components/editor/index.ts @@ -0,0 +1 @@ +export * from "./external-embed"; diff --git a/apps/web/ce/components/editor/external-embed/embed-handler.tsx b/apps/web/ce/components/editor/external-embed/embed-handler.tsx new file mode 100644 index 00000000000..2652cb35561 --- /dev/null +++ b/apps/web/ce/components/editor/external-embed/embed-handler.tsx @@ -0,0 +1,3 @@ +import { NodeViewProps } from "@tiptap/react"; + +export const EmbedHandler: React.FC = () => null; From fc3d923ead21d8c7441d11ceb6bdc5996bc356ed Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Thu, 24 Jul 2025 15:41:00 +0530 Subject: [PATCH 12/26] chore : minor ui fix --- .../editor/lite-text-editor/lite-text-editor.tsx | 2 +- .../lite-text-editor/lite-text-read-only-editor.tsx | 2 +- .../editor/rich-text-editor/rich-text-editor.tsx | 8 +------- apps/web/core/components/pages/version/editor.tsx | 4 ++-- packages/editor/src/styles/drag-drop.css | 9 +++++++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/web/core/components/editor/lite-text-editor/lite-text-editor.tsx b/apps/web/core/components/editor/lite-text-editor/lite-text-editor.tsx index 59c274b0eb3..8ea3dfee459 100644 --- a/apps/web/core/components/editor/lite-text-editor/lite-text-editor.tsx +++ b/apps/web/core/components/editor/lite-text-editor/lite-text-editor.tsx @@ -16,10 +16,10 @@ import { useEditorConfig, useEditorMention } from "@/hooks/editor"; // store hooks import { useMember } from "@/hooks/store"; // plane web hooks +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; // plane web services import { WorkspaceService } from "@/plane-web/services"; -import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; const workspaceService = new WorkspaceService(); interface LiteTextEditorWrapperProps diff --git a/apps/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx b/apps/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx index 509b9944a93..6e2a4ee887d 100644 --- a/apps/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx +++ b/apps/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx @@ -12,8 +12,8 @@ import { useEditorConfig } from "@/hooks/editor"; // store hooks import { useMember } from "@/hooks/store"; // plane web hooks +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; -import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; type LiteTextReadOnlyEditorWrapperProps = MakeOptional< Omit, diff --git a/apps/web/core/components/editor/rich-text-editor/rich-text-editor.tsx b/apps/web/core/components/editor/rich-text-editor/rich-text-editor.tsx index d26e1b9f67b..6ca22e6bc09 100644 --- a/apps/web/core/components/editor/rich-text-editor/rich-text-editor.tsx +++ b/apps/web/core/components/editor/rich-text-editor/rich-text-editor.tsx @@ -12,15 +12,9 @@ import { useEditorConfig, useEditorMention } from "@/hooks/editor"; // store hooks import { useMember } from "@/hooks/store"; // plane web hooks +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; -import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; -// interface RichTextEditorWrapperProps -// extends MakeOptional< -// Omit, -// "disabledExtensions" -// > { -// searchMentionCallback: (payload: TSearchEntityRequestPayload) => Promise; type RichTextEditorWrapperProps = MakeOptional< Omit, "disabledExtensions" | "editable" | "flaggedExtensions" diff --git a/apps/web/core/components/pages/version/editor.tsx b/apps/web/core/components/pages/version/editor.tsx index c0d85809d0b..a59bb44f5b1 100644 --- a/apps/web/core/components/pages/version/editor.tsx +++ b/apps/web/core/components/pages/version/editor.tsx @@ -1,6 +1,6 @@ +import { NodeViewProps } from "@tiptap/react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; -import { NodeViewProps } from "@tiptap/react"; // plane imports import { DocumentReadOnlyEditorWithRef, TDisplayConfig } from "@plane/editor"; import { TPageVersion } from "@plane/types"; @@ -12,9 +12,9 @@ import { useEditorConfig } from "@/hooks/editor"; import { useMember, useWorkspace } from "@/hooks/store"; import { usePageFilters } from "@/hooks/use-page-filters"; // plane web hooks +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed"; -import { EmbedHandler } from "@/plane-web/components/pages/editor/external-embed/embed-handler"; export type TVersionEditorProps = { activeVersion: string | null; diff --git a/packages/editor/src/styles/drag-drop.css b/packages/editor/src/styles/drag-drop.css index 7db6ed87554..f29bc95f847 100644 --- a/packages/editor/src/styles/drag-drop.css +++ b/packages/editor/src/styles/drag-drop.css @@ -35,7 +35,10 @@ } /* end ai handle */ -.ProseMirror:not(.dragging) .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image) { +.ProseMirror:not(.dragging) + .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image):not(.table-wrapper):not( + .node-externalEmbedComponent + ) { position: relative; cursor: grab; outline: none !important; @@ -61,7 +64,9 @@ } &.node-imageComponent, - &.node-image { + &.node-image, + &.table-wrapper, + &.node-externalEmbedComponent { --horizontal-offset: 0px; &::after { From 735fe53273e4d2ed2c4e089f100220221f85670c Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Thu, 24 Jul 2025 16:32:21 +0530 Subject: [PATCH 13/26] package: tldjs --- .../core/components/editor/sticky-editor/editor.tsx | 12 ++++++++++-- apps/web/package.json | 2 ++ .../src/ce/extensions/core/read-only-extensions.ts | 2 +- .../components/editors/document/read-only-editor.tsx | 2 +- .../src/core/components/editors/editor-container.tsx | 2 +- packages/editor/src/core/extensions/extensions.ts | 2 +- .../src/core/extensions/read-only-extensions.ts | 5 +++-- packages/editor/src/core/plugins/drag-handle.ts | 4 ---- packages/editor/src/core/types/editor.ts | 9 ++++----- packages/editor/src/styles/drag-drop.css | 4 ++-- 10 files changed, 25 insertions(+), 19 deletions(-) diff --git a/apps/web/core/components/editor/sticky-editor/editor.tsx b/apps/web/core/components/editor/sticky-editor/editor.tsx index f91cdd498f9..42d5b84e8d0 100644 --- a/apps/web/core/components/editor/sticky-editor/editor.tsx +++ b/apps/web/core/components/editor/sticky-editor/editor.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; // plane constants +import { NodeViewProps } from "@tiptap/react"; import { EIssueCommentAccessSpecifier } from "@plane/constants"; // plane editor import { EditorRefApi, ILiteTextEditorProps, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; @@ -10,11 +11,15 @@ import { cn } from "@plane/utils"; // hooks import { useEditorConfig } from "@/hooks/editor"; // plane web hooks +import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; import { StickyEditorToolbar } from "./toolbar"; interface StickyEditorWrapperProps - extends Omit { + extends Omit< + ILiteTextEditorProps, + "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler" | "embedHandler" + > { workspaceSlug: string; workspaceId: string; projectId?: string; @@ -56,7 +61,9 @@ export const StickyEditor = React.forwardRef(ref) ? ref.current : null; - + const embedHandlerConfig = { + externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, + }; return (
{showToolbar && (
; export const CoreReadOnlyEditorAdditionalExtensions = ( 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 76dcba7f807..9eaabe203fa 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 @@ -18,7 +18,6 @@ import { EditorReadOnlyRefApi, IDocumentReadOnlyEditorProps } from "@/types"; const DocumentReadOnlyEditor: React.FC = (props) => { const { containerClassName, - disabledExtensions, displayConfig = DEFAULT_DISPLAY_CONFIG, editorClassName = "", embedHandler, @@ -29,6 +28,7 @@ const DocumentReadOnlyEditor: React.FC = (props) = handleEditorReady, initialValue, mentionHandler, + disabledExtensions, } = props; const extensions: Extensions = []; if (embedHandler?.issue) { diff --git a/packages/editor/src/core/components/editors/editor-container.tsx b/packages/editor/src/core/components/editors/editor-container.tsx index c649acb0388..f189bde9850 100644 --- a/packages/editor/src/core/components/editors/editor-container.tsx +++ b/packages/editor/src/core/components/editors/editor-container.tsx @@ -3,12 +3,12 @@ import { FC, ReactNode, useRef } from "react"; // plane utils import { cn } from "@plane/utils"; // constants -import { LinkViewContainer } from "./link-view-container"; import { DEFAULT_DISPLAY_CONFIG } from "@/constants/config"; import { CORE_EXTENSIONS } from "@/constants/extension"; // types import { TDisplayConfig } from "@/types"; // components +import { LinkViewContainer } from "./link-view-container"; interface EditorContainerProps { children: ReactNode; diff --git a/packages/editor/src/core/extensions/extensions.ts b/packages/editor/src/core/extensions/extensions.ts index 4610282bbdb..94ba918328f 100644 --- a/packages/editor/src/core/extensions/extensions.ts +++ b/packages/editor/src/core/extensions/extensions.ts @@ -113,8 +113,8 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { }), ...CoreEditorAdditionalExtensions({ disabledExtensions, - fileHandler, flaggedExtensions, + fileHandler, embedHandler, }), ]; diff --git a/packages/editor/src/core/extensions/read-only-extensions.ts b/packages/editor/src/core/extensions/read-only-extensions.ts index ed3f9d7a099..6c125d59155 100644 --- a/packages/editor/src/core/extensions/read-only-extensions.ts +++ b/packages/editor/src/core/extensions/read-only-extensions.ts @@ -35,11 +35,11 @@ import { CustomStarterKitExtension } from "./starter-kit"; type Props = Pick< IReadOnlyEditorProps, - "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "mentionHandler" | "embedHandler" + "disabledExtensions" | "fileHandler" | "mentionHandler" | "embedHandler" | "flaggedExtensions" >; export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { - const { disabledExtensions, fileHandler, flaggedExtensions, mentionHandler } = props; + const { disabledExtensions, fileHandler, flaggedExtensions, mentionHandler, embedHandler } = props; const extensions = [ CustomStarterKitExtension({ @@ -86,6 +86,7 @@ export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => { ...CoreReadOnlyEditorAdditionalExtensions({ disabledExtensions, flaggedExtensions, + embedHandler, }), ]; diff --git a/packages/editor/src/core/plugins/drag-handle.ts b/packages/editor/src/core/plugins/drag-handle.ts index 0e310a9a1e2..3943d0c31d9 100644 --- a/packages/editor/src/core/plugins/drag-handle.ts +++ b/packages/editor/src/core/plugins/drag-handle.ts @@ -111,10 +111,6 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => { continue; } - // Skip elements inside .editor-embed-component - if (elem.closest(".editor-embed-component") && !elem.matches(".editor-embed-component")) { - continue; - } // apply general selector if (elem.matches(generalSelectors)) { return elem; diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index a040002983a..f4ec27e3a56 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -48,7 +48,8 @@ export type TEditorCommands = | "text-align" | "callout" | "attachment" - | "emoji"; + | "emoji" + | "external-embed"; export type TCommandExtraProps = { image: { @@ -144,13 +145,10 @@ export interface IEditorProps { value?: string | null; } -export type ILiteTextEditorProps = IEditorProps & { - embedHandler?: TEmbedConfig; -}; +export type ILiteTextEditorProps = IEditorProps; export type IRichTextEditorProps = IEditorProps & { dragDropEnabled?: boolean; - embedHandler?: TEmbedConfig; editable: boolean; }; @@ -158,6 +156,7 @@ export interface ICollaborativeDocumentEditorProps extends Omit { aiHandler?: TAIHandler; editable: boolean; + embedHandler?: TEmbedConfig; realtimeConfig: TRealtimeConfig; serverHandler?: TServerHandler; user: TUserDetails; diff --git a/packages/editor/src/styles/drag-drop.css b/packages/editor/src/styles/drag-drop.css index f29bc95f847..0b09530b695 100644 --- a/packages/editor/src/styles/drag-drop.css +++ b/packages/editor/src/styles/drag-drop.css @@ -65,8 +65,8 @@ &.node-imageComponent, &.node-image, - &.table-wrapper, - &.node-externalEmbedComponent { + &.node-externalEmbedComponent, + &.table-wrapper { --horizontal-offset: 0px; &::after { From 44443d417d8ac059bad8d1f75885d5ba2ad8addb Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 12:37:05 +0530 Subject: [PATCH 14/26] refactor : remove tldjs --- apps/web/core/components/pages/version/editor.tsx | 4 ---- apps/web/package.json | 2 -- 2 files changed, 6 deletions(-) diff --git a/apps/web/core/components/pages/version/editor.tsx b/apps/web/core/components/pages/version/editor.tsx index 3af0aa6f09e..28c466ab222 100644 --- a/apps/web/core/components/pages/version/editor.tsx +++ b/apps/web/core/components/pages/version/editor.tsx @@ -10,10 +10,6 @@ import { DocumentEditor } from "@/components/editor/document/editor"; // hooks import { useWorkspace } from "@/hooks/store"; import { usePageFilters } from "@/hooks/use-page-filters"; -// plane web hooks -import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; -import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; -import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed"; export type TVersionEditorProps = { activeVersion: string | null; diff --git a/apps/web/package.json b/apps/web/package.json index 6a96207a8eb..0395c8bbbf4 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -32,7 +32,6 @@ "@popperjs/core": "^2.11.8", "@react-pdf/renderer": "^3.4.5", "@tanstack/react-table": "^8.21.3", - "@types/tldjs": "^2.3.4", "axios": "1.11.0", "clsx": "^2.0.0", "cmdk": "^1.0.0", @@ -65,7 +64,6 @@ "smooth-scroll-into-view-if-needed": "^2.0.2", "swr": "^2.1.3", "tailwind-merge": "^2.0.0", - "tldjs": "^2.3.2", "use-font-face-observer": "^1.2.2", "uuid": "^9.0.0" }, From 5d084ce3cf2d62a7709f02d92baf10bb24716c77 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 17:53:57 +0530 Subject: [PATCH 15/26] refactor: flagged --- apps/space/core/components/editor/lite-text-editor.tsx | 10 ++++++---- apps/web/core/components/editor/lite-text/editor.tsx | 7 +++---- .../core/components/editor/sticky-editor/editor.tsx | 7 +++---- .../editors/document/collaborative-editor.tsx | 1 + .../core/components/editors/document/page-renderer.tsx | 8 +++++++- .../editor/src/core/components/menus/block-menu.tsx | 1 + 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/space/core/components/editor/lite-text-editor.tsx b/apps/space/core/components/editor/lite-text-editor.tsx index 590abbd2799..b9496b6d440 100644 --- a/apps/space/core/components/editor/lite-text-editor.tsx +++ b/apps/space/core/components/editor/lite-text-editor.tsx @@ -1,5 +1,6 @@ import React from "react"; // plane imports +import { NodeViewProps } from "@tiptap/react"; import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor"; import type { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; @@ -46,9 +47,6 @@ export const LiteTextEditor = React.forwardRef(ref) ? ref.current : null; - const embedHandlerConfig = { - externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, - }; return (
, }} {...rest} - embedHandler={embedHandlerConfig} + embedHandler={{ + externalEmbedComponent: { + widgetCallback: (props: NodeViewProps) => , + }, + }} // overriding the containerClassName to add relative class passed containerClassName={cn(containerClassName, "relative")} /> diff --git a/apps/web/core/components/editor/lite-text/editor.tsx b/apps/web/core/components/editor/lite-text/editor.tsx index e906bc6b9d5..472cfdf62b5 100644 --- a/apps/web/core/components/editor/lite-text/editor.tsx +++ b/apps/web/core/components/editor/lite-text/editor.tsx @@ -89,9 +89,6 @@ export const LiteTextEditor = React.forwardRef(ref) ? ref.current : null; - const embedHandlerConfig = { - externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, - }; return (
}, + }} /> {showToolbar && editable && (
(ref) ? ref.current : null; - const embedHandlerConfig = { - externalEmbedComponent: { widgetCallback: (props: NodeViewProps) => }, - }; return (
}, + }} /> {showToolbar && (
= isLoading={!hasServerSynced && !hasServerConnectionFailed} tabIndex={tabIndex} disabledExtensions={disabledExtensions} + flaggedExtensions={flaggedExtensions} /> ); }; 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 f2fe0e2ead4..1d88677cc4f 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -17,6 +17,7 @@ type Props = { isLoading?: boolean; tabIndex?: number; disabledExtensions: IEditorProps["disabledExtensions"]; + flaggedExtensions?: IEditorProps["flaggedExtensions"]; }; export const PageRenderer = (props: Props) => { @@ -30,6 +31,7 @@ export const PageRenderer = (props: Props) => { isLoading, tabIndex, disabledExtensions, + flaggedExtensions, } = props; return ( @@ -51,7 +53,11 @@ export const PageRenderer = (props: Props) => { {editor.isEditable && (
{bubbleMenuEnabled && } - +
)} diff --git a/packages/editor/src/core/components/menus/block-menu.tsx b/packages/editor/src/core/components/menus/block-menu.tsx index abb2495a7e7..a550343679a 100644 --- a/packages/editor/src/core/components/menus/block-menu.tsx +++ b/packages/editor/src/core/components/menus/block-menu.tsx @@ -9,6 +9,7 @@ import { IEditorProps } from "@/types"; interface BlockMenuProps { editor: Editor; disabledExtensions: IEditorProps["disabledExtensions"]; + flaggedExtensions?: IEditorProps["flaggedExtensions"]; } export const BlockMenu = (props: BlockMenuProps) => { From 7803d561f54f370012ca856b3147ad9bafb4ed5d Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 18:36:46 +0530 Subject: [PATCH 16/26] refactor: flagged --- packages/editor/src/core/components/editors/document/editor.tsx | 2 ++ packages/editor/src/core/types/hook.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/editor/src/core/components/editors/document/editor.tsx b/packages/editor/src/core/components/editors/document/editor.tsx index bf27c48e3fa..ac552ddb644 100644 --- a/packages/editor/src/core/components/editors/document/editor.tsx +++ b/packages/editor/src/core/components/editors/document/editor.tsx @@ -98,6 +98,8 @@ const DocumentEditor = (props: IDocumentEditorProps) => { editorContainerClassName={cn(editorContainerClassName, "document-editor")} id={id} isTouchDevice={!!isTouchDevice} + disabledExtensions={disabledExtensions} + flaggedExtensions={flaggedExtensions} /> ); }; diff --git a/packages/editor/src/core/types/hook.ts b/packages/editor/src/core/types/hook.ts index 52ebb6f619f..2ac9bc08227 100644 --- a/packages/editor/src/core/types/hook.ts +++ b/packages/editor/src/core/types/hook.ts @@ -13,6 +13,7 @@ type TCoreHookProps = Pick< | "handleEditorReady" | "isTouchDevice" | "onEditorFocus" + | "embedHandler" >; export type TEditorHookProps = TCoreHookProps & From 16c602af196c9256b652399a8cc52a6aa55a860e Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 18:45:18 +0530 Subject: [PATCH 17/26] chore : remove disbaled check in menu --- .../core/components/editors/document/collaborative-editor.tsx | 1 - packages/editor/src/core/components/editors/document/editor.tsx | 1 - .../src/core/components/editors/document/page-renderer.tsx | 1 - 3 files changed, 3 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 b3380886abc..61346a09839 100644 --- a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx +++ b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx @@ -108,7 +108,6 @@ const CollaborativeDocumentEditor: React.FC = isTouchDevice={!!isTouchDevice} isLoading={!hasServerSynced && !hasServerConnectionFailed} tabIndex={tabIndex} - disabledExtensions={disabledExtensions} flaggedExtensions={flaggedExtensions} /> ); diff --git a/packages/editor/src/core/components/editors/document/editor.tsx b/packages/editor/src/core/components/editors/document/editor.tsx index ac552ddb644..4e0ba4244c9 100644 --- a/packages/editor/src/core/components/editors/document/editor.tsx +++ b/packages/editor/src/core/components/editors/document/editor.tsx @@ -98,7 +98,6 @@ const DocumentEditor = (props: IDocumentEditorProps) => { editorContainerClassName={cn(editorContainerClassName, "document-editor")} id={id} isTouchDevice={!!isTouchDevice} - disabledExtensions={disabledExtensions} flaggedExtensions={flaggedExtensions} /> ); 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 280690448bb..1c852519b52 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -18,7 +18,6 @@ type Props = { isLoading?: boolean; isTouchDevice: boolean; tabIndex?: number; - disabledExtensions: IEditorProps["disabledExtensions"]; flaggedExtensions?: IEditorProps["flaggedExtensions"]; }; From 471878aa1324a09a1c1ecc325fe8e746453b9205 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 18:52:15 +0530 Subject: [PATCH 18/26] refactor: fix space --- packages/editor/src/core/extensions/extensions.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/editor/src/core/extensions/extensions.ts b/packages/editor/src/core/extensions/extensions.ts index cd709667dbf..eda64824ffb 100644 --- a/packages/editor/src/core/extensions/extensions.ts +++ b/packages/editor/src/core/extensions/extensions.ts @@ -38,17 +38,12 @@ import { CustomStarterKitExtension } from "./starter-kit"; type TArguments = Pick< IEditorProps, - | | "disabledExtensions" - + | "disabledExtensions" | "flaggedExtensions" - | "fileHandler" | "isTouchDevice" - | "mentionHandler" - | "placeholder" - | "tabIndex" | "embedHandler" > & { From 067f0200ac1260d7bd3dd4fd1ef38dd9ecd5d5ed Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 19:22:33 +0530 Subject: [PATCH 19/26] refactor: NodeViewProps --- .../editor/external-embed/embed-handler.tsx | 2 +- .../space/core/components/editor/lite-text-editor.tsx | 9 +++++++-- .../space/core/components/editor/rich-text-editor.tsx | 11 ++++++++--- .../editor/external-embed/embed-handler.tsx | 2 +- apps/web/core/components/editor/lite-text/editor.tsx | 9 +++++++-- apps/web/core/components/editor/rich-text/editor.tsx | 9 +++++++-- .../core/components/editor/sticky-editor/editor.tsx | 9 +++++++-- apps/web/core/components/pages/version/editor.tsx | 1 - packages/editor/src/core/types/editor.ts | 3 +++ .../pages/editor/external-embed/embed-handler.tsx | 3 +-- 10 files changed, 42 insertions(+), 16 deletions(-) diff --git a/apps/space/ce/components/editor/external-embed/embed-handler.tsx b/apps/space/ce/components/editor/external-embed/embed-handler.tsx index 5eb7bb0b781..47880b80c7c 100644 --- a/apps/space/ce/components/editor/external-embed/embed-handler.tsx +++ b/apps/space/ce/components/editor/external-embed/embed-handler.tsx @@ -1,4 +1,4 @@ -import { NodeViewProps } from "@tiptap/react"; +import type { NodeViewProps } from "@plane/editor"; interface EmbedHandlerProps extends NodeViewProps { anchor?: string; diff --git a/apps/space/core/components/editor/lite-text-editor.tsx b/apps/space/core/components/editor/lite-text-editor.tsx index f17a3110c87..d8c107990e5 100644 --- a/apps/space/core/components/editor/lite-text-editor.tsx +++ b/apps/space/core/components/editor/lite-text-editor.tsx @@ -1,7 +1,12 @@ import React from "react"; // plane imports -import { NodeViewProps } from "@tiptap/react"; -import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor"; +import { + type NodeViewProps, + type EditorRefApi, + type ILiteTextEditorProps, + LiteTextEditorWithRef, + type TFileHandler, +} from "@plane/editor"; import type { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; // components diff --git a/apps/space/core/components/editor/rich-text-editor.tsx b/apps/space/core/components/editor/rich-text-editor.tsx index c2171125741..6ba45bf7a2e 100644 --- a/apps/space/core/components/editor/rich-text-editor.tsx +++ b/apps/space/core/components/editor/rich-text-editor.tsx @@ -1,8 +1,12 @@ import React, { forwardRef } from "react"; // plane imports -import { useEditorFlagging } from "ce/hooks/use-editor-flagging"; -import { NodeViewProps } from "@tiptap/react"; -import { EditorRefApi, IRichTextEditorProps, RichTextEditorWithRef, TFileHandler } from "@plane/editor"; +import { + EditorRefApi, + IRichTextEditorProps, + RichTextEditorWithRef, + TFileHandler, + type NodeViewProps, +} from "@plane/editor"; import { MakeOptional } from "@plane/types"; // components import { EditorMentionsRoot } from "@/components/editor"; @@ -11,6 +15,7 @@ import { getEditorFileHandlers } from "@/helpers/editor.helper"; // store hooks import { useMember } from "@/hooks/store"; import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; +import { useEditorFlagging } from "ce/hooks/use-editor-flagging"; type RichTextEditorWrapperProps = MakeOptional< Omit, diff --git a/apps/web/ce/components/editor/external-embed/embed-handler.tsx b/apps/web/ce/components/editor/external-embed/embed-handler.tsx index 2652cb35561..b1f2036d3ee 100644 --- a/apps/web/ce/components/editor/external-embed/embed-handler.tsx +++ b/apps/web/ce/components/editor/external-embed/embed-handler.tsx @@ -1,3 +1,3 @@ -import { NodeViewProps } from "@tiptap/react"; +import type { NodeViewProps } from "@plane/editor"; export const EmbedHandler: React.FC = () => null; diff --git a/apps/web/core/components/editor/lite-text/editor.tsx b/apps/web/core/components/editor/lite-text/editor.tsx index 472cfdf62b5..78dcacada89 100644 --- a/apps/web/core/components/editor/lite-text/editor.tsx +++ b/apps/web/core/components/editor/lite-text/editor.tsx @@ -1,9 +1,14 @@ import React, { useState } from "react"; -import { NodeViewProps } from "@tiptap/react"; // plane constants import { EIssueCommentAccessSpecifier } from "@plane/constants"; // plane imports -import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor"; +import { + type EditorRefApi, + type ILiteTextEditorProps, + LiteTextEditorWithRef, + type TFileHandler, + type NodeViewProps, +} from "@plane/editor"; import { useTranslation } from "@plane/i18n"; import type { MakeOptional } from "@plane/types"; import { cn, isCommentEmpty } from "@plane/utils"; diff --git a/apps/web/core/components/editor/rich-text/editor.tsx b/apps/web/core/components/editor/rich-text/editor.tsx index 32ca94eddf6..85b314eb605 100644 --- a/apps/web/core/components/editor/rich-text/editor.tsx +++ b/apps/web/core/components/editor/rich-text/editor.tsx @@ -1,7 +1,12 @@ import React, { forwardRef } from "react"; -import { NodeViewProps } from "@tiptap/react"; // plane imports -import { type EditorRefApi, type IRichTextEditorProps, RichTextEditorWithRef, type TFileHandler } from "@plane/editor"; +import { + type NodeViewProps, + type EditorRefApi, + type IRichTextEditorProps, + RichTextEditorWithRef, + type TFileHandler, +} from "@plane/editor"; import type { MakeOptional, TSearchEntityRequestPayload, TSearchResponse } from "@plane/types"; import { cn } from "@plane/utils"; // components diff --git a/apps/web/core/components/editor/sticky-editor/editor.tsx b/apps/web/core/components/editor/sticky-editor/editor.tsx index e2d06179c92..2e55f267933 100644 --- a/apps/web/core/components/editor/sticky-editor/editor.tsx +++ b/apps/web/core/components/editor/sticky-editor/editor.tsx @@ -1,9 +1,14 @@ import React, { useState } from "react"; // plane constants -import { NodeViewProps } from "@tiptap/react"; import { EIssueCommentAccessSpecifier } from "@plane/constants"; // plane editor -import { EditorRefApi, ILiteTextEditorProps, LiteTextEditorWithRef, TFileHandler } from "@plane/editor"; +import { + type NodeViewProps, + EditorRefApi, + ILiteTextEditorProps, + LiteTextEditorWithRef, + TFileHandler, +} from "@plane/editor"; // components import { TSticky } from "@plane/types"; // helpers diff --git a/apps/web/core/components/pages/version/editor.tsx b/apps/web/core/components/pages/version/editor.tsx index 28c466ab222..b4aec1bb5ba 100644 --- a/apps/web/core/components/pages/version/editor.tsx +++ b/apps/web/core/components/pages/version/editor.tsx @@ -1,4 +1,3 @@ -import { NodeViewProps } from "@tiptap/react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; // plane imports diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index 2dba6f258ee..acfc2cc0e3e 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -2,6 +2,7 @@ import type { Content, Extensions, JSONContent, RawCommands } from "@tiptap/core import type { MarkType, NodeType } from "@tiptap/pm/model"; import type { Selection } from "@tiptap/pm/state"; import type { EditorProps, EditorView } from "@tiptap/pm/view"; +import type { NodeViewProps as nodeViewProps } from "@tiptap/react"; // extension types import type { TTextAlign } from "@/extensions"; // types @@ -193,3 +194,5 @@ export type EditorEvents = { destroy: never; ready: { height: number }; }; + +export type NodeViewProps = nodeViewProps; diff --git a/web/ce/components/pages/editor/external-embed/embed-handler.tsx b/web/ce/components/pages/editor/external-embed/embed-handler.tsx index 2652cb35561..e34052e1e2a 100644 --- a/web/ce/components/pages/editor/external-embed/embed-handler.tsx +++ b/web/ce/components/pages/editor/external-embed/embed-handler.tsx @@ -1,3 +1,2 @@ -import { NodeViewProps } from "@tiptap/react"; - +import type { NodeViewProps } from "@plane/editor"; export const EmbedHandler: React.FC = () => null; From 5bbd8ad08bedce1c58a68732baf841854c66ffb1 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 8 Aug 2025 19:25:32 +0530 Subject: [PATCH 20/26] refactor: type --- packages/editor/src/core/types/editor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts index acfc2cc0e3e..ed26bbbdac7 100644 --- a/packages/editor/src/core/types/editor.ts +++ b/packages/editor/src/core/types/editor.ts @@ -2,7 +2,7 @@ import type { Content, Extensions, JSONContent, RawCommands } from "@tiptap/core import type { MarkType, NodeType } from "@tiptap/pm/model"; import type { Selection } from "@tiptap/pm/state"; import type { EditorProps, EditorView } from "@tiptap/pm/view"; -import type { NodeViewProps as nodeViewProps } from "@tiptap/react"; +import type { NodeViewProps as TNodeViewProps } from "@tiptap/react"; // extension types import type { TTextAlign } from "@/extensions"; // types @@ -195,4 +195,4 @@ export type EditorEvents = { ready: { height: number }; }; -export type NodeViewProps = nodeViewProps; +export type NodeViewProps = TNodeViewProps; From 6e3940ae4d45a08f588d2408da70037be3140429 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Tue, 19 Aug 2025 20:09:59 +0530 Subject: [PATCH 21/26] refactor : update community types --- .../src/core/components/editors/document/editor.tsx | 1 + packages/editor/src/core/types/extensions.ts | 9 +-------- packages/editor/src/core/types/hook.ts | 1 - packages/editor/src/styles/drag-drop.css | 6 +----- 4 files changed, 3 insertions(+), 14 deletions(-) diff --git a/packages/editor/src/core/components/editors/document/editor.tsx b/packages/editor/src/core/components/editors/document/editor.tsx index 4e0ba4244c9..8895d9dce8e 100644 --- a/packages/editor/src/core/components/editors/document/editor.tsx +++ b/packages/editor/src/core/components/editors/document/editor.tsx @@ -82,6 +82,7 @@ const DocumentEditor = (props: IDocumentEditorProps) => { initialValue: value, mentionHandler, onChange, + embedHandler, }); const editorContainerClassName = getEditorClassNames({ diff --git a/packages/editor/src/core/types/extensions.ts b/packages/editor/src/core/types/extensions.ts index b30409c1261..8c1c0a48038 100644 --- a/packages/editor/src/core/types/extensions.ts +++ b/packages/editor/src/core/types/extensions.ts @@ -1,8 +1 @@ -export type TExtensions = - | "ai" - | "collaboration-cursor" - | "issue-embed" - | "slash-commands" - | "enter-key" - | "image" - | "external-embed"; +export type TExtensions = "ai" | "collaboration-cursor" | "issue-embed" | "slash-commands" | "enter-key" | "image"; diff --git a/packages/editor/src/core/types/hook.ts b/packages/editor/src/core/types/hook.ts index 2ac9bc08227..0376fc14db6 100644 --- a/packages/editor/src/core/types/hook.ts +++ b/packages/editor/src/core/types/hook.ts @@ -30,7 +30,6 @@ export type TEditorHookProps = TCoreHookProps & | "placeholder" | "tabIndex" | "value" - | "embedHandler" > & { editable: boolean; enableHistory: boolean; diff --git a/packages/editor/src/styles/drag-drop.css b/packages/editor/src/styles/drag-drop.css index 0b09530b695..7b9577cc40e 100644 --- a/packages/editor/src/styles/drag-drop.css +++ b/packages/editor/src/styles/drag-drop.css @@ -35,10 +35,7 @@ } /* end ai handle */ -.ProseMirror:not(.dragging) - .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image):not(.table-wrapper):not( - .node-externalEmbedComponent - ) { +.ProseMirror:not(.dragging) .ProseMirror-selectednode:not(.node-imageComponent):not(.node-image):not(.table-wrapper) { position: relative; cursor: grab; outline: none !important; @@ -65,7 +62,6 @@ &.node-imageComponent, &.node-image, - &.node-externalEmbedComponent, &.table-wrapper { --horizontal-offset: 0px; From 3eb0e047b4bfdebb533c3c571ea7b4872973bab9 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Wed, 20 Aug 2025 18:44:11 +0530 Subject: [PATCH 22/26] refactor : remove external embed CE --- .../editor/external-embed/embed-handler.tsx | 6 ------ .../ce/components/editor/external-embed/index.ts | 1 - .../core/components/editor/lite-text-editor.tsx | 14 +------------- .../core/components/editor/rich-text-editor.tsx | 5 ----- .../editor/external-embed/embed-handler.tsx | 3 --- .../core/components/editor/lite-text/editor.tsx | 12 +----------- .../core/components/editor/rich-text/editor.tsx | 12 +----------- .../components/editor/sticky-editor/editor.tsx | 4 ---- .../pages/editor/external-embed/embed-handler.tsx | 2 -- 9 files changed, 3 insertions(+), 56 deletions(-) delete mode 100644 apps/space/ce/components/editor/external-embed/embed-handler.tsx delete mode 100644 apps/space/ce/components/editor/external-embed/index.ts delete mode 100644 apps/web/ce/components/editor/external-embed/embed-handler.tsx delete mode 100644 web/ce/components/pages/editor/external-embed/embed-handler.tsx diff --git a/apps/space/ce/components/editor/external-embed/embed-handler.tsx b/apps/space/ce/components/editor/external-embed/embed-handler.tsx deleted file mode 100644 index 47880b80c7c..00000000000 --- a/apps/space/ce/components/editor/external-embed/embed-handler.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import type { NodeViewProps } from "@plane/editor"; - -interface EmbedHandlerProps extends NodeViewProps { - anchor?: string; -} -export const EmbedHandler: React.FC = () => null; diff --git a/apps/space/ce/components/editor/external-embed/index.ts b/apps/space/ce/components/editor/external-embed/index.ts deleted file mode 100644 index 781518d6cfa..00000000000 --- a/apps/space/ce/components/editor/external-embed/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./embed-handler"; diff --git a/apps/space/core/components/editor/lite-text-editor.tsx b/apps/space/core/components/editor/lite-text-editor.tsx index e5bf5149137..aeaac841310 100644 --- a/apps/space/core/components/editor/lite-text-editor.tsx +++ b/apps/space/core/components/editor/lite-text-editor.tsx @@ -1,18 +1,11 @@ import React from "react"; // plane imports -import { - type NodeViewProps, - type EditorRefApi, - type ILiteTextEditorProps, - LiteTextEditorWithRef, - type TFileHandler, -} from "@plane/editor"; +import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor"; import type { MakeOptional } from "@plane/types"; import { cn } from "@plane/utils"; // helpers import { getEditorFileHandlers } from "@/helpers/editor.helper"; import { isCommentEmpty } from "@/helpers/string.helper"; -import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; // local imports import { EditorMentionsRoot } from "./embeds/mentions"; @@ -70,11 +63,6 @@ export const LiteTextEditor = React.forwardRef , }} {...rest} - embedHandler={{ - externalEmbedComponent: { - widgetCallback: (props: NodeViewProps) => , - }, - }} // overriding the containerClassName to add relative class passed containerClassName={cn(containerClassName, "relative")} /> diff --git a/apps/space/core/components/editor/rich-text-editor.tsx b/apps/space/core/components/editor/rich-text-editor.tsx index 1c83fc03119..a63948567a3 100644 --- a/apps/space/core/components/editor/rich-text-editor.tsx +++ b/apps/space/core/components/editor/rich-text-editor.tsx @@ -57,11 +57,6 @@ export const RichTextEditor = forwardRef , - }, - }} containerClassName={containerClassName} editorClassName="min-h-[100px] max-h-[200px] border-[0.5px] border-custom-border-300 rounded-md pl-3 py-2 overflow-hidden" displayConfig={{ fontSize: "large-font" }} diff --git a/apps/web/ce/components/editor/external-embed/embed-handler.tsx b/apps/web/ce/components/editor/external-embed/embed-handler.tsx deleted file mode 100644 index b1f2036d3ee..00000000000 --- a/apps/web/ce/components/editor/external-embed/embed-handler.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import type { NodeViewProps } from "@plane/editor"; - -export const EmbedHandler: React.FC = () => null; diff --git a/apps/web/core/components/editor/lite-text/editor.tsx b/apps/web/core/components/editor/lite-text/editor.tsx index 06fa46d0317..3ea059c96b8 100644 --- a/apps/web/core/components/editor/lite-text/editor.tsx +++ b/apps/web/core/components/editor/lite-text/editor.tsx @@ -2,13 +2,7 @@ import React, { useState } from "react"; // plane constants import { EIssueCommentAccessSpecifier } from "@plane/constants"; // plane imports -import { - type EditorRefApi, - type ILiteTextEditorProps, - LiteTextEditorWithRef, - type TFileHandler, - type NodeViewProps, -} from "@plane/editor"; +import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor"; import { useTranslation } from "@plane/i18n"; import type { MakeOptional } from "@plane/types"; import { cn, isCommentEmpty } from "@plane/utils"; @@ -19,7 +13,6 @@ import { IssueCommentToolbar } from "@/components/editor/lite-text/toolbar"; import { useEditorConfig, useEditorMention } from "@/hooks/editor"; import { useMember } from "@/hooks/store/use-member"; // plane web hooks -import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; // plane web services import { WorkspaceService } from "@/plane-web/services"; @@ -134,9 +127,6 @@ export const LiteTextEditor = React.forwardRef }, - }} /> {showToolbar && editable && (
}, - }} {...rest} containerClassName={cn("relative pl-3 pb-3", containerClassName)} /> diff --git a/apps/web/core/components/editor/sticky-editor/editor.tsx b/apps/web/core/components/editor/sticky-editor/editor.tsx index 34edbfdc60e..be578c34d02 100644 --- a/apps/web/core/components/editor/sticky-editor/editor.tsx +++ b/apps/web/core/components/editor/sticky-editor/editor.tsx @@ -10,7 +10,6 @@ import { cn } from "@plane/utils"; // hooks import { useEditorConfig } from "@/hooks/editor"; // plane web hooks -import { EmbedHandler } from "@/plane-web/components/editor/external-embed/embed-handler"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; import { StickyEditorToolbar } from "./toolbar"; @@ -82,9 +81,6 @@ export const StickyEditor = React.forwardRef }, - }} /> {showToolbar && (
= () => null; From f19456bc420f442695a029f5da8b62561d7dfc15 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Thu, 21 Aug 2025 16:59:42 +0530 Subject: [PATCH 23/26] remove : external embed config from ce --- apps/space/ce/components/editor/index.ts | 1 - apps/space/core/components/editor/lite-text-editor.tsx | 2 +- apps/web/core/components/editor/lite-text/editor.tsx | 2 +- apps/web/core/components/editor/sticky-editor/editor.tsx | 2 +- packages/editor/src/ce/extensions/core/extensions.ts | 2 +- packages/editor/src/ce/types/issue-embed.ts | 5 ----- 6 files changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/space/ce/components/editor/index.ts b/apps/space/ce/components/editor/index.ts index 3501cf0ef81..cf8352ae4a8 100644 --- a/apps/space/ce/components/editor/index.ts +++ b/apps/space/ce/components/editor/index.ts @@ -1,2 +1 @@ export * from "./embeds"; -export * from "./external-embed"; diff --git a/apps/space/core/components/editor/lite-text-editor.tsx b/apps/space/core/components/editor/lite-text-editor.tsx index aeaac841310..fec17f1a5ae 100644 --- a/apps/space/core/components/editor/lite-text-editor.tsx +++ b/apps/space/core/components/editor/lite-text-editor.tsx @@ -12,7 +12,7 @@ import { EditorMentionsRoot } from "./embeds/mentions"; import { IssueCommentToolbar } from "./toolbar"; type LiteTextEditorWrapperProps = MakeOptional< - Omit, + Omit, "disabledExtensions" | "flaggedExtensions" > & { anchor: string; diff --git a/apps/web/core/components/editor/lite-text/editor.tsx b/apps/web/core/components/editor/lite-text/editor.tsx index 3ea059c96b8..feb99ea6e0b 100644 --- a/apps/web/core/components/editor/lite-text/editor.tsx +++ b/apps/web/core/components/editor/lite-text/editor.tsx @@ -19,7 +19,7 @@ import { WorkspaceService } from "@/plane-web/services"; const workspaceService = new WorkspaceService(); type LiteTextEditorWrapperProps = MakeOptional< - Omit, + Omit, "disabledExtensions" | "flaggedExtensions" > & { workspaceSlug: string; diff --git a/apps/web/core/components/editor/sticky-editor/editor.tsx b/apps/web/core/components/editor/sticky-editor/editor.tsx index be578c34d02..aa86d1ed586 100644 --- a/apps/web/core/components/editor/sticky-editor/editor.tsx +++ b/apps/web/core/components/editor/sticky-editor/editor.tsx @@ -16,7 +16,7 @@ import { StickyEditorToolbar } from "./toolbar"; interface StickyEditorWrapperProps extends Omit< ILiteTextEditorProps, - "disabledExtensions" | "editable" | "flaggedExtensions" | "fileHandler" | "mentionHandler" | "embedHandler" + "disabledExtensions" | "editable" | "flaggedExtensions" | "fileHandler" | "mentionHandler" > { workspaceSlug: string; workspaceId: string; diff --git a/packages/editor/src/ce/extensions/core/extensions.ts b/packages/editor/src/ce/extensions/core/extensions.ts index da03ba38615..a72bcc2159d 100644 --- a/packages/editor/src/ce/extensions/core/extensions.ts +++ b/packages/editor/src/ce/extensions/core/extensions.ts @@ -4,7 +4,7 @@ import type { IEditorProps } from "@/types"; export type TCoreAdditionalExtensionsProps = Pick< IEditorProps, - "disabledExtensions" | "flaggedExtensions" | "fileHandler" | "embedHandler" + "disabledExtensions" | "flaggedExtensions" | "fileHandler" >; export const CoreEditorAdditionalExtensions = (props: TCoreAdditionalExtensionsProps): Extensions => { diff --git a/packages/editor/src/ce/types/issue-embed.ts b/packages/editor/src/ce/types/issue-embed.ts index 324969ff50b..d68d182a043 100644 --- a/packages/editor/src/ce/types/issue-embed.ts +++ b/packages/editor/src/ce/types/issue-embed.ts @@ -1,12 +1,7 @@ -import { NodeViewProps } from "@tiptap/react"; - export type TEmbedConfig = { issue?: TIssueEmbedConfig; - externalEmbedComponent?: TExternalEmbedConfig; }; -export type TExternalEmbedConfig = { widgetCallback: (props: NodeViewProps) => React.ReactNode }; - export type TReadOnlyEmbedConfig = TEmbedConfig; export type TIssueEmbedConfig = { From b378d1653cc669a008081d3f34849a0c3082af8c Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 22 Aug 2025 17:00:21 +0530 Subject: [PATCH 24/26] refactor : update disabled --- apps/space/core/components/editor/lite-text-editor.tsx | 1 + apps/space/core/components/editor/rich-text-editor.tsx | 2 +- apps/web/core/components/editor/rich-text/editor.tsx | 2 +- .../components/editors/document/collaborative-editor.tsx | 1 + .../core/components/editors/document/page-renderer.tsx | 8 +++++++- packages/editor/src/core/components/menus/block-menu.tsx | 1 + 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/space/core/components/editor/lite-text-editor.tsx b/apps/space/core/components/editor/lite-text-editor.tsx index fec17f1a5ae..3223135c99c 100644 --- a/apps/space/core/components/editor/lite-text-editor.tsx +++ b/apps/space/core/components/editor/lite-text-editor.tsx @@ -47,6 +47,7 @@ export const LiteTextEditor = React.forwardRef(ref) ? ref.current : null; const { liteText: liteTextEditorExtensions } = useEditorFlagging(anchor); + return (
, + Omit, "disabledExtensions" | "flaggedExtensions" > & { anchor: string; diff --git a/apps/web/core/components/editor/rich-text/editor.tsx b/apps/web/core/components/editor/rich-text/editor.tsx index f69482cca57..aaaa0898dbf 100644 --- a/apps/web/core/components/editor/rich-text/editor.tsx +++ b/apps/web/core/components/editor/rich-text/editor.tsx @@ -12,7 +12,7 @@ import { useMember } from "@/hooks/store/use-member"; import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging"; type RichTextEditorWrapperProps = MakeOptional< - Omit, + Omit, "disabledExtensions" | "editable" | "flaggedExtensions" > & { workspaceSlug: string; 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 61346a09839..535f1b6ba13 100644 --- a/packages/editor/src/core/components/editors/document/collaborative-editor.tsx +++ b/packages/editor/src/core/components/editors/document/collaborative-editor.tsx @@ -109,6 +109,7 @@ const CollaborativeDocumentEditor: React.FC = isLoading={!hasServerSynced && !hasServerConnectionFailed} tabIndex={tabIndex} flaggedExtensions={flaggedExtensions} + disabledExtensions={disabledExtensions} /> ); }; 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 1c852519b52..7a628b3b22a 100644 --- a/packages/editor/src/core/components/editors/document/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -19,6 +19,7 @@ type Props = { isTouchDevice: boolean; tabIndex?: number; flaggedExtensions?: IEditorProps["flaggedExtensions"]; + disabledExtensions?: IEditorProps["disabledExtensions"]; }; export const PageRenderer = (props: Props) => { @@ -34,6 +35,7 @@ export const PageRenderer = (props: Props) => { isTouchDevice, tabIndex, flaggedExtensions, + disabledExtensions, } = props; return ( @@ -56,7 +58,11 @@ export const PageRenderer = (props: Props) => { {editor.isEditable && !isTouchDevice && (
{bubbleMenuEnabled && } - +
)} diff --git a/packages/editor/src/core/components/menus/block-menu.tsx b/packages/editor/src/core/components/menus/block-menu.tsx index 0d3f5cc6a31..43c0193c715 100644 --- a/packages/editor/src/core/components/menus/block-menu.tsx +++ b/packages/editor/src/core/components/menus/block-menu.tsx @@ -9,6 +9,7 @@ import { IEditorProps } from "@/types"; type Props = { editor: Editor; flaggedExtensions?: IEditorProps["flaggedExtensions"]; + disabledExtensions?: IEditorProps["disabledExtensions"]; }; export const BlockMenu = (props: Props) => { From 294318bc618ef3f589fb28022070700359e1d222 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 22 Aug 2025 17:02:56 +0530 Subject: [PATCH 25/26] chore: pass disabled --- packages/editor/src/core/components/editors/document/editor.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/editor/src/core/components/editors/document/editor.tsx b/packages/editor/src/core/components/editors/document/editor.tsx index 8895d9dce8e..85285adea2a 100644 --- a/packages/editor/src/core/components/editors/document/editor.tsx +++ b/packages/editor/src/core/components/editors/document/editor.tsx @@ -100,6 +100,7 @@ const DocumentEditor = (props: IDocumentEditorProps) => { id={id} isTouchDevice={!!isTouchDevice} flaggedExtensions={flaggedExtensions} + disabledExtensions={disabledExtensions} /> ); }; From 696a4b5b19faaf67e96ae16f7bfba0a829071771 Mon Sep 17 00:00:00 2001 From: VipinDevelops Date: Fri, 22 Aug 2025 17:03:43 +0530 Subject: [PATCH 26/26] chore : update utils --- packages/utils/src/string.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/src/string.ts b/packages/utils/src/string.ts index 6ffb4ea0411..062a162abec 100644 --- a/packages/utils/src/string.ts +++ b/packages/utils/src/string.ts @@ -174,7 +174,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => { return ( comment?.trim() === "" || comment === "

" || - isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"]) + isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component", "embed-component"]) ); };