@tiptap/react 2.0.0-beta.21 → 2.0.0-beta.210

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.
Files changed (37) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +437 -0
  3. package/dist/index.d.ts +101 -0
  4. package/dist/index.js +437 -0
  5. package/package.json +45 -16
  6. package/src/BubbleMenu.tsx +32 -16
  7. package/src/Editor.ts +9 -2
  8. package/src/EditorContent.tsx +55 -12
  9. package/src/FloatingMenu.tsx +36 -14
  10. package/src/NodeViewContent.tsx +10 -3
  11. package/src/NodeViewWrapper.tsx +11 -8
  12. package/src/ReactNodeViewRenderer.tsx +82 -34
  13. package/src/ReactRenderer.tsx +38 -29
  14. package/src/index.ts +6 -6
  15. package/src/useEditor.ts +16 -4
  16. package/src/useReactNodeView.ts +1 -0
  17. package/CHANGELOG.md +0 -190
  18. package/LICENSE.md +0 -21
  19. package/dist/packages/react/src/BubbleMenu.d.ts +0 -6
  20. package/dist/packages/react/src/Editor.d.ts +0 -6
  21. package/dist/packages/react/src/EditorContent.d.ts +0 -19
  22. package/dist/packages/react/src/FloatingMenu.d.ts +0 -6
  23. package/dist/packages/react/src/NodeViewContent.d.ts +0 -6
  24. package/dist/packages/react/src/NodeViewWrapper.d.ts +0 -6
  25. package/dist/packages/react/src/ReactNodeViewRenderer.d.ts +0 -9
  26. package/dist/packages/react/src/ReactRenderer.d.ts +0 -21
  27. package/dist/packages/react/src/index.d.ts +0 -10
  28. package/dist/packages/react/src/useEditor.d.ts +0 -3
  29. package/dist/packages/react/src/useReactNodeView.d.ts +0 -6
  30. package/dist/tiptap-react.bundle.umd.min.js +0 -54
  31. package/dist/tiptap-react.bundle.umd.min.js.map +0 -1
  32. package/dist/tiptap-react.cjs.js +0 -318
  33. package/dist/tiptap-react.cjs.js.map +0 -1
  34. package/dist/tiptap-react.esm.js +0 -293
  35. package/dist/tiptap-react.esm.js.map +0 -1
  36. package/dist/tiptap-react.umd.js +0 -318
  37. package/dist/tiptap-react.umd.js.map +0 -1
package/README.md CHANGED
@@ -7,8 +7,8 @@
7
7
  ## Introduction
8
8
  tiptap is a headless wrapper around [ProseMirror](https://ProseMirror.net) – a toolkit for building rich text WYSIWYG editors, which is already in use at many well-known companies such as *New York Times*, *The Guardian* or *Atlassian*.
9
9
 
10
- ## Offical Documentation
10
+ ## Official Documentation
11
11
  Documentation can be found on the [tiptap website](https://tiptap.dev).
12
12
 
13
13
  ## License
14
- tiptap is open sourced software licensed under the [MIT license](https://github.com/ueberdosis/tiptap-next/blob/main/LICENSE.md).
14
+ tiptap is open sourced software licensed under the [MIT license](https://github.com/ueberdosis/tiptap/blob/main/LICENSE.md).
package/dist/index.cjs ADDED
@@ -0,0 +1,437 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }// src/BubbleMenu.tsx
2
+ var _extensionbubblemenu = require('@tiptap/extension-bubble-menu');
3
+ var _react = require('react'); var _react2 = _interopRequireDefault(_react);
4
+ var BubbleMenu = (props) => {
5
+ const [element, setElement] = _react.useState.call(void 0, null);
6
+ _react.useEffect.call(void 0, () => {
7
+ if (!element) {
8
+ return;
9
+ }
10
+ if (props.editor.isDestroyed) {
11
+ return;
12
+ }
13
+ const {
14
+ pluginKey = "bubbleMenu",
15
+ editor,
16
+ tippyOptions = {},
17
+ updateDelay,
18
+ shouldShow = null
19
+ } = props;
20
+ const plugin = _extensionbubblemenu.BubbleMenuPlugin.call(void 0, {
21
+ updateDelay,
22
+ editor,
23
+ element,
24
+ pluginKey,
25
+ shouldShow,
26
+ tippyOptions
27
+ });
28
+ editor.registerPlugin(plugin);
29
+ return () => editor.unregisterPlugin(pluginKey);
30
+ }, [props.editor, element]);
31
+ return /* @__PURE__ */ _react2.default.createElement("div", { ref: setElement, className: props.className, style: { visibility: "hidden" } }, props.children);
32
+ };
33
+
34
+ // src/Editor.ts
35
+ var _core = require('@tiptap/core'); _createStarExport(_core);
36
+ var Editor = class extends _core.Editor {
37
+ constructor() {
38
+ super(...arguments);
39
+ this.contentComponent = null;
40
+ }
41
+ };
42
+
43
+ // src/EditorContent.tsx
44
+
45
+ var _reactdom = require('react-dom'); var _reactdom2 = _interopRequireDefault(_reactdom);
46
+ var Portals = ({ renderers }) => {
47
+ return /* @__PURE__ */ _react2.default.createElement(_react2.default.Fragment, null, Object.entries(renderers).map(([key, renderer]) => {
48
+ return _reactdom2.default.createPortal(
49
+ renderer.reactElement,
50
+ renderer.element,
51
+ key
52
+ );
53
+ }));
54
+ };
55
+ var PureEditorContent = class extends _react2.default.Component {
56
+ constructor(props) {
57
+ super(props);
58
+ this.editorContentRef = _react2.default.createRef();
59
+ this.initialized = false;
60
+ this.state = {
61
+ renderers: {}
62
+ };
63
+ }
64
+ componentDidMount() {
65
+ this.init();
66
+ }
67
+ componentDidUpdate() {
68
+ this.init();
69
+ }
70
+ init() {
71
+ const { editor } = this.props;
72
+ if (editor && editor.options.element) {
73
+ if (editor.contentComponent) {
74
+ return;
75
+ }
76
+ const element = this.editorContentRef.current;
77
+ element.append(...editor.options.element.childNodes);
78
+ editor.setOptions({
79
+ element
80
+ });
81
+ editor.contentComponent = this;
82
+ editor.createNodeViews();
83
+ this.initialized = true;
84
+ }
85
+ }
86
+ maybeFlushSync(fn) {
87
+ if (this.initialized) {
88
+ _reactdom.flushSync.call(void 0, fn);
89
+ } else {
90
+ fn();
91
+ }
92
+ }
93
+ setRenderer(id, renderer) {
94
+ this.maybeFlushSync(() => {
95
+ this.setState(({ renderers }) => ({
96
+ renderers: {
97
+ ...renderers,
98
+ [id]: renderer
99
+ }
100
+ }));
101
+ });
102
+ }
103
+ removeRenderer(id) {
104
+ this.maybeFlushSync(() => {
105
+ this.setState(({ renderers }) => {
106
+ const nextRenderers = { ...renderers };
107
+ delete nextRenderers[id];
108
+ return { renderers: nextRenderers };
109
+ });
110
+ });
111
+ }
112
+ componentWillUnmount() {
113
+ const { editor } = this.props;
114
+ if (!editor) {
115
+ return;
116
+ }
117
+ if (!editor.isDestroyed) {
118
+ editor.view.setProps({
119
+ nodeViews: {}
120
+ });
121
+ }
122
+ editor.contentComponent = null;
123
+ if (!editor.options.element.firstChild) {
124
+ return;
125
+ }
126
+ const newElement = document.createElement("div");
127
+ newElement.append(...editor.options.element.childNodes);
128
+ editor.setOptions({
129
+ element: newElement
130
+ });
131
+ }
132
+ render() {
133
+ const { editor, ...rest } = this.props;
134
+ return /* @__PURE__ */ _react2.default.createElement(_react2.default.Fragment, null, /* @__PURE__ */ _react2.default.createElement("div", { ref: this.editorContentRef, ...rest }), /* @__PURE__ */ _react2.default.createElement(Portals, { renderers: this.state.renderers }));
135
+ }
136
+ };
137
+ var EditorContent = _react2.default.memo(PureEditorContent);
138
+
139
+ // src/FloatingMenu.tsx
140
+ var _extensionfloatingmenu = require('@tiptap/extension-floating-menu');
141
+
142
+
143
+
144
+
145
+ var FloatingMenu = (props) => {
146
+ const [element, setElement] = _react.useState.call(void 0, null);
147
+ _react.useEffect.call(void 0, () => {
148
+ if (!element) {
149
+ return;
150
+ }
151
+ if (props.editor.isDestroyed) {
152
+ return;
153
+ }
154
+ const {
155
+ pluginKey = "floatingMenu",
156
+ editor,
157
+ tippyOptions = {},
158
+ shouldShow = null
159
+ } = props;
160
+ const plugin = _extensionfloatingmenu.FloatingMenuPlugin.call(void 0, {
161
+ pluginKey,
162
+ editor,
163
+ element,
164
+ tippyOptions,
165
+ shouldShow
166
+ });
167
+ editor.registerPlugin(plugin);
168
+ return () => editor.unregisterPlugin(pluginKey);
169
+ }, [
170
+ props.editor,
171
+ element
172
+ ]);
173
+ return /* @__PURE__ */ _react2.default.createElement("div", { ref: setElement, className: props.className, style: { visibility: "hidden" } }, props.children);
174
+ };
175
+
176
+ // src/NodeViewContent.tsx
177
+
178
+
179
+ // src/useReactNodeView.ts
180
+
181
+ var ReactNodeViewContext = _react.createContext.call(void 0, {
182
+ onDragStart: void 0
183
+ });
184
+ var useReactNodeView = () => _react.useContext.call(void 0, ReactNodeViewContext);
185
+
186
+ // src/NodeViewContent.tsx
187
+ var NodeViewContent = (props) => {
188
+ const Tag = props.as || "div";
189
+ const { nodeViewContentRef } = useReactNodeView();
190
+ return /* @__PURE__ */ _react2.default.createElement(
191
+ Tag,
192
+ {
193
+ ...props,
194
+ ref: nodeViewContentRef,
195
+ "data-node-view-content": "",
196
+ style: {
197
+ whiteSpace: "pre-wrap",
198
+ ...props.style
199
+ }
200
+ }
201
+ );
202
+ };
203
+
204
+ // src/NodeViewWrapper.tsx
205
+
206
+ var NodeViewWrapper = _react2.default.forwardRef((props, ref) => {
207
+ const { onDragStart } = useReactNodeView();
208
+ const Tag = props.as || "div";
209
+ return /* @__PURE__ */ _react2.default.createElement(
210
+ Tag,
211
+ {
212
+ ...props,
213
+ ref,
214
+ "data-node-view-wrapper": "",
215
+ onDragStart,
216
+ style: {
217
+ whiteSpace: "normal",
218
+ ...props.style
219
+ }
220
+ }
221
+ );
222
+ });
223
+
224
+ // src/ReactNodeViewRenderer.tsx
225
+
226
+
227
+
228
+
229
+
230
+ // src/ReactRenderer.tsx
231
+
232
+ function isClassComponent(Component) {
233
+ return !!(typeof Component === "function" && Component.prototype && Component.prototype.isReactComponent);
234
+ }
235
+ function isForwardRefComponent(Component) {
236
+ var _a;
237
+ return !!(typeof Component === "object" && ((_a = Component.$$typeof) == null ? void 0 : _a.toString()) === "Symbol(react.forward_ref)");
238
+ }
239
+ var ReactRenderer = class {
240
+ constructor(component, {
241
+ editor,
242
+ props = {},
243
+ as = "div",
244
+ className = ""
245
+ }) {
246
+ this.ref = null;
247
+ this.id = Math.floor(Math.random() * 4294967295).toString();
248
+ this.component = component;
249
+ this.editor = editor;
250
+ this.props = props;
251
+ this.element = document.createElement(as);
252
+ this.element.classList.add("react-renderer");
253
+ if (className) {
254
+ this.element.classList.add(...className.split(" "));
255
+ }
256
+ this.render();
257
+ }
258
+ render() {
259
+ var _a, _b;
260
+ const Component = this.component;
261
+ const props = this.props;
262
+ if (isClassComponent(Component) || isForwardRefComponent(Component)) {
263
+ props.ref = (ref) => {
264
+ this.ref = ref;
265
+ };
266
+ }
267
+ this.reactElement = /* @__PURE__ */ _react2.default.createElement(Component, { ...props });
268
+ (_b = (_a = this.editor) == null ? void 0 : _a.contentComponent) == null ? void 0 : _b.setRenderer(this.id, this);
269
+ }
270
+ updateProps(props = {}) {
271
+ this.props = {
272
+ ...this.props,
273
+ ...props
274
+ };
275
+ this.render();
276
+ }
277
+ destroy() {
278
+ var _a, _b;
279
+ (_b = (_a = this.editor) == null ? void 0 : _a.contentComponent) == null ? void 0 : _b.removeRenderer(this.id);
280
+ }
281
+ };
282
+
283
+ // src/ReactNodeViewRenderer.tsx
284
+ var ReactNodeView = class extends _core.NodeView {
285
+ mount() {
286
+ const props = {
287
+ editor: this.editor,
288
+ node: this.node,
289
+ decorations: this.decorations,
290
+ selected: false,
291
+ extension: this.extension,
292
+ getPos: () => this.getPos(),
293
+ updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
294
+ deleteNode: () => this.deleteNode()
295
+ };
296
+ if (!this.component.displayName) {
297
+ const capitalizeFirstChar = (string) => {
298
+ return string.charAt(0).toUpperCase() + string.substring(1);
299
+ };
300
+ this.component.displayName = capitalizeFirstChar(this.extension.name);
301
+ }
302
+ const ReactNodeViewProvider = (componentProps) => {
303
+ const Component = this.component;
304
+ const onDragStart = this.onDragStart.bind(this);
305
+ const nodeViewContentRef = (element) => {
306
+ if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
307
+ element.appendChild(this.contentDOMElement);
308
+ }
309
+ };
310
+ return /* @__PURE__ */ _react2.default.createElement(_react2.default.Fragment, null, /* @__PURE__ */ _react2.default.createElement(ReactNodeViewContext.Provider, { value: { onDragStart, nodeViewContentRef } }, /* @__PURE__ */ _react2.default.createElement(Component, { ...componentProps })));
311
+ };
312
+ ReactNodeViewProvider.displayName = "ReactNodeView";
313
+ this.contentDOMElement = this.node.isLeaf ? null : document.createElement(this.node.isInline ? "span" : "div");
314
+ if (this.contentDOMElement) {
315
+ this.contentDOMElement.style.whiteSpace = "inherit";
316
+ }
317
+ let as = this.node.isInline ? "span" : "div";
318
+ if (this.options.as) {
319
+ as = this.options.as;
320
+ }
321
+ const { className = "" } = this.options;
322
+ this.renderer = new ReactRenderer(ReactNodeViewProvider, {
323
+ editor: this.editor,
324
+ props,
325
+ as,
326
+ className: `node-${this.node.type.name} ${className}`.trim()
327
+ });
328
+ }
329
+ get dom() {
330
+ var _a;
331
+ if (this.renderer.element.firstElementChild && !((_a = this.renderer.element.firstElementChild) == null ? void 0 : _a.hasAttribute("data-node-view-wrapper"))) {
332
+ throw Error("Please use the NodeViewWrapper component for your node view.");
333
+ }
334
+ return this.renderer.element;
335
+ }
336
+ get contentDOM() {
337
+ if (this.node.isLeaf) {
338
+ return null;
339
+ }
340
+ return this.contentDOMElement;
341
+ }
342
+ update(node, decorations) {
343
+ const updateProps = (props) => {
344
+ this.renderer.updateProps(props);
345
+ };
346
+ if (node.type !== this.node.type) {
347
+ return false;
348
+ }
349
+ if (typeof this.options.update === "function") {
350
+ const oldNode = this.node;
351
+ const oldDecorations = this.decorations;
352
+ this.node = node;
353
+ this.decorations = decorations;
354
+ return this.options.update({
355
+ oldNode,
356
+ oldDecorations,
357
+ newNode: node,
358
+ newDecorations: decorations,
359
+ updateProps: () => updateProps({ node, decorations })
360
+ });
361
+ }
362
+ if (node === this.node && this.decorations === decorations) {
363
+ return true;
364
+ }
365
+ this.node = node;
366
+ this.decorations = decorations;
367
+ updateProps({ node, decorations });
368
+ return true;
369
+ }
370
+ selectNode() {
371
+ this.renderer.updateProps({
372
+ selected: true
373
+ });
374
+ }
375
+ deselectNode() {
376
+ this.renderer.updateProps({
377
+ selected: false
378
+ });
379
+ }
380
+ destroy() {
381
+ this.renderer.destroy();
382
+ this.contentDOMElement = null;
383
+ }
384
+ };
385
+ function ReactNodeViewRenderer(component, options) {
386
+ return (props) => {
387
+ if (!props.editor.contentComponent) {
388
+ return {};
389
+ }
390
+ return new ReactNodeView(component, props, options);
391
+ };
392
+ }
393
+
394
+ // src/useEditor.ts
395
+
396
+ function useForceUpdate() {
397
+ const [, setValue] = _react.useState.call(void 0, 0);
398
+ return () => setValue((value) => value + 1);
399
+ }
400
+ var useEditor = (options = {}, deps = []) => {
401
+ const [editor, setEditor] = _react.useState.call(void 0, null);
402
+ const forceUpdate = useForceUpdate();
403
+ _react.useEffect.call(void 0, () => {
404
+ let isMounted = true;
405
+ const instance = new Editor(options);
406
+ setEditor(instance);
407
+ instance.on("transaction", () => {
408
+ requestAnimationFrame(() => {
409
+ requestAnimationFrame(() => {
410
+ if (isMounted) {
411
+ forceUpdate();
412
+ }
413
+ });
414
+ });
415
+ });
416
+ return () => {
417
+ instance.destroy();
418
+ isMounted = false;
419
+ };
420
+ }, deps);
421
+ return editor;
422
+ };
423
+
424
+ // src/index.ts
425
+
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436
+
437
+ exports.BubbleMenu = BubbleMenu; exports.Editor = Editor; exports.EditorContent = EditorContent; exports.FloatingMenu = FloatingMenu; exports.NodeViewContent = NodeViewContent; exports.NodeViewWrapper = NodeViewWrapper; exports.PureEditorContent = PureEditorContent; exports.ReactNodeViewRenderer = ReactNodeViewRenderer; exports.ReactRenderer = ReactRenderer; exports.useEditor = useEditor;
@@ -0,0 +1,101 @@
1
+ import { BubbleMenuPluginProps } from '@tiptap/extension-bubble-menu';
2
+ import React, { HTMLProps, DependencyList } from 'react';
3
+ import { Editor as Editor$1, NodeViewRendererOptions, NodeViewRenderer, EditorOptions } from '@tiptap/core';
4
+ export * from '@tiptap/core';
5
+ import { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu';
6
+ import { Node } from '@tiptap/pm/model';
7
+ import { Decoration } from '@tiptap/pm/view';
8
+
9
+ declare type Optional$1<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
10
+ declare type BubbleMenuProps = Omit<Optional$1<BubbleMenuPluginProps, 'pluginKey'>, 'element'> & {
11
+ className?: string;
12
+ children: React.ReactNode;
13
+ updateDelay?: number;
14
+ };
15
+ declare const BubbleMenu: (props: BubbleMenuProps) => JSX.Element;
16
+
17
+ interface ReactRendererOptions {
18
+ editor: Editor$1;
19
+ props?: Record<string, any>;
20
+ as?: string;
21
+ className?: string;
22
+ }
23
+ declare type ComponentType<R, P> = React.ComponentClass<P> | React.FunctionComponent<P> | React.ForwardRefExoticComponent<React.PropsWithoutRef<P> & React.RefAttributes<R>>;
24
+ declare class ReactRenderer<R = unknown, P = unknown> {
25
+ id: string;
26
+ editor: Editor;
27
+ component: any;
28
+ element: Element;
29
+ props: Record<string, any>;
30
+ reactElement: React.ReactNode;
31
+ ref: R | null;
32
+ constructor(component: ComponentType<R, P>, { editor, props, as, className, }: ReactRendererOptions);
33
+ render(): void;
34
+ updateProps(props?: Record<string, any>): void;
35
+ destroy(): void;
36
+ }
37
+
38
+ interface EditorContentProps extends HTMLProps<HTMLDivElement> {
39
+ editor: Editor | null;
40
+ }
41
+ interface EditorContentState {
42
+ renderers: Record<string, ReactRenderer>;
43
+ }
44
+ declare class PureEditorContent extends React.Component<EditorContentProps, EditorContentState> {
45
+ editorContentRef: React.RefObject<any>;
46
+ initialized: boolean;
47
+ constructor(props: EditorContentProps);
48
+ componentDidMount(): void;
49
+ componentDidUpdate(): void;
50
+ init(): void;
51
+ maybeFlushSync(fn: () => void): void;
52
+ setRenderer(id: string, renderer: ReactRenderer): void;
53
+ removeRenderer(id: string): void;
54
+ componentWillUnmount(): void;
55
+ render(): JSX.Element;
56
+ }
57
+ declare const EditorContent: React.MemoExoticComponent<typeof PureEditorContent>;
58
+
59
+ declare type ContentComponent = React.Component<EditorContentProps, EditorContentState> & {
60
+ setRenderer(id: string, renderer: ReactRenderer): void;
61
+ removeRenderer(id: string): void;
62
+ };
63
+ declare class Editor extends Editor$1 {
64
+ contentComponent: ContentComponent | null;
65
+ }
66
+
67
+ declare type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
68
+ declare type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element'> & {
69
+ className?: string;
70
+ children: React.ReactNode;
71
+ };
72
+ declare const FloatingMenu: (props: FloatingMenuProps) => JSX.Element;
73
+
74
+ interface NodeViewContentProps {
75
+ [key: string]: any;
76
+ as?: React.ElementType;
77
+ }
78
+ declare const NodeViewContent: React.FC<NodeViewContentProps>;
79
+
80
+ interface NodeViewWrapperProps {
81
+ [key: string]: any;
82
+ as?: React.ElementType;
83
+ }
84
+ declare const NodeViewWrapper: React.FC<NodeViewWrapperProps>;
85
+
86
+ interface ReactNodeViewRendererOptions extends NodeViewRendererOptions {
87
+ update: ((props: {
88
+ oldNode: Node;
89
+ oldDecorations: Decoration[];
90
+ newNode: Node;
91
+ newDecorations: Decoration[];
92
+ updateProps: () => void;
93
+ }) => boolean) | null;
94
+ as?: string;
95
+ className?: string;
96
+ }
97
+ declare function ReactNodeViewRenderer(component: any, options?: Partial<ReactNodeViewRendererOptions>): NodeViewRenderer;
98
+
99
+ declare const useEditor: (options?: Partial<EditorOptions>, deps?: DependencyList) => Editor | null;
100
+
101
+ export { BubbleMenu, BubbleMenuProps, Editor, EditorContent, EditorContentProps, EditorContentState, FloatingMenu, FloatingMenuProps, NodeViewContent, NodeViewContentProps, NodeViewWrapper, NodeViewWrapperProps, PureEditorContent, ReactNodeViewRenderer, ReactNodeViewRendererOptions, ReactRenderer, ReactRendererOptions, useEditor };