@codemirror/view 6.43.3 → 6.43.5
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 +18 -0
- package/dist/index.cjs +41 -23
- package/dist/index.js +41 -23
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.43.5 (2026-07-04)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue what would cause `domAtPos` to return positions on the wrong side of widgets.
|
|
6
|
+
|
|
7
|
+
Fix an issue that could cause the DOM cursor to be drawn on the wrong side of a collapsing decoration.
|
|
8
|
+
|
|
9
|
+
Don't return off-by-one coordinate positions at the edge of right-to-left text node in Safari.
|
|
10
|
+
|
|
11
|
+
Don't abort momentum scrolling on iOS by stabilizing the scroll position.
|
|
12
|
+
|
|
13
|
+
## 6.43.4 (2026-06-27)
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
Fix a regression in DOM document updates that could corrupt the tile tree and cause crashes.
|
|
18
|
+
|
|
1
19
|
## 6.43.3 (2026-06-25)
|
|
2
20
|
|
|
3
21
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -514,8 +514,11 @@ function scanFor(node, off, targetNode, targetOff, dir) {
|
|
|
514
514
|
function maxOffset(node) {
|
|
515
515
|
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
516
516
|
}
|
|
517
|
-
function flattenRect(rect,
|
|
518
|
-
let
|
|
517
|
+
function flattenRect(rect, toLeft) {
|
|
518
|
+
let { left, right } = rect;
|
|
519
|
+
if (left == right)
|
|
520
|
+
return rect;
|
|
521
|
+
let x = toLeft ? left : right;
|
|
519
522
|
return { left: x, right: x, top: rect.top, bottom: rect.bottom };
|
|
520
523
|
}
|
|
521
524
|
function windowRect(win) {
|
|
@@ -1780,7 +1783,7 @@ class Tile {
|
|
|
1780
1783
|
return this.posBefore(tile) + tile.length;
|
|
1781
1784
|
}
|
|
1782
1785
|
covers(side) { return true; }
|
|
1783
|
-
coordsIn(pos, side) { return null; }
|
|
1786
|
+
coordsIn(pos, side, rtl) { return null; }
|
|
1784
1787
|
domPosFor(off, side) {
|
|
1785
1788
|
let index = domIndex(this.dom);
|
|
1786
1789
|
let after = this.length ? off > 0 : side > 0;
|
|
@@ -1976,7 +1979,7 @@ class LineTile extends CompositeTile {
|
|
|
1976
1979
|
if (child.isComposite()) {
|
|
1977
1980
|
scan(child, pos - off);
|
|
1978
1981
|
}
|
|
1979
|
-
else if ((!after || after.isHidden && (side > 0 || forCoords && onSameLine(after, child))) &&
|
|
1982
|
+
else if ((!after || after.isHidden && (side > 0 && !(after.flags & 32 /* TileFlag.After */) || forCoords && onSameLine(after, child))) &&
|
|
1980
1983
|
(end > pos || (child.flags & 32 /* TileFlag.After */))) {
|
|
1981
1984
|
after = child;
|
|
1982
1985
|
afterOff = pos - off;
|
|
@@ -1993,11 +1996,11 @@ class LineTile extends CompositeTile {
|
|
|
1993
1996
|
let target = ((side < 0 ? before : after) || before || after);
|
|
1994
1997
|
return target ? { tile: target, offset: target == before ? beforeOff : afterOff } : null;
|
|
1995
1998
|
}
|
|
1996
|
-
coordsIn(pos, side) {
|
|
1999
|
+
coordsIn(pos, side, rtl) {
|
|
1997
2000
|
let found = this.resolveInline(pos, side, true);
|
|
1998
2001
|
if (!found)
|
|
1999
2002
|
return fallbackRect(this);
|
|
2000
|
-
return found.tile.coordsIn(Math.max(0, found.offset), side);
|
|
2003
|
+
return found.tile.coordsIn(Math.max(0, found.offset), side, rtl);
|
|
2001
2004
|
}
|
|
2002
2005
|
domIn(pos, side) {
|
|
2003
2006
|
let found = this.resolveInline(pos, side);
|
|
@@ -2061,7 +2064,7 @@ class TextTile extends Tile {
|
|
|
2061
2064
|
}
|
|
2062
2065
|
isText() { return true; }
|
|
2063
2066
|
toString() { return JSON.stringify(this.text); }
|
|
2064
|
-
coordsIn(pos, side) {
|
|
2067
|
+
coordsIn(pos, side, rtl) {
|
|
2065
2068
|
let length = this.dom.nodeValue.length;
|
|
2066
2069
|
if (pos > length)
|
|
2067
2070
|
pos = length;
|
|
@@ -2071,7 +2074,7 @@ class TextTile extends Tile {
|
|
|
2071
2074
|
if (pos) {
|
|
2072
2075
|
from--;
|
|
2073
2076
|
flatten = 1;
|
|
2074
|
-
}
|
|
2077
|
+
}
|
|
2075
2078
|
else if (to < length) {
|
|
2076
2079
|
to++;
|
|
2077
2080
|
flatten = -1;
|
|
@@ -2090,7 +2093,7 @@ class TextTile extends Tile {
|
|
|
2090
2093
|
let rect = rects[(flatten ? flatten < 0 : side >= 0) ? 0 : rects.length - 1];
|
|
2091
2094
|
if (browser.safari && !flatten && rect.width == 0)
|
|
2092
2095
|
rect = Array.prototype.find.call(rects, r => r.width) || rect;
|
|
2093
|
-
return
|
|
2096
|
+
return rtl == null ? rect : flattenRect(rect, (flatten ? flatten > 0 : side < 0) == rtl);
|
|
2094
2097
|
}
|
|
2095
2098
|
static of(text, dom) {
|
|
2096
2099
|
let tile = new TextTile(dom || document.createTextNode(text), text);
|
|
@@ -2166,7 +2169,10 @@ class WidgetBufferTile extends Tile {
|
|
|
2166
2169
|
}
|
|
2167
2170
|
get isHidden() { return true; }
|
|
2168
2171
|
get overrideDOMText() { return state.Text.empty; }
|
|
2169
|
-
coordsIn(pos
|
|
2172
|
+
coordsIn(pos, side, rtl) {
|
|
2173
|
+
let rect = this.dom.getBoundingClientRect();
|
|
2174
|
+
return rtl == null ? rect : flattenRect(rect, (side > 0) == rtl);
|
|
2175
|
+
}
|
|
2170
2176
|
}
|
|
2171
2177
|
// Represents a position in the tile tree.
|
|
2172
2178
|
class TilePointer {
|
|
@@ -2528,8 +2534,8 @@ class TileCache {
|
|
|
2528
2534
|
find(cls, test, type = 2 /* Reused.DOM */) {
|
|
2529
2535
|
let i = cls.bucket;
|
|
2530
2536
|
let bucket = this.buckets[i], off = this.index[i];
|
|
2531
|
-
for (let j =
|
|
2532
|
-
// Look at the most
|
|
2537
|
+
for (let j = 0; j < bucket.length; j++) {
|
|
2538
|
+
// Look at the most oldest items first (first-in, first-out)
|
|
2533
2539
|
let index = (j + off) % bucket.length, tile = bucket[index];
|
|
2534
2540
|
if ((!test || test(tile)) && !this.reused.has(tile)) {
|
|
2535
2541
|
bucket.splice(index, 1);
|
|
@@ -2783,6 +2789,7 @@ class TileUpdate {
|
|
|
2783
2789
|
}
|
|
2784
2790
|
pendingLineAttrs = null;
|
|
2785
2791
|
}
|
|
2792
|
+
markCount = active.length;
|
|
2786
2793
|
}
|
|
2787
2794
|
});
|
|
2788
2795
|
this.openWidget = openEnd > markCount;
|
|
@@ -3194,7 +3201,7 @@ class DocView {
|
|
|
3194
3201
|
domAtPos(pos, side) {
|
|
3195
3202
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3196
3203
|
if (tile.isWidget())
|
|
3197
|
-
return tile.domPosFor(
|
|
3204
|
+
return tile.domPosFor(offset, side);
|
|
3198
3205
|
return tile.domIn(offset, side);
|
|
3199
3206
|
}
|
|
3200
3207
|
inlineDOMNearPos(pos, side) {
|
|
@@ -3231,14 +3238,16 @@ class DocView {
|
|
|
3231
3238
|
after = null;
|
|
3232
3239
|
return before && side < 0 || !after ? before.domIn(beforeOff, side) : after.domIn(afterOff, side);
|
|
3233
3240
|
}
|
|
3234
|
-
|
|
3241
|
+
// Get the coord of the element at the given side of the given
|
|
3242
|
+
// position. If rtl is given, flatten it using that text direction.
|
|
3243
|
+
coordsAt(pos, side, rtl) {
|
|
3235
3244
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3236
3245
|
if (tile.isWidget()) {
|
|
3237
3246
|
if (tile.widget instanceof BlockGapWidget)
|
|
3238
3247
|
return null;
|
|
3239
3248
|
return tile.coordsInWidget(offset, side, true);
|
|
3240
3249
|
}
|
|
3241
|
-
return tile.coordsIn(offset, side);
|
|
3250
|
+
return tile.coordsIn(offset, side, rtl);
|
|
3242
3251
|
}
|
|
3243
3252
|
lineAt(pos, side) {
|
|
3244
3253
|
let { tile } = this.tile.resolveBlock(pos, side);
|
|
@@ -3412,7 +3421,6 @@ class DocView {
|
|
|
3412
3421
|
this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
|
|
3413
3422
|
}
|
|
3414
3423
|
scrollIntoView(target) {
|
|
3415
|
-
var _a;
|
|
3416
3424
|
if (target.isSnapshot) {
|
|
3417
3425
|
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3418
3426
|
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
@@ -3429,7 +3437,7 @@ class DocView {
|
|
|
3429
3437
|
}
|
|
3430
3438
|
}
|
|
3431
3439
|
let { range } = target;
|
|
3432
|
-
let rect = this.coordsAt(range.head,
|
|
3440
|
+
let rect = this.coordsAt(range.head, range.assoc || (range.head > range.anchor ? -1 : 1)), other;
|
|
3433
3441
|
if (!rect)
|
|
3434
3442
|
return;
|
|
3435
3443
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
@@ -4471,6 +4479,7 @@ class InputState {
|
|
|
4471
4479
|
this.view = view;
|
|
4472
4480
|
this.lastKeyCode = 0;
|
|
4473
4481
|
this.lastKeyTime = 0;
|
|
4482
|
+
this.touchActive = false;
|
|
4474
4483
|
this.lastTouchTime = 0;
|
|
4475
4484
|
this.lastTouchX = 0;
|
|
4476
4485
|
this.lastTouchY = 0;
|
|
@@ -4482,6 +4491,10 @@ class InputState {
|
|
|
4482
4491
|
// (after which we retroactively handle them and reset the DOM) to
|
|
4483
4492
|
// avoid messing up the virtual keyboard state.
|
|
4484
4493
|
this.pendingIOSKey = undefined;
|
|
4494
|
+
// Set to a time stap by scroll events when touch isn't active on
|
|
4495
|
+
// iOS, to work around an issue where Safari will abort the scroll
|
|
4496
|
+
// momentum if we set scrollTop
|
|
4497
|
+
this.lastIOSMomentumScroll = 0;
|
|
4485
4498
|
// When enabled (>-1), tab presses are not given to key handlers,
|
|
4486
4499
|
// leaving the browser's default behavior. If >0, the mode expires
|
|
4487
4500
|
// at that timestamp, and any other keypress clears it.
|
|
@@ -4912,8 +4925,11 @@ function doPaste(view, input) {
|
|
|
4912
4925
|
});
|
|
4913
4926
|
}
|
|
4914
4927
|
observers.scroll = view => {
|
|
4915
|
-
|
|
4916
|
-
|
|
4928
|
+
let iState = view.inputState;
|
|
4929
|
+
iState.lastScrollTop = view.scrollDOM.scrollTop;
|
|
4930
|
+
iState.lastScrollLeft = view.scrollDOM.scrollLeft;
|
|
4931
|
+
if (browser.ios && !iState.touchActive)
|
|
4932
|
+
iState.lastIOSMomentumScroll = Date.now();
|
|
4917
4933
|
};
|
|
4918
4934
|
observers.wheel = observers.mousewheel = view => {
|
|
4919
4935
|
view.inputState.lastWheelEvent = Date.now();
|
|
@@ -4926,6 +4942,7 @@ handlers.keydown = (view, event) => {
|
|
|
4926
4942
|
};
|
|
4927
4943
|
observers.touchstart = (view, e) => {
|
|
4928
4944
|
let iState = view.inputState, touch = e.targetTouches[0];
|
|
4945
|
+
iState.touchActive = true;
|
|
4929
4946
|
iState.lastTouchTime = Date.now();
|
|
4930
4947
|
if (touch) {
|
|
4931
4948
|
iState.lastTouchX = touch.clientX;
|
|
@@ -4936,6 +4953,9 @@ observers.touchstart = (view, e) => {
|
|
|
4936
4953
|
observers.touchmove = view => {
|
|
4937
4954
|
view.inputState.setSelectionOrigin("select.pointer");
|
|
4938
4955
|
};
|
|
4956
|
+
observers.touchend = (view, e) => {
|
|
4957
|
+
view.inputState.touchActive = false;
|
|
4958
|
+
};
|
|
4939
4959
|
handlers.mousedown = (view, event) => {
|
|
4940
4960
|
view.observer.flush();
|
|
4941
4961
|
if (view.inputState.lastTouchTime > Date.now() - 2000)
|
|
@@ -8198,6 +8218,7 @@ class EditorView {
|
|
|
8198
8218
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
8199
8219
|
let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
|
|
8200
8220
|
if ((diff > 1 || diff < -1) &&
|
|
8221
|
+
!(browser.ios && this.inputState.lastIOSMomentumScroll > Date.now() - 100) &&
|
|
8201
8222
|
(scroll == this.scrollDOM || this.hasFocus ||
|
|
8202
8223
|
Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
|
|
8203
8224
|
scrollOffset = scrollOffset + diff;
|
|
@@ -8489,12 +8510,9 @@ class EditorView {
|
|
|
8489
8510
|
*/
|
|
8490
8511
|
coordsAtPos(pos, side = 1) {
|
|
8491
8512
|
this.readMeasured();
|
|
8492
|
-
let rect = this.docView.coordsAt(pos, side);
|
|
8493
|
-
if (!rect || rect.left == rect.right)
|
|
8494
|
-
return rect;
|
|
8495
8513
|
let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
|
|
8496
8514
|
let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
|
|
8497
|
-
return
|
|
8515
|
+
return this.docView.coordsAt(pos, side, span.dir == exports.Direction.RTL);
|
|
8498
8516
|
}
|
|
8499
8517
|
/**
|
|
8500
8518
|
Return the rectangle around a given character. If `pos` does not
|
package/dist/index.js
CHANGED
|
@@ -511,8 +511,11 @@ function scanFor(node, off, targetNode, targetOff, dir) {
|
|
|
511
511
|
function maxOffset(node) {
|
|
512
512
|
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
513
513
|
}
|
|
514
|
-
function flattenRect(rect,
|
|
515
|
-
let
|
|
514
|
+
function flattenRect(rect, toLeft) {
|
|
515
|
+
let { left, right } = rect;
|
|
516
|
+
if (left == right)
|
|
517
|
+
return rect;
|
|
518
|
+
let x = toLeft ? left : right;
|
|
516
519
|
return { left: x, right: x, top: rect.top, bottom: rect.bottom };
|
|
517
520
|
}
|
|
518
521
|
function windowRect(win) {
|
|
@@ -1776,7 +1779,7 @@ class Tile {
|
|
|
1776
1779
|
return this.posBefore(tile) + tile.length;
|
|
1777
1780
|
}
|
|
1778
1781
|
covers(side) { return true; }
|
|
1779
|
-
coordsIn(pos, side) { return null; }
|
|
1782
|
+
coordsIn(pos, side, rtl) { return null; }
|
|
1780
1783
|
domPosFor(off, side) {
|
|
1781
1784
|
let index = domIndex(this.dom);
|
|
1782
1785
|
let after = this.length ? off > 0 : side > 0;
|
|
@@ -1972,7 +1975,7 @@ class LineTile extends CompositeTile {
|
|
|
1972
1975
|
if (child.isComposite()) {
|
|
1973
1976
|
scan(child, pos - off);
|
|
1974
1977
|
}
|
|
1975
|
-
else if ((!after || after.isHidden && (side > 0 || forCoords && onSameLine(after, child))) &&
|
|
1978
|
+
else if ((!after || after.isHidden && (side > 0 && !(after.flags & 32 /* TileFlag.After */) || forCoords && onSameLine(after, child))) &&
|
|
1976
1979
|
(end > pos || (child.flags & 32 /* TileFlag.After */))) {
|
|
1977
1980
|
after = child;
|
|
1978
1981
|
afterOff = pos - off;
|
|
@@ -1989,11 +1992,11 @@ class LineTile extends CompositeTile {
|
|
|
1989
1992
|
let target = ((side < 0 ? before : after) || before || after);
|
|
1990
1993
|
return target ? { tile: target, offset: target == before ? beforeOff : afterOff } : null;
|
|
1991
1994
|
}
|
|
1992
|
-
coordsIn(pos, side) {
|
|
1995
|
+
coordsIn(pos, side, rtl) {
|
|
1993
1996
|
let found = this.resolveInline(pos, side, true);
|
|
1994
1997
|
if (!found)
|
|
1995
1998
|
return fallbackRect(this);
|
|
1996
|
-
return found.tile.coordsIn(Math.max(0, found.offset), side);
|
|
1999
|
+
return found.tile.coordsIn(Math.max(0, found.offset), side, rtl);
|
|
1997
2000
|
}
|
|
1998
2001
|
domIn(pos, side) {
|
|
1999
2002
|
let found = this.resolveInline(pos, side);
|
|
@@ -2057,7 +2060,7 @@ class TextTile extends Tile {
|
|
|
2057
2060
|
}
|
|
2058
2061
|
isText() { return true; }
|
|
2059
2062
|
toString() { return JSON.stringify(this.text); }
|
|
2060
|
-
coordsIn(pos, side) {
|
|
2063
|
+
coordsIn(pos, side, rtl) {
|
|
2061
2064
|
let length = this.dom.nodeValue.length;
|
|
2062
2065
|
if (pos > length)
|
|
2063
2066
|
pos = length;
|
|
@@ -2067,7 +2070,7 @@ class TextTile extends Tile {
|
|
|
2067
2070
|
if (pos) {
|
|
2068
2071
|
from--;
|
|
2069
2072
|
flatten = 1;
|
|
2070
|
-
}
|
|
2073
|
+
}
|
|
2071
2074
|
else if (to < length) {
|
|
2072
2075
|
to++;
|
|
2073
2076
|
flatten = -1;
|
|
@@ -2086,7 +2089,7 @@ class TextTile extends Tile {
|
|
|
2086
2089
|
let rect = rects[(flatten ? flatten < 0 : side >= 0) ? 0 : rects.length - 1];
|
|
2087
2090
|
if (browser.safari && !flatten && rect.width == 0)
|
|
2088
2091
|
rect = Array.prototype.find.call(rects, r => r.width) || rect;
|
|
2089
|
-
return
|
|
2092
|
+
return rtl == null ? rect : flattenRect(rect, (flatten ? flatten > 0 : side < 0) == rtl);
|
|
2090
2093
|
}
|
|
2091
2094
|
static of(text, dom) {
|
|
2092
2095
|
let tile = new TextTile(dom || document.createTextNode(text), text);
|
|
@@ -2162,7 +2165,10 @@ class WidgetBufferTile extends Tile {
|
|
|
2162
2165
|
}
|
|
2163
2166
|
get isHidden() { return true; }
|
|
2164
2167
|
get overrideDOMText() { return Text.empty; }
|
|
2165
|
-
coordsIn(pos
|
|
2168
|
+
coordsIn(pos, side, rtl) {
|
|
2169
|
+
let rect = this.dom.getBoundingClientRect();
|
|
2170
|
+
return rtl == null ? rect : flattenRect(rect, (side > 0) == rtl);
|
|
2171
|
+
}
|
|
2166
2172
|
}
|
|
2167
2173
|
// Represents a position in the tile tree.
|
|
2168
2174
|
class TilePointer {
|
|
@@ -2524,8 +2530,8 @@ class TileCache {
|
|
|
2524
2530
|
find(cls, test, type = 2 /* Reused.DOM */) {
|
|
2525
2531
|
let i = cls.bucket;
|
|
2526
2532
|
let bucket = this.buckets[i], off = this.index[i];
|
|
2527
|
-
for (let j =
|
|
2528
|
-
// Look at the most
|
|
2533
|
+
for (let j = 0; j < bucket.length; j++) {
|
|
2534
|
+
// Look at the most oldest items first (first-in, first-out)
|
|
2529
2535
|
let index = (j + off) % bucket.length, tile = bucket[index];
|
|
2530
2536
|
if ((!test || test(tile)) && !this.reused.has(tile)) {
|
|
2531
2537
|
bucket.splice(index, 1);
|
|
@@ -2779,6 +2785,7 @@ class TileUpdate {
|
|
|
2779
2785
|
}
|
|
2780
2786
|
pendingLineAttrs = null;
|
|
2781
2787
|
}
|
|
2788
|
+
markCount = active.length;
|
|
2782
2789
|
}
|
|
2783
2790
|
});
|
|
2784
2791
|
this.openWidget = openEnd > markCount;
|
|
@@ -3190,7 +3197,7 @@ class DocView {
|
|
|
3190
3197
|
domAtPos(pos, side) {
|
|
3191
3198
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3192
3199
|
if (tile.isWidget())
|
|
3193
|
-
return tile.domPosFor(
|
|
3200
|
+
return tile.domPosFor(offset, side);
|
|
3194
3201
|
return tile.domIn(offset, side);
|
|
3195
3202
|
}
|
|
3196
3203
|
inlineDOMNearPos(pos, side) {
|
|
@@ -3227,14 +3234,16 @@ class DocView {
|
|
|
3227
3234
|
after = null;
|
|
3228
3235
|
return before && side < 0 || !after ? before.domIn(beforeOff, side) : after.domIn(afterOff, side);
|
|
3229
3236
|
}
|
|
3230
|
-
|
|
3237
|
+
// Get the coord of the element at the given side of the given
|
|
3238
|
+
// position. If rtl is given, flatten it using that text direction.
|
|
3239
|
+
coordsAt(pos, side, rtl) {
|
|
3231
3240
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3232
3241
|
if (tile.isWidget()) {
|
|
3233
3242
|
if (tile.widget instanceof BlockGapWidget)
|
|
3234
3243
|
return null;
|
|
3235
3244
|
return tile.coordsInWidget(offset, side, true);
|
|
3236
3245
|
}
|
|
3237
|
-
return tile.coordsIn(offset, side);
|
|
3246
|
+
return tile.coordsIn(offset, side, rtl);
|
|
3238
3247
|
}
|
|
3239
3248
|
lineAt(pos, side) {
|
|
3240
3249
|
let { tile } = this.tile.resolveBlock(pos, side);
|
|
@@ -3408,7 +3417,6 @@ class DocView {
|
|
|
3408
3417
|
this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
|
|
3409
3418
|
}
|
|
3410
3419
|
scrollIntoView(target) {
|
|
3411
|
-
var _a;
|
|
3412
3420
|
if (target.isSnapshot) {
|
|
3413
3421
|
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3414
3422
|
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
@@ -3425,7 +3433,7 @@ class DocView {
|
|
|
3425
3433
|
}
|
|
3426
3434
|
}
|
|
3427
3435
|
let { range } = target;
|
|
3428
|
-
let rect = this.coordsAt(range.head,
|
|
3436
|
+
let rect = this.coordsAt(range.head, range.assoc || (range.head > range.anchor ? -1 : 1)), other;
|
|
3429
3437
|
if (!rect)
|
|
3430
3438
|
return;
|
|
3431
3439
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
@@ -4467,6 +4475,7 @@ class InputState {
|
|
|
4467
4475
|
this.view = view;
|
|
4468
4476
|
this.lastKeyCode = 0;
|
|
4469
4477
|
this.lastKeyTime = 0;
|
|
4478
|
+
this.touchActive = false;
|
|
4470
4479
|
this.lastTouchTime = 0;
|
|
4471
4480
|
this.lastTouchX = 0;
|
|
4472
4481
|
this.lastTouchY = 0;
|
|
@@ -4478,6 +4487,10 @@ class InputState {
|
|
|
4478
4487
|
// (after which we retroactively handle them and reset the DOM) to
|
|
4479
4488
|
// avoid messing up the virtual keyboard state.
|
|
4480
4489
|
this.pendingIOSKey = undefined;
|
|
4490
|
+
// Set to a time stap by scroll events when touch isn't active on
|
|
4491
|
+
// iOS, to work around an issue where Safari will abort the scroll
|
|
4492
|
+
// momentum if we set scrollTop
|
|
4493
|
+
this.lastIOSMomentumScroll = 0;
|
|
4481
4494
|
// When enabled (>-1), tab presses are not given to key handlers,
|
|
4482
4495
|
// leaving the browser's default behavior. If >0, the mode expires
|
|
4483
4496
|
// at that timestamp, and any other keypress clears it.
|
|
@@ -4908,8 +4921,11 @@ function doPaste(view, input) {
|
|
|
4908
4921
|
});
|
|
4909
4922
|
}
|
|
4910
4923
|
observers.scroll = view => {
|
|
4911
|
-
|
|
4912
|
-
|
|
4924
|
+
let iState = view.inputState;
|
|
4925
|
+
iState.lastScrollTop = view.scrollDOM.scrollTop;
|
|
4926
|
+
iState.lastScrollLeft = view.scrollDOM.scrollLeft;
|
|
4927
|
+
if (browser.ios && !iState.touchActive)
|
|
4928
|
+
iState.lastIOSMomentumScroll = Date.now();
|
|
4913
4929
|
};
|
|
4914
4930
|
observers.wheel = observers.mousewheel = view => {
|
|
4915
4931
|
view.inputState.lastWheelEvent = Date.now();
|
|
@@ -4922,6 +4938,7 @@ handlers.keydown = (view, event) => {
|
|
|
4922
4938
|
};
|
|
4923
4939
|
observers.touchstart = (view, e) => {
|
|
4924
4940
|
let iState = view.inputState, touch = e.targetTouches[0];
|
|
4941
|
+
iState.touchActive = true;
|
|
4925
4942
|
iState.lastTouchTime = Date.now();
|
|
4926
4943
|
if (touch) {
|
|
4927
4944
|
iState.lastTouchX = touch.clientX;
|
|
@@ -4932,6 +4949,9 @@ observers.touchstart = (view, e) => {
|
|
|
4932
4949
|
observers.touchmove = view => {
|
|
4933
4950
|
view.inputState.setSelectionOrigin("select.pointer");
|
|
4934
4951
|
};
|
|
4952
|
+
observers.touchend = (view, e) => {
|
|
4953
|
+
view.inputState.touchActive = false;
|
|
4954
|
+
};
|
|
4935
4955
|
handlers.mousedown = (view, event) => {
|
|
4936
4956
|
view.observer.flush();
|
|
4937
4957
|
if (view.inputState.lastTouchTime > Date.now() - 2000)
|
|
@@ -8193,6 +8213,7 @@ class EditorView {
|
|
|
8193
8213
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
8194
8214
|
let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
|
|
8195
8215
|
if ((diff > 1 || diff < -1) &&
|
|
8216
|
+
!(browser.ios && this.inputState.lastIOSMomentumScroll > Date.now() - 100) &&
|
|
8196
8217
|
(scroll == this.scrollDOM || this.hasFocus ||
|
|
8197
8218
|
Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
|
|
8198
8219
|
scrollOffset = scrollOffset + diff;
|
|
@@ -8484,12 +8505,9 @@ class EditorView {
|
|
|
8484
8505
|
*/
|
|
8485
8506
|
coordsAtPos(pos, side = 1) {
|
|
8486
8507
|
this.readMeasured();
|
|
8487
|
-
let rect = this.docView.coordsAt(pos, side);
|
|
8488
|
-
if (!rect || rect.left == rect.right)
|
|
8489
|
-
return rect;
|
|
8490
8508
|
let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
|
|
8491
8509
|
let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
|
|
8492
|
-
return
|
|
8510
|
+
return this.docView.coordsAt(pos, side, span.dir == Direction.RTL);
|
|
8493
8511
|
}
|
|
8494
8512
|
/**
|
|
8495
8513
|
Return the rectangle around a given character. If `pos` does not
|