prosemirror-view 1.38.0 → 1.39.0
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/CHANGELOG.md +20 -0
- package/dist/index.cjs +19 -6
- package/dist/index.d.cts +7 -100
- package/dist/index.d.ts +7 -100
- package/dist/index.js +18 -7
- package/package.json +1 -1
- package/src/domchange.ts +3 -2
- package/src/domcoords.ts +5 -3
- package/src/domobserver.ts +1 -0
- package/src/index.ts +6 -1
- package/src/input.ts +8 -2
- package/src/viewdesc.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 1.39.0 (2025-04-04)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where, with some types of schemas, pressing Enter on Android with a Chinese keyboard wouldn't properly detect the Enter press.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
The new `dragCopies` prop can be used to configure whether a drag event inside the editor copies or moves content.
|
|
10
|
+
|
|
11
|
+
## 1.38.1 (2025-03-04)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Fix a regression in 1.38.0 that breaks scrolling back to the selection after Chrome tries to reset it on focus.
|
|
16
|
+
|
|
17
|
+
Remove some internally used types from the public type declaration files. Include file extension in web test local imports
|
|
18
|
+
|
|
19
|
+
Fix an issue where scrolling the cursor into view could inappropriately scroll parent nodes of absolutely positioned elements.
|
|
20
|
+
|
|
1
21
|
## 1.38.0 (2025-02-12)
|
|
2
22
|
|
|
3
23
|
### New features
|
package/dist/index.cjs
CHANGED
|
@@ -200,9 +200,12 @@ function scrollRectIntoView(view, rect, startDOM) {
|
|
|
200
200
|
var scrollThreshold = view.someProp("scrollThreshold") || 0,
|
|
201
201
|
scrollMargin = view.someProp("scrollMargin") || 5;
|
|
202
202
|
var doc = view.dom.ownerDocument;
|
|
203
|
-
for (var parent = startDOM || view.dom;;
|
|
203
|
+
for (var parent = startDOM || view.dom;;) {
|
|
204
204
|
if (!parent) break;
|
|
205
|
-
if (parent.nodeType != 1)
|
|
205
|
+
if (parent.nodeType != 1) {
|
|
206
|
+
parent = parentNode(parent);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
206
209
|
var elt = parent;
|
|
207
210
|
var atTop = elt == doc.body;
|
|
208
211
|
var bounding = atTop ? windowRect(doc) : clientRect(elt);
|
|
@@ -228,7 +231,9 @@ function scrollRectIntoView(view, rect, startDOM) {
|
|
|
228
231
|
};
|
|
229
232
|
}
|
|
230
233
|
}
|
|
231
|
-
|
|
234
|
+
var pos = atTop ? "fixed" : getComputedStyle(parent).position;
|
|
235
|
+
if (/^(fixed|sticky)$/.test(pos)) break;
|
|
236
|
+
parent = pos == "absolute" ? parent.offsetParent : parentNode(parent);
|
|
232
237
|
}
|
|
233
238
|
}
|
|
234
239
|
function storeScrollPos(view) {
|
|
@@ -3406,6 +3411,7 @@ editHandlers.paste = function (view, _event) {
|
|
|
3406
3411
|
if (view.composing && !android) return;
|
|
3407
3412
|
var data = brokenClipboardAPI ? null : event.clipboardData;
|
|
3408
3413
|
var plain = view.input.shiftKey && view.input.lastKeyCode != 45;
|
|
3414
|
+
console.log("paste event", !!data, view.state.selection.from, view.state.selection.to);
|
|
3409
3415
|
if (data && doPaste(view, getText(data), data.getData("text/html"), plain, event)) event.preventDefault();else capturePaste(view, event);
|
|
3410
3416
|
};
|
|
3411
3417
|
var Dragging = _createClass(function Dragging(slice, move, node) {
|
|
@@ -3415,6 +3421,12 @@ var Dragging = _createClass(function Dragging(slice, move, node) {
|
|
|
3415
3421
|
this.node = node;
|
|
3416
3422
|
});
|
|
3417
3423
|
var dragCopyModifier = mac ? "altKey" : "ctrlKey";
|
|
3424
|
+
function dragMoves(view, event) {
|
|
3425
|
+
var moves = view.someProp("dragCopies", function (test) {
|
|
3426
|
+
return !test(event);
|
|
3427
|
+
});
|
|
3428
|
+
return moves != null ? moves : !event[dragCopyModifier];
|
|
3429
|
+
}
|
|
3418
3430
|
handlers.dragstart = function (view, _event) {
|
|
3419
3431
|
var event = _event;
|
|
3420
3432
|
var mouseDown = view.input.mouseDown;
|
|
@@ -3438,7 +3450,7 @@ handlers.dragstart = function (view, _event) {
|
|
|
3438
3450
|
event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
|
|
3439
3451
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
3440
3452
|
if (!brokenClipboardAPI) event.dataTransfer.setData("text/plain", text);
|
|
3441
|
-
view.dragging = new Dragging(slice,
|
|
3453
|
+
view.dragging = new Dragging(slice, dragMoves(view, event), node);
|
|
3442
3454
|
};
|
|
3443
3455
|
handlers.dragend = function (view) {
|
|
3444
3456
|
var dragging = view.dragging;
|
|
@@ -3465,7 +3477,7 @@ editHandlers.drop = function (view, _event) {
|
|
|
3465
3477
|
} else {
|
|
3466
3478
|
slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
|
|
3467
3479
|
}
|
|
3468
|
-
var move = !!(dragging &&
|
|
3480
|
+
var move = !!(dragging && dragMoves(view, event));
|
|
3469
3481
|
if (view.someProp("handleDrop", function (f) {
|
|
3470
3482
|
return f(view, event, slice || prosemirrorModel.Slice.empty, move);
|
|
3471
3483
|
})) {
|
|
@@ -4369,6 +4381,7 @@ var DOMObserver = function () {
|
|
|
4369
4381
|
view.input.lastFocus = 0;
|
|
4370
4382
|
selectionToDOM(view);
|
|
4371
4383
|
this.currentSelection.set(sel);
|
|
4384
|
+
view.scrollToSelection();
|
|
4372
4385
|
} else if (from > -1 || newSel) {
|
|
4373
4386
|
if (from > -1) {
|
|
4374
4387
|
view.docView.markDirty(from, to);
|
|
@@ -4656,7 +4669,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
4656
4669
|
var nextSel;
|
|
4657
4670
|
if ((ios && view.input.lastIOSEnter > Date.now() - 225 && (!inlineChange || addedNodes.some(function (n) {
|
|
4658
4671
|
return n.nodeName == "DIV" || n.nodeName == "P";
|
|
4659
|
-
})) || !inlineChange && $from.pos < parse.doc.content.size && !$from.sameParent($to) && (nextSel = prosemirrorState.Selection.findFrom(parse.doc.resolve($from.pos + 1), 1, true)) && nextSel.head
|
|
4672
|
+
})) || !inlineChange && $from.pos < parse.doc.content.size && (!$from.sameParent($to) || !$from.parent.inlineContent) && (nextSel = prosemirrorState.Selection.findFrom(parse.doc.resolve($from.pos + 1), 1, true)) && nextSel.head > $from.pos) && view.someProp("handleKeyDown", function (f) {
|
|
4660
4673
|
return f(view, keyEvent(13, "Enter"));
|
|
4661
4674
|
})) {
|
|
4662
4675
|
view.input.lastIOSEnter = 0;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
|
|
2
|
-
import { Mark, Node,
|
|
2
|
+
import { Mark, Node, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
|
|
3
3
|
import { Mapping } from 'prosemirror-transform';
|
|
4
4
|
|
|
5
5
|
type DOMNode = InstanceType<typeof window.Node>;
|
|
@@ -234,7 +234,6 @@ declare class DecorationGroup implements DecorationSource {
|
|
|
234
234
|
|
|
235
235
|
declare global {
|
|
236
236
|
interface Node {
|
|
237
|
-
pmViewDesc?: ViewDesc;
|
|
238
237
|
}
|
|
239
238
|
}
|
|
240
239
|
/**
|
|
@@ -361,104 +360,6 @@ interface MarkView {
|
|
|
361
360
|
*/
|
|
362
361
|
destroy?: () => void;
|
|
363
362
|
}
|
|
364
|
-
declare class ViewDesc {
|
|
365
|
-
parent: ViewDesc | undefined;
|
|
366
|
-
children: ViewDesc[];
|
|
367
|
-
dom: DOMNode;
|
|
368
|
-
contentDOM: HTMLElement | null;
|
|
369
|
-
dirty: number;
|
|
370
|
-
node: Node | null;
|
|
371
|
-
constructor(parent: ViewDesc | undefined, children: ViewDesc[], dom: DOMNode, contentDOM: HTMLElement | null);
|
|
372
|
-
matchesWidget(widget: Decoration): boolean;
|
|
373
|
-
matchesMark(mark: Mark): boolean;
|
|
374
|
-
matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
|
|
375
|
-
matchesHack(nodeName: string): boolean;
|
|
376
|
-
parseRule(): Omit<TagParseRule, "tag"> | null;
|
|
377
|
-
stopEvent(event: Event): boolean;
|
|
378
|
-
get size(): number;
|
|
379
|
-
get border(): number;
|
|
380
|
-
destroy(): void;
|
|
381
|
-
posBeforeChild(child: ViewDesc): number;
|
|
382
|
-
get posBefore(): number;
|
|
383
|
-
get posAtStart(): number;
|
|
384
|
-
get posAfter(): number;
|
|
385
|
-
get posAtEnd(): number;
|
|
386
|
-
localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
387
|
-
nearestDesc(dom: DOMNode): ViewDesc | undefined;
|
|
388
|
-
nearestDesc(dom: DOMNode, onlyNodes: true): NodeViewDesc | undefined;
|
|
389
|
-
getDesc(dom: DOMNode): ViewDesc | undefined;
|
|
390
|
-
posFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
391
|
-
descAt(pos: number): ViewDesc | undefined;
|
|
392
|
-
domFromPos(pos: number, side: number): {
|
|
393
|
-
node: DOMNode;
|
|
394
|
-
offset: number;
|
|
395
|
-
atom?: number;
|
|
396
|
-
};
|
|
397
|
-
parseRange(from: number, to: number, base?: number): {
|
|
398
|
-
node: DOMNode;
|
|
399
|
-
from: number;
|
|
400
|
-
to: number;
|
|
401
|
-
fromOffset: number;
|
|
402
|
-
toOffset: number;
|
|
403
|
-
};
|
|
404
|
-
emptyChildAt(side: number): boolean;
|
|
405
|
-
domAfterPos(pos: number): DOMNode;
|
|
406
|
-
setSelection(anchor: number, head: number, view: EditorView, force?: boolean): void;
|
|
407
|
-
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
408
|
-
get contentLost(): boolean | null;
|
|
409
|
-
markDirty(from: number, to: number): void;
|
|
410
|
-
markParentsDirty(): void;
|
|
411
|
-
get domAtom(): boolean;
|
|
412
|
-
get ignoreForCoords(): boolean;
|
|
413
|
-
isText(text: string): boolean;
|
|
414
|
-
}
|
|
415
|
-
declare class NodeViewDesc extends ViewDesc {
|
|
416
|
-
node: Node;
|
|
417
|
-
outerDeco: readonly Decoration[];
|
|
418
|
-
innerDeco: DecorationSource;
|
|
419
|
-
readonly nodeDOM: DOMNode;
|
|
420
|
-
constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, contentDOM: HTMLElement | null, nodeDOM: DOMNode, view: EditorView, pos: number);
|
|
421
|
-
static create(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView, pos: number): NodeViewDesc | TextViewDesc;
|
|
422
|
-
parseRule(): Omit<TagParseRule, "tag"> | null;
|
|
423
|
-
matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
|
|
424
|
-
get size(): number;
|
|
425
|
-
get border(): 0 | 1;
|
|
426
|
-
updateChildren(view: EditorView, pos: number): void;
|
|
427
|
-
localCompositionInfo(view: EditorView, pos: number): {
|
|
428
|
-
node: Text;
|
|
429
|
-
pos: number;
|
|
430
|
-
text: string;
|
|
431
|
-
} | null;
|
|
432
|
-
protectLocalComposition(view: EditorView, { node, pos, text }: {
|
|
433
|
-
node: Text;
|
|
434
|
-
pos: number;
|
|
435
|
-
text: string;
|
|
436
|
-
}): void;
|
|
437
|
-
update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
|
|
438
|
-
updateInner(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): void;
|
|
439
|
-
updateOuterDeco(outerDeco: readonly Decoration[]): void;
|
|
440
|
-
selectNode(): void;
|
|
441
|
-
deselectNode(): void;
|
|
442
|
-
get domAtom(): boolean;
|
|
443
|
-
}
|
|
444
|
-
declare class TextViewDesc extends NodeViewDesc {
|
|
445
|
-
constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, nodeDOM: DOMNode, view: EditorView);
|
|
446
|
-
parseRule(): {
|
|
447
|
-
skip: any;
|
|
448
|
-
};
|
|
449
|
-
update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
|
|
450
|
-
inParent(): boolean;
|
|
451
|
-
domFromPos(pos: number): {
|
|
452
|
-
node: globalThis.Node;
|
|
453
|
-
offset: number;
|
|
454
|
-
};
|
|
455
|
-
localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
456
|
-
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
457
|
-
slice(from: number, to: number, view: EditorView): TextViewDesc;
|
|
458
|
-
markDirty(from: number, to: number): void;
|
|
459
|
-
get domAtom(): boolean;
|
|
460
|
-
isText(text: string): boolean;
|
|
461
|
-
}
|
|
462
363
|
|
|
463
364
|
/**
|
|
464
365
|
An editor view manages the DOM structure that represents an
|
|
@@ -798,6 +699,12 @@ interface EditorProps<P = any> {
|
|
|
798
699
|
*/
|
|
799
700
|
handleScrollToSelection?: (this: P, view: EditorView) => boolean;
|
|
800
701
|
/**
|
|
702
|
+
Determines whether an in-editor drag event should copy or move
|
|
703
|
+
the selection. When not given, the event's `altKey` property is
|
|
704
|
+
used on macOS, `ctrlKey` on other platforms.
|
|
705
|
+
*/
|
|
706
|
+
dragCopies?: (event: DragEvent) => boolean;
|
|
707
|
+
/**
|
|
801
708
|
Can be used to override the way a selection is created when
|
|
802
709
|
reading a DOM selection between the given anchor and head.
|
|
803
710
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
|
|
2
|
-
import { Mark, Node,
|
|
2
|
+
import { Mark, Node, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
|
|
3
3
|
import { Mapping } from 'prosemirror-transform';
|
|
4
4
|
|
|
5
5
|
type DOMNode = InstanceType<typeof window.Node>;
|
|
@@ -234,7 +234,6 @@ declare class DecorationGroup implements DecorationSource {
|
|
|
234
234
|
|
|
235
235
|
declare global {
|
|
236
236
|
interface Node {
|
|
237
|
-
pmViewDesc?: ViewDesc;
|
|
238
237
|
}
|
|
239
238
|
}
|
|
240
239
|
/**
|
|
@@ -361,104 +360,6 @@ interface MarkView {
|
|
|
361
360
|
*/
|
|
362
361
|
destroy?: () => void;
|
|
363
362
|
}
|
|
364
|
-
declare class ViewDesc {
|
|
365
|
-
parent: ViewDesc | undefined;
|
|
366
|
-
children: ViewDesc[];
|
|
367
|
-
dom: DOMNode;
|
|
368
|
-
contentDOM: HTMLElement | null;
|
|
369
|
-
dirty: number;
|
|
370
|
-
node: Node | null;
|
|
371
|
-
constructor(parent: ViewDesc | undefined, children: ViewDesc[], dom: DOMNode, contentDOM: HTMLElement | null);
|
|
372
|
-
matchesWidget(widget: Decoration): boolean;
|
|
373
|
-
matchesMark(mark: Mark): boolean;
|
|
374
|
-
matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
|
|
375
|
-
matchesHack(nodeName: string): boolean;
|
|
376
|
-
parseRule(): Omit<TagParseRule, "tag"> | null;
|
|
377
|
-
stopEvent(event: Event): boolean;
|
|
378
|
-
get size(): number;
|
|
379
|
-
get border(): number;
|
|
380
|
-
destroy(): void;
|
|
381
|
-
posBeforeChild(child: ViewDesc): number;
|
|
382
|
-
get posBefore(): number;
|
|
383
|
-
get posAtStart(): number;
|
|
384
|
-
get posAfter(): number;
|
|
385
|
-
get posAtEnd(): number;
|
|
386
|
-
localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
387
|
-
nearestDesc(dom: DOMNode): ViewDesc | undefined;
|
|
388
|
-
nearestDesc(dom: DOMNode, onlyNodes: true): NodeViewDesc | undefined;
|
|
389
|
-
getDesc(dom: DOMNode): ViewDesc | undefined;
|
|
390
|
-
posFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
391
|
-
descAt(pos: number): ViewDesc | undefined;
|
|
392
|
-
domFromPos(pos: number, side: number): {
|
|
393
|
-
node: DOMNode;
|
|
394
|
-
offset: number;
|
|
395
|
-
atom?: number;
|
|
396
|
-
};
|
|
397
|
-
parseRange(from: number, to: number, base?: number): {
|
|
398
|
-
node: DOMNode;
|
|
399
|
-
from: number;
|
|
400
|
-
to: number;
|
|
401
|
-
fromOffset: number;
|
|
402
|
-
toOffset: number;
|
|
403
|
-
};
|
|
404
|
-
emptyChildAt(side: number): boolean;
|
|
405
|
-
domAfterPos(pos: number): DOMNode;
|
|
406
|
-
setSelection(anchor: number, head: number, view: EditorView, force?: boolean): void;
|
|
407
|
-
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
408
|
-
get contentLost(): boolean | null;
|
|
409
|
-
markDirty(from: number, to: number): void;
|
|
410
|
-
markParentsDirty(): void;
|
|
411
|
-
get domAtom(): boolean;
|
|
412
|
-
get ignoreForCoords(): boolean;
|
|
413
|
-
isText(text: string): boolean;
|
|
414
|
-
}
|
|
415
|
-
declare class NodeViewDesc extends ViewDesc {
|
|
416
|
-
node: Node;
|
|
417
|
-
outerDeco: readonly Decoration[];
|
|
418
|
-
innerDeco: DecorationSource;
|
|
419
|
-
readonly nodeDOM: DOMNode;
|
|
420
|
-
constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, contentDOM: HTMLElement | null, nodeDOM: DOMNode, view: EditorView, pos: number);
|
|
421
|
-
static create(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView, pos: number): NodeViewDesc | TextViewDesc;
|
|
422
|
-
parseRule(): Omit<TagParseRule, "tag"> | null;
|
|
423
|
-
matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
|
|
424
|
-
get size(): number;
|
|
425
|
-
get border(): 0 | 1;
|
|
426
|
-
updateChildren(view: EditorView, pos: number): void;
|
|
427
|
-
localCompositionInfo(view: EditorView, pos: number): {
|
|
428
|
-
node: Text;
|
|
429
|
-
pos: number;
|
|
430
|
-
text: string;
|
|
431
|
-
} | null;
|
|
432
|
-
protectLocalComposition(view: EditorView, { node, pos, text }: {
|
|
433
|
-
node: Text;
|
|
434
|
-
pos: number;
|
|
435
|
-
text: string;
|
|
436
|
-
}): void;
|
|
437
|
-
update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
|
|
438
|
-
updateInner(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): void;
|
|
439
|
-
updateOuterDeco(outerDeco: readonly Decoration[]): void;
|
|
440
|
-
selectNode(): void;
|
|
441
|
-
deselectNode(): void;
|
|
442
|
-
get domAtom(): boolean;
|
|
443
|
-
}
|
|
444
|
-
declare class TextViewDesc extends NodeViewDesc {
|
|
445
|
-
constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, nodeDOM: DOMNode, view: EditorView);
|
|
446
|
-
parseRule(): {
|
|
447
|
-
skip: any;
|
|
448
|
-
};
|
|
449
|
-
update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
|
|
450
|
-
inParent(): boolean;
|
|
451
|
-
domFromPos(pos: number): {
|
|
452
|
-
node: globalThis.Node;
|
|
453
|
-
offset: number;
|
|
454
|
-
};
|
|
455
|
-
localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
456
|
-
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
457
|
-
slice(from: number, to: number, view: EditorView): TextViewDesc;
|
|
458
|
-
markDirty(from: number, to: number): void;
|
|
459
|
-
get domAtom(): boolean;
|
|
460
|
-
isText(text: string): boolean;
|
|
461
|
-
}
|
|
462
363
|
|
|
463
364
|
/**
|
|
464
365
|
An editor view manages the DOM structure that represents an
|
|
@@ -798,6 +699,12 @@ interface EditorProps<P = any> {
|
|
|
798
699
|
*/
|
|
799
700
|
handleScrollToSelection?: (this: P, view: EditorView) => boolean;
|
|
800
701
|
/**
|
|
702
|
+
Determines whether an in-editor drag event should copy or move
|
|
703
|
+
the selection. When not given, the event's `altKey` property is
|
|
704
|
+
used on macOS, `ctrlKey` on other platforms.
|
|
705
|
+
*/
|
|
706
|
+
dragCopies?: (event: DragEvent) => boolean;
|
|
707
|
+
/**
|
|
801
708
|
Can be used to override the way a selection is created when
|
|
802
709
|
reading a DOM selection between the given anchor and head.
|
|
803
710
|
*/
|
package/dist/index.js
CHANGED
|
@@ -201,11 +201,13 @@ function clientRect(node) {
|
|
|
201
201
|
function scrollRectIntoView(view, rect, startDOM) {
|
|
202
202
|
let scrollThreshold = view.someProp("scrollThreshold") || 0, scrollMargin = view.someProp("scrollMargin") || 5;
|
|
203
203
|
let doc = view.dom.ownerDocument;
|
|
204
|
-
for (let parent = startDOM || view.dom;;
|
|
204
|
+
for (let parent = startDOM || view.dom;;) {
|
|
205
205
|
if (!parent)
|
|
206
206
|
break;
|
|
207
|
-
if (parent.nodeType != 1)
|
|
207
|
+
if (parent.nodeType != 1) {
|
|
208
|
+
parent = parentNode(parent);
|
|
208
209
|
continue;
|
|
210
|
+
}
|
|
209
211
|
let elt = parent;
|
|
210
212
|
let atTop = elt == doc.body;
|
|
211
213
|
let bounding = atTop ? windowRect(doc) : clientRect(elt);
|
|
@@ -234,8 +236,10 @@ function scrollRectIntoView(view, rect, startDOM) {
|
|
|
234
236
|
rect = { left: rect.left - dX, top: rect.top - dY, right: rect.right - dX, bottom: rect.bottom - dY };
|
|
235
237
|
}
|
|
236
238
|
}
|
|
237
|
-
|
|
239
|
+
let pos = atTop ? "fixed" : getComputedStyle(parent).position;
|
|
240
|
+
if (/^(fixed|sticky)$/.test(pos))
|
|
238
241
|
break;
|
|
242
|
+
parent = pos == "absolute" ? parent.offsetParent : parentNode(parent);
|
|
239
243
|
}
|
|
240
244
|
}
|
|
241
245
|
// Store the scroll position of the editor's parent nodes, along with
|
|
@@ -3659,6 +3663,7 @@ editHandlers.paste = (view, _event) => {
|
|
|
3659
3663
|
return;
|
|
3660
3664
|
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
3661
3665
|
let plain = view.input.shiftKey && view.input.lastKeyCode != 45;
|
|
3666
|
+
console.log("paste event", !!data, view.state.selection.from, view.state.selection.to);
|
|
3662
3667
|
if (data && doPaste(view, getText(data), data.getData("text/html"), plain, event))
|
|
3663
3668
|
event.preventDefault();
|
|
3664
3669
|
else
|
|
@@ -3672,6 +3677,10 @@ class Dragging {
|
|
|
3672
3677
|
}
|
|
3673
3678
|
}
|
|
3674
3679
|
const dragCopyModifier = mac ? "altKey" : "ctrlKey";
|
|
3680
|
+
function dragMoves(view, event) {
|
|
3681
|
+
let moves = view.someProp("dragCopies", test => !test(event));
|
|
3682
|
+
return moves != null ? moves : !event[dragCopyModifier];
|
|
3683
|
+
}
|
|
3675
3684
|
handlers.dragstart = (view, _event) => {
|
|
3676
3685
|
let event = _event;
|
|
3677
3686
|
let mouseDown = view.input.mouseDown;
|
|
@@ -3701,7 +3710,7 @@ handlers.dragstart = (view, _event) => {
|
|
|
3701
3710
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
3702
3711
|
if (!brokenClipboardAPI)
|
|
3703
3712
|
event.dataTransfer.setData("text/plain", text);
|
|
3704
|
-
view.dragging = new Dragging(slice,
|
|
3713
|
+
view.dragging = new Dragging(slice, dragMoves(view, event), node);
|
|
3705
3714
|
};
|
|
3706
3715
|
handlers.dragend = view => {
|
|
3707
3716
|
let dragging = view.dragging;
|
|
@@ -3728,7 +3737,7 @@ editHandlers.drop = (view, _event) => {
|
|
|
3728
3737
|
else {
|
|
3729
3738
|
slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
|
|
3730
3739
|
}
|
|
3731
|
-
let move = !!(dragging &&
|
|
3740
|
+
let move = !!(dragging && dragMoves(view, event));
|
|
3732
3741
|
if (view.someProp("handleDrop", f => f(view, event, slice || Slice.empty, move))) {
|
|
3733
3742
|
event.preventDefault();
|
|
3734
3743
|
return;
|
|
@@ -4705,6 +4714,7 @@ class DOMObserver {
|
|
|
4705
4714
|
view.input.lastFocus = 0;
|
|
4706
4715
|
selectionToDOM(view);
|
|
4707
4716
|
this.currentSelection.set(sel);
|
|
4717
|
+
view.scrollToSelection();
|
|
4708
4718
|
}
|
|
4709
4719
|
else if (from > -1 || newSel) {
|
|
4710
4720
|
if (from > -1) {
|
|
@@ -5012,9 +5022,10 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
5012
5022
|
// as being an iOS enter press), just dispatch an Enter key instead.
|
|
5013
5023
|
if (((ios && view.input.lastIOSEnter > Date.now() - 225 &&
|
|
5014
5024
|
(!inlineChange || addedNodes.some(n => n.nodeName == "DIV" || n.nodeName == "P"))) ||
|
|
5015
|
-
(!inlineChange && $from.pos < parse.doc.content.size &&
|
|
5025
|
+
(!inlineChange && $from.pos < parse.doc.content.size &&
|
|
5026
|
+
(!$from.sameParent($to) || !$from.parent.inlineContent) &&
|
|
5016
5027
|
(nextSel = Selection.findFrom(parse.doc.resolve($from.pos + 1), 1, true)) &&
|
|
5017
|
-
nextSel.head
|
|
5028
|
+
nextSel.head > $from.pos)) &&
|
|
5018
5029
|
view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter")))) {
|
|
5019
5030
|
view.input.lastIOSEnter = 0;
|
|
5020
5031
|
return;
|
package/package.json
CHANGED
package/src/domchange.ts
CHANGED
|
@@ -181,9 +181,10 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
|
|
|
181
181
|
// as being an iOS enter press), just dispatch an Enter key instead.
|
|
182
182
|
if (((browser.ios && view.input.lastIOSEnter > Date.now() - 225 &&
|
|
183
183
|
(!inlineChange || addedNodes.some(n => n.nodeName == "DIV" || n.nodeName == "P"))) ||
|
|
184
|
-
(!inlineChange && $from.pos < parse.doc.content.size &&
|
|
184
|
+
(!inlineChange && $from.pos < parse.doc.content.size &&
|
|
185
|
+
(!$from.sameParent($to) || !$from.parent.inlineContent) &&
|
|
185
186
|
(nextSel = Selection.findFrom(parse.doc.resolve($from.pos + 1), 1, true)) &&
|
|
186
|
-
nextSel.head
|
|
187
|
+
nextSel.head > $from.pos)) &&
|
|
187
188
|
view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter")))) {
|
|
188
189
|
view.input.lastIOSEnter = 0
|
|
189
190
|
return
|
package/src/domcoords.ts
CHANGED
|
@@ -32,9 +32,9 @@ function clientRect(node: HTMLElement): Rect {
|
|
|
32
32
|
export function scrollRectIntoView(view: EditorView, rect: Rect, startDOM: Node) {
|
|
33
33
|
let scrollThreshold = view.someProp("scrollThreshold") || 0, scrollMargin = view.someProp("scrollMargin") || 5
|
|
34
34
|
let doc = view.dom.ownerDocument
|
|
35
|
-
for (let parent: Node | null = startDOM || view.dom;;
|
|
35
|
+
for (let parent: Node | null = startDOM || view.dom;;) {
|
|
36
36
|
if (!parent) break
|
|
37
|
-
if (parent.nodeType != 1) continue
|
|
37
|
+
if (parent.nodeType != 1) { parent = parentNode(parent); continue }
|
|
38
38
|
let elt = parent as HTMLElement
|
|
39
39
|
let atTop = elt == doc.body
|
|
40
40
|
let bounding = atTop ? windowRect(doc) : clientRect(elt as HTMLElement)
|
|
@@ -60,7 +60,9 @@ export function scrollRectIntoView(view: EditorView, rect: Rect, startDOM: Node)
|
|
|
60
60
|
rect = {left: rect.left - dX, top: rect.top - dY, right: rect.right - dX, bottom: rect.bottom - dY}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
let pos: string = atTop ? "fixed" : getComputedStyle(parent as HTMLElement).position
|
|
64
|
+
if (/^(fixed|sticky)$/.test(pos)) break
|
|
65
|
+
parent = pos == "absolute" ? (parent as HTMLElement).offsetParent : parentNode(parent)
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
|
package/src/domobserver.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -51,7 +51,7 @@ export class EditorView {
|
|
|
51
51
|
private prevDirectPlugins: readonly Plugin[] = []
|
|
52
52
|
private pluginViews: PluginView[] = []
|
|
53
53
|
/// @internal
|
|
54
|
-
domObserver
|
|
54
|
+
declare domObserver: DOMObserver
|
|
55
55
|
/// Holds `true` when a hack node is needed in Firefox to prevent the
|
|
56
56
|
/// [space is eaten issue](https://github.com/ProseMirror/prosemirror/issues/651)
|
|
57
57
|
/// @internal
|
|
@@ -673,6 +673,11 @@ export interface EditorProps<P = any> {
|
|
|
673
673
|
/// handlers or the default behavior should be tried.
|
|
674
674
|
handleScrollToSelection?: (this: P, view: EditorView) => boolean
|
|
675
675
|
|
|
676
|
+
/// Determines whether an in-editor drag event should copy or move
|
|
677
|
+
/// the selection. When not given, the event's `altKey` property is
|
|
678
|
+
/// used on macOS, `ctrlKey` on other platforms.
|
|
679
|
+
dragCopies?: (event: DragEvent) => boolean
|
|
680
|
+
|
|
676
681
|
/// Can be used to override the way a selection is created when
|
|
677
682
|
/// reading a DOM selection between the given anchor and head.
|
|
678
683
|
createSelectionBetween?: (this: P, view: EditorView, anchor: ResolvedPos, head: ResolvedPos) => Selection | null
|
package/src/input.ts
CHANGED
|
@@ -648,6 +648,7 @@ editHandlers.paste = (view, _event) => {
|
|
|
648
648
|
if (view.composing && !browser.android) return
|
|
649
649
|
let data = brokenClipboardAPI ? null : event.clipboardData
|
|
650
650
|
let plain = view.input.shiftKey && view.input.lastKeyCode != 45
|
|
651
|
+
console.log("paste event", !!data, view.state.selection.from, view.state.selection.to)
|
|
651
652
|
if (data && doPaste(view, getText(data), data.getData("text/html"), plain, event))
|
|
652
653
|
event.preventDefault()
|
|
653
654
|
else
|
|
@@ -660,6 +661,11 @@ export class Dragging {
|
|
|
660
661
|
|
|
661
662
|
const dragCopyModifier: keyof DragEvent = browser.mac ? "altKey" : "ctrlKey"
|
|
662
663
|
|
|
664
|
+
function dragMoves(view: EditorView, event: DragEvent) {
|
|
665
|
+
let moves = view.someProp("dragCopies", test => !test(event))
|
|
666
|
+
return moves != null ? moves : !event[dragCopyModifier]
|
|
667
|
+
}
|
|
668
|
+
|
|
663
669
|
handlers.dragstart = (view, _event) => {
|
|
664
670
|
let event = _event as DragEvent
|
|
665
671
|
let mouseDown = view.input.mouseDown
|
|
@@ -687,7 +693,7 @@ handlers.dragstart = (view, _event) => {
|
|
|
687
693
|
// See https://github.com/ProseMirror/prosemirror/issues/1156
|
|
688
694
|
event.dataTransfer.effectAllowed = "copyMove"
|
|
689
695
|
if (!brokenClipboardAPI) event.dataTransfer.setData("text/plain", text)
|
|
690
|
-
view.dragging = new Dragging(slice,
|
|
696
|
+
view.dragging = new Dragging(slice, dragMoves(view, event), node)
|
|
691
697
|
}
|
|
692
698
|
|
|
693
699
|
handlers.dragend = view => {
|
|
@@ -716,7 +722,7 @@ editHandlers.drop = (view, _event) => {
|
|
|
716
722
|
slice = parseFromClipboard(view, getText(event.dataTransfer),
|
|
717
723
|
brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse)
|
|
718
724
|
}
|
|
719
|
-
let move = !!(dragging &&
|
|
725
|
+
let move = !!(dragging && dragMoves(view, event))
|
|
720
726
|
if (view.someProp("handleDrop", f => f(view, event, slice || Slice.empty, move))) {
|
|
721
727
|
event.preventDefault()
|
|
722
728
|
return
|
package/src/viewdesc.ts
CHANGED
|
@@ -7,7 +7,10 @@ import {Decoration, DecorationSource, WidgetConstructor, WidgetType, NodeType} f
|
|
|
7
7
|
import {EditorView} from "./index"
|
|
8
8
|
|
|
9
9
|
declare global {
|
|
10
|
-
interface Node {
|
|
10
|
+
interface Node {
|
|
11
|
+
/// @internal
|
|
12
|
+
pmViewDesc?: ViewDesc
|
|
13
|
+
}
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
/// A ViewMutationRecord represents a DOM
|
|
@@ -132,7 +135,7 @@ const NOT_DIRTY = 0, CHILD_DIRTY = 1, CONTENT_DIRTY = 2, NODE_DIRTY = 3
|
|
|
132
135
|
// basic structure and shared methods.
|
|
133
136
|
export class ViewDesc {
|
|
134
137
|
dirty = NOT_DIRTY
|
|
135
|
-
node
|
|
138
|
+
declare node: Node | null
|
|
136
139
|
|
|
137
140
|
constructor(
|
|
138
141
|
public parent: ViewDesc | undefined,
|