@handlewithcare/react-prosemirror 3.2.3 → 3.2.5

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.
@@ -187,29 +187,7 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
187
187
  // this ensures that the base class validates the DOM selection and invokes
188
188
  // node view selection callbacks.
189
189
  this.docView.markDirty(-1, -1);
190
- const nextSelection = this.nextProps.state.selection;
191
- const prevSelection = this.prevState.selection;
192
- const selectionChanged = !nextSelection.eq(prevSelection);
193
- const needsSelectionUpdate = selectionChanged || // If the doc within the selection has changed, then the DOM has likely changed.
194
- // In this case, we need to force a re-sync of the selection, because the browser
195
- // will have probably collapsed the selection to work around the new DOM, which
196
- // no longer matches the previous selection.
197
- !this.prevState.doc.slice(prevSelection.from, prevSelection.to).eq(this.nextProps.state.doc.slice(prevSelection.from, prevSelection.to));
198
- if (!needsSelectionUpdate) {
199
- // If the selection hasn't changed between renders, force
200
- // prosemirror-view to skip the selectionToDOM call. If a render happens after a DOM
201
- // selection change but before the "selectionchange" event fired, calling
202
- // selectionToDOM will cause the selection to be reset to its previous position.
203
- this.domObserver.setCurSelection();
204
- this.input.mouseDown = {
205
- allowDefault: false,
206
- delayedSelectionSync: false
207
- };
208
- }
209
190
  super.update(this.nextProps);
210
- if (!needsSelectionUpdate) {
211
- this.input.mouseDown = null;
212
- }
213
191
  // Store the new previous state.
214
192
  this.prevState = this.state;
215
193
  }
@@ -11,12 +11,26 @@ Object.defineProperty(exports, "useEditor", {
11
11
  }
12
12
  });
13
13
  const _core = require("@tiptap/core");
14
- const _react = require("@tiptap/react");
15
- const _react1 = require("react");
14
+ const _react = require("react");
16
15
  const _index = require("use-sync-external-store/shim/index.js");
17
- const isDev = process.env.NODE_ENV !== "production";
18
- const isSSR = typeof window === "undefined";
19
- const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
16
+ const _StaticEditorView = require("../../StaticEditorView.js");
17
+ let ReactEditor = class ReactEditor extends _core.Editor {
18
+ constructor(options){
19
+ super(options);
20
+ // @ts-expect-error Internal property
21
+ this.editorView = new _StaticEditorView.StaticEditorView({
22
+ // @ts-expect-error Internal property
23
+ state: this.editorState.reconfigure({
24
+ plugins: this.extensionManager.plugins
25
+ }),
26
+ ...this.options.editorProps,
27
+ attributes: {
28
+ role: "textbox",
29
+ ...this.options.editorProps.attributes
30
+ }
31
+ });
32
+ }
33
+ };
20
34
  /**
21
35
  * This class handles the creation, destruction, and re-creation of the editor instance.
22
36
  */ let EditorInstanceManager = class EditorInstanceManager {
@@ -45,7 +59,7 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
45
59
  constructor(options){
46
60
  this.options = options;
47
61
  this.subscriptions = new Set();
48
- this.setEditor(this.getInitialEditor());
62
+ this.setEditor(this.createEditor());
49
63
  this.scheduleDestroy();
50
64
  this.getEditor = this.getEditor.bind(this);
51
65
  this.getServerSnapshot = this.getServerSnapshot.bind(this);
@@ -61,34 +75,6 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
61
75
  // Notify all subscribers that the editor instance has been created
62
76
  this.subscriptions.forEach((cb)=>cb());
63
77
  }
64
- getInitialEditor() {
65
- if (this.options.current.immediatelyRender === undefined) {
66
- if (isSSR || isNext) {
67
- if (isDev) {
68
- /**
69
- * Throw an error in development, to make sure the developer is aware that tiptap cannot be SSR'd
70
- * and that they need to set `immediatelyRender` to `false` to avoid hydration mismatches.
71
- */ throw new Error("Tiptap Error: SSR has been detected, please set `immediatelyRender` explicitly to `false` to avoid hydration mismatches.");
72
- }
73
- // Best faith effort in production, run the code in the legacy mode to avoid hydration mismatches and errors in production
74
- return null;
75
- }
76
- // Default to immediately rendering when client-side rendering
77
- return this.createEditor();
78
- }
79
- // ----- FORKED CHANGES -----
80
- // if (this.options.current.immediatelyRender && isSSR && isDev) {
81
- // // Warn in development, to make sure the developer is aware that tiptap cannot be SSR'd, set `immediatelyRender` to `false` to avoid hydration mismatches.
82
- // throw new Error(
83
- // "Tiptap Error: SSR has been detected, and `immediatelyRender` has been set to `true` this is an unsupported configuration that may result in errors, explicitly set `immediatelyRender` to `false` to avoid hydration mismatches."
84
- // );
85
- // }
86
- // ----- END FORKED CHANGES -----
87
- if (this.options.current.immediatelyRender) {
88
- return this.createEditor();
89
- }
90
- return null;
91
- }
92
78
  /**
93
79
  * Create a new editor instance. And attach event listeners.
94
80
  */ createEditor() {
@@ -169,7 +155,7 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
169
155
  return _this.options.current.onDelete?.(...args);
170
156
  }
171
157
  };
172
- const editor = new _core.Editor(optionsToApply);
158
+ const editor = new ReactEditor(optionsToApply);
173
159
  // no need to keep track of the event listeners, they will be removed when the editor is destroyed
174
160
  return editor;
175
161
  }
@@ -320,30 +306,13 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
320
306
  };
321
307
  function useEditor() {
322
308
  let options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}, deps = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : [];
323
- const mostRecentOptions = (0, _react1.useRef)(options);
309
+ const mostRecentOptions = (0, _react.useRef)(options);
324
310
  mostRecentOptions.current = options;
325
- const [instanceManager] = (0, _react1.useState)(()=>new EditorInstanceManager(mostRecentOptions));
311
+ const [instanceManager] = (0, _react.useState)(()=>new EditorInstanceManager(mostRecentOptions));
326
312
  const editor = (0, _index.useSyncExternalStore)(instanceManager.subscribe, instanceManager.getEditor, instanceManager.getServerSnapshot);
327
- (0, _react1.useDebugValue)(editor);
313
+ (0, _react.useDebugValue)(editor);
328
314
  // This effect will handle creating/updating the editor instance
329
315
  // eslint-disable-next-line react-hooks/exhaustive-deps
330
- (0, _react1.useEffect)(instanceManager.onRender(deps));
331
- // The default behavior is to re-render on each transaction
332
- // This is legacy behavior that will be removed in future versions
333
- (0, _react.useEditorState)({
334
- editor,
335
- selector: (param)=>{
336
- let { transactionNumber } = param;
337
- if (options.shouldRerenderOnTransaction === false || options.shouldRerenderOnTransaction === undefined) {
338
- // This will prevent the editor from re-rendering on each transaction
339
- return null;
340
- }
341
- // This will avoid re-rendering on the first transaction when `immediatelyRender` is set to `true`
342
- if (options.immediatelyRender && transactionNumber === 0) {
343
- return 0;
344
- }
345
- return transactionNumber + 1;
346
- }
347
- });
316
+ (0, _react.useEffect)(instanceManager.onRender(deps));
348
317
  return editor;
349
318
  }
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "useTiptapEditor", {
8
8
  return useTiptapEditor;
9
9
  }
10
10
  });
11
- const _StaticEditorView = require("../../StaticEditorView.js");
12
11
  const _ReactProseMirror = require("../extensions/ReactProseMirror.js");
13
12
  const _ReactProseMirrorCommands = require("../extensions/ReactProseMirrorCommands.js");
14
13
  const _useEditor = require("./useEditor.js");
@@ -28,34 +27,9 @@ function useTiptapEditor(options, deps) {
28
27
  };
29
28
  extensions.push(_ReactProseMirrorCommands.ReactProseMirrorCommands);
30
29
  }
31
- const editor = (0, _useEditor.useEditor)({
30
+ return (0, _useEditor.useEditor)({
32
31
  ...options,
33
32
  extensions,
34
33
  element: null
35
34
  }, deps);
36
- // @ts-expect-error private property
37
- editor.editorView ??= new _StaticEditorView.StaticEditorView({
38
- // @ts-expect-error private property
39
- state: editor.editorState,
40
- ...editor.options.editorProps,
41
- attributes: {
42
- role: "textbox",
43
- ...editor.options.editorProps.attributes
44
- }
45
- });
46
- // @ts-expect-error private property
47
- const stateHasPlugins = !!editor.editorState.plugins.length;
48
- const stateNeedsReconfigure = !stateHasPlugins && !editor.isDestroyed;
49
- if (stateNeedsReconfigure) {
50
- const managerPlugins = editor.extensionManager.plugins;
51
- if (managerPlugins.length) {
52
- // @ts-expect-error private property
53
- editor.editorState = editor.editorState.reconfigure({
54
- plugins: editor.extensionManager.plugins
55
- });
56
- // @ts-expect-error private property
57
- editor.editorView.updateState(editor.editorState);
58
- }
59
- }
60
- return editor;
61
35
  }
@@ -187,29 +187,7 @@ function changedNodeViews(a, b) {
187
187
  // this ensures that the base class validates the DOM selection and invokes
188
188
  // node view selection callbacks.
189
189
  this.docView.markDirty(-1, -1);
190
- const nextSelection = this.nextProps.state.selection;
191
- const prevSelection = this.prevState.selection;
192
- const selectionChanged = !nextSelection.eq(prevSelection);
193
- const needsSelectionUpdate = selectionChanged || // If the doc within the selection has changed, then the DOM has likely changed.
194
- // In this case, we need to force a re-sync of the selection, because the browser
195
- // will have probably collapsed the selection to work around the new DOM, which
196
- // no longer matches the previous selection.
197
- !this.prevState.doc.slice(prevSelection.from, prevSelection.to).eq(this.nextProps.state.doc.slice(prevSelection.from, prevSelection.to));
198
- if (!needsSelectionUpdate) {
199
- // If the selection hasn't changed between renders, force
200
- // prosemirror-view to skip the selectionToDOM call. If a render happens after a DOM
201
- // selection change but before the "selectionchange" event fired, calling
202
- // selectionToDOM will cause the selection to be reset to its previous position.
203
- this.domObserver.setCurSelection();
204
- this.input.mouseDown = {
205
- allowDefault: false,
206
- delayedSelectionSync: false
207
- };
208
- }
209
190
  super.update(this.nextProps);
210
- if (!needsSelectionUpdate) {
211
- this.input.mouseDown = null;
212
- }
213
191
  // Store the new previous state.
214
192
  this.prevState = this.state;
215
193
  }
@@ -1,12 +1,26 @@
1
1
  // Forked from Tiptap's useEditor hook, with modifications to support
2
2
  // server-side rendering
3
3
  import { Editor } from "@tiptap/core";
4
- import { useEditorState } from "@tiptap/react";
5
4
  import { useDebugValue, useEffect, useRef, useState } from "react";
6
5
  import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
7
- const isDev = process.env.NODE_ENV !== "production";
8
- const isSSR = typeof window === "undefined";
9
- const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
6
+ import { StaticEditorView } from "../../StaticEditorView.js";
7
+ let ReactEditor = class ReactEditor extends Editor {
8
+ constructor(options){
9
+ super(options);
10
+ // @ts-expect-error Internal property
11
+ this.editorView = new StaticEditorView({
12
+ // @ts-expect-error Internal property
13
+ state: this.editorState.reconfigure({
14
+ plugins: this.extensionManager.plugins
15
+ }),
16
+ ...this.options.editorProps,
17
+ attributes: {
18
+ role: "textbox",
19
+ ...this.options.editorProps.attributes
20
+ }
21
+ });
22
+ }
23
+ };
10
24
  /**
11
25
  * This class handles the creation, destruction, and re-creation of the editor instance.
12
26
  */ let EditorInstanceManager = class EditorInstanceManager {
@@ -35,7 +49,7 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
35
49
  constructor(options){
36
50
  this.options = options;
37
51
  this.subscriptions = new Set();
38
- this.setEditor(this.getInitialEditor());
52
+ this.setEditor(this.createEditor());
39
53
  this.scheduleDestroy();
40
54
  this.getEditor = this.getEditor.bind(this);
41
55
  this.getServerSnapshot = this.getServerSnapshot.bind(this);
@@ -51,34 +65,6 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
51
65
  // Notify all subscribers that the editor instance has been created
52
66
  this.subscriptions.forEach((cb)=>cb());
53
67
  }
54
- getInitialEditor() {
55
- if (this.options.current.immediatelyRender === undefined) {
56
- if (isSSR || isNext) {
57
- if (isDev) {
58
- /**
59
- * Throw an error in development, to make sure the developer is aware that tiptap cannot be SSR'd
60
- * and that they need to set `immediatelyRender` to `false` to avoid hydration mismatches.
61
- */ throw new Error("Tiptap Error: SSR has been detected, please set `immediatelyRender` explicitly to `false` to avoid hydration mismatches.");
62
- }
63
- // Best faith effort in production, run the code in the legacy mode to avoid hydration mismatches and errors in production
64
- return null;
65
- }
66
- // Default to immediately rendering when client-side rendering
67
- return this.createEditor();
68
- }
69
- // ----- FORKED CHANGES -----
70
- // if (this.options.current.immediatelyRender && isSSR && isDev) {
71
- // // Warn in development, to make sure the developer is aware that tiptap cannot be SSR'd, set `immediatelyRender` to `false` to avoid hydration mismatches.
72
- // throw new Error(
73
- // "Tiptap Error: SSR has been detected, and `immediatelyRender` has been set to `true` this is an unsupported configuration that may result in errors, explicitly set `immediatelyRender` to `false` to avoid hydration mismatches."
74
- // );
75
- // }
76
- // ----- END FORKED CHANGES -----
77
- if (this.options.current.immediatelyRender) {
78
- return this.createEditor();
79
- }
80
- return null;
81
- }
82
68
  /**
83
69
  * Create a new editor instance. And attach event listeners.
84
70
  */ createEditor() {
@@ -159,7 +145,7 @@ const isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
159
145
  return _this.options.current.onDelete?.(...args);
160
146
  }
161
147
  };
162
- const editor = new Editor(optionsToApply);
148
+ const editor = new ReactEditor(optionsToApply);
163
149
  // no need to keep track of the event listeners, they will be removed when the editor is destroyed
164
150
  return editor;
165
151
  }
@@ -318,22 +304,5 @@ export function useEditor() {
318
304
  // This effect will handle creating/updating the editor instance
319
305
  // eslint-disable-next-line react-hooks/exhaustive-deps
320
306
  useEffect(instanceManager.onRender(deps));
321
- // The default behavior is to re-render on each transaction
322
- // This is legacy behavior that will be removed in future versions
323
- useEditorState({
324
- editor,
325
- selector: (param)=>{
326
- let { transactionNumber } = param;
327
- if (options.shouldRerenderOnTransaction === false || options.shouldRerenderOnTransaction === undefined) {
328
- // This will prevent the editor from re-rendering on each transaction
329
- return null;
330
- }
331
- // This will avoid re-rendering on the first transaction when `immediatelyRender` is set to `true`
332
- if (options.immediatelyRender && transactionNumber === 0) {
333
- return 0;
334
- }
335
- return transactionNumber + 1;
336
- }
337
- });
338
307
  return editor;
339
308
  }
@@ -1,4 +1,3 @@
1
- import { StaticEditorView } from "../../StaticEditorView.js";
2
1
  import { ReactProseMirror } from "../extensions/ReactProseMirror.js";
3
2
  import { ReactProseMirrorCommands } from "../extensions/ReactProseMirrorCommands.js";
4
3
  import { useEditor } from "./useEditor.js";
@@ -24,34 +23,9 @@ import { useEditor } from "./useEditor.js";
24
23
  };
25
24
  extensions.push(ReactProseMirrorCommands);
26
25
  }
27
- const editor = useEditor({
26
+ return useEditor({
28
27
  ...options,
29
28
  extensions,
30
29
  element: null
31
30
  }, deps);
32
- // @ts-expect-error private property
33
- editor.editorView ??= new StaticEditorView({
34
- // @ts-expect-error private property
35
- state: editor.editorState,
36
- ...editor.options.editorProps,
37
- attributes: {
38
- role: "textbox",
39
- ...editor.options.editorProps.attributes
40
- }
41
- });
42
- // @ts-expect-error private property
43
- const stateHasPlugins = !!editor.editorState.plugins.length;
44
- const stateNeedsReconfigure = !stateHasPlugins && !editor.isDestroyed;
45
- if (stateNeedsReconfigure) {
46
- const managerPlugins = editor.extensionManager.plugins;
47
- if (managerPlugins.length) {
48
- // @ts-expect-error private property
49
- editor.editorState = editor.editorState.reconfigure({
50
- plugins: editor.extensionManager.plugins
51
- });
52
- // @ts-expect-error private property
53
- editor.editorView.updateState(editor.editorState);
54
- }
55
- }
56
- return editor;
57
31
  }