[WIKI-632] chore: accept additional props for document collaborative editor (#7718)
* chore: add collaborative document editor extended props * fix: additional rich text extension props * fix: formatting * chore: add types to the trailing node extension --------- Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
This commit is contained in:
parent
0f7bfdde91
commit
11cd8d11e4
6 changed files with 84 additions and 3 deletions
|
|
@ -6,7 +6,7 @@ import { IEditorProps, TExtensions } from "@/types";
|
||||||
|
|
||||||
export type TRichTextEditorAdditionalExtensionsProps = Pick<
|
export type TRichTextEditorAdditionalExtensionsProps = Pick<
|
||||||
IEditorProps,
|
IEditorProps,
|
||||||
"disabledExtensions" | "flaggedExtensions" | "fileHandler"
|
"disabledExtensions" | "flaggedExtensions" | "fileHandler" | "extendedEditorProps"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ export type IEditorExtensionOptions = unknown;
|
||||||
|
|
||||||
export type IEditorPropsExtended = unknown;
|
export type IEditorPropsExtended = unknown;
|
||||||
|
|
||||||
|
export type ICollaborativeDocumentEditorPropsExtended = unknown;
|
||||||
|
|
||||||
export type TExtendedEditorCommands = never;
|
export type TExtendedEditorCommands = never;
|
||||||
|
|
||||||
export type TExtendedCommandExtraProps = unknown;
|
export type TExtendedCommandExtraProps = unknown;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ const RichTextEditor: React.FC<IRichTextEditorProps> = (props) => {
|
||||||
extensions: externalExtensions = [],
|
extensions: externalExtensions = [],
|
||||||
fileHandler,
|
fileHandler,
|
||||||
flaggedExtensions,
|
flaggedExtensions,
|
||||||
|
extendedEditorProps,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const getExtensions = useCallback(() => {
|
const getExtensions = useCallback(() => {
|
||||||
|
|
@ -30,11 +31,12 @@ const RichTextEditor: React.FC<IRichTextEditorProps> = (props) => {
|
||||||
disabledExtensions,
|
disabledExtensions,
|
||||||
fileHandler,
|
fileHandler,
|
||||||
flaggedExtensions,
|
flaggedExtensions,
|
||||||
|
extendedEditorProps,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}, [dragDropEnabled, disabledExtensions, externalExtensions, fileHandler, flaggedExtensions]);
|
}, [dragDropEnabled, disabledExtensions, externalExtensions, fileHandler, flaggedExtensions, extendedEditorProps]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditorWrapper {...props} extensions={getExtensions()}>
|
<EditorWrapper {...props} extensions={getExtensions()}>
|
||||||
|
|
|
||||||
69
packages/editor/src/core/extensions/trailing-node.ts
Normal file
69
packages/editor/src/core/extensions/trailing-node.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Extension } from "@tiptap/core";
|
||||||
|
import { NodeType, Node as ProseMirrorNode } from "@tiptap/pm/model";
|
||||||
|
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
||||||
|
// constants
|
||||||
|
import { CORE_EXTENSIONS } from "@/constants/extension";
|
||||||
|
|
||||||
|
function nodeEqualsType({ types, node }: { types: NodeType[]; node: ProseMirrorNode | null }) {
|
||||||
|
// TODO: check this logic, might be wrong
|
||||||
|
// @ts-expect-error - logic might be wrong
|
||||||
|
return (Array.isArray(types) && types.includes(node?.type)) || node?.type === types;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TrailingNodeOptions {
|
||||||
|
node: string;
|
||||||
|
notAfter: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TrailingNode = Extension.create<TrailingNodeOptions>({
|
||||||
|
name: "trailingNode",
|
||||||
|
|
||||||
|
addOptions() {
|
||||||
|
return {
|
||||||
|
node: CORE_EXTENSIONS.PARAGRAPH,
|
||||||
|
notAfter: [CORE_EXTENSIONS.PARAGRAPH],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
addProseMirrorPlugins() {
|
||||||
|
const plugin = new PluginKey(this.name);
|
||||||
|
const disabledNodes = Object.entries(this.editor.schema.nodes)
|
||||||
|
.map(([, value]) => value)
|
||||||
|
.filter((node) => this.options.notAfter.includes(node.name));
|
||||||
|
|
||||||
|
return [
|
||||||
|
new Plugin({
|
||||||
|
key: plugin,
|
||||||
|
appendTransaction: (_, __, state) => {
|
||||||
|
const { doc, tr, schema } = state;
|
||||||
|
const shouldInsertNodeAtEnd = plugin.getState(state);
|
||||||
|
const endPosition = doc.content.size;
|
||||||
|
const type = schema.nodes[this.options.node];
|
||||||
|
|
||||||
|
if (!shouldInsertNodeAtEnd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line consistent-return
|
||||||
|
return tr.insert(endPosition, type.create());
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
init: (_, state) => {
|
||||||
|
const lastNode = state.tr.doc.lastChild;
|
||||||
|
|
||||||
|
return !nodeEqualsType({ node: lastNode, types: disabledNodes });
|
||||||
|
},
|
||||||
|
apply: (tr, value) => {
|
||||||
|
if (!tr.docChanged) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastNode = tr.doc.lastChild;
|
||||||
|
|
||||||
|
return !nodeEqualsType({ node: lastNode, types: disabledNodes });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -6,7 +6,11 @@ import type { NodeViewProps as TNodeViewProps } from "@tiptap/react";
|
||||||
// extension types
|
// extension types
|
||||||
import type { TTextAlign } from "@/extensions";
|
import type { TTextAlign } from "@/extensions";
|
||||||
// plane editor imports
|
// plane editor imports
|
||||||
import type { IEditorPropsExtended, TExtendedEditorCommands } from "@/plane-editor/types/editor-extended";
|
import type {
|
||||||
|
IEditorPropsExtended,
|
||||||
|
TExtendedEditorCommands,
|
||||||
|
ICollaborativeDocumentEditorPropsExtended,
|
||||||
|
} from "@/plane-editor/types/editor-extended";
|
||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
IMarking,
|
IMarking,
|
||||||
|
|
@ -176,6 +180,7 @@ export type ICollaborativeDocumentEditorProps = Omit<IEditorProps, "initialValue
|
||||||
realtimeConfig: TRealtimeConfig;
|
realtimeConfig: TRealtimeConfig;
|
||||||
serverHandler?: TServerHandler;
|
serverHandler?: TServerHandler;
|
||||||
user: TUserDetails;
|
user: TUserDetails;
|
||||||
|
extendedDocumentEditorProps?: ICollaborativeDocumentEditorPropsExtended;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IDocumentEditorProps = Omit<IEditorProps, "initialValue" | "onEnterKeyPress" | "value"> & {
|
export type IDocumentEditorProps = Omit<IEditorProps, "initialValue" | "onEnterKeyPress" | "value"> & {
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,6 @@ export { ADDITIONAL_EXTENSIONS } from "@/plane-editor/constants/extensions";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
export * from "@/types";
|
export * from "@/types";
|
||||||
|
|
||||||
|
// additional exports
|
||||||
|
export { TrailingNode } from "./core/extensions/trailing-node";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue