@codemirror/view 6.39.17 → 6.41.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 +26 -0
- package/README.md +1 -1
- package/dist/index.cjs +63 -21
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +63 -21
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
## 6.41.0 (2026-04-01)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where `EditorView.posAtCoords` could incorrectly return a position near a higher element on the line, in mixed-font-size lines.
|
|
6
|
+
|
|
7
|
+
Expand the workaround for the Webkit bug that causes nonexistent selections to stay visible to be active on non-Safari Webkit browsers.
|
|
8
|
+
|
|
9
|
+
### New features
|
|
10
|
+
|
|
11
|
+
The new `EditorView.cursorScrollMargin` facet can now be used to configure the extra space used when scrolling the cursor into view.
|
|
12
|
+
|
|
13
|
+
## 6.40.0 (2026-03-12)
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
Fix a bug that caused Shift-Enter/Backspace/Delete on iOS to lose the shift modifier when delivered to key event handlers.
|
|
18
|
+
|
|
19
|
+
Fix an issue where `EditorView.moveVertically` could move to the wrong place in wrapped lines with a large line height.
|
|
20
|
+
|
|
21
|
+
Make sure the selection head associativity is properly set for mouse selections made with shift held down.
|
|
22
|
+
|
|
23
|
+
### New features
|
|
24
|
+
|
|
25
|
+
`WidgetType.updateDOM` is now called with the previous widget value as third argument.
|
|
26
|
+
|
|
1
27
|
## 6.39.17 (2026-03-10)
|
|
2
28
|
|
|
3
29
|
### Bug fixes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @codemirror/view [](https://www.npmjs.org/package/@codemirror/view)
|
|
2
2
|
|
|
3
|
-
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/
|
|
3
|
+
[ [**WEBSITE**](https://codemirror.net/) | [**DOCS**](https://codemirror.net/docs/ref/#view) | [**ISSUES**](https://github.com/codemirror/dev/issues) | [**FORUM**](https://discuss.codemirror.net/) | [**CHANGELOG**](https://github.com/codemirror/view/blob/main/CHANGELOG.md) ]
|
|
4
4
|
|
|
5
5
|
This package implements the DOM view component for the
|
|
6
6
|
[CodeMirror](https://codemirror.net/) code editor.
|
package/dist/index.cjs
CHANGED
|
@@ -134,7 +134,7 @@ class WidgetType {
|
|
|
134
134
|
couldn't (in which case the widget will be redrawn). The default
|
|
135
135
|
implementation just returns false.
|
|
136
136
|
*/
|
|
137
|
-
updateDOM(dom, view) { return false; }
|
|
137
|
+
updateDOM(dom, view, from) { return false; }
|
|
138
138
|
/**
|
|
139
139
|
@internal
|
|
140
140
|
*/
|
|
@@ -548,12 +548,12 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
548
548
|
}
|
|
549
549
|
let moveX = 0, moveY = 0;
|
|
550
550
|
if (y == "nearest") {
|
|
551
|
-
if (rect.top < bounding.top) {
|
|
551
|
+
if (rect.top < bounding.top + yMargin) {
|
|
552
552
|
moveY = rect.top - (bounding.top + yMargin);
|
|
553
553
|
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
554
554
|
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
555
555
|
}
|
|
556
|
-
else if (rect.bottom > bounding.bottom) {
|
|
556
|
+
else if (rect.bottom > bounding.bottom - yMargin) {
|
|
557
557
|
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
558
558
|
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
559
559
|
moveY = rect.top - (bounding.top + yMargin);
|
|
@@ -567,12 +567,12 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
567
567
|
moveY = targetTop - bounding.top;
|
|
568
568
|
}
|
|
569
569
|
if (x == "nearest") {
|
|
570
|
-
if (rect.left < bounding.left) {
|
|
570
|
+
if (rect.left < bounding.left + xMargin) {
|
|
571
571
|
moveX = rect.left - (bounding.left + xMargin);
|
|
572
572
|
if (side > 0 && rect.right > bounding.right + moveX)
|
|
573
573
|
moveX = rect.right - bounding.right + xMargin;
|
|
574
574
|
}
|
|
575
|
-
else if (rect.right > bounding.right) {
|
|
575
|
+
else if (rect.right > bounding.right - xMargin) {
|
|
576
576
|
moveX = rect.right - bounding.right + xMargin;
|
|
577
577
|
if (side < 0 && rect.left < bounding.left + moveX)
|
|
578
578
|
moveX = rect.left - (bounding.left + xMargin);
|
|
@@ -1313,7 +1313,7 @@ const nativeSelectionHidden = state.Facet.define({
|
|
|
1313
1313
|
});
|
|
1314
1314
|
const scrollHandler = state.Facet.define();
|
|
1315
1315
|
class ScrollTarget {
|
|
1316
|
-
constructor(range, y
|
|
1316
|
+
constructor(range, y, x, yMargin, xMargin,
|
|
1317
1317
|
// This data structure is abused to also store precise scroll
|
|
1318
1318
|
// snapshots, instead of a `scrollIntoView` request. When this
|
|
1319
1319
|
// flag is `true`, `range` points at a position in the reference
|
|
@@ -2539,7 +2539,7 @@ class TileCache {
|
|
|
2539
2539
|
let tile = widgets[i];
|
|
2540
2540
|
if (!this.reused.has(tile) &&
|
|
2541
2541
|
(pass == 0 ? tile.widget.compare(widget)
|
|
2542
|
-
: tile.widget.constructor == widget.constructor && widget.updateDOM(tile.dom, this.view))) {
|
|
2542
|
+
: tile.widget.constructor == widget.constructor && widget.updateDOM(tile.dom, this.view, tile.widget))) {
|
|
2543
2543
|
widgets.splice(i, 1);
|
|
2544
2544
|
if (i < this.index[0])
|
|
2545
2545
|
this.index[0]--;
|
|
@@ -3395,6 +3395,7 @@ class DocView {
|
|
|
3395
3395
|
this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
|
|
3396
3396
|
}
|
|
3397
3397
|
scrollIntoView(target) {
|
|
3398
|
+
var _a;
|
|
3398
3399
|
if (target.isSnapshot) {
|
|
3399
3400
|
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3400
3401
|
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
@@ -3411,7 +3412,7 @@ class DocView {
|
|
|
3411
3412
|
}
|
|
3412
3413
|
}
|
|
3413
3414
|
let { range } = target;
|
|
3414
|
-
let rect = this.coordsAt(range.head, range.
|
|
3415
|
+
let rect = this.coordsAt(range.head, (_a = range.assoc) !== null && _a !== void 0 ? _a : (range.empty ? 0 : range.head > range.anchor ? -1 : 1)), other;
|
|
3415
3416
|
if (!rect)
|
|
3416
3417
|
return;
|
|
3417
3418
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
@@ -3678,7 +3679,8 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3678
3679
|
return state.EditorSelection.cursor(startPos, start.assoc);
|
|
3679
3680
|
let goal = start.goalColumn, startY;
|
|
3680
3681
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3681
|
-
let startCoords = view.coordsAtPos(startPos, (start.empty ? start.
|
|
3682
|
+
let startCoords = view.coordsAtPos(startPos, start.assoc || ((start.empty ? forward : start.head == start.from) ? 1 : -1));
|
|
3683
|
+
let docTop = view.documentTop;
|
|
3682
3684
|
if (startCoords) {
|
|
3683
3685
|
if (goal == null)
|
|
3684
3686
|
goal = startCoords.left - rect.left;
|
|
@@ -3691,9 +3693,16 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3691
3693
|
startY = (dir < 0 ? line.top : line.bottom) + docTop;
|
|
3692
3694
|
}
|
|
3693
3695
|
let resolvedGoal = rect.left + goal;
|
|
3694
|
-
let dist = distance !== null && distance !== void 0 ? distance :
|
|
3695
|
-
let
|
|
3696
|
-
|
|
3696
|
+
let halfText = view.viewState.heightOracle.textHeight >> 1, dist = distance !== null && distance !== void 0 ? distance : halfText;
|
|
3697
|
+
for (let scan = 0;; scan += halfText) {
|
|
3698
|
+
let y = startY + (dist + scan) * dir;
|
|
3699
|
+
let pos = posAtCoords(view, { x: resolvedGoal, y }, false, dir);
|
|
3700
|
+
if (forward ? y > rect.bottom : y < rect.top)
|
|
3701
|
+
return state.EditorSelection.cursor(pos.pos, pos.assoc);
|
|
3702
|
+
let posCoords = view.coordsAtPos(pos.pos, pos.assoc), mid = posCoords ? (posCoords.top + posCoords.bottom) / 2 : 0;
|
|
3703
|
+
if (!posCoords || (forward ? mid > startY : mid < startY))
|
|
3704
|
+
return state.EditorSelection.cursor(pos.pos, pos.assoc, undefined, goal);
|
|
3705
|
+
}
|
|
3697
3706
|
}
|
|
3698
3707
|
function skipAtomicRanges(atoms, pos, bias) {
|
|
3699
3708
|
for (;;) {
|
|
@@ -3901,6 +3910,18 @@ class InlineCoordsScan {
|
|
|
3901
3910
|
this.y = (side.top + side.bottom) / 2;
|
|
3902
3911
|
return this.scan(positions, getRects);
|
|
3903
3912
|
}
|
|
3913
|
+
// Handle the case where closest matched a higher element on the
|
|
3914
|
+
// same line as an element below/above the coords
|
|
3915
|
+
if (closestDx) {
|
|
3916
|
+
if (above && above.bottom > closestRect.top) {
|
|
3917
|
+
this.y = above.bottom - 1;
|
|
3918
|
+
return this.scan(positions, getRects);
|
|
3919
|
+
}
|
|
3920
|
+
if (below && below.top < closestRect.bottom) {
|
|
3921
|
+
this.y = below.top + 1;
|
|
3922
|
+
return this.scan(positions, getRects);
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3904
3925
|
let ltr = (bidi ? this.dirAt(positions[closestI], 1) : this.baseDir) == exports.Direction.LTR;
|
|
3905
3926
|
return {
|
|
3906
3927
|
i: closestI,
|
|
@@ -4552,9 +4573,9 @@ class InputState {
|
|
|
4552
4573
|
// applyDOMChange, notify key handlers of it and reset to
|
|
4553
4574
|
// the state they produce.
|
|
4554
4575
|
let pending;
|
|
4555
|
-
if (browser.ios && !event.synthetic && !event.altKey && !event.metaKey &&
|
|
4576
|
+
if (browser.ios && !event.synthetic && !event.altKey && !event.metaKey && !event.shiftKey &&
|
|
4556
4577
|
((pending = PendingKeys.find(key => key.keyCode == event.keyCode)) && !event.ctrlKey ||
|
|
4557
|
-
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey
|
|
4578
|
+
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey)) {
|
|
4558
4579
|
this.pendingIOSKey = pending || event;
|
|
4559
4580
|
setTimeout(() => this.flushIOSKey(), 250);
|
|
4560
4581
|
return true;
|
|
@@ -4958,10 +4979,10 @@ function basicMouseSelection(view, event) {
|
|
|
4958
4979
|
if (start.pos != cur.pos && !extend) {
|
|
4959
4980
|
let startRange = rangeForClick(view, start.pos, start.assoc, type);
|
|
4960
4981
|
let from = Math.min(startRange.from, range.from), to = Math.max(startRange.to, range.to);
|
|
4961
|
-
range = from < range.from ? state.EditorSelection.range(from, to) : state.EditorSelection.range(to, from);
|
|
4982
|
+
range = from < range.from ? state.EditorSelection.range(from, to, range.assoc) : state.EditorSelection.range(to, from, range.assoc);
|
|
4962
4983
|
}
|
|
4963
4984
|
if (extend)
|
|
4964
|
-
return startSel.replaceRange(startSel.main.extend(range.from, range.to));
|
|
4985
|
+
return startSel.replaceRange(startSel.main.extend(range.from, range.to, range.assoc));
|
|
4965
4986
|
else if (multiple && type == 1 && startSel.ranges.length > 1 && (removed = removeRangeAround(startSel, cur.pos)))
|
|
4966
4987
|
return removed;
|
|
4967
4988
|
else if (multiple)
|
|
@@ -7918,7 +7939,8 @@ class EditorView {
|
|
|
7918
7939
|
scrollTarget = scrollTarget.map(tr.changes);
|
|
7919
7940
|
if (tr.scrollIntoView) {
|
|
7920
7941
|
let { main } = tr.state.selection;
|
|
7921
|
-
|
|
7942
|
+
let { x, y } = this.state.facet(EditorView.cursorScrollMargin);
|
|
7943
|
+
scrollTarget = new ScrollTarget(main.empty ? main : state.EditorSelection.cursor(main.head, main.head > main.anchor ? -1 : 1), "nearest", "nearest", y, x);
|
|
7922
7944
|
}
|
|
7923
7945
|
for (let e of tr.effects)
|
|
7924
7946
|
if (e.is(scrollIntoView))
|
|
@@ -8575,7 +8597,8 @@ class EditorView {
|
|
|
8575
8597
|
cause it to scroll the given position or range into view.
|
|
8576
8598
|
*/
|
|
8577
8599
|
static scrollIntoView(pos, options = {}) {
|
|
8578
|
-
|
|
8600
|
+
var _a, _b, _c, _d;
|
|
8601
|
+
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? state.EditorSelection.cursor(pos) : pos, (_a = options.y) !== null && _a !== void 0 ? _a : "nearest", (_b = options.x) !== null && _b !== void 0 ? _b : "nearest", (_c = options.yMargin) !== null && _c !== void 0 ? _c : 5, (_d = options.xMargin) !== null && _d !== void 0 ? _d : 5));
|
|
8579
8602
|
}
|
|
8580
8603
|
/**
|
|
8581
8604
|
Return an effect that resets the editor to its current (at the
|
|
@@ -8834,11 +8857,30 @@ supported.)
|
|
|
8834
8857
|
*/
|
|
8835
8858
|
EditorView.bidiIsolatedRanges = bidiIsolatedRanges;
|
|
8836
8859
|
/**
|
|
8860
|
+
Can be used to specify the distance that scrolling cursor into
|
|
8861
|
+
view keeps it away from the sides of the editor, either as a
|
|
8862
|
+
single pixel number or two different values for the different
|
|
8863
|
+
axes. Defaults to 5 pixels on both axes.
|
|
8864
|
+
*/
|
|
8865
|
+
EditorView.cursorScrollMargin = state.Facet.define({
|
|
8866
|
+
combine: inputs => {
|
|
8867
|
+
let x = 5, y = 5;
|
|
8868
|
+
for (let i of inputs) {
|
|
8869
|
+
if (typeof i == "number")
|
|
8870
|
+
x = y = i;
|
|
8871
|
+
else
|
|
8872
|
+
({ x, y } = i);
|
|
8873
|
+
}
|
|
8874
|
+
return { x, y };
|
|
8875
|
+
}
|
|
8876
|
+
});
|
|
8877
|
+
/**
|
|
8837
8878
|
Facet that allows extensions to provide additional scroll
|
|
8838
8879
|
margins (space around the sides of the scrolling element that
|
|
8839
8880
|
should be considered invisible). This can be useful when the
|
|
8840
8881
|
plugin introduces elements that cover part of that element (for
|
|
8841
|
-
example a horizontally fixed gutter).
|
|
8882
|
+
example a horizontally fixed gutter). Not to be confused with
|
|
8883
|
+
[`cursorScrollMargin`](https://codemirror.net/6/docs/ref/#view.EditorView^cursorScrollMargin).
|
|
8842
8884
|
*/
|
|
8843
8885
|
EditorView.scrollMargins = scrollMargins;
|
|
8844
8886
|
/**
|
|
@@ -9374,7 +9416,7 @@ class LayerView {
|
|
|
9374
9416
|
old = next;
|
|
9375
9417
|
}
|
|
9376
9418
|
this.drawn = markers;
|
|
9377
|
-
if (browser.
|
|
9419
|
+
if (browser.webkit) // Issue #1600, 1627, 1686
|
|
9378
9420
|
this.dom.style.display = this.dom.firstChild ? "" : "none";
|
|
9379
9421
|
}
|
|
9380
9422
|
}
|
|
@@ -9454,7 +9496,7 @@ const cursorLayer = layer({
|
|
|
9454
9496
|
let prim = r == state$1.selection.main;
|
|
9455
9497
|
if (r.empty || conf.drawRangeCursor && !(prim && browser.ios && conf.iosSelectionHandles)) {
|
|
9456
9498
|
let className = prim ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary";
|
|
9457
|
-
let cursor = r.empty ? r : state.EditorSelection.cursor(r.head, r.
|
|
9499
|
+
let cursor = r.empty ? r : state.EditorSelection.cursor(r.head, r.assoc);
|
|
9458
9500
|
for (let piece of RectangleMarker.forRange(view, className, cursor))
|
|
9459
9501
|
cursors.push(piece);
|
|
9460
9502
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -224,7 +224,7 @@ declare abstract class WidgetType {
|
|
|
224
224
|
couldn't (in which case the widget will be redrawn). The default
|
|
225
225
|
implementation just returns false.
|
|
226
226
|
*/
|
|
227
|
-
updateDOM(dom: HTMLElement, view: EditorView): boolean;
|
|
227
|
+
updateDOM(dom: HTMLElement, view: EditorView, from: this): boolean;
|
|
228
228
|
/**
|
|
229
229
|
The estimated height this widget will have, to be used when
|
|
230
230
|
estimating the height of content that hasn't been drawn. May
|
|
@@ -404,7 +404,7 @@ declare class ScrollTarget {
|
|
|
404
404
|
readonly yMargin: number;
|
|
405
405
|
readonly xMargin: number;
|
|
406
406
|
readonly isSnapshot: boolean;
|
|
407
|
-
constructor(range: SelectionRange, y
|
|
407
|
+
constructor(range: SelectionRange, y: ScrollStrategy, x: ScrollStrategy, yMargin: number, xMargin: number, isSnapshot?: boolean);
|
|
408
408
|
map(changes: ChangeDesc): ScrollTarget;
|
|
409
409
|
clip(state: EditorState): ScrollTarget;
|
|
410
410
|
}
|
|
@@ -1356,11 +1356,25 @@ declare class EditorView {
|
|
|
1356
1356
|
*/
|
|
1357
1357
|
static bidiIsolatedRanges: Facet<DecorationSet | ((view: EditorView) => DecorationSet), readonly (DecorationSet | ((view: EditorView) => DecorationSet))[]>;
|
|
1358
1358
|
/**
|
|
1359
|
+
Can be used to specify the distance that scrolling cursor into
|
|
1360
|
+
view keeps it away from the sides of the editor, either as a
|
|
1361
|
+
single pixel number or two different values for the different
|
|
1362
|
+
axes. Defaults to 5 pixels on both axes.
|
|
1363
|
+
*/
|
|
1364
|
+
static cursorScrollMargin: Facet<number | {
|
|
1365
|
+
x: number;
|
|
1366
|
+
y: number;
|
|
1367
|
+
}, {
|
|
1368
|
+
x: number;
|
|
1369
|
+
y: number;
|
|
1370
|
+
}>;
|
|
1371
|
+
/**
|
|
1359
1372
|
Facet that allows extensions to provide additional scroll
|
|
1360
1373
|
margins (space around the sides of the scrolling element that
|
|
1361
1374
|
should be considered invisible). This can be useful when the
|
|
1362
1375
|
plugin introduces elements that cover part of that element (for
|
|
1363
|
-
example a horizontally fixed gutter).
|
|
1376
|
+
example a horizontally fixed gutter). Not to be confused with
|
|
1377
|
+
[`cursorScrollMargin`](https://codemirror.net/6/docs/ref/#view.EditorView^cursorScrollMargin).
|
|
1364
1378
|
*/
|
|
1365
1379
|
static scrollMargins: Facet<(view: EditorView) => Partial<Rect> | null, readonly ((view: EditorView) => Partial<Rect> | null)[]>;
|
|
1366
1380
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -224,7 +224,7 @@ declare abstract class WidgetType {
|
|
|
224
224
|
couldn't (in which case the widget will be redrawn). The default
|
|
225
225
|
implementation just returns false.
|
|
226
226
|
*/
|
|
227
|
-
updateDOM(dom: HTMLElement, view: EditorView): boolean;
|
|
227
|
+
updateDOM(dom: HTMLElement, view: EditorView, from: this): boolean;
|
|
228
228
|
/**
|
|
229
229
|
The estimated height this widget will have, to be used when
|
|
230
230
|
estimating the height of content that hasn't been drawn. May
|
|
@@ -404,7 +404,7 @@ declare class ScrollTarget {
|
|
|
404
404
|
readonly yMargin: number;
|
|
405
405
|
readonly xMargin: number;
|
|
406
406
|
readonly isSnapshot: boolean;
|
|
407
|
-
constructor(range: SelectionRange, y
|
|
407
|
+
constructor(range: SelectionRange, y: ScrollStrategy, x: ScrollStrategy, yMargin: number, xMargin: number, isSnapshot?: boolean);
|
|
408
408
|
map(changes: ChangeDesc): ScrollTarget;
|
|
409
409
|
clip(state: EditorState): ScrollTarget;
|
|
410
410
|
}
|
|
@@ -1356,11 +1356,25 @@ declare class EditorView {
|
|
|
1356
1356
|
*/
|
|
1357
1357
|
static bidiIsolatedRanges: Facet<DecorationSet | ((view: EditorView) => DecorationSet), readonly (DecorationSet | ((view: EditorView) => DecorationSet))[]>;
|
|
1358
1358
|
/**
|
|
1359
|
+
Can be used to specify the distance that scrolling cursor into
|
|
1360
|
+
view keeps it away from the sides of the editor, either as a
|
|
1361
|
+
single pixel number or two different values for the different
|
|
1362
|
+
axes. Defaults to 5 pixels on both axes.
|
|
1363
|
+
*/
|
|
1364
|
+
static cursorScrollMargin: Facet<number | {
|
|
1365
|
+
x: number;
|
|
1366
|
+
y: number;
|
|
1367
|
+
}, {
|
|
1368
|
+
x: number;
|
|
1369
|
+
y: number;
|
|
1370
|
+
}>;
|
|
1371
|
+
/**
|
|
1359
1372
|
Facet that allows extensions to provide additional scroll
|
|
1360
1373
|
margins (space around the sides of the scrolling element that
|
|
1361
1374
|
should be considered invisible). This can be useful when the
|
|
1362
1375
|
plugin introduces elements that cover part of that element (for
|
|
1363
|
-
example a horizontally fixed gutter).
|
|
1376
|
+
example a horizontally fixed gutter). Not to be confused with
|
|
1377
|
+
[`cursorScrollMargin`](https://codemirror.net/6/docs/ref/#view.EditorView^cursorScrollMargin).
|
|
1364
1378
|
*/
|
|
1365
1379
|
static scrollMargins: Facet<(view: EditorView) => Partial<Rect> | null, readonly ((view: EditorView) => Partial<Rect> | null)[]>;
|
|
1366
1380
|
/**
|
package/dist/index.js
CHANGED
|
@@ -132,7 +132,7 @@ class WidgetType {
|
|
|
132
132
|
couldn't (in which case the widget will be redrawn). The default
|
|
133
133
|
implementation just returns false.
|
|
134
134
|
*/
|
|
135
|
-
updateDOM(dom, view) { return false; }
|
|
135
|
+
updateDOM(dom, view, from) { return false; }
|
|
136
136
|
/**
|
|
137
137
|
@internal
|
|
138
138
|
*/
|
|
@@ -545,12 +545,12 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
545
545
|
}
|
|
546
546
|
let moveX = 0, moveY = 0;
|
|
547
547
|
if (y == "nearest") {
|
|
548
|
-
if (rect.top < bounding.top) {
|
|
548
|
+
if (rect.top < bounding.top + yMargin) {
|
|
549
549
|
moveY = rect.top - (bounding.top + yMargin);
|
|
550
550
|
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
551
551
|
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
552
552
|
}
|
|
553
|
-
else if (rect.bottom > bounding.bottom) {
|
|
553
|
+
else if (rect.bottom > bounding.bottom - yMargin) {
|
|
554
554
|
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
555
555
|
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
556
556
|
moveY = rect.top - (bounding.top + yMargin);
|
|
@@ -564,12 +564,12 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
564
564
|
moveY = targetTop - bounding.top;
|
|
565
565
|
}
|
|
566
566
|
if (x == "nearest") {
|
|
567
|
-
if (rect.left < bounding.left) {
|
|
567
|
+
if (rect.left < bounding.left + xMargin) {
|
|
568
568
|
moveX = rect.left - (bounding.left + xMargin);
|
|
569
569
|
if (side > 0 && rect.right > bounding.right + moveX)
|
|
570
570
|
moveX = rect.right - bounding.right + xMargin;
|
|
571
571
|
}
|
|
572
|
-
else if (rect.right > bounding.right) {
|
|
572
|
+
else if (rect.right > bounding.right - xMargin) {
|
|
573
573
|
moveX = rect.right - bounding.right + xMargin;
|
|
574
574
|
if (side < 0 && rect.left < bounding.left + moveX)
|
|
575
575
|
moveX = rect.left - (bounding.left + xMargin);
|
|
@@ -1309,7 +1309,7 @@ const nativeSelectionHidden = /*@__PURE__*/Facet.define({
|
|
|
1309
1309
|
});
|
|
1310
1310
|
const scrollHandler = /*@__PURE__*/Facet.define();
|
|
1311
1311
|
class ScrollTarget {
|
|
1312
|
-
constructor(range, y
|
|
1312
|
+
constructor(range, y, x, yMargin, xMargin,
|
|
1313
1313
|
// This data structure is abused to also store precise scroll
|
|
1314
1314
|
// snapshots, instead of a `scrollIntoView` request. When this
|
|
1315
1315
|
// flag is `true`, `range` points at a position in the reference
|
|
@@ -2535,7 +2535,7 @@ class TileCache {
|
|
|
2535
2535
|
let tile = widgets[i];
|
|
2536
2536
|
if (!this.reused.has(tile) &&
|
|
2537
2537
|
(pass == 0 ? tile.widget.compare(widget)
|
|
2538
|
-
: tile.widget.constructor == widget.constructor && widget.updateDOM(tile.dom, this.view))) {
|
|
2538
|
+
: tile.widget.constructor == widget.constructor && widget.updateDOM(tile.dom, this.view, tile.widget))) {
|
|
2539
2539
|
widgets.splice(i, 1);
|
|
2540
2540
|
if (i < this.index[0])
|
|
2541
2541
|
this.index[0]--;
|
|
@@ -3391,6 +3391,7 @@ class DocView {
|
|
|
3391
3391
|
this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
|
|
3392
3392
|
}
|
|
3393
3393
|
scrollIntoView(target) {
|
|
3394
|
+
var _a;
|
|
3394
3395
|
if (target.isSnapshot) {
|
|
3395
3396
|
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3396
3397
|
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
@@ -3407,7 +3408,7 @@ class DocView {
|
|
|
3407
3408
|
}
|
|
3408
3409
|
}
|
|
3409
3410
|
let { range } = target;
|
|
3410
|
-
let rect = this.coordsAt(range.head, range.
|
|
3411
|
+
let rect = this.coordsAt(range.head, (_a = range.assoc) !== null && _a !== void 0 ? _a : (range.empty ? 0 : range.head > range.anchor ? -1 : 1)), other;
|
|
3411
3412
|
if (!rect)
|
|
3412
3413
|
return;
|
|
3413
3414
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
@@ -3674,7 +3675,8 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3674
3675
|
return EditorSelection.cursor(startPos, start.assoc);
|
|
3675
3676
|
let goal = start.goalColumn, startY;
|
|
3676
3677
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3677
|
-
let startCoords = view.coordsAtPos(startPos, (start.empty ? start.
|
|
3678
|
+
let startCoords = view.coordsAtPos(startPos, start.assoc || ((start.empty ? forward : start.head == start.from) ? 1 : -1));
|
|
3679
|
+
let docTop = view.documentTop;
|
|
3678
3680
|
if (startCoords) {
|
|
3679
3681
|
if (goal == null)
|
|
3680
3682
|
goal = startCoords.left - rect.left;
|
|
@@ -3687,9 +3689,16 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3687
3689
|
startY = (dir < 0 ? line.top : line.bottom) + docTop;
|
|
3688
3690
|
}
|
|
3689
3691
|
let resolvedGoal = rect.left + goal;
|
|
3690
|
-
let dist = distance !== null && distance !== void 0 ? distance :
|
|
3691
|
-
let
|
|
3692
|
-
|
|
3692
|
+
let halfText = view.viewState.heightOracle.textHeight >> 1, dist = distance !== null && distance !== void 0 ? distance : halfText;
|
|
3693
|
+
for (let scan = 0;; scan += halfText) {
|
|
3694
|
+
let y = startY + (dist + scan) * dir;
|
|
3695
|
+
let pos = posAtCoords(view, { x: resolvedGoal, y }, false, dir);
|
|
3696
|
+
if (forward ? y > rect.bottom : y < rect.top)
|
|
3697
|
+
return EditorSelection.cursor(pos.pos, pos.assoc);
|
|
3698
|
+
let posCoords = view.coordsAtPos(pos.pos, pos.assoc), mid = posCoords ? (posCoords.top + posCoords.bottom) / 2 : 0;
|
|
3699
|
+
if (!posCoords || (forward ? mid > startY : mid < startY))
|
|
3700
|
+
return EditorSelection.cursor(pos.pos, pos.assoc, undefined, goal);
|
|
3701
|
+
}
|
|
3693
3702
|
}
|
|
3694
3703
|
function skipAtomicRanges(atoms, pos, bias) {
|
|
3695
3704
|
for (;;) {
|
|
@@ -3897,6 +3906,18 @@ class InlineCoordsScan {
|
|
|
3897
3906
|
this.y = (side.top + side.bottom) / 2;
|
|
3898
3907
|
return this.scan(positions, getRects);
|
|
3899
3908
|
}
|
|
3909
|
+
// Handle the case where closest matched a higher element on the
|
|
3910
|
+
// same line as an element below/above the coords
|
|
3911
|
+
if (closestDx) {
|
|
3912
|
+
if (above && above.bottom > closestRect.top) {
|
|
3913
|
+
this.y = above.bottom - 1;
|
|
3914
|
+
return this.scan(positions, getRects);
|
|
3915
|
+
}
|
|
3916
|
+
if (below && below.top < closestRect.bottom) {
|
|
3917
|
+
this.y = below.top + 1;
|
|
3918
|
+
return this.scan(positions, getRects);
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3900
3921
|
let ltr = (bidi ? this.dirAt(positions[closestI], 1) : this.baseDir) == Direction.LTR;
|
|
3901
3922
|
return {
|
|
3902
3923
|
i: closestI,
|
|
@@ -4548,9 +4569,9 @@ class InputState {
|
|
|
4548
4569
|
// applyDOMChange, notify key handlers of it and reset to
|
|
4549
4570
|
// the state they produce.
|
|
4550
4571
|
let pending;
|
|
4551
|
-
if (browser.ios && !event.synthetic && !event.altKey && !event.metaKey &&
|
|
4572
|
+
if (browser.ios && !event.synthetic && !event.altKey && !event.metaKey && !event.shiftKey &&
|
|
4552
4573
|
((pending = PendingKeys.find(key => key.keyCode == event.keyCode)) && !event.ctrlKey ||
|
|
4553
|
-
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey
|
|
4574
|
+
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey)) {
|
|
4554
4575
|
this.pendingIOSKey = pending || event;
|
|
4555
4576
|
setTimeout(() => this.flushIOSKey(), 250);
|
|
4556
4577
|
return true;
|
|
@@ -4954,10 +4975,10 @@ function basicMouseSelection(view, event) {
|
|
|
4954
4975
|
if (start.pos != cur.pos && !extend) {
|
|
4955
4976
|
let startRange = rangeForClick(view, start.pos, start.assoc, type);
|
|
4956
4977
|
let from = Math.min(startRange.from, range.from), to = Math.max(startRange.to, range.to);
|
|
4957
|
-
range = from < range.from ? EditorSelection.range(from, to) : EditorSelection.range(to, from);
|
|
4978
|
+
range = from < range.from ? EditorSelection.range(from, to, range.assoc) : EditorSelection.range(to, from, range.assoc);
|
|
4958
4979
|
}
|
|
4959
4980
|
if (extend)
|
|
4960
|
-
return startSel.replaceRange(startSel.main.extend(range.from, range.to));
|
|
4981
|
+
return startSel.replaceRange(startSel.main.extend(range.from, range.to, range.assoc));
|
|
4961
4982
|
else if (multiple && type == 1 && startSel.ranges.length > 1 && (removed = removeRangeAround(startSel, cur.pos)))
|
|
4962
4983
|
return removed;
|
|
4963
4984
|
else if (multiple)
|
|
@@ -7913,7 +7934,8 @@ class EditorView {
|
|
|
7913
7934
|
scrollTarget = scrollTarget.map(tr.changes);
|
|
7914
7935
|
if (tr.scrollIntoView) {
|
|
7915
7936
|
let { main } = tr.state.selection;
|
|
7916
|
-
|
|
7937
|
+
let { x, y } = this.state.facet(EditorView.cursorScrollMargin);
|
|
7938
|
+
scrollTarget = new ScrollTarget(main.empty ? main : EditorSelection.cursor(main.head, main.head > main.anchor ? -1 : 1), "nearest", "nearest", y, x);
|
|
7917
7939
|
}
|
|
7918
7940
|
for (let e of tr.effects)
|
|
7919
7941
|
if (e.is(scrollIntoView))
|
|
@@ -8570,7 +8592,8 @@ class EditorView {
|
|
|
8570
8592
|
cause it to scroll the given position or range into view.
|
|
8571
8593
|
*/
|
|
8572
8594
|
static scrollIntoView(pos, options = {}) {
|
|
8573
|
-
|
|
8595
|
+
var _a, _b, _c, _d;
|
|
8596
|
+
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? EditorSelection.cursor(pos) : pos, (_a = options.y) !== null && _a !== void 0 ? _a : "nearest", (_b = options.x) !== null && _b !== void 0 ? _b : "nearest", (_c = options.yMargin) !== null && _c !== void 0 ? _c : 5, (_d = options.xMargin) !== null && _d !== void 0 ? _d : 5));
|
|
8574
8597
|
}
|
|
8575
8598
|
/**
|
|
8576
8599
|
Return an effect that resets the editor to its current (at the
|
|
@@ -8829,11 +8852,30 @@ supported.)
|
|
|
8829
8852
|
*/
|
|
8830
8853
|
EditorView.bidiIsolatedRanges = bidiIsolatedRanges;
|
|
8831
8854
|
/**
|
|
8855
|
+
Can be used to specify the distance that scrolling cursor into
|
|
8856
|
+
view keeps it away from the sides of the editor, either as a
|
|
8857
|
+
single pixel number or two different values for the different
|
|
8858
|
+
axes. Defaults to 5 pixels on both axes.
|
|
8859
|
+
*/
|
|
8860
|
+
EditorView.cursorScrollMargin = /*@__PURE__*/Facet.define({
|
|
8861
|
+
combine: inputs => {
|
|
8862
|
+
let x = 5, y = 5;
|
|
8863
|
+
for (let i of inputs) {
|
|
8864
|
+
if (typeof i == "number")
|
|
8865
|
+
x = y = i;
|
|
8866
|
+
else
|
|
8867
|
+
({ x, y } = i);
|
|
8868
|
+
}
|
|
8869
|
+
return { x, y };
|
|
8870
|
+
}
|
|
8871
|
+
});
|
|
8872
|
+
/**
|
|
8832
8873
|
Facet that allows extensions to provide additional scroll
|
|
8833
8874
|
margins (space around the sides of the scrolling element that
|
|
8834
8875
|
should be considered invisible). This can be useful when the
|
|
8835
8876
|
plugin introduces elements that cover part of that element (for
|
|
8836
|
-
example a horizontally fixed gutter).
|
|
8877
|
+
example a horizontally fixed gutter). Not to be confused with
|
|
8878
|
+
[`cursorScrollMargin`](https://codemirror.net/6/docs/ref/#view.EditorView^cursorScrollMargin).
|
|
8837
8879
|
*/
|
|
8838
8880
|
EditorView.scrollMargins = scrollMargins;
|
|
8839
8881
|
/**
|
|
@@ -9369,7 +9411,7 @@ class LayerView {
|
|
|
9369
9411
|
old = next;
|
|
9370
9412
|
}
|
|
9371
9413
|
this.drawn = markers;
|
|
9372
|
-
if (browser.
|
|
9414
|
+
if (browser.webkit) // Issue #1600, 1627, 1686
|
|
9373
9415
|
this.dom.style.display = this.dom.firstChild ? "" : "none";
|
|
9374
9416
|
}
|
|
9375
9417
|
}
|
|
@@ -9449,7 +9491,7 @@ const cursorLayer = /*@__PURE__*/layer({
|
|
|
9449
9491
|
let prim = r == state.selection.main;
|
|
9450
9492
|
if (r.empty || conf.drawRangeCursor && !(prim && browser.ios && conf.iosSelectionHandles)) {
|
|
9451
9493
|
let className = prim ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary";
|
|
9452
|
-
let cursor = r.empty ? r : EditorSelection.cursor(r.head, r.
|
|
9494
|
+
let cursor = r.empty ? r : EditorSelection.cursor(r.head, r.assoc);
|
|
9453
9495
|
for (let piece of RectangleMarker.forRange(view, className, cursor))
|
|
9454
9496
|
cursors.push(piece);
|
|
9455
9497
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.41.0",
|
|
4
4
|
"description": "DOM view component for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@codemirror/state": "^6.
|
|
29
|
+
"@codemirror/state": "^6.6.0",
|
|
30
30
|
"crelt": "^1.0.6",
|
|
31
31
|
"style-mod": "^4.1.0",
|
|
32
32
|
"w3c-keyname": "^2.2.4"
|