@codemirror/view 6.9.3 → 6.9.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,35 @@
1
+ ## 6.9.5 (2023-04-17)
2
+
3
+ ### Bug fixes
4
+
5
+ Avoid disrupting the composition in specific cases where Safari invasively changes the DOM structure in the middle of a composition.
6
+
7
+ Fix a bug that prevented `destroy` being called on hover tooltips.
8
+
9
+ Fix a bug where the editor could take focus when content changes required it to restore the DOM selection.
10
+
11
+ Fix height layout corruption caused by a division by zero.
12
+
13
+ Make sure styles targeting the editor's focus status are specific enough to not cause them to apply to editors nested inside another focused editor. This will require themes to adjust their selection background styles to match the new specificity.
14
+
15
+ ## 6.9.4 (2023-04-11)
16
+
17
+ ### Bug fixes
18
+
19
+ Make the editor scroll while dragging a selection near its sides, even if the cursor isn't outside the scrollable element.
20
+
21
+ Fix a bug that interrupted composition after widgets in some circumstances on Firefox.
22
+
23
+ Make sure the last change in a composition has its user event set to `input.type.compose`, even if the `compositionend` event fires before the changes are applied.
24
+
25
+ Make it possible to remove additional selection ranges by clicking on them with ctrl/cmd held, even if they aren't cursors.
26
+
27
+ Keep widget buffers between widgets and compositions, since removing them confuses IME on macOS Firefox.
28
+
29
+ Fix a bug where, for DOM changes that put the selection in the middle of the changed range, the editor incorrectly set its selection state.
30
+
31
+ Fix a bug where `coordsAtPos` could return a coordinates before the line break when querying a line-wrapped position with a positive `side`.
32
+
1
33
  ## 6.9.3 (2023-03-21)
2
34
 
3
35
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -520,6 +520,7 @@ class ContentView {
520
520
  static get(node) { return node.cmView; }
521
521
  get isEditable() { return true; }
522
522
  get isWidget() { return false; }
523
+ get isHidden() { return false; }
523
524
  merge(from, to, source, hasStart, openStart, openEnd) {
524
525
  return false;
525
526
  }
@@ -857,7 +858,7 @@ class WidgetView extends ContentView {
857
858
  become(other) {
858
859
  if (other.length == this.length && other instanceof WidgetView && other.side == this.side) {
859
860
  if (this.widget.constructor == other.widget.constructor) {
860
- if (!this.widget.eq(other.widget))
861
+ if (!this.widget.compare(other.widget))
861
862
  this.markDirty(true);
862
863
  if (this.dom && !this.prevWidget)
863
864
  this.prevWidget = this.widget;
@@ -879,7 +880,9 @@ class WidgetView extends ContentView {
879
880
  return text ? text.slice(start, start + this.length) : state.Text.empty;
880
881
  }
881
882
  domAtPos(pos) {
882
- return pos == 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom, pos == this.length);
883
+ return (this.length ? pos == 0 : this.side > 0)
884
+ ? DOMPos.before(this.dom)
885
+ : DOMPos.after(this.dom, pos == this.length);
883
886
  }
884
887
  domBoundsAround() { return null; }
885
888
  coordsAt(pos, side) {
@@ -895,6 +898,7 @@ class WidgetView extends ContentView {
895
898
  }
896
899
  get isEditable() { return false; }
897
900
  get isWidget() { return true; }
901
+ get isHidden() { return this.widget.isHidden; }
898
902
  destroy() {
899
903
  super.destroy();
900
904
  if (this.dom)
@@ -906,14 +910,14 @@ class CompositionView extends WidgetView {
906
910
  let { topView, text } = this.widget;
907
911
  if (!topView)
908
912
  return new DOMPos(text, Math.min(pos, text.nodeValue.length));
909
- return scanCompositionTree(pos, 0, topView, text, (v, p) => v.domAtPos(p), p => new DOMPos(text, Math.min(p, text.nodeValue.length)));
913
+ return scanCompositionTree(pos, 0, topView, text, this.length - topView.length, (v, p) => v.domAtPos(p), (text, p) => new DOMPos(text, Math.min(p, text.nodeValue.length)));
910
914
  }
911
915
  sync() { this.setDOM(this.widget.toDOM()); }
912
916
  localPosFromDOM(node, offset) {
913
917
  let { topView, text } = this.widget;
914
918
  if (!topView)
915
919
  return Math.min(offset, this.length);
916
- return posFromDOMInCompositionTree(node, offset, topView, text);
920
+ return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
917
921
  }
918
922
  ignoreMutation() { return false; }
919
923
  get overrideDOMText() { return null; }
@@ -921,7 +925,7 @@ class CompositionView extends WidgetView {
921
925
  let { topView, text } = this.widget;
922
926
  if (!topView)
923
927
  return textCoords(text, pos, side);
924
- return scanCompositionTree(pos, side, topView, text, (v, pos, side) => v.coordsAt(pos, side), (pos, side) => textCoords(text, pos, side));
928
+ return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
925
929
  }
926
930
  destroy() {
927
931
  var _a;
@@ -934,35 +938,68 @@ class CompositionView extends WidgetView {
934
938
  // Uses the old structure of a chunk of content view frozen for
935
939
  // composition to try and find a reasonable DOM location for the given
936
940
  // offset.
937
- function scanCompositionTree(pos, side, view, text, enterView, fromText) {
941
+ function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
938
942
  if (view instanceof MarkView) {
939
943
  for (let child = view.dom.firstChild; child; child = child.nextSibling) {
940
944
  let desc = ContentView.get(child);
941
- if (!desc)
942
- return fromText(pos, side);
943
- let hasComp = contains(child, text);
944
- let len = desc.length + (hasComp ? text.nodeValue.length : 0);
945
- if (pos < len || pos == len && desc.getSide() <= 0)
946
- return hasComp ? scanCompositionTree(pos, side, desc, text, enterView, fromText) : enterView(desc, pos, side);
947
- pos -= len;
945
+ if (!desc) {
946
+ let inner = scanCompositionNode(pos, side, child, fromText);
947
+ if (typeof inner != "number")
948
+ return inner;
949
+ pos = inner;
950
+ }
951
+ else {
952
+ let hasComp = contains(child, text);
953
+ let len = desc.length + (hasComp ? dLen : 0);
954
+ if (pos < len || pos == len && desc.getSide() <= 0)
955
+ return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
956
+ pos -= len;
957
+ }
948
958
  }
949
959
  return enterView(view, view.length, -1);
950
960
  }
951
961
  else if (view.dom == text) {
952
- return fromText(pos, side);
962
+ return fromText(text, pos, side);
953
963
  }
954
964
  else {
955
965
  return enterView(view, pos, side);
956
966
  }
957
967
  }
958
- function posFromDOMInCompositionTree(node, offset, view, text) {
968
+ function scanCompositionNode(pos, side, node, fromText) {
969
+ if (node.nodeType == 3) {
970
+ let len = node.nodeValue.length;
971
+ if (pos <= len)
972
+ return fromText(node, pos, side);
973
+ pos -= len;
974
+ }
975
+ else if (node.nodeType == 1 && node.contentEditable != "false") {
976
+ for (let child = node.firstChild; child; child = child.nextSibling) {
977
+ let inner = scanCompositionNode(pos, side, child, fromText);
978
+ if (typeof inner != "number")
979
+ return inner;
980
+ pos = inner;
981
+ }
982
+ }
983
+ return pos;
984
+ }
985
+ function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
959
986
  if (view instanceof MarkView) {
960
987
  let pos = 0;
961
- for (let child of view.children) {
962
- let hasComp = contains(child.dom, text);
963
- if (contains(child.dom, node))
964
- return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
965
- pos += hasComp ? text.nodeValue.length : child.length;
988
+ for (let child = view.dom.firstChild; child; child = child.nextSibling) {
989
+ let childView = ContentView.get(child);
990
+ if (childView) {
991
+ let hasComp = contains(child, text);
992
+ if (contains(child, node))
993
+ return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
994
+ : childView.localPosFromDOM(node, offset));
995
+ pos += childView.length + (hasComp ? dLen : 0);
996
+ }
997
+ else {
998
+ let inner = posFromDOMInOpaqueNode(node, offset, child);
999
+ if (inner.result != null)
1000
+ return pos + inner.result;
1001
+ pos += inner.size;
1002
+ }
966
1003
  }
967
1004
  }
968
1005
  else if (view.dom == text) {
@@ -970,6 +1007,27 @@ function posFromDOMInCompositionTree(node, offset, view, text) {
970
1007
  }
971
1008
  return view.localPosFromDOM(node, offset);
972
1009
  }
1010
+ function posFromDOMInOpaqueNode(node, offset, target) {
1011
+ if (target.nodeType == 3) {
1012
+ return node == target ? { result: offset } : { size: target.nodeValue.length };
1013
+ }
1014
+ else if (target.nodeType == 1 && target.contentEditable != "false") {
1015
+ let pos = 0;
1016
+ for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
1017
+ if (node == target && i == offset)
1018
+ return { result: pos };
1019
+ if (!child)
1020
+ return { size: pos };
1021
+ let inner = posFromDOMInOpaqueNode(node, offset, child);
1022
+ if (inner.result != null)
1023
+ return { result: offset + inner.result };
1024
+ pos += inner.size;
1025
+ }
1026
+ }
1027
+ else {
1028
+ return target.contains(node) ? { result: 0 } : { size: 0 };
1029
+ }
1030
+ }
973
1031
  // These are drawn around uneditable widgets to avoid a number of
974
1032
  // browser bugs that show up when the cursor is directly next to
975
1033
  // uneditable inline content.
@@ -1007,6 +1065,7 @@ class WidgetBufferView extends ContentView {
1007
1065
  get overrideDOMText() {
1008
1066
  return state.Text.empty;
1009
1067
  }
1068
+ get isHidden() { return true; }
1010
1069
  }
1011
1070
  TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
1012
1071
  function inlineSiblingRect(view, side) {
@@ -1080,7 +1139,8 @@ function coordsInChildren(view, pos, side) {
1080
1139
  if (child.children.length) {
1081
1140
  scan(child, pos - off);
1082
1141
  }
1083
- else if (!after && (end > pos || off == end && child.getSide() > 0)) {
1142
+ else if ((!after || after instanceof WidgetBufferView && side > 0) &&
1143
+ (end > pos || off == end && child.getSide() > 0)) {
1084
1144
  after = child;
1085
1145
  afterPos = pos - off;
1086
1146
  }
@@ -1194,6 +1254,10 @@ class WidgetType {
1194
1254
  */
1195
1255
  get customView() { return null; }
1196
1256
  /**
1257
+ @internal
1258
+ */
1259
+ get isHidden() { return false; }
1260
+ /**
1197
1261
  This is called when the an instance of the widget is removed
1198
1262
  from the editor view.
1199
1263
  */
@@ -1605,7 +1669,7 @@ class BlockWidgetView extends ContentView {
1605
1669
  become(other) {
1606
1670
  if (other instanceof BlockWidgetView && other.type == this.type &&
1607
1671
  other.widget.constructor == this.widget.constructor) {
1608
- if (!other.widget.eq(this.widget))
1672
+ if (!other.widget.compare(this.widget))
1609
1673
  this.markDirty(true);
1610
1674
  if (this.dom && !this.prevWidget)
1611
1675
  this.prevWidget = this.widget;
@@ -1736,10 +1800,11 @@ class ContentBuilder {
1736
1800
  }
1737
1801
  else {
1738
1802
  let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
1739
- let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length && (from < to || deco.startSide > 0);
1803
+ let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length &&
1804
+ (from < to || deco.startSide > 0);
1740
1805
  let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
1741
1806
  let line = this.getLine();
1742
- if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
1807
+ if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore && !view.isEditable)
1743
1808
  this.pendingBuffer = 0 /* Buf.No */;
1744
1809
  this.flushBuffer(active);
1745
1810
  if (cursorBefore) {
@@ -1793,6 +1858,7 @@ class NullWidget extends WidgetType {
1793
1858
  eq(other) { return other.tag == this.tag; }
1794
1859
  toDOM() { return document.createElement(this.tag); }
1795
1860
  updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
1861
+ get isHidden() { return true; }
1796
1862
  }
1797
1863
 
1798
1864
  const clickAddsSelectionRange = state.Facet.define();
@@ -2636,7 +2702,10 @@ class DocView extends ContentView {
2636
2702
  updateSelection(mustRead = false, fromPointer = false) {
2637
2703
  if (mustRead || !this.view.observer.selectionRange.focusNode)
2638
2704
  this.view.observer.readSelectionRange();
2639
- if (!(fromPointer || this.mayControlSelection()))
2705
+ let activeElt = this.view.root.activeElement, focused = activeElt == this.dom;
2706
+ let selectionNotFocus = !focused &&
2707
+ hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));
2708
+ if (!(focused || fromPointer || selectionNotFocus))
2640
2709
  return;
2641
2710
  let force = this.forceSelection;
2642
2711
  this.forceSelection = false;
@@ -2646,7 +2715,7 @@ class DocView extends ContentView {
2646
2715
  let head = main.empty ? anchor : this.domAtPos(main.head);
2647
2716
  // Always reset on Firefox when next to an uneditable node to
2648
2717
  // avoid invisible cursor bugs (#111)
2649
- if (browser.gecko && main.empty && betweenUneditable(anchor)) {
2718
+ if (browser.gecko && main.empty && !this.compositionDeco.size && betweenUneditable(anchor)) {
2650
2719
  let dummy = document.createTextNode("");
2651
2720
  this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
2652
2721
  anchor = head = new DOMPos(dummy, 0);
@@ -2706,6 +2775,11 @@ class DocView extends ContentView {
2706
2775
  rawSel.removeAllRanges();
2707
2776
  rawSel.addRange(range);
2708
2777
  }
2778
+ if (selectionNotFocus && this.view.root.activeElement == this.dom) {
2779
+ this.dom.blur();
2780
+ if (activeElt)
2781
+ activeElt.focus();
2782
+ }
2709
2783
  });
2710
2784
  this.view.observer.setSelectionRange(anchor, head);
2711
2785
  }
@@ -2739,11 +2813,6 @@ class DocView extends ContentView {
2739
2813
  if (view.docView.posFromDOM(newRange.anchorNode, newRange.anchorOffset) != cursor.from)
2740
2814
  sel.collapse(anchorNode, anchorOffset);
2741
2815
  }
2742
- mayControlSelection() {
2743
- let active = this.view.root.activeElement;
2744
- return active == this.dom ||
2745
- hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
2746
- }
2747
2816
  nearest(dom) {
2748
2817
  for (let cur = dom; cur;) {
2749
2818
  let domView = ContentView.get(cur);
@@ -3440,7 +3509,15 @@ class InputState {
3440
3509
  // first, false means first has already been marked for this
3441
3510
  // composition)
3442
3511
  this.compositionFirstChange = null;
3512
+ // End time of the previous composition
3443
3513
  this.compositionEndedAt = 0;
3514
+ // Used in a kludge to detect when an Enter keypress should be
3515
+ // considered part of the composition on Safari, which fires events
3516
+ // in the wrong order
3517
+ this.compositionPendingKey = false;
3518
+ // Used to categorize changes as part of a composition, even when
3519
+ // the mutation events fire shortly after the compositionend event
3520
+ this.compositionPendingChange = false;
3444
3521
  this.mouseSelection = null;
3445
3522
  let handleEvent = (handler, event) => {
3446
3523
  if (this.ignoreDuringComposition(event))
@@ -3597,8 +3674,8 @@ class InputState {
3597
3674
  // compositionend and keydown events are sometimes emitted in the
3598
3675
  // wrong order. The key event should still be ignored, even when
3599
3676
  // it happens after the compositionend event.
3600
- if (browser.safari && !browser.ios && Date.now() - this.compositionEndedAt < 100) {
3601
- this.compositionEndedAt = 0;
3677
+ if (browser.safari && !browser.ios && this.compositionPendingKey && Date.now() - this.compositionEndedAt < 100) {
3678
+ this.compositionPendingKey = false;
3602
3679
  return true;
3603
3680
  }
3604
3681
  return false;
@@ -3630,8 +3707,9 @@ const PendingKeys = [
3630
3707
  const EmacsyPendingKeys = "dthko";
3631
3708
  // Key codes for modifier keys
3632
3709
  const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
3710
+ const dragScrollMargin = 6;
3633
3711
  function dragScrollSpeed(dist) {
3634
- return dist * 0.7 + 8;
3712
+ return Math.max(0, dist) * 0.7 + 8;
3635
3713
  }
3636
3714
  class MouseSelection {
3637
3715
  constructor(view, startEvent, style, mustSelect) {
@@ -3668,13 +3746,13 @@ class MouseSelection {
3668
3746
  let sx = 0, sy = 0;
3669
3747
  let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
3670
3748
  || { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
3671
- if (event.clientX <= rect.left)
3749
+ if (event.clientX <= rect.left + dragScrollMargin)
3672
3750
  sx = -dragScrollSpeed(rect.left - event.clientX);
3673
- else if (event.clientX >= rect.right)
3751
+ else if (event.clientX >= rect.right - dragScrollMargin)
3674
3752
  sx = dragScrollSpeed(event.clientX - rect.right);
3675
- if (event.clientY <= rect.top)
3753
+ if (event.clientY <= rect.top + dragScrollMargin)
3676
3754
  sy = -dragScrollSpeed(rect.top - event.clientY);
3677
- else if (event.clientY >= rect.bottom)
3755
+ else if (event.clientY >= rect.bottom - dragScrollMargin)
3678
3756
  sy = dragScrollSpeed(event.clientY - rect.bottom);
3679
3757
  this.setScrollSpeed(sx, sy);
3680
3758
  }
@@ -3921,7 +3999,7 @@ function basicMouseSelection(view, event) {
3921
3999
  }
3922
4000
  },
3923
4001
  get(event, extend, multiple) {
3924
- let cur = queryPos(view, event);
4002
+ let cur = queryPos(view, event), removed;
3925
4003
  let range = rangeForClick(view, cur.pos, cur.bias, type);
3926
4004
  if (start.pos != cur.pos && !extend) {
3927
4005
  let startRange = rangeForClick(view, start.pos, start.bias, type);
@@ -3930,8 +4008,8 @@ function basicMouseSelection(view, event) {
3930
4008
  }
3931
4009
  if (extend)
3932
4010
  return startSel.replaceRange(startSel.main.extend(range.from, range.to));
3933
- else if (multiple && startSel.ranges.length > 1 && startSel.ranges.some(r => r.eq(range)))
3934
- return removeRange(startSel, range);
4011
+ else if (multiple && type == 1 && startSel.ranges.length > 1 && (removed = removeRangeAround(startSel, cur.pos)))
4012
+ return removed;
3935
4013
  else if (multiple)
3936
4014
  return startSel.addRange(range);
3937
4015
  else
@@ -3939,11 +4017,13 @@ function basicMouseSelection(view, event) {
3939
4017
  }
3940
4018
  };
3941
4019
  }
3942
- function removeRange(sel, range) {
3943
- for (let i = 0;; i++) {
3944
- if (sel.ranges[i].eq(range))
4020
+ function removeRangeAround(sel, pos) {
4021
+ for (let i = 0; i < sel.ranges.length; i++) {
4022
+ let { from, to } = sel.ranges[i];
4023
+ if (from <= pos && to >= pos)
3945
4024
  return state.EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
3946
4025
  }
4026
+ return null;
3947
4027
  }
3948
4028
  handlers.dragstart = (view, event) => {
3949
4029
  let { selection: { main } } = view.state;
@@ -4120,6 +4200,8 @@ handlers.compositionstart = handlers.compositionupdate = view => {
4120
4200
  handlers.compositionend = view => {
4121
4201
  view.inputState.composing = -1;
4122
4202
  view.inputState.compositionEndedAt = Date.now();
4203
+ view.inputState.compositionPendingKey = true;
4204
+ view.inputState.compositionPendingChange = view.observer.pendingRecords().length > 0;
4123
4205
  view.inputState.compositionFirstChange = null;
4124
4206
  if (browser.chrome && browser.android)
4125
4207
  view.observer.flushSoon();
@@ -4467,7 +4549,8 @@ class HeightMapGap extends HeightMap {
4467
4549
  if (oracle.lineWrapping) {
4468
4550
  let totalPerLine = Math.min(this.height, oracle.lineHeight * lines);
4469
4551
  perLine = totalPerLine / lines;
4470
- perChar = (this.height - totalPerLine) / (this.length - lines - 1);
4552
+ if (this.length > lines + 1)
4553
+ perChar = (this.height - totalPerLine) / (this.length - lines - 1);
4471
4554
  }
4472
4555
  else {
4473
4556
  perLine = this.height / lines;
@@ -5483,16 +5566,16 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
5483
5566
  "&dark .cm-selectionBackground": {
5484
5567
  background: "#222"
5485
5568
  },
5486
- "&light.cm-focused .cm-selectionBackground": {
5569
+ "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
5487
5570
  background: "#d7d4f0"
5488
5571
  },
5489
- "&dark.cm-focused .cm-selectionBackground": {
5572
+ "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
5490
5573
  background: "#233"
5491
5574
  },
5492
5575
  ".cm-cursorLayer": {
5493
5576
  pointerEvents: "none"
5494
5577
  },
5495
- "&.cm-focused .cm-cursorLayer": {
5578
+ "&.cm-focused > .cm-scroller > .cm-cursorLayer": {
5496
5579
  animation: "steps(1) cm-blink 1.2s infinite"
5497
5580
  },
5498
5581
  // Two animations defined so that we can switch between them to
@@ -5514,7 +5597,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
5514
5597
  ".cm-dropCursor": {
5515
5598
  position: "absolute"
5516
5599
  },
5517
- "&.cm-focused .cm-cursor": {
5600
+ "&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor": {
5518
5601
  display: "block"
5519
5602
  },
5520
5603
  "&light .cm-activeLine": { backgroundColor: "#cceeff44" },
@@ -5775,8 +5858,7 @@ function applyDOMChange(view, domChange) {
5775
5858
  }
5776
5859
  else {
5777
5860
  let changes = startState.changes(change);
5778
- let mainSel = newSel && !startState.selection.main.eq(newSel.main) && newSel.main.to <= changes.newLength
5779
- ? newSel.main : undefined;
5861
+ let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
5780
5862
  // Try to apply a composition change to all cursors
5781
5863
  if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
5782
5864
  change.to <= sel.to && change.to >= sel.to - 10) {
@@ -5810,7 +5892,9 @@ function applyDOMChange(view, domChange) {
5810
5892
  }
5811
5893
  }
5812
5894
  let userEvent = "input.type";
5813
- if (view.composing) {
5895
+ if (view.composing ||
5896
+ view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
5897
+ view.inputState.compositionPendingChange = false;
5814
5898
  userEvent += ".compose";
5815
5899
  if (view.inputState.compositionFirstChange) {
5816
5900
  userEvent += ".start";
@@ -6186,10 +6270,13 @@ class DOMObserver {
6186
6270
  }
6187
6271
  this.flush();
6188
6272
  }
6189
- processRecords() {
6190
- let records = this.queue;
6273
+ pendingRecords() {
6191
6274
  for (let mut of this.observer.takeRecords())
6192
- records.push(mut);
6275
+ this.queue.push(mut);
6276
+ return this.queue;
6277
+ }
6278
+ processRecords() {
6279
+ let records = this.pendingRecords();
6193
6280
  if (records.length)
6194
6281
  this.queue = [];
6195
6282
  let from = -1, to = -1, typeOver = false;
@@ -8782,6 +8869,11 @@ class HoverTooltipHost {
8782
8869
  update(update) {
8783
8870
  this.manager.update(update);
8784
8871
  }
8872
+ destroy() {
8873
+ var _a;
8874
+ for (let t of this.manager.tooltipViews)
8875
+ (_a = t.destroy) === null || _a === void 0 ? void 0 : _a.call(t);
8876
+ }
8785
8877
  }
8786
8878
  const showHoverTooltipHost = showTooltip.compute([showHoverTooltip], state => {
8787
8879
  let tooltips = state.facet(showHoverTooltip).filter(t => t);
package/dist/index.js CHANGED
@@ -516,6 +516,7 @@ class ContentView {
516
516
  static get(node) { return node.cmView; }
517
517
  get isEditable() { return true; }
518
518
  get isWidget() { return false; }
519
+ get isHidden() { return false; }
519
520
  merge(from, to, source, hasStart, openStart, openEnd) {
520
521
  return false;
521
522
  }
@@ -853,7 +854,7 @@ class WidgetView extends ContentView {
853
854
  become(other) {
854
855
  if (other.length == this.length && other instanceof WidgetView && other.side == this.side) {
855
856
  if (this.widget.constructor == other.widget.constructor) {
856
- if (!this.widget.eq(other.widget))
857
+ if (!this.widget.compare(other.widget))
857
858
  this.markDirty(true);
858
859
  if (this.dom && !this.prevWidget)
859
860
  this.prevWidget = this.widget;
@@ -875,7 +876,9 @@ class WidgetView extends ContentView {
875
876
  return text ? text.slice(start, start + this.length) : Text.empty;
876
877
  }
877
878
  domAtPos(pos) {
878
- return pos == 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom, pos == this.length);
879
+ return (this.length ? pos == 0 : this.side > 0)
880
+ ? DOMPos.before(this.dom)
881
+ : DOMPos.after(this.dom, pos == this.length);
879
882
  }
880
883
  domBoundsAround() { return null; }
881
884
  coordsAt(pos, side) {
@@ -891,6 +894,7 @@ class WidgetView extends ContentView {
891
894
  }
892
895
  get isEditable() { return false; }
893
896
  get isWidget() { return true; }
897
+ get isHidden() { return this.widget.isHidden; }
894
898
  destroy() {
895
899
  super.destroy();
896
900
  if (this.dom)
@@ -902,14 +906,14 @@ class CompositionView extends WidgetView {
902
906
  let { topView, text } = this.widget;
903
907
  if (!topView)
904
908
  return new DOMPos(text, Math.min(pos, text.nodeValue.length));
905
- return scanCompositionTree(pos, 0, topView, text, (v, p) => v.domAtPos(p), p => new DOMPos(text, Math.min(p, text.nodeValue.length)));
909
+ return scanCompositionTree(pos, 0, topView, text, this.length - topView.length, (v, p) => v.domAtPos(p), (text, p) => new DOMPos(text, Math.min(p, text.nodeValue.length)));
906
910
  }
907
911
  sync() { this.setDOM(this.widget.toDOM()); }
908
912
  localPosFromDOM(node, offset) {
909
913
  let { topView, text } = this.widget;
910
914
  if (!topView)
911
915
  return Math.min(offset, this.length);
912
- return posFromDOMInCompositionTree(node, offset, topView, text);
916
+ return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
913
917
  }
914
918
  ignoreMutation() { return false; }
915
919
  get overrideDOMText() { return null; }
@@ -917,7 +921,7 @@ class CompositionView extends WidgetView {
917
921
  let { topView, text } = this.widget;
918
922
  if (!topView)
919
923
  return textCoords(text, pos, side);
920
- return scanCompositionTree(pos, side, topView, text, (v, pos, side) => v.coordsAt(pos, side), (pos, side) => textCoords(text, pos, side));
924
+ return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
921
925
  }
922
926
  destroy() {
923
927
  var _a;
@@ -930,35 +934,68 @@ class CompositionView extends WidgetView {
930
934
  // Uses the old structure of a chunk of content view frozen for
931
935
  // composition to try and find a reasonable DOM location for the given
932
936
  // offset.
933
- function scanCompositionTree(pos, side, view, text, enterView, fromText) {
937
+ function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
934
938
  if (view instanceof MarkView) {
935
939
  for (let child = view.dom.firstChild; child; child = child.nextSibling) {
936
940
  let desc = ContentView.get(child);
937
- if (!desc)
938
- return fromText(pos, side);
939
- let hasComp = contains(child, text);
940
- let len = desc.length + (hasComp ? text.nodeValue.length : 0);
941
- if (pos < len || pos == len && desc.getSide() <= 0)
942
- return hasComp ? scanCompositionTree(pos, side, desc, text, enterView, fromText) : enterView(desc, pos, side);
943
- pos -= len;
941
+ if (!desc) {
942
+ let inner = scanCompositionNode(pos, side, child, fromText);
943
+ if (typeof inner != "number")
944
+ return inner;
945
+ pos = inner;
946
+ }
947
+ else {
948
+ let hasComp = contains(child, text);
949
+ let len = desc.length + (hasComp ? dLen : 0);
950
+ if (pos < len || pos == len && desc.getSide() <= 0)
951
+ return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
952
+ pos -= len;
953
+ }
944
954
  }
945
955
  return enterView(view, view.length, -1);
946
956
  }
947
957
  else if (view.dom == text) {
948
- return fromText(pos, side);
958
+ return fromText(text, pos, side);
949
959
  }
950
960
  else {
951
961
  return enterView(view, pos, side);
952
962
  }
953
963
  }
954
- function posFromDOMInCompositionTree(node, offset, view, text) {
964
+ function scanCompositionNode(pos, side, node, fromText) {
965
+ if (node.nodeType == 3) {
966
+ let len = node.nodeValue.length;
967
+ if (pos <= len)
968
+ return fromText(node, pos, side);
969
+ pos -= len;
970
+ }
971
+ else if (node.nodeType == 1 && node.contentEditable != "false") {
972
+ for (let child = node.firstChild; child; child = child.nextSibling) {
973
+ let inner = scanCompositionNode(pos, side, child, fromText);
974
+ if (typeof inner != "number")
975
+ return inner;
976
+ pos = inner;
977
+ }
978
+ }
979
+ return pos;
980
+ }
981
+ function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
955
982
  if (view instanceof MarkView) {
956
983
  let pos = 0;
957
- for (let child of view.children) {
958
- let hasComp = contains(child.dom, text);
959
- if (contains(child.dom, node))
960
- return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
961
- pos += hasComp ? text.nodeValue.length : child.length;
984
+ for (let child = view.dom.firstChild; child; child = child.nextSibling) {
985
+ let childView = ContentView.get(child);
986
+ if (childView) {
987
+ let hasComp = contains(child, text);
988
+ if (contains(child, node))
989
+ return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
990
+ : childView.localPosFromDOM(node, offset));
991
+ pos += childView.length + (hasComp ? dLen : 0);
992
+ }
993
+ else {
994
+ let inner = posFromDOMInOpaqueNode(node, offset, child);
995
+ if (inner.result != null)
996
+ return pos + inner.result;
997
+ pos += inner.size;
998
+ }
962
999
  }
963
1000
  }
964
1001
  else if (view.dom == text) {
@@ -966,6 +1003,27 @@ function posFromDOMInCompositionTree(node, offset, view, text) {
966
1003
  }
967
1004
  return view.localPosFromDOM(node, offset);
968
1005
  }
1006
+ function posFromDOMInOpaqueNode(node, offset, target) {
1007
+ if (target.nodeType == 3) {
1008
+ return node == target ? { result: offset } : { size: target.nodeValue.length };
1009
+ }
1010
+ else if (target.nodeType == 1 && target.contentEditable != "false") {
1011
+ let pos = 0;
1012
+ for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
1013
+ if (node == target && i == offset)
1014
+ return { result: pos };
1015
+ if (!child)
1016
+ return { size: pos };
1017
+ let inner = posFromDOMInOpaqueNode(node, offset, child);
1018
+ if (inner.result != null)
1019
+ return { result: offset + inner.result };
1020
+ pos += inner.size;
1021
+ }
1022
+ }
1023
+ else {
1024
+ return target.contains(node) ? { result: 0 } : { size: 0 };
1025
+ }
1026
+ }
969
1027
  // These are drawn around uneditable widgets to avoid a number of
970
1028
  // browser bugs that show up when the cursor is directly next to
971
1029
  // uneditable inline content.
@@ -1003,6 +1061,7 @@ class WidgetBufferView extends ContentView {
1003
1061
  get overrideDOMText() {
1004
1062
  return Text.empty;
1005
1063
  }
1064
+ get isHidden() { return true; }
1006
1065
  }
1007
1066
  TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
1008
1067
  function inlineSiblingRect(view, side) {
@@ -1076,7 +1135,8 @@ function coordsInChildren(view, pos, side) {
1076
1135
  if (child.children.length) {
1077
1136
  scan(child, pos - off);
1078
1137
  }
1079
- else if (!after && (end > pos || off == end && child.getSide() > 0)) {
1138
+ else if ((!after || after instanceof WidgetBufferView && side > 0) &&
1139
+ (end > pos || off == end && child.getSide() > 0)) {
1080
1140
  after = child;
1081
1141
  afterPos = pos - off;
1082
1142
  }
@@ -1190,6 +1250,10 @@ class WidgetType {
1190
1250
  */
1191
1251
  get customView() { return null; }
1192
1252
  /**
1253
+ @internal
1254
+ */
1255
+ get isHidden() { return false; }
1256
+ /**
1193
1257
  This is called when the an instance of the widget is removed
1194
1258
  from the editor view.
1195
1259
  */
@@ -1600,7 +1664,7 @@ class BlockWidgetView extends ContentView {
1600
1664
  become(other) {
1601
1665
  if (other instanceof BlockWidgetView && other.type == this.type &&
1602
1666
  other.widget.constructor == this.widget.constructor) {
1603
- if (!other.widget.eq(this.widget))
1667
+ if (!other.widget.compare(this.widget))
1604
1668
  this.markDirty(true);
1605
1669
  if (this.dom && !this.prevWidget)
1606
1670
  this.prevWidget = this.widget;
@@ -1731,10 +1795,11 @@ class ContentBuilder {
1731
1795
  }
1732
1796
  else {
1733
1797
  let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
1734
- let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length && (from < to || deco.startSide > 0);
1798
+ let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length &&
1799
+ (from < to || deco.startSide > 0);
1735
1800
  let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
1736
1801
  let line = this.getLine();
1737
- if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
1802
+ if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore && !view.isEditable)
1738
1803
  this.pendingBuffer = 0 /* Buf.No */;
1739
1804
  this.flushBuffer(active);
1740
1805
  if (cursorBefore) {
@@ -1788,6 +1853,7 @@ class NullWidget extends WidgetType {
1788
1853
  eq(other) { return other.tag == this.tag; }
1789
1854
  toDOM() { return document.createElement(this.tag); }
1790
1855
  updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
1856
+ get isHidden() { return true; }
1791
1857
  }
1792
1858
 
1793
1859
  const clickAddsSelectionRange = /*@__PURE__*/Facet.define();
@@ -2630,7 +2696,10 @@ class DocView extends ContentView {
2630
2696
  updateSelection(mustRead = false, fromPointer = false) {
2631
2697
  if (mustRead || !this.view.observer.selectionRange.focusNode)
2632
2698
  this.view.observer.readSelectionRange();
2633
- if (!(fromPointer || this.mayControlSelection()))
2699
+ let activeElt = this.view.root.activeElement, focused = activeElt == this.dom;
2700
+ let selectionNotFocus = !focused &&
2701
+ hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));
2702
+ if (!(focused || fromPointer || selectionNotFocus))
2634
2703
  return;
2635
2704
  let force = this.forceSelection;
2636
2705
  this.forceSelection = false;
@@ -2640,7 +2709,7 @@ class DocView extends ContentView {
2640
2709
  let head = main.empty ? anchor : this.domAtPos(main.head);
2641
2710
  // Always reset on Firefox when next to an uneditable node to
2642
2711
  // avoid invisible cursor bugs (#111)
2643
- if (browser.gecko && main.empty && betweenUneditable(anchor)) {
2712
+ if (browser.gecko && main.empty && !this.compositionDeco.size && betweenUneditable(anchor)) {
2644
2713
  let dummy = document.createTextNode("");
2645
2714
  this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
2646
2715
  anchor = head = new DOMPos(dummy, 0);
@@ -2700,6 +2769,11 @@ class DocView extends ContentView {
2700
2769
  rawSel.removeAllRanges();
2701
2770
  rawSel.addRange(range);
2702
2771
  }
2772
+ if (selectionNotFocus && this.view.root.activeElement == this.dom) {
2773
+ this.dom.blur();
2774
+ if (activeElt)
2775
+ activeElt.focus();
2776
+ }
2703
2777
  });
2704
2778
  this.view.observer.setSelectionRange(anchor, head);
2705
2779
  }
@@ -2733,11 +2807,6 @@ class DocView extends ContentView {
2733
2807
  if (view.docView.posFromDOM(newRange.anchorNode, newRange.anchorOffset) != cursor.from)
2734
2808
  sel.collapse(anchorNode, anchorOffset);
2735
2809
  }
2736
- mayControlSelection() {
2737
- let active = this.view.root.activeElement;
2738
- return active == this.dom ||
2739
- hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
2740
- }
2741
2810
  nearest(dom) {
2742
2811
  for (let cur = dom; cur;) {
2743
2812
  let domView = ContentView.get(cur);
@@ -3434,7 +3503,15 @@ class InputState {
3434
3503
  // first, false means first has already been marked for this
3435
3504
  // composition)
3436
3505
  this.compositionFirstChange = null;
3506
+ // End time of the previous composition
3437
3507
  this.compositionEndedAt = 0;
3508
+ // Used in a kludge to detect when an Enter keypress should be
3509
+ // considered part of the composition on Safari, which fires events
3510
+ // in the wrong order
3511
+ this.compositionPendingKey = false;
3512
+ // Used to categorize changes as part of a composition, even when
3513
+ // the mutation events fire shortly after the compositionend event
3514
+ this.compositionPendingChange = false;
3438
3515
  this.mouseSelection = null;
3439
3516
  let handleEvent = (handler, event) => {
3440
3517
  if (this.ignoreDuringComposition(event))
@@ -3591,8 +3668,8 @@ class InputState {
3591
3668
  // compositionend and keydown events are sometimes emitted in the
3592
3669
  // wrong order. The key event should still be ignored, even when
3593
3670
  // it happens after the compositionend event.
3594
- if (browser.safari && !browser.ios && Date.now() - this.compositionEndedAt < 100) {
3595
- this.compositionEndedAt = 0;
3671
+ if (browser.safari && !browser.ios && this.compositionPendingKey && Date.now() - this.compositionEndedAt < 100) {
3672
+ this.compositionPendingKey = false;
3596
3673
  return true;
3597
3674
  }
3598
3675
  return false;
@@ -3624,8 +3701,9 @@ const PendingKeys = [
3624
3701
  const EmacsyPendingKeys = "dthko";
3625
3702
  // Key codes for modifier keys
3626
3703
  const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
3704
+ const dragScrollMargin = 6;
3627
3705
  function dragScrollSpeed(dist) {
3628
- return dist * 0.7 + 8;
3706
+ return Math.max(0, dist) * 0.7 + 8;
3629
3707
  }
3630
3708
  class MouseSelection {
3631
3709
  constructor(view, startEvent, style, mustSelect) {
@@ -3662,13 +3740,13 @@ class MouseSelection {
3662
3740
  let sx = 0, sy = 0;
3663
3741
  let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
3664
3742
  || { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
3665
- if (event.clientX <= rect.left)
3743
+ if (event.clientX <= rect.left + dragScrollMargin)
3666
3744
  sx = -dragScrollSpeed(rect.left - event.clientX);
3667
- else if (event.clientX >= rect.right)
3745
+ else if (event.clientX >= rect.right - dragScrollMargin)
3668
3746
  sx = dragScrollSpeed(event.clientX - rect.right);
3669
- if (event.clientY <= rect.top)
3747
+ if (event.clientY <= rect.top + dragScrollMargin)
3670
3748
  sy = -dragScrollSpeed(rect.top - event.clientY);
3671
- else if (event.clientY >= rect.bottom)
3749
+ else if (event.clientY >= rect.bottom - dragScrollMargin)
3672
3750
  sy = dragScrollSpeed(event.clientY - rect.bottom);
3673
3751
  this.setScrollSpeed(sx, sy);
3674
3752
  }
@@ -3915,7 +3993,7 @@ function basicMouseSelection(view, event) {
3915
3993
  }
3916
3994
  },
3917
3995
  get(event, extend, multiple) {
3918
- let cur = queryPos(view, event);
3996
+ let cur = queryPos(view, event), removed;
3919
3997
  let range = rangeForClick(view, cur.pos, cur.bias, type);
3920
3998
  if (start.pos != cur.pos && !extend) {
3921
3999
  let startRange = rangeForClick(view, start.pos, start.bias, type);
@@ -3924,8 +4002,8 @@ function basicMouseSelection(view, event) {
3924
4002
  }
3925
4003
  if (extend)
3926
4004
  return startSel.replaceRange(startSel.main.extend(range.from, range.to));
3927
- else if (multiple && startSel.ranges.length > 1 && startSel.ranges.some(r => r.eq(range)))
3928
- return removeRange(startSel, range);
4005
+ else if (multiple && type == 1 && startSel.ranges.length > 1 && (removed = removeRangeAround(startSel, cur.pos)))
4006
+ return removed;
3929
4007
  else if (multiple)
3930
4008
  return startSel.addRange(range);
3931
4009
  else
@@ -3933,11 +4011,13 @@ function basicMouseSelection(view, event) {
3933
4011
  }
3934
4012
  };
3935
4013
  }
3936
- function removeRange(sel, range) {
3937
- for (let i = 0;; i++) {
3938
- if (sel.ranges[i].eq(range))
4014
+ function removeRangeAround(sel, pos) {
4015
+ for (let i = 0; i < sel.ranges.length; i++) {
4016
+ let { from, to } = sel.ranges[i];
4017
+ if (from <= pos && to >= pos)
3939
4018
  return EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
3940
4019
  }
4020
+ return null;
3941
4021
  }
3942
4022
  handlers.dragstart = (view, event) => {
3943
4023
  let { selection: { main } } = view.state;
@@ -4114,6 +4194,8 @@ handlers.compositionstart = handlers.compositionupdate = view => {
4114
4194
  handlers.compositionend = view => {
4115
4195
  view.inputState.composing = -1;
4116
4196
  view.inputState.compositionEndedAt = Date.now();
4197
+ view.inputState.compositionPendingKey = true;
4198
+ view.inputState.compositionPendingChange = view.observer.pendingRecords().length > 0;
4117
4199
  view.inputState.compositionFirstChange = null;
4118
4200
  if (browser.chrome && browser.android)
4119
4201
  view.observer.flushSoon();
@@ -4460,7 +4542,8 @@ class HeightMapGap extends HeightMap {
4460
4542
  if (oracle.lineWrapping) {
4461
4543
  let totalPerLine = Math.min(this.height, oracle.lineHeight * lines);
4462
4544
  perLine = totalPerLine / lines;
4463
- perChar = (this.height - totalPerLine) / (this.length - lines - 1);
4545
+ if (this.length > lines + 1)
4546
+ perChar = (this.height - totalPerLine) / (this.length - lines - 1);
4464
4547
  }
4465
4548
  else {
4466
4549
  perLine = this.height / lines;
@@ -5476,16 +5559,16 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
5476
5559
  "&dark .cm-selectionBackground": {
5477
5560
  background: "#222"
5478
5561
  },
5479
- "&light.cm-focused .cm-selectionBackground": {
5562
+ "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
5480
5563
  background: "#d7d4f0"
5481
5564
  },
5482
- "&dark.cm-focused .cm-selectionBackground": {
5565
+ "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
5483
5566
  background: "#233"
5484
5567
  },
5485
5568
  ".cm-cursorLayer": {
5486
5569
  pointerEvents: "none"
5487
5570
  },
5488
- "&.cm-focused .cm-cursorLayer": {
5571
+ "&.cm-focused > .cm-scroller > .cm-cursorLayer": {
5489
5572
  animation: "steps(1) cm-blink 1.2s infinite"
5490
5573
  },
5491
5574
  // Two animations defined so that we can switch between them to
@@ -5507,7 +5590,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
5507
5590
  ".cm-dropCursor": {
5508
5591
  position: "absolute"
5509
5592
  },
5510
- "&.cm-focused .cm-cursor": {
5593
+ "&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor": {
5511
5594
  display: "block"
5512
5595
  },
5513
5596
  "&light .cm-activeLine": { backgroundColor: "#cceeff44" },
@@ -5768,8 +5851,7 @@ function applyDOMChange(view, domChange) {
5768
5851
  }
5769
5852
  else {
5770
5853
  let changes = startState.changes(change);
5771
- let mainSel = newSel && !startState.selection.main.eq(newSel.main) && newSel.main.to <= changes.newLength
5772
- ? newSel.main : undefined;
5854
+ let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
5773
5855
  // Try to apply a composition change to all cursors
5774
5856
  if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
5775
5857
  change.to <= sel.to && change.to >= sel.to - 10) {
@@ -5803,7 +5885,9 @@ function applyDOMChange(view, domChange) {
5803
5885
  }
5804
5886
  }
5805
5887
  let userEvent = "input.type";
5806
- if (view.composing) {
5888
+ if (view.composing ||
5889
+ view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
5890
+ view.inputState.compositionPendingChange = false;
5807
5891
  userEvent += ".compose";
5808
5892
  if (view.inputState.compositionFirstChange) {
5809
5893
  userEvent += ".start";
@@ -6179,10 +6263,13 @@ class DOMObserver {
6179
6263
  }
6180
6264
  this.flush();
6181
6265
  }
6182
- processRecords() {
6183
- let records = this.queue;
6266
+ pendingRecords() {
6184
6267
  for (let mut of this.observer.takeRecords())
6185
- records.push(mut);
6268
+ this.queue.push(mut);
6269
+ return this.queue;
6270
+ }
6271
+ processRecords() {
6272
+ let records = this.pendingRecords();
6186
6273
  if (records.length)
6187
6274
  this.queue = [];
6188
6275
  let from = -1, to = -1, typeOver = false;
@@ -8775,6 +8862,11 @@ class HoverTooltipHost {
8775
8862
  update(update) {
8776
8863
  this.manager.update(update);
8777
8864
  }
8865
+ destroy() {
8866
+ var _a;
8867
+ for (let t of this.manager.tooltipViews)
8868
+ (_a = t.destroy) === null || _a === void 0 ? void 0 : _a.call(t);
8869
+ }
8778
8870
  }
8779
8871
  const showHoverTooltipHost = /*@__PURE__*/showTooltip.compute([showHoverTooltip], state => {
8780
8872
  let tooltips = state.facet(showHoverTooltip).filter(t => t);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.9.3",
3
+ "version": "6.9.5",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",