@handlewithcare/react-prosemirror 2.5.3 → 2.5.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.
- package/README.md +2 -3
- package/dist/cjs/ReactEditorView.js +24 -0
- package/dist/cjs/hooks/useEditor.js +19 -17
- package/dist/cjs/hooks/useEffectEvent.js +34 -0
- package/dist/cjs/hooks/useNodeViewDescriptor.js +16 -24
- package/dist/esm/ReactEditorView.js +24 -0
- package/dist/esm/hooks/useEditor.js +19 -17
- package/dist/esm/hooks/useEffectEvent.js +24 -0
- package/dist/esm/hooks/useNodeViewDescriptor.js +17 -25
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ReactEditorView.d.ts +12 -0
- package/dist/types/hooks/useEffectEvent.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -693,15 +693,14 @@ export function SelectionWidget() {
|
|
|
693
693
|
### `NodeViewComponentProps`
|
|
694
694
|
|
|
695
695
|
```tsx
|
|
696
|
-
|
|
696
|
+
interface NodeViewComponentProps extends AllHTMLAttributes<HTMLElement> = {
|
|
697
697
|
nodeProps: {
|
|
698
698
|
decorations: readonly Decoration[];
|
|
699
699
|
innerDecorations: DecorationSource;
|
|
700
700
|
node: Node;
|
|
701
|
-
children?: ReactNode | ReactNode[];
|
|
702
701
|
getPos: () => number;
|
|
703
702
|
};
|
|
704
|
-
}
|
|
703
|
+
};
|
|
705
704
|
```
|
|
706
705
|
|
|
707
706
|
The props that will be passed to all node view components. These props map
|
|
@@ -32,6 +32,7 @@ function changedNodeViews(a, b) {
|
|
|
32
32
|
let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView {
|
|
33
33
|
nextProps;
|
|
34
34
|
prevState;
|
|
35
|
+
_destroyed;
|
|
35
36
|
constructor(place, props){
|
|
36
37
|
// Prevent the base class from destroying the React-managed nodes.
|
|
37
38
|
// Restore them below after invoking the base class constructor.
|
|
@@ -55,6 +56,16 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
|
|
|
55
56
|
this.domObserver.stop();
|
|
56
57
|
this.domObserver.observer = null;
|
|
57
58
|
this.domObserver.queue = [];
|
|
59
|
+
const originalOnSelectionChange = this.domObserver.onSelectionChange;
|
|
60
|
+
this.domObserver.onSelectionChange = ()=>{
|
|
61
|
+
// During a composition, we completely pause React-driven
|
|
62
|
+
// selection and DOM updates. Compositions are "fragile";
|
|
63
|
+
// in Safari, even updating the selection to the same
|
|
64
|
+
// position it's already set to will end the current
|
|
65
|
+
// composition.
|
|
66
|
+
if (this.composing) return;
|
|
67
|
+
originalOnSelectionChange();
|
|
68
|
+
};
|
|
58
69
|
} finally{
|
|
59
70
|
place.mount.replaceChildren(...reactContent);
|
|
60
71
|
for (const attr of place.mount.attributes){
|
|
@@ -73,10 +84,22 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
|
|
|
73
84
|
this.docView.destroy();
|
|
74
85
|
// @ts-expect-error this violates the typing but class does it, too.
|
|
75
86
|
this.docView = null;
|
|
87
|
+
this._destroyed = false;
|
|
76
88
|
}
|
|
77
89
|
get props() {
|
|
78
90
|
return this.nextProps;
|
|
79
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* @privateremarks
|
|
94
|
+
*
|
|
95
|
+
* We override this getter because the base implementation
|
|
96
|
+
* relies on checking `docView === null`, but we unconditionally
|
|
97
|
+
* set view.docView in a layout effect in the DocNodeView.
|
|
98
|
+
* This has the effect of "un-destroying" the EditorView,
|
|
99
|
+
* making it impossible to determine whether it's been destroyed.
|
|
100
|
+
*/ get isDestroyed() {
|
|
101
|
+
return this._destroyed;
|
|
102
|
+
}
|
|
80
103
|
setProps(props) {
|
|
81
104
|
this.update({
|
|
82
105
|
...this.props,
|
|
@@ -142,6 +165,7 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
|
|
|
142
165
|
super.destroy();
|
|
143
166
|
} finally{
|
|
144
167
|
this.dom.replaceChildren(...reactContent);
|
|
168
|
+
this._destroyed = true;
|
|
145
169
|
}
|
|
146
170
|
}
|
|
147
171
|
/**
|
|
@@ -16,6 +16,7 @@ const _constants = require("../constants.js");
|
|
|
16
16
|
const _beforeInputPlugin = require("../plugins/beforeInputPlugin.js");
|
|
17
17
|
const _useClientLayoutEffect = require("./useClientLayoutEffect.js");
|
|
18
18
|
const _useComponentEventListeners = require("./useComponentEventListeners.js");
|
|
19
|
+
const _useEffectEvent = require("./useEffectEvent.js");
|
|
19
20
|
const _useForceUpdate = require("./useForceUpdate.js");
|
|
20
21
|
let didWarnValueDefaultValue = false;
|
|
21
22
|
function useEditor(mount, options) {
|
|
@@ -77,30 +78,31 @@ function useEditor(mount, options) {
|
|
|
77
78
|
const [view, setView] = (0, _react.useState)(()=>{
|
|
78
79
|
return new _StaticEditorView.StaticEditorView(directEditorProps);
|
|
79
80
|
});
|
|
81
|
+
const createEditorView = (0, _useEffectEvent.useEffectEvent)((mount)=>{
|
|
82
|
+
if (mount) {
|
|
83
|
+
const view = new _ReactEditorView.ReactEditorView({
|
|
84
|
+
mount
|
|
85
|
+
}, directEditorProps);
|
|
86
|
+
view.dom.addEventListener("compositionend", forceUpdate);
|
|
87
|
+
return view;
|
|
88
|
+
}
|
|
89
|
+
return new _StaticEditorView.StaticEditorView(directEditorProps);
|
|
90
|
+
});
|
|
80
91
|
(0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
|
|
92
|
+
const view = createEditorView(mount);
|
|
93
|
+
setView(view);
|
|
81
94
|
return ()=>{
|
|
82
95
|
view.destroy();
|
|
83
96
|
};
|
|
84
97
|
}, [
|
|
85
|
-
|
|
98
|
+
createEditorView,
|
|
99
|
+
mount
|
|
86
100
|
]);
|
|
87
|
-
// This rule is concerned about infinite updates due to the
|
|
88
|
-
// call to setView. These calls are deliberately conditional,
|
|
89
|
-
// so this is not a concern.
|
|
90
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
91
101
|
(0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}, directEditorProps);
|
|
97
|
-
view.dom.addEventListener("compositionend", forceUpdate);
|
|
98
|
-
setView(view);
|
|
99
|
-
} else {
|
|
100
|
-
const view = new _StaticEditorView.StaticEditorView(directEditorProps);
|
|
101
|
-
setView(view);
|
|
102
|
-
}
|
|
103
|
-
} else if (view instanceof _ReactEditorView.ReactEditorView) {
|
|
102
|
+
// Ensure that the EditorView hasn't been destroyed before
|
|
103
|
+
// running effects. Running effects will reattach selection
|
|
104
|
+
// change listeners if the EditorView has been destroyed.
|
|
105
|
+
if (view instanceof _ReactEditorView.ReactEditorView && !view.isDestroyed) {
|
|
104
106
|
view.commitPendingEffects();
|
|
105
107
|
}
|
|
106
108
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "useEffectEvent", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return useEffectEvent;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = require("react");
|
|
12
|
+
function useEffectEvent(fn) {
|
|
13
|
+
const ref = (0, _react.useRef)(fn);
|
|
14
|
+
// Ideally this would be a useInsertionEffect, but
|
|
15
|
+
// that was introduced in React 18 and we still
|
|
16
|
+
// support React 17. useLayoutEffect is safe
|
|
17
|
+
// here as long as the function returned by
|
|
18
|
+
// useEffectEvent isn't called in a layout effect
|
|
19
|
+
// that's defined _before_ the useEffectEvent
|
|
20
|
+
// call, and effect events are never passed
|
|
21
|
+
// to child components.
|
|
22
|
+
(0, _react.useLayoutEffect)(()=>{
|
|
23
|
+
ref.current = fn;
|
|
24
|
+
}, [
|
|
25
|
+
fn
|
|
26
|
+
]);
|
|
27
|
+
return (0, _react.useCallback)(function() {
|
|
28
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
29
|
+
args[_key] = arguments[_key];
|
|
30
|
+
}
|
|
31
|
+
const f = ref.current;
|
|
32
|
+
return f(...args);
|
|
33
|
+
}, []);
|
|
34
|
+
}
|
|
@@ -14,6 +14,7 @@ const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js
|
|
|
14
14
|
const _EditorContext = require("../contexts/EditorContext.js");
|
|
15
15
|
const _viewdesc = require("../viewdesc.js");
|
|
16
16
|
const _useClientLayoutEffect = require("./useClientLayoutEffect.js");
|
|
17
|
+
const _useEffectEvent = require("./useEffectEvent.js");
|
|
17
18
|
function findContentDOM(source, children) {
|
|
18
19
|
return source?.contentDOM ?? children[0]?.dom?.parentElement ?? null;
|
|
19
20
|
}
|
|
@@ -25,7 +26,7 @@ function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
25
26
|
const [contentDOM, setContentDOM] = (0, _react.useState)(null);
|
|
26
27
|
const viewDescRef = (0, _react.useRef)();
|
|
27
28
|
const childrenRef = (0, _react.useRef)([]);
|
|
28
|
-
const create = (0,
|
|
29
|
+
const create = (0, _useEffectEvent.useEffectEvent)(()=>{
|
|
29
30
|
if (!(view instanceof _ReactEditorView.ReactEditorView)) {
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
@@ -47,13 +48,8 @@ function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
47
48
|
setContentDOM(contentDOM);
|
|
48
49
|
setNodeDOM(nodeDOM);
|
|
49
50
|
return viewDesc;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
parentRef,
|
|
53
|
-
constructor,
|
|
54
|
-
view
|
|
55
|
-
]);
|
|
56
|
-
const update = (0, _react.useCallback)((props)=>{
|
|
51
|
+
});
|
|
52
|
+
const update = (0, _useEffectEvent.useEffectEvent)(()=>{
|
|
57
53
|
if (!(view instanceof _ReactEditorView.ReactEditorView)) {
|
|
58
54
|
return false;
|
|
59
55
|
}
|
|
@@ -74,11 +70,8 @@ function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
74
70
|
}
|
|
75
71
|
const { node, decorations, innerDecorations } = props;
|
|
76
72
|
return viewDesc.matchesNode(node, decorations, innerDecorations) || viewDesc.update(node, decorations, innerDecorations, view);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
view
|
|
80
|
-
]);
|
|
81
|
-
const destroy = (0, _react.useCallback)(()=>{
|
|
73
|
+
});
|
|
74
|
+
const destroy = (0, _useEffectEvent.useEffectEvent)(()=>{
|
|
82
75
|
const viewDesc = viewDescRef.current;
|
|
83
76
|
if (!viewDesc) {
|
|
84
77
|
return;
|
|
@@ -92,13 +85,20 @@ function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
92
85
|
setDOM(null);
|
|
93
86
|
setContentDOM(null);
|
|
94
87
|
setNodeDOM(null);
|
|
88
|
+
});
|
|
89
|
+
(0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
|
|
90
|
+
viewDescRef.current = create();
|
|
91
|
+
return ()=>{
|
|
92
|
+
destroy();
|
|
93
|
+
};
|
|
95
94
|
}, [
|
|
96
|
-
|
|
95
|
+
create,
|
|
96
|
+
destroy
|
|
97
97
|
]);
|
|
98
98
|
(0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
|
|
99
|
-
if (!update(
|
|
99
|
+
if (!update()) {
|
|
100
100
|
destroy();
|
|
101
|
-
viewDescRef.current = create(
|
|
101
|
+
viewDescRef.current = create();
|
|
102
102
|
}
|
|
103
103
|
const viewDesc = viewDescRef.current;
|
|
104
104
|
if (!viewDesc) {
|
|
@@ -137,14 +137,6 @@ function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
});
|
|
140
|
-
(0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
|
|
141
|
-
return ()=>{
|
|
142
|
-
destroy();
|
|
143
|
-
viewDescRef.current = undefined;
|
|
144
|
-
};
|
|
145
|
-
}, [
|
|
146
|
-
destroy
|
|
147
|
-
]);
|
|
148
140
|
const childContextValue = (0, _react.useMemo)(()=>({
|
|
149
141
|
parentRef: viewDescRef,
|
|
150
142
|
siblingsRef: childrenRef
|
|
@@ -32,6 +32,7 @@ function changedNodeViews(a, b) {
|
|
|
32
32
|
*/ export class ReactEditorView extends EditorView {
|
|
33
33
|
nextProps;
|
|
34
34
|
prevState;
|
|
35
|
+
_destroyed;
|
|
35
36
|
constructor(place, props){
|
|
36
37
|
// Prevent the base class from destroying the React-managed nodes.
|
|
37
38
|
// Restore them below after invoking the base class constructor.
|
|
@@ -55,6 +56,16 @@ function changedNodeViews(a, b) {
|
|
|
55
56
|
this.domObserver.stop();
|
|
56
57
|
this.domObserver.observer = null;
|
|
57
58
|
this.domObserver.queue = [];
|
|
59
|
+
const originalOnSelectionChange = this.domObserver.onSelectionChange;
|
|
60
|
+
this.domObserver.onSelectionChange = ()=>{
|
|
61
|
+
// During a composition, we completely pause React-driven
|
|
62
|
+
// selection and DOM updates. Compositions are "fragile";
|
|
63
|
+
// in Safari, even updating the selection to the same
|
|
64
|
+
// position it's already set to will end the current
|
|
65
|
+
// composition.
|
|
66
|
+
if (this.composing) return;
|
|
67
|
+
originalOnSelectionChange();
|
|
68
|
+
};
|
|
58
69
|
} finally{
|
|
59
70
|
place.mount.replaceChildren(...reactContent);
|
|
60
71
|
for (const attr of place.mount.attributes){
|
|
@@ -73,10 +84,22 @@ function changedNodeViews(a, b) {
|
|
|
73
84
|
this.docView.destroy();
|
|
74
85
|
// @ts-expect-error this violates the typing but class does it, too.
|
|
75
86
|
this.docView = null;
|
|
87
|
+
this._destroyed = false;
|
|
76
88
|
}
|
|
77
89
|
get props() {
|
|
78
90
|
return this.nextProps;
|
|
79
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* @privateremarks
|
|
94
|
+
*
|
|
95
|
+
* We override this getter because the base implementation
|
|
96
|
+
* relies on checking `docView === null`, but we unconditionally
|
|
97
|
+
* set view.docView in a layout effect in the DocNodeView.
|
|
98
|
+
* This has the effect of "un-destroying" the EditorView,
|
|
99
|
+
* making it impossible to determine whether it's been destroyed.
|
|
100
|
+
*/ get isDestroyed() {
|
|
101
|
+
return this._destroyed;
|
|
102
|
+
}
|
|
80
103
|
setProps(props) {
|
|
81
104
|
this.update({
|
|
82
105
|
...this.props,
|
|
@@ -142,6 +165,7 @@ function changedNodeViews(a, b) {
|
|
|
142
165
|
super.destroy();
|
|
143
166
|
} finally{
|
|
144
167
|
this.dom.replaceChildren(...reactContent);
|
|
168
|
+
this._destroyed = true;
|
|
145
169
|
}
|
|
146
170
|
}
|
|
147
171
|
/**
|
|
@@ -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
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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 {
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
85
|
+
create,
|
|
86
|
+
destroy
|
|
87
87
|
]);
|
|
88
88
|
useClientLayoutEffect(()=>{
|
|
89
|
-
if (!update(
|
|
89
|
+
if (!update()) {
|
|
90
90
|
destroy();
|
|
91
|
-
viewDescRef.current = create(
|
|
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
|