@handlewithcare/react-prosemirror 2.6.0-tiptap.0 → 2.6.0-tiptap.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/cjs/tiptap/TiptapEditorContent.js +59 -8
- package/dist/cjs/tiptap/TiptapEditorView.js +8 -1
- package/dist/cjs/tiptap/hooks/useTiptapEditor.js +17 -0
- package/dist/cjs/tiptap/index.js +4 -0
- package/dist/cjs/tiptap/tiptapNodeView.js +10 -11
- package/dist/esm/tiptap/TiptapEditorContent.js +60 -9
- package/dist/esm/tiptap/TiptapEditorView.js +8 -1
- package/dist/esm/tiptap/hooks/useTiptapEditor.js +7 -0
- package/dist/esm/tiptap/index.js +1 -0
- package/dist/esm/tiptap/tiptapNodeView.js +11 -12
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/props.d.ts +7 -7
- package/dist/types/tiptap/TiptapEditorContent.d.ts +14 -2
- package/dist/types/tiptap/hooks/useTiptapEditor.d.ts +4 -0
- package/dist/types/tiptap/index.d.ts +1 -0
- package/dist/types/tiptap/tiptapNodeView.d.ts +1 -1
- package/package.json +4 -4
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "TiptapEditorContent", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = require("@tiptap/react");
|
|
12
12
|
const _react1 = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
13
|
+
const _reactdom = require("react-dom");
|
|
13
14
|
const _ProseMirrorDoc = require("../components/ProseMirrorDoc.js");
|
|
14
15
|
const _useEditorEffect = require("../hooks/useEditorEffect.js");
|
|
15
16
|
function _getRequireWildcardCache(nodeInterop) {
|
|
@@ -53,18 +54,62 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
53
54
|
}
|
|
54
55
|
return newObj;
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* This component renders all of the editor's registered "React renderers".
|
|
59
|
+
*/ const Portals = (param)=>{
|
|
60
|
+
let { contentComponent } = param;
|
|
61
|
+
const renderers = (0, _react1.useSyncExternalStore)(contentComponent.subscribe, contentComponent.getSnapshot, contentComponent.getServerSnapshot);
|
|
62
|
+
return /*#__PURE__*/ _react1.default.createElement(_react1.default.Fragment, null, Object.values(renderers));
|
|
63
|
+
};
|
|
64
|
+
function getInstance() {
|
|
65
|
+
const subscribers = new Set();
|
|
66
|
+
let renderers = {};
|
|
67
|
+
return {
|
|
68
|
+
/**
|
|
69
|
+
* Subscribe to the editor instance's changes.
|
|
70
|
+
*/ subscribe (callback) {
|
|
71
|
+
subscribers.add(callback);
|
|
72
|
+
return ()=>{
|
|
73
|
+
subscribers.delete(callback);
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
getSnapshot () {
|
|
77
|
+
return renderers;
|
|
78
|
+
},
|
|
79
|
+
getServerSnapshot () {
|
|
80
|
+
return renderers;
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Adds a new React Renderer to the editor.
|
|
84
|
+
*/ setRenderer (id, renderer) {
|
|
85
|
+
renderers = {
|
|
86
|
+
...renderers,
|
|
87
|
+
[id]: /*#__PURE__*/ (0, _reactdom.createPortal)(renderer.reactElement, renderer.element, id)
|
|
88
|
+
};
|
|
89
|
+
subscribers.forEach((subscriber)=>subscriber());
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* Removes a React Renderer from the editor.
|
|
93
|
+
*/ removeRenderer (id) {
|
|
94
|
+
const nextRenderers = {
|
|
95
|
+
...renderers
|
|
96
|
+
};
|
|
97
|
+
delete nextRenderers[id];
|
|
98
|
+
renderers = nextRenderers;
|
|
99
|
+
subscribers.forEach((subscriber)=>subscriber());
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
56
103
|
function TiptapEditorContent(param) {
|
|
57
|
-
let { editor, ...props } = param;
|
|
104
|
+
let { editor: editorProp, ...props } = param;
|
|
105
|
+
const editor = editorProp;
|
|
58
106
|
(0, _useEditorEffect.useEditorEffect)((view)=>{
|
|
59
107
|
if (editor.view === view) {
|
|
60
108
|
return;
|
|
61
109
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
enumerable: true,
|
|
66
|
-
writable: true
|
|
67
|
-
});
|
|
110
|
+
// @ts-expect-error private property
|
|
111
|
+
editor.editorView = view;
|
|
112
|
+
editor.contentComponent = getInstance();
|
|
68
113
|
// @ts-expect-error private method
|
|
69
114
|
editor.injectCSS();
|
|
70
115
|
const dom = view.dom;
|
|
@@ -79,6 +124,10 @@ function TiptapEditorContent(param) {
|
|
|
79
124
|
});
|
|
80
125
|
editor.isInitialized = true;
|
|
81
126
|
});
|
|
127
|
+
return ()=>{
|
|
128
|
+
editor.isInitialized = false;
|
|
129
|
+
editor.contentComponent = null;
|
|
130
|
+
};
|
|
82
131
|
}, [
|
|
83
132
|
editor
|
|
84
133
|
]);
|
|
@@ -89,5 +138,7 @@ function TiptapEditorContent(param) {
|
|
|
89
138
|
]);
|
|
90
139
|
return /*#__PURE__*/ _react1.default.createElement(_react.EditorContext.Provider, {
|
|
91
140
|
value: contextValue
|
|
92
|
-
}, /*#__PURE__*/ _react1.default.createElement(_ProseMirrorDoc.ProseMirrorDoc, props)
|
|
141
|
+
}, /*#__PURE__*/ _react1.default.createElement(_react1.default.Fragment, null, /*#__PURE__*/ _react1.default.createElement(_ProseMirrorDoc.ProseMirrorDoc, props), editor?.contentComponent && /*#__PURE__*/ _react1.default.createElement(Portals, {
|
|
142
|
+
contentComponent: editor.contentComponent
|
|
143
|
+
})));
|
|
93
144
|
}
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "TiptapEditorView", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
12
|
const _ProseMirror = require("../components/ProseMirror.js");
|
|
13
|
+
const _useForceUpdate = require("../hooks/useForceUpdate.js");
|
|
13
14
|
function _getRequireWildcardCache(nodeInterop) {
|
|
14
15
|
if (typeof WeakMap !== "function") return null;
|
|
15
16
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -53,11 +54,17 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
53
54
|
}
|
|
54
55
|
function TiptapEditorView(param) {
|
|
55
56
|
let { editor, nodeViews, children } = param;
|
|
57
|
+
const forceUpdate = (0, _useForceUpdate.useForceUpdate)();
|
|
56
58
|
const dispatchTransaction = (0, _react.useCallback)((tr)=>{
|
|
57
59
|
// @ts-expect-error calling private method
|
|
58
60
|
editor.dispatchTransaction(tr);
|
|
61
|
+
// Tiptap's dispatchTransaction doesn't trigger
|
|
62
|
+
// a re-render, so we need to manually force
|
|
63
|
+
// one to ensure that React stays in sync.
|
|
64
|
+
forceUpdate();
|
|
59
65
|
}, [
|
|
60
|
-
editor
|
|
66
|
+
editor,
|
|
67
|
+
forceUpdate
|
|
61
68
|
]);
|
|
62
69
|
const initialEditorProps = {
|
|
63
70
|
...editor.options.editorProps,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "useTiptapEditor", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return useTiptapEditor;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = require("@tiptap/react");
|
|
12
|
+
function useTiptapEditor(options, deps) {
|
|
13
|
+
return (0, _react.useEditor)({
|
|
14
|
+
...options,
|
|
15
|
+
element: null
|
|
16
|
+
}, deps);
|
|
17
|
+
}
|
package/dist/cjs/tiptap/index.js
CHANGED
|
@@ -18,6 +18,9 @@ _export(exports, {
|
|
|
18
18
|
tiptapNodeView: function() {
|
|
19
19
|
return _tiptapNodeView.tiptapNodeView;
|
|
20
20
|
},
|
|
21
|
+
useTiptapEditor: function() {
|
|
22
|
+
return _useTiptapEditor.useTiptapEditor;
|
|
23
|
+
},
|
|
21
24
|
useTiptapEditorEffect: function() {
|
|
22
25
|
return _useTiptapEditorEffect.useTiptapEditorEffect;
|
|
23
26
|
},
|
|
@@ -30,3 +33,4 @@ const _TiptapEditorView = require("./TiptapEditorView.js");
|
|
|
30
33
|
const _TiptapEditorContent = require("./TiptapEditorContent.js");
|
|
31
34
|
const _useTiptapEditorEffect = require("./hooks/useTiptapEditorEffect.js");
|
|
32
35
|
const _useTiptapEditorEventCallback = require("./hooks/useTiptapEditorEventCallback.js");
|
|
36
|
+
const _useTiptapEditor = require("./hooks/useTiptapEditor.js");
|
|
@@ -64,10 +64,11 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
64
64
|
return newObj;
|
|
65
65
|
}
|
|
66
66
|
function tiptapNodeView(param) {
|
|
67
|
-
let { component: WrappedComponent, extension, as
|
|
67
|
+
let { component: WrappedComponent, extension, as, className = "", attrs, contentDOMElementTag: InnerTag = "div", stopEvent, ignoreMutation } = param;
|
|
68
68
|
const TiptapNodeView = /*#__PURE__*/ (0, _react1.memo)(/*#__PURE__*/ (0, _react1.forwardRef)(function TiptapNodeView(param, ref) {
|
|
69
69
|
let { children, nodeProps, ...props } = param;
|
|
70
70
|
const { node, getPos, decorations, innerDecorations } = nodeProps;
|
|
71
|
+
const OuterTag = as ?? node.type.isInline ? "span" : "div";
|
|
71
72
|
const { editor } = (0, _react.useCurrentEditor)();
|
|
72
73
|
const extensionManager = editor?.extensionManager ?? null;
|
|
73
74
|
const extensions = extensionManager?.extensions ?? null;
|
|
@@ -142,20 +143,18 @@ function tiptapNodeView(param) {
|
|
|
142
143
|
to
|
|
143
144
|
});
|
|
144
145
|
});
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}, children)
|
|
152
|
-
}), [
|
|
146
|
+
const nodeViewContent = (0, _react1.useMemo)(()=>/*#__PURE__*/ _react1.default.createElement(InnerTag, {
|
|
147
|
+
"data-node-view-content-inner": node.type.name,
|
|
148
|
+
style: {
|
|
149
|
+
whitespace: "inherit"
|
|
150
|
+
}
|
|
151
|
+
}, children), [
|
|
153
152
|
children,
|
|
154
153
|
node.type.name
|
|
155
154
|
]);
|
|
156
155
|
if (!editor) return null;
|
|
157
|
-
return /*#__PURE__*/ _react1.default.createElement(_react.
|
|
158
|
-
|
|
156
|
+
return /*#__PURE__*/ _react1.default.createElement(_react.ReactNodeViewContentProvider, {
|
|
157
|
+
content: nodeViewContent
|
|
159
158
|
}, /*#__PURE__*/ _react1.default.createElement(OuterTag, {
|
|
160
159
|
ref: ref,
|
|
161
160
|
className: finalClassName,
|
|
@@ -1,19 +1,64 @@
|
|
|
1
1
|
import { EditorContext } from "@tiptap/react";
|
|
2
|
-
import React, { useMemo } from "react";
|
|
2
|
+
import React, { useMemo, useSyncExternalStore } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
3
4
|
import { ProseMirrorDoc } from "../components/ProseMirrorDoc.js";
|
|
4
5
|
import { useEditorEffect } from "../hooks/useEditorEffect.js";
|
|
6
|
+
/**
|
|
7
|
+
* This component renders all of the editor's registered "React renderers".
|
|
8
|
+
*/ const Portals = (param)=>{
|
|
9
|
+
let { contentComponent } = param;
|
|
10
|
+
const renderers = useSyncExternalStore(contentComponent.subscribe, contentComponent.getSnapshot, contentComponent.getServerSnapshot);
|
|
11
|
+
return /*#__PURE__*/ React.createElement(React.Fragment, null, Object.values(renderers));
|
|
12
|
+
};
|
|
13
|
+
function getInstance() {
|
|
14
|
+
const subscribers = new Set();
|
|
15
|
+
let renderers = {};
|
|
16
|
+
return {
|
|
17
|
+
/**
|
|
18
|
+
* Subscribe to the editor instance's changes.
|
|
19
|
+
*/ subscribe (callback) {
|
|
20
|
+
subscribers.add(callback);
|
|
21
|
+
return ()=>{
|
|
22
|
+
subscribers.delete(callback);
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
getSnapshot () {
|
|
26
|
+
return renderers;
|
|
27
|
+
},
|
|
28
|
+
getServerSnapshot () {
|
|
29
|
+
return renderers;
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
* Adds a new React Renderer to the editor.
|
|
33
|
+
*/ setRenderer (id, renderer) {
|
|
34
|
+
renderers = {
|
|
35
|
+
...renderers,
|
|
36
|
+
[id]: /*#__PURE__*/ createPortal(renderer.reactElement, renderer.element, id)
|
|
37
|
+
};
|
|
38
|
+
subscribers.forEach((subscriber)=>subscriber());
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Removes a React Renderer from the editor.
|
|
42
|
+
*/ removeRenderer (id) {
|
|
43
|
+
const nextRenderers = {
|
|
44
|
+
...renderers
|
|
45
|
+
};
|
|
46
|
+
delete nextRenderers[id];
|
|
47
|
+
renderers = nextRenderers;
|
|
48
|
+
subscribers.forEach((subscriber)=>subscriber());
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
5
52
|
export function TiptapEditorContent(param) {
|
|
6
|
-
let { editor, ...props } = param;
|
|
53
|
+
let { editor: editorProp, ...props } = param;
|
|
54
|
+
const editor = editorProp;
|
|
7
55
|
useEditorEffect((view)=>{
|
|
8
56
|
if (editor.view === view) {
|
|
9
57
|
return;
|
|
10
58
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
enumerable: true,
|
|
15
|
-
writable: true
|
|
16
|
-
});
|
|
59
|
+
// @ts-expect-error private property
|
|
60
|
+
editor.editorView = view;
|
|
61
|
+
editor.contentComponent = getInstance();
|
|
17
62
|
// @ts-expect-error private method
|
|
18
63
|
editor.injectCSS();
|
|
19
64
|
const dom = view.dom;
|
|
@@ -28,6 +73,10 @@ export function TiptapEditorContent(param) {
|
|
|
28
73
|
});
|
|
29
74
|
editor.isInitialized = true;
|
|
30
75
|
});
|
|
76
|
+
return ()=>{
|
|
77
|
+
editor.isInitialized = false;
|
|
78
|
+
editor.contentComponent = null;
|
|
79
|
+
};
|
|
31
80
|
}, [
|
|
32
81
|
editor
|
|
33
82
|
]);
|
|
@@ -38,5 +87,7 @@ export function TiptapEditorContent(param) {
|
|
|
38
87
|
]);
|
|
39
88
|
return /*#__PURE__*/ React.createElement(EditorContext.Provider, {
|
|
40
89
|
value: contextValue
|
|
41
|
-
}, /*#__PURE__*/ React.createElement(ProseMirrorDoc, props)
|
|
90
|
+
}, /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(ProseMirrorDoc, props), editor?.contentComponent && /*#__PURE__*/ React.createElement(Portals, {
|
|
91
|
+
contentComponent: editor.contentComponent
|
|
92
|
+
})));
|
|
42
93
|
}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import React, { useCallback } from "react";
|
|
2
2
|
import { ProseMirror } from "../components/ProseMirror.js";
|
|
3
|
+
import { useForceUpdate } from "../hooks/useForceUpdate.js";
|
|
3
4
|
/**
|
|
4
5
|
* Render a Tiptap-compatible React ProseMirror editor.
|
|
5
6
|
*/ export function TiptapEditorView(param) {
|
|
6
7
|
let { editor, nodeViews, children } = param;
|
|
8
|
+
const forceUpdate = useForceUpdate();
|
|
7
9
|
const dispatchTransaction = useCallback((tr)=>{
|
|
8
10
|
// @ts-expect-error calling private method
|
|
9
11
|
editor.dispatchTransaction(tr);
|
|
12
|
+
// Tiptap's dispatchTransaction doesn't trigger
|
|
13
|
+
// a re-render, so we need to manually force
|
|
14
|
+
// one to ensure that React stays in sync.
|
|
15
|
+
forceUpdate();
|
|
10
16
|
}, [
|
|
11
|
-
editor
|
|
17
|
+
editor,
|
|
18
|
+
forceUpdate
|
|
12
19
|
]);
|
|
13
20
|
const initialEditorProps = {
|
|
14
21
|
...editor.options.editorProps,
|
package/dist/esm/tiptap/index.js
CHANGED
|
@@ -3,3 +3,4 @@ export { TiptapEditorView } from "./TiptapEditorView.js";
|
|
|
3
3
|
export { TiptapEditorContent } from "./TiptapEditorContent.js";
|
|
4
4
|
export { useTiptapEditorEffect } from "./hooks/useTiptapEditorEffect.js";
|
|
5
5
|
export { useTiptapEditorEventCallback } from "./hooks/useTiptapEditorEventCallback.js";
|
|
6
|
+
export { useTiptapEditor } from "./hooks/useTiptapEditor.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getAttributesFromExtensions, getRenderedAttributes } from "@tiptap/core";
|
|
2
|
-
import {
|
|
2
|
+
import { ReactNodeViewContentProvider, useCurrentEditor } from "@tiptap/react";
|
|
3
3
|
import cx from "classnames";
|
|
4
4
|
import React, { forwardRef, memo, useMemo, useRef } from "react";
|
|
5
5
|
import { useEditorEventCallback } from "../hooks/useEditorEventCallback.js";
|
|
@@ -32,10 +32,11 @@ import { htmlAttrsToReactProps } from "../props.js";
|
|
|
32
32
|
* }
|
|
33
33
|
* ```
|
|
34
34
|
*/ export function tiptapNodeView(param) {
|
|
35
|
-
let { component: WrappedComponent, extension, as
|
|
35
|
+
let { component: WrappedComponent, extension, as, className = "", attrs, contentDOMElementTag: InnerTag = "div", stopEvent, ignoreMutation } = param;
|
|
36
36
|
const TiptapNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function TiptapNodeView(param, ref) {
|
|
37
37
|
let { children, nodeProps, ...props } = param;
|
|
38
38
|
const { node, getPos, decorations, innerDecorations } = nodeProps;
|
|
39
|
+
const OuterTag = as ?? node.type.isInline ? "span" : "div";
|
|
39
40
|
const { editor } = useCurrentEditor();
|
|
40
41
|
const extensionManager = editor?.extensionManager ?? null;
|
|
41
42
|
const extensions = extensionManager?.extensions ?? null;
|
|
@@ -110,20 +111,18 @@ import { htmlAttrsToReactProps } from "../props.js";
|
|
|
110
111
|
to
|
|
111
112
|
});
|
|
112
113
|
});
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}, children)
|
|
120
|
-
}), [
|
|
114
|
+
const nodeViewContent = useMemo(()=>/*#__PURE__*/ React.createElement(InnerTag, {
|
|
115
|
+
"data-node-view-content-inner": node.type.name,
|
|
116
|
+
style: {
|
|
117
|
+
whitespace: "inherit"
|
|
118
|
+
}
|
|
119
|
+
}, children), [
|
|
121
120
|
children,
|
|
122
121
|
node.type.name
|
|
123
122
|
]);
|
|
124
123
|
if (!editor) return null;
|
|
125
|
-
return /*#__PURE__*/ React.createElement(
|
|
126
|
-
|
|
124
|
+
return /*#__PURE__*/ React.createElement(ReactNodeViewContentProvider, {
|
|
125
|
+
content: nodeViewContent
|
|
127
126
|
}, /*#__PURE__*/ React.createElement(OuterTag, {
|
|
128
127
|
ref: ref,
|
|
129
128
|
className: finalClassName,
|