@codemirror/view 6.40.0 → 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 +12 -0
- package/README.md +1 -1
- package/dist/index.cjs +42 -9
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +42 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
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
|
+
|
|
1
13
|
## 6.40.0 (2026-03-12)
|
|
2
14
|
|
|
3
15
|
### 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
|
@@ -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
|
|
@@ -3910,6 +3910,18 @@ class InlineCoordsScan {
|
|
|
3910
3910
|
this.y = (side.top + side.bottom) / 2;
|
|
3911
3911
|
return this.scan(positions, getRects);
|
|
3912
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
|
+
}
|
|
3913
3925
|
let ltr = (bidi ? this.dirAt(positions[closestI], 1) : this.baseDir) == exports.Direction.LTR;
|
|
3914
3926
|
return {
|
|
3915
3927
|
i: closestI,
|
|
@@ -7927,7 +7939,8 @@ class EditorView {
|
|
|
7927
7939
|
scrollTarget = scrollTarget.map(tr.changes);
|
|
7928
7940
|
if (tr.scrollIntoView) {
|
|
7929
7941
|
let { main } = tr.state.selection;
|
|
7930
|
-
|
|
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);
|
|
7931
7944
|
}
|
|
7932
7945
|
for (let e of tr.effects)
|
|
7933
7946
|
if (e.is(scrollIntoView))
|
|
@@ -8584,7 +8597,8 @@ class EditorView {
|
|
|
8584
8597
|
cause it to scroll the given position or range into view.
|
|
8585
8598
|
*/
|
|
8586
8599
|
static scrollIntoView(pos, options = {}) {
|
|
8587
|
-
|
|
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));
|
|
8588
8602
|
}
|
|
8589
8603
|
/**
|
|
8590
8604
|
Return an effect that resets the editor to its current (at the
|
|
@@ -8843,11 +8857,30 @@ supported.)
|
|
|
8843
8857
|
*/
|
|
8844
8858
|
EditorView.bidiIsolatedRanges = bidiIsolatedRanges;
|
|
8845
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
|
+
/**
|
|
8846
8878
|
Facet that allows extensions to provide additional scroll
|
|
8847
8879
|
margins (space around the sides of the scrolling element that
|
|
8848
8880
|
should be considered invisible). This can be useful when the
|
|
8849
8881
|
plugin introduces elements that cover part of that element (for
|
|
8850
|
-
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).
|
|
8851
8884
|
*/
|
|
8852
8885
|
EditorView.scrollMargins = scrollMargins;
|
|
8853
8886
|
/**
|
|
@@ -9383,7 +9416,7 @@ class LayerView {
|
|
|
9383
9416
|
old = next;
|
|
9384
9417
|
}
|
|
9385
9418
|
this.drawn = markers;
|
|
9386
|
-
if (browser.
|
|
9419
|
+
if (browser.webkit) // Issue #1600, 1627, 1686
|
|
9387
9420
|
this.dom.style.display = this.dom.firstChild ? "" : "none";
|
|
9388
9421
|
}
|
|
9389
9422
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -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
|
@@ -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
|
@@ -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
|
|
@@ -3906,6 +3906,18 @@ class InlineCoordsScan {
|
|
|
3906
3906
|
this.y = (side.top + side.bottom) / 2;
|
|
3907
3907
|
return this.scan(positions, getRects);
|
|
3908
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
|
+
}
|
|
3909
3921
|
let ltr = (bidi ? this.dirAt(positions[closestI], 1) : this.baseDir) == Direction.LTR;
|
|
3910
3922
|
return {
|
|
3911
3923
|
i: closestI,
|
|
@@ -7922,7 +7934,8 @@ class EditorView {
|
|
|
7922
7934
|
scrollTarget = scrollTarget.map(tr.changes);
|
|
7923
7935
|
if (tr.scrollIntoView) {
|
|
7924
7936
|
let { main } = tr.state.selection;
|
|
7925
|
-
|
|
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);
|
|
7926
7939
|
}
|
|
7927
7940
|
for (let e of tr.effects)
|
|
7928
7941
|
if (e.is(scrollIntoView))
|
|
@@ -8579,7 +8592,8 @@ class EditorView {
|
|
|
8579
8592
|
cause it to scroll the given position or range into view.
|
|
8580
8593
|
*/
|
|
8581
8594
|
static scrollIntoView(pos, options = {}) {
|
|
8582
|
-
|
|
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));
|
|
8583
8597
|
}
|
|
8584
8598
|
/**
|
|
8585
8599
|
Return an effect that resets the editor to its current (at the
|
|
@@ -8838,11 +8852,30 @@ supported.)
|
|
|
8838
8852
|
*/
|
|
8839
8853
|
EditorView.bidiIsolatedRanges = bidiIsolatedRanges;
|
|
8840
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
|
+
/**
|
|
8841
8873
|
Facet that allows extensions to provide additional scroll
|
|
8842
8874
|
margins (space around the sides of the scrolling element that
|
|
8843
8875
|
should be considered invisible). This can be useful when the
|
|
8844
8876
|
plugin introduces elements that cover part of that element (for
|
|
8845
|
-
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).
|
|
8846
8879
|
*/
|
|
8847
8880
|
EditorView.scrollMargins = scrollMargins;
|
|
8848
8881
|
/**
|
|
@@ -9378,7 +9411,7 @@ class LayerView {
|
|
|
9378
9411
|
old = next;
|
|
9379
9412
|
}
|
|
9380
9413
|
this.drawn = markers;
|
|
9381
|
-
if (browser.
|
|
9414
|
+
if (browser.webkit) // Issue #1600, 1627, 1686
|
|
9382
9415
|
this.dom.style.display = this.dom.firstChild ? "" : "none";
|
|
9383
9416
|
}
|
|
9384
9417
|
}
|