@codemirror/view 6.23.1 → 6.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 6.24.1 (2024-02-19)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a crash that happens when hover tooltips are active during changes, introduced in 6.24.0.
6
+
7
+ ## 6.24.0 (2024-02-09)
8
+
9
+ ### Bug fixes
10
+
11
+ Fix an issue that broke context-menu select-all on Chrome when the viewport didn't cover the whole document.
12
+
13
+ Make sure tooltips are ordered by extension precedence in the DOM.
14
+
15
+ ### New features
16
+
17
+ Hover tooltip sources may now return multiple tooltips.
18
+
1
19
  ## 6.23.1 (2024-01-24)
2
20
 
3
21
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -3193,6 +3193,7 @@ class BlockGapWidget extends WidgetType {
3193
3193
  }
3194
3194
  get editable() { return true; }
3195
3195
  get estimatedHeight() { return this.height; }
3196
+ ignoreEvent() { return false; }
3196
3197
  }
3197
3198
  function findCompositionNode(view, headPos) {
3198
3199
  let sel = view.observer.selectionRange;
@@ -6208,12 +6209,16 @@ class DOMChange {
6208
6209
  !contains(view.contentDOM, domSel.anchorNode)
6209
6210
  ? view.state.selection.main.anchor
6210
6211
  : view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset);
6211
- // iOS will refuse to select the block gaps when doing select-all
6212
+ // iOS will refuse to select the block gaps when doing
6213
+ // select-all.
6214
+ // Chrome will put the selection *inside* them, confusing
6215
+ // posFromDOM
6212
6216
  let vp = view.viewport;
6213
- if (browser.ios && view.state.selection.main.empty && head != anchor &&
6217
+ if ((browser.ios || browser.chrome) && view.state.selection.main.empty && head != anchor &&
6214
6218
  (vp.from > 0 || vp.to < view.state.doc.length)) {
6215
- let offFrom = vp.from - Math.min(head, anchor), offTo = vp.to - Math.max(head, anchor);
6216
- if ((offFrom == 0 || offFrom == 1) && (offTo == 0 || offTo == -1)) {
6219
+ let from = Math.min(head, anchor), to = Math.max(head, anchor);
6220
+ let offFrom = vp.from - from, offTo = vp.to - to;
6221
+ if ((offFrom == 0 || offFrom == 1 || from == 0) && (offTo == 0 || offTo == -1 || to == view.state.doc.length)) {
6217
6222
  head = 0;
6218
6223
  anchor = view.state.doc.length;
6219
6224
  }
@@ -9185,7 +9190,8 @@ class TooltipViewManager {
9185
9190
  this.removeTooltipView = removeTooltipView;
9186
9191
  this.input = view.state.facet(facet);
9187
9192
  this.tooltips = this.input.filter(t => t);
9188
- this.tooltipViews = this.tooltips.map(createTooltipView);
9193
+ let prev = null;
9194
+ this.tooltipViews = this.tooltips.map(t => prev = createTooltipView(t, prev));
9189
9195
  }
9190
9196
  update(update, above) {
9191
9197
  var _a;
@@ -9208,7 +9214,7 @@ class TooltipViewManager {
9208
9214
  known = i;
9209
9215
  }
9210
9216
  if (known < 0) {
9211
- tooltipViews[i] = this.createTooltipView(tip);
9217
+ tooltipViews[i] = this.createTooltipView(tip, i ? tooltipViews[i - 1] : null);
9212
9218
  if (newAbove)
9213
9219
  newAbove[i] = !!tip.above;
9214
9220
  }
@@ -9271,7 +9277,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
9271
9277
  this.createContainer();
9272
9278
  this.measureReq = { read: this.readMeasure.bind(this), write: this.writeMeasure.bind(this), key: this };
9273
9279
  this.resizeObserver = typeof ResizeObserver == "function" ? new ResizeObserver(() => this.measureSoon()) : null;
9274
- this.manager = new TooltipViewManager(view, showTooltip, t => this.createTooltip(t), t => {
9280
+ this.manager = new TooltipViewManager(view, showTooltip, (t, p) => this.createTooltip(t, p), t => {
9275
9281
  if (this.resizeObserver)
9276
9282
  this.resizeObserver.unobserve(t.dom);
9277
9283
  t.dom.remove();
@@ -9340,18 +9346,19 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
9340
9346
  if (shouldMeasure)
9341
9347
  this.maybeMeasure();
9342
9348
  }
9343
- createTooltip(tooltip) {
9349
+ createTooltip(tooltip, prev) {
9344
9350
  let tooltipView = tooltip.create(this.view);
9351
+ let before = prev ? prev.dom : null;
9345
9352
  tooltipView.dom.classList.add("cm-tooltip");
9346
9353
  if (tooltip.arrow && !tooltipView.dom.querySelector(".cm-tooltip > .cm-tooltip-arrow")) {
9347
9354
  let arrow = document.createElement("div");
9348
9355
  arrow.className = "cm-tooltip-arrow";
9349
- tooltipView.dom.appendChild(arrow);
9356
+ tooltipView.dom.insertBefore(arrow, before);
9350
9357
  }
9351
9358
  tooltipView.dom.style.position = this.position;
9352
9359
  tooltipView.dom.style.top = Outside;
9353
9360
  tooltipView.dom.style.left = "0px";
9354
- this.container.appendChild(tooltipView.dom);
9361
+ this.container.insertBefore(tooltipView.dom, before);
9355
9362
  if (tooltipView.mount)
9356
9363
  tooltipView.mount(this.view);
9357
9364
  if (this.resizeObserver)
@@ -9571,7 +9578,9 @@ Facet to which an extension can add a value to show a tooltip.
9571
9578
  const showTooltip = state.Facet.define({
9572
9579
  enables: [tooltipPlugin, baseTheme]
9573
9580
  });
9574
- const showHoverTooltip = state.Facet.define();
9581
+ const showHoverTooltip = state.Facet.define({
9582
+ combine: inputs => inputs.reduce((a, i) => a.concat(i), [])
9583
+ });
9575
9584
  class HoverTooltipHost {
9576
9585
  // Needs to be static so that host tooltip instances always match
9577
9586
  static create(view) {
@@ -9582,12 +9591,12 @@ class HoverTooltipHost {
9582
9591
  this.mounted = false;
9583
9592
  this.dom = document.createElement("div");
9584
9593
  this.dom.classList.add("cm-tooltip-hover");
9585
- this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t), t => t.dom.remove());
9594
+ this.manager = new TooltipViewManager(view, showHoverTooltip, (t, p) => this.createHostedView(t, p), t => t.dom.remove());
9586
9595
  }
9587
- createHostedView(tooltip) {
9596
+ createHostedView(tooltip, prev) {
9588
9597
  let hostedView = tooltip.create(this.view);
9589
9598
  hostedView.dom.classList.add("cm-tooltip-section");
9590
- this.dom.appendChild(hostedView.dom);
9599
+ this.dom.insertBefore(hostedView.dom, prev ? prev.dom.nextSibling : this.dom.firstChild);
9591
9600
  if (this.mounted && hostedView.mount)
9592
9601
  hostedView.mount(this.view);
9593
9602
  return hostedView;
@@ -9632,7 +9641,7 @@ class HoverTooltipHost {
9632
9641
  get resize() { return this.passProp("resize"); }
9633
9642
  }
9634
9643
  const showHoverTooltipHost = showTooltip.compute([showHoverTooltip], state => {
9635
- let tooltips = state.facet(showHoverTooltip).filter(t => t);
9644
+ let tooltips = state.facet(showHoverTooltip);
9636
9645
  if (tooltips.length === 0)
9637
9646
  return null;
9638
9647
  return {
@@ -9670,7 +9679,7 @@ class HoverPlugin {
9670
9679
  }
9671
9680
  checkHover() {
9672
9681
  this.hoverTimeout = -1;
9673
- if (this.active)
9682
+ if (this.active.length)
9674
9683
  return;
9675
9684
  let hovered = Date.now() - this.lastMove.time;
9676
9685
  if (hovered < this.hoverTime)
@@ -9708,13 +9717,13 @@ class HoverPlugin {
9708
9717
  open.then(result => {
9709
9718
  if (this.pending == pending) {
9710
9719
  this.pending = null;
9711
- if (result)
9712
- view.dispatch({ effects: this.setHover.of(result) });
9720
+ if (result && !(Array.isArray(result) && !result.length))
9721
+ view.dispatch({ effects: this.setHover.of(Array.isArray(result) ? result : [result]) });
9713
9722
  }
9714
9723
  }, e => logException(view.state, e, "hover tooltip"));
9715
9724
  }
9716
- else if (open) {
9717
- view.dispatch({ effects: this.setHover.of(open) });
9725
+ else if (open && !(Array.isArray(open) && !open.length)) {
9726
+ view.dispatch({ effects: this.setHover.of(Array.isArray(open) ? open : [open]) });
9718
9727
  }
9719
9728
  }
9720
9729
  get tooltip() {
@@ -9723,16 +9732,16 @@ class HoverPlugin {
9723
9732
  return index > -1 ? plugin.manager.tooltipViews[index] : null;
9724
9733
  }
9725
9734
  mousemove(event) {
9726
- var _a;
9735
+ var _a, _b;
9727
9736
  this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
9728
9737
  if (this.hoverTimeout < 0)
9729
9738
  this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
9730
9739
  let { active, tooltip } = this;
9731
- if (active && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
9732
- let { pos } = active || this.pending, end = (_a = active === null || active === void 0 ? void 0 : active.end) !== null && _a !== void 0 ? _a : pos;
9740
+ if (active.length && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
9741
+ let { pos } = active[0] || this.pending, end = (_b = (_a = active[0]) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : pos;
9733
9742
  if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
9734
9743
  : !isOverRange(this.view, pos, end, event.clientX, event.clientY))) {
9735
- this.view.dispatch({ effects: this.setHover.of(null) });
9744
+ this.view.dispatch({ effects: this.setHover.of([]) });
9736
9745
  this.pending = null;
9737
9746
  }
9738
9747
  }
@@ -9741,11 +9750,11 @@ class HoverPlugin {
9741
9750
  clearTimeout(this.hoverTimeout);
9742
9751
  this.hoverTimeout = -1;
9743
9752
  let { active } = this;
9744
- if (active) {
9753
+ if (active.length) {
9745
9754
  let { tooltip } = this;
9746
9755
  let inTooltip = tooltip && tooltip.dom.contains(event.relatedTarget);
9747
9756
  if (!inTooltip)
9748
- this.view.dispatch({ effects: this.setHover.of(null) });
9757
+ this.view.dispatch({ effects: this.setHover.of([]) });
9749
9758
  else
9750
9759
  this.watchTooltipLeave(tooltip.dom);
9751
9760
  }
@@ -9753,8 +9762,8 @@ class HoverPlugin {
9753
9762
  watchTooltipLeave(tooltip) {
9754
9763
  let watch = (event) => {
9755
9764
  tooltip.removeEventListener("mouseleave", watch);
9756
- if (this.active && !this.view.dom.contains(event.relatedTarget))
9757
- this.view.dispatch({ effects: this.setHover.of(null) });
9765
+ if (this.active.length && !this.view.dom.contains(event.relatedTarget))
9766
+ this.view.dispatch({ effects: this.setHover.of([]) });
9758
9767
  };
9759
9768
  tooltip.addEventListener("mouseleave", watch);
9760
9769
  }
@@ -9794,26 +9803,33 @@ range to be "merged" together without overlapping.
9794
9803
  function hoverTooltip(source, options = {}) {
9795
9804
  let setHover = state.StateEffect.define();
9796
9805
  let hoverState = state.StateField.define({
9797
- create() { return null; },
9806
+ create() { return []; },
9798
9807
  update(value, tr) {
9799
- if (value && (options.hideOnChange && (tr.docChanged || tr.selection) ||
9800
- options.hideOn && options.hideOn(tr, value)))
9801
- return null;
9802
- if (value && tr.docChanged) {
9803
- let newPos = tr.changes.mapPos(value.pos, -1, state.MapMode.TrackDel);
9804
- if (newPos == null)
9805
- return null;
9806
- let copy = Object.assign(Object.create(null), value);
9807
- copy.pos = newPos;
9808
- if (value.end != null)
9809
- copy.end = tr.changes.mapPos(value.end);
9810
- value = copy;
9808
+ if (value.length) {
9809
+ if (options.hideOnChange && (tr.docChanged || tr.selection))
9810
+ value = [];
9811
+ else if (options.hideOn)
9812
+ value = value.filter(v => !options.hideOn(tr, v));
9813
+ if (tr.docChanged) {
9814
+ let mapped = [];
9815
+ for (let tooltip of value) {
9816
+ let newPos = tr.changes.mapPos(tooltip.pos, -1, state.MapMode.TrackDel);
9817
+ if (newPos != null) {
9818
+ let copy = Object.assign(Object.create(null), tooltip);
9819
+ copy.pos = newPos;
9820
+ if (copy.end != null)
9821
+ copy.end = tr.changes.mapPos(copy.end);
9822
+ mapped.push(copy);
9823
+ }
9824
+ }
9825
+ value = mapped;
9826
+ }
9811
9827
  }
9812
9828
  for (let effect of tr.effects) {
9813
9829
  if (effect.is(setHover))
9814
9830
  value = effect.value;
9815
9831
  if (effect.is(closeHoverTooltipEffect))
9816
- value = null;
9832
+ value = [];
9817
9833
  }
9818
9834
  return value;
9819
9835
  },
package/dist/index.d.cts CHANGED
@@ -1889,6 +1889,7 @@ interface TooltipView {
1889
1889
  Facet to which an extension can add a value to show a tooltip.
1890
1890
  */
1891
1891
  declare const showTooltip: Facet<Tooltip | null, readonly (Tooltip | null)[]>;
1892
+ type HoverSource = (view: EditorView, pos: number, side: -1 | 1) => Tooltip | readonly Tooltip[] | null | Promise<Tooltip | readonly Tooltip[] | null>;
1892
1893
  /**
1893
1894
  Set up a hover tooltip, which shows up when the pointer hovers
1894
1895
  over ranges of text. The callback is called when the mouse hovers
@@ -1902,7 +1903,7 @@ Note that all hover tooltips are hosted within a single tooltip
1902
1903
  container element. This allows multiple tooltips over the same
1903
1904
  range to be "merged" together without overlapping.
1904
1905
  */
1905
- declare function hoverTooltip(source: (view: EditorView, pos: number, side: -1 | 1) => Tooltip | null | Promise<Tooltip | null>, options?: {
1906
+ declare function hoverTooltip(source: HoverSource, options?: {
1906
1907
  /**
1907
1908
  Controls whether a transaction hides the tooltip. The default
1908
1909
  is to not hide.
package/dist/index.d.ts CHANGED
@@ -1889,6 +1889,7 @@ interface TooltipView {
1889
1889
  Facet to which an extension can add a value to show a tooltip.
1890
1890
  */
1891
1891
  declare const showTooltip: Facet<Tooltip | null, readonly (Tooltip | null)[]>;
1892
+ type HoverSource = (view: EditorView, pos: number, side: -1 | 1) => Tooltip | readonly Tooltip[] | null | Promise<Tooltip | readonly Tooltip[] | null>;
1892
1893
  /**
1893
1894
  Set up a hover tooltip, which shows up when the pointer hovers
1894
1895
  over ranges of text. The callback is called when the mouse hovers
@@ -1902,7 +1903,7 @@ Note that all hover tooltips are hosted within a single tooltip
1902
1903
  container element. This allows multiple tooltips over the same
1903
1904
  range to be "merged" together without overlapping.
1904
1905
  */
1905
- declare function hoverTooltip(source: (view: EditorView, pos: number, side: -1 | 1) => Tooltip | null | Promise<Tooltip | null>, options?: {
1906
+ declare function hoverTooltip(source: HoverSource, options?: {
1906
1907
  /**
1907
1908
  Controls whether a transaction hides the tooltip. The default
1908
1909
  is to not hide.
package/dist/index.js CHANGED
@@ -3189,6 +3189,7 @@ class BlockGapWidget extends WidgetType {
3189
3189
  }
3190
3190
  get editable() { return true; }
3191
3191
  get estimatedHeight() { return this.height; }
3192
+ ignoreEvent() { return false; }
3192
3193
  }
3193
3194
  function findCompositionNode(view, headPos) {
3194
3195
  let sel = view.observer.selectionRange;
@@ -6203,12 +6204,16 @@ class DOMChange {
6203
6204
  !contains(view.contentDOM, domSel.anchorNode)
6204
6205
  ? view.state.selection.main.anchor
6205
6206
  : view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset);
6206
- // iOS will refuse to select the block gaps when doing select-all
6207
+ // iOS will refuse to select the block gaps when doing
6208
+ // select-all.
6209
+ // Chrome will put the selection *inside* them, confusing
6210
+ // posFromDOM
6207
6211
  let vp = view.viewport;
6208
- if (browser.ios && view.state.selection.main.empty && head != anchor &&
6212
+ if ((browser.ios || browser.chrome) && view.state.selection.main.empty && head != anchor &&
6209
6213
  (vp.from > 0 || vp.to < view.state.doc.length)) {
6210
- let offFrom = vp.from - Math.min(head, anchor), offTo = vp.to - Math.max(head, anchor);
6211
- if ((offFrom == 0 || offFrom == 1) && (offTo == 0 || offTo == -1)) {
6214
+ let from = Math.min(head, anchor), to = Math.max(head, anchor);
6215
+ let offFrom = vp.from - from, offTo = vp.to - to;
6216
+ if ((offFrom == 0 || offFrom == 1 || from == 0) && (offTo == 0 || offTo == -1 || to == view.state.doc.length)) {
6212
6217
  head = 0;
6213
6218
  anchor = view.state.doc.length;
6214
6219
  }
@@ -9180,7 +9185,8 @@ class TooltipViewManager {
9180
9185
  this.removeTooltipView = removeTooltipView;
9181
9186
  this.input = view.state.facet(facet);
9182
9187
  this.tooltips = this.input.filter(t => t);
9183
- this.tooltipViews = this.tooltips.map(createTooltipView);
9188
+ let prev = null;
9189
+ this.tooltipViews = this.tooltips.map(t => prev = createTooltipView(t, prev));
9184
9190
  }
9185
9191
  update(update, above) {
9186
9192
  var _a;
@@ -9203,7 +9209,7 @@ class TooltipViewManager {
9203
9209
  known = i;
9204
9210
  }
9205
9211
  if (known < 0) {
9206
- tooltipViews[i] = this.createTooltipView(tip);
9212
+ tooltipViews[i] = this.createTooltipView(tip, i ? tooltipViews[i - 1] : null);
9207
9213
  if (newAbove)
9208
9214
  newAbove[i] = !!tip.above;
9209
9215
  }
@@ -9266,7 +9272,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9266
9272
  this.createContainer();
9267
9273
  this.measureReq = { read: this.readMeasure.bind(this), write: this.writeMeasure.bind(this), key: this };
9268
9274
  this.resizeObserver = typeof ResizeObserver == "function" ? new ResizeObserver(() => this.measureSoon()) : null;
9269
- this.manager = new TooltipViewManager(view, showTooltip, t => this.createTooltip(t), t => {
9275
+ this.manager = new TooltipViewManager(view, showTooltip, (t, p) => this.createTooltip(t, p), t => {
9270
9276
  if (this.resizeObserver)
9271
9277
  this.resizeObserver.unobserve(t.dom);
9272
9278
  t.dom.remove();
@@ -9335,18 +9341,19 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9335
9341
  if (shouldMeasure)
9336
9342
  this.maybeMeasure();
9337
9343
  }
9338
- createTooltip(tooltip) {
9344
+ createTooltip(tooltip, prev) {
9339
9345
  let tooltipView = tooltip.create(this.view);
9346
+ let before = prev ? prev.dom : null;
9340
9347
  tooltipView.dom.classList.add("cm-tooltip");
9341
9348
  if (tooltip.arrow && !tooltipView.dom.querySelector(".cm-tooltip > .cm-tooltip-arrow")) {
9342
9349
  let arrow = document.createElement("div");
9343
9350
  arrow.className = "cm-tooltip-arrow";
9344
- tooltipView.dom.appendChild(arrow);
9351
+ tooltipView.dom.insertBefore(arrow, before);
9345
9352
  }
9346
9353
  tooltipView.dom.style.position = this.position;
9347
9354
  tooltipView.dom.style.top = Outside;
9348
9355
  tooltipView.dom.style.left = "0px";
9349
- this.container.appendChild(tooltipView.dom);
9356
+ this.container.insertBefore(tooltipView.dom, before);
9350
9357
  if (tooltipView.mount)
9351
9358
  tooltipView.mount(this.view);
9352
9359
  if (this.resizeObserver)
@@ -9566,7 +9573,9 @@ Facet to which an extension can add a value to show a tooltip.
9566
9573
  const showTooltip = /*@__PURE__*/Facet.define({
9567
9574
  enables: [tooltipPlugin, baseTheme]
9568
9575
  });
9569
- const showHoverTooltip = /*@__PURE__*/Facet.define();
9576
+ const showHoverTooltip = /*@__PURE__*/Facet.define({
9577
+ combine: inputs => inputs.reduce((a, i) => a.concat(i), [])
9578
+ });
9570
9579
  class HoverTooltipHost {
9571
9580
  // Needs to be static so that host tooltip instances always match
9572
9581
  static create(view) {
@@ -9577,12 +9586,12 @@ class HoverTooltipHost {
9577
9586
  this.mounted = false;
9578
9587
  this.dom = document.createElement("div");
9579
9588
  this.dom.classList.add("cm-tooltip-hover");
9580
- this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t), t => t.dom.remove());
9589
+ this.manager = new TooltipViewManager(view, showHoverTooltip, (t, p) => this.createHostedView(t, p), t => t.dom.remove());
9581
9590
  }
9582
- createHostedView(tooltip) {
9591
+ createHostedView(tooltip, prev) {
9583
9592
  let hostedView = tooltip.create(this.view);
9584
9593
  hostedView.dom.classList.add("cm-tooltip-section");
9585
- this.dom.appendChild(hostedView.dom);
9594
+ this.dom.insertBefore(hostedView.dom, prev ? prev.dom.nextSibling : this.dom.firstChild);
9586
9595
  if (this.mounted && hostedView.mount)
9587
9596
  hostedView.mount(this.view);
9588
9597
  return hostedView;
@@ -9627,7 +9636,7 @@ class HoverTooltipHost {
9627
9636
  get resize() { return this.passProp("resize"); }
9628
9637
  }
9629
9638
  const showHoverTooltipHost = /*@__PURE__*/showTooltip.compute([showHoverTooltip], state => {
9630
- let tooltips = state.facet(showHoverTooltip).filter(t => t);
9639
+ let tooltips = state.facet(showHoverTooltip);
9631
9640
  if (tooltips.length === 0)
9632
9641
  return null;
9633
9642
  return {
@@ -9665,7 +9674,7 @@ class HoverPlugin {
9665
9674
  }
9666
9675
  checkHover() {
9667
9676
  this.hoverTimeout = -1;
9668
- if (this.active)
9677
+ if (this.active.length)
9669
9678
  return;
9670
9679
  let hovered = Date.now() - this.lastMove.time;
9671
9680
  if (hovered < this.hoverTime)
@@ -9703,13 +9712,13 @@ class HoverPlugin {
9703
9712
  open.then(result => {
9704
9713
  if (this.pending == pending) {
9705
9714
  this.pending = null;
9706
- if (result)
9707
- view.dispatch({ effects: this.setHover.of(result) });
9715
+ if (result && !(Array.isArray(result) && !result.length))
9716
+ view.dispatch({ effects: this.setHover.of(Array.isArray(result) ? result : [result]) });
9708
9717
  }
9709
9718
  }, e => logException(view.state, e, "hover tooltip"));
9710
9719
  }
9711
- else if (open) {
9712
- view.dispatch({ effects: this.setHover.of(open) });
9720
+ else if (open && !(Array.isArray(open) && !open.length)) {
9721
+ view.dispatch({ effects: this.setHover.of(Array.isArray(open) ? open : [open]) });
9713
9722
  }
9714
9723
  }
9715
9724
  get tooltip() {
@@ -9718,16 +9727,16 @@ class HoverPlugin {
9718
9727
  return index > -1 ? plugin.manager.tooltipViews[index] : null;
9719
9728
  }
9720
9729
  mousemove(event) {
9721
- var _a;
9730
+ var _a, _b;
9722
9731
  this.lastMove = { x: event.clientX, y: event.clientY, target: event.target, time: Date.now() };
9723
9732
  if (this.hoverTimeout < 0)
9724
9733
  this.hoverTimeout = setTimeout(this.checkHover, this.hoverTime);
9725
9734
  let { active, tooltip } = this;
9726
- if (active && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
9727
- let { pos } = active || this.pending, end = (_a = active === null || active === void 0 ? void 0 : active.end) !== null && _a !== void 0 ? _a : pos;
9735
+ if (active.length && tooltip && !isInTooltip(tooltip.dom, event) || this.pending) {
9736
+ let { pos } = active[0] || this.pending, end = (_b = (_a = active[0]) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : pos;
9728
9737
  if ((pos == end ? this.view.posAtCoords(this.lastMove) != pos
9729
9738
  : !isOverRange(this.view, pos, end, event.clientX, event.clientY))) {
9730
- this.view.dispatch({ effects: this.setHover.of(null) });
9739
+ this.view.dispatch({ effects: this.setHover.of([]) });
9731
9740
  this.pending = null;
9732
9741
  }
9733
9742
  }
@@ -9736,11 +9745,11 @@ class HoverPlugin {
9736
9745
  clearTimeout(this.hoverTimeout);
9737
9746
  this.hoverTimeout = -1;
9738
9747
  let { active } = this;
9739
- if (active) {
9748
+ if (active.length) {
9740
9749
  let { tooltip } = this;
9741
9750
  let inTooltip = tooltip && tooltip.dom.contains(event.relatedTarget);
9742
9751
  if (!inTooltip)
9743
- this.view.dispatch({ effects: this.setHover.of(null) });
9752
+ this.view.dispatch({ effects: this.setHover.of([]) });
9744
9753
  else
9745
9754
  this.watchTooltipLeave(tooltip.dom);
9746
9755
  }
@@ -9748,8 +9757,8 @@ class HoverPlugin {
9748
9757
  watchTooltipLeave(tooltip) {
9749
9758
  let watch = (event) => {
9750
9759
  tooltip.removeEventListener("mouseleave", watch);
9751
- if (this.active && !this.view.dom.contains(event.relatedTarget))
9752
- this.view.dispatch({ effects: this.setHover.of(null) });
9760
+ if (this.active.length && !this.view.dom.contains(event.relatedTarget))
9761
+ this.view.dispatch({ effects: this.setHover.of([]) });
9753
9762
  };
9754
9763
  tooltip.addEventListener("mouseleave", watch);
9755
9764
  }
@@ -9789,26 +9798,33 @@ range to be "merged" together without overlapping.
9789
9798
  function hoverTooltip(source, options = {}) {
9790
9799
  let setHover = StateEffect.define();
9791
9800
  let hoverState = StateField.define({
9792
- create() { return null; },
9801
+ create() { return []; },
9793
9802
  update(value, tr) {
9794
- if (value && (options.hideOnChange && (tr.docChanged || tr.selection) ||
9795
- options.hideOn && options.hideOn(tr, value)))
9796
- return null;
9797
- if (value && tr.docChanged) {
9798
- let newPos = tr.changes.mapPos(value.pos, -1, MapMode.TrackDel);
9799
- if (newPos == null)
9800
- return null;
9801
- let copy = Object.assign(Object.create(null), value);
9802
- copy.pos = newPos;
9803
- if (value.end != null)
9804
- copy.end = tr.changes.mapPos(value.end);
9805
- value = copy;
9803
+ if (value.length) {
9804
+ if (options.hideOnChange && (tr.docChanged || tr.selection))
9805
+ value = [];
9806
+ else if (options.hideOn)
9807
+ value = value.filter(v => !options.hideOn(tr, v));
9808
+ if (tr.docChanged) {
9809
+ let mapped = [];
9810
+ for (let tooltip of value) {
9811
+ let newPos = tr.changes.mapPos(tooltip.pos, -1, MapMode.TrackDel);
9812
+ if (newPos != null) {
9813
+ let copy = Object.assign(Object.create(null), tooltip);
9814
+ copy.pos = newPos;
9815
+ if (copy.end != null)
9816
+ copy.end = tr.changes.mapPos(copy.end);
9817
+ mapped.push(copy);
9818
+ }
9819
+ }
9820
+ value = mapped;
9821
+ }
9806
9822
  }
9807
9823
  for (let effect of tr.effects) {
9808
9824
  if (effect.is(setHover))
9809
9825
  value = effect.value;
9810
9826
  if (effect.is(closeHoverTooltipEffect))
9811
- value = null;
9827
+ value = [];
9812
9828
  }
9813
9829
  return value;
9814
9830
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.23.1",
3
+ "version": "6.24.1",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",