@codemirror/view 0.19.32 → 0.19.36

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/dist/index.js CHANGED
@@ -98,8 +98,7 @@ function windowRect(win) {
98
98
  return { left: 0, right: win.innerWidth,
99
99
  top: 0, bottom: win.innerHeight };
100
100
  }
101
- const ScrollSpace = 5;
102
- function scrollRectIntoView(dom, rect, side, center) {
101
+ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
103
102
  let doc = dom.ownerDocument, win = doc.defaultView;
104
103
  for (let cur = dom; cur;) {
105
104
  if (cur.nodeType == 1) { // Element
@@ -118,38 +117,42 @@ function scrollRectIntoView(dom, rect, side, center) {
118
117
  top: rect.top, bottom: rect.top + cur.clientHeight };
119
118
  }
120
119
  let moveX = 0, moveY = 0;
121
- if (center) {
120
+ if (y == "nearest") {
121
+ if (rect.top < bounding.top) {
122
+ moveY = -(bounding.top - rect.top + yMargin);
123
+ if (side > 0 && rect.bottom > bounding.bottom + moveY)
124
+ moveY = rect.bottom - bounding.bottom + moveY + yMargin;
125
+ }
126
+ else if (rect.bottom > bounding.bottom) {
127
+ moveY = rect.bottom - bounding.bottom + yMargin;
128
+ if (side < 0 && (rect.top - moveY) < bounding.top)
129
+ moveY = -(bounding.top + moveY - rect.top + yMargin);
130
+ }
131
+ }
132
+ else {
122
133
  let rectHeight = rect.bottom - rect.top, boundingHeight = bounding.bottom - bounding.top;
123
- let targetTop;
124
- if (rectHeight <= boundingHeight)
125
- targetTop = rect.top + rectHeight / 2 - boundingHeight / 2;
126
- else if (side < 0)
127
- targetTop = rect.top - ScrollSpace;
128
- else
129
- targetTop = rect.bottom + ScrollSpace - boundingHeight;
134
+ let targetTop = y == "center" && rectHeight <= boundingHeight ? rect.top + rectHeight / 2 - boundingHeight / 2 :
135
+ y == "start" || y == "center" && side < 0 ? rect.top - yMargin :
136
+ rect.bottom - boundingHeight + yMargin;
130
137
  moveY = targetTop - bounding.top;
131
- if (Math.abs(moveY) <= 1)
132
- moveY = 0;
133
- }
134
- else if (rect.top < bounding.top) {
135
- moveY = -(bounding.top - rect.top + ScrollSpace);
136
- if (side > 0 && rect.bottom > bounding.bottom + moveY)
137
- moveY = rect.bottom - bounding.bottom + moveY + ScrollSpace;
138
- }
139
- else if (rect.bottom > bounding.bottom) {
140
- moveY = rect.bottom - bounding.bottom + ScrollSpace;
141
- if (side < 0 && (rect.top - moveY) < bounding.top)
142
- moveY = -(bounding.top + moveY - rect.top + ScrollSpace);
143
138
  }
144
- if (rect.left < bounding.left) {
145
- moveX = -(bounding.left - rect.left + ScrollSpace);
146
- if (side > 0 && rect.right > bounding.right + moveX)
147
- moveX = rect.right - bounding.right + moveX + ScrollSpace;
139
+ if (x == "nearest") {
140
+ if (rect.left < bounding.left) {
141
+ moveX = -(bounding.left - rect.left + xMargin);
142
+ if (side > 0 && rect.right > bounding.right + moveX)
143
+ moveX = rect.right - bounding.right + moveX + xMargin;
144
+ }
145
+ else if (rect.right > bounding.right) {
146
+ moveX = rect.right - bounding.right + xMargin;
147
+ if (side < 0 && rect.left < bounding.left + moveX)
148
+ moveX = -(bounding.left + moveX - rect.left + xMargin);
149
+ }
148
150
  }
149
- else if (rect.right > bounding.right) {
150
- moveX = rect.right - bounding.right + ScrollSpace;
151
- if (side < 0 && rect.left < bounding.left + moveX)
152
- moveX = -(bounding.left + moveX - rect.left + ScrollSpace);
151
+ else {
152
+ let targetLeft = x == "center" ? rect.left + (rect.right - rect.left) / 2 - (bounding.right - bounding.left) / 2 :
153
+ (x == "start") == ltr ? rect.left - xMargin :
154
+ rect.right - (bounding.right - bounding.left) + xMargin;
155
+ moveX = targetLeft - bounding.left;
153
156
  }
154
157
  if (moveX || moveY) {
155
158
  if (top) {
@@ -173,7 +176,7 @@ function scrollRectIntoView(dom, rect, side, center) {
173
176
  if (top)
174
177
  break;
175
178
  cur = cur.assignedSlot || cur.parentNode;
176
- center = false;
179
+ x = y = "nearest";
177
180
  }
178
181
  else if (cur.nodeType == 11) { // A shadow root
179
182
  cur = cur.host;
@@ -260,6 +263,10 @@ function getRoot(node) {
260
263
  }
261
264
  return null;
262
265
  }
266
+ function clearAttributes(node) {
267
+ while (node.attributes.length)
268
+ node.removeAttributeNode(node.attributes[0]);
269
+ }
263
270
 
264
271
  class DOMPos {
265
272
  constructor(node, offset, precise = true) {
@@ -306,14 +313,16 @@ class ContentView {
306
313
  // given position.
307
314
  coordsAt(_pos, _side) { return null; }
308
315
  sync(track) {
309
- var _a;
310
316
  if (this.dirty & 2 /* Node */) {
311
317
  let parent = this.dom;
312
318
  let pos = parent.firstChild;
313
319
  for (let child of this.children) {
314
320
  if (child.dirty) {
315
- if (!child.dom && pos && !((_a = ContentView.get(pos)) === null || _a === void 0 ? void 0 : _a.parent))
316
- child.reuseDOM(pos);
321
+ if (!child.dom && pos) {
322
+ let contentView = ContentView.get(pos);
323
+ if (!contentView || !contentView.parent && contentView.constructor == child.constructor)
324
+ child.reuseDOM(pos);
325
+ }
317
326
  child.sync(track);
318
327
  child.dirty = 0 /* Not */;
319
328
  }
@@ -341,7 +350,7 @@ class ContentView {
341
350
  }
342
351
  }
343
352
  }
344
- reuseDOM(_dom) { return false; }
353
+ reuseDOM(_dom) { }
345
354
  localPosFromDOM(node, offset) {
346
355
  let after;
347
356
  if (node == this.dom) {
@@ -640,10 +649,8 @@ class TextView extends ContentView {
640
649
  }
641
650
  }
642
651
  reuseDOM(dom) {
643
- if (dom.nodeType != 3)
644
- return false;
645
- this.createDOM(dom);
646
- return true;
652
+ if (dom.nodeType == 3)
653
+ this.createDOM(dom);
647
654
  }
648
655
  merge(from, to, source) {
649
656
  if (source && (!(source instanceof TextView) || this.length - (to - from) + source.length > MaxJoinLen))
@@ -678,18 +685,26 @@ class MarkView extends ContentView {
678
685
  for (let ch of children)
679
686
  ch.setParent(this);
680
687
  }
681
- createDOM() {
682
- let dom = document.createElement(this.mark.tagName);
688
+ setAttrs(dom) {
689
+ clearAttributes(dom);
683
690
  if (this.mark.class)
684
691
  dom.className = this.mark.class;
685
692
  if (this.mark.attrs)
686
693
  for (let name in this.mark.attrs)
687
694
  dom.setAttribute(name, this.mark.attrs[name]);
688
- this.setDOM(dom);
695
+ return dom;
696
+ }
697
+ reuseDOM(node) {
698
+ if (node.nodeName == this.mark.tagName.toUpperCase()) {
699
+ this.setDOM(node);
700
+ this.dirty |= 4 /* Attrs */ | 2 /* Node */;
701
+ }
689
702
  }
690
703
  sync(track) {
691
- if (!this.dom || (this.dirty & 4 /* Attrs */))
692
- this.createDOM();
704
+ if (!this.dom)
705
+ this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
706
+ else if (this.dirty & 4 /* Attrs */)
707
+ this.setAttrs(this.dom);
693
708
  super.sync(track);
694
709
  }
695
710
  merge(from, to, source, _hasStart, openStart, openEnd) {
@@ -833,8 +848,7 @@ class WidgetView extends ContentView {
833
848
  }
834
849
  class CompositionView extends WidgetView {
835
850
  domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
836
- sync() { if (!this.dom)
837
- this.setDOM(this.widget.toDOM()); }
851
+ sync() { this.setDOM(this.widget.toDOM()); }
838
852
  localPosFromDOM(node, offset) {
839
853
  return !offset ? 0 : node.nodeType == 3 ? Math.min(offset, this.length) : this.length;
840
854
  }
@@ -1298,13 +1312,24 @@ class LineView extends ContentView {
1298
1312
  domAtPos(pos) {
1299
1313
  return inlineDOMAtPos(this.dom, this.children, pos);
1300
1314
  }
1315
+ reuseDOM(node) {
1316
+ if (node.nodeName == "DIV") {
1317
+ this.setDOM(node);
1318
+ this.dirty |= 4 /* Attrs */ | 2 /* Node */;
1319
+ }
1320
+ }
1301
1321
  sync(track) {
1302
1322
  var _a;
1303
- if (!this.dom || (this.dirty & 4 /* Attrs */)) {
1323
+ if (!this.dom) {
1304
1324
  this.setDOM(document.createElement("div"));
1305
1325
  this.dom.className = "cm-line";
1306
1326
  this.prevAttrs = this.attrs ? null : undefined;
1307
1327
  }
1328
+ else if (this.dirty & 4 /* Attrs */) {
1329
+ clearAttributes(this.dom);
1330
+ this.dom.className = "cm-line";
1331
+ this.prevAttrs = this.attrs ? null : undefined;
1332
+ }
1308
1333
  if (this.prevAttrs !== undefined) {
1309
1334
  updateAttrs(this.dom, this.prevAttrs, this.attrs);
1310
1335
  this.dom.classList.add("cm-line");
@@ -1343,16 +1368,17 @@ class LineView extends ContentView {
1343
1368
  become(_other) { return false; }
1344
1369
  get type() { return BlockType.Text; }
1345
1370
  static find(docView, pos) {
1346
- for (let i = 0, off = 0;; i++) {
1371
+ for (let i = 0, off = 0; i < docView.children.length; i++) {
1347
1372
  let block = docView.children[i], end = off + block.length;
1348
1373
  if (end >= pos) {
1349
1374
  if (block instanceof LineView)
1350
1375
  return block;
1351
- if (block.length)
1352
- return null;
1376
+ if (end > pos)
1377
+ break;
1353
1378
  }
1354
1379
  off = end + block.breakAfter;
1355
1380
  }
1381
+ return null;
1356
1382
  }
1357
1383
  }
1358
1384
  class BlockWidgetView extends ContentView {
@@ -1413,10 +1439,11 @@ class BlockWidgetView extends ContentView {
1413
1439
  }
1414
1440
 
1415
1441
  class ContentBuilder {
1416
- constructor(doc, pos, end) {
1442
+ constructor(doc, pos, end, disallowBlockEffectsBelow) {
1417
1443
  this.doc = doc;
1418
1444
  this.pos = pos;
1419
1445
  this.end = end;
1446
+ this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
1420
1447
  this.content = [];
1421
1448
  this.curLine = null;
1422
1449
  this.breakAtStart = 0;
@@ -1545,8 +1572,15 @@ class ContentBuilder {
1545
1572
  if (this.openStart < 0)
1546
1573
  this.openStart = openStart;
1547
1574
  }
1548
- static build(text, from, to, decorations) {
1549
- let builder = new ContentBuilder(text, from, to);
1575
+ filterPoint(from, to, value, index) {
1576
+ if (index >= this.disallowBlockEffectsBelow || !(value instanceof PointDecoration))
1577
+ return true;
1578
+ if (value.block)
1579
+ throw new RangeError("Block decorations may not be specified via plugins");
1580
+ return to < this.doc.lineAt(this.pos).to;
1581
+ }
1582
+ static build(text, from, to, decorations, pluginDecorationLength) {
1583
+ let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
1550
1584
  builder.openEnd = RangeSet.spans(decorations, from, to, builder);
1551
1585
  if (builder.openStart < 0)
1552
1586
  builder.openStart = builder.openEnd;
@@ -1576,12 +1610,27 @@ const mouseSelectionStyle = /*@__PURE__*/Facet.define();
1576
1610
  const exceptionSink = /*@__PURE__*/Facet.define();
1577
1611
  const updateListener = /*@__PURE__*/Facet.define();
1578
1612
  const inputHandler = /*@__PURE__*/Facet.define();
1613
+ // FIXME remove
1579
1614
  const scrollTo = /*@__PURE__*/StateEffect.define({
1580
1615
  map: (range, changes) => range.map(changes)
1581
1616
  });
1617
+ // FIXME remove
1582
1618
  const centerOn = /*@__PURE__*/StateEffect.define({
1583
1619
  map: (range, changes) => range.map(changes)
1584
1620
  });
1621
+ class ScrollTarget {
1622
+ constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5) {
1623
+ this.range = range;
1624
+ this.y = y;
1625
+ this.x = x;
1626
+ this.yMargin = yMargin;
1627
+ this.xMargin = xMargin;
1628
+ }
1629
+ map(changes) {
1630
+ return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin);
1631
+ }
1632
+ }
1633
+ const scrollIntoView = /*@__PURE__*/StateEffect.define({ map: (t, ch) => t.map(ch) });
1585
1634
  /**
1586
1635
  Log or report an unhandled exception in client code. Should
1587
1636
  probably only be used by extension code that allows client code to
@@ -1654,11 +1703,13 @@ This field can be used by plugins to provide
1654
1703
  **Note**: For reasons of data flow (plugins are only updated
1655
1704
  after the viewport is computed), decorations produced by plugins
1656
1705
  are _not_ taken into account when predicting the vertical layout
1657
- structure of the editor. Thus, things like large widgets or big
1658
- replacements (i.e. code folding) should be provided through the
1659
- state-level [`decorations` facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations),
1660
- not this plugin field. Specifically, replacing decorations that
1661
- cross line boundaries will break if provided through a plugin.
1706
+ structure of the editor. They **must not** introduce block
1707
+ widgets (that will raise an error) or replacing decorations that
1708
+ cover line breaks (these will be ignored if they occur). Such
1709
+ decorations, or others that cause a large amount of vertical
1710
+ size shift compared to the undecorated content, should be
1711
+ provided through the state-level [`decorations`
1712
+ facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
1662
1713
  */
1663
1714
  PluginField.decorations = /*@__PURE__*/PluginField.define();
1664
1715
  /**
@@ -1891,8 +1942,6 @@ class ViewUpdate {
1891
1942
  view.inputState.notifiedFocused = focus;
1892
1943
  this.flags |= 1 /* Focus */;
1893
1944
  }
1894
- if (this.docChanged)
1895
- this.flags |= 2 /* Height */;
1896
1945
  }
1897
1946
  /**
1898
1947
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
@@ -1903,14 +1952,15 @@ class ViewUpdate {
1903
1952
  return (this.flags & 4 /* Viewport */) > 0;
1904
1953
  }
1905
1954
  /**
1906
- Indicates whether the line height in the editor changed in this update.
1955
+ Indicates whether the height of an element in the editor changed
1956
+ in this update.
1907
1957
  */
1908
1958
  get heightChanged() {
1909
1959
  return (this.flags & 2 /* Height */) > 0;
1910
1960
  }
1911
1961
  /**
1912
- Returns true when the document changed or the size of the editor
1913
- or the lines or characters within it has changed.
1962
+ Returns true when the document was modified or the size of the
1963
+ editor, or elements within the editor, changed.
1914
1964
  */
1915
1965
  get geometryChanged() {
1916
1966
  return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
@@ -2328,6 +2378,7 @@ class DocView extends ContentView {
2328
2378
  this.view = view;
2329
2379
  this.compositionDeco = Decoration.none;
2330
2380
  this.decorations = [];
2381
+ this.pluginDecorationLength = 0;
2331
2382
  // Track a minimum width for the editor. When measuring sizes in
2332
2383
  // measureVisibleLineHeights, this is updated to point at the width
2333
2384
  // of a given element and its extent in the document. When a change
@@ -2349,7 +2400,8 @@ class DocView extends ContentView {
2349
2400
  this.setDOM(view.contentDOM);
2350
2401
  this.children = [new LineView];
2351
2402
  this.children[0].setParent(this);
2352
- this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], this.updateDeco(), 0);
2403
+ this.updateDeco();
2404
+ this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
2353
2405
  }
2354
2406
  get root() { return this.view.root; }
2355
2407
  get editorView() { return this.view; }
@@ -2388,7 +2440,7 @@ class DocView extends ContentView {
2388
2440
  return false;
2389
2441
  }
2390
2442
  else {
2391
- this.updateInner(changedRanges, deco, update.startState.doc.length);
2443
+ this.updateInner(changedRanges, update.startState.doc.length);
2392
2444
  if (update.transactions.length)
2393
2445
  this.lastUpdate = Date.now();
2394
2446
  return true;
@@ -2396,9 +2448,9 @@ class DocView extends ContentView {
2396
2448
  }
2397
2449
  // Used by update and the constructor do perform the actual DOM
2398
2450
  // update
2399
- updateInner(changes, deco, oldLength) {
2451
+ updateInner(changes, oldLength) {
2400
2452
  this.view.viewState.mustMeasureContent = true;
2401
- this.updateChildren(changes, deco, oldLength);
2453
+ this.updateChildren(changes, oldLength);
2402
2454
  let { observer } = this.view;
2403
2455
  observer.ignore(() => {
2404
2456
  // Lock the height during redrawing, since Chrome sometimes
@@ -2425,14 +2477,14 @@ class DocView extends ContentView {
2425
2477
  gaps.push(child.dom);
2426
2478
  observer.updateGaps(gaps);
2427
2479
  }
2428
- updateChildren(changes, deco, oldLength) {
2480
+ updateChildren(changes, oldLength) {
2429
2481
  let cursor = this.childCursor(oldLength);
2430
2482
  for (let i = changes.length - 1;; i--) {
2431
2483
  let next = i >= 0 ? changes[i] : null;
2432
2484
  if (!next)
2433
2485
  break;
2434
2486
  let { fromA, toA, fromB, toB } = next;
2435
- let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
2487
+ let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.pluginDecorationLength);
2436
2488
  let { i: toI, off: toOff } = cursor.findPos(toA, 1);
2437
2489
  let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
2438
2490
  replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
@@ -2651,15 +2703,18 @@ class DocView extends ContentView {
2651
2703
  return Decoration.set(deco);
2652
2704
  }
2653
2705
  updateDeco() {
2706
+ let pluginDecorations = this.view.pluginField(PluginField.decorations);
2707
+ this.pluginDecorationLength = pluginDecorations.length;
2654
2708
  return this.decorations = [
2655
- ...this.view.pluginField(PluginField.decorations),
2709
+ ...pluginDecorations,
2656
2710
  ...this.view.state.facet(decorations),
2657
2711
  this.compositionDeco,
2658
2712
  this.computeBlockGapDeco(),
2659
2713
  this.view.viewState.lineGapDeco
2660
2714
  ];
2661
2715
  }
2662
- scrollIntoView({ range, center }) {
2716
+ scrollIntoView(target) {
2717
+ let { range } = target;
2663
2718
  let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
2664
2719
  if (!rect)
2665
2720
  return;
@@ -2679,10 +2734,11 @@ class DocView extends ContentView {
2679
2734
  if (bottom != null)
2680
2735
  mBottom = Math.max(mBottom, bottom);
2681
2736
  }
2682
- scrollRectIntoView(this.view.scrollDOM, {
2737
+ let targetRect = {
2683
2738
  left: rect.left - mLeft, top: rect.top - mTop,
2684
2739
  right: rect.right + mRight, bottom: rect.bottom + mBottom
2685
- }, range.head < range.anchor ? -1 : 1, center);
2740
+ };
2741
+ scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == Direction.LTR);
2686
2742
  }
2687
2743
  }
2688
2744
  function betweenUneditable(pos) {
@@ -2943,12 +2999,8 @@ function domPosInText(node, x, y) {
2943
2999
  function posAtCoords(view, { x, y }, precise, bias = -1) {
2944
3000
  var _a;
2945
3001
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
2946
- let block, yOffset = y - docTop, { docHeight } = view.viewState;
2947
- if (yOffset < 0 || yOffset > docHeight) {
2948
- if (precise)
2949
- return null;
2950
- yOffset = yOffset < 0 ? 0 : docHeight;
2951
- }
3002
+ let block, { docHeight } = view.viewState;
3003
+ let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
2952
3004
  // Scan for a text block near the queried y position
2953
3005
  for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
2954
3006
  block = view.elementAtHeight(yOffset);
@@ -2969,20 +3021,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
2969
3021
  }
2970
3022
  y = docTop + yOffset;
2971
3023
  let lineStart = block.from;
2972
- // Clip x to the viewport sides
2973
- x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
2974
3024
  // If this is outside of the rendered viewport, we can't determine a position
2975
3025
  if (lineStart < view.viewport.from)
2976
- return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
3026
+ return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
2977
3027
  if (lineStart > view.viewport.to)
2978
- return view.viewport.to == view.state.doc.length ? view.state.doc.length : posAtCoordsImprecise(view, content, block, x, y);
3028
+ return view.viewport.to == view.state.doc.length ? view.state.doc.length :
3029
+ precise ? null : posAtCoordsImprecise(view, content, block, x, y);
2979
3030
  // Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
2980
3031
  let doc = view.dom.ownerDocument;
2981
- let element = (view.root.elementFromPoint ? view.root : doc).elementFromPoint(x, y);
3032
+ let root = view.root.elementFromPoint ? view.root : doc;
3033
+ let element = root.elementFromPoint(x, y);
3034
+ if (element && !view.contentDOM.contains(element))
3035
+ element = null;
3036
+ // If the element is unexpected, clip x at the sides of the content area and try again
3037
+ if (!element) {
3038
+ x = Math.max(content.left + 1, Math.min(content.right - 1, x));
3039
+ element = root.elementFromPoint(x, y);
3040
+ if (element && !view.contentDOM.contains(element))
3041
+ element = null;
3042
+ }
2982
3043
  // There's visible editor content under the point, so we can try
2983
3044
  // using caret(Position|Range)FromPoint as a shortcut
2984
3045
  let node, offset = -1;
2985
- if (element && view.contentDOM.contains(element) && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
3046
+ if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
2986
3047
  if (doc.caretPositionFromPoint) {
2987
3048
  let pos = doc.caretPositionFromPoint(x, y);
2988
3049
  if (pos)
@@ -3000,6 +3061,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3000
3061
  // No luck, do our own (potentially expensive) search
3001
3062
  if (!node || !view.docView.dom.contains(node)) {
3002
3063
  let line = LineView.find(view.docView, lineStart);
3064
+ if (!line)
3065
+ return yOffset > block.top + block.height / 2 ? block.to : block.from;
3003
3066
  ({ node, offset } = domPosAtCoords(line.dom, x, y));
3004
3067
  }
3005
3068
  return view.docView.posFromDOM(node, offset);
@@ -3463,7 +3526,7 @@ handlers.touchmove = view => {
3463
3526
  };
3464
3527
  handlers.mousedown = (view, event) => {
3465
3528
  view.observer.flush();
3466
- if (lastTouch > Date.now() - 2000)
3529
+ if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
3467
3530
  return; // Ignore touch interaction
3468
3531
  let style = null;
3469
3532
  for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
@@ -3585,9 +3648,9 @@ handlers.dragstart = (view, event) => {
3585
3648
  }
3586
3649
  };
3587
3650
  function dropText(view, event, text, direct) {
3588
- let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY });
3589
- if (dropPos == null || !text)
3651
+ if (!text)
3590
3652
  return;
3653
+ let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
3591
3654
  event.preventDefault();
3592
3655
  let { mouseSelection } = view.inputState;
3593
3656
  let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
@@ -4515,15 +4578,6 @@ class LineGapWidget extends WidgetType {
4515
4578
  }
4516
4579
  get estimatedHeight() { return this.vertical ? this.size : -1; }
4517
4580
  }
4518
- class ScrollTarget {
4519
- constructor(range, center = false) {
4520
- this.range = range;
4521
- this.center = center;
4522
- }
4523
- map(changes) {
4524
- return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.center);
4525
- }
4526
- }
4527
4581
  class ViewState {
4528
4582
  constructor(state) {
4529
4583
  this.state = state;
@@ -4704,9 +4758,9 @@ class ViewState {
4704
4758
  let { head } = scrollTarget.range, viewHeight = this.editorHeight;
4705
4759
  if (head < viewport.from || head > viewport.to) {
4706
4760
  let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
4707
- if (scrollTarget.center)
4761
+ if (scrollTarget.y == "center")
4708
4762
  topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
4709
- else if (head < viewport.from)
4763
+ else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
4710
4764
  topPos = block.top;
4711
4765
  else
4712
4766
  topPos = block.bottom - viewHeight;
@@ -5253,8 +5307,10 @@ class DOMObserver {
5253
5307
  // Deletions on IE11 fire their events in the wrong order, giving
5254
5308
  // us a selection change event before the DOM changes are
5255
5309
  // reported.
5256
- // (Selection.isCollapsed isn't reliable on IE)
5257
- if (browser.ie && browser.ie_version <= 11 && !view.state.selection.main.empty &&
5310
+ // Chrome Android has a similar issue when backspacing out a
5311
+ // selection (#645).
5312
+ if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
5313
+ // (Selection.isCollapsed isn't reliable on IE)
5258
5314
  sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
5259
5315
  this.flushSoon();
5260
5316
  else
@@ -5812,7 +5868,9 @@ class EditorView {
5812
5868
  if (e.is(scrollTo))
5813
5869
  scrollTarget = new ScrollTarget(e.value);
5814
5870
  else if (e.is(centerOn))
5815
- scrollTarget = new ScrollTarget(e.value, true);
5871
+ scrollTarget = new ScrollTarget(e.value, "center");
5872
+ else if (e.is(scrollIntoView))
5873
+ scrollTarget = e.value;
5816
5874
  }
5817
5875
  }
5818
5876
  this.viewState.update(update, scrollTarget);
@@ -6380,6 +6438,14 @@ class EditorView {
6380
6438
  this.destroyed = true;
6381
6439
  }
6382
6440
  /**
6441
+ Returns an effect that can be
6442
+ [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
6443
+ cause it to scroll the given position or range into view.
6444
+ */
6445
+ static scrollIntoView(pos, options = {}) {
6446
+ return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
6447
+ }
6448
+ /**
6383
6449
  Facet that can be used to add DOM event handlers. The value
6384
6450
  should be an object mapping event names to handler functions. The
6385
6451
  first such function to return true will be assumed to have handled
@@ -6433,11 +6499,15 @@ class EditorView {
6433
6499
  /**
6434
6500
  Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
6435
6501
  transaction to make it scroll the given range into view.
6502
+
6503
+ *Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
6436
6504
  */
6437
6505
  EditorView.scrollTo = scrollTo;
6438
6506
  /**
6439
6507
  Effect that makes the editor scroll the given range to the
6440
6508
  center of the visible view.
6509
+
6510
+ *Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
6441
6511
  */
6442
6512
  EditorView.centerOn = centerOn;
6443
6513
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "0.19.32",
3
+ "version": "0.19.36",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",
@@ -26,7 +26,7 @@
26
26
  "sideEffects": false,
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
- "@codemirror/rangeset": "^0.19.4",
29
+ "@codemirror/rangeset": "^0.19.5",
30
30
  "@codemirror/state": "^0.19.3",
31
31
  "@codemirror/text": "^0.19.0",
32
32
  "style-mod": "^4.0.0",