@tiptap/react 3.0.0-next.0 → 3.0.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +996 -1126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +334 -0
- package/dist/index.d.ts +334 -0
- package/dist/index.js +960 -1098
- package/dist/index.js.map +1 -1
- package/package.json +14 -15
- package/src/BubbleMenu.tsx +70 -50
- package/src/Context.tsx +15 -7
- package/src/Editor.ts +7 -8
- package/src/EditorContent.tsx +98 -50
- package/src/FloatingMenu.tsx +51 -45
- package/src/NodeViewContent.tsx +1 -0
- package/src/NodeViewWrapper.tsx +1 -0
- package/src/ReactNodeViewRenderer.tsx +163 -53
- package/src/ReactRenderer.tsx +42 -23
- package/src/index.ts +0 -1
- package/src/useEditor.ts +253 -92
- package/src/useEditorState.ts +122 -69
- package/dist/index.umd.js +0 -1176
- package/dist/index.umd.js.map +0 -1
- package/dist/packages/core/src/CommandManager.d.ts +0 -20
- package/dist/packages/core/src/Editor.d.ts +0 -159
- package/dist/packages/core/src/EventEmitter.d.ts +0 -11
- package/dist/packages/core/src/Extension.d.ts +0 -343
- package/dist/packages/core/src/ExtensionManager.d.ts +0 -55
- package/dist/packages/core/src/InputRule.d.ts +0 -42
- package/dist/packages/core/src/Mark.d.ts +0 -451
- package/dist/packages/core/src/Node.d.ts +0 -611
- package/dist/packages/core/src/NodePos.d.ts +0 -44
- package/dist/packages/core/src/NodeView.d.ts +0 -31
- package/dist/packages/core/src/PasteRule.d.ts +0 -50
- package/dist/packages/core/src/Tracker.d.ts +0 -11
- package/dist/packages/core/src/commands/blur.d.ts +0 -13
- package/dist/packages/core/src/commands/clearContent.d.ts +0 -14
- package/dist/packages/core/src/commands/clearNodes.d.ts +0 -13
- package/dist/packages/core/src/commands/command.d.ts +0 -18
- package/dist/packages/core/src/commands/createParagraphNear.d.ts +0 -13
- package/dist/packages/core/src/commands/cut.d.ts +0 -20
- package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +0 -13
- package/dist/packages/core/src/commands/deleteNode.d.ts +0 -15
- package/dist/packages/core/src/commands/deleteRange.d.ts +0 -14
- package/dist/packages/core/src/commands/deleteSelection.d.ts +0 -13
- package/dist/packages/core/src/commands/enter.d.ts +0 -13
- package/dist/packages/core/src/commands/exitCode.d.ts +0 -13
- package/dist/packages/core/src/commands/extendMarkRange.d.ts +0 -25
- package/dist/packages/core/src/commands/first.d.ts +0 -14
- package/dist/packages/core/src/commands/focus.d.ts +0 -27
- package/dist/packages/core/src/commands/forEach.d.ts +0 -14
- package/dist/packages/core/src/commands/index.d.ts +0 -55
- package/dist/packages/core/src/commands/insertContent.d.ts +0 -34
- package/dist/packages/core/src/commands/insertContentAt.d.ts +0 -47
- package/dist/packages/core/src/commands/join.d.ts +0 -41
- package/dist/packages/core/src/commands/joinItemBackward.d.ts +0 -13
- package/dist/packages/core/src/commands/joinItemForward.d.ts +0 -13
- package/dist/packages/core/src/commands/joinTextblockBackward.d.ts +0 -12
- package/dist/packages/core/src/commands/joinTextblockForward.d.ts +0 -12
- package/dist/packages/core/src/commands/keyboardShortcut.d.ts +0 -14
- package/dist/packages/core/src/commands/lift.d.ts +0 -17
- package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +0 -13
- package/dist/packages/core/src/commands/liftListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/newlineInCode.d.ts +0 -13
- package/dist/packages/core/src/commands/resetAttributes.d.ts +0 -16
- package/dist/packages/core/src/commands/scrollIntoView.d.ts +0 -13
- package/dist/packages/core/src/commands/selectAll.d.ts +0 -13
- package/dist/packages/core/src/commands/selectNodeBackward.d.ts +0 -13
- package/dist/packages/core/src/commands/selectNodeForward.d.ts +0 -13
- package/dist/packages/core/src/commands/selectParentNode.d.ts +0 -13
- package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +0 -13
- package/dist/packages/core/src/commands/selectTextblockStart.d.ts +0 -13
- package/dist/packages/core/src/commands/setContent.d.ts +0 -40
- package/dist/packages/core/src/commands/setMark.d.ts +0 -15
- package/dist/packages/core/src/commands/setMeta.d.ts +0 -15
- package/dist/packages/core/src/commands/setNode.d.ts +0 -16
- package/dist/packages/core/src/commands/setNodeSelection.d.ts +0 -14
- package/dist/packages/core/src/commands/setTextSelection.d.ts +0 -14
- package/dist/packages/core/src/commands/sinkListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/splitBlock.d.ts +0 -17
- package/dist/packages/core/src/commands/splitListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/toggleList.d.ts +0 -18
- package/dist/packages/core/src/commands/toggleMark.d.ts +0 -30
- package/dist/packages/core/src/commands/toggleNode.d.ts +0 -17
- package/dist/packages/core/src/commands/toggleWrap.d.ts +0 -16
- package/dist/packages/core/src/commands/undoInputRule.d.ts +0 -13
- package/dist/packages/core/src/commands/unsetAllMarks.d.ts +0 -13
- package/dist/packages/core/src/commands/unsetMark.d.ts +0 -25
- package/dist/packages/core/src/commands/updateAttributes.d.ts +0 -24
- package/dist/packages/core/src/commands/wrapIn.d.ts +0 -16
- package/dist/packages/core/src/commands/wrapInList.d.ts +0 -16
- package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +0 -5
- package/dist/packages/core/src/extensions/commands.d.ts +0 -3
- package/dist/packages/core/src/extensions/editable.d.ts +0 -2
- package/dist/packages/core/src/extensions/focusEvents.d.ts +0 -2
- package/dist/packages/core/src/extensions/index.d.ts +0 -6
- package/dist/packages/core/src/extensions/keymap.d.ts +0 -2
- package/dist/packages/core/src/extensions/tabindex.d.ts +0 -2
- package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +0 -10
- package/dist/packages/core/src/helpers/createChainableState.d.ts +0 -10
- package/dist/packages/core/src/helpers/createDocument.d.ts +0 -12
- package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +0 -15
- package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +0 -7
- package/dist/packages/core/src/helpers/findChildren.d.ts +0 -9
- package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +0 -10
- package/dist/packages/core/src/helpers/findParentNode.d.ts +0 -16
- package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +0 -17
- package/dist/packages/core/src/helpers/generateHTML.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateJSON.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateText.d.ts +0 -12
- package/dist/packages/core/src/helpers/getAttributes.d.ts +0 -9
- package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +0 -6
- package/dist/packages/core/src/helpers/getChangedRanges.d.ts +0 -11
- package/dist/packages/core/src/helpers/getDebugJSON.d.ts +0 -8
- package/dist/packages/core/src/helpers/getExtensionField.d.ts +0 -9
- package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkRange.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarksBetween.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeAtPosition.d.ts +0 -11
- package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getSchema.d.ts +0 -4
- package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +0 -10
- package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +0 -8
- package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +0 -8
- package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +0 -9
- package/dist/packages/core/src/helpers/getText.d.ts +0 -15
- package/dist/packages/core/src/helpers/getTextBetween.d.ts +0 -14
- package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +0 -8
- package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +0 -8
- package/dist/packages/core/src/helpers/index.d.ts +0 -50
- package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +0 -9
- package/dist/packages/core/src/helpers/isActive.d.ts +0 -2
- package/dist/packages/core/src/helpers/isAtEndOfNode.d.ts +0 -2
- package/dist/packages/core/src/helpers/isAtStartOfNode.d.ts +0 -2
- package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +0 -2
- package/dist/packages/core/src/helpers/isList.d.ts +0 -2
- package/dist/packages/core/src/helpers/isMarkActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isNodeActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +0 -8
- package/dist/packages/core/src/helpers/isNodeSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/isTextSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/posToDOMRect.d.ts +0 -2
- package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +0 -4
- package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +0 -2
- package/dist/packages/core/src/helpers/splitExtensions.d.ts +0 -9
- package/dist/packages/core/src/index.d.ts +0 -24
- package/dist/packages/core/src/inputRules/index.d.ts +0 -5
- package/dist/packages/core/src/inputRules/markInputRule.d.ts +0 -13
- package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +0 -23
- package/dist/packages/core/src/inputRules/textInputRule.d.ts +0 -10
- package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +0 -15
- package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +0 -28
- package/dist/packages/core/src/pasteRules/index.d.ts +0 -3
- package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +0 -13
- package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +0 -13
- package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +0 -10
- package/dist/packages/core/src/style.d.ts +0 -1
- package/dist/packages/core/src/types.d.ts +0 -253
- package/dist/packages/core/src/utilities/callOrReturn.d.ts +0 -9
- package/dist/packages/core/src/utilities/createStyleTag.d.ts +0 -1
- package/dist/packages/core/src/utilities/deleteProps.d.ts +0 -6
- package/dist/packages/core/src/utilities/elementFromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +0 -1
- package/dist/packages/core/src/utilities/findDuplicates.d.ts +0 -1
- package/dist/packages/core/src/utilities/fromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/index.d.ts +0 -20
- package/dist/packages/core/src/utilities/isAndroid.d.ts +0 -1
- package/dist/packages/core/src/utilities/isEmptyObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isFunction.d.ts +0 -1
- package/dist/packages/core/src/utilities/isMacOS.d.ts +0 -1
- package/dist/packages/core/src/utilities/isNumber.d.ts +0 -1
- package/dist/packages/core/src/utilities/isPlainObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isRegExp.d.ts +0 -1
- package/dist/packages/core/src/utilities/isString.d.ts +0 -1
- package/dist/packages/core/src/utilities/isiOS.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeAttributes.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeDeep.d.ts +0 -1
- package/dist/packages/core/src/utilities/minMax.d.ts +0 -1
- package/dist/packages/core/src/utilities/objectIncludes.d.ts +0 -8
- package/dist/packages/core/src/utilities/removeDuplicates.d.ts +0 -8
- package/dist/packages/extension-bubble-menu/src/bubble-menu-plugin.d.ts +0 -99
- package/dist/packages/extension-bubble-menu/src/bubble-menu.d.ts +0 -15
- package/dist/packages/extension-bubble-menu/src/index.d.ts +0 -4
- package/dist/packages/extension-floating-menu/src/floating-menu-plugin.d.ts +0 -81
- package/dist/packages/extension-floating-menu/src/floating-menu.d.ts +0 -15
- package/dist/packages/extension-floating-menu/src/index.d.ts +0 -4
- package/dist/packages/react/src/BubbleMenu.d.ts +0 -13
- package/dist/packages/react/src/Context.d.ts +0 -23
- package/dist/packages/react/src/Editor.d.ts +0 -12
- package/dist/packages/react/src/EditorContent.d.ts +0 -24
- package/dist/packages/react/src/FloatingMenu.d.ts +0 -11
- package/dist/packages/react/src/NodeViewContent.d.ts +0 -6
- package/dist/packages/react/src/NodeViewWrapper.d.ts +0 -6
- package/dist/packages/react/src/ReactNodeViewRenderer.d.ts +0 -16
- package/dist/packages/react/src/ReactRenderer.d.ts +0 -62
- package/dist/packages/react/src/index.d.ts +0 -13
- package/dist/packages/react/src/useEditor.d.ts +0 -39
- package/dist/packages/react/src/useEditorState.d.ts +0 -22
- package/dist/packages/react/src/useReactNodeView.d.ts +0 -6
package/src/Context.tsx
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Editor } from '@tiptap/core'
|
|
2
|
+
import React, {
|
|
3
|
+
createContext, HTMLAttributes, ReactNode, useContext, useMemo,
|
|
4
|
+
} from 'react'
|
|
2
5
|
|
|
3
|
-
import { Editor } from './Editor.js'
|
|
4
6
|
import { EditorContent } from './EditorContent.js'
|
|
5
7
|
import { useEditor, UseEditorOptions } from './useEditor.js'
|
|
6
8
|
|
|
7
9
|
export type EditorContextValue = {
|
|
8
10
|
editor: Editor | null;
|
|
9
|
-
}
|
|
11
|
+
};
|
|
10
12
|
|
|
11
13
|
export const EditorContext = createContext<EditorContextValue>({
|
|
12
14
|
editor: null,
|
|
@@ -23,7 +25,8 @@ export type EditorProviderProps = {
|
|
|
23
25
|
children?: ReactNode;
|
|
24
26
|
slotBefore?: ReactNode;
|
|
25
27
|
slotAfter?: ReactNode;
|
|
26
|
-
|
|
28
|
+
editorContainerProps?: HTMLAttributes<HTMLDivElement>;
|
|
29
|
+
} & UseEditorOptions;
|
|
27
30
|
|
|
28
31
|
/**
|
|
29
32
|
* This is the provider component for the editor.
|
|
@@ -31,20 +34,25 @@ export type EditorProviderProps = {
|
|
|
31
34
|
* with `useCurrentEditor`.
|
|
32
35
|
*/
|
|
33
36
|
export function EditorProvider({
|
|
34
|
-
children,
|
|
37
|
+
children,
|
|
38
|
+
slotAfter,
|
|
39
|
+
slotBefore,
|
|
40
|
+
editorContainerProps = {},
|
|
41
|
+
...editorOptions
|
|
35
42
|
}: EditorProviderProps) {
|
|
36
43
|
const editor = useEditor(editorOptions)
|
|
44
|
+
const contextValue = useMemo(() => ({ editor }), [editor])
|
|
37
45
|
|
|
38
46
|
if (!editor) {
|
|
39
47
|
return null
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
return (
|
|
43
|
-
<EditorContext.Provider value={
|
|
51
|
+
<EditorContext.Provider value={contextValue}>
|
|
44
52
|
{slotBefore}
|
|
45
53
|
<EditorConsumer>
|
|
46
54
|
{({ editor: currentEditor }) => (
|
|
47
|
-
<EditorContent editor={currentEditor} />
|
|
55
|
+
<EditorContent editor={currentEditor} {...editorContainerProps} />
|
|
48
56
|
)}
|
|
49
57
|
</EditorConsumer>
|
|
50
58
|
{children}
|
package/src/Editor.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { Editor
|
|
2
|
-
import
|
|
1
|
+
import { Editor } from '@tiptap/core'
|
|
2
|
+
import { ReactPortal } from 'react'
|
|
3
3
|
|
|
4
|
-
import { EditorContentProps, EditorContentState } from './EditorContent.js'
|
|
5
4
|
import { ReactRenderer } from './ReactRenderer.js'
|
|
6
5
|
|
|
7
|
-
type
|
|
6
|
+
export type EditorWithContentComponent = Editor & { contentComponent?: ContentComponent | null }
|
|
7
|
+
export type ContentComponent = {
|
|
8
8
|
setRenderer(id: string, renderer: ReactRenderer): void;
|
|
9
9
|
removeRenderer(id: string): void;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
public contentComponent: ContentComponent | null = null
|
|
10
|
+
subscribe: (callback: () => void) => () => void;
|
|
11
|
+
getSnapshot: () => Record<string, ReactPortal>;
|
|
12
|
+
getServerSnapshot: () => Record<string, ReactPortal>;
|
|
14
13
|
}
|
package/src/EditorContent.tsx
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core'
|
|
1
2
|
import React, {
|
|
2
3
|
ForwardedRef, forwardRef, HTMLProps, LegacyRef, MutableRefObject,
|
|
3
4
|
} from 'react'
|
|
4
|
-
import ReactDOM
|
|
5
|
+
import ReactDOM from 'react-dom'
|
|
6
|
+
import { useSyncExternalStore } from 'use-sync-external-store/shim'
|
|
5
7
|
|
|
6
|
-
import {
|
|
8
|
+
import { ContentComponent, EditorWithContentComponent } from './Editor.js'
|
|
7
9
|
import { ReactRenderer } from './ReactRenderer.js'
|
|
8
10
|
|
|
9
11
|
const mergeRefs = <T extends HTMLDivElement>(
|
|
@@ -20,12 +22,23 @@ const mergeRefs = <T extends HTMLDivElement>(
|
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
/**
|
|
26
|
+
* This component renders all of the editor's node views.
|
|
27
|
+
*/
|
|
28
|
+
const Portals: React.FC<{ contentComponent: ContentComponent }> = ({
|
|
29
|
+
contentComponent,
|
|
30
|
+
}) => {
|
|
31
|
+
// For performance reasons, we render the node view portals on state changes only
|
|
32
|
+
const renderers = useSyncExternalStore(
|
|
33
|
+
contentComponent.subscribe,
|
|
34
|
+
contentComponent.getSnapshot,
|
|
35
|
+
contentComponent.getServerSnapshot,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
// This allows us to directly render the portals without any additional wrapper
|
|
24
39
|
return (
|
|
25
40
|
<>
|
|
26
|
-
{Object.
|
|
27
|
-
return ReactDOM.createPortal(renderer.reactElement, renderer.element, key)
|
|
28
|
-
})}
|
|
41
|
+
{Object.values(renderers)}
|
|
29
42
|
</>
|
|
30
43
|
)
|
|
31
44
|
}
|
|
@@ -35,22 +48,67 @@ export interface EditorContentProps extends HTMLProps<HTMLDivElement> {
|
|
|
35
48
|
innerRef?: ForwardedRef<HTMLDivElement | null>;
|
|
36
49
|
}
|
|
37
50
|
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
function getInstance(): ContentComponent {
|
|
52
|
+
const subscribers = new Set<() => void>()
|
|
53
|
+
let renderers: Record<string, React.ReactPortal> = {}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
/**
|
|
57
|
+
* Subscribe to the editor instance's changes.
|
|
58
|
+
*/
|
|
59
|
+
subscribe(callback: () => void) {
|
|
60
|
+
subscribers.add(callback)
|
|
61
|
+
return () => {
|
|
62
|
+
subscribers.delete(callback)
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
getSnapshot() {
|
|
66
|
+
return renderers
|
|
67
|
+
},
|
|
68
|
+
getServerSnapshot() {
|
|
69
|
+
return renderers
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Adds a new NodeView Renderer to the editor.
|
|
73
|
+
*/
|
|
74
|
+
setRenderer(id: string, renderer: ReactRenderer) {
|
|
75
|
+
renderers = {
|
|
76
|
+
...renderers,
|
|
77
|
+
[id]: ReactDOM.createPortal(renderer.reactElement, renderer.element, id),
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
subscribers.forEach(subscriber => subscriber())
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Removes a NodeView Renderer from the editor.
|
|
84
|
+
*/
|
|
85
|
+
removeRenderer(id: string) {
|
|
86
|
+
const nextRenderers = { ...renderers }
|
|
87
|
+
|
|
88
|
+
delete nextRenderers[id]
|
|
89
|
+
renderers = nextRenderers
|
|
90
|
+
subscribers.forEach(subscriber => subscriber())
|
|
91
|
+
},
|
|
92
|
+
}
|
|
40
93
|
}
|
|
41
94
|
|
|
42
|
-
export class PureEditorContent extends React.Component<
|
|
95
|
+
export class PureEditorContent extends React.Component<
|
|
96
|
+
EditorContentProps,
|
|
97
|
+
{ hasContentComponentInitialized: boolean }
|
|
98
|
+
> {
|
|
43
99
|
editorContentRef: React.RefObject<any>
|
|
44
100
|
|
|
45
101
|
initialized: boolean
|
|
46
102
|
|
|
103
|
+
unsubscribeToContentComponent?: () => void
|
|
104
|
+
|
|
47
105
|
constructor(props: EditorContentProps) {
|
|
48
106
|
super(props)
|
|
49
107
|
this.editorContentRef = React.createRef()
|
|
50
108
|
this.initialized = false
|
|
51
109
|
|
|
52
110
|
this.state = {
|
|
53
|
-
|
|
111
|
+
hasContentComponentInitialized: Boolean((props.editor as EditorWithContentComponent | null)?.contentComponent),
|
|
54
112
|
}
|
|
55
113
|
}
|
|
56
114
|
|
|
@@ -63,7 +121,7 @@ export class PureEditorContent extends React.Component<EditorContentProps, Edito
|
|
|
63
121
|
}
|
|
64
122
|
|
|
65
123
|
init() {
|
|
66
|
-
const
|
|
124
|
+
const editor = this.props.editor as EditorWithContentComponent | null
|
|
67
125
|
|
|
68
126
|
if (editor && !editor.isDestroyed && editor.options.element) {
|
|
69
127
|
if (editor.contentComponent) {
|
|
@@ -78,7 +136,27 @@ export class PureEditorContent extends React.Component<EditorContentProps, Edito
|
|
|
78
136
|
element,
|
|
79
137
|
})
|
|
80
138
|
|
|
81
|
-
editor.contentComponent =
|
|
139
|
+
editor.contentComponent = getInstance()
|
|
140
|
+
|
|
141
|
+
// Has the content component been initialized?
|
|
142
|
+
if (!this.state.hasContentComponentInitialized) {
|
|
143
|
+
// Subscribe to the content component
|
|
144
|
+
this.unsubscribeToContentComponent = editor.contentComponent.subscribe(() => {
|
|
145
|
+
this.setState(prevState => {
|
|
146
|
+
if (!prevState.hasContentComponentInitialized) {
|
|
147
|
+
return {
|
|
148
|
+
hasContentComponentInitialized: true,
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return prevState
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// Unsubscribe to previous content component
|
|
155
|
+
if (this.unsubscribeToContentComponent) {
|
|
156
|
+
this.unsubscribeToContentComponent()
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
}
|
|
82
160
|
|
|
83
161
|
editor.createNodeViews()
|
|
84
162
|
|
|
@@ -86,43 +164,8 @@ export class PureEditorContent extends React.Component<EditorContentProps, Edito
|
|
|
86
164
|
}
|
|
87
165
|
}
|
|
88
166
|
|
|
89
|
-
maybeFlushSync(fn: () => void) {
|
|
90
|
-
// Avoid calling flushSync until the editor is initialized.
|
|
91
|
-
// Initialization happens during the componentDidMount or componentDidUpdate
|
|
92
|
-
// lifecycle methods, and React doesn't allow calling flushSync from inside
|
|
93
|
-
// a lifecycle method.
|
|
94
|
-
if (this.initialized) {
|
|
95
|
-
flushSync(fn)
|
|
96
|
-
} else {
|
|
97
|
-
fn()
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
setRenderer(id: string, renderer: ReactRenderer) {
|
|
102
|
-
this.maybeFlushSync(() => {
|
|
103
|
-
this.setState(({ renderers }) => ({
|
|
104
|
-
renderers: {
|
|
105
|
-
...renderers,
|
|
106
|
-
[id]: renderer,
|
|
107
|
-
},
|
|
108
|
-
}))
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
removeRenderer(id: string) {
|
|
113
|
-
this.maybeFlushSync(() => {
|
|
114
|
-
this.setState(({ renderers }) => {
|
|
115
|
-
const nextRenderers = { ...renderers }
|
|
116
|
-
|
|
117
|
-
delete nextRenderers[id]
|
|
118
|
-
|
|
119
|
-
return { renderers: nextRenderers }
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
167
|
componentWillUnmount() {
|
|
125
|
-
const
|
|
168
|
+
const editor = this.props.editor as EditorWithContentComponent | null
|
|
126
169
|
|
|
127
170
|
if (!editor) {
|
|
128
171
|
return
|
|
@@ -136,6 +179,10 @@ export class PureEditorContent extends React.Component<EditorContentProps, Edito
|
|
|
136
179
|
})
|
|
137
180
|
}
|
|
138
181
|
|
|
182
|
+
if (this.unsubscribeToContentComponent) {
|
|
183
|
+
this.unsubscribeToContentComponent()
|
|
184
|
+
}
|
|
185
|
+
|
|
139
186
|
editor.contentComponent = null
|
|
140
187
|
|
|
141
188
|
if (!editor.options.element.firstChild) {
|
|
@@ -158,7 +205,7 @@ export class PureEditorContent extends React.Component<EditorContentProps, Edito
|
|
|
158
205
|
<>
|
|
159
206
|
<div ref={mergeRefs(innerRef, this.editorContentRef)} {...rest} />
|
|
160
207
|
{/* @ts-ignore */}
|
|
161
|
-
<Portals
|
|
208
|
+
{editor?.contentComponent && <Portals contentComponent={editor.contentComponent} />}
|
|
162
209
|
</>
|
|
163
210
|
)
|
|
164
211
|
}
|
|
@@ -168,7 +215,8 @@ export class PureEditorContent extends React.Component<EditorContentProps, Edito
|
|
|
168
215
|
const EditorContentWithKey = forwardRef<HTMLDivElement, EditorContentProps>(
|
|
169
216
|
(props: Omit<EditorContentProps, 'innerRef'>, ref) => {
|
|
170
217
|
const key = React.useMemo(() => {
|
|
171
|
-
return Math.floor(Math.random() *
|
|
218
|
+
return Math.floor(Math.random() * 0xffffffff).toString()
|
|
219
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
172
220
|
}, [props.editor])
|
|
173
221
|
|
|
174
222
|
// Can't use JSX here because it conflicts with the type definition of Vue's JSX, so use createElement
|
package/src/FloatingMenu.tsx
CHANGED
|
@@ -1,77 +1,83 @@
|
|
|
1
1
|
import { FloatingMenuPlugin, FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'
|
|
2
|
-
import React, {
|
|
3
|
-
useEffect, useRef,
|
|
4
|
-
} from 'react'
|
|
2
|
+
import React, { useEffect, useRef } from 'react'
|
|
5
3
|
import { createPortal } from 'react-dom'
|
|
6
4
|
|
|
7
5
|
import { useCurrentEditor } from './Context.js'
|
|
8
6
|
|
|
9
|
-
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K
|
|
7
|
+
type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
|
10
8
|
|
|
11
|
-
export type FloatingMenuProps = Omit<
|
|
9
|
+
export type FloatingMenuProps = Omit<
|
|
10
|
+
Optional<FloatingMenuPluginProps, 'pluginKey'>,
|
|
11
|
+
'element' | 'editor'
|
|
12
|
+
> & {
|
|
12
13
|
editor: FloatingMenuPluginProps['editor'] | null;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
options?: FloatingMenuPluginProps['options']
|
|
16
|
-
}
|
|
14
|
+
options?: FloatingMenuPluginProps['options'];
|
|
15
|
+
} & React.HTMLAttributes<HTMLDivElement>;
|
|
17
16
|
|
|
18
|
-
export const FloatingMenu =
|
|
17
|
+
export const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(({
|
|
18
|
+
pluginKey = 'floatingMenu',
|
|
19
|
+
editor,
|
|
20
|
+
shouldShow = null,
|
|
21
|
+
options,
|
|
22
|
+
children,
|
|
23
|
+
...restProps
|
|
24
|
+
}, ref) => {
|
|
19
25
|
const menuEl = useRef(document.createElement('div'))
|
|
26
|
+
|
|
27
|
+
if (typeof ref === 'function') {
|
|
28
|
+
ref(menuEl.current)
|
|
29
|
+
} else if (ref) {
|
|
30
|
+
ref.current = menuEl.current
|
|
31
|
+
}
|
|
32
|
+
|
|
20
33
|
const { editor: currentEditor } = useCurrentEditor()
|
|
21
34
|
|
|
22
35
|
useEffect(() => {
|
|
23
|
-
menuEl.current
|
|
24
|
-
|
|
36
|
+
const floatingMenuElement = menuEl.current
|
|
37
|
+
|
|
38
|
+
floatingMenuElement.style.visibility = 'hidden'
|
|
39
|
+
floatingMenuElement.style.position = 'absolute'
|
|
25
40
|
|
|
26
|
-
if (
|
|
41
|
+
if (editor?.isDestroyed || currentEditor?.isDestroyed) {
|
|
27
42
|
return
|
|
28
43
|
}
|
|
29
44
|
|
|
30
|
-
const
|
|
31
|
-
pluginKey = 'floatingMenu',
|
|
32
|
-
editor,
|
|
33
|
-
options,
|
|
34
|
-
shouldShow = null,
|
|
35
|
-
} = props
|
|
36
|
-
|
|
37
|
-
const menuEditor = editor || currentEditor
|
|
45
|
+
const attachToEditor = editor || currentEditor
|
|
38
46
|
|
|
39
|
-
if (!
|
|
40
|
-
console.warn(
|
|
47
|
+
if (!attachToEditor) {
|
|
48
|
+
console.warn(
|
|
49
|
+
'FloatingMenu component is not rendered inside of an editor component or does not have editor prop.',
|
|
50
|
+
)
|
|
41
51
|
return
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
const plugin = FloatingMenuPlugin({
|
|
55
|
+
editor: attachToEditor,
|
|
56
|
+
element: floatingMenuElement,
|
|
45
57
|
pluginKey,
|
|
46
|
-
editor: menuEditor,
|
|
47
|
-
element: menuEl.current,
|
|
48
|
-
options,
|
|
49
58
|
shouldShow,
|
|
59
|
+
options,
|
|
50
60
|
})
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
attachToEditor.registerPlugin(plugin)
|
|
63
|
+
|
|
53
64
|
return () => {
|
|
54
|
-
|
|
65
|
+
attachToEditor.unregisterPlugin(pluginKey)
|
|
55
66
|
window.requestAnimationFrame(() => {
|
|
56
|
-
if (
|
|
57
|
-
|
|
67
|
+
if (floatingMenuElement.parentNode) {
|
|
68
|
+
floatingMenuElement.parentNode.removeChild(floatingMenuElement)
|
|
58
69
|
}
|
|
59
70
|
})
|
|
60
71
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
currentEditor,
|
|
64
|
-
])
|
|
65
|
-
|
|
66
|
-
const portal = createPortal(
|
|
67
|
-
(
|
|
68
|
-
<div className={props.className}>
|
|
69
|
-
{props.children}
|
|
70
|
-
</div>
|
|
71
|
-
), menuEl.current,
|
|
72
|
-
)
|
|
72
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
73
|
+
}, [editor, currentEditor])
|
|
73
74
|
|
|
74
|
-
return (
|
|
75
|
-
|
|
75
|
+
return createPortal(
|
|
76
|
+
<div
|
|
77
|
+
{...restProps}
|
|
78
|
+
>
|
|
79
|
+
{children}
|
|
80
|
+
</div>,
|
|
81
|
+
menuEl.current,
|
|
76
82
|
)
|
|
77
|
-
}
|
|
83
|
+
})
|
package/src/NodeViewContent.tsx
CHANGED