diff --git a/package.json b/package.json index 758af2da6..b975be60b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "web", "space", "admin", - "packages/editor/*", + "packages/editor", "packages/eslint-config-custom", "packages/tailwind-config-custom", "packages/tsconfig", diff --git a/packages/editor/core/.eslintrc.js b/packages/editor/.eslintrc.js similarity index 100% rename from packages/editor/core/.eslintrc.js rename to packages/editor/.eslintrc.js diff --git a/packages/editor/core/.prettierignore b/packages/editor/.prettierignore similarity index 100% rename from packages/editor/core/.prettierignore rename to packages/editor/.prettierignore diff --git a/packages/editor/core/.prettierrc b/packages/editor/.prettierrc similarity index 100% rename from packages/editor/core/.prettierrc rename to packages/editor/.prettierrc diff --git a/packages/editor/core/Readme.md b/packages/editor/Readme.md similarity index 85% rename from packages/editor/core/Readme.md rename to packages/editor/Readme.md index aafda7008..75aad2c95 100644 --- a/packages/editor/core/Readme.md +++ b/packages/editor/Readme.md @@ -1,8 +1,8 @@ -# @plane/editor-core +# @plane/editor ## Description -The `@plane/editor-core` package serves as the foundation for our editor system. It provides the base functionality for our other editor packages, but it will not be used directly in any of the projects but only for extending other editors. +The `@plane/editor` package serves as the foundation for our editor system. It provides the base functionality for our other editor packages, but it will not be used directly in any of the projects but only for extending other editors. ## Utilities @@ -64,40 +64,6 @@ const customEditorClassNames = getEditorClassNames({ - **Value Cleaning**: The Editor’s value is cleaned at the editor core level, eliminating the need for additional validation before sending from our app. This results in cleaner code and less potential for errors. - **Turbo Pipeline**: Added a turbo pipeline for both dev and build tasks for projects depending on the editor package. -```json - "web#develop": { - "cache": false, - "persistent": true, - "dependsOn": [ - "@plane/lite-text-editor#build", - "@plane/rich-text-editor#build" - ] - }, - "space#develop": { - "cache": false, - "persistent": true, - "dependsOn": [ - "@plane/lite-text-editor#build", - "@plane/rich-text-editor#build" - ] - }, - "web#build": { - "cache": true, - "dependsOn": [ - "@plane/lite-text-editor#build", - "@plane/rich-text-editor#build" - ] - }, - "space#build": { - "cache": true, - "dependsOn": [ - "@plane/lite-text-editor#build", - "@plane/rich-text-editor#build" - ] - }, - -``` - ## Base extensions included - BulletList diff --git a/packages/editor/core/src/index.ts b/packages/editor/core/src/index.ts deleted file mode 100644 index 493f02d2f..000000000 --- a/packages/editor/core/src/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -// styles -// import "./styles/tailwind.css"; -import "src/styles/editor.css"; -import "src/styles/table.css"; -import "src/styles/github-dark.css"; - -export { isCellSelection } from "src/ui/extensions/table/table/utilities/is-cell-selection"; - -// utils -export * from "src/lib/utils"; -export * from "src/ui/extensions/table/table"; -export { startImageUpload } from "src/ui/plugins/image/image-upload-handler"; - -// components -export { EditorContainer } from "src/ui/components/editor-container"; -export { EditorContentWrapper } from "src/ui/components/editor-content"; - -// hooks -export { useEditor } from "src/hooks/use-editor"; -export { useReadOnlyEditor } from "src/hooks/use-read-only-editor"; - -// helper items -export * from "src/ui/menus/menu-items"; -export * from "src/lib/editor-commands"; - -// types -export type { CustomEditorProps, TFileHandler } from "src/hooks/use-editor"; -export type { DeleteImage } from "src/types/delete-image"; -export type { UploadImage } from "src/types/upload-image"; -export type { EditorRefApi, EditorReadOnlyRefApi } from "src/types/editor-ref-api"; -export type { RestoreImage } from "src/types/restore-image"; -export type { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion"; -export type { ISlashCommandItem, CommandProps } from "src/types/slash-commands-suggestion"; -export type { LucideIconType } from "src/types/lucide-icon"; diff --git a/packages/editor/core/src/types/delete-image.ts b/packages/editor/core/src/types/delete-image.ts deleted file mode 100644 index 40bfffe2f..000000000 --- a/packages/editor/core/src/types/delete-image.ts +++ /dev/null @@ -1 +0,0 @@ -export type DeleteImage = (assetUrlWithWorkspaceId: string) => Promise; diff --git a/packages/editor/core/src/types/editor-ref-api.ts b/packages/editor/core/src/types/editor-ref-api.ts deleted file mode 100644 index b15ae943d..000000000 --- a/packages/editor/core/src/types/editor-ref-api.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { IMarking } from "src/helpers/scroll-to-node"; -import { EditorMenuItemNames } from "src/ui/menus/menu-items"; - -export type EditorReadOnlyRefApi = { - getMarkDown: () => string; - getHTML: () => string; - clearEditor: () => void; - setEditorValue: (content: string) => void; - scrollSummary: (marking: IMarking) => void; -}; - -export interface EditorRefApi extends EditorReadOnlyRefApi { - setEditorValueAtCursorPosition: (content: string) => void; - executeMenuItemCommand: (itemName: EditorMenuItemNames) => void; - isMenuItemActive: (itemName: EditorMenuItemNames) => boolean; - onStateChange: (callback: () => void) => () => void; - setFocusAtPosition: (position: number) => void; - isEditorReadyToDiscard: () => boolean; -} diff --git a/packages/editor/core/src/types/lucide-icon.ts b/packages/editor/core/src/types/lucide-icon.ts deleted file mode 100644 index 2211c18e8..000000000 --- a/packages/editor/core/src/types/lucide-icon.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Smile } from "lucide-react"; - -export type LucideIconType = typeof Smile; diff --git a/packages/editor/core/src/types/restore-image.ts b/packages/editor/core/src/types/restore-image.ts deleted file mode 100644 index 9b33177b7..000000000 --- a/packages/editor/core/src/types/restore-image.ts +++ /dev/null @@ -1 +0,0 @@ -export type RestoreImage = (assetUrlWithWorkspaceId: string) => Promise; diff --git a/packages/editor/core/src/types/upload-image.ts b/packages/editor/core/src/types/upload-image.ts deleted file mode 100644 index 3cf1408d2..000000000 --- a/packages/editor/core/src/types/upload-image.ts +++ /dev/null @@ -1 +0,0 @@ -export type UploadImage = (file: File) => Promise; diff --git a/packages/editor/core/src/ui/mentions/custom.tsx b/packages/editor/core/src/ui/mentions/custom.tsx deleted file mode 100644 index 8bab79666..000000000 --- a/packages/editor/core/src/ui/mentions/custom.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Mention, MentionOptions } from "@tiptap/extension-mention"; -import { mergeAttributes } from "@tiptap/core"; -import { ReactNodeViewRenderer } from "@tiptap/react"; -import { MentionNodeView } from "src/ui/mentions/mention-node-view"; -import { IMentionHighlight } from "src/types/mention-suggestion"; - -export interface CustomMentionOptions extends MentionOptions { - mentionHighlights: () => Promise; - readonly?: boolean; -} - -export const CustomMention = Mention.extend({ - addStorage(this) { - return { - mentionsOpen: false, - }; - }, - addAttributes() { - return { - id: { - default: null, - }, - label: { - default: null, - }, - target: { - default: null, - }, - self: { - default: false, - }, - redirect_uri: { - default: "/", - }, - entity_identifier: { - default: null, - }, - entity_name: { - default: null, - }, - }; - }, - - addNodeView() { - return ReactNodeViewRenderer(MentionNodeView); - }, - - parseHTML() { - return [ - { - tag: "mention-component", - }, - ]; - }, - renderHTML({ HTMLAttributes }) { - return ["mention-component", mergeAttributes(HTMLAttributes)]; - }, -}); diff --git a/packages/editor/core/src/ui/mentions/mention-without-props.tsx b/packages/editor/core/src/ui/mentions/mention-without-props.tsx deleted file mode 100644 index a0d22ef4f..000000000 --- a/packages/editor/core/src/ui/mentions/mention-without-props.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { CustomMention } from "./custom"; -import { ReactRenderer } from "@tiptap/react"; -import { Editor } from "@tiptap/core"; -import tippy from "tippy.js"; - -import { MentionList } from "./mention-list"; - -export const MentionsWithoutProps = () => - CustomMention.configure({ - HTMLAttributes: { - class: "mention", - }, - // mentionHighlights: mentionHighlights, - suggestion: { - // @ts-expect-error - Tiptap types are incorrect - render: () => { - let component: ReactRenderer | null = null; - let popup: any | null = null; - - return { - onStart: (props: { editor: Editor; clientRect: DOMRect }) => { - if (!props.clientRect) { - return; - } - component = new ReactRenderer(MentionList, { - props: { ...props }, - editor: props.editor, - }); - props.editor.storage.mentionsOpen = true; - // @ts-expect-error - Tippy types are incorrect - popup = tippy("body", { - getReferenceClientRect: props.clientRect, - appendTo: () => document.querySelector(".active-editor") ?? document.querySelector("#editor-container"), - content: component.element, - showOnCreate: true, - interactive: true, - trigger: "manual", - placement: "bottom-start", - }); - }, - onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => { - component?.updateProps(props); - - if (!props.clientRect) { - return; - } - - popup && - popup[0].setProps({ - getReferenceClientRect: props.clientRect, - }); - }, - - onKeyDown: (props: { event: KeyboardEvent }) => { - if (props.event.key === "Escape") { - popup?.[0].hide(); - - return true; - } - - const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"]; - - if (navigationKeys.includes(props.event.key)) { - // @ts-expect-error - Tippy types are incorrect - component?.ref?.onKeyDown(props); - event?.stopPropagation(); - return true; - } - return false; - }, - onExit: (props: { editor: Editor; event: KeyboardEvent }) => { - props.editor.storage.mentionsOpen = false; - popup?.[0].destroy(); - component?.destroy(); - }, - }; - }, - }, - }); diff --git a/packages/editor/core/src/ui/mentions/suggestion.ts b/packages/editor/core/src/ui/mentions/suggestion.ts deleted file mode 100644 index 8eaf0982f..000000000 --- a/packages/editor/core/src/ui/mentions/suggestion.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; -import { IMentionSuggestion } from "src/types/mention-suggestion"; - -export const getSuggestionItems = - (suggestions: IMentionSuggestion[]) => - ({ query }: { query: string }) => { - const mappedSuggestions: IMentionSuggestion[] = suggestions.map((suggestion): IMentionSuggestion => { - const transactionId = uuidv4(); - return { - ...suggestion, - id: transactionId, - }; - }); - return mappedSuggestions - .filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase())) - .slice(0, 5); - }; diff --git a/packages/editor/core/tsconfig.json b/packages/editor/core/tsconfig.json deleted file mode 100644 index c15534037..000000000 --- a/packages/editor/core/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "tsconfig/react-library.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ], - "compilerOptions": { - "baseUrl": "." - } -} diff --git a/packages/editor/document-editor/.eslintrc.js b/packages/editor/document-editor/.eslintrc.js deleted file mode 100644 index c8df60750..000000000 --- a/packages/editor/document-editor/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["custom"], -}; diff --git a/packages/editor/document-editor/.prettierignore b/packages/editor/document-editor/.prettierignore deleted file mode 100644 index 43e8a7b8f..000000000 --- a/packages/editor/document-editor/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -.next -.vercel -.tubro -out/ -dis/ -build/ \ No newline at end of file diff --git a/packages/editor/document-editor/.prettierrc b/packages/editor/document-editor/.prettierrc deleted file mode 100644 index 87d988f1b..000000000 --- a/packages/editor/document-editor/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "printWidth": 120, - "tabWidth": 2, - "trailingComma": "es5" -} diff --git a/packages/editor/document-editor/Readme.md b/packages/editor/document-editor/Readme.md deleted file mode 100644 index f019d6827..000000000 --- a/packages/editor/document-editor/Readme.md +++ /dev/null @@ -1 +0,0 @@ -# Document Editor diff --git a/packages/editor/document-editor/package.json b/packages/editor/document-editor/package.json deleted file mode 100644 index b565bfedf..000000000 --- a/packages/editor/document-editor/package.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "@plane/document-editor", - "version": "0.21.0", - "description": "Package that powers Plane's Pages Editor", - "main": "./dist/index.mjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.mts", - "files": [ - "dist/**/*" - ], - "exports": { - ".": { - "types": "./dist/index.d.mts", - "import": "./dist/index.mjs", - "module": "./dist/index.mjs" - } - }, - "scripts": { - "build": "tsup --minify", - "dev": "tsup --watch", - "check-types": "tsc --noEmit", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "peerDependencies": { - "next": "12.3.2", - "next-themes": "^0.2.1", - "react": "^18.2.0", - "react-dom": "18.2.0" - }, - "dependencies": { - "@floating-ui/react": "^0.26.4", - "@plane/editor-core": "*", - "@plane/editor-extensions": "*", - "@plane/ui": "*", - "@tippyjs/react": "^4.2.6", - "@tiptap/core": "^2.1.13", - "@tiptap/extension-collaboration": "^2.3.2", - "@tiptap/pm": "^2.1.13", - "@tiptap/suggestion": "^2.1.13", - "lucide-react": "^0.378.0", - "react-popper": "^2.3.0", - "tippy.js": "^6.3.7", - "uuid": "^9.0.1", - "y-indexeddb": "^9.0.12", - "y-prosemirror": "^1.2.5", - "y-protocols": "^1.0.6", - "yjs": "^13.6.15" - }, - "devDependencies": { - "@types/node": "18.15.3", - "@types/react": "^18.2.42", - "@types/react-dom": "^18.2.17", - "eslint-config-custom": "*", - "postcss": "^8.4.38", - "tailwind-config-custom": "*", - "tsconfig": "*", - "tsup": "^7.2.0", - "typescript": "4.9.5" - }, - "keywords": [ - "editor", - "rich-text", - "markdown", - "nextjs", - "react" - ] -} diff --git a/packages/editor/document-editor/postcss.config.js b/packages/editor/document-editor/postcss.config.js deleted file mode 100644 index 419fe25d1..000000000 --- a/packages/editor/document-editor/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -// If you want to use other PostCSS plugins, see the following: -// https://tailwindcss.com/docs/using-with-preprocessors - -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, - }; \ No newline at end of file diff --git a/packages/editor/document-editor/src/index.ts b/packages/editor/document-editor/src/index.ts deleted file mode 100644 index 9e8407ce3..000000000 --- a/packages/editor/document-editor/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export { DocumentEditor, DocumentEditorWithRef } from "src/ui"; -export { DocumentReadOnlyEditor, DocumentReadOnlyEditorWithRef } from "src/ui/readonly"; - -// hooks -export { useEditorMarkings } from "src/hooks/use-editor-markings"; -// utils -export { proseMirrorJSONToBinaryString, applyUpdates, mergeUpdates } from "src/utils/yjs"; - -export type { EditorRefApi, EditorReadOnlyRefApi, EditorMenuItem, EditorMenuItemNames } from "@plane/editor-core"; - -export type { IMarking } from "src/types/editor-types"; diff --git a/packages/editor/document-editor/src/types/editor-types.ts b/packages/editor/document-editor/src/types/editor-types.ts deleted file mode 100644 index 476642103..000000000 --- a/packages/editor/document-editor/src/types/editor-types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IMarking { - type: "heading"; - level: number; - text: string; - sequence: number; -} diff --git a/packages/editor/document-editor/src/types/mark.ts b/packages/editor/document-editor/src/types/mark.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/editor/document-editor/src/types/menu-actions.d.ts b/packages/editor/document-editor/src/types/menu-actions.d.ts deleted file mode 100644 index 87e848be7..000000000 --- a/packages/editor/document-editor/src/types/menu-actions.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -export interface IDuplicationConfig { - action: () => Promise; -} -export interface IPageLockConfig { - is_locked: boolean; - action: () => Promise; - locked_by?: string; -} -export interface IPageArchiveConfig { - is_archived: boolean; - archived_at?: Date; - action: () => Promise; -} diff --git a/packages/editor/document-editor/src/ui/components/index.ts b/packages/editor/document-editor/src/ui/components/index.ts deleted file mode 100644 index 4d2d76baa..000000000 --- a/packages/editor/document-editor/src/ui/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./page-renderer"; diff --git a/packages/editor/document-editor/src/ui/extensions/index.tsx b/packages/editor/document-editor/src/ui/extensions/index.tsx deleted file mode 100644 index 10c9fa596..000000000 --- a/packages/editor/document-editor/src/ui/extensions/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { IssueWidgetPlaceholder } from "src/ui/extensions/widgets/issue-embed-widget"; - -import { SlashCommand, DragAndDrop } from "@plane/editor-extensions"; -import { UploadImage } from "@plane/editor-core"; -import { CollaborationProvider } from "src/providers/collaboration-provider"; -import Collaboration from "@tiptap/extension-collaboration"; - -type TArguments = { - uploadFile: UploadImage; - setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void; - provider: CollaborationProvider; -}; - -export const DocumentEditorExtensions = ({ uploadFile, setHideDragHandle, provider }: TArguments) => [ - SlashCommand(uploadFile), - DragAndDrop(setHideDragHandle), - IssueWidgetPlaceholder(), - Collaboration.configure({ - document: provider.document, - }), -]; diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/index.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/index.tsx deleted file mode 100644 index 35a09bcc2..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Editor, Range } from "@tiptap/react"; -import { IssueEmbedSuggestions } from "src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-extension"; -import { getIssueSuggestionItems } from "src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-items"; -import { IssueListRenderer } from "src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer"; -import { v4 as uuidv4 } from "uuid"; - -export type CommandProps = { - editor: Editor; - range: Range; -}; - -export interface IIssueListSuggestion { - title: string; - priority: "high" | "low" | "medium" | "urgent"; - identifier: string; - state: "Cancelled" | "In Progress" | "Todo" | "Done" | "Backlog"; - command: ({ editor, range }: CommandProps) => void; -} - -export const IssueSuggestions = (suggestions: any[]) => { - const mappedSuggestions: IIssueListSuggestion[] = suggestions.map((suggestion): IIssueListSuggestion => { - const transactionId = uuidv4(); - return { - title: suggestion.name, - priority: suggestion.priority.toString(), - identifier: `${suggestion.project_detail.identifier}-${suggestion.sequence_id}`, - state: suggestion.state_detail && suggestion.state_detail.name ? suggestion.state_detail.name : "Todo", - command: ({ editor, range }) => { - editor - .chain() - .focus() - .insertContentAt(range, { - type: "issue-embed-component", - attrs: { - entity_identifier: suggestion.id, - id: transactionId, - title: suggestion.name, - project_identifier: suggestion.project_detail.identifier, - sequence_id: suggestion.sequence_id, - entity_name: "issue", - }, - }) - .run(); - }, - }; - }); - - return IssueEmbedSuggestions.configure({ - suggestion: { - items: getIssueSuggestionItems(mappedSuggestions), - render: IssueListRenderer, - }, - }); -}; diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-extension.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-extension.tsx deleted file mode 100644 index 96a5c1325..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-extension.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Extension, Range } from "@tiptap/core"; -import { PluginKey } from "@tiptap/pm/state"; -import { Editor } from "@tiptap/react"; -import Suggestion from "@tiptap/suggestion"; - -export const IssueEmbedSuggestions = Extension.create({ - name: "issue-embed-suggestions", - - addOptions() { - return { - suggestion: { - char: "#issue_", - allowSpaces: true, - command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => { - props.command({ editor, range }); - }, - }, - }; - }, - addProseMirrorPlugins() { - return [ - Suggestion({ - pluginKey: new PluginKey("issue-embed-suggestions"), - editor: this.editor, - ...this.options.suggestion, - }), - ]; - }, -}); diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-items.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-items.tsx deleted file mode 100644 index df468f2ee..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-items.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { IIssueListSuggestion } from "src/ui/extensions/widgets/issue-embed-suggestion-list"; - -export const getIssueSuggestionItems = - (issueSuggestions: Array) => - ({ query }: { query: string }) => { - const search = query.toLowerCase(); - const filteredSuggestions = issueSuggestions.filter( - (item) => - item.title.toLowerCase().includes(search) || - item.identifier.toLowerCase().includes(search) || - item.priority.toLowerCase().includes(search) - ); - - return filteredSuggestions; - }; diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx deleted file mode 100644 index da6cd250c..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-suggestion-list/issue-suggestion-renderer.tsx +++ /dev/null @@ -1,256 +0,0 @@ -"use client"; - -import { cn } from "@plane/editor-core"; -import { Editor } from "@tiptap/core"; -import tippy from "tippy.js"; -import { ReactRenderer } from "@tiptap/react"; -import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react"; -import { PriorityIcon } from "@plane/ui"; - -const updateScrollView = (container: HTMLElement, item: HTMLElement) => { - const containerHeight = container.offsetHeight; - const itemHeight = item ? item.offsetHeight : 0; - - const top = item.offsetTop; - const bottom = top + itemHeight; - - if (top < container.scrollTop) { - // container.scrollTop = top - containerHeight; - item.scrollIntoView({ - behavior: "smooth", - block: "center", - }); - } else if (bottom > containerHeight + container.scrollTop) { - // container.scrollTop = bottom - containerHeight; - item.scrollIntoView({ - behavior: "smooth", - block: "center", - }); - } -}; -interface IssueSuggestionProps { - title: string; - priority: "high" | "low" | "medium" | "urgent" | "none"; - state: "Cancelled" | "In Progress" | "Todo" | "Done" | "Backlog"; - identifier: string; -} - -const IssueSuggestionList = ({ - items, - command, - editor, -}: { - items: IssueSuggestionProps[]; - command: any; - editor: Editor; - range: any; -}) => { - const [selectedIndex, setSelectedIndex] = useState(0); - const [currentSection, setCurrentSection] = useState("Backlog"); - const sections = ["Backlog", "In Progress", "Todo", "Done", "Cancelled"]; - const [displayedItems, setDisplayedItems] = useState<{ - [key: string]: IssueSuggestionProps[]; - }>({}); - const [displayedTotalLength, setDisplayedTotalLength] = useState(0); - const commandListContainer = useRef(null); - - useEffect(() => { - const newDisplayedItems: { [key: string]: IssueSuggestionProps[] } = {}; - let totalLength = 0; - sections.forEach((section) => { - newDisplayedItems[section] = items.filter((item) => item.state === section).slice(0, 5); - - totalLength += newDisplayedItems[section].length; - }); - setDisplayedTotalLength(totalLength); - setDisplayedItems(newDisplayedItems); - }, [items]); - - const selectItem = useCallback( - (section: string, index: number) => { - const item = displayedItems[section][index]; - if (item) { - command(item); - } - }, - [command, displayedItems, currentSection] - ); - - useEffect(() => { - const navigationKeys = ["ArrowUp", "ArrowDown", "Enter", "Tab"]; - const onKeyDown = (e: KeyboardEvent) => { - if (navigationKeys.includes(e.key)) { - // if (editor.isFocused) { - // editor.chain().blur(); - // commandListContainer.current?.focus(); - // } - if (e.key === "ArrowUp") { - setSelectedIndex( - (selectedIndex + displayedItems[currentSection].length - 1) % displayedItems[currentSection].length - ); - return true; - } - if (e.key === "ArrowDown") { - const nextIndex = (selectedIndex + 1) % displayedItems[currentSection].length; - setSelectedIndex(nextIndex); - if (nextIndex === 4) { - const nextItems = items - .filter((item) => item.state === currentSection) - .slice(displayedItems[currentSection].length, displayedItems[currentSection].length + 5); - setDisplayedItems((prevItems) => ({ - ...prevItems, - [currentSection]: [...prevItems[currentSection], ...nextItems], - })); - } - return true; - } - if (e.key === "Enter") { - selectItem(currentSection, selectedIndex); - return true; - } - if (e.key === "Tab") { - const currentSectionIndex = sections.indexOf(currentSection); - const nextSectionIndex = (currentSectionIndex + 1) % sections.length; - setCurrentSection(sections[nextSectionIndex]); - setSelectedIndex(0); - return true; - } - return false; - } else if (e.key === "Escape") { - if (!editor.isFocused) { - editor.chain().focus(); - } - } - }; - document.addEventListener("keydown", onKeyDown); - return () => { - document.removeEventListener("keydown", onKeyDown); - }; - }, [displayedItems, selectedIndex, setSelectedIndex, selectItem, currentSection]); - - useLayoutEffect(() => { - const container = commandListContainer?.current; - if (container) { - const sectionContainer = container?.querySelector(`#${currentSection}-container`) as HTMLDivElement; - if (sectionContainer) { - updateScrollView(container, sectionContainer); - } - const sectionScrollContainer = container?.querySelector(`#${currentSection}`) as HTMLElement; - const item = sectionScrollContainer?.children[selectedIndex] as HTMLElement; - if (item && sectionScrollContainer) { - updateScrollView(sectionScrollContainer, item); - } - } - }, [selectedIndex, currentSection]); - - return displayedTotalLength > 0 ? ( -
- {sections.map((section) => { - const sectionItems = displayedItems[section]; - return ( - sectionItems && - sectionItems.length > 0 && ( -
-
- {section} -
-
- {sectionItems.map((item: IssueSuggestionProps, index: number) => ( - - ))} -
-
- ) - ); - })} -
- ) : null; -}; -export const IssueListRenderer = () => { - let component: ReactRenderer | null = null; - let popup: any | null = null; - - return { - onStart: (props: { editor: Editor; clientRect?: (() => DOMRect | null) | null }) => { - const container = document.querySelector(".frame-renderer") as HTMLElement; - component = new ReactRenderer(IssueSuggestionList, { - props, - // @ts-ignore - editor: props.editor, - }); - // @ts-ignore - popup = tippy(".frame-renderer", { - flipbehavior: ["bottom", "top"], - appendTo: () => document.querySelector(".frame-renderer") as HTMLElement, - flip: true, - flipOnUpdate: true, - getReferenceClientRect: props.clientRect, - content: component.element, - showOnCreate: true, - interactive: true, - trigger: "manual", - placement: "bottom-start", - }); - - container.addEventListener("scroll", () => { - popup?.[0].destroy(); - }); - }, - onUpdate: (props: { editor: Editor; clientRect?: (() => DOMRect | null) | null }) => { - component?.updateProps(props); - - popup && - popup[0].setProps({ - getReferenceClientRect: props.clientRect, - }); - }, - onKeyDown: (props: { event: KeyboardEvent }) => { - if (props.event.key === "Escape") { - popup?.[0].hide(); - return true; - } - - const navigationKeys = ["ArrowUp", "ArrowDown", "Enter", "Tab"]; - if (navigationKeys.includes(props.event.key)) { - // @ts-ignore - component?.ref?.onKeyDown(props); - return true; - } - return false; - }, - onExit: (e) => { - const container = document.querySelector(".frame-renderer") as HTMLElement; - if (container) { - container.removeEventListener("scroll", () => {}); - } - popup?.[0].destroy(); - setTimeout(() => { - component?.destroy(); - }, 300); - }, - }; -}; diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx deleted file mode 100644 index 264a70152..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/index.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { IssueWidget } from "src/ui/extensions/widgets/issue-embed-widget/issue-widget-node"; - -export const IssueWidgetPlaceholder = () => IssueWidget.configure({}); diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx deleted file mode 100644 index bc0ca00fa..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-card.tsx +++ /dev/null @@ -1,35 +0,0 @@ -"use client"; - -// @ts-nocheck -import { Button } from "@plane/ui"; -import { NodeViewWrapper } from "@tiptap/react"; -import { Crown } from "lucide-react"; - -export const IssueWidgetCard = (props) => ( - -
-
- {props.node.attrs.project_identifier}-{props.node.attrs.sequence_id} -
-
-
-
-
- -
-
- Embed and access issues in pages seamlessly, upgrade to plane pro now. -
-
- - - -
-
-
-
-); diff --git a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx b/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx deleted file mode 100644 index 6c744927a..000000000 --- a/packages/editor/document-editor/src/ui/extensions/widgets/issue-embed-widget/issue-widget-node.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { mergeAttributes, Node } from "@tiptap/core"; -import { IssueWidgetCard } from "src/ui/extensions/widgets/issue-embed-widget/issue-widget-card"; -import { ReactNodeViewRenderer } from "@tiptap/react"; - -export const IssueWidget = Node.create({ - name: "issue-embed-component", - group: "block", - atom: true, - - addAttributes() { - return { - id: { - default: null, - }, - class: { - default: "w-[600px]", - }, - title: { - default: null, - }, - entity_name: { - default: null, - }, - entity_identifier: { - default: null, - }, - project_identifier: { - default: null, - }, - sequence_id: { - default: null, - }, - }; - }, - - addNodeView() { - return ReactNodeViewRenderer((props: Object) => ); - }, - - parseHTML() { - return [ - { - tag: "issue-embed-component", - getAttrs: (node: string | HTMLElement) => { - if (typeof node === "string") { - return null; - } - return { - id: node.getAttribute("id") || "", - title: node.getAttribute("title") || "", - entity_name: node.getAttribute("entity_name") || "", - entity_identifier: node.getAttribute("entity_identifier") || "", - project_identifier: node.getAttribute("project_identifier") || "", - sequence_id: node.getAttribute("sequence_id") || "", - }; - }, - }, - ]; - }, - renderHTML({ HTMLAttributes }) { - return ["issue-embed-component", mergeAttributes(HTMLAttributes)]; - }, -}); diff --git a/packages/editor/document-editor/src/ui/menu/icon.tsx b/packages/editor/document-editor/src/ui/menu/icon.tsx deleted file mode 100644 index 7ddc76843..000000000 --- a/packages/editor/document-editor/src/ui/menu/icon.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; - -type Props = { - iconName: string; - className?: string; -}; - -export const Icon: React.FC = ({ iconName, className = "" }) => ( - {iconName} -); diff --git a/packages/editor/document-editor/src/ui/tooltip.tsx b/packages/editor/document-editor/src/ui/tooltip.tsx deleted file mode 100644 index 127efc7cb..000000000 --- a/packages/editor/document-editor/src/ui/tooltip.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as React from "react"; - -// next-themes -import { useTheme } from "next-themes"; -// tooltip2 -import { Tooltip2 } from "@blueprintjs/popover2"; - -type Props = { - tooltipHeading?: string; - tooltipContent: string | React.ReactNode; - position?: - | "top" - | "right" - | "bottom" - | "left" - | "auto" - | "auto-end" - | "auto-start" - | "bottom-left" - | "bottom-right" - | "left-bottom" - | "left-top" - | "right-bottom" - | "right-top" - | "top-left" - | "top-right"; - children: JSX.Element; - disabled?: boolean; - className?: string; - openDelay?: number; - closeDelay?: number; -}; - -export const Tooltip: React.FC = ({ - tooltipHeading, - tooltipContent, - position = "top", - children, - disabled = false, - className = "", - openDelay = 200, - closeDelay, -}) => { - const { theme } = useTheme(); - - return ( - - {tooltipHeading && ( -
- {tooltipHeading} -
- )} - {tooltipContent} - - } - position={position} - renderTarget={({ isOpen: isTooltipOpen, ref: eleReference, ...tooltipProps }) => - React.cloneElement(children, { - ref: eleReference, - ...tooltipProps, - ...children.props, - }) - } - /> - ); -}; diff --git a/packages/editor/document-editor/src/utils/date-utils.ts b/packages/editor/document-editor/src/utils/date-utils.ts deleted file mode 100644 index 63c20a974..000000000 --- a/packages/editor/document-editor/src/utils/date-utils.ts +++ /dev/null @@ -1,26 +0,0 @@ -function isNumber(value: any) { - return typeof value === "number"; -} - -/** - * This method returns a date from string of type yyyy-mm-dd - * This method is recommended to use instead of new Date() as this does not introduce any timezone offsets - * @param date - * @returns date or undefined - */ -export const getDate = (date: string | Date | undefined | null): Date | undefined => { - try { - if (!date || date === "") return; - - if (typeof date !== "string" && !(date instanceof String)) return date; - const [yearString, monthString, dayString] = date.substring(0, 10).split("-"); - const year = parseInt(yearString); - const month = parseInt(monthString); - const day = parseInt(dayString); - if (!isNumber(year) || !isNumber(month) || !isNumber(day)) return; - - return new Date(year, month - 1, day); - } catch (e) { - return undefined; - } -}; diff --git a/packages/editor/document-editor/src/utils/editor-summary-utils.ts b/packages/editor/document-editor/src/utils/editor-summary-utils.ts deleted file mode 100644 index b5160fddd..000000000 --- a/packages/editor/document-editor/src/utils/editor-summary-utils.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Editor } from "@tiptap/react"; -import { IMarking } from "src/types/editor-types"; - -function findNthH1(editor: Editor, n: number, level: number): number { - let count = 0; - let pos = 0; - editor.state.doc.descendants((node, position) => { - if (node.type.name === "heading" && node.attrs.level === level) { - count++; - if (count === n) { - pos = position; - return false; - } - } - }); - return pos; -} - -function scrollToNode(editor: Editor, pos: number): void { - const headingNode = editor.state.doc.nodeAt(pos); - if (headingNode) { - const headingDOM = editor.view.nodeDOM(pos); - if (headingDOM instanceof HTMLElement) { - headingDOM.scrollIntoView({ behavior: "smooth" }); - } - } -} - -export function scrollSummary(editor: Editor, marking: IMarking) { - if (editor) { - const pos = findNthH1(editor, marking.sequence, marking.level); - scrollToNode(editor, pos); - } -} diff --git a/packages/editor/document-editor/tailwind.config.js b/packages/editor/document-editor/tailwind.config.js deleted file mode 100644 index f32063158..000000000 --- a/packages/editor/document-editor/tailwind.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const sharedConfig = require("tailwind-config-custom/tailwind.config.js"); - -module.exports = { - // prefix ui lib classes to avoid conflicting with the app - ...sharedConfig, -}; diff --git a/packages/editor/document-editor/tsconfig.json b/packages/editor/document-editor/tsconfig.json deleted file mode 100644 index c15534037..000000000 --- a/packages/editor/document-editor/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "tsconfig/react-library.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ], - "compilerOptions": { - "baseUrl": "." - } -} diff --git a/packages/editor/document-editor/tsup.config.ts b/packages/editor/document-editor/tsup.config.ts deleted file mode 100644 index 5e89e04af..000000000 --- a/packages/editor/document-editor/tsup.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig, Options } from "tsup"; - -export default defineConfig((options: Options) => ({ - entry: ["src/index.ts"], - format: ["cjs", "esm"], - dts: true, - clean: false, - external: ["react"], - injectStyle: true, - ...options, -})); diff --git a/packages/editor/extensions/.eslintrc.js b/packages/editor/extensions/.eslintrc.js deleted file mode 100644 index c8df60750..000000000 --- a/packages/editor/extensions/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["custom"], -}; diff --git a/packages/editor/extensions/.prettierignore b/packages/editor/extensions/.prettierignore deleted file mode 100644 index 43e8a7b8f..000000000 --- a/packages/editor/extensions/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -.next -.vercel -.tubro -out/ -dis/ -build/ \ No newline at end of file diff --git a/packages/editor/extensions/.prettierrc b/packages/editor/extensions/.prettierrc deleted file mode 100644 index 87d988f1b..000000000 --- a/packages/editor/extensions/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "printWidth": 120, - "tabWidth": 2, - "trailingComma": "es5" -} diff --git a/packages/editor/extensions/Readme.md b/packages/editor/extensions/Readme.md deleted file mode 100644 index 39aca1226..000000000 --- a/packages/editor/extensions/Readme.md +++ /dev/null @@ -1,97 +0,0 @@ -# @plane/editor-extensions - -## Description - -The `@plane/lite-text-editor` package extends from the `editor-core` package, inheriting its base functionality while adding its own unique features of Custom control over Enter key, etc. - -## Key Features - -- **Exported Components**: There are two components exported from the Lite text editor (with and without Ref), you can choose to use the `withRef` instance whenever you want to control the Editor’s state via a side effect of some external action from within the application code. - - `LiteTextEditor` & `LiteTextEditorWithRef` - -- **Read Only Editor Instances**: We have added a really light weight _Read Only_ Editor instance for the Lite editor types (with and without Ref) - `LiteReadOnlyEditor` &`LiteReadOnlyEditorWithRef` - -## LiteTextEditor - -| Prop | Type | Description | -| ------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `uploadFile` | `(file: File) => Promise` | A function that handles file upload. It takes a file as input and handles the process of uploading that file. | -| `deleteFile` | `(assetUrlWithWorkspaceId: string) => Promise` | A function that handles deleting an image. It takes the asset url from your bucket and handles the process of deleting that image. | -| `value` | `html string` | The initial content of the editor. | -| `onEnterKeyPress` | `(e) => void` | The event that happens on Enter key press | -| `debouncedUpdatesEnabled` | `boolean` | If set to true, the `onChange` event handler is debounced, meaning it will only be invoked after the specified delay (default 1500ms) once the user has stopped typing. | -| `onChange` | `(json: any, html: string) => void` | This function is invoked whenever the content of the editor changes. It is passed the new content in both JSON and HTML formats. | -| `setIsSubmitting` | `(isSubmitting: "submitting" \| "submitted" \| "saved") => void` | This function is called to update the submission status. | -| `setShouldShowAlert` | `(showAlert: boolean) => void` | This function is used to show or hide an alert incase of content not being "saved". | -| `noBorder` | `boolean` | If set to true, the editor will not have a border. | -| `borderOnFocus` | `boolean` | If set to true, the editor will show a border when it is focused. | -| `customClassName` | `string` | This is a custom CSS class that can be applied to the editor. | -| `editorContentCustomClassNames` | `string` | This is a custom CSS class that can be applied to the editor content. | - -### Usage - -1. Here is an example of how to use the `RichTextEditor` component - -```tsx - { - onChange(comment_html); - }} -/> -``` - -2. Example of how to use the `LiteTextEditorWithRef` component - -```tsx -const editorRef = useRef(null); - -// can use it to set the editor's value -editorRef.current?.setEditorValue(`${watch("description_html")}`); - -// can use it to clear the editor -editorRef?.current?.clearEditor(); - -return ( - { - onChange(comment_html); - }} - /> -); -``` - -## LiteReadOnlyEditor - -| Prop | Type | Description | -| ------------------------------- | ------------- | --------------------------------------------------------------------- | -| `value` | `html string` | The initial content of the editor. | -| `noBorder` | `boolean` | If set to true, the editor will not have a border. | -| `borderOnFocus` | `boolean` | If set to true, the editor will show a border when it is focused. | -| `customClassName` | `string` | This is a custom CSS class that can be applied to the editor. | -| `editorContentCustomClassNames` | `string` | This is a custom CSS class that can be applied to the editor content. | - -### Usage - -Here is an example of how to use the `RichReadOnlyEditor` component - -```tsx - -``` diff --git a/packages/editor/extensions/package.json b/packages/editor/extensions/package.json deleted file mode 100644 index 7a5d20933..000000000 --- a/packages/editor/extensions/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@plane/editor-extensions", - "version": "0.21.0", - "description": "Package that powers Plane's Editor with extensions", - "private": true, - "main": "./dist/index.mjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.mts", - "files": [ - "dist/**/*" - ], - "exports": { - ".": { - "types": "./dist/index.d.mts", - "import": "./dist/index.mjs", - "module": "./dist/index.mjs" - } - }, - "scripts": { - "build": "tsup --minify", - "dev": "tsup --watch", - "check-types": "tsc --noEmit" - }, - "peerDependencies": { - "next": "12.3.2", - "next-themes": "^0.2.1", - "react": "^18.2.0", - "react-dom": "18.2.0" - }, - "dependencies": { - "@plane/editor-core": "*", - "@plane/ui": "*", - "@tiptap/core": "^2.1.13", - "@tiptap/pm": "^2.1.13", - "@tiptap/react": "^2.1.13", - "@tiptap/suggestion": "^2.1.13", - "lucide-react": "^0.378.0", - "tippy.js": "^6.3.7" - }, - "devDependencies": { - "@types/node": "18.15.3", - "@types/react": "^18.2.42", - "@types/react-dom": "^18.2.17", - "eslint-config-custom": "*", - "postcss": "^8.4.38", - "tailwind-config-custom": "*", - "tsconfig": "*", - "tsup": "^7.2.0", - "typescript": "4.9.5" - }, - "keywords": [ - "editor", - "rich-text", - "markdown", - "nextjs", - "react" - ] -} diff --git a/packages/editor/extensions/postcss.config.js b/packages/editor/extensions/postcss.config.js deleted file mode 100644 index 07aa434b2..000000000 --- a/packages/editor/extensions/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -// If you want to use other PostCSS plugins, see the following: -// https://tailwindcss.com/docs/using-with-preprocessors - -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/packages/editor/extensions/src/extensions/index.ts b/packages/editor/extensions/src/extensions/index.ts deleted file mode 100644 index 9ceeb6493..000000000 --- a/packages/editor/extensions/src/extensions/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./drag-drop"; -export * from "./slash-commands"; diff --git a/packages/editor/extensions/src/index.ts b/packages/editor/extensions/src/index.ts deleted file mode 100644 index 440de1351..000000000 --- a/packages/editor/extensions/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import "src/styles/drag-drop.css"; - -export { DragAndDrop, SlashCommand } from "src/extensions"; diff --git a/packages/editor/extensions/tailwind.config.js b/packages/editor/extensions/tailwind.config.js deleted file mode 100644 index f32063158..000000000 --- a/packages/editor/extensions/tailwind.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const sharedConfig = require("tailwind-config-custom/tailwind.config.js"); - -module.exports = { - // prefix ui lib classes to avoid conflicting with the app - ...sharedConfig, -}; diff --git a/packages/editor/extensions/tsconfig.json b/packages/editor/extensions/tsconfig.json deleted file mode 100644 index c15534037..000000000 --- a/packages/editor/extensions/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "tsconfig/react-library.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ], - "compilerOptions": { - "baseUrl": "." - } -} diff --git a/packages/editor/extensions/tsup.config.ts b/packages/editor/extensions/tsup.config.ts deleted file mode 100644 index 5e89e04af..000000000 --- a/packages/editor/extensions/tsup.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig, Options } from "tsup"; - -export default defineConfig((options: Options) => ({ - entry: ["src/index.ts"], - format: ["cjs", "esm"], - dts: true, - clean: false, - external: ["react"], - injectStyle: true, - ...options, -})); diff --git a/packages/editor/lite-text-editor/.eslintrc.js b/packages/editor/lite-text-editor/.eslintrc.js deleted file mode 100644 index c8df60750..000000000 --- a/packages/editor/lite-text-editor/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["custom"], -}; diff --git a/packages/editor/lite-text-editor/.prettierignore b/packages/editor/lite-text-editor/.prettierignore deleted file mode 100644 index 43e8a7b8f..000000000 --- a/packages/editor/lite-text-editor/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -.next -.vercel -.tubro -out/ -dis/ -build/ \ No newline at end of file diff --git a/packages/editor/lite-text-editor/.prettierrc b/packages/editor/lite-text-editor/.prettierrc deleted file mode 100644 index 87d988f1b..000000000 --- a/packages/editor/lite-text-editor/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "printWidth": 120, - "tabWidth": 2, - "trailingComma": "es5" -} diff --git a/packages/editor/lite-text-editor/Readme.md b/packages/editor/lite-text-editor/Readme.md deleted file mode 100644 index 1f10f5ff4..000000000 --- a/packages/editor/lite-text-editor/Readme.md +++ /dev/null @@ -1,97 +0,0 @@ -# @plane/lite-text-editor - -## Description - -The `@plane/lite-text-editor` package extends from the `editor-core` package, inheriting its base functionality while adding its own unique features of Custom control over Enter key, etc. - -## Key Features - -- **Exported Components**: There are two components exported from the Lite text editor (with and without Ref), you can choose to use the `withRef` instance whenever you want to control the Editor’s state via a side effect of some external action from within the application code. - - `LiteTextEditor` & `LiteTextEditorWithRef` - -- **Read Only Editor Instances**: We have added a really light weight _Read Only_ Editor instance for the Lite editor types (with and without Ref) - `LiteReadOnlyEditor` &`LiteReadOnlyEditorWithRef` - -## LiteTextEditor - -| Prop | Type | Description | -| ------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `uploadFile` | `(file: File) => Promise` | A function that handles file upload. It takes a file as input and handles the process of uploading that file. | -| `deleteFile` | `(assetUrlWithWorkspaceId: string) => Promise` | A function that handles deleting an image. It takes the asset url from your bucket and handles the process of deleting that image. | -| `value` | `html string` | The initial content of the editor. | -| `onEnterKeyPress` | `(e) => void` | The event that happens on Enter key press | -| `debouncedUpdatesEnabled` | `boolean` | If set to true, the `onChange` event handler is debounced, meaning it will only be invoked after the specified delay (default 1500ms) once the user has stopped typing. | -| `onChange` | `(json: any, html: string) => void` | This function is invoked whenever the content of the editor changes. It is passed the new content in both JSON and HTML formats. | -| `setIsSubmitting` | `(isSubmitting: "submitting" \| "submitted" \| "saved") => void` | This function is called to update the submission status. | -| `setShouldShowAlert` | `(showAlert: boolean) => void` | This function is used to show or hide an alert incase of content not being "saved". | -| `noBorder` | `boolean` | If set to true, the editor will not have a border. | -| `borderOnFocus` | `boolean` | If set to true, the editor will show a border when it is focused. | -| `customClassName` | `string` | This is a custom CSS class that can be applied to the editor. | -| `editorContentCustomClassNames` | `string` | This is a custom CSS class that can be applied to the editor content. | - -### Usage - -1. Here is an example of how to use the `RichTextEditor` component - -```tsx - { - onChange(comment_html); - }} -/> -``` - -2. Example of how to use the `LiteTextEditorWithRef` component - -```tsx -const editorRef = useRef(null); - -// can use it to set the editor's value -editorRef.current?.setEditorValue(`${watch("description_html")}`); - -// can use it to clear the editor -editorRef?.current?.clearEditor(); - -return ( - { - onChange(comment_html); - }} - /> -); -``` - -## LiteReadOnlyEditor - -| Prop | Type | Description | -| ------------------------------- | ------------- | --------------------------------------------------------------------- | -| `value` | `html string` | The initial content of the editor. | -| `noBorder` | `boolean` | If set to true, the editor will not have a border. | -| `borderOnFocus` | `boolean` | If set to true, the editor will show a border when it is focused. | -| `customClassName` | `string` | This is a custom CSS class that can be applied to the editor. | -| `editorContentCustomClassNames` | `string` | This is a custom CSS class that can be applied to the editor content. | - -### Usage - -Here is an example of how to use the `RichReadOnlyEditor` component - -```tsx - -``` diff --git a/packages/editor/lite-text-editor/package.json b/packages/editor/lite-text-editor/package.json deleted file mode 100644 index 8e03e82ac..000000000 --- a/packages/editor/lite-text-editor/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@plane/lite-text-editor", - "version": "0.21.0", - "description": "Package that powers Plane's Comment Editor", - "private": true, - "main": "./dist/index.mjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.mts", - "files": [ - "dist/**/*" - ], - "exports": { - ".": { - "types": "./dist/index.d.mts", - "import": "./dist/index.mjs", - "module": "./dist/index.mjs" - } - }, - "scripts": { - "build": "tsup --minify", - "dev": "tsup --watch", - "check-types": "tsc --noEmit", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "peerDependencies": { - "next": "12.3.2", - "next-themes": "^0.2.1", - "react": "^18.2.0", - "react-dom": "18.2.0" - }, - "dependencies": { - "@plane/editor-core": "*", - "@plane/ui": "*" - }, - "devDependencies": { - "@types/node": "18.15.3", - "@types/react": "^18.2.42", - "@types/react-dom": "^18.2.17", - "eslint-config-custom": "*", - "postcss": "^8.4.38", - "tailwind-config-custom": "*", - "tsconfig": "*", - "tsup": "^7.2.0", - "typescript": "4.9.5" - }, - "keywords": [ - "editor", - "rich-text", - "markdown", - "nextjs", - "react" - ] -} diff --git a/packages/editor/lite-text-editor/postcss.config.js b/packages/editor/lite-text-editor/postcss.config.js deleted file mode 100644 index 07aa434b2..000000000 --- a/packages/editor/lite-text-editor/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -// If you want to use other PostCSS plugins, see the following: -// https://tailwindcss.com/docs/using-with-preprocessors - -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/packages/editor/lite-text-editor/src/index.ts b/packages/editor/lite-text-editor/src/index.ts deleted file mode 100644 index 3ca8c71db..000000000 --- a/packages/editor/lite-text-editor/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { LiteTextEditor, LiteTextEditorWithRef } from "src/ui"; -export { LiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "src/ui/read-only"; -export type { IMentionSuggestion, IMentionHighlight } from "@plane/editor-core"; - -export type { ILiteTextEditor } from "src/ui"; -export type { ILiteTextReadOnlyEditor } from "src/ui/read-only"; -export type { EditorRefApi, EditorReadOnlyRefApi, EditorMenuItem, EditorMenuItemNames } from "@plane/editor-core"; diff --git a/packages/editor/lite-text-editor/src/ui/extensions/index.tsx b/packages/editor/lite-text-editor/src/ui/extensions/index.tsx deleted file mode 100644 index c4b24d166..000000000 --- a/packages/editor/lite-text-editor/src/ui/extensions/index.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { EnterKeyExtension } from "src/ui/extensions/enter-key-extension"; - -export const LiteTextEditorExtensions = (onEnterKeyPress?: () => void) => [EnterKeyExtension(onEnterKeyPress)]; diff --git a/packages/editor/lite-text-editor/src/ui/index.tsx b/packages/editor/lite-text-editor/src/ui/index.tsx deleted file mode 100644 index 77d3ca0ec..000000000 --- a/packages/editor/lite-text-editor/src/ui/index.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import * as React from "react"; -// editor-core -import { - IMentionSuggestion, - EditorContainer, - EditorContentWrapper, - getEditorClassNames, - useEditor, - IMentionHighlight, - EditorRefApi, - TFileHandler, -} from "@plane/editor-core"; -// extensions -import { LiteTextEditorExtensions } from "src/ui/extensions"; - -export interface ILiteTextEditor { - initialValue: string; - value?: string | null; - fileHandler: TFileHandler; - containerClassName?: string; - editorClassName?: string; - onChange?: (json: object, html: string) => void; - forwardedRef?: React.MutableRefObject; - onEnterKeyPress?: (e?: any) => void; - mentionHandler: { - highlights: () => Promise; - suggestions?: () => Promise; - }; - tabIndex?: number; - placeholder?: string | ((isFocused: boolean, value: string) => string); - id?: string; -} - -const LiteTextEditor = (props: ILiteTextEditor) => { - const { - onChange, - initialValue, - fileHandler, - value, - containerClassName, - editorClassName = "", - forwardedRef, - onEnterKeyPress, - tabIndex, - mentionHandler, - placeholder = "Add comment...", - id = "", - } = props; - - const editor = useEditor({ - onChange, - initialValue, - value, - id, - editorClassName, - fileHandler, - forwardedRef, - extensions: LiteTextEditorExtensions(onEnterKeyPress), - mentionHandler, - placeholder, - tabIndex, - }); - - const editorContainerClassName = getEditorClassNames({ - noBorder: true, - borderOnFocus: false, - containerClassName, - }); - - if (!editor) return null; - - return ( - -
- -
-
- ); -}; - -const LiteTextEditorWithRef = React.forwardRef((props, ref) => ( - } /> -)); - -LiteTextEditorWithRef.displayName = "LiteTextEditorWithRef"; - -export { LiteTextEditor, LiteTextEditorWithRef }; diff --git a/packages/editor/lite-text-editor/src/ui/read-only/index.tsx b/packages/editor/lite-text-editor/src/ui/read-only/index.tsx deleted file mode 100644 index 5ceb6956e..000000000 --- a/packages/editor/lite-text-editor/src/ui/read-only/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from "react"; -import { - EditorContainer, - EditorContentWrapper, - EditorReadOnlyRefApi, - getEditorClassNames, - IMentionHighlight, - useReadOnlyEditor, -} from "@plane/editor-core"; - -export interface ILiteTextReadOnlyEditor { - initialValue: string; - borderOnFocus?: boolean; - containerClassName?: string; - editorClassName?: string; - forwardedRef?: React.MutableRefObject; - mentionHandler: { - highlights: () => Promise; - }; - tabIndex?: number; -} - -const LiteTextReadOnlyEditor = ({ - containerClassName, - editorClassName = "", - initialValue, - forwardedRef, - mentionHandler, - tabIndex, -}: ILiteTextReadOnlyEditor) => { - const editor = useReadOnlyEditor({ - initialValue, - editorClassName, - forwardedRef, - mentionHandler, - }); - - const editorContainerClassName = getEditorClassNames({ - containerClassName, - }); - - if (!editor) return null; - - return ( - -
- -
-
- ); -}; - -const LiteTextReadOnlyEditorWithRef = React.forwardRef((props, ref) => ( - } /> -)); - -LiteTextReadOnlyEditorWithRef.displayName = "LiteReadOnlyEditorWithRef"; - -export { LiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef }; diff --git a/packages/editor/lite-text-editor/tailwind.config.js b/packages/editor/lite-text-editor/tailwind.config.js deleted file mode 100644 index f32063158..000000000 --- a/packages/editor/lite-text-editor/tailwind.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const sharedConfig = require("tailwind-config-custom/tailwind.config.js"); - -module.exports = { - // prefix ui lib classes to avoid conflicting with the app - ...sharedConfig, -}; diff --git a/packages/editor/lite-text-editor/tsconfig.json b/packages/editor/lite-text-editor/tsconfig.json deleted file mode 100644 index c15534037..000000000 --- a/packages/editor/lite-text-editor/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "tsconfig/react-library.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ], - "compilerOptions": { - "baseUrl": "." - } -} diff --git a/packages/editor/lite-text-editor/tsup.config.ts b/packages/editor/lite-text-editor/tsup.config.ts deleted file mode 100644 index 5e89e04af..000000000 --- a/packages/editor/lite-text-editor/tsup.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig, Options } from "tsup"; - -export default defineConfig((options: Options) => ({ - entry: ["src/index.ts"], - format: ["cjs", "esm"], - dts: true, - clean: false, - external: ["react"], - injectStyle: true, - ...options, -})); diff --git a/packages/editor/core/package.json b/packages/editor/package.json similarity index 88% rename from packages/editor/core/package.json rename to packages/editor/package.json index d91758019..ab3610131 100644 --- a/packages/editor/core/package.json +++ b/packages/editor/package.json @@ -1,5 +1,5 @@ { - "name": "@plane/editor-core", + "name": "@plane/editor", "version": "0.21.0", "description": "Core Editor that powers Plane", "private": true, @@ -28,9 +28,11 @@ "react-dom": "18.2.0" }, "dependencies": { + "@floating-ui/react": "^0.26.4", "@plane/ui": "*", "@tiptap/core": "^2.1.13", "@tiptap/extension-blockquote": "^2.1.13", + "@tiptap/extension-collaboration": "^2.3.2", "@tiptap/extension-image": "^2.1.13", "@tiptap/extension-list-item": "^2.1.13", "@tiptap/extension-mention": "^2.1.13", @@ -54,7 +56,11 @@ "react-moveable": "^0.54.2", "tailwind-merge": "^1.14.0", "tippy.js": "^6.3.7", - "tiptap-markdown": "^0.8.9" + "tiptap-markdown": "^0.8.9", + "y-indexeddb": "^9.0.12", + "y-prosemirror": "^1.2.5", + "y-protocols": "^1.0.6", + "yjs": "^13.6.15" }, "devDependencies": { "@types/node": "18.15.3", diff --git a/packages/editor/core/postcss.config.js b/packages/editor/postcss.config.js similarity index 100% rename from packages/editor/core/postcss.config.js rename to packages/editor/postcss.config.js diff --git a/packages/editor/rich-text-editor/.eslintrc.js b/packages/editor/rich-text-editor/.eslintrc.js deleted file mode 100644 index c8df60750..000000000 --- a/packages/editor/rich-text-editor/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: ["custom"], -}; diff --git a/packages/editor/rich-text-editor/.prettierignore b/packages/editor/rich-text-editor/.prettierignore deleted file mode 100644 index 43e8a7b8f..000000000 --- a/packages/editor/rich-text-editor/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -.next -.vercel -.tubro -out/ -dis/ -build/ \ No newline at end of file diff --git a/packages/editor/rich-text-editor/.prettierrc b/packages/editor/rich-text-editor/.prettierrc deleted file mode 100644 index 87d988f1b..000000000 --- a/packages/editor/rich-text-editor/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "printWidth": 120, - "tabWidth": 2, - "trailingComma": "es5" -} diff --git a/packages/editor/rich-text-editor/Readme.md b/packages/editor/rich-text-editor/Readme.md deleted file mode 100644 index 2e5662e30..000000000 --- a/packages/editor/rich-text-editor/Readme.md +++ /dev/null @@ -1,98 +0,0 @@ -# @plane/rich-text-editor - -## Description - -The `@plane/rich-text-editor` package extends from the `editor-core` package, inheriting its base functionality while adding its own unique features of Slash Commands and many more. - -## Key Features - -- **Exported Components**: There are two components exported from the Rich text editor (with and without Ref), you can choose to use the `withRef` instance whenever you want to control the Editor’s state via a side effect of some external action from within the application code. - - `RichTextEditor` & `RichTextEditorWithRef` - -- **Read Only Editor Instances**: We have added a really light weight _Read Only_ Editor instance for the Rich editor types (with and without Ref) - `RichReadOnlyEditor` &`RichReadOnlyEditorWithRef` - -## RichTextEditor - -| Prop | Type | Description | -| ------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `uploadFile` | `(file: File) => Promise` | A function that handles file upload. It takes a file as input and handles the process of uploading that file. | -| `deleteFile` | `(assetUrlWithWorkspaceId: string) => Promise` | A function that handles deleting an image. It takes the asset url from your bucket and handles the process of deleting that image. | -| `value` | `html string` | The initial content of the editor. | -| `debouncedUpdatesEnabled` | `boolean` | If set to true, the `onChange` event handler is debounced, meaning it will only be invoked after the specified delay (default 1500ms) once the user has stopped typing. | -| `onChange` | `(json: any, html: string) => void` | This function is invoked whenever the content of the editor changes. It is passed the new content in both JSON and HTML formats. | -| `setIsSubmitting` | `(isSubmitting: "submitting" \| "submitted" \| "saved") => void` | This function is called to update the submission status. | -| `setShouldShowAlert` | `(showAlert: boolean) => void` | This function is used to show or hide an alert incase of content not being "saved". | -| `noBorder` | `boolean` | If set to true, the editor will not have a border. | -| `borderOnFocus` | `boolean` | If set to true, the editor will show a border when it is focused. | -| `customClassName` | `string` | This is a custom CSS class that can be applied to the editor. | -| `editorContentCustomClassNames` | `string` | This is a custom CSS class that can be applied to the editor content. | - -### Usage - -1. Here is an example of how to use the `RichTextEditor` component - -```tsx - { - setShowAlert(true); - setIsSubmitting("submitting"); - onChange(description_html); - // custom stuff you want to do - }} -/> -``` - -2. Example of how to use the `RichTextEditorWithRef` component - -```tsx -const editorRef = useRef(null); - -// can use it to set the editor's value -editorRef.current?.setEditorValue(`${watch("description_html")}`); - -// can use it to clear the editor -editorRef?.current?.clearEditor(); - -return ( - { - onChange(description_html); - // custom stuff you want to do - }} - /> -); -``` - -## RichReadOnlyEditor - -| Prop | Type | Description | -| ------------------------------- | ------------- | --------------------------------------------------------------------- | -| `value` | `html string` | The initial content of the editor. | -| `noBorder` | `boolean` | If set to true, the editor will not have a border. | -| `borderOnFocus` | `boolean` | If set to true, the editor will show a border when it is focused. | -| `customClassName` | `string` | This is a custom CSS class that can be applied to the editor. | -| `editorContentCustomClassNames` | `string` | This is a custom CSS class that can be applied to the editor content. | - -### Usage - -Here is an example of how to use the `RichReadOnlyEditor` component - -```tsx - -``` diff --git a/packages/editor/rich-text-editor/package.json b/packages/editor/rich-text-editor/package.json deleted file mode 100644 index c0b3d28cc..000000000 --- a/packages/editor/rich-text-editor/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "@plane/rich-text-editor", - "version": "0.21.0", - "description": "Rich Text Editor that powers Plane", - "private": true, - "main": "./dist/index.mjs", - "module": "./dist/index.mjs", - "types": "./dist/index.d.mts", - "files": [ - "dist/**/*" - ], - "exports": { - ".": { - "types": "./dist/index.d.mts", - "import": "./dist/index.mjs", - "module": "./dist/index.mjs" - } - }, - "scripts": { - "build": "tsup --minify", - "dev": "tsup --watch", - "check-types": "tsc --noEmit", - "format": "prettier --write \"**/*.{ts,tsx,md}\"" - }, - "peerDependencies": { - "next": "12.3.2", - "next-themes": "^0.2.1", - "react": "^18.2.0", - "react-dom": "18.2.0" - }, - "dependencies": { - "@plane/editor-core": "*", - "@plane/editor-extensions": "*", - "@tiptap/core": "^2.1.13", - "lucide-react": "^0.378.0" - }, - "devDependencies": { - "@types/node": "18.15.3", - "@types/react": "^18.2.42", - "@types/react-dom": "^18.2.17", - "eslint-config-custom": "*", - "postcss": "^8.4.38", - "react": "^18.2.0", - "tailwind-config-custom": "*", - "tsconfig": "*", - "tsup": "^7.2.0", - "typescript": "4.9.5" - }, - "keywords": [ - "editor", - "rich-text", - "markdown", - "nextjs", - "react" - ] -} diff --git a/packages/editor/rich-text-editor/postcss.config.js b/packages/editor/rich-text-editor/postcss.config.js deleted file mode 100644 index 07aa434b2..000000000 --- a/packages/editor/rich-text-editor/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -// If you want to use other PostCSS plugins, see the following: -// https://tailwindcss.com/docs/using-with-preprocessors - -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/packages/editor/rich-text-editor/src/index.ts b/packages/editor/rich-text-editor/src/index.ts deleted file mode 100644 index ad6f043a1..000000000 --- a/packages/editor/rich-text-editor/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { RichTextEditor, RichTextEditorWithRef } from "src/ui"; -export { RichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "src/ui/read-only"; - -export type { IRichTextEditor } from "src/ui"; - -export type { IRichTextReadOnlyEditor } from "src/ui/read-only"; -export type { IMentionSuggestion, IMentionHighlight } from "@plane/editor-core"; -export type { EditorRefApi, EditorReadOnlyRefApi } from "@plane/editor-core"; diff --git a/packages/editor/rich-text-editor/src/ui/extensions/enter-key-extension.tsx b/packages/editor/rich-text-editor/src/ui/extensions/enter-key-extension.tsx deleted file mode 100644 index 70037f046..000000000 --- a/packages/editor/rich-text-editor/src/ui/extensions/enter-key-extension.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Extension } from "@tiptap/core"; - -export const EnterKeyExtension = (onEnterKeyPress?: () => void) => - Extension.create({ - name: "enterKey", - - addKeyboardShortcuts(this) { - return { - Enter: () => { - if (onEnterKeyPress) { - onEnterKeyPress(); - } - return true; - }, - "Shift-Enter": ({ editor }) => - editor.commands.first(({ commands }) => [ - () => commands.newlineInCode(), - () => commands.splitListItem("listItem"), - () => commands.createParagraphNear(), - () => commands.liftEmptyBlock(), - () => commands.splitBlock(), - ]), - }; - }, - }); diff --git a/packages/editor/rich-text-editor/src/ui/extensions/index.tsx b/packages/editor/rich-text-editor/src/ui/extensions/index.tsx deleted file mode 100644 index 4face2cb7..000000000 --- a/packages/editor/rich-text-editor/src/ui/extensions/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { UploadImage } from "@plane/editor-core"; -import { DragAndDrop, SlashCommand } from "@plane/editor-extensions"; -import { EnterKeyExtension } from "./enter-key-extension"; - -type TArguments = { - uploadFile: UploadImage; - dragDropEnabled?: boolean; - setHideDragHandle?: (hideDragHandlerFromDragDrop: () => void) => void; - onEnterKeyPress?: () => void; -}; - -export const RichTextEditorExtensions = ({ - uploadFile, - dragDropEnabled, - setHideDragHandle, - onEnterKeyPress, -}: TArguments) => [ - SlashCommand(uploadFile), - dragDropEnabled === true && DragAndDrop(setHideDragHandle), - // TODO; add the extension conditionally for forms that don't require it - // EnterKeyExtension(onEnterKeyPress), -]; diff --git a/packages/editor/rich-text-editor/src/ui/index.tsx b/packages/editor/rich-text-editor/src/ui/index.tsx deleted file mode 100644 index 2b8348a62..000000000 --- a/packages/editor/rich-text-editor/src/ui/index.tsx +++ /dev/null @@ -1,113 +0,0 @@ -"use client"; -import * as React from "react"; -// editor-core -import { - EditorContainer, - EditorContentWrapper, - getEditorClassNames, - IMentionHighlight, - IMentionSuggestion, - useEditor, - EditorRefApi, - TFileHandler, -} from "@plane/editor-core"; -// extensions -import { RichTextEditorExtensions } from "src/ui/extensions"; -// components -import { EditorBubbleMenu } from "src/ui/menus/bubble-menu"; - -export type IRichTextEditor = { - initialValue: string; - value?: string | null; - dragDropEnabled?: boolean; - fileHandler: TFileHandler; - id?: string; - containerClassName?: string; - editorClassName?: string; - onChange?: (json: object, html: string) => void; - forwardedRef?: React.MutableRefObject; - debouncedUpdatesEnabled?: boolean; - mentionHandler: { - highlights: () => Promise; - suggestions: () => Promise; - }; - placeholder?: string | ((isFocused: boolean, value: string) => string); - tabIndex?: number; - onEnterKeyPress?: (e?: any) => void; -}; - -const RichTextEditor = (props: IRichTextEditor) => { - const { - onChange, - dragDropEnabled, - initialValue, - value, - fileHandler, - containerClassName, - editorClassName = "", - forwardedRef, - // rerenderOnPropsChange, - id = "", - placeholder, - tabIndex, - mentionHandler, - onEnterKeyPress, - } = props; - - const [hideDragHandleOnMouseLeave, setHideDragHandleOnMouseLeave] = React.useState<() => void>(() => {}); - - // this essentially sets the hideDragHandle function from the DragAndDrop extension as the Plugin - // loads such that we can invoke it from react when the cursor leaves the container - const setHideDragHandleFunction = (hideDragHandlerFromDragDrop: () => void) => { - setHideDragHandleOnMouseLeave(() => hideDragHandlerFromDragDrop); - }; - - const editor = useEditor({ - id, - editorClassName, - fileHandler, - onChange, - initialValue, - value, - forwardedRef, - // rerenderOnPropsChange, - extensions: RichTextEditorExtensions({ - uploadFile: fileHandler.upload, - dragDropEnabled, - setHideDragHandle: setHideDragHandleFunction, - onEnterKeyPress, - }), - tabIndex, - mentionHandler, - placeholder, - }); - - const editorContainerClassName = getEditorClassNames({ - noBorder: true, - borderOnFocus: false, - containerClassName, - }); - - if (!editor) return null; - - return ( - - {editor && } -
- -
-
- ); -}; - -const RichTextEditorWithRef = React.forwardRef((props, ref) => ( - } /> -)); - -RichTextEditorWithRef.displayName = "RichTextEditorWithRef"; - -export { RichTextEditor, RichTextEditorWithRef }; diff --git a/packages/editor/rich-text-editor/src/ui/read-only/index.tsx b/packages/editor/rich-text-editor/src/ui/read-only/index.tsx deleted file mode 100644 index 3220c477e..000000000 --- a/packages/editor/rich-text-editor/src/ui/read-only/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -"use client"; -import { - EditorReadOnlyRefApi, - EditorContainer, - EditorContentWrapper, - getEditorClassNames, - IMentionHighlight, - useReadOnlyEditor, -} from "@plane/editor-core"; -import * as React from "react"; - -export interface IRichTextReadOnlyEditor { - initialValue: string; - containerClassName?: string; - editorClassName?: string; - tabIndex?: number; - forwardedRef?: React.MutableRefObject; - mentionHandler: { - highlights: () => Promise; - }; -} - -const RichTextReadOnlyEditor = (props: IRichTextReadOnlyEditor) => { - const { containerClassName, editorClassName = "", initialValue, forwardedRef, mentionHandler } = props; - - const editor = useReadOnlyEditor({ - initialValue, - editorClassName, - forwardedRef, - mentionHandler, - }); - - const editorContainerClassName = getEditorClassNames({ - containerClassName, - }); - - if (!editor) return null; - - return ( - -
- -
-
- ); -}; - -const RichTextReadOnlyEditorWithRef = React.forwardRef((props, ref) => ( - } /> -)); - -RichTextReadOnlyEditorWithRef.displayName = "RichReadOnlyEditorWithRef"; - -export { RichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef }; diff --git a/packages/editor/rich-text-editor/tailwind.config.js b/packages/editor/rich-text-editor/tailwind.config.js deleted file mode 100644 index f32063158..000000000 --- a/packages/editor/rich-text-editor/tailwind.config.js +++ /dev/null @@ -1,6 +0,0 @@ -const sharedConfig = require("tailwind-config-custom/tailwind.config.js"); - -module.exports = { - // prefix ui lib classes to avoid conflicting with the app - ...sharedConfig, -}; diff --git a/packages/editor/rich-text-editor/tsconfig.json b/packages/editor/rich-text-editor/tsconfig.json deleted file mode 100644 index c15534037..000000000 --- a/packages/editor/rich-text-editor/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "tsconfig/react-library.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ], - "compilerOptions": { - "baseUrl": "." - } -} diff --git a/packages/editor/rich-text-editor/tsup.config.ts b/packages/editor/rich-text-editor/tsup.config.ts deleted file mode 100644 index 5e89e04af..000000000 --- a/packages/editor/rich-text-editor/tsup.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig, Options } from "tsup"; - -export default defineConfig((options: Options) => ({ - entry: ["src/index.ts"], - format: ["cjs", "esm"], - dts: true, - clean: false, - external: ["react"], - injectStyle: true, - ...options, -})); diff --git a/packages/editor/document-editor/src/providers/collaboration-provider.ts b/packages/editor/src/ce/providers/collaboration-provider.ts similarity index 100% rename from packages/editor/document-editor/src/providers/collaboration-provider.ts rename to packages/editor/src/ce/providers/collaboration-provider.ts diff --git a/packages/editor/src/ce/providers/index.ts b/packages/editor/src/ce/providers/index.ts new file mode 100644 index 000000000..9ff7a505f --- /dev/null +++ b/packages/editor/src/ce/providers/index.ts @@ -0,0 +1 @@ +export * from "./collaboration-provider"; diff --git a/packages/editor/src/ce/types/index.ts b/packages/editor/src/ce/types/index.ts new file mode 100644 index 000000000..f30596cb0 --- /dev/null +++ b/packages/editor/src/ce/types/index.ts @@ -0,0 +1 @@ +export * from "./issue-embed"; diff --git a/packages/editor/src/ce/types/issue-embed.ts b/packages/editor/src/ce/types/issue-embed.ts new file mode 100644 index 000000000..d68d182a0 --- /dev/null +++ b/packages/editor/src/ce/types/issue-embed.ts @@ -0,0 +1,17 @@ +export type TEmbedConfig = { + issue?: TIssueEmbedConfig; +}; + +export type TReadOnlyEmbedConfig = TEmbedConfig; + +export type TIssueEmbedConfig = { + widgetCallback: ({ + issueId, + projectId, + workspaceSlug, + }: { + issueId: string; + projectId: string | undefined; + workspaceSlug: string | undefined; + }) => React.ReactNode; +}; diff --git a/packages/editor/document-editor/src/ui/index.tsx b/packages/editor/src/core/components/editors/document/editor.tsx similarity index 81% rename from packages/editor/document-editor/src/ui/index.tsx rename to packages/editor/src/core/components/editors/document/editor.tsx index 1cafe6de7..0684fb88c 100644 --- a/packages/editor/document-editor/src/ui/index.tsx +++ b/packages/editor/src/core/components/editors/document/editor.tsx @@ -1,47 +1,48 @@ import React, { useState } from "react"; -// editor-core -import { - getEditorClassNames, - EditorRefApi, - IMentionHighlight, - IMentionSuggestion, - TFileHandler, -} from "@plane/editor-core"; // components -import { PageRenderer } from "src/ui/components/page-renderer"; +import { PageRenderer } from "@/components/editors"; +// helpers +import { getEditorClassNames } from "@/helpers/common"; // hooks -import { useDocumentEditor } from "src/hooks/use-document-editor"; +import { useDocumentEditor } from "@/hooks/use-document-editor"; +import { TFileHandler } from "@/hooks/use-editor"; +// plane editor types +import { TEmbedConfig } from "@/plane-editor/types"; +// types +import { EditorRefApi, IMentionHighlight, IMentionSuggestion } from "@/types"; interface IDocumentEditor { - id: string; - value: Uint8Array; - fileHandler: TFileHandler; - handleEditorReady?: (value: boolean) => void; containerClassName?: string; editorClassName?: string; - onChange: (updates: Uint8Array) => void; + embedHandler: TEmbedConfig; + fileHandler: TFileHandler; forwardedRef?: React.MutableRefObject; + handleEditorReady?: (value: boolean) => void; + id: string; mentionHandler: { highlights: () => Promise; suggestions: () => Promise; }; - tabIndex?: number; + onChange: (updates: Uint8Array) => void; placeholder?: string | ((isFocused: boolean, value: string) => string); + tabIndex?: number; + value: Uint8Array; } const DocumentEditor = (props: IDocumentEditor) => { const { - onChange, - id, - value, - fileHandler, containerClassName, editorClassName = "", - mentionHandler, - handleEditorReady, + embedHandler, + fileHandler, forwardedRef, - tabIndex, + handleEditorReady, + id, + mentionHandler, + onChange, placeholder, + tabIndex, + value, } = props; // states const [hideDragHandleOnMouseLeave, setHideDragHandleOnMouseLeave] = useState<() => void>(() => {}); @@ -55,6 +56,7 @@ const DocumentEditor = (props: IDocumentEditor) => { const editor = useDocumentEditor({ id, editorClassName, + embedHandler, fileHandler, value, onChange, @@ -90,4 +92,4 @@ const DocumentEditorWithRef = React.forwardRef((p DocumentEditorWithRef.displayName = "DocumentEditorWithRef"; -export { DocumentEditor, DocumentEditorWithRef }; +export { DocumentEditorWithRef }; diff --git a/packages/editor/src/core/components/editors/document/index.ts b/packages/editor/src/core/components/editors/document/index.ts new file mode 100644 index 000000000..6c48975bd --- /dev/null +++ b/packages/editor/src/core/components/editors/document/index.ts @@ -0,0 +1,3 @@ +export * from "./editor"; +export * from "./page-renderer"; +export * from "./read-only-editor"; diff --git a/packages/editor/document-editor/src/ui/components/page-renderer.tsx b/packages/editor/src/core/components/editors/document/page-renderer.tsx similarity index 95% rename from packages/editor/document-editor/src/ui/components/page-renderer.tsx rename to packages/editor/src/core/components/editors/document/page-renderer.tsx index a6b5eb5e8..5e1d1ef8a 100644 --- a/packages/editor/document-editor/src/ui/components/page-renderer.tsx +++ b/packages/editor/src/core/components/editors/document/page-renderer.tsx @@ -1,9 +1,4 @@ import { useCallback, useRef, useState } from "react"; -import { EditorContainer, EditorContentWrapper } from "@plane/editor-core"; -import { Node } from "@tiptap/pm/model"; -import { EditorView } from "@tiptap/pm/view"; -import { Editor, ReactRenderer } from "@tiptap/react"; -import { LinkView, LinkViewProps } from "./links/link-view"; import { autoUpdate, computePosition, @@ -14,7 +9,13 @@ import { useFloating, useInteractions, } from "@floating-ui/react"; -import BlockMenu from "../menu//block-menu"; +import { Node } from "@tiptap/pm/model"; +import { EditorView } from "@tiptap/pm/view"; +import { Editor, ReactRenderer } from "@tiptap/react"; +// components +import { EditorContainer, EditorContentWrapper } from "@/components/editors"; +import { LinkView, LinkViewProps } from "@/components/links"; +import { BlockMenu } from "@/components/menus"; type IPageRenderer = { editor: Editor; diff --git a/packages/editor/document-editor/src/ui/readonly/index.tsx b/packages/editor/src/core/components/editors/document/read-only-editor.tsx similarity index 67% rename from packages/editor/document-editor/src/ui/readonly/index.tsx rename to packages/editor/src/core/components/editors/document/read-only-editor.tsx index 0e75c2db4..9b91d9782 100644 --- a/packages/editor/document-editor/src/ui/readonly/index.tsx +++ b/packages/editor/src/core/components/editors/document/read-only-editor.tsx @@ -1,13 +1,22 @@ import { forwardRef, MutableRefObject } from "react"; -import { EditorReadOnlyRefApi, getEditorClassNames, IMentionHighlight, useReadOnlyEditor } from "@plane/editor-core"; // components -import { PageRenderer } from "src/ui/components/page-renderer"; -import { IssueWidgetPlaceholder } from "../extensions/widgets/issue-embed-widget"; +import { PageRenderer } from "@/components/editors"; +// extensions +import { IssueWidget } from "@/extensions"; +// helpers +import { getEditorClassNames } from "@/helpers/common"; +// hooks +import { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; +// plane web types +import { TEmbedConfig } from "@/plane-editor/types"; +// types +import { EditorReadOnlyRefApi, IMentionHighlight } from "@/types"; interface IDocumentReadOnlyEditor { initialValue: string; containerClassName: string; editorClassName?: string; + embedHandler: TEmbedConfig; tabIndex?: number; handleEditorReady?: (value: boolean) => void; mentionHandler: { @@ -20,6 +29,7 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { const { containerClassName, editorClassName = "", + embedHandler, initialValue, forwardedRef, tabIndex, @@ -32,7 +42,12 @@ const DocumentReadOnlyEditor = (props: IDocumentReadOnlyEditor) => { mentionHandler, forwardedRef, handleEditorReady, - extensions: [IssueWidgetPlaceholder()], + extensions: [ + embedHandler?.issue && + IssueWidget({ + widgetCallback: embedHandler?.issue.widgetCallback, + }), + ], }); if (!editor) { @@ -52,4 +67,4 @@ const DocumentReadOnlyEditorWithRef = forwardRef React.ReactNode; + extensions: Extension[]; + hideDragHandleOnMouseLeave: () => void; +}; + +export const EditorWrapper: React.FC = (props) => { + const { + children, + containerClassName, + editorClassName = "", + extensions, + hideDragHandleOnMouseLeave, + id = "", + initialValue, + fileHandler, + forwardedRef, + mentionHandler, + onChange, + placeholder, + tabIndex, + value, + } = props; + + const editor = useEditor({ + editorClassName, + extensions, + fileHandler, + forwardedRef, + id, + initialValue, + mentionHandler, + onChange, + placeholder, + tabIndex, + value, + }); + + const editorContainerClassName = getEditorClassNames({ + noBorder: true, + borderOnFocus: false, + containerClassName, + }); + + if (!editor) return null; + + return ( + + {children?.(editor)} +
+ +
+
+ ); +}; diff --git a/packages/editor/src/core/components/editors/index.ts b/packages/editor/src/core/components/editors/index.ts new file mode 100644 index 000000000..03ada4f72 --- /dev/null +++ b/packages/editor/src/core/components/editors/index.ts @@ -0,0 +1,7 @@ +export * from "./document"; +export * from "./lite-text"; +export * from "./rich-text"; +export * from "./editor-container"; +export * from "./editor-content"; +export * from "./editor-wrapper"; +export * from "./read-only-editor-wrapper"; diff --git a/packages/editor/src/core/components/editors/lite-text/editor.tsx b/packages/editor/src/core/components/editors/lite-text/editor.tsx new file mode 100644 index 000000000..0ef708022 --- /dev/null +++ b/packages/editor/src/core/components/editors/lite-text/editor.tsx @@ -0,0 +1,23 @@ +import { forwardRef } from "react"; +// components +import { EditorWrapper } from "@/components/editors/editor-wrapper"; +// extensions +import { EnterKeyExtension } from "@/extensions"; +// types +import { EditorRefApi, ILiteTextEditor } from "@/types"; + +const LiteTextEditor = (props: ILiteTextEditor) => { + const { onEnterKeyPress } = props; + + const extensions = [EnterKeyExtension(onEnterKeyPress)]; + + return {}} />; +}; + +const LiteTextEditorWithRef = forwardRef((props, ref) => ( + } /> +)); + +LiteTextEditorWithRef.displayName = "LiteTextEditorWithRef"; + +export { LiteTextEditorWithRef }; diff --git a/packages/editor/src/core/components/editors/lite-text/index.ts b/packages/editor/src/core/components/editors/lite-text/index.ts new file mode 100644 index 000000000..b2ba8682a --- /dev/null +++ b/packages/editor/src/core/components/editors/lite-text/index.ts @@ -0,0 +1,2 @@ +export * from "./editor"; +export * from "./read-only-editor"; diff --git a/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx b/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx new file mode 100644 index 000000000..b721c84c5 --- /dev/null +++ b/packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx @@ -0,0 +1,13 @@ +import { forwardRef } from "react"; +// components +import { ReadOnlyEditorWrapper } from "@/components/editors"; +// types +import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor } from "@/types"; + +const LiteTextReadOnlyEditorWithRef = forwardRef((props, ref) => ( + } /> +)); + +LiteTextReadOnlyEditorWithRef.displayName = "LiteReadOnlyEditorWithRef"; + +export { LiteTextReadOnlyEditorWithRef }; 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 new file mode 100644 index 000000000..25da4d9af --- /dev/null +++ b/packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx @@ -0,0 +1,33 @@ +// components +import { EditorContainer, EditorContentWrapper } from "@/components/editors"; +// helpers +import { getEditorClassNames } from "@/helpers/common"; +// hooks +import { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; +// types +import { IReadOnlyEditorProps } from "@/types"; + +export const ReadOnlyEditorWrapper = (props: IReadOnlyEditorProps) => { + const { containerClassName, editorClassName = "", initialValue, forwardedRef, mentionHandler } = props; + + const editor = useReadOnlyEditor({ + initialValue, + editorClassName, + forwardedRef, + mentionHandler, + }); + + const editorContainerClassName = getEditorClassNames({ + containerClassName, + }); + + if (!editor) return null; + + return ( + +
+ +
+
+ ); +}; diff --git a/packages/editor/src/core/components/editors/rich-text/editor.tsx b/packages/editor/src/core/components/editors/rich-text/editor.tsx new file mode 100644 index 000000000..069681dab --- /dev/null +++ b/packages/editor/src/core/components/editors/rich-text/editor.tsx @@ -0,0 +1,46 @@ +import { forwardRef, useCallback, useState } from "react"; +// components +import { EditorWrapper } from "@/components/editors"; +import { EditorBubbleMenu } from "@/components/menus"; +// extensions +import { DragAndDrop, SlashCommand } from "@/extensions"; +// types +import { EditorRefApi, IRichTextEditor } from "@/types"; + +const RichTextEditor = (props: IRichTextEditor) => { + const { dragDropEnabled, fileHandler } = props; + // states + const [hideDragHandleOnMouseLeave, setHideDragHandleOnMouseLeave] = useState<() => void>(() => {}); + + // this essentially sets the hideDragHandle function from the DragAndDrop extension as the Plugin + // loads such that we can invoke it from react when the cursor leaves the container + const setHideDragHandleFunction = (hideDragHandlerFromDragDrop: () => void) => { + setHideDragHandleOnMouseLeave(() => hideDragHandlerFromDragDrop); + }; + + const getExtensions = useCallback(() => { + const extensions = [ + SlashCommand(fileHandler.upload), + // TODO; add the extension conditionally for forms that don't require it + // EnterKeyExtension(onEnterKeyPress), + ]; + + if (dragDropEnabled) extensions.push(DragAndDrop(setHideDragHandleFunction)); + + return extensions; + }, [dragDropEnabled, fileHandler.upload]); + + return ( + + {(editor) => <>{editor && }} + + ); +}; + +const RichTextEditorWithRef = forwardRef((props, ref) => ( + } /> +)); + +RichTextEditorWithRef.displayName = "RichTextEditorWithRef"; + +export { RichTextEditorWithRef }; diff --git a/packages/editor/src/core/components/editors/rich-text/index.ts b/packages/editor/src/core/components/editors/rich-text/index.ts new file mode 100644 index 000000000..b2ba8682a --- /dev/null +++ b/packages/editor/src/core/components/editors/rich-text/index.ts @@ -0,0 +1,2 @@ +export * from "./editor"; +export * from "./read-only-editor"; diff --git a/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx b/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx new file mode 100644 index 000000000..8bd7a837a --- /dev/null +++ b/packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx @@ -0,0 +1,12 @@ +import { forwardRef } from "react"; +// types +import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor } from "@/types"; +import { ReadOnlyEditorWrapper } from "../read-only-editor-wrapper"; + +const RichTextReadOnlyEditorWithRef = forwardRef((props, ref) => ( + } /> +)); + +RichTextReadOnlyEditorWithRef.displayName = "RichReadOnlyEditorWithRef"; + +export { RichTextReadOnlyEditorWithRef }; diff --git a/packages/editor/src/core/components/links/index.ts b/packages/editor/src/core/components/links/index.ts new file mode 100644 index 000000000..8e123098e --- /dev/null +++ b/packages/editor/src/core/components/links/index.ts @@ -0,0 +1,4 @@ +export * from "./link-edit-view"; +export * from "./link-input-view"; +export * from "./link-preview"; +export * from "./link-view"; diff --git a/packages/editor/document-editor/src/ui/components/links/link-edit-view.tsx b/packages/editor/src/core/components/links/link-edit-view.tsx similarity index 96% rename from packages/editor/document-editor/src/ui/components/links/link-edit-view.tsx rename to packages/editor/src/core/components/links/link-edit-view.tsx index 0cee059df..ad8e9baeb 100644 --- a/packages/editor/document-editor/src/ui/components/links/link-edit-view.tsx +++ b/packages/editor/src/core/components/links/link-edit-view.tsx @@ -1,8 +1,10 @@ -import { isValidHttpUrl } from "@plane/editor-core"; +import { useEffect, useRef, useState } from "react"; import { Node } from "@tiptap/pm/model"; import { Link2Off } from "lucide-react"; -import { useEffect, useRef, useState } from "react"; -import { LinkViewProps } from "./link-view"; +// components +import { LinkViewProps } from "@/components/links"; +// helpers +import { isValidHttpUrl } from "@/helpers/common"; const InputView = ({ label, @@ -50,7 +52,7 @@ export const LinkEditView = ({ }; const isValidUrl = (urlString: string) => { - var urlPattern = new RegExp( + const urlPattern = new RegExp( "^(https?:\\/\\/)?" + // validate protocol "([\\w-]+\\.)+[\\w-]{2,}" + // validate domain name "|((\\d{1,3}\\.){3}\\d{1,3})" + // validate IP (v4) address diff --git a/packages/editor/document-editor/src/ui/components/links/link-input-view.tsx b/packages/editor/src/core/components/links/link-input-view.tsx similarity index 55% rename from packages/editor/document-editor/src/ui/components/links/link-input-view.tsx rename to packages/editor/src/core/components/links/link-input-view.tsx index fa73adbe1..a66d80e6d 100644 --- a/packages/editor/document-editor/src/ui/components/links/link-input-view.tsx +++ b/packages/editor/src/core/components/links/link-input-view.tsx @@ -1,9 +1,7 @@ -import { LinkViewProps } from "./link-view"; +// components +import { LinkViewProps } from "@/components/links"; -export const LinkInputView = ({ - viewProps, - switchView, -}: { +export const LinkInputView = ({}: { viewProps: LinkViewProps; switchView: (view: "LinkPreview" | "LinkEditView" | "LinkInputView") => void; }) =>

LinkInputView

; diff --git a/packages/editor/document-editor/src/ui/components/links/link-preview.tsx b/packages/editor/src/core/components/links/link-preview.tsx similarity index 95% rename from packages/editor/document-editor/src/ui/components/links/link-preview.tsx rename to packages/editor/src/core/components/links/link-preview.tsx index 0bb719d93..1237c7c98 100644 --- a/packages/editor/document-editor/src/ui/components/links/link-preview.tsx +++ b/packages/editor/src/core/components/links/link-preview.tsx @@ -1,5 +1,6 @@ import { Copy, GlobeIcon, Link2Off, PencilIcon } from "lucide-react"; -import { LinkViewProps } from "./link-view"; +// components +import { LinkViewProps } from "@/components/links"; export const LinkPreview = ({ viewProps, diff --git a/packages/editor/document-editor/src/ui/components/links/link-view.tsx b/packages/editor/src/core/components/links/link-view.tsx similarity index 88% rename from packages/editor/document-editor/src/ui/components/links/link-view.tsx rename to packages/editor/src/core/components/links/link-view.tsx index 9befc514c..988250387 100644 --- a/packages/editor/document-editor/src/ui/components/links/link-view.tsx +++ b/packages/editor/src/core/components/links/link-view.tsx @@ -1,8 +1,7 @@ -import { Editor } from "@tiptap/react"; import { CSSProperties, useEffect, useState } from "react"; -import { LinkEditView } from "./link-edit-view"; -import { LinkInputView } from "./link-input-view"; -import { LinkPreview } from "./link-preview"; +import { Editor } from "@tiptap/react"; +// components +import { LinkEditView, LinkInputView, LinkPreview } from "@/components/links"; export interface LinkViewProps { view?: "LinkPreview" | "LinkEditView" | "LinkInputView"; diff --git a/packages/editor/document-editor/src/ui/menu/block-menu.tsx b/packages/editor/src/core/components/menus/block-menu.tsx similarity index 98% rename from packages/editor/document-editor/src/ui/menu/block-menu.tsx rename to packages/editor/src/core/components/menus/block-menu.tsx index 8a303809c..8473f6c10 100644 --- a/packages/editor/document-editor/src/ui/menu/block-menu.tsx +++ b/packages/editor/src/core/components/menus/block-menu.tsx @@ -1,13 +1,13 @@ import { useCallback, useEffect, useRef } from "react"; -import tippy, { Instance } from "tippy.js"; import { Copy, LucideIcon, Trash2 } from "lucide-react"; +import tippy, { Instance } from "tippy.js"; import { Editor } from "@tiptap/react"; interface BlockMenuProps { editor: Editor; } -export default function BlockMenu(props: BlockMenuProps) { +export const BlockMenu = (props: BlockMenuProps) => { const { editor } = props; const menuRef = useRef(null); const popup = useRef(null); @@ -171,4 +171,4 @@ export default function BlockMenu(props: BlockMenuProps) { })} ); -} +}; diff --git a/packages/editor/src/core/components/menus/bubble-menu/index.ts b/packages/editor/src/core/components/menus/bubble-menu/index.ts new file mode 100644 index 000000000..71a98bada --- /dev/null +++ b/packages/editor/src/core/components/menus/bubble-menu/index.ts @@ -0,0 +1,3 @@ +export * from "./link-selector"; +export * from "./node-selector"; +export * from "./root"; diff --git a/packages/editor/rich-text-editor/src/ui/menus/bubble-menu/link-selector.tsx b/packages/editor/src/core/components/menus/bubble-menu/link-selector.tsx similarity index 92% rename from packages/editor/rich-text-editor/src/ui/menus/bubble-menu/link-selector.tsx rename to packages/editor/src/core/components/menus/bubble-menu/link-selector.tsx index e45cfb317..20335e8ab 100644 --- a/packages/editor/rich-text-editor/src/ui/menus/bubble-menu/link-selector.tsx +++ b/packages/editor/src/core/components/menus/bubble-menu/link-selector.tsx @@ -1,15 +1,17 @@ +import { Dispatch, FC, SetStateAction, useCallback, useEffect, useRef } from "react"; import { Editor } from "@tiptap/core"; import { Check, Trash } from "lucide-react"; -import { Dispatch, FC, SetStateAction, useCallback, useEffect, useRef } from "react"; -import { cn, isValidHttpUrl, setLinkEditor, unsetLinkEditor } from "@plane/editor-core"; +// helpers +import { cn, isValidHttpUrl } from "@/helpers/common"; +import { setLinkEditor, unsetLinkEditor } from "@/helpers/editor-commands"; -interface LinkSelectorProps { +type Props = { editor: Editor; isOpen: boolean; setIsOpen: Dispatch>; -} +}; -export const LinkSelector: FC = ({ editor, isOpen, setIsOpen }) => { +export const BubbleMenuLinkSelector: FC = ({ editor, isOpen, setIsOpen }) => { const inputRef = useRef(null); const onLinkSubmit = useCallback(() => { diff --git a/packages/editor/rich-text-editor/src/ui/menus/bubble-menu/node-selector.tsx b/packages/editor/src/core/components/menus/bubble-menu/node-selector.tsx similarity index 92% rename from packages/editor/rich-text-editor/src/ui/menus/bubble-menu/node-selector.tsx rename to packages/editor/src/core/components/menus/bubble-menu/node-selector.tsx index 5c1c8479f..466d07c0d 100644 --- a/packages/editor/rich-text-editor/src/ui/menus/bubble-menu/node-selector.tsx +++ b/packages/editor/src/core/components/menus/bubble-menu/node-selector.tsx @@ -1,6 +1,9 @@ +import { Dispatch, FC, SetStateAction } from "react"; +import { Editor } from "@tiptap/react"; +import { Check, ChevronDown } from "lucide-react"; +// components import { BulletListItem, - cn, HeadingOneItem, HeadingThreeItem, HeadingTwoItem, @@ -12,20 +15,18 @@ import { HeadingFourItem, HeadingFiveItem, HeadingSixItem, -} from "@plane/editor-core"; -import { Editor } from "@tiptap/react"; -import { Check, ChevronDown } from "lucide-react"; -import { Dispatch, FC, SetStateAction } from "react"; + BubbleMenuItem, +} from "@/components/menus"; +// helpers +import { cn } from "@/helpers/common"; -import { BubbleMenuItem } from "."; - -interface NodeSelectorProps { +type Props = { editor: Editor; isOpen: boolean; setIsOpen: Dispatch>; -} +}; -export const NodeSelector: FC = ({ editor, isOpen, setIsOpen }) => { +export const BubbleMenuNodeSelector: FC = ({ editor, isOpen, setIsOpen }) => { const items: BubbleMenuItem[] = [ TextItem(editor), HeadingOneItem(editor), diff --git a/packages/editor/rich-text-editor/src/ui/menus/bubble-menu/index.tsx b/packages/editor/src/core/components/menus/bubble-menu/root.tsx similarity index 91% rename from packages/editor/rich-text-editor/src/ui/menus/bubble-menu/index.tsx rename to packages/editor/src/core/components/menus/bubble-menu/root.tsx index c11f0593d..ec72f1540 100644 --- a/packages/editor/rich-text-editor/src/ui/menus/bubble-menu/index.tsx +++ b/packages/editor/src/core/components/menus/bubble-menu/root.tsx @@ -1,25 +1,27 @@ -import { BubbleMenu, BubbleMenuProps, isNodeSelection } from "@tiptap/react"; import { FC, useEffect, useState } from "react"; - -import { NodeSelector } from "src/ui/menus/bubble-menu/node-selector"; -import { LinkSelector } from "src/ui/menus/bubble-menu/link-selector"; +import { BubbleMenu, BubbleMenuProps, isNodeSelection } from "@tiptap/react"; +import { LucideIcon } from "lucide-react"; +// components import { BoldItem, - cn, + BubbleMenuLinkSelector, + BubbleMenuNodeSelector, CodeItem, - isCellSelection, ItalicItem, - LucideIconType, StrikeThroughItem, UnderLineItem, -} from "@plane/editor-core"; +} from "@/components/menus"; +// extensions +import { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; +// helpers +import { cn } from "@/helpers/common"; export interface BubbleMenuItem { key: string; name: string; isActive: () => boolean; command: () => void; - icon: LucideIconType; + icon: LucideIcon; } type EditorBubbleMenuProps = Omit; @@ -105,7 +107,7 @@ export const EditorBubbleMenu: FC = (props: any) => { {isSelecting ? null : ( <> {!props.editor.isActive("table") && ( - { @@ -115,7 +117,7 @@ export const EditorBubbleMenu: FC = (props: any) => { /> )} {!props.editor.isActive("code") && ( - { diff --git a/packages/editor/src/core/components/menus/index.ts b/packages/editor/src/core/components/menus/index.ts new file mode 100644 index 000000000..0c6964ea6 --- /dev/null +++ b/packages/editor/src/core/components/menus/index.ts @@ -0,0 +1,3 @@ +export * from "./bubble-menu"; +export * from "./block-menu"; +export * from "./menu-items"; diff --git a/packages/editor/core/src/ui/menus/menu-items/index.ts b/packages/editor/src/core/components/menus/menu-items.ts similarity index 97% rename from packages/editor/core/src/ui/menus/menu-items/index.ts rename to packages/editor/src/core/components/menus/menu-items.ts index ab2ad8ed4..d5c2316b9 100644 --- a/packages/editor/core/src/ui/menus/menu-items/index.ts +++ b/packages/editor/src/core/components/menus/menu-items.ts @@ -17,8 +17,11 @@ import { Heading5, Heading6, CaseSensitive, + LucideIcon, } from "lucide-react"; +import { Selection } from "@tiptap/pm/state"; import { Editor } from "@tiptap/react"; +// helpers import { insertImageCommand, insertTableCommand, @@ -38,17 +41,16 @@ import { toggleStrike, toggleTaskList, toggleUnderline, -} from "src/lib/editor-commands"; -import { LucideIconType } from "src/types/lucide-icon"; -import { UploadImage } from "src/types/upload-image"; -import { Selection } from "@tiptap/pm/state"; +} from "@/helpers/editor-commands"; +// types +import { UploadImage } from "@/types"; export interface EditorMenuItem { key: string; name: string; isActive: () => boolean; command: () => void; - icon: LucideIconType; + icon: LucideIcon; } export const TextItem = (editor: Editor) => diff --git a/packages/editor/core/src/ui/extensions/code-inline/index.tsx b/packages/editor/src/core/extensions/code-inline/index.tsx similarity index 96% rename from packages/editor/core/src/ui/extensions/code-inline/index.tsx rename to packages/editor/src/core/extensions/code-inline/index.tsx index 60a12364e..70270355d 100644 --- a/packages/editor/core/src/ui/extensions/code-inline/index.tsx +++ b/packages/editor/src/core/extensions/code-inline/index.tsx @@ -24,7 +24,7 @@ declare module "@tiptap/core" { } export const inputRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))$/; -export const pasteRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))/g; +const pasteRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))/g; export const CustomCodeInlineExtension = Mark.create({ name: "code", diff --git a/packages/editor/core/src/ui/extensions/code/code-block-lowlight.ts b/packages/editor/src/core/extensions/code/code-block-lowlight.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/code/code-block-lowlight.ts rename to packages/editor/src/core/extensions/code/code-block-lowlight.ts diff --git a/packages/editor/core/src/ui/extensions/code/code-block-node-view.tsx b/packages/editor/src/core/extensions/code/code-block-node-view.tsx similarity index 97% rename from packages/editor/core/src/ui/extensions/code/code-block-node-view.tsx rename to packages/editor/src/core/extensions/code/code-block-node-view.tsx index 57c665231..2211fa2f4 100644 --- a/packages/editor/core/src/ui/extensions/code/code-block-node-view.tsx +++ b/packages/editor/src/core/extensions/code/code-block-node-view.tsx @@ -6,8 +6,10 @@ import { common, createLowlight } from "lowlight"; import ts from "highlight.js/lib/languages/typescript"; import { CopyIcon, CheckIcon } from "lucide-react"; import { Node as ProseMirrorNode } from "@tiptap/pm/model"; -import { cn } from "src/lib/utils"; +// ui import { Tooltip } from "@plane/ui"; +// helpers +import { cn } from "@/helpers/common"; // we just have ts support for now const lowlight = createLowlight(common); diff --git a/packages/editor/core/src/ui/extensions/code/code-block.ts b/packages/editor/src/core/extensions/code/code-block.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/code/code-block.ts rename to packages/editor/src/core/extensions/code/code-block.ts diff --git a/packages/editor/core/src/ui/extensions/code/index.tsx b/packages/editor/src/core/extensions/code/index.tsx similarity index 100% rename from packages/editor/core/src/ui/extensions/code/index.tsx rename to packages/editor/src/core/extensions/code/index.tsx diff --git a/packages/editor/core/src/ui/extensions/code/lowlight-plugin.ts b/packages/editor/src/core/extensions/code/lowlight-plugin.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/code/lowlight-plugin.ts rename to packages/editor/src/core/extensions/code/lowlight-plugin.ts diff --git a/packages/editor/core/src/ui/extensions/code/utils/replace-code-block-with-text.ts b/packages/editor/src/core/extensions/code/utils/replace-code-block-with-text.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/code/utils/replace-code-block-with-text.ts rename to packages/editor/src/core/extensions/code/utils/replace-code-block-with-text.ts diff --git a/packages/editor/core/src/ui/extensions/core-without-props.tsx b/packages/editor/src/core/extensions/core-without-props.tsx similarity index 68% rename from packages/editor/core/src/ui/extensions/core-without-props.tsx rename to packages/editor/src/core/extensions/core-without-props.tsx index 3bb00010b..a24717310 100644 --- a/packages/editor/core/src/ui/extensions/core-without-props.tsx +++ b/packages/editor/src/core/extensions/core-without-props.tsx @@ -4,27 +4,26 @@ import TextStyle from "@tiptap/extension-text-style"; import TiptapUnderline from "@tiptap/extension-underline"; import Placeholder from "@tiptap/extension-placeholder"; import { Markdown } from "tiptap-markdown"; - -import { Table } from "src/ui/extensions/table/table"; -import { TableCell } from "src/ui/extensions/table/table-cell/table-cell"; -import { TableHeader } from "src/ui/extensions/table/table-header/table-header"; -import { TableRow } from "src/ui/extensions/table/table-row/table-row"; - -import { isValidHttpUrl } from "src/lib/utils"; - -import { CustomCodeBlockExtension } from "src/ui/extensions/code"; -import { CustomKeymap } from "src/ui/extensions/keymap"; -import { CustomQuoteExtension } from "src/ui/extensions/quote"; - -import { CustomLinkExtension } from "src/ui/extensions/custom-link"; -import { CustomCodeInlineExtension } from "src/ui/extensions/code-inline"; -import { CustomTypographyExtension } from "src/ui/extensions/typography"; -import { CustomHorizontalRule } from "src/ui/extensions/horizontal-rule/horizontal-rule"; -import { CustomCodeMarkPlugin } from "src/ui/extensions/custom-code-inline/inline-code-plugin"; -import { MentionsWithoutProps } from "src/ui/mentions/mention-without-props"; -import { ImageExtensionWithoutProps } from "src/ui/extensions/image/image-extension-without-props"; - import StarterKit from "@tiptap/starter-kit"; +// extensions +import { + CustomCodeBlockExtension, + CustomCodeInlineExtension, + CustomCodeMarkPlugin, + CustomHorizontalRule, + CustomKeymap, + CustomLinkExtension, + CustomMentionWithoutProps, + CustomQuoteExtension, + CustomTypographyExtension, + ImageExtensionWithoutProps, + Table, + TableCell, + TableHeader, + TableRow, +} from "@/extensions"; +// helpers +import { isValidHttpUrl } from "@/helpers/common"; export const CoreEditorExtensionsWithoutProps = () => [ StarterKit.configure({ @@ -105,7 +104,7 @@ export const CoreEditorExtensionsWithoutProps = () => [ TableHeader, TableCell, TableRow, - MentionsWithoutProps(), + CustomMentionWithoutProps(), Placeholder.configure({ placeholder: ({ editor, node }) => { if (node.type.name === "heading") return `Heading ${node.attrs.level}`; diff --git a/packages/editor/core/src/ui/extensions/custom-code-inline/inline-code-plugin.ts b/packages/editor/src/core/extensions/custom-code-inline.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/custom-code-inline/inline-code-plugin.ts rename to packages/editor/src/core/extensions/custom-code-inline.ts diff --git a/packages/editor/core/src/ui/extensions/custom-link/index.ts b/packages/editor/src/core/extensions/custom-link/extension.tsx similarity index 97% rename from packages/editor/core/src/ui/extensions/custom-link/index.ts rename to packages/editor/src/core/extensions/custom-link/extension.tsx index 88e7abfe5..e74916a8f 100644 --- a/packages/editor/core/src/ui/extensions/custom-link/index.ts +++ b/packages/editor/src/core/extensions/custom-link/extension.tsx @@ -10,9 +10,6 @@ export interface LinkProtocolOptions { optionalSlashes?: boolean; } -export const pasteRegex = - /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)/gi; - export interface LinkOptions { /** * If enabled, it adds links as you type. diff --git a/packages/editor/core/src/ui/extensions/custom-link/helpers/autolink.ts b/packages/editor/src/core/extensions/custom-link/helpers/autolink.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/custom-link/helpers/autolink.ts rename to packages/editor/src/core/extensions/custom-link/helpers/autolink.ts diff --git a/packages/editor/core/src/ui/extensions/custom-link/helpers/clickHandler.ts b/packages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/custom-link/helpers/clickHandler.ts rename to packages/editor/src/core/extensions/custom-link/helpers/clickHandler.ts diff --git a/packages/editor/core/src/ui/extensions/custom-link/helpers/pasteHandler.ts b/packages/editor/src/core/extensions/custom-link/helpers/pasteHandler.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/custom-link/helpers/pasteHandler.ts rename to packages/editor/src/core/extensions/custom-link/helpers/pasteHandler.ts diff --git a/packages/editor/src/core/extensions/custom-link/index.ts b/packages/editor/src/core/extensions/custom-link/index.ts new file mode 100644 index 000000000..2ce32da8b --- /dev/null +++ b/packages/editor/src/core/extensions/custom-link/index.ts @@ -0,0 +1 @@ +export * from "./extension"; diff --git a/packages/editor/core/src/ui/extensions/custom-list-keymap/index.ts b/packages/editor/src/core/extensions/custom-list-keymap/index.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/custom-list-keymap/index.ts rename to packages/editor/src/core/extensions/custom-list-keymap/index.ts diff --git a/packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers.ts b/packages/editor/src/core/extensions/custom-list-keymap/list-helpers.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/custom-list-keymap/list-helpers.ts rename to packages/editor/src/core/extensions/custom-list-keymap/list-helpers.ts diff --git a/packages/editor/core/src/ui/extensions/custom-list-keymap/list-keymap.ts b/packages/editor/src/core/extensions/custom-list-keymap/list-keymap.ts similarity index 97% rename from packages/editor/core/src/ui/extensions/custom-list-keymap/list-keymap.ts rename to packages/editor/src/core/extensions/custom-list-keymap/list-keymap.ts index f2b6dd999..b02517bab 100644 --- a/packages/editor/core/src/ui/extensions/custom-list-keymap/list-keymap.ts +++ b/packages/editor/src/core/extensions/custom-list-keymap/list-keymap.ts @@ -1,6 +1,6 @@ import { Extension } from "@tiptap/core"; -import { handleBackspace, handleDelete } from "src/ui/extensions/custom-list-keymap/list-helpers"; +import { handleBackspace, handleDelete } from "src/core/extensions/custom-list-keymap/list-helpers"; export type ListKeymapOptions = { listTypes: Array<{ diff --git a/packages/editor/extensions/src/extensions/drag-drop.tsx b/packages/editor/src/core/extensions/drag-drop.tsx similarity index 99% rename from packages/editor/extensions/src/extensions/drag-drop.tsx rename to packages/editor/src/core/extensions/drag-drop.tsx index 32867a5f1..a1496c47b 100644 --- a/packages/editor/extensions/src/extensions/drag-drop.tsx +++ b/packages/editor/src/core/extensions/drag-drop.tsx @@ -1,7 +1,6 @@ import { Extension } from "@tiptap/core"; - -import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state"; import { Fragment, Slice, Node } from "@tiptap/pm/model"; +import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state"; // @ts-expect-error __serializeForClipboard's is not exported import { __serializeForClipboard, EditorView } from "@tiptap/pm/view"; diff --git a/packages/editor/core/src/ui/extensions/drop.tsx b/packages/editor/src/core/extensions/drop.tsx similarity index 92% rename from packages/editor/core/src/ui/extensions/drop.tsx rename to packages/editor/src/core/extensions/drop.tsx index 4bf4e2625..d56f802d9 100644 --- a/packages/editor/core/src/ui/extensions/drop.tsx +++ b/packages/editor/src/core/extensions/drop.tsx @@ -1,7 +1,9 @@ import { Extension } from "@tiptap/core"; import { Plugin, PluginKey } from "prosemirror-state"; -import { UploadImage } from "src/types/upload-image"; -import { startImageUpload } from "src/ui/plugins/image/image-upload-handler"; +// plugins +import { startImageUpload } from "@/plugins/image"; +// types +import { UploadImage } from "@/types"; export const DropHandlerExtension = (uploadFile: UploadImage) => Extension.create({ diff --git a/packages/editor/lite-text-editor/src/ui/extensions/enter-key-extension.tsx b/packages/editor/src/core/extensions/enter-key-extension.tsx similarity index 100% rename from packages/editor/lite-text-editor/src/ui/extensions/enter-key-extension.tsx rename to packages/editor/src/core/extensions/enter-key-extension.tsx diff --git a/packages/editor/core/src/ui/extensions/index.tsx b/packages/editor/src/core/extensions/extensions.tsx similarity index 71% rename from packages/editor/core/src/ui/extensions/index.tsx rename to packages/editor/src/core/extensions/extensions.tsx index 2507aca36..6094c9446 100644 --- a/packages/editor/core/src/ui/extensions/index.tsx +++ b/packages/editor/src/core/extensions/extensions.tsx @@ -5,32 +5,29 @@ import TiptapUnderline from "@tiptap/extension-underline"; import Placeholder from "@tiptap/extension-placeholder"; import StarterKit from "@tiptap/starter-kit"; import { Markdown } from "tiptap-markdown"; - -import { Table } from "src/ui/extensions/table/table"; -import { TableCell } from "src/ui/extensions/table/table-cell/table-cell"; -import { TableHeader } from "src/ui/extensions/table/table-header/table-header"; -import { TableRow } from "src/ui/extensions/table/table-row/table-row"; - -import { ImageExtension } from "src/ui/extensions/image"; - -import { isValidHttpUrl } from "src/lib/utils"; -import { Mentions } from "src/ui/mentions"; - -import { CustomCodeBlockExtension } from "src/ui/extensions/code"; -import { ListKeymap } from "src/ui/extensions/custom-list-keymap"; -import { CustomKeymap } from "src/ui/extensions/keymap"; -import { CustomQuoteExtension } from "src/ui/extensions/quote"; - -import { DeleteImage } from "src/types/delete-image"; -import { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion"; -import { RestoreImage } from "src/types/restore-image"; -import { CustomLinkExtension } from "src/ui/extensions/custom-link"; -import { CustomCodeInlineExtension } from "src/ui/extensions/code-inline"; -import { CustomTypographyExtension } from "src/ui/extensions/typography"; -import { CustomHorizontalRule } from "src/ui/extensions/horizontal-rule/horizontal-rule"; -import { CustomCodeMarkPlugin } from "src/ui/extensions/custom-code-inline/inline-code-plugin"; -import { UploadImage } from "src/types/upload-image"; -import { DropHandlerExtension } from "src/ui/extensions/drop"; +// extensions +import { + CustomCodeBlockExtension, + CustomCodeInlineExtension, + CustomCodeMarkPlugin, + CustomHorizontalRule, + CustomKeymap, + CustomLinkExtension, + CustomMention, + CustomQuoteExtension, + CustomTypographyExtension, + DropHandlerExtension, + ImageExtension, + ListKeymap, + Table, + TableCell, + TableHeader, + TableRow, +} from "@/extensions"; +// helpers +import { isValidHttpUrl } from "@/helpers/common"; +// types +import { DeleteImage, IMentionHighlight, IMentionSuggestion, RestoreImage, UploadImage } from "@/types"; type TArguments = { mentionConfig: { @@ -132,7 +129,7 @@ export const CoreEditorExtensions = ({ TableHeader, TableCell, TableRow, - Mentions({ + CustomMention({ mentionSuggestions: mentionConfig.mentionSuggestions, mentionHighlights: mentionConfig.mentionHighlights, readonly: false, diff --git a/packages/editor/core/src/ui/extensions/horizontal-rule/horizontal-rule.ts b/packages/editor/src/core/extensions/horizontal-rule.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/horizontal-rule/horizontal-rule.ts rename to packages/editor/src/core/extensions/horizontal-rule.ts diff --git a/packages/editor/core/src/ui/extensions/image/index.tsx b/packages/editor/src/core/extensions/image/extension.tsx similarity index 77% rename from packages/editor/core/src/ui/extensions/image/index.tsx rename to packages/editor/src/core/extensions/image/extension.tsx index 7ea12fb11..7f4001dab 100644 --- a/packages/editor/core/src/ui/extensions/image/index.tsx +++ b/packages/editor/src/core/extensions/image/extension.tsx @@ -1,13 +1,12 @@ -import { UploadImagesPlugin } from "src/ui/plugins/image/upload-image"; +import { UploadImagesPlugin } from "src/core/plugins/image/upload-image"; import ImageExt from "@tiptap/extension-image"; -import { TrackImageDeletionPlugin } from "src/ui/plugins/image/delete-image"; -import { DeleteImage } from "src/types/delete-image"; -import { RestoreImage } from "src/types/restore-image"; +import { TrackImageDeletionPlugin } from "src/core/plugins/image/delete-image"; +import { DeleteImage, RestoreImage } from "@/types"; import { insertLineBelowImageAction } from "./utilities/insert-line-below-image"; import { insertLineAboveImageAction } from "./utilities/insert-line-above-image"; -import { TrackImageRestorationPlugin } from "src/ui/plugins/image/restore-image"; -import { IMAGE_NODE_TYPE } from "src/ui/plugins/image/constants"; -import { ImageExtensionStorage } from "src/ui/plugins/image/types/image-node"; +import { TrackImageRestorationPlugin } from "src/core/plugins/image/restore-image"; +import { IMAGE_NODE_TYPE } from "src/core/plugins/image/constants"; +import { ImageExtensionStorage } from "src/core/plugins/image/types/image-node"; export const ImageExtension = (deleteImage: DeleteImage, restoreImage: RestoreImage, cancelUploadImage?: () => void) => ImageExt.extend({ diff --git a/packages/editor/core/src/ui/extensions/image/image-extension-without-props.tsx b/packages/editor/src/core/extensions/image/image-extension-without-props.tsx similarity index 100% rename from packages/editor/core/src/ui/extensions/image/image-extension-without-props.tsx rename to packages/editor/src/core/extensions/image/image-extension-without-props.tsx diff --git a/packages/editor/core/src/ui/extensions/image/image-resize.tsx b/packages/editor/src/core/extensions/image/image-resize.tsx similarity index 100% rename from packages/editor/core/src/ui/extensions/image/image-resize.tsx rename to packages/editor/src/core/extensions/image/image-resize.tsx diff --git a/packages/editor/src/core/extensions/image/index.ts b/packages/editor/src/core/extensions/image/index.ts new file mode 100644 index 000000000..3e2f7518d --- /dev/null +++ b/packages/editor/src/core/extensions/image/index.ts @@ -0,0 +1,4 @@ +export * from "./extension"; +export * from "./image-extension-without-props"; +export * from "./image-resize"; +export * from "./read-only-image"; diff --git a/packages/editor/core/src/ui/extensions/image/read-only-image.tsx b/packages/editor/src/core/extensions/image/read-only-image.tsx similarity index 100% rename from packages/editor/core/src/ui/extensions/image/read-only-image.tsx rename to packages/editor/src/core/extensions/image/read-only-image.tsx diff --git a/packages/editor/core/src/ui/extensions/image/utilities/insert-line-above-image.ts b/packages/editor/src/core/extensions/image/utilities/insert-line-above-image.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/image/utilities/insert-line-above-image.ts rename to packages/editor/src/core/extensions/image/utilities/insert-line-above-image.ts diff --git a/packages/editor/core/src/ui/extensions/image/utilities/insert-line-below-image.ts b/packages/editor/src/core/extensions/image/utilities/insert-line-below-image.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/image/utilities/insert-line-below-image.ts rename to packages/editor/src/core/extensions/image/utilities/insert-line-below-image.ts diff --git a/packages/editor/src/core/extensions/index.ts b/packages/editor/src/core/extensions/index.ts new file mode 100644 index 000000000..2fb9d8974 --- /dev/null +++ b/packages/editor/src/core/extensions/index.ts @@ -0,0 +1,20 @@ +export * from "./code"; +export * from "./code-inline"; +export * from "./custom-link"; +export * from "./custom-list-keymap"; +export * from "./image"; +export * from "./issue-embed"; +export * from "./mentions"; +export * from "./table"; +export * from "./typography"; +export * from "./core-without-props"; +export * from "./custom-code-inline"; +export * from "./drag-drop"; +export * from "./drop"; +export * from "./enter-key-extension"; +export * from "./extensions"; +export * from "./horizontal-rule"; +export * from "./keymap"; +export * from "./quote"; +export * from "./read-only-extensions"; +export * from "./slash-commands"; diff --git a/packages/editor/src/core/extensions/issue-embed/index.ts b/packages/editor/src/core/extensions/issue-embed/index.ts new file mode 100644 index 000000000..f6674719e --- /dev/null +++ b/packages/editor/src/core/extensions/issue-embed/index.ts @@ -0,0 +1 @@ +export * from "./widget-node"; diff --git a/packages/editor/src/core/extensions/issue-embed/widget-node.tsx b/packages/editor/src/core/extensions/issue-embed/widget-node.tsx new file mode 100644 index 000000000..a216ab6d9 --- /dev/null +++ b/packages/editor/src/core/extensions/issue-embed/widget-node.tsx @@ -0,0 +1,66 @@ +import { mergeAttributes, Node } from "@tiptap/core"; +import { ReactNodeViewRenderer, NodeViewWrapper } from "@tiptap/react"; + +type Props = { + widgetCallback: ({ + issueId, + projectId, + workspaceSlug, + }: { + issueId: string; + projectId: string | undefined; + workspaceSlug: string | undefined; + }) => React.ReactNode; +}; + +export const IssueWidget = (props: Props) => + Node.create({ + name: "issue-embed-component", + group: "block", + atom: true, + selectable: true, + draggable: true, + + addAttributes() { + return { + entity_identifier: { + default: undefined, + }, + project_identifier: { + default: undefined, + }, + workspace_identifier: { + default: undefined, + }, + id: { + default: undefined, + }, + entity_name: { + default: undefined, + }, + }; + }, + + addNodeView() { + return ReactNodeViewRenderer((issueProps: any) => ( + + {props.widgetCallback({ + issueId: issueProps.node.attrs.entity_identifier, + projectId: issueProps.node.attrs.project_identifier, + workspaceSlug: issueProps.node.attrs.workspace_identifier, + })} + + )); + }, + + parseHTML() { + return [ + { + tag: "issue-embed-component", + }, + ]; + }, + renderHTML({ HTMLAttributes }) { + return ["issue-embed-component", mergeAttributes(HTMLAttributes)]; + }, + }); diff --git a/packages/editor/core/src/ui/extensions/keymap.tsx b/packages/editor/src/core/extensions/keymap.tsx similarity index 100% rename from packages/editor/core/src/ui/extensions/keymap.tsx rename to packages/editor/src/core/extensions/keymap.tsx diff --git a/packages/editor/core/src/ui/mentions/index.tsx b/packages/editor/src/core/extensions/mentions/extension.tsx similarity index 64% rename from packages/editor/core/src/ui/mentions/index.tsx rename to packages/editor/src/core/extensions/mentions/extension.tsx index 838622cbb..f6777cafc 100644 --- a/packages/editor/core/src/ui/mentions/index.tsx +++ b/packages/editor/src/core/extensions/mentions/extension.tsx @@ -1,12 +1,18 @@ -import { CustomMention } from "src/ui/mentions/custom"; -import { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion"; -import { ReactRenderer } from "@tiptap/react"; -import { Editor } from "@tiptap/core"; +import Mention, { MentionOptions } from "@tiptap/extension-mention"; +import { ReactNodeViewRenderer, ReactRenderer } from "@tiptap/react"; +import { Editor, mergeAttributes } from "@tiptap/core"; import tippy from "tippy.js"; +// extensions +import { MentionList, MentionNodeView } from "@/extensions"; +// types +import { IMentionHighlight, IMentionSuggestion } from "@/types"; -import { MentionList } from "src/ui/mentions/mention-list"; +export interface CustomMentionOptions extends MentionOptions { + mentionHighlights: () => Promise; + readonly?: boolean; +} -export const Mentions = ({ +export const CustomMention = ({ mentionHighlights, mentionSuggestions, readonly, @@ -15,14 +21,58 @@ export const Mentions = ({ mentionHighlights?: () => Promise; readonly: boolean; }) => - CustomMention.configure({ + Mention.extend({ + addStorage(this) { + return { + mentionsOpen: false, + }; + }, + addAttributes() { + return { + id: { + default: null, + }, + label: { + default: null, + }, + target: { + default: null, + }, + self: { + default: false, + }, + redirect_uri: { + default: "/", + }, + entity_identifier: { + default: null, + }, + entity_name: { + default: null, + }, + }; + }, + + addNodeView() { + return ReactNodeViewRenderer(MentionNodeView); + }, + + parseHTML() { + return [ + { + tag: "mention-component", + }, + ]; + }, + renderHTML({ HTMLAttributes }) { + return ["mention-component", mergeAttributes(HTMLAttributes)]; + }, HTMLAttributes: { class: "mention", }, readonly: readonly, mentionHighlights: mentionHighlights, suggestion: { - // @ts-expect-error - Tiptap types are incorrect render: () => { if (!mentionSuggestions) return; let component: ReactRenderer | null = null; diff --git a/packages/editor/src/core/extensions/mentions/index.ts b/packages/editor/src/core/extensions/mentions/index.ts new file mode 100644 index 000000000..c7f2317a7 --- /dev/null +++ b/packages/editor/src/core/extensions/mentions/index.ts @@ -0,0 +1,4 @@ +export * from "./extension"; +export * from "./mention-node-view"; +export * from "./mentions-list"; +export * from "./mentions-without-props"; diff --git a/packages/editor/core/src/ui/mentions/mention-node-view.tsx b/packages/editor/src/core/extensions/mentions/mention-node-view.tsx similarity index 92% rename from packages/editor/core/src/ui/mentions/mention-node-view.tsx rename to packages/editor/src/core/extensions/mentions/mention-node-view.tsx index 2100bd24a..87bdacfe8 100644 --- a/packages/editor/core/src/ui/mentions/mention-node-view.tsx +++ b/packages/editor/src/core/extensions/mentions/mention-node-view.tsx @@ -1,9 +1,11 @@ /* eslint-disable react/display-name */ // @ts-nocheck -import { NodeViewWrapper } from "@tiptap/react"; -import { cn } from "src/lib/utils"; -import { IMentionHighlight } from "src/types/mention-suggestion"; import { useEffect, useState } from "react"; +import { NodeViewWrapper } from "@tiptap/react"; +// helpers +import { cn } from "@/helpers/common"; +// types +import { IMentionHighlight } from "@/types"; // eslint-disable-next-line import/no-anonymous-default-export export const MentionNodeView = (props) => { diff --git a/packages/editor/core/src/ui/mentions/mention-list.tsx b/packages/editor/src/core/extensions/mentions/mentions-list.tsx similarity index 97% rename from packages/editor/core/src/ui/mentions/mention-list.tsx rename to packages/editor/src/core/extensions/mentions/mentions-list.tsx index dc67d26ae..6ca6ba8eb 100644 --- a/packages/editor/core/src/ui/mentions/mention-list.tsx +++ b/packages/editor/src/core/extensions/mentions/mentions-list.tsx @@ -1,11 +1,14 @@ "use client"; -import { Editor } from "@tiptap/react"; import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react"; -import { cn } from "src/lib/utils"; -import { IMentionSuggestion } from "src/types/mention-suggestion"; +import { Editor } from "@tiptap/react"; import { v4 as uuidv4 } from "uuid"; +// ui import { Avatar } from "@plane/ui"; +// helpers +import { cn } from "@/helpers/common"; +// types +import { IMentionSuggestion } from "@/types"; interface MentionListProps { command: (item: { diff --git a/packages/editor/src/core/extensions/mentions/mentions-without-props.tsx b/packages/editor/src/core/extensions/mentions/mentions-without-props.tsx new file mode 100644 index 000000000..60a005bfd --- /dev/null +++ b/packages/editor/src/core/extensions/mentions/mentions-without-props.tsx @@ -0,0 +1,50 @@ +import Mention from "@tiptap/extension-mention"; +import { ReactNodeViewRenderer } from "@tiptap/react"; +import { mergeAttributes } from "@tiptap/core"; +// extensions +import { CustomMentionOptions, MentionNodeView } from "@/extensions"; + +export const CustomMentionWithoutProps = () => + Mention.extend({ + addAttributes() { + return { + id: { + default: null, + }, + label: { + default: null, + }, + target: { + default: null, + }, + self: { + default: false, + }, + redirect_uri: { + default: "/", + }, + entity_identifier: { + default: null, + }, + entity_name: { + default: null, + }, + }; + }, + addNodeView() { + return ReactNodeViewRenderer(MentionNodeView); + }, + parseHTML() { + return [ + { + tag: "mention-component", + }, + ]; + }, + renderHTML({ HTMLAttributes }) { + return ["mention-component", mergeAttributes(HTMLAttributes)]; + }, + HTMLAttributes: { + class: "mention", + }, + }); diff --git a/packages/editor/core/src/ui/extensions/quote/index.tsx b/packages/editor/src/core/extensions/quote.tsx similarity index 100% rename from packages/editor/core/src/ui/extensions/quote/index.tsx rename to packages/editor/src/core/extensions/quote.tsx diff --git a/packages/editor/core/src/ui/read-only/extensions.tsx b/packages/editor/src/core/extensions/read-only-extensions.tsx similarity index 68% rename from packages/editor/core/src/ui/read-only/extensions.tsx rename to packages/editor/src/core/extensions/read-only-extensions.tsx index 3f0cd98c3..88988e5ca 100644 --- a/packages/editor/core/src/ui/read-only/extensions.tsx +++ b/packages/editor/src/core/extensions/read-only-extensions.tsx @@ -4,22 +4,25 @@ import TextStyle from "@tiptap/extension-text-style"; import TaskItem from "@tiptap/extension-task-item"; import TaskList from "@tiptap/extension-task-list"; import { Markdown } from "tiptap-markdown"; - -import { TableHeader } from "src/ui/extensions/table/table-header/table-header"; -import { Table } from "src/ui/extensions/table/table"; -import { TableCell } from "src/ui/extensions/table/table-cell/table-cell"; -import { TableRow } from "src/ui/extensions/table/table-row/table-row"; - -import { ReadOnlyImageExtension } from "src/ui/extensions/image/read-only-image"; -import { isValidHttpUrl } from "src/lib/utils"; -import { Mentions } from "src/ui/mentions"; -import { IMentionHighlight } from "src/types/mention-suggestion"; -import { CustomLinkExtension } from "src/ui/extensions/custom-link"; -import { CustomHorizontalRule } from "src/ui/extensions/horizontal-rule/horizontal-rule"; -import { CustomQuoteExtension } from "src/ui/extensions/quote"; -import { CustomTypographyExtension } from "src/ui/extensions/typography"; -import { CustomCodeBlockExtension } from "src/ui/extensions/code"; -import { CustomCodeInlineExtension } from "src/ui/extensions/code-inline"; +// helpers +import { isValidHttpUrl } from "@/helpers/common"; +// extensions +import { + CustomQuoteExtension, + CustomHorizontalRule, + CustomLinkExtension, + CustomTypographyExtension, + ReadOnlyImageExtension, + CustomCodeBlockExtension, + CustomCodeInlineExtension, + TableHeader, + TableCell, + TableRow, + Table, + CustomMention, +} from "@/extensions"; +// types +import { IMentionHighlight } from "@/types"; export const CoreReadOnlyEditorExtensions = (mentionConfig: { mentionHighlights?: () => Promise; @@ -97,7 +100,7 @@ export const CoreReadOnlyEditorExtensions = (mentionConfig: { TableHeader, TableCell, TableRow, - Mentions({ + CustomMention({ mentionHighlights: mentionConfig.mentionHighlights, readonly: true, }), diff --git a/packages/editor/extensions/src/extensions/slash-commands.tsx b/packages/editor/src/core/extensions/slash-commands.tsx similarity index 97% rename from packages/editor/extensions/src/extensions/slash-commands.tsx rename to packages/editor/src/core/extensions/slash-commands.tsx index 7844700bf..9f9abaee7 100644 --- a/packages/editor/extensions/src/extensions/slash-commands.tsx +++ b/packages/editor/src/core/extensions/slash-commands.tsx @@ -17,11 +17,9 @@ import { Quote, Table, } from "lucide-react"; +// helpers +import { cn } from "@/helpers/common"; import { - UploadImage, - ISlashCommandItem, - CommandProps, - cn, insertTableCommand, toggleBlockquote, toggleBulletList, @@ -31,7 +29,9 @@ import { toggleHeadingOne, toggleHeadingTwo, toggleHeadingThree, -} from "@plane/editor-core"; +} from "@/helpers/editor-commands"; +// types +import { CommandProps, ISlashCommandItem, UploadImage } from "@/types"; interface CommandItemProps { key: string; @@ -183,9 +183,7 @@ const getSuggestionItems = description: "Capture a code snippet.", searchTerms: ["codeblock"], icon: , - command: ({ editor, range }: CommandProps) => - // @ts-expect-error I have to move this to the core - editor.chain().focus().deleteRange(range).toggleCodeBlock().run(), + command: ({ editor, range }: CommandProps) => editor.chain().focus().deleteRange(range).toggleCodeBlock().run(), }, { key: "image", @@ -204,7 +202,6 @@ const getSuggestionItems = searchTerms: ["line", "divider", "horizontal", "rule", "separate"], icon: , command: ({ editor, range }: CommandProps) => { - // @ts-expect-error I have to move this to the core editor.chain().focus().deleteRange(range).setHorizontalRule().run(); }, }, diff --git a/packages/editor/src/core/extensions/table/index.ts b/packages/editor/src/core/extensions/table/index.ts new file mode 100644 index 000000000..2277e09ae --- /dev/null +++ b/packages/editor/src/core/extensions/table/index.ts @@ -0,0 +1,4 @@ +export * from "./table"; +export * from "./table-cell"; +export * from "./table-header"; +export * from "./table-row"; diff --git a/packages/editor/core/src/ui/extensions/table/table-cell/index.ts b/packages/editor/src/core/extensions/table/table-cell/index.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table-cell/index.ts rename to packages/editor/src/core/extensions/table/table-cell/index.ts diff --git a/packages/editor/core/src/ui/extensions/table/table-cell/table-cell.ts b/packages/editor/src/core/extensions/table/table-cell/table-cell.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table-cell/table-cell.ts rename to packages/editor/src/core/extensions/table/table-cell/table-cell.ts diff --git a/packages/editor/core/src/ui/extensions/table/table-header/index.ts b/packages/editor/src/core/extensions/table/table-header/index.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table-header/index.ts rename to packages/editor/src/core/extensions/table/table-header/index.ts diff --git a/packages/editor/core/src/ui/extensions/table/table-header/table-header.ts b/packages/editor/src/core/extensions/table/table-header/table-header.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table-header/table-header.ts rename to packages/editor/src/core/extensions/table/table-header/table-header.ts diff --git a/packages/editor/core/src/ui/extensions/table/table-row/index.ts b/packages/editor/src/core/extensions/table/table-row/index.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table-row/index.ts rename to packages/editor/src/core/extensions/table/table-row/index.ts diff --git a/packages/editor/core/src/ui/extensions/table/table-row/table-row.ts b/packages/editor/src/core/extensions/table/table-row/table-row.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table-row/table-row.ts rename to packages/editor/src/core/extensions/table/table-row/table-row.ts diff --git a/packages/editor/core/src/ui/extensions/table/table/icons.ts b/packages/editor/src/core/extensions/table/table/icons.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table/icons.ts rename to packages/editor/src/core/extensions/table/table/icons.ts diff --git a/packages/editor/core/src/ui/extensions/table/table/index.ts b/packages/editor/src/core/extensions/table/table/index.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table/index.ts rename to packages/editor/src/core/extensions/table/table/index.ts diff --git a/packages/editor/core/src/ui/extensions/table/table/table-controls.ts b/packages/editor/src/core/extensions/table/table/table-controls.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table/table-controls.ts rename to packages/editor/src/core/extensions/table/table/table-controls.ts diff --git a/packages/editor/core/src/ui/extensions/table/table/table-view.tsx b/packages/editor/src/core/extensions/table/table/table-view.tsx similarity index 99% rename from packages/editor/core/src/ui/extensions/table/table/table-view.tsx rename to packages/editor/src/core/extensions/table/table/table-view.tsx index d4dfcf5c7..347e82171 100644 --- a/packages/editor/core/src/ui/extensions/table/table/table-view.tsx +++ b/packages/editor/src/core/extensions/table/table/table-view.tsx @@ -6,7 +6,7 @@ import tippy, { Instance, Props } from "tippy.js"; import { Editor } from "@tiptap/core"; import { CellSelection, TableMap, updateColumnsOnResize } from "@tiptap/pm/tables"; -import { icons } from "src/ui/extensions/table/table/icons"; +import { icons } from "src/core/extensions/table/table/icons"; type ToolboxItem = { label: string; diff --git a/packages/editor/core/src/ui/extensions/table/table/table.ts b/packages/editor/src/core/extensions/table/table/table.ts similarity index 95% rename from packages/editor/core/src/ui/extensions/table/table/table.ts rename to packages/editor/src/core/extensions/table/table/table.ts index c1f65feec..4299ff221 100644 --- a/packages/editor/core/src/ui/extensions/table/table/table.ts +++ b/packages/editor/src/core/extensions/table/table/table.ts @@ -21,10 +21,10 @@ import { toggleHeaderCell, } from "@tiptap/pm/tables"; -import { tableControls } from "src/ui/extensions/table/table/table-controls"; -import { TableView } from "src/ui/extensions/table/table/table-view"; -import { createTable } from "src/ui/extensions/table/table/utilities/create-table"; -import { deleteTableWhenAllCellsSelected } from "src/ui/extensions/table/table/utilities/delete-table-when-all-cells-selected"; +import { tableControls } from "src/core/extensions/table/table/table-controls"; +import { TableView } from "src/core/extensions/table/table/table-view"; +import { createTable } from "src/core/extensions/table/table/utilities/create-table"; +import { deleteTableWhenAllCellsSelected } from "src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected"; import { insertLineBelowTableAction } from "./utilities/insert-line-below-table-action"; import { insertLineAboveTableAction } from "./utilities/insert-line-above-table-action"; diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/create-cell.ts b/packages/editor/src/core/extensions/table/table/utilities/create-cell.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table/utilities/create-cell.ts rename to packages/editor/src/core/extensions/table/table/utilities/create-cell.ts diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/create-table.ts b/packages/editor/src/core/extensions/table/table/utilities/create-table.ts similarity index 84% rename from packages/editor/core/src/ui/extensions/table/table/utilities/create-table.ts rename to packages/editor/src/core/extensions/table/table/utilities/create-table.ts index 7299dd442..cede65cbc 100644 --- a/packages/editor/core/src/ui/extensions/table/table/utilities/create-table.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/create-table.ts @@ -1,7 +1,7 @@ import { Fragment, Node as ProsemirrorNode, Schema } from "@tiptap/pm/model"; -import { createCell } from "src/ui/extensions/table/table/utilities/create-cell"; -import { getTableNodeTypes } from "src/ui/extensions/table/table/utilities/get-table-node-types"; +import { createCell } from "src/core/extensions/table/table/utilities/create-cell"; +import { getTableNodeTypes } from "src/core/extensions/table/table/utilities/get-table-node-types"; export function createTable( schema: Schema, diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts b/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts similarity index 89% rename from packages/editor/core/src/ui/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts rename to packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts index c08228a00..f8f131230 100644 --- a/packages/editor/core/src/ui/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/delete-table-when-all-cells-selected.ts @@ -1,6 +1,6 @@ import { findParentNodeClosestToPos, KeyboardShortcutCommand } from "@tiptap/core"; -import { isCellSelection } from "src/ui/extensions/table/table/utilities/is-cell-selection"; +import { isCellSelection } from "src/core/extensions/table/table/utilities/is-cell-selection"; export const deleteTableWhenAllCellsSelected: KeyboardShortcutCommand = ({ editor }) => { const { selection } = editor.state; diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/get-table-node-types.ts b/packages/editor/src/core/extensions/table/table/utilities/get-table-node-types.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table/utilities/get-table-node-types.ts rename to packages/editor/src/core/extensions/table/table/utilities/get-table-node-types.ts diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/insert-line-above-table-action.ts b/packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts similarity index 96% rename from packages/editor/core/src/ui/extensions/table/table/utilities/insert-line-above-table-action.ts rename to packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts index 865bce8b7..ca5ed3d7e 100644 --- a/packages/editor/core/src/ui/extensions/table/table/utilities/insert-line-above-table-action.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/insert-line-above-table-action.ts @@ -1,5 +1,6 @@ import { KeyboardShortcutCommand } from "@tiptap/core"; -import { findParentNodeOfType } from "src/lib/utils"; +// helpers +import { findParentNodeOfType } from "@/helpers/common"; export const insertLineAboveTableAction: KeyboardShortcutCommand = ({ editor }) => { // Check if the current selection or the closest node is a table diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/insert-line-below-table-action.ts b/packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts similarity index 96% rename from packages/editor/core/src/ui/extensions/table/table/utilities/insert-line-below-table-action.ts rename to packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts index 6ce0fa4c4..7edca9f30 100644 --- a/packages/editor/core/src/ui/extensions/table/table/utilities/insert-line-below-table-action.ts +++ b/packages/editor/src/core/extensions/table/table/utilities/insert-line-below-table-action.ts @@ -1,5 +1,6 @@ import { KeyboardShortcutCommand } from "@tiptap/core"; -import { findParentNodeOfType } from "src/lib/utils"; +// helpers +import { findParentNodeOfType } from "@/helpers/common"; export const insertLineBelowTableAction: KeyboardShortcutCommand = ({ editor }) => { // Check if the current selection or the closest node is a table diff --git a/packages/editor/core/src/ui/extensions/table/table/utilities/is-cell-selection.ts b/packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/table/table/utilities/is-cell-selection.ts rename to packages/editor/src/core/extensions/table/table/utilities/is-cell-selection.ts diff --git a/packages/editor/core/src/ui/extensions/typography/index.ts b/packages/editor/src/core/extensions/typography/index.ts similarity index 98% rename from packages/editor/core/src/ui/extensions/typography/index.ts rename to packages/editor/src/core/extensions/typography/index.ts index 78af3c46e..c752c6422 100644 --- a/packages/editor/core/src/ui/extensions/typography/index.ts +++ b/packages/editor/src/core/extensions/typography/index.ts @@ -20,7 +20,7 @@ import { oneQuarter, threeQuarters, impliesArrowRight, -} from "src/ui/extensions/typography/inputRules"; +} from "src/core/extensions/typography/inputRules"; export const CustomTypographyExtension = Extension.create({ name: "typography", diff --git a/packages/editor/core/src/ui/extensions/typography/inputRules.ts b/packages/editor/src/core/extensions/typography/inputRules.ts similarity index 100% rename from packages/editor/core/src/ui/extensions/typography/inputRules.ts rename to packages/editor/src/core/extensions/typography/inputRules.ts diff --git a/packages/editor/core/src/lib/utils.ts b/packages/editor/src/core/helpers/common.ts similarity index 96% rename from packages/editor/core/src/lib/utils.ts rename to packages/editor/src/core/helpers/common.ts index 137c70c2e..5fbff4510 100644 --- a/packages/editor/core/src/lib/utils.ts +++ b/packages/editor/src/core/helpers/common.ts @@ -1,8 +1,9 @@ import { Extensions, generateJSON, getSchema } from "@tiptap/core"; import { Selection } from "@tiptap/pm/state"; import { clsx, type ClassValue } from "clsx"; -import { CoreEditorExtensionsWithoutProps } from "src/ui/extensions/core-without-props"; +import { CoreEditorExtensionsWithoutProps } from "src/core/extensions/core-without-props"; import { twMerge } from "tailwind-merge"; + interface EditorClassNames { noBorder?: boolean; borderOnFocus?: boolean; diff --git a/packages/editor/core/src/lib/editor-commands.ts b/packages/editor/src/core/helpers/editor-commands.ts similarity index 95% rename from packages/editor/core/src/lib/editor-commands.ts rename to packages/editor/src/core/helpers/editor-commands.ts index 6e05ff13d..a73769cf2 100644 --- a/packages/editor/core/src/lib/editor-commands.ts +++ b/packages/editor/src/core/helpers/editor-commands.ts @@ -1,9 +1,10 @@ import { Editor, Range } from "@tiptap/core"; -import { startImageUpload } from "src/ui/plugins/image/image-upload-handler"; -import { findTableAncestor } from "src/lib/utils"; +import { startImageUpload } from "src/core/plugins/image/image-upload-handler"; +import { findTableAncestor } from "@/helpers/common"; import { Selection } from "@tiptap/pm/state"; -import { UploadImage } from "src/types/upload-image"; -import { replaceCodeWithText } from "src/ui/extensions/code/utils/replace-code-block-with-text"; +import { replaceCodeWithText } from "@/extensions/code/utils/replace-code-block-with-text"; +// types +import { UploadImage } from "@/types"; export const setText = (editor: Editor, range?: Range) => { if (range) editor.chain().focus().deleteRange(range).clearNodes().run(); diff --git a/packages/editor/core/src/helpers/insert-content-at-cursor-position.ts b/packages/editor/src/core/helpers/insert-content-at-cursor-position.ts similarity index 100% rename from packages/editor/core/src/helpers/insert-content-at-cursor-position.ts rename to packages/editor/src/core/helpers/insert-content-at-cursor-position.ts diff --git a/packages/editor/core/src/helpers/scroll-to-node.ts b/packages/editor/src/core/helpers/scroll-to-node.ts similarity index 100% rename from packages/editor/core/src/helpers/scroll-to-node.ts rename to packages/editor/src/core/helpers/scroll-to-node.ts diff --git a/packages/editor/document-editor/src/utils/yjs.ts b/packages/editor/src/core/helpers/yjs.ts similarity index 100% rename from packages/editor/document-editor/src/utils/yjs.ts rename to packages/editor/src/core/helpers/yjs.ts diff --git a/packages/editor/document-editor/src/hooks/use-document-editor.ts b/packages/editor/src/core/hooks/use-document-editor.ts similarity index 59% rename from packages/editor/document-editor/src/hooks/use-document-editor.ts rename to packages/editor/src/core/hooks/use-document-editor.ts index 47bd397f9..5ab5bc08f 100644 --- a/packages/editor/document-editor/src/hooks/use-document-editor.ts +++ b/packages/editor/src/core/hooks/use-document-editor.ts @@ -1,46 +1,55 @@ import { useEffect, useLayoutEffect, useMemo } from "react"; +import Collaboration from "@tiptap/extension-collaboration"; import { EditorProps } from "@tiptap/pm/view"; import { IndexeddbPersistence } from "y-indexeddb"; import * as Y from "yjs"; -// editor-core -import { EditorRefApi, IMentionHighlight, IMentionSuggestion, TFileHandler, useEditor } from "@plane/editor-core"; -// custom provider -import { CollaborationProvider } from "src/providers/collaboration-provider"; // extensions -import { DocumentEditorExtensions } from "src/ui/extensions"; +import { DragAndDrop, IssueWidget, SlashCommand } from "@/extensions"; +// hooks +import { TFileHandler, useEditor } from "@/hooks/use-editor"; +// plane editor provider +import { CollaborationProvider } from "@/plane-editor/providers"; +// plane editor types +import { TEmbedConfig } from "@/plane-editor/types"; +// types +import { EditorRefApi, IMentionHighlight, IMentionSuggestion } from "@/types"; type DocumentEditorProps = { - id: string; - fileHandler: TFileHandler; - value: Uint8Array; editorClassName: string; - onChange: (updates: Uint8Array) => void; editorProps?: EditorProps; + embedHandler?: TEmbedConfig; + fileHandler: TFileHandler; forwardedRef?: React.MutableRefObject; + handleEditorReady?: (value: boolean) => void; + id: string; mentionHandler: { highlights: () => Promise; suggestions?: () => Promise; }; - handleEditorReady?: (value: boolean) => void; + onChange: (updates: Uint8Array) => void; placeholder?: string | ((isFocused: boolean, value: string) => string); setHideDragHandleFunction: (hideDragHandlerFromDragDrop: () => void) => void; tabIndex?: number; + value: Uint8Array; }; -export const useDocumentEditor = ({ - id, - editorProps = {}, - value, - editorClassName, - fileHandler, - onChange, - forwardedRef, - tabIndex, - handleEditorReady, - mentionHandler, - placeholder, - setHideDragHandleFunction, -}: DocumentEditorProps) => { +export const useDocumentEditor = (props: DocumentEditorProps) => { + const { + editorClassName, + editorProps = {}, + embedHandler, + fileHandler, + forwardedRef, + handleEditorReady, + id, + mentionHandler, + onChange, + placeholder, + setHideDragHandleFunction, + tabIndex, + value, + } = props; + const provider = useMemo( () => new CollaborationProvider({ @@ -75,11 +84,17 @@ export const useDocumentEditor = ({ handleEditorReady, forwardedRef, mentionHandler, - extensions: DocumentEditorExtensions({ - uploadFile: fileHandler.upload, - setHideDragHandle: setHideDragHandleFunction, - provider, - }), + extensions: [ + SlashCommand(fileHandler.upload), + DragAndDrop(setHideDragHandleFunction), + embedHandler?.issue && + IssueWidget({ + widgetCallback: embedHandler.issue.widgetCallback, + }), + Collaboration.configure({ + document: provider.document, + }), + ], placeholder, tabIndex, }); diff --git a/packages/editor/document-editor/src/hooks/use-editor-markings.tsx b/packages/editor/src/core/hooks/use-editor-markings.tsx similarity index 90% rename from packages/editor/document-editor/src/hooks/use-editor-markings.tsx rename to packages/editor/src/core/hooks/use-editor-markings.tsx index 88f125a26..76d02cd68 100644 --- a/packages/editor/document-editor/src/hooks/use-editor-markings.tsx +++ b/packages/editor/src/core/hooks/use-editor-markings.tsx @@ -1,5 +1,11 @@ import { useCallback, useState } from "react"; -import { IMarking } from "src/types/editor-types"; + +export interface IMarking { + type: "heading"; + level: number; + text: string; + sequence: number; +} export const useEditorMarkings = () => { const [markings, setMarkings] = useState([]); diff --git a/packages/editor/core/src/hooks/use-editor.tsx b/packages/editor/src/core/hooks/use-editor.ts similarity index 91% rename from packages/editor/core/src/hooks/use-editor.tsx rename to packages/editor/src/core/hooks/use-editor.ts index 563cb5122..7083354ac 100644 --- a/packages/editor/core/src/hooks/use-editor.tsx +++ b/packages/editor/src/core/hooks/use-editor.ts @@ -1,17 +1,18 @@ import { useEditor as useCustomEditor, Editor } from "@tiptap/react"; import { useImperativeHandle, useRef, MutableRefObject, useState, useEffect } from "react"; -import { CoreEditorProps } from "src/ui/props"; -import { CoreEditorExtensions } from "src/ui/extensions"; import { EditorProps } from "@tiptap/pm/view"; -import { DeleteImage } from "src/types/delete-image"; -import { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion"; -import { RestoreImage } from "src/types/restore-image"; -import { UploadImage } from "src/types/upload-image"; import { Selection } from "@tiptap/pm/state"; -import { insertContentAtSavedSelection } from "src/helpers/insert-content-at-cursor-position"; -import { EditorMenuItemNames, getEditorMenuItems } from "src/ui/menus/menu-items"; -import { EditorRefApi } from "src/types/editor-ref-api"; -import { IMarking, scrollSummary } from "src/helpers/scroll-to-node"; +// components +import { EditorMenuItemNames, getEditorMenuItems } from "@/components/menus"; +// extensions +import { CoreEditorExtensions } from "@/extensions"; +// helpers +import { insertContentAtSavedSelection } from "@/helpers/insert-content-at-cursor-position"; +import { IMarking, scrollSummary } from "@/helpers/scroll-to-node"; +// props +import { CoreEditorProps } from "@/props"; +// types +import { DeleteImage, EditorRefApi, IMentionHighlight, IMentionSuggestion, RestoreImage, UploadImage } from "@/types"; export type TFileHandler = { cancel: () => void; diff --git a/packages/editor/core/src/hooks/use-read-only-editor.tsx b/packages/editor/src/core/hooks/use-read-only-editor.ts similarity index 87% rename from packages/editor/core/src/hooks/use-read-only-editor.tsx rename to packages/editor/src/core/hooks/use-read-only-editor.ts index 8b16d1e76..fcaf0c6dd 100644 --- a/packages/editor/core/src/hooks/use-read-only-editor.tsx +++ b/packages/editor/src/core/hooks/use-read-only-editor.ts @@ -1,11 +1,14 @@ -import { useEditor as useCustomEditor, Editor } from "@tiptap/react"; import { useImperativeHandle, useRef, MutableRefObject, useEffect } from "react"; -import { CoreReadOnlyEditorExtensions } from "src/ui/read-only/extensions"; -import { CoreReadOnlyEditorProps } from "src/ui/read-only/props"; import { EditorProps } from "@tiptap/pm/view"; -import { EditorReadOnlyRefApi } from "src/types/editor-ref-api"; -import { IMarking, scrollSummary } from "src/helpers/scroll-to-node"; -import { IMentionHighlight } from "src/types/mention-suggestion"; +import { useEditor as useCustomEditor, Editor } from "@tiptap/react"; +// extensions +import { CoreReadOnlyEditorExtensions } from "@/extensions"; +// helpers +import { IMarking, scrollSummary } from "@/helpers/scroll-to-node"; +// props +import { CoreReadOnlyEditorProps } from "@/props"; +// types +import { EditorReadOnlyRefApi, IMentionHighlight } from "@/types"; interface CustomReadOnlyEditorProps { initialValue: string; diff --git a/packages/editor/core/src/ui/plugins/image/constants.ts b/packages/editor/src/core/plugins/image/constants.ts similarity index 100% rename from packages/editor/core/src/ui/plugins/image/constants.ts rename to packages/editor/src/core/plugins/image/constants.ts diff --git a/packages/editor/core/src/ui/plugins/image/delete-image.ts b/packages/editor/src/core/plugins/image/delete-image.ts similarity index 89% rename from packages/editor/core/src/ui/plugins/image/delete-image.ts rename to packages/editor/src/core/plugins/image/delete-image.ts index 645dda99e..8dc1bf072 100644 --- a/packages/editor/core/src/ui/plugins/image/delete-image.ts +++ b/packages/editor/src/core/plugins/image/delete-image.ts @@ -1,9 +1,9 @@ -import { EditorState, Plugin, Transaction } from "@tiptap/pm/state"; -import { DeleteImage } from "src/types/delete-image"; import { Editor } from "@tiptap/core"; - -import { type ImageNode } from "src/ui/plugins/image/types/image-node"; -import { deleteKey, IMAGE_NODE_TYPE } from "src/ui/plugins/image/constants"; +import { EditorState, Plugin, Transaction } from "@tiptap/pm/state"; +// plugins +import { IMAGE_NODE_TYPE, deleteKey, type ImageNode } from "@/plugins/image"; +// types +import { DeleteImage } from "@/types"; export const TrackImageDeletionPlugin = (editor: Editor, deleteImage: DeleteImage): Plugin => new Plugin({ diff --git a/packages/editor/core/src/ui/plugins/image/image-upload-handler.ts b/packages/editor/src/core/plugins/image/image-upload-handler.ts similarity index 93% rename from packages/editor/core/src/ui/plugins/image/image-upload-handler.ts rename to packages/editor/src/core/plugins/image/image-upload-handler.ts index eb7021819..d0bd339da 100644 --- a/packages/editor/core/src/ui/plugins/image/image-upload-handler.ts +++ b/packages/editor/src/core/plugins/image/image-upload-handler.ts @@ -1,14 +1,10 @@ -import { type UploadImage } from "src/types/upload-image"; - -// utilities -import { v4 as uuidv4 } from "uuid"; - -// types -import { isFileValid } from "src/ui/plugins/image/utils/validate-file"; import { Editor } from "@tiptap/core"; import { EditorView } from "@tiptap/pm/view"; -import { uploadKey } from "./constants"; -import { removePlaceholder, findPlaceholder } from "./utils/placeholder"; +import { v4 as uuidv4 } from "uuid"; +// plugins +import { findPlaceholder, isFileValid, removePlaceholder, uploadKey } from "@/plugins/image"; +// types +import { UploadImage } from "@/types"; export async function startImageUpload( editor: Editor, diff --git a/packages/editor/src/core/plugins/image/index.ts b/packages/editor/src/core/plugins/image/index.ts new file mode 100644 index 000000000..e5a290abe --- /dev/null +++ b/packages/editor/src/core/plugins/image/index.ts @@ -0,0 +1,7 @@ +export * from "./types"; +export * from "./utils"; +export * from "./constants"; +export * from "./delete-image"; +export * from "./image-upload-handler"; +export * from "./restore-image"; +export * from "./upload-image"; diff --git a/packages/editor/core/src/ui/plugins/image/restore-image.ts b/packages/editor/src/core/plugins/image/restore-image.ts similarity index 92% rename from packages/editor/core/src/ui/plugins/image/restore-image.ts rename to packages/editor/src/core/plugins/image/restore-image.ts index 61a7a7a34..036df9b88 100644 --- a/packages/editor/core/src/ui/plugins/image/restore-image.ts +++ b/packages/editor/src/core/plugins/image/restore-image.ts @@ -1,9 +1,9 @@ import { Editor } from "@tiptap/core"; import { EditorState, Plugin, Transaction } from "@tiptap/pm/state"; -import { RestoreImage } from "src/types/restore-image"; - -import { restoreKey, IMAGE_NODE_TYPE } from "./constants"; -import { type ImageNode } from "./types/image-node"; +// plugins +import { IMAGE_NODE_TYPE, ImageNode, restoreKey } from "@/plugins/image"; +// types +import { RestoreImage } from "@/types"; export const TrackImageRestorationPlugin = (editor: Editor, restoreImage: RestoreImage): Plugin => new Plugin({ diff --git a/packages/editor/core/src/ui/plugins/image/types/image-node.ts b/packages/editor/src/core/plugins/image/types/image-node.ts similarity index 100% rename from packages/editor/core/src/ui/plugins/image/types/image-node.ts rename to packages/editor/src/core/plugins/image/types/image-node.ts diff --git a/packages/editor/src/core/plugins/image/types/index.ts b/packages/editor/src/core/plugins/image/types/index.ts new file mode 100644 index 000000000..2fddf3bf6 --- /dev/null +++ b/packages/editor/src/core/plugins/image/types/index.ts @@ -0,0 +1 @@ +export * from "./image-node"; diff --git a/packages/editor/core/src/ui/plugins/image/upload-image.ts b/packages/editor/src/core/plugins/image/upload-image.ts similarity index 94% rename from packages/editor/core/src/ui/plugins/image/upload-image.ts rename to packages/editor/src/core/plugins/image/upload-image.ts index 554e37de2..e3db70d13 100644 --- a/packages/editor/core/src/ui/plugins/image/upload-image.ts +++ b/packages/editor/src/core/plugins/image/upload-image.ts @@ -1,12 +1,8 @@ import { Editor } from "@tiptap/core"; import { Plugin } from "@tiptap/pm/state"; import { Decoration, DecorationSet, EditorView } from "@tiptap/pm/view"; - -// utils -import { removePlaceholder } from "src/ui/plugins/image/utils/placeholder"; - -// constants -import { uploadKey } from "src/ui/plugins/image/constants"; +// plugins +import { removePlaceholder, uploadKey } from "@/plugins/image"; export const UploadImagesPlugin = (editor: Editor, cancelUploadImage?: () => void) => { let currentView: EditorView | null = null; diff --git a/packages/editor/src/core/plugins/image/utils/index.ts b/packages/editor/src/core/plugins/image/utils/index.ts new file mode 100644 index 000000000..217ec4117 --- /dev/null +++ b/packages/editor/src/core/plugins/image/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./placeholder"; +export * from "./validate-file"; diff --git a/packages/editor/core/src/ui/plugins/image/utils/placeholder.ts b/packages/editor/src/core/plugins/image/utils/placeholder.ts similarity index 91% rename from packages/editor/core/src/ui/plugins/image/utils/placeholder.ts rename to packages/editor/src/core/plugins/image/utils/placeholder.ts index 9636da4a7..e69882300 100644 --- a/packages/editor/core/src/ui/plugins/image/utils/placeholder.ts +++ b/packages/editor/src/core/plugins/image/utils/placeholder.ts @@ -1,7 +1,7 @@ import { Editor } from "@tiptap/core"; import { EditorState } from "@tiptap/pm/state"; import { DecorationSet, EditorView } from "@tiptap/pm/view"; -import { uploadKey } from "src/ui/plugins/image/constants"; +import { uploadKey } from "src/core/plugins/image/constants"; export function findPlaceholder(state: EditorState, id: string): number | null { const decos = uploadKey.getState(state) as DecorationSet; diff --git a/packages/editor/core/src/ui/plugins/image/utils/validate-file.ts b/packages/editor/src/core/plugins/image/utils/validate-file.ts similarity index 100% rename from packages/editor/core/src/ui/plugins/image/utils/validate-file.ts rename to packages/editor/src/core/plugins/image/utils/validate-file.ts diff --git a/packages/editor/src/core/props/index.ts b/packages/editor/src/core/props/index.ts new file mode 100644 index 000000000..eaa89f059 --- /dev/null +++ b/packages/editor/src/core/props/index.ts @@ -0,0 +1,2 @@ +export * from "./props"; +export * from "./read-only"; diff --git a/packages/editor/core/src/ui/props.tsx b/packages/editor/src/core/props/props.tsx similarity index 93% rename from packages/editor/core/src/ui/props.tsx rename to packages/editor/src/core/props/props.tsx index 32d1510c7..11e829162 100644 --- a/packages/editor/core/src/ui/props.tsx +++ b/packages/editor/src/core/props/props.tsx @@ -1,5 +1,6 @@ import { EditorProps } from "@tiptap/pm/view"; -import { cn } from "src/lib/utils"; +// helpers +import { cn } from "@/helpers/common"; export function CoreEditorProps(editorClassName: string): EditorProps { return { diff --git a/packages/editor/core/src/ui/read-only/props.tsx b/packages/editor/src/core/props/read-only.tsx similarity index 85% rename from packages/editor/core/src/ui/read-only/props.tsx rename to packages/editor/src/core/props/read-only.tsx index bd9b6713b..ea583938f 100644 --- a/packages/editor/core/src/ui/read-only/props.tsx +++ b/packages/editor/src/core/props/read-only.tsx @@ -1,5 +1,6 @@ import { EditorProps } from "@tiptap/pm/view"; -import { cn } from "src/lib/utils"; +// helpers +import { cn } from "@/helpers/common"; export const CoreReadOnlyEditorProps = (editorClassName: string): EditorProps => ({ attributes: { diff --git a/packages/editor/src/core/types/editor.ts b/packages/editor/src/core/types/editor.ts new file mode 100644 index 000000000..a7d167a3a --- /dev/null +++ b/packages/editor/src/core/types/editor.ts @@ -0,0 +1,61 @@ +// types +import { EditorMenuItemNames } from "@/components/menus"; +import { IMarking } from "@/helpers/scroll-to-node"; +import { TFileHandler } from "@/hooks/use-editor"; +import { IMentionHighlight, IMentionSuggestion } from "@/types"; + +export type EditorReadOnlyRefApi = { + getMarkDown: () => string; + getHTML: () => string; + clearEditor: () => void; + setEditorValue: (content: string) => void; + scrollSummary: (marking: IMarking) => void; +}; + +export interface EditorRefApi extends EditorReadOnlyRefApi { + setEditorValueAtCursorPosition: (content: string) => void; + executeMenuItemCommand: (itemName: EditorMenuItemNames) => void; + isMenuItemActive: (itemName: EditorMenuItemNames) => boolean; + onStateChange: (callback: () => void) => () => void; + setFocusAtPosition: (position: number) => void; + isEditorReadyToDiscard: () => boolean; +} + +export interface IEditorProps { + containerClassName?: string; + editorClassName?: string; + fileHandler: TFileHandler; + forwardedRef?: React.MutableRefObject; + id?: string; + initialValue: string; + mentionHandler: { + highlights: () => Promise; + suggestions?: () => Promise; + }; + onChange?: (json: object, html: string) => void; + onEnterKeyPress?: (e?: any) => void; + placeholder?: string | ((isFocused: boolean, value: string) => string); + tabIndex?: number; + value?: string | null; +} + +export interface ILiteTextEditor extends IEditorProps {} + +export interface IRichTextEditor extends IEditorProps { + dragDropEnabled?: boolean; +} + +export interface IReadOnlyEditorProps { + containerClassName?: string; + editorClassName?: string; + forwardedRef?: React.MutableRefObject; + initialValue: string; + mentionHandler: { + highlights: () => Promise; + }; + tabIndex?: number; +} + +export interface ILiteTextReadOnlyEditor extends IReadOnlyEditorProps {} + +export interface IRichTextReadOnlyEditor extends IReadOnlyEditorProps {} diff --git a/packages/editor/src/core/types/embed.ts b/packages/editor/src/core/types/embed.ts new file mode 100644 index 000000000..3acd662be --- /dev/null +++ b/packages/editor/src/core/types/embed.ts @@ -0,0 +1,8 @@ +export type TEmbedItem = { + id: string; + title: string; + subTitle: string; + icon: React.ReactNode; + projectId: string; + workspaceSlug: string; +}; diff --git a/packages/editor/src/core/types/image.ts b/packages/editor/src/core/types/image.ts new file mode 100644 index 000000000..c1b174a48 --- /dev/null +++ b/packages/editor/src/core/types/image.ts @@ -0,0 +1,5 @@ +export type DeleteImage = (assetUrlWithWorkspaceId: string) => Promise; + +export type RestoreImage = (assetUrlWithWorkspaceId: string) => Promise; + +export type UploadImage = (file: File) => Promise; diff --git a/packages/editor/src/core/types/index.ts b/packages/editor/src/core/types/index.ts new file mode 100644 index 000000000..f4dd89412 --- /dev/null +++ b/packages/editor/src/core/types/index.ts @@ -0,0 +1,5 @@ +export * from "./editor"; +export * from "./embed"; +export * from "./image"; +export * from "./mention-suggestion"; +export * from "./slash-commands-suggestion"; diff --git a/packages/editor/core/src/types/mention-suggestion.ts b/packages/editor/src/core/types/mention-suggestion.ts similarity index 67% rename from packages/editor/core/src/types/mention-suggestion.ts rename to packages/editor/src/core/types/mention-suggestion.ts index aa2ad4ba2..a51bed704 100644 --- a/packages/editor/core/src/types/mention-suggestion.ts +++ b/packages/editor/src/core/types/mention-suggestion.ts @@ -1,4 +1,3 @@ -import { Editor, Range } from "@tiptap/react"; export type IMentionSuggestion = { id: string; type: string; @@ -10,9 +9,4 @@ export type IMentionSuggestion = { redirect_uri: string; }; -export type CommandProps = { - editor: Editor; - range: Range; -}; - export type IMentionHighlight = string; diff --git a/packages/editor/core/src/types/slash-commands-suggestion.ts b/packages/editor/src/core/types/slash-commands-suggestion.ts similarity index 100% rename from packages/editor/core/src/types/slash-commands-suggestion.ts rename to packages/editor/src/core/types/slash-commands-suggestion.ts diff --git a/packages/editor/src/ee/providers/index.ts b/packages/editor/src/ee/providers/index.ts new file mode 100644 index 000000000..3f53c1e7a --- /dev/null +++ b/packages/editor/src/ee/providers/index.ts @@ -0,0 +1 @@ +export * from "src/ce/providers"; diff --git a/packages/editor/src/ee/types/index.ts b/packages/editor/src/ee/types/index.ts new file mode 100644 index 000000000..00cebc05e --- /dev/null +++ b/packages/editor/src/ee/types/index.ts @@ -0,0 +1 @@ +export * from "src/ce/types"; diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts new file mode 100644 index 000000000..1dae4e8b3 --- /dev/null +++ b/packages/editor/src/index.ts @@ -0,0 +1,37 @@ +// styles +// import "./styles/tailwind.css"; +import "src/styles/editor.css"; +import "src/styles/table.css"; +import "src/styles/github-dark.css"; +import "src/styles/drag-drop.css"; + +// editors +export { + DocumentEditorWithRef, + DocumentReadOnlyEditorWithRef, + LiteTextEditorWithRef, + LiteTextReadOnlyEditorWithRef, + RichTextEditorWithRef, + RichTextReadOnlyEditorWithRef, +} from "@/components/editors"; + +export { isCellSelection } from "@/extensions/table/table/utilities/is-cell-selection"; + +// helpers +export * from "@/helpers/common"; +export * from "@/helpers/editor-commands"; +export * from "@/helpers/yjs"; +export * from "@/extensions/table/table"; +export { startImageUpload } from "@/plugins/image"; + +// components +export * from "@/components/menus"; + +// hooks +export { useEditor } from "@/hooks/use-editor"; +export { type IMarking, useEditorMarkings } from "@/hooks/use-editor-markings"; +export { useReadOnlyEditor } from "@/hooks/use-read-only-editor"; + +// types +export type { CustomEditorProps, TFileHandler } from "@/hooks/use-editor"; +export * from "@/types"; diff --git a/packages/editor/extensions/src/styles/drag-drop.css b/packages/editor/src/styles/drag-drop.css similarity index 100% rename from packages/editor/extensions/src/styles/drag-drop.css rename to packages/editor/src/styles/drag-drop.css diff --git a/packages/editor/core/src/styles/editor.css b/packages/editor/src/styles/editor.css similarity index 100% rename from packages/editor/core/src/styles/editor.css rename to packages/editor/src/styles/editor.css diff --git a/packages/editor/core/src/styles/github-dark.css b/packages/editor/src/styles/github-dark.css similarity index 100% rename from packages/editor/core/src/styles/github-dark.css rename to packages/editor/src/styles/github-dark.css diff --git a/packages/editor/core/src/styles/table.css b/packages/editor/src/styles/table.css similarity index 100% rename from packages/editor/core/src/styles/table.css rename to packages/editor/src/styles/table.css diff --git a/packages/editor/core/src/styles/tailwind.css b/packages/editor/src/styles/tailwind.css similarity index 100% rename from packages/editor/core/src/styles/tailwind.css rename to packages/editor/src/styles/tailwind.css diff --git a/packages/editor/core/tailwind.config.js b/packages/editor/tailwind.config.js similarity index 100% rename from packages/editor/core/tailwind.config.js rename to packages/editor/tailwind.config.js diff --git a/packages/editor/tsconfig.json b/packages/editor/tsconfig.json new file mode 100644 index 000000000..cfe8401f6 --- /dev/null +++ b/packages/editor/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "tsconfig/react-library.json", + "include": ["src/**/*", "index.d.ts"], + "exclude": ["dist", "build", "node_modules"], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["src/core/*"], + "@/styles/*": ["src/styles/*"], + "@/plane-editor/*": ["src/ce/*"] + } + } +} diff --git a/packages/editor/core/tsup.config.ts b/packages/editor/tsup.config.ts similarity index 100% rename from packages/editor/core/tsup.config.ts rename to packages/editor/tsup.config.ts diff --git a/space/core/components/editor/lite-text-editor.tsx b/space/core/components/editor/lite-text-editor.tsx index b911ebecb..3cc8347a1 100644 --- a/space/core/components/editor/lite-text-editor.tsx +++ b/space/core/components/editor/lite-text-editor.tsx @@ -1,6 +1,6 @@ import React from "react"; // editor -import { EditorRefApi, ILiteTextEditor, LiteTextEditorWithRef } from "@plane/lite-text-editor"; +import { EditorRefApi, ILiteTextEditor, LiteTextEditorWithRef } from "@plane/editor"; // components import { IssueCommentToolbar } from "@/components/editor"; // helpers 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 6b16a0b07..0659939ba 100644 --- a/space/core/components/editor/lite-text-read-only-editor.tsx +++ b/space/core/components/editor/lite-text-read-only-editor.tsx @@ -1,6 +1,6 @@ import React from "react"; // editor -import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "@plane/lite-text-editor"; +import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "@plane/editor"; // helpers import { cn } from "@/helpers/common.helper"; // hooks 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 56694e91f..3fd7cae57 100644 --- a/space/core/components/editor/rich-text-read-only-editor.tsx +++ b/space/core/components/editor/rich-text-read-only-editor.tsx @@ -1,6 +1,6 @@ import React from "react"; // editor -import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/rich-text-editor"; +import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/editor"; // helpers import { cn } from "@/helpers/common.helper"; // hooks diff --git a/space/core/components/editor/toolbar.tsx b/space/core/components/editor/toolbar.tsx index 0140a46b6..f69ce7b3f 100644 --- a/space/core/components/editor/toolbar.tsx +++ b/space/core/components/editor/toolbar.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState, useCallback } from "react"; // editor -import { EditorMenuItemNames, EditorRefApi } from "@plane/lite-text-editor"; +import { EditorMenuItemNames, EditorRefApi } from "@plane/editor"; // ui import { Button, Tooltip } from "@plane/ui"; // constants diff --git a/space/core/components/issues/peek-overview/comment/add-comment.tsx b/space/core/components/issues/peek-overview/comment/add-comment.tsx index 3e86a084f..cf11aa333 100644 --- a/space/core/components/issues/peek-overview/comment/add-comment.tsx +++ b/space/core/components/issues/peek-overview/comment/add-comment.tsx @@ -4,7 +4,7 @@ import React, { useRef } from "react"; import { observer } from "mobx-react"; import { useForm, Controller } from "react-hook-form"; // editor -import { EditorRefApi } from "@plane/lite-text-editor"; +import { EditorRefApi } from "@plane/editor"; // ui import { TOAST_TYPE, setToast } from "@plane/ui"; // editor components diff --git a/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx b/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx index c065480e9..2bdd8ca8f 100644 --- a/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx +++ b/space/core/components/issues/peek-overview/comment/comment-detail-card.tsx @@ -4,7 +4,7 @@ import { Controller, useForm } from "react-hook-form"; import { Check, MessageSquare, MoreVertical, X } from "lucide-react"; import { Menu, Transition } from "@headlessui/react"; // components -import { EditorRefApi } from "@plane/lite-text-editor"; +import { EditorRefApi } from "@plane/editor"; import { LiteTextEditor, LiteTextReadOnlyEditor } from "@/components/editor"; import { CommentReactions } from "@/components/issues/peek-overview"; // helpers diff --git a/space/core/constants/editor.ts b/space/core/constants/editor.ts index eb8b99495..698faf8cb 100644 --- a/space/core/constants/editor.ts +++ b/space/core/constants/editor.ts @@ -19,7 +19,7 @@ import { Underline, } from "lucide-react"; // editor -import { EditorMenuItemNames } from "@plane/lite-text-editor"; +import { EditorMenuItemNames } from "@plane/editor"; type TEditorTypes = "lite" | "document"; diff --git a/space/core/store/mentions.store.ts b/space/core/store/mentions.store.ts index 77228595c..977df4221 100644 --- a/space/core/store/mentions.store.ts +++ b/space/core/store/mentions.store.ts @@ -1,6 +1,6 @@ import { computed, makeObservable } from "mobx"; // editor -import { IMentionHighlight } from "@plane/lite-text-editor"; +import { IMentionHighlight } from "@plane/editor"; // store import { CoreRootStore } from "@/store/root.store"; diff --git a/space/package.json b/space/package.json index 0e2d62eab..fdf156e9f 100644 --- a/space/package.json +++ b/space/package.json @@ -17,9 +17,7 @@ "@emotion/styled": "^11.11.0", "@headlessui/react": "^1.7.13", "@mui/material": "^5.14.1", - "@plane/document-editor": "*", - "@plane/lite-text-editor": "*", - "@plane/rich-text-editor": "*", + "@plane/editor": "*", "@plane/types": "*", "@plane/ui": "*", "@sentry/nextjs": "^8", diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx index bbd3f4c06..753b2ae58 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx @@ -6,7 +6,7 @@ import Link from "next/link"; import { useParams } from "next/navigation"; import useSWR from "swr"; // document-editor -import { EditorRefApi, useEditorMarkings } from "@plane/document-editor"; +import { EditorRefApi, useEditorMarkings } from "@plane/editor"; // types import { TPage } from "@plane/types"; // ui diff --git a/web/ce/components/pages/editor/embed/index.ts b/web/ce/components/pages/editor/embed/index.ts new file mode 100644 index 000000000..f30596cb0 --- /dev/null +++ b/web/ce/components/pages/editor/embed/index.ts @@ -0,0 +1 @@ +export * from "./issue-embed"; diff --git a/web/ce/components/pages/editor/embed/issue-embed.tsx b/web/ce/components/pages/editor/embed/issue-embed.tsx new file mode 100644 index 000000000..dc06f4f9d --- /dev/null +++ b/web/ce/components/pages/editor/embed/issue-embed.tsx @@ -0,0 +1,30 @@ +import { Crown } from "lucide-react"; +// ui +import { Button } from "@plane/ui"; + +export const IssueEmbedCard: React.FC = (props) => ( +
+
+ {props.node?.attrs?.project_identifier}-{props?.node?.attrs?.sequence_id} +
+
+
+
+
+ +
+
+ Embed and access issues in pages seamlessly, upgrade to plane pro now. +
+
+ + + +
+
+
+); diff --git a/web/ce/components/pages/editor/index.ts b/web/ce/components/pages/editor/index.ts new file mode 100644 index 000000000..12b3c5295 --- /dev/null +++ b/web/ce/components/pages/editor/index.ts @@ -0,0 +1 @@ +export * from "./embed"; diff --git a/web/ce/components/pages/index.ts b/web/ce/components/pages/index.ts index 5ce39384e..6f3d30c9a 100644 --- a/web/ce/components/pages/index.ts +++ b/web/ce/components/pages/index.ts @@ -1 +1,2 @@ +export * from "./editor"; export * from "./extra-actions"; 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 6fde70d6e..9f1608d5c 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,6 +1,6 @@ import React from "react"; // editor -import { EditorRefApi, ILiteTextEditor, LiteTextEditorWithRef } from "@plane/lite-text-editor"; +import { EditorRefApi, ILiteTextEditor, LiteTextEditorWithRef } from "@plane/editor"; // types import { IUserLite } from "@plane/types"; // components diff --git a/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx b/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx index 8ee95b585..5e8dfbd7a 100644 --- a/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx +++ b/web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx @@ -1,6 +1,6 @@ import React from "react"; // editor -import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "@plane/lite-text-editor"; +import { EditorReadOnlyRefApi, ILiteTextReadOnlyEditor, LiteTextReadOnlyEditorWithRef } from "@plane/editor"; // helpers import { cn } from "@/helpers/common.helper"; // hooks diff --git a/web/core/components/editor/lite-text-editor/toolbar.tsx b/web/core/components/editor/lite-text-editor/toolbar.tsx index e053e9b0d..69affb67e 100644 --- a/web/core/components/editor/lite-text-editor/toolbar.tsx +++ b/web/core/components/editor/lite-text-editor/toolbar.tsx @@ -3,8 +3,7 @@ import React, { useEffect, useState, useCallback } from "react"; import { Globe2, Lock, LucideIcon } from "lucide-react"; // editor -import { EditorMenuItemNames } from "@plane/document-editor"; -import { EditorRefApi } from "@plane/lite-text-editor"; +import { EditorMenuItemNames, EditorRefApi } from "@plane/editor"; // ui import { Button, Tooltip } from "@plane/ui"; // constants 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 0324d1f17..68adbb9fd 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,6 +1,6 @@ import React, { forwardRef } from "react"; // editor -import { EditorRefApi, IRichTextEditor, RichTextEditorWithRef } from "@plane/rich-text-editor"; +import { EditorRefApi, IRichTextEditor, RichTextEditorWithRef } from "@plane/editor"; // types import { IUserLite } from "@plane/types"; // helpers 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 4aead5469..d97eba98a 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 @@ -1,6 +1,6 @@ import React from "react"; // editor -import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/rich-text-editor"; +import { EditorReadOnlyRefApi, IRichTextReadOnlyEditor, RichTextReadOnlyEditorWithRef } from "@plane/editor"; // helpers import { cn } from "@/helpers/common.helper"; // hooks diff --git a/web/core/components/inbox/modals/create-edit-modal/create-root.tsx b/web/core/components/inbox/modals/create-edit-modal/create-root.tsx index b6456bac1..36574b513 100644 --- a/web/core/components/inbox/modals/create-edit-modal/create-root.tsx +++ b/web/core/components/inbox/modals/create-edit-modal/create-root.tsx @@ -4,7 +4,7 @@ import { FC, FormEvent, useCallback, useRef, useState } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; // editor -import { EditorRefApi } from "@plane/rich-text-editor"; +import { EditorRefApi } from "@plane/editor"; // types import { TIssue } from "@plane/types"; import { Button, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui"; diff --git a/web/core/components/inbox/modals/create-edit-modal/edit-root.tsx b/web/core/components/inbox/modals/create-edit-modal/edit-root.tsx index 000426b6c..05ff4f1e5 100644 --- a/web/core/components/inbox/modals/create-edit-modal/edit-root.tsx +++ b/web/core/components/inbox/modals/create-edit-modal/edit-root.tsx @@ -4,7 +4,7 @@ import { FC, useCallback, useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; // editor -import { EditorRefApi } from "@plane/rich-text-editor"; +import { EditorRefApi } from "@plane/editor"; // types import { TIssue } from "@plane/types"; // ui diff --git a/web/core/components/inbox/modals/create-edit-modal/issue-description.tsx b/web/core/components/inbox/modals/create-edit-modal/issue-description.tsx index 1cbfaded5..7b9ef6749 100644 --- a/web/core/components/inbox/modals/create-edit-modal/issue-description.tsx +++ b/web/core/components/inbox/modals/create-edit-modal/issue-description.tsx @@ -2,8 +2,11 @@ import { FC, RefObject } from "react"; import { observer } from "mobx-react"; -import { EditorRefApi } from "@plane/rich-text-editor"; +// editor +import { EditorRefApi } from "@plane/editor"; +// types import { TIssue } from "@plane/types"; +// ui import { Loader } from "@plane/ui"; // components import { RichTextEditor } from "@/components/editor/rich-text-editor/rich-text-editor"; diff --git a/web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx b/web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx index 7413edf08..29945dda9 100644 --- a/web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx +++ b/web/core/components/issues/issue-detail/issue-activity/comments/comment-card.tsx @@ -4,7 +4,7 @@ import { FC, useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; import { useForm } from "react-hook-form"; import { Check, Globe2, Lock, Pencil, Trash2, X } from "lucide-react"; -import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/lite-text-editor"; +import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor"; import { TIssueComment } from "@plane/types"; // ui import { CustomMenu } from "@plane/ui"; diff --git a/web/core/components/issues/issue-layouts/list/list-group.tsx b/web/core/components/issues/issue-layouts/list/list-group.tsx index 0bca2a712..fa49b79b8 100644 --- a/web/core/components/issues/issue-layouts/list/list-group.tsx +++ b/web/core/components/issues/issue-layouts/list/list-group.tsx @@ -4,7 +4,7 @@ import { MutableRefObject, useEffect, useRef, useState } from "react"; import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react"; -import { cn } from "@plane/editor-core"; +import { cn } from "@plane/editor"; // plane packages import { IGroupByColumn, @@ -59,7 +59,7 @@ interface Props { showEmptyGroup?: boolean; loadMoreIssues: (groupId?: string) => void; selectionHelpers: TSelectionHelper; -}; +} export const ListGroup = observer((props: Props) => { const { diff --git a/web/core/components/issues/issue-modal/form.tsx b/web/core/components/issues/issue-modal/form.tsx index 385dda43f..990509e5e 100644 --- a/web/core/components/issues/issue-modal/form.tsx +++ b/web/core/components/issues/issue-modal/form.tsx @@ -5,7 +5,9 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Controller, useForm } from "react-hook-form"; import { LayoutPanelTop, Sparkle, X } from "lucide-react"; -import { EditorRefApi } from "@plane/rich-text-editor"; +// editor +import { EditorRefApi } from "@plane/editor"; +// types import type { TIssue, ISearchIssueResponse } from "@plane/types"; // hooks import { Button, CustomMenu, Input, Loader, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui"; diff --git a/web/core/components/modules/module-view-header.tsx b/web/core/components/modules/module-view-header.tsx index 71418a2cc..3038f0bc7 100644 --- a/web/core/components/modules/module-view-header.tsx +++ b/web/core/components/modules/module-view-header.tsx @@ -6,7 +6,7 @@ import { useParams } from "next/navigation"; // icons import { ListFilter, Search, X } from "lucide-react"; // helpers -import { cn } from "@plane/editor-core"; +import { cn } from "@plane/editor"; // types import { TModuleFilters } from "@plane/types"; // ui diff --git a/web/core/components/pages/editor/editor-body.tsx b/web/core/components/pages/editor/editor-body.tsx index 3f859f1a2..b0032c2a1 100644 --- a/web/core/components/pages/editor/editor-body.tsx +++ b/web/core/components/pages/editor/editor-body.tsx @@ -8,7 +8,7 @@ import { EditorReadOnlyRefApi, EditorRefApi, IMarking, -} from "@plane/document-editor"; +} from "@plane/editor"; // types import { IUserLite } from "@plane/types"; // components @@ -19,6 +19,8 @@ import { cn } from "@/helpers/common.helper"; import { useMember, useMention, useUser, useWorkspace } from "@/hooks/store"; import { usePageDescription } from "@/hooks/use-page-description"; import { usePageFilters } from "@/hooks/use-page-filters"; +// plane web components +import { IssueEmbedCard } from "@/plane-web/components/pages"; // services import { FileService } from "@/services/file.service"; // store @@ -138,6 +140,11 @@ export const PageEditorBody: React.FC = observer((props) => { highlights: mentionHighlights, suggestions: mentionSuggestions, }} + embedHandler={{ + issue: { + widgetCallback: () => , + }, + }} /> ) : ( = observer((props) => { mentionHandler={{ highlights: mentionHighlights, }} + embedHandler={{ + issue: { + widgetCallback: () => , + }, + }} /> )} diff --git a/web/core/components/pages/editor/header/extra-options.tsx b/web/core/components/pages/editor/header/extra-options.tsx index 3a244b074..bd022eed2 100644 --- a/web/core/components/pages/editor/header/extra-options.tsx +++ b/web/core/components/pages/editor/header/extra-options.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { Lock, Sparkle } from "lucide-react"; // editor -import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/document-editor"; +import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor"; // ui import { ArchiveIcon } from "@plane/ui"; // components diff --git a/web/core/components/pages/editor/header/mobile-root.tsx b/web/core/components/pages/editor/header/mobile-root.tsx index 4a73d0a55..166a4b7dc 100644 --- a/web/core/components/pages/editor/header/mobile-root.tsx +++ b/web/core/components/pages/editor/header/mobile-root.tsx @@ -1,5 +1,5 @@ import { observer } from "mobx-react"; -import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/document-editor"; +import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/editor"; // components import { PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages"; // hooks diff --git a/web/core/components/pages/editor/header/options-dropdown.tsx b/web/core/components/pages/editor/header/options-dropdown.tsx index 67a477e8b..0d0172e00 100644 --- a/web/core/components/pages/editor/header/options-dropdown.tsx +++ b/web/core/components/pages/editor/header/options-dropdown.tsx @@ -4,7 +4,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ArchiveRestoreIcon, Clipboard, Copy, Link, Lock, LockOpen } from "lucide-react"; // document editor -import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/document-editor"; +import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/editor"; // ui import { ArchiveIcon, CustomMenu, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui"; // helpers diff --git a/web/core/components/pages/editor/header/root.tsx b/web/core/components/pages/editor/header/root.tsx index d8051a7d2..2b58e7c76 100644 --- a/web/core/components/pages/editor/header/root.tsx +++ b/web/core/components/pages/editor/header/root.tsx @@ -1,5 +1,5 @@ import { observer } from "mobx-react"; -import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/document-editor"; +import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/editor"; // components import { PageEditorMobileHeaderRoot, PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages"; // helpers diff --git a/web/core/components/pages/editor/header/toolbar.tsx b/web/core/components/pages/editor/header/toolbar.tsx index 4cbead1ab..9ca72434c 100644 --- a/web/core/components/pages/editor/header/toolbar.tsx +++ b/web/core/components/pages/editor/header/toolbar.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useState, useCallback } from "react"; import { Check, ChevronDown } from "lucide-react"; // editor -import { EditorMenuItemNames, EditorRefApi } from "@plane/document-editor"; +import { EditorMenuItemNames, EditorRefApi } from "@plane/editor"; // ui import { CustomMenu, Tooltip } from "@plane/ui"; // constants diff --git a/web/core/components/pages/editor/summary/content-browser.tsx b/web/core/components/pages/editor/summary/content-browser.tsx index 00fd06a66..7f7ad4053 100644 --- a/web/core/components/pages/editor/summary/content-browser.tsx +++ b/web/core/components/pages/editor/summary/content-browser.tsx @@ -1,5 +1,5 @@ // types -import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/document-editor"; +import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/editor"; import { OutlineHeading1, OutlineHeading2, OutlineHeading3 } from "./heading-components"; type Props = { diff --git a/web/core/components/pages/editor/summary/heading-components.tsx b/web/core/components/pages/editor/summary/heading-components.tsx index 6807f36b7..5ed1752de 100644 --- a/web/core/components/pages/editor/summary/heading-components.tsx +++ b/web/core/components/pages/editor/summary/heading-components.tsx @@ -1,5 +1,5 @@ // document editor -import { IMarking } from "@plane/document-editor"; +import { IMarking } from "@plane/editor"; type HeadingProps = { marking: IMarking; diff --git a/web/core/components/pages/editor/summary/popover.tsx b/web/core/components/pages/editor/summary/popover.tsx index 4f9654c96..ccb6b7b8c 100644 --- a/web/core/components/pages/editor/summary/popover.tsx +++ b/web/core/components/pages/editor/summary/popover.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { usePopper } from "react-popper"; import { List } from "lucide-react"; // document editor -import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/document-editor"; +import { EditorReadOnlyRefApi, EditorRefApi, IMarking } from "@plane/editor"; // helpers import { cn } from "@/helpers/common.helper"; // components diff --git a/web/core/components/pages/editor/title.tsx b/web/core/components/pages/editor/title.tsx index 85b7be22d..59502ba81 100644 --- a/web/core/components/pages/editor/title.tsx +++ b/web/core/components/pages/editor/title.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { observer } from "mobx-react"; // editor -import { EditorRefApi } from "@plane/document-editor"; +import { EditorRefApi } from "@plane/editor"; // ui import { TextArea } from "@plane/ui"; // helpers diff --git a/web/core/constants/editor.ts b/web/core/constants/editor.ts index 2247d9f5c..ea5279233 100644 --- a/web/core/constants/editor.ts +++ b/web/core/constants/editor.ts @@ -20,7 +20,7 @@ import { Underline, } from "lucide-react"; // editor -import { EditorMenuItemNames } from "@plane/document-editor"; +import { EditorMenuItemNames } from "@plane/editor"; type TEditorTypes = "lite" | "document"; diff --git a/web/core/hooks/use-page-description.ts b/web/core/hooks/use-page-description.ts index 245d61395..3c824b00d 100644 --- a/web/core/hooks/use-page-description.ts +++ b/web/core/hooks/use-page-description.ts @@ -1,12 +1,18 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; import useSWR from "swr"; // editor -import { applyUpdates, mergeUpdates, proseMirrorJSONToBinaryString } from "@plane/document-editor"; -import { EditorRefApi, generateJSONfromHTML } from "@plane/editor-core"; +import { + EditorRefApi, + applyUpdates, + generateJSONfromHTML, + mergeUpdates, + proseMirrorJSONToBinaryString, +} from "@plane/editor"; // hooks import useReloadConfirmations from "@/hooks/use-reload-confirmation"; // services import { ProjectPageService } from "@/services/page"; +// store import { IPage } from "@/store/pages/page"; const projectPageService = new ProjectPageService(); diff --git a/web/ee/components/pages/extra-actions.tsx b/web/ee/components/pages/extra-actions.tsx deleted file mode 100644 index 4e3c17968..000000000 --- a/web/ee/components/pages/extra-actions.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from "ce/components/pages/extra-actions"; diff --git a/web/ee/components/pages/index.ts b/web/ee/components/pages/index.ts index 5ce39384e..06b906428 100644 --- a/web/ee/components/pages/index.ts +++ b/web/ee/components/pages/index.ts @@ -1 +1 @@ -export * from "./extra-actions"; +export * from "ce/components/pages"; diff --git a/web/package.json b/web/package.json index 177f4dcc7..6e8c3c27a 100644 --- a/web/package.json +++ b/web/package.json @@ -24,9 +24,7 @@ "@nivo/line": "0.80.0", "@nivo/pie": "0.80.0", "@nivo/scatterplot": "0.80.0", - "@plane/document-editor": "*", - "@plane/lite-text-editor": "*", - "@plane/rich-text-editor": "*", + "@plane/editor": "*", "@plane/types": "*", "@plane/ui": "*", "@popperjs/core": "^2.11.8", diff --git a/yarn.lock b/yarn.lock index 2d6b2695e..94630c5df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1587,9 +1587,9 @@ "@floating-ui/dom" "^1.0.0" "@floating-ui/react@^0.26.4": - version "0.26.16" - resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.16.tgz#3415a087f452165161c2d313d1d57e8142894679" - integrity sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow== + version "0.26.17" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.17.tgz#efa2e1a0dea3d9d308965c5ccd49756bb64a883d" + integrity sha512-ESD+jYWwqwVzaIgIhExrArdsCL1rOAzryG/Sjlu8yaD3Mtqi3uVyhbE2V7jD58Mo52qbzKz2eUY/Xgh5I86FCQ== dependencies: "@floating-ui/react-dom" "^2.1.0" "@floating-ui/utils" "^0.2.0" @@ -3774,13 +3774,6 @@ resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ== -"@tippyjs/react@^4.2.6": - version "4.2.6" - resolved "https://registry.yarnpkg.com/@tippyjs/react/-/react-4.2.6.tgz#971677a599bf663f20bb1c60a62b9555b749cc71" - integrity sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw== - dependencies: - tippy.js "^6.3.1" - "@tiptap/core@^2.1.13", "@tiptap/core@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.4.0.tgz#6f8eee8beb5b89363582366b201ccc4798ac98a9" @@ -3987,7 +3980,7 @@ "@tiptap/extension-strike" "^2.4.0" "@tiptap/extension-text" "^2.4.0" -"@tiptap/suggestion@^2.0.13", "@tiptap/suggestion@^2.1.13": +"@tiptap/suggestion@^2.0.13": version "2.4.0" resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.4.0.tgz#1926cde5f197d116baf7794f55bd971245540e5c" integrity sha512-6dCkjbL8vIzcLWtS6RCBx0jlYPKf2Beuyq5nNLrDDZZuyJow5qJAY0eGu6Xomp9z0WDK/BYOxT4hHNoGMDkoAg== @@ -12795,7 +12788,7 @@ tinyspy@^2.2.0: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1" integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A== -tippy.js@^6.3.1, tippy.js@^6.3.7: +tippy.js@^6.3.7: version "6.3.7" resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c" integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ== @@ -13957,9 +13950,9 @@ y-indexeddb@^9.0.12: lib0 "^0.2.74" y-prosemirror@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/y-prosemirror/-/y-prosemirror-1.2.6.tgz#a324991cc158a6ff3b3f5902111b3dbf8928e603" - integrity sha512-rGz8kX4v/uFJrLaqZvsezY1JGN/zTDSPMO76zRbNcpE63OEiw2PBCEQi9ZlfbEwgCMoeJLUT+otNyO/Oj73TGQ== + version "1.2.9" + resolved "https://registry.yarnpkg.com/y-prosemirror/-/y-prosemirror-1.2.9.tgz#0202b5f6b164fa35d80bdbcdc876d81fe6da7ac2" + integrity sha512-fThGIVmSqrqnG/ckywEGlHM9ElfILC4TcMZd5zxWPe/i+UuP97TEr4swsopRKG3Y+KHBVt4Y/5NVBC3AAsUoUg== dependencies: lib0 "^0.2.42" @@ -14014,9 +14007,9 @@ yargs@^17.0.0: yargs-parser "^21.1.1" yjs@^13.6.15: - version "13.6.15" - resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.6.15.tgz#5a2402632aabf83e5baf56342b4c82fe40859306" - integrity sha512-moFv4uNYhp8BFxIk3AkpoAnnjts7gwdpiG8RtyFiKbMtxKCS0zVZ5wPaaGpwC3V2N/K8TK8MwtSI3+WO9CHWjQ== + version "13.6.18" + resolved "https://registry.yarnpkg.com/yjs/-/yjs-13.6.18.tgz#d1575203478bc99ad1b89c098e7d4bacb7f91c3b" + integrity sha512-GBTjO4QCmv2HFKFkYIJl7U77hIB1o22vSCSQD1Ge8ZxWbIbn8AltI4gyXbtL+g5/GJep67HCMq3Y5AmNwDSyEg== dependencies: lib0 "^0.2.86"