@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 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, left) {
518
- let x = left ? rect.left : rect.right;
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
- } // FIXME this is wrong in RTL text
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 flatten ? flattenRect(rect, flatten < 0) : rect || null;
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) { return this.dom.getBoundingClientRect(); }
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 = bucket.length - 1; j >= 0; j--) {
2532
- // Look at the most recently added items first (last-in, first-out)
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(pos, side);
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
- coordsAt(pos, side) {
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, (_a = range.assoc) !== null && _a !== void 0 ? _a : (range.empty ? 0 : range.head > range.anchor ? -1 : 1)), other;
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
- view.inputState.lastScrollTop = view.scrollDOM.scrollTop;
4916
- view.inputState.lastScrollLeft = view.scrollDOM.scrollLeft;
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 flattenRect(rect, (span.dir == exports.Direction.LTR) == (side > 0));
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, left) {
515
- let x = left ? rect.left : rect.right;
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
- } // FIXME this is wrong in RTL text
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 flatten ? flattenRect(rect, flatten < 0) : rect || null;
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) { return this.dom.getBoundingClientRect(); }
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 = bucket.length - 1; j >= 0; j--) {
2528
- // Look at the most recently added items first (last-in, first-out)
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(pos, side);
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
- coordsAt(pos, side) {
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, (_a = range.assoc) !== null && _a !== void 0 ? _a : (range.empty ? 0 : range.head > range.anchor ? -1 : 1)), other;
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
- view.inputState.lastScrollTop = view.scrollDOM.scrollTop;
4912
- view.inputState.lastScrollLeft = view.scrollDOM.scrollLeft;
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 flattenRect(rect, (span.dir == Direction.LTR) == (side > 0));
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.43.3",
3
+ "version": "6.43.5",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",