@codemirror/view 6.43.4 → 6.43.6
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 +43 -25
- package/dist/index.js +43 -25
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.43.6 (2026-07-06)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix another tile tree corruption bug that could occur on zero-length content updates.
|
|
6
|
+
|
|
7
|
+
## 6.43.5 (2026-07-04)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix an issue what would cause `domAtPos` to return positions on the wrong side of widgets.
|
|
12
|
+
|
|
13
|
+
Fix an issue that could cause the DOM cursor to be drawn on the wrong side of a collapsing decoration.
|
|
14
|
+
|
|
15
|
+
Don't return off-by-one coordinate positions at the edge of right-to-left text node in Safari.
|
|
16
|
+
|
|
17
|
+
Don't abort momentum scrolling on iOS by stabilizing the scroll position.
|
|
18
|
+
|
|
1
19
|
## 6.43.4 (2026-06-27)
|
|
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);
|
|
@@ -2732,7 +2738,7 @@ class TileUpdate {
|
|
|
2732
2738
|
}
|
|
2733
2739
|
emit(from, to) {
|
|
2734
2740
|
let pendingLineAttrs = null;
|
|
2735
|
-
let b = this.builder, markCount =
|
|
2741
|
+
let b = this.builder, markCount = -1;
|
|
2736
2742
|
let openEnd = state.RangeSet.spans(this.decorations, from, to, {
|
|
2737
2743
|
point: (from, to, deco, active, openStart, index) => {
|
|
2738
2744
|
if (deco instanceof PointDecoration) {
|
|
@@ -2786,7 +2792,8 @@ class TileUpdate {
|
|
|
2786
2792
|
markCount = active.length;
|
|
2787
2793
|
}
|
|
2788
2794
|
});
|
|
2789
|
-
|
|
2795
|
+
if (markCount > -1)
|
|
2796
|
+
this.openWidget = openEnd > markCount;
|
|
2790
2797
|
if (!this.openWidget)
|
|
2791
2798
|
b.addLineStartIfNotCovered(pendingLineAttrs);
|
|
2792
2799
|
this.openMarks = openEnd;
|
|
@@ -3195,7 +3202,7 @@ class DocView {
|
|
|
3195
3202
|
domAtPos(pos, side) {
|
|
3196
3203
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3197
3204
|
if (tile.isWidget())
|
|
3198
|
-
return tile.domPosFor(
|
|
3205
|
+
return tile.domPosFor(offset, side);
|
|
3199
3206
|
return tile.domIn(offset, side);
|
|
3200
3207
|
}
|
|
3201
3208
|
inlineDOMNearPos(pos, side) {
|
|
@@ -3232,14 +3239,16 @@ class DocView {
|
|
|
3232
3239
|
after = null;
|
|
3233
3240
|
return before && side < 0 || !after ? before.domIn(beforeOff, side) : after.domIn(afterOff, side);
|
|
3234
3241
|
}
|
|
3235
|
-
|
|
3242
|
+
// Get the coord of the element at the given side of the given
|
|
3243
|
+
// position. If rtl is given, flatten it using that text direction.
|
|
3244
|
+
coordsAt(pos, side, rtl) {
|
|
3236
3245
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3237
3246
|
if (tile.isWidget()) {
|
|
3238
3247
|
if (tile.widget instanceof BlockGapWidget)
|
|
3239
3248
|
return null;
|
|
3240
3249
|
return tile.coordsInWidget(offset, side, true);
|
|
3241
3250
|
}
|
|
3242
|
-
return tile.coordsIn(offset, side);
|
|
3251
|
+
return tile.coordsIn(offset, side, rtl);
|
|
3243
3252
|
}
|
|
3244
3253
|
lineAt(pos, side) {
|
|
3245
3254
|
let { tile } = this.tile.resolveBlock(pos, side);
|
|
@@ -3413,7 +3422,6 @@ class DocView {
|
|
|
3413
3422
|
this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
|
|
3414
3423
|
}
|
|
3415
3424
|
scrollIntoView(target) {
|
|
3416
|
-
var _a;
|
|
3417
3425
|
if (target.isSnapshot) {
|
|
3418
3426
|
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3419
3427
|
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
@@ -3430,7 +3438,7 @@ class DocView {
|
|
|
3430
3438
|
}
|
|
3431
3439
|
}
|
|
3432
3440
|
let { range } = target;
|
|
3433
|
-
let rect = this.coordsAt(range.head,
|
|
3441
|
+
let rect = this.coordsAt(range.head, range.assoc || (range.head > range.anchor ? -1 : 1)), other;
|
|
3434
3442
|
if (!rect)
|
|
3435
3443
|
return;
|
|
3436
3444
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
@@ -4472,6 +4480,7 @@ class InputState {
|
|
|
4472
4480
|
this.view = view;
|
|
4473
4481
|
this.lastKeyCode = 0;
|
|
4474
4482
|
this.lastKeyTime = 0;
|
|
4483
|
+
this.touchActive = false;
|
|
4475
4484
|
this.lastTouchTime = 0;
|
|
4476
4485
|
this.lastTouchX = 0;
|
|
4477
4486
|
this.lastTouchY = 0;
|
|
@@ -4483,6 +4492,10 @@ class InputState {
|
|
|
4483
4492
|
// (after which we retroactively handle them and reset the DOM) to
|
|
4484
4493
|
// avoid messing up the virtual keyboard state.
|
|
4485
4494
|
this.pendingIOSKey = undefined;
|
|
4495
|
+
// Set to a time stap by scroll events when touch isn't active on
|
|
4496
|
+
// iOS, to work around an issue where Safari will abort the scroll
|
|
4497
|
+
// momentum if we set scrollTop
|
|
4498
|
+
this.lastIOSMomentumScroll = 0;
|
|
4486
4499
|
// When enabled (>-1), tab presses are not given to key handlers,
|
|
4487
4500
|
// leaving the browser's default behavior. If >0, the mode expires
|
|
4488
4501
|
// at that timestamp, and any other keypress clears it.
|
|
@@ -4913,8 +4926,11 @@ function doPaste(view, input) {
|
|
|
4913
4926
|
});
|
|
4914
4927
|
}
|
|
4915
4928
|
observers.scroll = view => {
|
|
4916
|
-
|
|
4917
|
-
|
|
4929
|
+
let iState = view.inputState;
|
|
4930
|
+
iState.lastScrollTop = view.scrollDOM.scrollTop;
|
|
4931
|
+
iState.lastScrollLeft = view.scrollDOM.scrollLeft;
|
|
4932
|
+
if (browser.ios && !iState.touchActive)
|
|
4933
|
+
iState.lastIOSMomentumScroll = Date.now();
|
|
4918
4934
|
};
|
|
4919
4935
|
observers.wheel = observers.mousewheel = view => {
|
|
4920
4936
|
view.inputState.lastWheelEvent = Date.now();
|
|
@@ -4927,6 +4943,7 @@ handlers.keydown = (view, event) => {
|
|
|
4927
4943
|
};
|
|
4928
4944
|
observers.touchstart = (view, e) => {
|
|
4929
4945
|
let iState = view.inputState, touch = e.targetTouches[0];
|
|
4946
|
+
iState.touchActive = true;
|
|
4930
4947
|
iState.lastTouchTime = Date.now();
|
|
4931
4948
|
if (touch) {
|
|
4932
4949
|
iState.lastTouchX = touch.clientX;
|
|
@@ -4937,6 +4954,9 @@ observers.touchstart = (view, e) => {
|
|
|
4937
4954
|
observers.touchmove = view => {
|
|
4938
4955
|
view.inputState.setSelectionOrigin("select.pointer");
|
|
4939
4956
|
};
|
|
4957
|
+
observers.touchend = (view, e) => {
|
|
4958
|
+
view.inputState.touchActive = false;
|
|
4959
|
+
};
|
|
4940
4960
|
handlers.mousedown = (view, event) => {
|
|
4941
4961
|
view.observer.flush();
|
|
4942
4962
|
if (view.inputState.lastTouchTime > Date.now() - 2000)
|
|
@@ -8199,6 +8219,7 @@ class EditorView {
|
|
|
8199
8219
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
8200
8220
|
let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
|
|
8201
8221
|
if ((diff > 1 || diff < -1) &&
|
|
8222
|
+
!(browser.ios && this.inputState.lastIOSMomentumScroll > Date.now() - 100) &&
|
|
8202
8223
|
(scroll == this.scrollDOM || this.hasFocus ||
|
|
8203
8224
|
Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
|
|
8204
8225
|
scrollOffset = scrollOffset + diff;
|
|
@@ -8490,12 +8511,9 @@ class EditorView {
|
|
|
8490
8511
|
*/
|
|
8491
8512
|
coordsAtPos(pos, side = 1) {
|
|
8492
8513
|
this.readMeasured();
|
|
8493
|
-
let rect = this.docView.coordsAt(pos, side);
|
|
8494
|
-
if (!rect || rect.left == rect.right)
|
|
8495
|
-
return rect;
|
|
8496
8514
|
let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
|
|
8497
8515
|
let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
|
|
8498
|
-
return
|
|
8516
|
+
return this.docView.coordsAt(pos, side, span.dir == exports.Direction.RTL);
|
|
8499
8517
|
}
|
|
8500
8518
|
/**
|
|
8501
8519
|
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);
|
|
@@ -2728,7 +2734,7 @@ class TileUpdate {
|
|
|
2728
2734
|
}
|
|
2729
2735
|
emit(from, to) {
|
|
2730
2736
|
let pendingLineAttrs = null;
|
|
2731
|
-
let b = this.builder, markCount =
|
|
2737
|
+
let b = this.builder, markCount = -1;
|
|
2732
2738
|
let openEnd = RangeSet.spans(this.decorations, from, to, {
|
|
2733
2739
|
point: (from, to, deco, active, openStart, index) => {
|
|
2734
2740
|
if (deco instanceof PointDecoration) {
|
|
@@ -2782,7 +2788,8 @@ class TileUpdate {
|
|
|
2782
2788
|
markCount = active.length;
|
|
2783
2789
|
}
|
|
2784
2790
|
});
|
|
2785
|
-
|
|
2791
|
+
if (markCount > -1)
|
|
2792
|
+
this.openWidget = openEnd > markCount;
|
|
2786
2793
|
if (!this.openWidget)
|
|
2787
2794
|
b.addLineStartIfNotCovered(pendingLineAttrs);
|
|
2788
2795
|
this.openMarks = openEnd;
|
|
@@ -3191,7 +3198,7 @@ class DocView {
|
|
|
3191
3198
|
domAtPos(pos, side) {
|
|
3192
3199
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3193
3200
|
if (tile.isWidget())
|
|
3194
|
-
return tile.domPosFor(
|
|
3201
|
+
return tile.domPosFor(offset, side);
|
|
3195
3202
|
return tile.domIn(offset, side);
|
|
3196
3203
|
}
|
|
3197
3204
|
inlineDOMNearPos(pos, side) {
|
|
@@ -3228,14 +3235,16 @@ class DocView {
|
|
|
3228
3235
|
after = null;
|
|
3229
3236
|
return before && side < 0 || !after ? before.domIn(beforeOff, side) : after.domIn(afterOff, side);
|
|
3230
3237
|
}
|
|
3231
|
-
|
|
3238
|
+
// Get the coord of the element at the given side of the given
|
|
3239
|
+
// position. If rtl is given, flatten it using that text direction.
|
|
3240
|
+
coordsAt(pos, side, rtl) {
|
|
3232
3241
|
let { tile, offset } = this.tile.resolveBlock(pos, side);
|
|
3233
3242
|
if (tile.isWidget()) {
|
|
3234
3243
|
if (tile.widget instanceof BlockGapWidget)
|
|
3235
3244
|
return null;
|
|
3236
3245
|
return tile.coordsInWidget(offset, side, true);
|
|
3237
3246
|
}
|
|
3238
|
-
return tile.coordsIn(offset, side);
|
|
3247
|
+
return tile.coordsIn(offset, side, rtl);
|
|
3239
3248
|
}
|
|
3240
3249
|
lineAt(pos, side) {
|
|
3241
3250
|
let { tile } = this.tile.resolveBlock(pos, side);
|
|
@@ -3409,7 +3418,6 @@ class DocView {
|
|
|
3409
3418
|
this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
|
|
3410
3419
|
}
|
|
3411
3420
|
scrollIntoView(target) {
|
|
3412
|
-
var _a;
|
|
3413
3421
|
if (target.isSnapshot) {
|
|
3414
3422
|
let ref = this.view.viewState.lineBlockAt(target.range.head);
|
|
3415
3423
|
this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
|
|
@@ -3426,7 +3434,7 @@ class DocView {
|
|
|
3426
3434
|
}
|
|
3427
3435
|
}
|
|
3428
3436
|
let { range } = target;
|
|
3429
|
-
let rect = this.coordsAt(range.head,
|
|
3437
|
+
let rect = this.coordsAt(range.head, range.assoc || (range.head > range.anchor ? -1 : 1)), other;
|
|
3430
3438
|
if (!rect)
|
|
3431
3439
|
return;
|
|
3432
3440
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
@@ -4468,6 +4476,7 @@ class InputState {
|
|
|
4468
4476
|
this.view = view;
|
|
4469
4477
|
this.lastKeyCode = 0;
|
|
4470
4478
|
this.lastKeyTime = 0;
|
|
4479
|
+
this.touchActive = false;
|
|
4471
4480
|
this.lastTouchTime = 0;
|
|
4472
4481
|
this.lastTouchX = 0;
|
|
4473
4482
|
this.lastTouchY = 0;
|
|
@@ -4479,6 +4488,10 @@ class InputState {
|
|
|
4479
4488
|
// (after which we retroactively handle them and reset the DOM) to
|
|
4480
4489
|
// avoid messing up the virtual keyboard state.
|
|
4481
4490
|
this.pendingIOSKey = undefined;
|
|
4491
|
+
// Set to a time stap by scroll events when touch isn't active on
|
|
4492
|
+
// iOS, to work around an issue where Safari will abort the scroll
|
|
4493
|
+
// momentum if we set scrollTop
|
|
4494
|
+
this.lastIOSMomentumScroll = 0;
|
|
4482
4495
|
// When enabled (>-1), tab presses are not given to key handlers,
|
|
4483
4496
|
// leaving the browser's default behavior. If >0, the mode expires
|
|
4484
4497
|
// at that timestamp, and any other keypress clears it.
|
|
@@ -4909,8 +4922,11 @@ function doPaste(view, input) {
|
|
|
4909
4922
|
});
|
|
4910
4923
|
}
|
|
4911
4924
|
observers.scroll = view => {
|
|
4912
|
-
|
|
4913
|
-
|
|
4925
|
+
let iState = view.inputState;
|
|
4926
|
+
iState.lastScrollTop = view.scrollDOM.scrollTop;
|
|
4927
|
+
iState.lastScrollLeft = view.scrollDOM.scrollLeft;
|
|
4928
|
+
if (browser.ios && !iState.touchActive)
|
|
4929
|
+
iState.lastIOSMomentumScroll = Date.now();
|
|
4914
4930
|
};
|
|
4915
4931
|
observers.wheel = observers.mousewheel = view => {
|
|
4916
4932
|
view.inputState.lastWheelEvent = Date.now();
|
|
@@ -4923,6 +4939,7 @@ handlers.keydown = (view, event) => {
|
|
|
4923
4939
|
};
|
|
4924
4940
|
observers.touchstart = (view, e) => {
|
|
4925
4941
|
let iState = view.inputState, touch = e.targetTouches[0];
|
|
4942
|
+
iState.touchActive = true;
|
|
4926
4943
|
iState.lastTouchTime = Date.now();
|
|
4927
4944
|
if (touch) {
|
|
4928
4945
|
iState.lastTouchX = touch.clientX;
|
|
@@ -4933,6 +4950,9 @@ observers.touchstart = (view, e) => {
|
|
|
4933
4950
|
observers.touchmove = view => {
|
|
4934
4951
|
view.inputState.setSelectionOrigin("select.pointer");
|
|
4935
4952
|
};
|
|
4953
|
+
observers.touchend = (view, e) => {
|
|
4954
|
+
view.inputState.touchActive = false;
|
|
4955
|
+
};
|
|
4936
4956
|
handlers.mousedown = (view, event) => {
|
|
4937
4957
|
view.observer.flush();
|
|
4938
4958
|
if (view.inputState.lastTouchTime > Date.now() - 2000)
|
|
@@ -8194,6 +8214,7 @@ class EditorView {
|
|
|
8194
8214
|
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
8195
8215
|
let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
|
|
8196
8216
|
if ((diff > 1 || diff < -1) &&
|
|
8217
|
+
!(browser.ios && this.inputState.lastIOSMomentumScroll > Date.now() - 100) &&
|
|
8197
8218
|
(scroll == this.scrollDOM || this.hasFocus ||
|
|
8198
8219
|
Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
|
|
8199
8220
|
scrollOffset = scrollOffset + diff;
|
|
@@ -8485,12 +8506,9 @@ class EditorView {
|
|
|
8485
8506
|
*/
|
|
8486
8507
|
coordsAtPos(pos, side = 1) {
|
|
8487
8508
|
this.readMeasured();
|
|
8488
|
-
let rect = this.docView.coordsAt(pos, side);
|
|
8489
|
-
if (!rect || rect.left == rect.right)
|
|
8490
|
-
return rect;
|
|
8491
8509
|
let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
|
|
8492
8510
|
let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
|
|
8493
|
-
return
|
|
8511
|
+
return this.docView.coordsAt(pos, side, span.dir == Direction.RTL);
|
|
8494
8512
|
}
|
|
8495
8513
|
/**
|
|
8496
8514
|
Return the rectangle around a given character. If `pos` does not
|