@codemirror/view 6.43.4 → 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,15 @@
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
+
1
13
  ## 6.43.4 (2026-06-27)
2
14
 
3
15
  ### 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);
@@ -3195,7 +3201,7 @@ class DocView {
3195
3201
  domAtPos(pos, side) {
3196
3202
  let { tile, offset } = this.tile.resolveBlock(pos, side);
3197
3203
  if (tile.isWidget())
3198
- return tile.domPosFor(pos, side);
3204
+ return tile.domPosFor(offset, side);
3199
3205
  return tile.domIn(offset, side);
3200
3206
  }
3201
3207
  inlineDOMNearPos(pos, side) {
@@ -3232,14 +3238,16 @@ class DocView {
3232
3238
  after = null;
3233
3239
  return before && side < 0 || !after ? before.domIn(beforeOff, side) : after.domIn(afterOff, side);
3234
3240
  }
3235
- 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) {
3236
3244
  let { tile, offset } = this.tile.resolveBlock(pos, side);
3237
3245
  if (tile.isWidget()) {
3238
3246
  if (tile.widget instanceof BlockGapWidget)
3239
3247
  return null;
3240
3248
  return tile.coordsInWidget(offset, side, true);
3241
3249
  }
3242
- return tile.coordsIn(offset, side);
3250
+ return tile.coordsIn(offset, side, rtl);
3243
3251
  }
3244
3252
  lineAt(pos, side) {
3245
3253
  let { tile } = this.tile.resolveBlock(pos, side);
@@ -3413,7 +3421,6 @@ class DocView {
3413
3421
  this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
3414
3422
  }
3415
3423
  scrollIntoView(target) {
3416
- var _a;
3417
3424
  if (target.isSnapshot) {
3418
3425
  let ref = this.view.viewState.lineBlockAt(target.range.head);
3419
3426
  this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
@@ -3430,7 +3437,7 @@ class DocView {
3430
3437
  }
3431
3438
  }
3432
3439
  let { range } = target;
3433
- 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;
3434
3441
  if (!rect)
3435
3442
  return;
3436
3443
  if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
@@ -4472,6 +4479,7 @@ class InputState {
4472
4479
  this.view = view;
4473
4480
  this.lastKeyCode = 0;
4474
4481
  this.lastKeyTime = 0;
4482
+ this.touchActive = false;
4475
4483
  this.lastTouchTime = 0;
4476
4484
  this.lastTouchX = 0;
4477
4485
  this.lastTouchY = 0;
@@ -4483,6 +4491,10 @@ class InputState {
4483
4491
  // (after which we retroactively handle them and reset the DOM) to
4484
4492
  // avoid messing up the virtual keyboard state.
4485
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;
4486
4498
  // When enabled (>-1), tab presses are not given to key handlers,
4487
4499
  // leaving the browser's default behavior. If >0, the mode expires
4488
4500
  // at that timestamp, and any other keypress clears it.
@@ -4913,8 +4925,11 @@ function doPaste(view, input) {
4913
4925
  });
4914
4926
  }
4915
4927
  observers.scroll = view => {
4916
- view.inputState.lastScrollTop = view.scrollDOM.scrollTop;
4917
- 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();
4918
4933
  };
4919
4934
  observers.wheel = observers.mousewheel = view => {
4920
4935
  view.inputState.lastWheelEvent = Date.now();
@@ -4927,6 +4942,7 @@ handlers.keydown = (view, event) => {
4927
4942
  };
4928
4943
  observers.touchstart = (view, e) => {
4929
4944
  let iState = view.inputState, touch = e.targetTouches[0];
4945
+ iState.touchActive = true;
4930
4946
  iState.lastTouchTime = Date.now();
4931
4947
  if (touch) {
4932
4948
  iState.lastTouchX = touch.clientX;
@@ -4937,6 +4953,9 @@ observers.touchstart = (view, e) => {
4937
4953
  observers.touchmove = view => {
4938
4954
  view.inputState.setSelectionOrigin("select.pointer");
4939
4955
  };
4956
+ observers.touchend = (view, e) => {
4957
+ view.inputState.touchActive = false;
4958
+ };
4940
4959
  handlers.mousedown = (view, event) => {
4941
4960
  view.observer.flush();
4942
4961
  if (view.inputState.lastTouchTime > Date.now() - 2000)
@@ -8199,6 +8218,7 @@ class EditorView {
8199
8218
  this.viewState.lineBlockAt(scrollAnchorPos).top;
8200
8219
  let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
8201
8220
  if ((diff > 1 || diff < -1) &&
8221
+ !(browser.ios && this.inputState.lastIOSMomentumScroll > Date.now() - 100) &&
8202
8222
  (scroll == this.scrollDOM || this.hasFocus ||
8203
8223
  Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
8204
8224
  scrollOffset = scrollOffset + diff;
@@ -8490,12 +8510,9 @@ class EditorView {
8490
8510
  */
8491
8511
  coordsAtPos(pos, side = 1) {
8492
8512
  this.readMeasured();
8493
- let rect = this.docView.coordsAt(pos, side);
8494
- if (!rect || rect.left == rect.right)
8495
- return rect;
8496
8513
  let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
8497
8514
  let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
8498
- return flattenRect(rect, (span.dir == exports.Direction.LTR) == (side > 0));
8515
+ return this.docView.coordsAt(pos, side, span.dir == exports.Direction.RTL);
8499
8516
  }
8500
8517
  /**
8501
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);
@@ -3191,7 +3197,7 @@ class DocView {
3191
3197
  domAtPos(pos, side) {
3192
3198
  let { tile, offset } = this.tile.resolveBlock(pos, side);
3193
3199
  if (tile.isWidget())
3194
- return tile.domPosFor(pos, side);
3200
+ return tile.domPosFor(offset, side);
3195
3201
  return tile.domIn(offset, side);
3196
3202
  }
3197
3203
  inlineDOMNearPos(pos, side) {
@@ -3228,14 +3234,16 @@ class DocView {
3228
3234
  after = null;
3229
3235
  return before && side < 0 || !after ? before.domIn(beforeOff, side) : after.domIn(afterOff, side);
3230
3236
  }
3231
- 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) {
3232
3240
  let { tile, offset } = this.tile.resolveBlock(pos, side);
3233
3241
  if (tile.isWidget()) {
3234
3242
  if (tile.widget instanceof BlockGapWidget)
3235
3243
  return null;
3236
3244
  return tile.coordsInWidget(offset, side, true);
3237
3245
  }
3238
- return tile.coordsIn(offset, side);
3246
+ return tile.coordsIn(offset, side, rtl);
3239
3247
  }
3240
3248
  lineAt(pos, side) {
3241
3249
  let { tile } = this.tile.resolveBlock(pos, side);
@@ -3409,7 +3417,6 @@ class DocView {
3409
3417
  this.blockWrappers = this.view.state.facet(blockWrappers).map(v => typeof v == "function" ? v(this.view) : v);
3410
3418
  }
3411
3419
  scrollIntoView(target) {
3412
- var _a;
3413
3420
  if (target.isSnapshot) {
3414
3421
  let ref = this.view.viewState.lineBlockAt(target.range.head);
3415
3422
  this.view.scrollDOM.scrollTop = ref.top - target.yMargin;
@@ -3426,7 +3433,7 @@ class DocView {
3426
3433
  }
3427
3434
  }
3428
3435
  let { range } = target;
3429
- 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;
3430
3437
  if (!rect)
3431
3438
  return;
3432
3439
  if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
@@ -4468,6 +4475,7 @@ class InputState {
4468
4475
  this.view = view;
4469
4476
  this.lastKeyCode = 0;
4470
4477
  this.lastKeyTime = 0;
4478
+ this.touchActive = false;
4471
4479
  this.lastTouchTime = 0;
4472
4480
  this.lastTouchX = 0;
4473
4481
  this.lastTouchY = 0;
@@ -4479,6 +4487,10 @@ class InputState {
4479
4487
  // (after which we retroactively handle them and reset the DOM) to
4480
4488
  // avoid messing up the virtual keyboard state.
4481
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;
4482
4494
  // When enabled (>-1), tab presses are not given to key handlers,
4483
4495
  // leaving the browser's default behavior. If >0, the mode expires
4484
4496
  // at that timestamp, and any other keypress clears it.
@@ -4909,8 +4921,11 @@ function doPaste(view, input) {
4909
4921
  });
4910
4922
  }
4911
4923
  observers.scroll = view => {
4912
- view.inputState.lastScrollTop = view.scrollDOM.scrollTop;
4913
- 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();
4914
4929
  };
4915
4930
  observers.wheel = observers.mousewheel = view => {
4916
4931
  view.inputState.lastWheelEvent = Date.now();
@@ -4923,6 +4938,7 @@ handlers.keydown = (view, event) => {
4923
4938
  };
4924
4939
  observers.touchstart = (view, e) => {
4925
4940
  let iState = view.inputState, touch = e.targetTouches[0];
4941
+ iState.touchActive = true;
4926
4942
  iState.lastTouchTime = Date.now();
4927
4943
  if (touch) {
4928
4944
  iState.lastTouchX = touch.clientX;
@@ -4933,6 +4949,9 @@ observers.touchstart = (view, e) => {
4933
4949
  observers.touchmove = view => {
4934
4950
  view.inputState.setSelectionOrigin("select.pointer");
4935
4951
  };
4952
+ observers.touchend = (view, e) => {
4953
+ view.inputState.touchActive = false;
4954
+ };
4936
4955
  handlers.mousedown = (view, event) => {
4937
4956
  view.observer.flush();
4938
4957
  if (view.inputState.lastTouchTime > Date.now() - 2000)
@@ -8194,6 +8213,7 @@ class EditorView {
8194
8213
  this.viewState.lineBlockAt(scrollAnchorPos).top;
8195
8214
  let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
8196
8215
  if ((diff > 1 || diff < -1) &&
8216
+ !(browser.ios && this.inputState.lastIOSMomentumScroll > Date.now() - 100) &&
8197
8217
  (scroll == this.scrollDOM || this.hasFocus ||
8198
8218
  Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
8199
8219
  scrollOffset = scrollOffset + diff;
@@ -8485,12 +8505,9 @@ class EditorView {
8485
8505
  */
8486
8506
  coordsAtPos(pos, side = 1) {
8487
8507
  this.readMeasured();
8488
- let rect = this.docView.coordsAt(pos, side);
8489
- if (!rect || rect.left == rect.right)
8490
- return rect;
8491
8508
  let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
8492
8509
  let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
8493
- return flattenRect(rect, (span.dir == Direction.LTR) == (side > 0));
8510
+ return this.docView.coordsAt(pos, side, span.dir == Direction.RTL);
8494
8511
  }
8495
8512
  /**
8496
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.4",
3
+ "version": "6.43.5",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",