@handlewithcare/react-prosemirror 3.0.5 → 3.0.6
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 +36 -6
- package/dist/cjs/components/WidgetView.js +1 -0
- package/dist/cjs/hooks/useComponentEventListeners.js +37 -4
- package/dist/cjs/hooks/useEditor.js +3 -4
- package/dist/esm/components/WidgetView.js +1 -0
- package/dist/esm/hooks/useComponentEventListeners.js +44 -11
- package/dist/esm/hooks/useEditor.js +3 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/components/CursorWrapper.d.ts +2 -4
- package/dist/types/components/WidgetViewComponentProps.d.ts +4 -3
- package/dist/types/contexts/EditorContext.d.ts +1 -1
- package/dist/types/hooks/useComponentEventListeners.d.ts +11 -10
- package/dist/types/hooks/useEditor.d.ts +2 -2
- package/dist/types/hooks/useEditorEventListener.d.ts +1 -1
- package/dist/types/props.d.ts +1 -1
- package/package.json +1 -1
- package/dist/cjs/plugins/componentEventListeners.js +0 -35
- package/dist/cjs/plugins/componentEventListenersPlugin.js +0 -35
- package/dist/esm/plugins/componentEventListeners.js +0 -25
- package/dist/esm/plugins/componentEventListenersPlugin.js +0 -25
- package/dist/types/plugins/componentEventListeners.d.ts +0 -4
- package/dist/types/plugins/componentEventListenersPlugin.d.ts +0 -4
package/README.md
CHANGED
|
@@ -837,10 +837,40 @@ significant contributors help shape our roadmap priorities.
|
|
|
837
837
|
[Become a Sponsor](https://handlewithcare.dev/pitter-patter/#become-a-sponsor)
|
|
838
838
|
|
|
839
839
|
<h3>Sponsors</h3>
|
|
840
|
-
|
|
841
|
-
<
|
|
842
|
-
<
|
|
843
|
-
<
|
|
844
|
-
<
|
|
845
|
-
|
|
840
|
+
|
|
841
|
+
<table>
|
|
842
|
+
<tbody>
|
|
843
|
+
<tr>
|
|
844
|
+
<td align="center" valign="top" >
|
|
845
|
+
<a href="https://moment.dev/">
|
|
846
|
+
<img src="https://media.githubusercontent.com/media/handlewithcarecollective/pitter-patter-sponsors/main/logos/Moment.png" alt="Moment" height="128">
|
|
847
|
+
<br>
|
|
848
|
+
Moment
|
|
849
|
+
</a>
|
|
850
|
+
</td>
|
|
851
|
+
<td align="center" valign="top" >
|
|
852
|
+
<a href="https://www.lingco.io/">
|
|
853
|
+
<img src="https://media.githubusercontent.com/media/handlewithcarecollective/pitter-patter-sponsors/main/logos/Lingco.png" alt="Lingco" height="128">
|
|
854
|
+
<br>
|
|
855
|
+
Lingco
|
|
856
|
+
</a>
|
|
857
|
+
</td>
|
|
858
|
+
<td align="center" valign="top" >
|
|
859
|
+
<a href="https://dskrpt.de/">
|
|
860
|
+
<img src="https://media.githubusercontent.com/media/handlewithcarecollective/pitter-patter-sponsors/main/logos/Dskrpt.png" alt="dskrpt" height="128">
|
|
861
|
+
<br>
|
|
862
|
+
dskrpt
|
|
863
|
+
</a>
|
|
864
|
+
</td>
|
|
865
|
+
<td align="center" valign="top" >
|
|
866
|
+
<a href="https://char.com/">
|
|
867
|
+
<img src="https://media.githubusercontent.com/media/handlewithcarecollective/pitter-patter-sponsors/main/logos/Fastrepl.png" alt="Fastrepl" height="128">
|
|
868
|
+
<br>
|
|
869
|
+
Fastrepl
|
|
870
|
+
</a>
|
|
871
|
+
</td>
|
|
872
|
+
</tr>
|
|
873
|
+
</tbody>
|
|
874
|
+
</table>
|
|
875
|
+
|
|
846
876
|
<!--sponsorsend-->
|
|
@@ -78,6 +78,7 @@ function WidgetView(param) {
|
|
|
78
78
|
viewDescRef.current.parent = parentRef.current;
|
|
79
79
|
viewDescRef.current.widget = widget;
|
|
80
80
|
viewDescRef.current.dom = domRef.current;
|
|
81
|
+
viewDescRef.current.dom.pmViewDesc = viewDescRef.current;
|
|
81
82
|
}
|
|
82
83
|
if (!siblingsRef.current.includes(viewDescRef.current)) {
|
|
83
84
|
siblingsRef.current.push(viewDescRef.current);
|
|
@@ -9,8 +9,8 @@ Object.defineProperty(exports, "useComponentEventListeners", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _react = require("react");
|
|
12
|
-
const
|
|
13
|
-
function useComponentEventListeners() {
|
|
12
|
+
const _reactdom = require("react-dom");
|
|
13
|
+
function useComponentEventListeners(handleDOMEventsProp) {
|
|
14
14
|
const [registry, setRegistry] = (0, _react.useState)(new Map());
|
|
15
15
|
const registerEventListener = (0, _react.useCallback)((eventType, handler)=>{
|
|
16
16
|
const handlers = registry.get(eventType) ?? [];
|
|
@@ -28,12 +28,45 @@ function useComponentEventListeners() {
|
|
|
28
28
|
}, [
|
|
29
29
|
registry
|
|
30
30
|
]);
|
|
31
|
-
|
|
31
|
+
(0, _react.useLayoutEffect)(()=>{
|
|
32
|
+
if (!handleDOMEventsProp) return;
|
|
33
|
+
for (const [eventType, handler] of Object.entries(handleDOMEventsProp)){
|
|
34
|
+
if (!handler) return;
|
|
35
|
+
registerEventListener(eventType, handler);
|
|
36
|
+
}
|
|
37
|
+
return ()=>{
|
|
38
|
+
for (const [eventType, handler] of Object.entries(handleDOMEventsProp)){
|
|
39
|
+
if (!handler) return;
|
|
40
|
+
unregisterEventListener(eventType, handler);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}, [
|
|
44
|
+
handleDOMEventsProp,
|
|
45
|
+
registerEventListener,
|
|
46
|
+
unregisterEventListener
|
|
47
|
+
]);
|
|
48
|
+
const handleDOMEvents = (0, _react.useMemo)(()=>{
|
|
49
|
+
const domEventHandlers = {};
|
|
50
|
+
for (const [eventType, handlers] of registry.entries()){
|
|
51
|
+
function handleEvent(view, event) {
|
|
52
|
+
for (const handler of handlers){
|
|
53
|
+
let handled = false;
|
|
54
|
+
(0, _reactdom.unstable_batchedUpdates)(()=>{
|
|
55
|
+
handled = !!handler(view, event);
|
|
56
|
+
});
|
|
57
|
+
if (handled || event.defaultPrevented) return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
domEventHandlers[eventType] = handleEvent;
|
|
62
|
+
}
|
|
63
|
+
return domEventHandlers;
|
|
64
|
+
}, [
|
|
32
65
|
registry
|
|
33
66
|
]);
|
|
34
67
|
return {
|
|
35
68
|
registerEventListener,
|
|
36
69
|
unregisterEventListener,
|
|
37
|
-
|
|
70
|
+
handleDOMEvents
|
|
38
71
|
};
|
|
39
72
|
}
|
|
@@ -32,7 +32,7 @@ function useEditor(mount, options) {
|
|
|
32
32
|
const defaultState = options.defaultState ?? _constants.EMPTY_STATE;
|
|
33
33
|
const [_state, setState] = (0, _react.useState)(defaultState);
|
|
34
34
|
const state = options.state ?? _state;
|
|
35
|
-
const {
|
|
35
|
+
const { handleDOMEvents, registerEventListener, unregisterEventListener } = (0, _useComponentEventListeners.useComponentEventListeners)(options.handleDOMEvents);
|
|
36
36
|
const setCursorWrapper = (0, _react.useCallback)((deco)=>{
|
|
37
37
|
(0, _reactdom.flushSync)(()=>{
|
|
38
38
|
_setCursorWrapper(deco);
|
|
@@ -40,11 +40,9 @@ function useEditor(mount, options) {
|
|
|
40
40
|
}, []);
|
|
41
41
|
const plugins = (0, _react.useMemo)(()=>[
|
|
42
42
|
...options.plugins ?? [],
|
|
43
|
-
componentEventListenersPlugin,
|
|
44
43
|
(0, _beforeInputPlugin.beforeInputPlugin)(setCursorWrapper)
|
|
45
44
|
], [
|
|
46
45
|
options.plugins,
|
|
47
|
-
componentEventListenersPlugin,
|
|
48
46
|
setCursorWrapper
|
|
49
47
|
]);
|
|
50
48
|
const dispatchTransaction = (0, _react.useCallback)(function dispatchTransaction(tr) {
|
|
@@ -73,7 +71,8 @@ function useEditor(mount, options) {
|
|
|
73
71
|
...options,
|
|
74
72
|
state,
|
|
75
73
|
plugins,
|
|
76
|
-
dispatchTransaction
|
|
74
|
+
dispatchTransaction,
|
|
75
|
+
handleDOMEvents
|
|
77
76
|
};
|
|
78
77
|
const [view, setView] = (0, _react.useState)(()=>{
|
|
79
78
|
return new _StaticEditorView.StaticEditorView(directEditorProps);
|
|
@@ -27,6 +27,7 @@ export function WidgetView(param) {
|
|
|
27
27
|
viewDescRef.current.parent = parentRef.current;
|
|
28
28
|
viewDescRef.current.widget = widget;
|
|
29
29
|
viewDescRef.current.dom = domRef.current;
|
|
30
|
+
viewDescRef.current.dom.pmViewDesc = viewDescRef.current;
|
|
30
31
|
}
|
|
31
32
|
if (!siblingsRef.current.includes(viewDescRef.current)) {
|
|
32
33
|
siblingsRef.current.push(viewDescRef.current);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/* Copyright (c) The New York Times Company */ import { useCallback, useMemo, useState } from "react";
|
|
2
|
-
import {
|
|
1
|
+
/* Copyright (c) The New York Times Company */ import { useCallback, useLayoutEffect, useMemo, useState } from "react";
|
|
2
|
+
import { unstable_batchedUpdates as batch } from "react-dom";
|
|
3
3
|
/**
|
|
4
4
|
* Produces a plugin that can be used with ProseMirror to handle DOM
|
|
5
5
|
* events at the EditorView.dom element.
|
|
@@ -14,18 +14,18 @@ import { componentEventListeners } from "../plugins/componentEventListeners.js";
|
|
|
14
14
|
* @privateRemarks
|
|
15
15
|
*
|
|
16
16
|
* This hook uses a combination of mutable and immutable updates to give
|
|
17
|
-
* us precise control over when we re-create the
|
|
17
|
+
* us precise control over when we re-create the event listeners.
|
|
18
18
|
*
|
|
19
|
-
* The
|
|
19
|
+
* The hook has a mutable reference to the set of handlers for each
|
|
20
20
|
* event type, but the set of event types is static. This means that we
|
|
21
|
-
* need to produce a new
|
|
22
|
-
* registered. We avoid producing a new
|
|
23
|
-
* scenario to avoid the performance overhead of
|
|
24
|
-
* in the EditorView.
|
|
21
|
+
* need to produce a new handleDOMEVents record whenever a new event type is
|
|
22
|
+
* registered. We avoid producing a new record in any other
|
|
23
|
+
* scenario to avoid the performance overhead of re-registering the event
|
|
24
|
+
* listeners in the EditorView.
|
|
25
25
|
*
|
|
26
26
|
* To accomplish this, we shallowly clone the registry whenever a new event
|
|
27
27
|
* type is registered.
|
|
28
|
-
*/ export function useComponentEventListeners() {
|
|
28
|
+
*/ export function useComponentEventListeners(handleDOMEventsProp) {
|
|
29
29
|
const [registry, setRegistry] = useState(new Map());
|
|
30
30
|
const registerEventListener = useCallback((eventType, handler)=>{
|
|
31
31
|
const handlers = registry.get(eventType) ?? [];
|
|
@@ -43,12 +43,45 @@ import { componentEventListeners } from "../plugins/componentEventListeners.js";
|
|
|
43
43
|
}, [
|
|
44
44
|
registry
|
|
45
45
|
]);
|
|
46
|
-
|
|
46
|
+
useLayoutEffect(()=>{
|
|
47
|
+
if (!handleDOMEventsProp) return;
|
|
48
|
+
for (const [eventType, handler] of Object.entries(handleDOMEventsProp)){
|
|
49
|
+
if (!handler) return;
|
|
50
|
+
registerEventListener(eventType, handler);
|
|
51
|
+
}
|
|
52
|
+
return ()=>{
|
|
53
|
+
for (const [eventType, handler] of Object.entries(handleDOMEventsProp)){
|
|
54
|
+
if (!handler) return;
|
|
55
|
+
unregisterEventListener(eventType, handler);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}, [
|
|
59
|
+
handleDOMEventsProp,
|
|
60
|
+
registerEventListener,
|
|
61
|
+
unregisterEventListener
|
|
62
|
+
]);
|
|
63
|
+
const handleDOMEvents = useMemo(()=>{
|
|
64
|
+
const domEventHandlers = {};
|
|
65
|
+
for (const [eventType, handlers] of registry.entries()){
|
|
66
|
+
function handleEvent(view, event) {
|
|
67
|
+
for (const handler of handlers){
|
|
68
|
+
let handled = false;
|
|
69
|
+
batch(()=>{
|
|
70
|
+
handled = !!handler(view, event);
|
|
71
|
+
});
|
|
72
|
+
if (handled || event.defaultPrevented) return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
domEventHandlers[eventType] = handleEvent;
|
|
77
|
+
}
|
|
78
|
+
return domEventHandlers;
|
|
79
|
+
}, [
|
|
47
80
|
registry
|
|
48
81
|
]);
|
|
49
82
|
return {
|
|
50
83
|
registerEventListener,
|
|
51
84
|
unregisterEventListener,
|
|
52
|
-
|
|
85
|
+
handleDOMEvents
|
|
53
86
|
};
|
|
54
87
|
}
|
|
@@ -30,7 +30,7 @@ let didWarnValueDefaultValue = false;
|
|
|
30
30
|
const defaultState = options.defaultState ?? EMPTY_STATE;
|
|
31
31
|
const [_state, setState] = useState(defaultState);
|
|
32
32
|
const state = options.state ?? _state;
|
|
33
|
-
const {
|
|
33
|
+
const { handleDOMEvents, registerEventListener, unregisterEventListener } = useComponentEventListeners(options.handleDOMEvents);
|
|
34
34
|
const setCursorWrapper = useCallback((deco)=>{
|
|
35
35
|
flushSync(()=>{
|
|
36
36
|
_setCursorWrapper(deco);
|
|
@@ -38,11 +38,9 @@ let didWarnValueDefaultValue = false;
|
|
|
38
38
|
}, []);
|
|
39
39
|
const plugins = useMemo(()=>[
|
|
40
40
|
...options.plugins ?? [],
|
|
41
|
-
componentEventListenersPlugin,
|
|
42
41
|
beforeInputPlugin(setCursorWrapper)
|
|
43
42
|
], [
|
|
44
43
|
options.plugins,
|
|
45
|
-
componentEventListenersPlugin,
|
|
46
44
|
setCursorWrapper
|
|
47
45
|
]);
|
|
48
46
|
const dispatchTransaction = useCallback(function dispatchTransaction(tr) {
|
|
@@ -71,7 +69,8 @@ let didWarnValueDefaultValue = false;
|
|
|
71
69
|
...options,
|
|
72
70
|
state,
|
|
73
71
|
plugins,
|
|
74
|
-
dispatchTransaction
|
|
72
|
+
dispatchTransaction,
|
|
73
|
+
handleDOMEvents
|
|
75
74
|
};
|
|
76
75
|
const [view, setView] = useState(()=>{
|
|
77
76
|
return new StaticEditorView(directEditorProps);
|