@handlewithcare/react-prosemirror 2.5.2 → 2.5.4

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.
@@ -6,6 +6,7 @@ import { EMPTY_STATE } from "../constants.js";
6
6
  import { beforeInputPlugin } from "../plugins/beforeInputPlugin.js";
7
7
  import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
8
8
  import { useComponentEventListeners } from "./useComponentEventListeners.js";
9
+ import { useEffectEvent } from "./useEffectEvent.js";
9
10
  import { useForceUpdate } from "./useForceUpdate.js";
10
11
  let didWarnValueDefaultValue = false;
11
12
  /**
@@ -75,30 +76,31 @@ let didWarnValueDefaultValue = false;
75
76
  const [view, setView] = useState(()=>{
76
77
  return new StaticEditorView(directEditorProps);
77
78
  });
79
+ const createEditorView = useEffectEvent((mount)=>{
80
+ if (mount) {
81
+ const view = new ReactEditorView({
82
+ mount
83
+ }, directEditorProps);
84
+ view.dom.addEventListener("compositionend", forceUpdate);
85
+ return view;
86
+ }
87
+ return new StaticEditorView(directEditorProps);
88
+ });
78
89
  useClientLayoutEffect(()=>{
90
+ const view = createEditorView(mount);
91
+ setView(view);
79
92
  return ()=>{
80
93
  view.destroy();
81
94
  };
82
95
  }, [
83
- view
96
+ createEditorView,
97
+ mount
84
98
  ]);
85
- // This rule is concerned about infinite updates due to the
86
- // call to setView. These calls are deliberately conditional,
87
- // so this is not a concern.
88
- // eslint-disable-next-line react-hooks/exhaustive-deps
89
99
  useClientLayoutEffect(()=>{
90
- if (mount !== view.dom) {
91
- if (mount) {
92
- const view = new ReactEditorView({
93
- mount
94
- }, directEditorProps);
95
- view.dom.addEventListener("compositionend", forceUpdate);
96
- setView(view);
97
- } else {
98
- const view = new StaticEditorView(directEditorProps);
99
- setView(view);
100
- }
101
- } else if (view instanceof ReactEditorView) {
100
+ // Ensure that the EditorView hasn't been destroyed before
101
+ // running effects. Running effects will reattach selection
102
+ // change listeners if the EditorView has been destroyed.
103
+ if (view instanceof ReactEditorView && !view.isDestroyed) {
102
104
  view.commitPendingEffects();
103
105
  }
104
106
  });
@@ -0,0 +1,24 @@
1
+ import { useCallback, useLayoutEffect, useRef } from "react";
2
+ export function useEffectEvent(fn) {
3
+ const ref = useRef(fn);
4
+ // Ideally this would be a useInsertionEffect, but
5
+ // that was introduced in React 18 and we still
6
+ // support React 17. useLayoutEffect is safe
7
+ // here as long as the function returned by
8
+ // useEffectEvent isn't called in a layout effect
9
+ // that's defined _before_ the useEffectEvent
10
+ // call, and effect events are never passed
11
+ // to child components.
12
+ useLayoutEffect(()=>{
13
+ ref.current = fn;
14
+ }, [
15
+ fn
16
+ ]);
17
+ return useCallback(function() {
18
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
19
+ args[_key] = arguments[_key];
20
+ }
21
+ const f = ref.current;
22
+ return f(...args);
23
+ }, []);
24
+ }
@@ -1,9 +1,10 @@
1
- import { useCallback, useContext, useMemo, useRef, useState } from "react";
1
+ import { useContext, useMemo, useRef, useState } from "react";
2
2
  import { ReactEditorView } from "../ReactEditorView.js";
3
3
  import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
4
4
  import { EditorContext } from "../contexts/EditorContext.js";
5
5
  import { CompositionViewDesc, ReactNodeViewDesc, sortViewDescs } from "../viewdesc.js";
6
6
  import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
7
+ import { useEffectEvent } from "./useEffectEvent.js";
7
8
  function findContentDOM(source, children) {
8
9
  return source?.contentDOM ?? children[0]?.dom?.parentElement ?? null;
9
10
  }
@@ -15,7 +16,7 @@ export function useNodeViewDescriptor(ref, constructor, props) {
15
16
  const [contentDOM, setContentDOM] = useState(null);
16
17
  const viewDescRef = useRef();
17
18
  const childrenRef = useRef([]);
18
- const create = useCallback((props)=>{
19
+ const create = useEffectEvent(()=>{
19
20
  if (!(view instanceof ReactEditorView)) {
20
21
  return;
21
22
  }
@@ -37,13 +38,8 @@ export function useNodeViewDescriptor(ref, constructor, props) {
37
38
  setContentDOM(contentDOM);
38
39
  setNodeDOM(nodeDOM);
39
40
  return viewDesc;
40
- }, [
41
- ref,
42
- parentRef,
43
- constructor,
44
- view
45
- ]);
46
- const update = useCallback((props)=>{
41
+ });
42
+ const update = useEffectEvent(()=>{
47
43
  if (!(view instanceof ReactEditorView)) {
48
44
  return false;
49
45
  }
@@ -64,11 +60,8 @@ export function useNodeViewDescriptor(ref, constructor, props) {
64
60
  }
65
61
  const { node, decorations, innerDecorations } = props;
66
62
  return viewDesc.matchesNode(node, decorations, innerDecorations) || viewDesc.update(node, decorations, innerDecorations, view);
67
- }, [
68
- ref,
69
- view
70
- ]);
71
- const destroy = useCallback(()=>{
63
+ });
64
+ const destroy = useEffectEvent(()=>{
72
65
  const viewDesc = viewDescRef.current;
73
66
  if (!viewDesc) {
74
67
  return;
@@ -82,13 +75,20 @@ export function useNodeViewDescriptor(ref, constructor, props) {
82
75
  setDOM(null);
83
76
  setContentDOM(null);
84
77
  setNodeDOM(null);
78
+ });
79
+ useClientLayoutEffect(()=>{
80
+ viewDescRef.current = create();
81
+ return ()=>{
82
+ destroy();
83
+ };
85
84
  }, [
86
- siblingsRef
85
+ create,
86
+ destroy
87
87
  ]);
88
88
  useClientLayoutEffect(()=>{
89
- if (!update(props)) {
89
+ if (!update()) {
90
90
  destroy();
91
- viewDescRef.current = create(props);
91
+ viewDescRef.current = create();
92
92
  }
93
93
  const viewDesc = viewDescRef.current;
94
94
  if (!viewDesc) {
@@ -127,14 +127,6 @@ export function useNodeViewDescriptor(ref, constructor, props) {
127
127
  }
128
128
  }
129
129
  });
130
- useClientLayoutEffect(()=>{
131
- return ()=>{
132
- destroy();
133
- viewDescRef.current = undefined;
134
- };
135
- }, [
136
- destroy
137
- ]);
138
130
  const childContextValue = useMemo(()=>({
139
131
  parentRef: viewDescRef,
140
132
  siblingsRef: childrenRef