[PE-92] fix: removing readonly collaborative document editor (#6209)
* fix: removing readonly editor * fix: sync state * fix: indexeddb sync loader added * fix: remove node error fixed * style: page title and checkbox * chore: removing the syncing logic * revert: is editable check removed in display message * fix: editable field optional * fix: editable removed as optional prop * fix: extra options import fix --------- Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
This commit is contained in:
parent
580c4b1930
commit
e33bae2125
28 changed files with 215 additions and 460 deletions
|
|
@ -19,6 +19,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
|
|||
containerClassName,
|
||||
disabledExtensions,
|
||||
displayConfig = DEFAULT_DISPLAY_CONFIG,
|
||||
editable,
|
||||
editorClassName = "",
|
||||
embedHandler,
|
||||
fileHandler,
|
||||
|
|
@ -44,8 +45,8 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
|
|||
|
||||
// use document editor
|
||||
const { editor, hasServerConnectionFailed, hasServerSynced } = useCollaborativeEditor({
|
||||
onTransaction,
|
||||
disabledExtensions,
|
||||
editable,
|
||||
editorClassName,
|
||||
embedHandler,
|
||||
extensions,
|
||||
|
|
@ -54,6 +55,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
|
|||
handleEditorReady,
|
||||
id,
|
||||
mentionHandler,
|
||||
onTransaction,
|
||||
placeholder,
|
||||
realtimeConfig,
|
||||
serverHandler,
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
import { forwardRef, MutableRefObject } from "react";
|
||||
// components
|
||||
import { DocumentContentLoader, PageRenderer } from "@/components/editors";
|
||||
// constants
|
||||
import { DEFAULT_DISPLAY_CONFIG } from "@/constants/config";
|
||||
// extensions
|
||||
import { IssueWidget } from "@/extensions";
|
||||
// helpers
|
||||
import { getEditorClassNames } from "@/helpers/common";
|
||||
// hooks
|
||||
import { useReadOnlyCollaborativeEditor } from "@/hooks/use-read-only-collaborative-editor";
|
||||
// types
|
||||
import { EditorReadOnlyRefApi, ICollaborativeDocumentReadOnlyEditor } from "@/types";
|
||||
|
||||
const CollaborativeDocumentReadOnlyEditor = (props: ICollaborativeDocumentReadOnlyEditor) => {
|
||||
const {
|
||||
containerClassName,
|
||||
disabledExtensions,
|
||||
displayConfig = DEFAULT_DISPLAY_CONFIG,
|
||||
editorClassName = "",
|
||||
embedHandler,
|
||||
fileHandler,
|
||||
forwardedRef,
|
||||
handleEditorReady,
|
||||
id,
|
||||
mentionHandler,
|
||||
realtimeConfig,
|
||||
serverHandler,
|
||||
user,
|
||||
} = props;
|
||||
const extensions = [];
|
||||
if (embedHandler?.issue) {
|
||||
extensions.push(
|
||||
IssueWidget({
|
||||
widgetCallback: embedHandler.issue.widgetCallback,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const { editor, hasServerConnectionFailed, hasServerSynced } = useReadOnlyCollaborativeEditor({
|
||||
disabledExtensions,
|
||||
editorClassName,
|
||||
extensions,
|
||||
fileHandler,
|
||||
forwardedRef,
|
||||
handleEditorReady,
|
||||
id,
|
||||
mentionHandler,
|
||||
realtimeConfig,
|
||||
serverHandler,
|
||||
user,
|
||||
});
|
||||
|
||||
const editorContainerClassName = getEditorClassNames({
|
||||
containerClassName,
|
||||
});
|
||||
|
||||
if (!editor) return null;
|
||||
|
||||
if (!hasServerSynced && !hasServerConnectionFailed) return <DocumentContentLoader />;
|
||||
|
||||
return (
|
||||
<PageRenderer
|
||||
displayConfig={displayConfig}
|
||||
id={id}
|
||||
editor={editor}
|
||||
editorContainerClassName={editorContainerClassName}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const CollaborativeDocumentReadOnlyEditorWithRef = forwardRef<
|
||||
EditorReadOnlyRefApi,
|
||||
ICollaborativeDocumentReadOnlyEditor
|
||||
>((props, ref) => (
|
||||
<CollaborativeDocumentReadOnlyEditor {...props} forwardedRef={ref as MutableRefObject<EditorReadOnlyRefApi | null>} />
|
||||
));
|
||||
|
||||
CollaborativeDocumentReadOnlyEditorWithRef.displayName = "CollaborativeDocumentReadOnlyEditorWithRef";
|
||||
|
||||
export { CollaborativeDocumentReadOnlyEditorWithRef };
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
export * from "./collaborative-editor";
|
||||
export * from "./collaborative-read-only-editor";
|
||||
export * from "./loader";
|
||||
export * from "./page-renderer";
|
||||
export * from "./read-only-editor";
|
||||
|
|
|
|||
|
|
@ -140,10 +140,10 @@ export const PageRenderer = (props: IPageRenderer) => {
|
|||
>
|
||||
<EditorContentWrapper editor={editor} id={id} tabIndex={tabIndex} />
|
||||
{editor.isEditable && (
|
||||
<>
|
||||
<div>
|
||||
<BlockMenu editor={editor} />
|
||||
<AIFeaturesMenu menu={aiHandler?.menu} />
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</EditorContainer>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
|
|||
} = props;
|
||||
|
||||
const editor = useEditor({
|
||||
editable: true,
|
||||
disabledExtensions,
|
||||
editorClassName,
|
||||
enableHistory: true,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => {
|
|||
return "Uploading...";
|
||||
}
|
||||
|
||||
if (draggedInside) {
|
||||
if (draggedInside && editor.isEditable) {
|
||||
return "Drop image here";
|
||||
}
|
||||
|
||||
|
|
@ -137,14 +137,16 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"image-upload-component flex items-center justify-start gap-2 py-3 px-2 rounded-lg text-custom-text-300 hover:text-custom-text-200 bg-custom-background-90 hover:bg-custom-background-80 border border-dashed border-custom-border-300 transition-all duration-200 ease-in-out cursor-default",
|
||||
"image-upload-component flex items-center justify-start gap-2 py-3 px-2 rounded-lg text-custom-text-300 bg-custom-background-90 border border-dashed border-custom-border-300 transition-all duration-200 ease-in-out cursor-default",
|
||||
{
|
||||
"hover:text-custom-text-200 cursor-pointer": editor.isEditable,
|
||||
"bg-custom-background-80 text-custom-text-200": draggedInside,
|
||||
"text-custom-primary-200 bg-custom-primary-100/10 hover:bg-custom-primary-100/10 hover:text-custom-primary-200 border-custom-primary-200/10":
|
||||
selected,
|
||||
"text-red-500 cursor-default hover:text-red-500": failedToLoadImage,
|
||||
"bg-red-500/10 hover:bg-red-500/10": failedToLoadImage && selected,
|
||||
"hover:text-custom-text-200 hover:bg-custom-background-80 cursor-pointer": editor.isEditable,
|
||||
"bg-custom-background-80 text-custom-text-200": draggedInside && editor.isEditable,
|
||||
"text-custom-primary-200 bg-custom-primary-100/10 border-custom-primary-200/10 hover:bg-custom-primary-100/10 hover:text-custom-primary-200":
|
||||
selected && editor.isEditable,
|
||||
"text-red-500 cursor-default": failedToLoadImage,
|
||||
"hover:text-red-500": failedToLoadImage && editor.isEditable,
|
||||
"bg-red-500/10": failedToLoadImage && selected,
|
||||
"hover:bg-red-500/10": failedToLoadImage && selected && editor.isEditable,
|
||||
}
|
||||
)}
|
||||
onDrop={onDrop}
|
||||
|
|
|
|||
|
|
@ -2,58 +2,67 @@ import { Extension, Editor } from "@tiptap/core";
|
|||
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
||||
import { EditorView } from "@tiptap/pm/view";
|
||||
|
||||
export const DropHandlerExtension = () =>
|
||||
Extension.create({
|
||||
name: "dropHandler",
|
||||
priority: 1000,
|
||||
export const DropHandlerExtension = Extension.create({
|
||||
name: "dropHandler",
|
||||
priority: 1000,
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
const editor = this.editor;
|
||||
return [
|
||||
new Plugin({
|
||||
key: new PluginKey("drop-handler-plugin"),
|
||||
props: {
|
||||
handlePaste: (view: EditorView, event: ClipboardEvent) => {
|
||||
if (event.clipboardData && event.clipboardData.files && event.clipboardData.files.length > 0) {
|
||||
event.preventDefault();
|
||||
const files = Array.from(event.clipboardData.files);
|
||||
const imageFiles = files.filter((file) => file.type.startsWith("image"));
|
||||
addProseMirrorPlugins() {
|
||||
const editor = this.editor;
|
||||
return [
|
||||
new Plugin({
|
||||
key: new PluginKey("drop-handler-plugin"),
|
||||
props: {
|
||||
handlePaste: (view: EditorView, event: ClipboardEvent) => {
|
||||
if (
|
||||
editor.isEditable &&
|
||||
event.clipboardData &&
|
||||
event.clipboardData.files &&
|
||||
event.clipboardData.files.length > 0
|
||||
) {
|
||||
event.preventDefault();
|
||||
const files = Array.from(event.clipboardData.files);
|
||||
const imageFiles = files.filter((file) => file.type.startsWith("image"));
|
||||
|
||||
if (imageFiles.length > 0) {
|
||||
const pos = view.state.selection.from;
|
||||
if (imageFiles.length > 0) {
|
||||
const pos = view.state.selection.from;
|
||||
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleDrop: (view: EditorView, event: DragEvent, _slice: any, moved: boolean) => {
|
||||
if (
|
||||
editor.isEditable &&
|
||||
!moved &&
|
||||
event.dataTransfer &&
|
||||
event.dataTransfer.files &&
|
||||
event.dataTransfer.files.length > 0
|
||||
) {
|
||||
event.preventDefault();
|
||||
const files = Array.from(event.dataTransfer.files);
|
||||
const imageFiles = files.filter((file) => file.type.startsWith("image"));
|
||||
|
||||
if (imageFiles.length > 0) {
|
||||
const coordinates = view.posAtCoords({
|
||||
left: event.clientX,
|
||||
top: event.clientY,
|
||||
});
|
||||
|
||||
if (coordinates) {
|
||||
const pos = coordinates.pos;
|
||||
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleDrop: (view: EditorView, event: DragEvent, _slice: any, moved: boolean) => {
|
||||
if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length > 0) {
|
||||
event.preventDefault();
|
||||
const files = Array.from(event.dataTransfer.files);
|
||||
const imageFiles = files.filter((file) => file.type.startsWith("image"));
|
||||
|
||||
if (imageFiles.length > 0) {
|
||||
const coordinates = view.posAtCoords({
|
||||
left: event.clientX,
|
||||
top: event.clientY,
|
||||
});
|
||||
|
||||
if (coordinates) {
|
||||
const pos = coordinates.pos;
|
||||
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}),
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
}),
|
||||
];
|
||||
},
|
||||
});
|
||||
export const insertImagesSafely = async ({
|
||||
editor,
|
||||
files,
|
||||
|
|
|
|||
|
|
@ -47,10 +47,11 @@ type TArguments = {
|
|||
};
|
||||
placeholder?: string | ((isFocused: boolean, value: string) => string);
|
||||
tabIndex?: number;
|
||||
editable: boolean;
|
||||
};
|
||||
|
||||
export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
||||
const { disabledExtensions, enableHistory, fileHandler, mentionConfig, placeholder, tabIndex } = args;
|
||||
const { disabledExtensions, enableHistory, fileHandler, mentionConfig, placeholder, tabIndex, editable } = args;
|
||||
|
||||
return [
|
||||
StarterKit.configure({
|
||||
|
|
@ -89,7 +90,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
|||
...(enableHistory ? {} : { history: false }),
|
||||
}),
|
||||
CustomQuoteExtension,
|
||||
DropHandlerExtension(),
|
||||
DropHandlerExtension,
|
||||
CustomHorizontalRule.configure({
|
||||
HTMLAttributes: {
|
||||
class: "py-4 border-custom-border-400",
|
||||
|
|
@ -137,6 +138,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
|||
CustomCodeInlineExtension,
|
||||
Markdown.configure({
|
||||
html: true,
|
||||
transformCopiedText: true,
|
||||
transformPastedText: true,
|
||||
breaks: true,
|
||||
}),
|
||||
|
|
@ -145,12 +147,14 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
|
|||
TableCell,
|
||||
TableRow,
|
||||
CustomMention({
|
||||
mentionSuggestions: mentionConfig.mentionSuggestions,
|
||||
mentionSuggestions: editable ? mentionConfig.mentionSuggestions : undefined,
|
||||
mentionHighlights: mentionConfig.mentionHighlights,
|
||||
readonly: false,
|
||||
readonly: !editable,
|
||||
}),
|
||||
Placeholder.configure({
|
||||
placeholder: ({ editor, node }) => {
|
||||
if (!editor.isEditable) return;
|
||||
|
||||
if (node.type.name === "heading") return `Heading ${node.attrs.level}`;
|
||||
|
||||
if (editor.storage.imageComponent.uploadInProgress) return "";
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import {
|
|||
TableRow,
|
||||
Table,
|
||||
CustomMention,
|
||||
HeadingListExtension,
|
||||
CustomReadOnlyImageExtension,
|
||||
CustomTextAlignExtension,
|
||||
CustomCalloutReadOnlyExtension,
|
||||
|
|
@ -139,7 +138,6 @@ export const CoreReadOnlyEditorExtensions = (props: Props): Extensions => {
|
|||
}),
|
||||
CharacterCount,
|
||||
CustomColorExtension,
|
||||
HeadingListExtension,
|
||||
CustomTextAlignExtension,
|
||||
CustomCalloutReadOnlyExtension,
|
||||
...CoreReadOnlyEditorAdditionalExtensions({
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
|
|||
const {
|
||||
onTransaction,
|
||||
disabledExtensions,
|
||||
editable,
|
||||
editorClassName,
|
||||
editorProps = {},
|
||||
embedHandler,
|
||||
|
|
@ -75,7 +76,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
|
|||
const editor = useEditor({
|
||||
disabledExtensions,
|
||||
id,
|
||||
onTransaction,
|
||||
editable,
|
||||
editorProps,
|
||||
editorClassName,
|
||||
enableHistory: false,
|
||||
|
|
@ -97,9 +98,10 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
|
|||
}),
|
||||
],
|
||||
fileHandler,
|
||||
handleEditorReady,
|
||||
forwardedRef,
|
||||
handleEditorReady,
|
||||
mentionHandler,
|
||||
onTransaction,
|
||||
placeholder,
|
||||
provider,
|
||||
tabIndex,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import type {
|
|||
} from "@/types";
|
||||
|
||||
export interface CustomEditorProps {
|
||||
editable: boolean;
|
||||
editorClassName: string;
|
||||
editorProps?: EditorProps;
|
||||
enableHistory: boolean;
|
||||
|
|
@ -55,6 +56,7 @@ export interface CustomEditorProps {
|
|||
export const useEditor = (props: CustomEditorProps) => {
|
||||
const {
|
||||
disabledExtensions,
|
||||
editable = true,
|
||||
editorClassName,
|
||||
editorProps = {},
|
||||
enableHistory,
|
||||
|
|
@ -74,42 +76,46 @@ export const useEditor = (props: CustomEditorProps) => {
|
|||
autofocus = false,
|
||||
} = props;
|
||||
// states
|
||||
|
||||
const [savedSelection, setSavedSelection] = useState<Selection | null>(null);
|
||||
// refs
|
||||
const editorRef: MutableRefObject<Editor | null> = useRef(null);
|
||||
const savedSelectionRef = useRef(savedSelection);
|
||||
const editor = useTiptapEditor({
|
||||
autofocus,
|
||||
editorProps: {
|
||||
...CoreEditorProps({
|
||||
editorClassName,
|
||||
}),
|
||||
...editorProps,
|
||||
const editor = useTiptapEditor(
|
||||
{
|
||||
editable,
|
||||
autofocus,
|
||||
editorProps: {
|
||||
...CoreEditorProps({
|
||||
editorClassName,
|
||||
}),
|
||||
...editorProps,
|
||||
},
|
||||
extensions: [
|
||||
...CoreEditorExtensions({
|
||||
editable,
|
||||
disabledExtensions,
|
||||
enableHistory,
|
||||
fileHandler,
|
||||
mentionConfig: {
|
||||
mentionSuggestions: mentionHandler.suggestions ?? (() => Promise.resolve<IMentionSuggestion[]>([])),
|
||||
mentionHighlights: mentionHandler.highlights,
|
||||
},
|
||||
placeholder,
|
||||
tabIndex,
|
||||
}),
|
||||
...extensions,
|
||||
],
|
||||
content: typeof initialValue === "string" && initialValue.trim() !== "" ? initialValue : "<p></p>",
|
||||
onCreate: () => handleEditorReady?.(true),
|
||||
onTransaction: ({ editor }) => {
|
||||
setSavedSelection(editor.state.selection);
|
||||
onTransaction?.();
|
||||
},
|
||||
onUpdate: ({ editor }) => onChange?.(editor.getJSON(), editor.getHTML()),
|
||||
onDestroy: () => handleEditorReady?.(false),
|
||||
},
|
||||
extensions: [
|
||||
...CoreEditorExtensions({
|
||||
disabledExtensions,
|
||||
enableHistory,
|
||||
fileHandler,
|
||||
mentionConfig: {
|
||||
mentionSuggestions: mentionHandler.suggestions ?? (() => Promise.resolve<IMentionSuggestion[]>([])),
|
||||
mentionHighlights: mentionHandler.highlights,
|
||||
},
|
||||
placeholder,
|
||||
tabIndex,
|
||||
}),
|
||||
...extensions,
|
||||
],
|
||||
content: typeof initialValue === "string" && initialValue.trim() !== "" ? initialValue : "<p></p>",
|
||||
onCreate: () => handleEditorReady?.(true),
|
||||
onTransaction: ({ editor }) => {
|
||||
setSavedSelection(editor.state.selection);
|
||||
onTransaction?.();
|
||||
},
|
||||
onUpdate: ({ editor }) => onChange?.(editor.getJSON(), editor.getHTML()),
|
||||
onDestroy: () => handleEditorReady?.(false),
|
||||
});
|
||||
[editable]
|
||||
);
|
||||
|
||||
// Update the ref whenever savedSelection changes
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ export const useDropZone = (args: TDropzoneArgs) => {
|
|||
async (e: DragEvent<HTMLDivElement>) => {
|
||||
e.preventDefault();
|
||||
setDraggedInside(false);
|
||||
if (e.dataTransfer.files.length === 0) {
|
||||
if (e.dataTransfer.files.length === 0 || !editor.isEditable) {
|
||||
return;
|
||||
}
|
||||
const filesList = e.dataTransfer.files;
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { HocuspocusProvider } from "@hocuspocus/provider";
|
||||
import Collaboration from "@tiptap/extension-collaboration";
|
||||
import { IndexeddbPersistence } from "y-indexeddb";
|
||||
// extensions
|
||||
import { HeadingListExtension } from "@/extensions";
|
||||
// hooks
|
||||
import { useReadOnlyEditor } from "@/hooks/use-read-only-editor";
|
||||
// types
|
||||
import { TReadOnlyCollaborativeEditorProps } from "@/types";
|
||||
|
||||
export const useReadOnlyCollaborativeEditor = (props: TReadOnlyCollaborativeEditorProps) => {
|
||||
const {
|
||||
disabledExtensions,
|
||||
editorClassName,
|
||||
editorProps = {},
|
||||
extensions,
|
||||
fileHandler,
|
||||
forwardedRef,
|
||||
handleEditorReady,
|
||||
id,
|
||||
mentionHandler,
|
||||
realtimeConfig,
|
||||
serverHandler,
|
||||
user,
|
||||
} = props;
|
||||
// states
|
||||
const [hasServerConnectionFailed, setHasServerConnectionFailed] = useState(false);
|
||||
const [hasServerSynced, setHasServerSynced] = useState(false);
|
||||
// initialize Hocuspocus provider
|
||||
const provider = useMemo(
|
||||
() =>
|
||||
new HocuspocusProvider({
|
||||
name: id,
|
||||
url: realtimeConfig.url,
|
||||
token: JSON.stringify(user),
|
||||
parameters: realtimeConfig.queryParams,
|
||||
onAuthenticationFailed: () => {
|
||||
serverHandler?.onServerError?.();
|
||||
setHasServerConnectionFailed(true);
|
||||
},
|
||||
onConnect: () => serverHandler?.onConnect?.(),
|
||||
onClose: (data) => {
|
||||
if (data.event.code === 1006) {
|
||||
serverHandler?.onServerError?.();
|
||||
setHasServerConnectionFailed(true);
|
||||
}
|
||||
},
|
||||
onSynced: () => setHasServerSynced(true),
|
||||
}),
|
||||
[id, realtimeConfig, serverHandler, user]
|
||||
);
|
||||
|
||||
// indexed db integration for offline support
|
||||
const localProvider = useMemo(
|
||||
() => (id ? new IndexeddbPersistence(id, provider.document) : undefined),
|
||||
[id, provider]
|
||||
);
|
||||
|
||||
// destroy and disconnect connection on unmount
|
||||
useEffect(
|
||||
() => () => {
|
||||
provider.destroy();
|
||||
localProvider?.destroy();
|
||||
},
|
||||
[provider, localProvider]
|
||||
);
|
||||
|
||||
const editor = useReadOnlyEditor({
|
||||
disabledExtensions,
|
||||
editorProps,
|
||||
editorClassName,
|
||||
extensions: [
|
||||
...(extensions ?? []),
|
||||
HeadingListExtension,
|
||||
Collaboration.configure({
|
||||
document: provider.document,
|
||||
}),
|
||||
],
|
||||
fileHandler,
|
||||
forwardedRef,
|
||||
handleEditorReady,
|
||||
mentionHandler,
|
||||
provider,
|
||||
});
|
||||
|
||||
return {
|
||||
editor,
|
||||
hasServerConnectionFailed,
|
||||
hasServerSynced,
|
||||
};
|
||||
};
|
||||
|
|
@ -21,6 +21,7 @@ export type TServerHandler = {
|
|||
|
||||
type TCollaborativeEditorHookProps = {
|
||||
disabledExtensions: TExtensions[];
|
||||
editable?: boolean;
|
||||
editorClassName: string;
|
||||
editorProps?: EditorProps;
|
||||
extensions?: Extensions;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ export interface IRichTextEditor extends IEditorProps {
|
|||
|
||||
export interface ICollaborativeDocumentEditor
|
||||
extends Omit<IEditorProps, "initialValue" | "onChange" | "onEnterKeyPress" | "value"> {
|
||||
editable: boolean;
|
||||
aiHandler?: TAIHandler;
|
||||
embedHandler: TEmbedConfig;
|
||||
handleEditorReady?: (value: boolean) => void;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import "./styles/drag-drop.css";
|
|||
// editors
|
||||
export {
|
||||
CollaborativeDocumentEditorWithRef,
|
||||
CollaborativeDocumentReadOnlyEditorWithRef,
|
||||
DocumentReadOnlyEditorWithRef,
|
||||
LiteTextEditorWithRef,
|
||||
LiteTextReadOnlyEditorWithRef,
|
||||
|
|
|
|||
|
|
@ -111,8 +111,12 @@ ul[data-type="taskList"] li > label input[type="checkbox"] {
|
|||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
ul[data-type="taskList"] li > label input[type="checkbox"]:hover {
|
||||
background-color: rgba(var(--color-background-80)) !important;
|
||||
.ProseMirror[contenteditable="true"] input[type="checkbox"]:hover {
|
||||
background-color: rgba(var(--color-background-80));
|
||||
}
|
||||
|
||||
.ProseMirror[contenteditable="false"] input[type="checkbox"] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
ul[data-type="taskList"] li > label input[type="checkbox"][checked] {
|
||||
|
|
@ -151,10 +155,6 @@ ul[data-type="taskList"] li > label input[type="checkbox"] {
|
|||
margin-right: 0.2rem;
|
||||
margin-top: 0.15rem;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(var(--color-background-80));
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: rgb(var(--color-background-90));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue