@handlewithcare/react-prosemirror 3.1.0-tiptap.49 → 3.1.0-tiptap.51
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/cjs/ReactEditorView.js +2 -0
- package/dist/cjs/components/ChildNodeViews.js +14 -9
- package/dist/cjs/components/CursorWrapper.js +6 -9
- package/dist/cjs/components/TextNodeView.js +109 -38
- package/dist/cjs/components/TrailingHackView.js +29 -0
- package/dist/cjs/hooks/useComponentEventListeners.js +46 -5
- package/dist/cjs/hooks/useEditor.js +3 -6
- package/dist/cjs/hooks/useNodeViewDescription.js +37 -16
- package/dist/cjs/plugins/beforeInputPlugin.js +41 -43
- package/dist/cjs/viewdesc.js +10 -3
- package/dist/esm/ReactEditorView.js +2 -0
- package/dist/esm/components/ChildNodeViews.js +14 -9
- package/dist/esm/components/CursorWrapper.js +7 -10
- package/dist/esm/components/TextNodeView.js +109 -38
- package/dist/esm/components/TrailingHackView.js +30 -1
- package/dist/esm/hooks/useComponentEventListeners.js +53 -12
- package/dist/esm/hooks/useEditor.js +3 -6
- package/dist/esm/hooks/useNodeViewDescription.js +38 -17
- package/dist/esm/plugins/beforeInputPlugin.js +41 -43
- package/dist/esm/viewdesc.js +10 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ReactEditorView.d.ts +4 -0
- package/dist/types/components/TextNodeView.d.ts +14 -4
- package/dist/types/components/TrailingHackView.d.ts +1 -1
- package/dist/types/constants.d.ts +1 -1
- 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 +26 -26
- package/dist/types/viewdesc.d.ts +2 -2
- package/package.json +2 -1
- package/dist/cjs/tiptap/utils/ssrJSDOMPatch.js +0 -59
- package/dist/esm/tiptap/utils/ssrJSDOMPatch.js +0 -56
- package/dist/types/tiptap/utils/ssrJSDOMPatch.d.ts +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment, Slice } from "prosemirror-model";
|
|
2
2
|
import { Plugin, TextSelection } from "prosemirror-state";
|
|
3
|
+
import { ReactEditorView } from "../ReactEditorView.js";
|
|
3
4
|
import { CursorWrapper } from "../components/CursorWrapper.js";
|
|
4
5
|
import { widget } from "../decorations/ReactWidgetType.js";
|
|
5
6
|
function insertText(view, eventData) {
|
|
@@ -46,68 +47,41 @@ function handleGapCursorComposition(view) {
|
|
|
46
47
|
}
|
|
47
48
|
export function beforeInputPlugin(setCursorWrapper) {
|
|
48
49
|
let compositionMarks = null;
|
|
49
|
-
let precompositionSnapshot = null;
|
|
50
50
|
return new Plugin({
|
|
51
51
|
props: {
|
|
52
52
|
handleDOMEvents: {
|
|
53
53
|
compositionstart (view) {
|
|
54
|
-
|
|
55
|
-
view.
|
|
54
|
+
if (!(view instanceof ReactEditorView)) return false;
|
|
55
|
+
view.input.composing = true;
|
|
56
|
+
compositionMarks = view.state.storedMarks;
|
|
57
|
+
const tr = view.state.tr.deleteSelection().setStoredMarks(null);
|
|
58
|
+
view.dispatch(tr);
|
|
56
59
|
handleGapCursorComposition(view);
|
|
57
60
|
const { state } = view;
|
|
58
|
-
|
|
59
|
-
if (compositionMarks) {
|
|
61
|
+
if (compositionMarks?.length) {
|
|
60
62
|
setCursorWrapper(widget(state.selection.from, CursorWrapper, {
|
|
61
63
|
key: "cursor-wrapper",
|
|
62
|
-
marks: compositionMarks
|
|
64
|
+
marks: compositionMarks,
|
|
65
|
+
side: 1
|
|
63
66
|
}));
|
|
64
67
|
}
|
|
65
|
-
// Snapshot the siblings of the node that contains the
|
|
66
|
-
// current cursor. We'll restore this later, so that React
|
|
67
|
-
// doesn't panic about unknown DOM nodes.
|
|
68
|
-
const { node: parent } = view.domAtPos($pos.pos);
|
|
69
|
-
precompositionSnapshot = [];
|
|
70
|
-
for (const node of parent.childNodes){
|
|
71
|
-
precompositionSnapshot.push(node);
|
|
72
|
-
}
|
|
73
|
-
// @ts-expect-error Internal property - input
|
|
74
|
-
view.input.composing = true;
|
|
75
68
|
return true;
|
|
76
69
|
},
|
|
77
70
|
compositionupdate () {
|
|
78
71
|
return true;
|
|
79
72
|
},
|
|
80
73
|
compositionend (view, event) {
|
|
81
|
-
|
|
74
|
+
if (!(view instanceof ReactEditorView)) return false;
|
|
75
|
+
if (!view.composing) return false;
|
|
82
76
|
view.input.composing = false;
|
|
83
|
-
const { state } = view;
|
|
84
|
-
const { node: parent } = view.domAtPos(state.selection.from);
|
|
85
|
-
if (precompositionSnapshot) {
|
|
86
|
-
// Restore the snapshot of the parent node's children
|
|
87
|
-
// from before the composition started. This gives us a
|
|
88
|
-
// clean slate from which to dispatch our transaction
|
|
89
|
-
// and trigger a React update.
|
|
90
|
-
precompositionSnapshot.forEach((prevNode, i)=>{
|
|
91
|
-
if (parent.childNodes.length <= i) {
|
|
92
|
-
parent.appendChild(prevNode);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
parent.replaceChild(prevNode, parent.childNodes.item(i));
|
|
96
|
-
});
|
|
97
|
-
if (parent.childNodes.length > precompositionSnapshot.length) {
|
|
98
|
-
for(let i = precompositionSnapshot.length; i < parent.childNodes.length; i++){
|
|
99
|
-
parent.removeChild(parent.childNodes.item(i));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (event.data) {
|
|
104
|
-
insertText(view, event.data, {
|
|
105
|
-
marks: compositionMarks
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
77
|
compositionMarks = null;
|
|
109
|
-
precompositionSnapshot = null;
|
|
110
78
|
setCursorWrapper(null);
|
|
79
|
+
if (view.input.compositionNode && !view.input.compositionNode.pmViewDesc) {
|
|
80
|
+
view.input.compositionNode.remove();
|
|
81
|
+
}
|
|
82
|
+
view.input.compositionEndedAt = event.timeStamp;
|
|
83
|
+
view.input.compositionNode = null;
|
|
84
|
+
view.input.compositionID++;
|
|
111
85
|
return true;
|
|
112
86
|
},
|
|
113
87
|
beforeinput (view, event) {
|
|
@@ -156,6 +130,30 @@ export function beforeInputPlugin(setCursorWrapper) {
|
|
|
156
130
|
insertText(view, event.data);
|
|
157
131
|
break;
|
|
158
132
|
}
|
|
133
|
+
case "insertCompositionText":
|
|
134
|
+
{
|
|
135
|
+
const { tr } = view.state;
|
|
136
|
+
// There's always a range on insertCompositionText beforeinput events
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
138
|
+
const range = event.getTargetRanges()[0];
|
|
139
|
+
const start = view.posAtDOM(range.startContainer, range.startOffset);
|
|
140
|
+
const end = view.posAtDOM(range.endContainer, range.endOffset, 1);
|
|
141
|
+
if (view.state.doc.textBetween(start, end, "**", "*") === event.data) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (event.data) {
|
|
145
|
+
if (compositionMarks) tr.ensureMarks(compositionMarks);
|
|
146
|
+
tr.insertText(event.data, start, end);
|
|
147
|
+
} else {
|
|
148
|
+
tr.delete(start, end);
|
|
149
|
+
}
|
|
150
|
+
view.dom.addEventListener("input", ()=>{
|
|
151
|
+
view.dispatch(tr);
|
|
152
|
+
}, {
|
|
153
|
+
once: true
|
|
154
|
+
});
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
159
157
|
case "deleteWordBackward":
|
|
160
158
|
case "deleteHardLineBackward":
|
|
161
159
|
case "deleteSoftLineBackward":
|
package/dist/esm/viewdesc.js
CHANGED
|
@@ -235,7 +235,9 @@ export class ViewDesc {
|
|
|
235
235
|
prev = i ? this.children[i - 1] : null;
|
|
236
236
|
if (!prev || prev.dom.parentNode == this.contentDOM) break;
|
|
237
237
|
}
|
|
238
|
-
if (prev && side && enter && !prev.border && !prev.domAtom)
|
|
238
|
+
if (prev && side && enter && !prev.border && !prev.domAtom) {
|
|
239
|
+
return prev.domFromPos(prev.size, side);
|
|
240
|
+
}
|
|
239
241
|
return {
|
|
240
242
|
node: this.contentDOM,
|
|
241
243
|
offset: prev ? domIndex(prev.dom) + 1 : 0
|
|
@@ -370,7 +372,9 @@ export class ViewDesc {
|
|
|
370
372
|
const after = selRange.focusNode.childNodes[selRange.focusOffset];
|
|
371
373
|
if (after && after.contentEditable == "false") force = true;
|
|
372
374
|
}
|
|
373
|
-
if (!(force || brKludge && browser.safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset))
|
|
375
|
+
if (!(force || brKludge && browser.safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset)) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
374
378
|
// Selection.extend can be used to create an 'inverted' selection
|
|
375
379
|
// (one where the focus is before the anchor), but not all
|
|
376
380
|
// browsers support it yet.
|
|
@@ -645,7 +649,10 @@ export class TextViewDesc extends NodeViewDesc {
|
|
|
645
649
|
skip: skip || true
|
|
646
650
|
};
|
|
647
651
|
}
|
|
648
|
-
update(
|
|
652
|
+
update(node, outerDeco, _innerDeco, _view) {
|
|
653
|
+
if (this.dirty == NODE_DIRTY || this.dirty != NOT_DIRTY && !this.inParent() || !node.sameMarkup(this.node)) return false;
|
|
654
|
+
this.updateOuterDeco(outerDeco);
|
|
655
|
+
this.node = node;
|
|
649
656
|
this.dirty = NOT_DIRTY;
|
|
650
657
|
return true;
|
|
651
658
|
}
|