@tiptap/react 3.0.0-next.1 → 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 +255 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +155 -42
- package/dist/index.d.ts +155 -42
- package/dist/index.js +244 -113
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
- package/src/BubbleMenu.tsx +70 -50
- package/src/Context.tsx +14 -6
- package/src/FloatingMenu.tsx +51 -45
- package/src/ReactNodeViewRenderer.tsx +152 -41
- package/src/ReactRenderer.tsx +26 -19
- package/src/useEditor.ts +17 -9
- package/src/useEditorState.ts +49 -10
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,7 @@ __export(src_exports, {
|
|
|
40
40
|
NodeViewContent: () => NodeViewContent,
|
|
41
41
|
NodeViewWrapper: () => NodeViewWrapper,
|
|
42
42
|
PureEditorContent: () => PureEditorContent,
|
|
43
|
+
ReactNodeView: () => ReactNodeView,
|
|
43
44
|
ReactNodeViewContext: () => ReactNodeViewContext,
|
|
44
45
|
ReactNodeViewRenderer: () => ReactNodeViewRenderer,
|
|
45
46
|
ReactRenderer: () => ReactRenderer,
|
|
@@ -52,11 +53,11 @@ module.exports = __toCommonJS(src_exports);
|
|
|
52
53
|
|
|
53
54
|
// src/BubbleMenu.tsx
|
|
54
55
|
var import_extension_bubble_menu = require("@tiptap/extension-bubble-menu");
|
|
55
|
-
var
|
|
56
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
56
57
|
var import_react_dom2 = require("react-dom");
|
|
57
58
|
|
|
58
59
|
// src/Context.tsx
|
|
59
|
-
var
|
|
60
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
60
61
|
|
|
61
62
|
// src/EditorContent.tsx
|
|
62
63
|
var import_react = __toESM(require("react"), 1);
|
|
@@ -215,12 +216,14 @@ var EditorContent = import_react.default.memo(EditorContentWithKey);
|
|
|
215
216
|
|
|
216
217
|
// src/useEditor.ts
|
|
217
218
|
var import_core = require("@tiptap/core");
|
|
218
|
-
var
|
|
219
|
+
var import_react4 = require("react");
|
|
219
220
|
var import_shim2 = require("use-sync-external-store/shim");
|
|
220
221
|
|
|
221
222
|
// src/useEditorState.ts
|
|
222
|
-
var import_react2 = require("react");
|
|
223
|
+
var import_react2 = __toESM(require("fast-deep-equal/es6/react"), 1);
|
|
224
|
+
var import_react3 = require("react");
|
|
223
225
|
var import_with_selector = require("use-sync-external-store/shim/with-selector");
|
|
226
|
+
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react3.useLayoutEffect : import_react3.useEffect;
|
|
224
227
|
var EditorStateManager = class {
|
|
225
228
|
constructor(initialEditor) {
|
|
226
229
|
this.transactionNumber = 0;
|
|
@@ -279,18 +282,19 @@ var EditorStateManager = class {
|
|
|
279
282
|
}
|
|
280
283
|
};
|
|
281
284
|
function useEditorState(options) {
|
|
282
|
-
|
|
285
|
+
var _a;
|
|
286
|
+
const [editorStateManager] = (0, import_react3.useState)(() => new EditorStateManager(options.editor));
|
|
283
287
|
const selectedState = (0, import_with_selector.useSyncExternalStoreWithSelector)(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
288
|
+
editorStateManager.subscribe,
|
|
289
|
+
editorStateManager.getSnapshot,
|
|
290
|
+
editorStateManager.getServerSnapshot,
|
|
287
291
|
options.selector,
|
|
288
|
-
options.equalityFn
|
|
292
|
+
(_a = options.equalityFn) != null ? _a : import_react2.default
|
|
289
293
|
);
|
|
290
|
-
(
|
|
291
|
-
return
|
|
292
|
-
}, [options.editor,
|
|
293
|
-
(0,
|
|
294
|
+
useIsomorphicLayoutEffect(() => {
|
|
295
|
+
return editorStateManager.watch(options.editor);
|
|
296
|
+
}, [options.editor, editorStateManager]);
|
|
297
|
+
(0, import_react3.useDebugValue)(selectedState);
|
|
294
298
|
return selectedState;
|
|
295
299
|
}
|
|
296
300
|
|
|
@@ -324,6 +328,7 @@ var EditorInstanceManager = class {
|
|
|
324
328
|
this.options = options;
|
|
325
329
|
this.subscriptions = /* @__PURE__ */ new Set();
|
|
326
330
|
this.setEditor(this.getInitialEditor());
|
|
331
|
+
this.scheduleDestroy();
|
|
327
332
|
this.getEditor = this.getEditor.bind(this);
|
|
328
333
|
this.getServerSnapshot = this.getServerSnapshot.bind(this);
|
|
329
334
|
this.subscribe = this.subscribe.bind(this);
|
|
@@ -401,6 +406,14 @@ var EditorInstanceManager = class {
|
|
|
401
406
|
onContentError: (...args) => {
|
|
402
407
|
var _a, _b;
|
|
403
408
|
return (_b = (_a = this.options.current).onContentError) == null ? void 0 : _b.call(_a, ...args);
|
|
409
|
+
},
|
|
410
|
+
onDrop: (...args) => {
|
|
411
|
+
var _a, _b;
|
|
412
|
+
return (_b = (_a = this.options.current).onDrop) == null ? void 0 : _b.call(_a, ...args);
|
|
413
|
+
},
|
|
414
|
+
onPaste: (...args) => {
|
|
415
|
+
var _a, _b;
|
|
416
|
+
return (_b = (_a = this.options.current).onPaste) == null ? void 0 : _b.call(_a, ...args);
|
|
404
417
|
}
|
|
405
418
|
};
|
|
406
419
|
const editor = new import_core.Editor(optionsToApply);
|
|
@@ -437,7 +450,10 @@ var EditorInstanceManager = class {
|
|
|
437
450
|
this.isComponentMounted = true;
|
|
438
451
|
clearTimeout(this.scheduledDestructionTimeout);
|
|
439
452
|
if (this.editor && !this.editor.isDestroyed && deps.length === 0) {
|
|
440
|
-
this.editor.setOptions(
|
|
453
|
+
this.editor.setOptions({
|
|
454
|
+
...this.options.current,
|
|
455
|
+
editable: this.editor.isEditable
|
|
456
|
+
});
|
|
441
457
|
} else {
|
|
442
458
|
this.refreshEditorInstance(deps);
|
|
443
459
|
}
|
|
@@ -488,24 +504,24 @@ var EditorInstanceManager = class {
|
|
|
488
504
|
this.setEditor(null);
|
|
489
505
|
}
|
|
490
506
|
}
|
|
491
|
-
},
|
|
507
|
+
}, 1);
|
|
492
508
|
}
|
|
493
509
|
};
|
|
494
510
|
function useEditor(options = {}, deps = []) {
|
|
495
|
-
const mostRecentOptions = (0,
|
|
511
|
+
const mostRecentOptions = (0, import_react4.useRef)(options);
|
|
496
512
|
mostRecentOptions.current = options;
|
|
497
|
-
const [instanceManager] = (0,
|
|
513
|
+
const [instanceManager] = (0, import_react4.useState)(() => new EditorInstanceManager(mostRecentOptions));
|
|
498
514
|
const editor = (0, import_shim2.useSyncExternalStore)(
|
|
499
515
|
instanceManager.subscribe,
|
|
500
516
|
instanceManager.getEditor,
|
|
501
517
|
instanceManager.getServerSnapshot
|
|
502
518
|
);
|
|
503
|
-
(0,
|
|
504
|
-
(0,
|
|
519
|
+
(0, import_react4.useDebugValue)(editor);
|
|
520
|
+
(0, import_react4.useEffect)(instanceManager.onRender(deps));
|
|
505
521
|
useEditorState({
|
|
506
522
|
editor,
|
|
507
523
|
selector: ({ transactionNumber }) => {
|
|
508
|
-
if (options.shouldRerenderOnTransaction === false) {
|
|
524
|
+
if (options.shouldRerenderOnTransaction === false || options.shouldRerenderOnTransaction === void 0) {
|
|
509
525
|
return null;
|
|
510
526
|
}
|
|
511
527
|
if (options.immediatelyRender && transactionNumber === 0) {
|
|
@@ -518,134 +534,162 @@ function useEditor(options = {}, deps = []) {
|
|
|
518
534
|
}
|
|
519
535
|
|
|
520
536
|
// src/Context.tsx
|
|
521
|
-
var EditorContext = (0,
|
|
537
|
+
var EditorContext = (0, import_react5.createContext)({
|
|
522
538
|
editor: null
|
|
523
539
|
});
|
|
524
540
|
var EditorConsumer = EditorContext.Consumer;
|
|
525
|
-
var useCurrentEditor = () => (0,
|
|
541
|
+
var useCurrentEditor = () => (0, import_react5.useContext)(EditorContext);
|
|
526
542
|
function EditorProvider({
|
|
527
543
|
children,
|
|
528
544
|
slotAfter,
|
|
529
545
|
slotBefore,
|
|
546
|
+
editorContainerProps = {},
|
|
530
547
|
...editorOptions
|
|
531
548
|
}) {
|
|
532
549
|
const editor = useEditor(editorOptions);
|
|
550
|
+
const contextValue = (0, import_react5.useMemo)(() => ({ editor }), [editor]);
|
|
533
551
|
if (!editor) {
|
|
534
552
|
return null;
|
|
535
553
|
}
|
|
536
|
-
return /* @__PURE__ */
|
|
554
|
+
return /* @__PURE__ */ import_react5.default.createElement(EditorContext.Provider, { value: contextValue }, slotBefore, /* @__PURE__ */ import_react5.default.createElement(EditorConsumer, null, ({ editor: currentEditor }) => /* @__PURE__ */ import_react5.default.createElement(EditorContent, { editor: currentEditor, ...editorContainerProps })), children, slotAfter);
|
|
537
555
|
}
|
|
538
556
|
|
|
539
557
|
// src/BubbleMenu.tsx
|
|
540
|
-
var BubbleMenu = (
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
} = props;
|
|
557
|
-
const menuEditor = editor || currentEditor;
|
|
558
|
-
if (!menuEditor) {
|
|
559
|
-
console.warn("BubbleMenu component is not rendered inside of an editor component or does not have editor prop.");
|
|
560
|
-
return;
|
|
558
|
+
var BubbleMenu = import_react6.default.forwardRef(
|
|
559
|
+
({
|
|
560
|
+
pluginKey = "bubbleMenu",
|
|
561
|
+
editor,
|
|
562
|
+
updateDelay,
|
|
563
|
+
resizeDelay,
|
|
564
|
+
shouldShow = null,
|
|
565
|
+
options,
|
|
566
|
+
children,
|
|
567
|
+
...restProps
|
|
568
|
+
}, ref) => {
|
|
569
|
+
const menuEl = (0, import_react6.useRef)(document.createElement("div"));
|
|
570
|
+
if (typeof ref === "function") {
|
|
571
|
+
ref(menuEl.current);
|
|
572
|
+
} else if (ref) {
|
|
573
|
+
ref.current = menuEl.current;
|
|
561
574
|
}
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
575
|
+
const { editor: currentEditor } = useCurrentEditor();
|
|
576
|
+
(0, import_react6.useEffect)(() => {
|
|
577
|
+
const bubbleMenuElement = menuEl.current;
|
|
578
|
+
bubbleMenuElement.style.visibility = "hidden";
|
|
579
|
+
bubbleMenuElement.style.position = "absolute";
|
|
580
|
+
if ((editor == null ? void 0 : editor.isDestroyed) || (currentEditor == null ? void 0 : currentEditor.isDestroyed)) {
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
const attachToEditor = editor || currentEditor;
|
|
584
|
+
if (!attachToEditor) {
|
|
585
|
+
console.warn(
|
|
586
|
+
"BubbleMenu component is not rendered inside of an editor component or does not have editor prop."
|
|
587
|
+
);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
const plugin = (0, import_extension_bubble_menu.BubbleMenuPlugin)({
|
|
591
|
+
updateDelay,
|
|
592
|
+
resizeDelay,
|
|
593
|
+
editor: attachToEditor,
|
|
594
|
+
element: bubbleMenuElement,
|
|
595
|
+
pluginKey,
|
|
596
|
+
shouldShow,
|
|
597
|
+
options
|
|
578
598
|
});
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
};
|
|
599
|
+
attachToEditor.registerPlugin(plugin);
|
|
600
|
+
return () => {
|
|
601
|
+
attachToEditor.unregisterPlugin(pluginKey);
|
|
602
|
+
window.requestAnimationFrame(() => {
|
|
603
|
+
if (bubbleMenuElement.parentNode) {
|
|
604
|
+
bubbleMenuElement.parentNode.removeChild(bubbleMenuElement);
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
};
|
|
608
|
+
}, [editor, currentEditor]);
|
|
609
|
+
return (0, import_react_dom2.createPortal)(
|
|
610
|
+
/* @__PURE__ */ import_react6.default.createElement(
|
|
611
|
+
"div",
|
|
612
|
+
{
|
|
613
|
+
...restProps
|
|
614
|
+
},
|
|
615
|
+
children
|
|
616
|
+
),
|
|
617
|
+
menuEl.current
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
);
|
|
587
621
|
|
|
588
622
|
// src/FloatingMenu.tsx
|
|
589
623
|
var import_extension_floating_menu = require("@tiptap/extension-floating-menu");
|
|
590
|
-
var
|
|
624
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
591
625
|
var import_react_dom3 = require("react-dom");
|
|
592
|
-
var FloatingMenu = (
|
|
593
|
-
|
|
626
|
+
var FloatingMenu = import_react7.default.forwardRef(({
|
|
627
|
+
pluginKey = "floatingMenu",
|
|
628
|
+
editor,
|
|
629
|
+
shouldShow = null,
|
|
630
|
+
options,
|
|
631
|
+
children,
|
|
632
|
+
...restProps
|
|
633
|
+
}, ref) => {
|
|
634
|
+
const menuEl = (0, import_react7.useRef)(document.createElement("div"));
|
|
635
|
+
if (typeof ref === "function") {
|
|
636
|
+
ref(menuEl.current);
|
|
637
|
+
} else if (ref) {
|
|
638
|
+
ref.current = menuEl.current;
|
|
639
|
+
}
|
|
594
640
|
const { editor: currentEditor } = useCurrentEditor();
|
|
595
|
-
(0,
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if ((
|
|
641
|
+
(0, import_react7.useEffect)(() => {
|
|
642
|
+
const floatingMenuElement = menuEl.current;
|
|
643
|
+
floatingMenuElement.style.visibility = "hidden";
|
|
644
|
+
floatingMenuElement.style.position = "absolute";
|
|
645
|
+
if ((editor == null ? void 0 : editor.isDestroyed) || (currentEditor == null ? void 0 : currentEditor.isDestroyed)) {
|
|
600
646
|
return;
|
|
601
647
|
}
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
} = props;
|
|
608
|
-
const menuEditor = editor || currentEditor;
|
|
609
|
-
if (!menuEditor) {
|
|
610
|
-
console.warn("FloatingMenu component is not rendered inside of an editor component or does not have editor prop.");
|
|
648
|
+
const attachToEditor = editor || currentEditor;
|
|
649
|
+
if (!attachToEditor) {
|
|
650
|
+
console.warn(
|
|
651
|
+
"FloatingMenu component is not rendered inside of an editor component or does not have editor prop."
|
|
652
|
+
);
|
|
611
653
|
return;
|
|
612
654
|
}
|
|
613
655
|
const plugin = (0, import_extension_floating_menu.FloatingMenuPlugin)({
|
|
656
|
+
editor: attachToEditor,
|
|
657
|
+
element: floatingMenuElement,
|
|
614
658
|
pluginKey,
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
options,
|
|
618
|
-
shouldShow
|
|
659
|
+
shouldShow,
|
|
660
|
+
options
|
|
619
661
|
});
|
|
620
|
-
|
|
662
|
+
attachToEditor.registerPlugin(plugin);
|
|
621
663
|
return () => {
|
|
622
|
-
|
|
664
|
+
attachToEditor.unregisterPlugin(pluginKey);
|
|
623
665
|
window.requestAnimationFrame(() => {
|
|
624
|
-
if (
|
|
625
|
-
|
|
666
|
+
if (floatingMenuElement.parentNode) {
|
|
667
|
+
floatingMenuElement.parentNode.removeChild(floatingMenuElement);
|
|
626
668
|
}
|
|
627
669
|
});
|
|
628
670
|
};
|
|
629
|
-
}, [
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
671
|
+
}, [editor, currentEditor]);
|
|
672
|
+
return (0, import_react_dom3.createPortal)(
|
|
673
|
+
/* @__PURE__ */ import_react7.default.createElement(
|
|
674
|
+
"div",
|
|
675
|
+
{
|
|
676
|
+
...restProps
|
|
677
|
+
},
|
|
678
|
+
children
|
|
679
|
+
),
|
|
635
680
|
menuEl.current
|
|
636
681
|
);
|
|
637
|
-
|
|
638
|
-
};
|
|
682
|
+
});
|
|
639
683
|
|
|
640
684
|
// src/NodeViewContent.tsx
|
|
641
|
-
var
|
|
685
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
642
686
|
|
|
643
687
|
// src/useReactNodeView.ts
|
|
644
|
-
var
|
|
645
|
-
var ReactNodeViewContext = (0,
|
|
688
|
+
var import_react8 = require("react");
|
|
689
|
+
var ReactNodeViewContext = (0, import_react8.createContext)({
|
|
646
690
|
onDragStart: void 0
|
|
647
691
|
});
|
|
648
|
-
var useReactNodeView = () => (0,
|
|
692
|
+
var useReactNodeView = () => (0, import_react8.useContext)(ReactNodeViewContext);
|
|
649
693
|
|
|
650
694
|
// src/NodeViewContent.tsx
|
|
651
695
|
var NodeViewContent = (props) => {
|
|
@@ -653,7 +697,7 @@ var NodeViewContent = (props) => {
|
|
|
653
697
|
const { nodeViewContentRef } = useReactNodeView();
|
|
654
698
|
return (
|
|
655
699
|
// @ts-ignore
|
|
656
|
-
/* @__PURE__ */
|
|
700
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
657
701
|
Tag,
|
|
658
702
|
{
|
|
659
703
|
...props,
|
|
@@ -669,13 +713,13 @@ var NodeViewContent = (props) => {
|
|
|
669
713
|
};
|
|
670
714
|
|
|
671
715
|
// src/NodeViewWrapper.tsx
|
|
672
|
-
var
|
|
673
|
-
var NodeViewWrapper =
|
|
716
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
717
|
+
var NodeViewWrapper = import_react10.default.forwardRef((props, ref) => {
|
|
674
718
|
const { onDragStart } = useReactNodeView();
|
|
675
719
|
const Tag = props.as || "div";
|
|
676
720
|
return (
|
|
677
721
|
// @ts-ignore
|
|
678
|
-
/* @__PURE__ */
|
|
722
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
679
723
|
Tag,
|
|
680
724
|
{
|
|
681
725
|
...props,
|
|
@@ -693,10 +737,10 @@ var NodeViewWrapper = import_react9.default.forwardRef((props, ref) => {
|
|
|
693
737
|
|
|
694
738
|
// src/ReactNodeViewRenderer.tsx
|
|
695
739
|
var import_core2 = require("@tiptap/core");
|
|
696
|
-
var
|
|
740
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
697
741
|
|
|
698
742
|
// src/ReactRenderer.tsx
|
|
699
|
-
var
|
|
743
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
700
744
|
var import_react_dom4 = require("react-dom");
|
|
701
745
|
function isClassComponent(Component) {
|
|
702
746
|
return !!(typeof Component === "function" && Component.prototype && Component.prototype.isReactComponent);
|
|
@@ -706,12 +750,14 @@ function isForwardRefComponent(Component) {
|
|
|
706
750
|
return !!(typeof Component === "object" && ((_a = Component.$$typeof) == null ? void 0 : _a.toString()) === "Symbol(react.forward_ref)");
|
|
707
751
|
}
|
|
708
752
|
var ReactRenderer = class {
|
|
753
|
+
/**
|
|
754
|
+
* Immediately creates element and renders the provided React component.
|
|
755
|
+
*/
|
|
709
756
|
constructor(component, {
|
|
710
757
|
editor,
|
|
711
758
|
props = {},
|
|
712
759
|
as = "div",
|
|
713
|
-
className = ""
|
|
714
|
-
attrs
|
|
760
|
+
className = ""
|
|
715
761
|
}) {
|
|
716
762
|
this.ref = null;
|
|
717
763
|
this.id = Math.floor(Math.random() * 4294967295).toString();
|
|
@@ -723,11 +769,6 @@ var ReactRenderer = class {
|
|
|
723
769
|
if (className) {
|
|
724
770
|
this.element.classList.add(...className.split(" "));
|
|
725
771
|
}
|
|
726
|
-
if (attrs) {
|
|
727
|
-
Object.keys(attrs).forEach((key) => {
|
|
728
|
-
this.element.setAttribute(key, attrs[key]);
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
772
|
if (this.editor.isInitialized) {
|
|
732
773
|
(0, import_react_dom4.flushSync)(() => {
|
|
733
774
|
this.render();
|
|
@@ -736,6 +777,9 @@ var ReactRenderer = class {
|
|
|
736
777
|
this.render();
|
|
737
778
|
}
|
|
738
779
|
}
|
|
780
|
+
/**
|
|
781
|
+
* Render the React component.
|
|
782
|
+
*/
|
|
739
783
|
render() {
|
|
740
784
|
var _a;
|
|
741
785
|
const Component = this.component;
|
|
@@ -746,9 +790,12 @@ var ReactRenderer = class {
|
|
|
746
790
|
this.ref = ref;
|
|
747
791
|
};
|
|
748
792
|
}
|
|
749
|
-
this.reactElement =
|
|
793
|
+
this.reactElement = /* @__PURE__ */ import_react11.default.createElement(Component, { ...props });
|
|
750
794
|
(_a = editor == null ? void 0 : editor.contentComponent) == null ? void 0 : _a.setRenderer(this.id, this);
|
|
751
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* Re-renders the React component with new props.
|
|
798
|
+
*/
|
|
752
799
|
updateProps(props = {}) {
|
|
753
800
|
this.props = {
|
|
754
801
|
...this.props,
|
|
@@ -756,22 +803,40 @@ var ReactRenderer = class {
|
|
|
756
803
|
};
|
|
757
804
|
this.render();
|
|
758
805
|
}
|
|
806
|
+
/**
|
|
807
|
+
* Destroy the React component.
|
|
808
|
+
*/
|
|
759
809
|
destroy() {
|
|
760
810
|
var _a;
|
|
761
811
|
const editor = this.editor;
|
|
762
812
|
(_a = editor == null ? void 0 : editor.contentComponent) == null ? void 0 : _a.removeRenderer(this.id);
|
|
763
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Update the attributes of the element that holds the React component.
|
|
816
|
+
*/
|
|
817
|
+
updateAttributes(attributes) {
|
|
818
|
+
Object.keys(attributes).forEach((key) => {
|
|
819
|
+
this.element.setAttribute(key, attributes[key]);
|
|
820
|
+
});
|
|
821
|
+
}
|
|
764
822
|
};
|
|
765
823
|
|
|
766
824
|
// src/ReactNodeViewRenderer.tsx
|
|
767
825
|
var ReactNodeView = class extends import_core2.NodeView {
|
|
826
|
+
/**
|
|
827
|
+
* Setup the React component.
|
|
828
|
+
* Called on initialization.
|
|
829
|
+
*/
|
|
768
830
|
mount() {
|
|
769
831
|
const props = {
|
|
770
832
|
editor: this.editor,
|
|
771
833
|
node: this.node,
|
|
772
834
|
decorations: this.decorations,
|
|
835
|
+
innerDecorations: this.innerDecorations,
|
|
836
|
+
view: this.view,
|
|
773
837
|
selected: false,
|
|
774
838
|
extension: this.extension,
|
|
839
|
+
HTMLAttributes: this.HTMLAttributes,
|
|
775
840
|
getPos: () => this.getPos(),
|
|
776
841
|
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
777
842
|
deleteNode: () => this.deleteNode()
|
|
@@ -790,9 +855,11 @@ var ReactNodeView = class extends import_core2.NodeView {
|
|
|
790
855
|
};
|
|
791
856
|
const context = { onDragStart, nodeViewContentRef };
|
|
792
857
|
const Component = this.component;
|
|
793
|
-
const ReactNodeViewProvider =
|
|
794
|
-
|
|
795
|
-
|
|
858
|
+
const ReactNodeViewProvider = import_react12.default.memo(
|
|
859
|
+
(componentProps) => {
|
|
860
|
+
return /* @__PURE__ */ import_react12.default.createElement(ReactNodeViewContext.Provider, { value: context }, import_react12.default.createElement(Component, componentProps));
|
|
861
|
+
}
|
|
862
|
+
);
|
|
796
863
|
ReactNodeViewProvider.displayName = "ReactNodeView";
|
|
797
864
|
if (this.node.isLeaf) {
|
|
798
865
|
this.contentDOMElement = null;
|
|
@@ -802,6 +869,7 @@ var ReactNodeView = class extends import_core2.NodeView {
|
|
|
802
869
|
this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
|
|
803
870
|
}
|
|
804
871
|
if (this.contentDOMElement) {
|
|
872
|
+
this.contentDOMElement.dataset.nodeViewContentReact = "";
|
|
805
873
|
this.contentDOMElement.style.whiteSpace = "inherit";
|
|
806
874
|
}
|
|
807
875
|
let as = this.node.isInline ? "span" : "div";
|
|
@@ -815,10 +883,14 @@ var ReactNodeView = class extends import_core2.NodeView {
|
|
|
815
883
|
editor: this.editor,
|
|
816
884
|
props,
|
|
817
885
|
as,
|
|
818
|
-
className: `node-${this.node.type.name} ${className}`.trim()
|
|
819
|
-
attrs: this.options.attrs
|
|
886
|
+
className: `node-${this.node.type.name} ${className}`.trim()
|
|
820
887
|
});
|
|
888
|
+
this.updateElementAttributes();
|
|
821
889
|
}
|
|
890
|
+
/**
|
|
891
|
+
* Return the DOM element.
|
|
892
|
+
* This is the element that will be used to display the node view.
|
|
893
|
+
*/
|
|
822
894
|
get dom() {
|
|
823
895
|
var _a;
|
|
824
896
|
if (this.renderer.element.firstElementChild && !((_a = this.renderer.element.firstElementChild) == null ? void 0 : _a.hasAttribute("data-node-view-wrapper"))) {
|
|
@@ -826,15 +898,27 @@ var ReactNodeView = class extends import_core2.NodeView {
|
|
|
826
898
|
}
|
|
827
899
|
return this.renderer.element;
|
|
828
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* Return the content DOM element.
|
|
903
|
+
* This is the element that will be used to display the rich-text content of the node.
|
|
904
|
+
*/
|
|
829
905
|
get contentDOM() {
|
|
830
906
|
if (this.node.isLeaf) {
|
|
831
907
|
return null;
|
|
832
908
|
}
|
|
833
909
|
return this.contentDOMElement;
|
|
834
910
|
}
|
|
911
|
+
/**
|
|
912
|
+
* On editor selection update, check if the node is selected.
|
|
913
|
+
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
914
|
+
*/
|
|
835
915
|
handleSelectionUpdate() {
|
|
836
916
|
const { from, to } = this.editor.state.selection;
|
|
837
|
-
|
|
917
|
+
const pos = this.getPos();
|
|
918
|
+
if (typeof pos !== "number") {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
838
922
|
if (this.renderer.props.selected) {
|
|
839
923
|
return;
|
|
840
924
|
}
|
|
@@ -846,9 +930,16 @@ var ReactNodeView = class extends import_core2.NodeView {
|
|
|
846
930
|
this.deselectNode();
|
|
847
931
|
}
|
|
848
932
|
}
|
|
849
|
-
|
|
850
|
-
|
|
933
|
+
/**
|
|
934
|
+
* On update, update the React component.
|
|
935
|
+
* To prevent unnecessary updates, the `update` option can be used.
|
|
936
|
+
*/
|
|
937
|
+
update(node, decorations, innerDecorations) {
|
|
938
|
+
const rerenderComponent = (props) => {
|
|
851
939
|
this.renderer.updateProps(props);
|
|
940
|
+
if (typeof this.options.attrs === "function") {
|
|
941
|
+
this.updateElementAttributes();
|
|
942
|
+
}
|
|
852
943
|
};
|
|
853
944
|
if (node.type !== this.node.type) {
|
|
854
945
|
return false;
|
|
@@ -856,41 +947,74 @@ var ReactNodeView = class extends import_core2.NodeView {
|
|
|
856
947
|
if (typeof this.options.update === "function") {
|
|
857
948
|
const oldNode = this.node;
|
|
858
949
|
const oldDecorations = this.decorations;
|
|
950
|
+
const oldInnerDecorations = this.innerDecorations;
|
|
859
951
|
this.node = node;
|
|
860
952
|
this.decorations = decorations;
|
|
953
|
+
this.innerDecorations = innerDecorations;
|
|
861
954
|
return this.options.update({
|
|
862
955
|
oldNode,
|
|
863
956
|
oldDecorations,
|
|
864
957
|
newNode: node,
|
|
865
958
|
newDecorations: decorations,
|
|
866
|
-
|
|
959
|
+
oldInnerDecorations,
|
|
960
|
+
innerDecorations,
|
|
961
|
+
updateProps: () => rerenderComponent({ node, decorations, innerDecorations })
|
|
867
962
|
});
|
|
868
963
|
}
|
|
869
|
-
if (node === this.node && this.decorations === decorations) {
|
|
964
|
+
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
870
965
|
return true;
|
|
871
966
|
}
|
|
872
967
|
this.node = node;
|
|
873
968
|
this.decorations = decorations;
|
|
874
|
-
|
|
969
|
+
this.innerDecorations = innerDecorations;
|
|
970
|
+
rerenderComponent({ node, decorations, innerDecorations });
|
|
875
971
|
return true;
|
|
876
972
|
}
|
|
973
|
+
/**
|
|
974
|
+
* Select the node.
|
|
975
|
+
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
976
|
+
*/
|
|
877
977
|
selectNode() {
|
|
878
978
|
this.renderer.updateProps({
|
|
879
979
|
selected: true
|
|
880
980
|
});
|
|
881
981
|
this.renderer.element.classList.add("ProseMirror-selectednode");
|
|
882
982
|
}
|
|
983
|
+
/**
|
|
984
|
+
* Deselect the node.
|
|
985
|
+
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
986
|
+
*/
|
|
883
987
|
deselectNode() {
|
|
884
988
|
this.renderer.updateProps({
|
|
885
989
|
selected: false
|
|
886
990
|
});
|
|
887
991
|
this.renderer.element.classList.remove("ProseMirror-selectednode");
|
|
888
992
|
}
|
|
993
|
+
/**
|
|
994
|
+
* Destroy the React component instance.
|
|
995
|
+
*/
|
|
889
996
|
destroy() {
|
|
890
997
|
this.renderer.destroy();
|
|
891
998
|
this.editor.off("selectionUpdate", this.handleSelectionUpdate);
|
|
892
999
|
this.contentDOMElement = null;
|
|
893
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Update the attributes of the top-level element that holds the React component.
|
|
1003
|
+
* Applying the attributes defined in the `attrs` option.
|
|
1004
|
+
*/
|
|
1005
|
+
updateElementAttributes() {
|
|
1006
|
+
if (this.options.attrs) {
|
|
1007
|
+
let attrsObj = {};
|
|
1008
|
+
if (typeof this.options.attrs === "function") {
|
|
1009
|
+
const extensionAttributes = this.editor.extensionManager.attributes;
|
|
1010
|
+
const HTMLAttributes2 = (0, import_core2.getRenderedAttributes)(this.node, extensionAttributes);
|
|
1011
|
+
attrsObj = this.options.attrs({ node: this.node, HTMLAttributes: HTMLAttributes2 });
|
|
1012
|
+
} else {
|
|
1013
|
+
attrsObj = this.options.attrs;
|
|
1014
|
+
}
|
|
1015
|
+
this.renderer.updateAttributes(attrsObj);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
894
1018
|
};
|
|
895
1019
|
function ReactNodeViewRenderer(component, options) {
|
|
896
1020
|
return (props) => {
|
|
@@ -914,6 +1038,7 @@ __reExport(src_exports, require("@tiptap/core"), module.exports);
|
|
|
914
1038
|
NodeViewContent,
|
|
915
1039
|
NodeViewWrapper,
|
|
916
1040
|
PureEditorContent,
|
|
1041
|
+
ReactNodeView,
|
|
917
1042
|
ReactNodeViewContext,
|
|
918
1043
|
ReactNodeViewRenderer,
|
|
919
1044
|
ReactRenderer,
|