@codemirror/view 6.34.1 → 6.34.3

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,19 @@
1
+ ## 6.34.3 (2024-11-15)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure positions covered by a gutter or a panel aren't treated as visible for the purpose of displaying tooltips.
6
+
7
+ Properly include the tooltip arrow height when checking whether a tooltip fits in its preferred above/below position.
8
+
9
+ Fix an issue with compositions on Chrome inserting their content in the wrong position when another document change came in during composition.
10
+
11
+ ## 6.34.2 (2024-11-05)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix the default cursor color for dark themes, which was way too dark.
16
+
1
17
  ## 6.34.1 (2024-09-27)
2
18
 
3
19
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -6487,7 +6487,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
6487
6487
  display: "none"
6488
6488
  },
6489
6489
  "&dark .cm-cursor": {
6490
- borderLeftColor: "#444"
6490
+ borderLeftColor: "#ddd"
6491
6491
  },
6492
6492
  ".cm-dropCursor": {
6493
6493
  position: "absolute"
@@ -7155,6 +7155,9 @@ class EditContextManager {
7155
7155
  // user action on some Android keyboards)
7156
7156
  this.pendingContextChange = null;
7157
7157
  this.handlers = Object.create(null);
7158
+ // Kludge to work around the fact that EditContext does not respond
7159
+ // well to having its content updated during a composition (see #1472)
7160
+ this.composing = null;
7158
7161
  this.resetRange(view.state);
7159
7162
  let context = this.editContext = new window.EditContext({
7160
7163
  text: view.state.doc.sliceString(this.from, this.to),
@@ -7163,9 +7166,10 @@ class EditContextManager {
7163
7166
  });
7164
7167
  this.handlers.textupdate = e => {
7165
7168
  let { anchor } = view.state.selection.main;
7166
- let change = { from: this.toEditorPos(e.updateRangeStart),
7167
- to: this.toEditorPos(e.updateRangeEnd),
7168
- insert: state.Text.of(e.text.split("\n")) };
7169
+ let from = this.toEditorPos(e.updateRangeStart), to = this.toEditorPos(e.updateRangeEnd);
7170
+ if (view.inputState.composing >= 0 && !this.composing)
7171
+ this.composing = { contextBase: e.updateRangeStart, editorBase: from, drifted: false };
7172
+ let change = { from, to, insert: state.Text.of(e.text.split("\n")) };
7169
7173
  // If the window doesn't include the anchor, assume changes
7170
7174
  // adjacent to a side go up to the anchor.
7171
7175
  if (change.from == this.from && anchor < this.from)
@@ -7216,6 +7220,12 @@ class EditContextManager {
7216
7220
  this.handlers.compositionend = () => {
7217
7221
  view.inputState.composing = -1;
7218
7222
  view.inputState.compositionFirstChange = null;
7223
+ if (this.composing) {
7224
+ let { drifted } = this.composing;
7225
+ this.composing = null;
7226
+ if (drifted)
7227
+ this.reset(view.state);
7228
+ }
7219
7229
  };
7220
7230
  for (let event in this.handlers)
7221
7231
  context.addEventListener(event, this.handlers[event]);
@@ -7266,11 +7276,13 @@ class EditContextManager {
7266
7276
  }
7267
7277
  update(update) {
7268
7278
  let reverted = this.pendingContextChange;
7269
- if (!this.applyEdits(update) || !this.rangeIsValid(update.state)) {
7279
+ if (this.composing && (this.composing.drifted || update.transactions.some(tr => !tr.isUserEvent("input.type") && tr.changes.touchesRange(this.from, this.to)))) {
7280
+ this.composing.drifted = true;
7281
+ this.composing.editorBase = update.changes.mapPos(this.composing.editorBase);
7282
+ }
7283
+ else if (!this.applyEdits(update) || !this.rangeIsValid(update.state)) {
7270
7284
  this.pendingContextChange = null;
7271
- this.resetRange(update.state);
7272
- this.editContext.updateText(0, this.editContext.text.length, update.state.doc.sliceString(this.from, this.to));
7273
- this.setSelection(update.state);
7285
+ this.reset(update.state);
7274
7286
  }
7275
7287
  else if (update.docChanged || update.selectionSet || reverted) {
7276
7288
  this.setSelection(update.state);
@@ -7283,6 +7295,11 @@ class EditContextManager {
7283
7295
  this.from = Math.max(0, head - 10000 /* CxVp.Margin */);
7284
7296
  this.to = Math.min(state.doc.length, head + 10000 /* CxVp.Margin */);
7285
7297
  }
7298
+ reset(state) {
7299
+ this.resetRange(state);
7300
+ this.editContext.updateText(0, this.editContext.text.length, state.doc.sliceString(this.from, this.to));
7301
+ this.setSelection(state);
7302
+ }
7286
7303
  revertPending(state) {
7287
7304
  let pending = this.pendingContextChange;
7288
7305
  this.pendingContextChange = null;
@@ -7301,8 +7318,14 @@ class EditContextManager {
7301
7318
  this.to < state.doc.length && this.to - head < 500 /* CxVp.MinMargin */ ||
7302
7319
  this.to - this.from > 10000 /* CxVp.Margin */ * 3);
7303
7320
  }
7304
- toEditorPos(contextPos) { return contextPos + this.from; }
7305
- toContextPos(editorPos) { return editorPos - this.from; }
7321
+ toEditorPos(contextPos) {
7322
+ let c = this.composing;
7323
+ return c && c.drifted ? c.editorBase + (contextPos - c.contextBase) : contextPos + this.from;
7324
+ }
7325
+ toContextPos(editorPos) {
7326
+ let c = this.composing;
7327
+ return c && c.drifted ? c.contextBase + (editorPos - c.editorBase) : editorPos - this.from;
7328
+ }
7306
7329
  destroy() {
7307
7330
  for (let event in this.handlers)
7308
7331
  this.editContext.removeEventListener(event, this.handlers[event]);
@@ -9868,7 +9891,6 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
9868
9891
  clearTimeout(this.measureTimeout);
9869
9892
  }
9870
9893
  readMeasure() {
9871
- let editor = this.view.dom.getBoundingClientRect();
9872
9894
  let scaleX = 1, scaleY = 1, makeAbsolute = false;
9873
9895
  if (this.position == "fixed" && this.manager.tooltipViews.length) {
9874
9896
  let { dom } = this.manager.tooltipViews[0];
@@ -9897,9 +9919,13 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
9897
9919
  ({ scaleX, scaleY } = this.view.viewState);
9898
9920
  }
9899
9921
  }
9922
+ let visible = this.view.scrollDOM.getBoundingClientRect(), margins = getScrollMargins(this.view);
9900
9923
  return {
9901
- editor,
9902
- parent: this.parent ? this.container.getBoundingClientRect() : editor,
9924
+ visible: {
9925
+ left: visible.left + margins.left, top: visible.top + margins.top,
9926
+ right: visible.right - margins.right, bottom: visible.bottom - margins.bottom
9927
+ },
9928
+ parent: this.parent ? this.container.getBoundingClientRect() : this.view.dom.getBoundingClientRect(),
9903
9929
  pos: this.manager.tooltips.map((t, i) => {
9904
9930
  let tv = this.manager.tooltipViews[i];
9905
9931
  return tv.getCoords ? tv.getCoords(t.pos) : this.view.coordsAtPos(t.pos);
@@ -9917,16 +9943,16 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
9917
9943
  for (let t of this.manager.tooltipViews)
9918
9944
  t.dom.style.position = "absolute";
9919
9945
  }
9920
- let { editor, space, scaleX, scaleY } = measured;
9946
+ let { visible, space, scaleX, scaleY } = measured;
9921
9947
  let others = [];
9922
9948
  for (let i = 0; i < this.manager.tooltips.length; i++) {
9923
9949
  let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
9924
9950
  let pos = measured.pos[i], size = measured.size[i];
9925
9951
  // Hide tooltips that are outside of the editor.
9926
- if (!pos || pos.bottom <= Math.max(editor.top, space.top) ||
9927
- pos.top >= Math.min(editor.bottom, space.bottom) ||
9928
- pos.right < Math.max(editor.left, space.left) - .1 ||
9929
- pos.left > Math.min(editor.right, space.right) + .1) {
9952
+ if (!pos || pos.bottom <= Math.max(visible.top, space.top) ||
9953
+ pos.top >= Math.min(visible.bottom, space.bottom) ||
9954
+ pos.right < Math.max(visible.left, space.left) - .1 ||
9955
+ pos.left > Math.min(visible.right, space.right) + .1) {
9930
9956
  dom.style.top = Outside;
9931
9957
  continue;
9932
9958
  }
@@ -9940,8 +9966,8 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
9940
9966
  : Math.min(Math.max(space.left, pos.left - width + (arrow ? 14 /* Arrow.Offset */ : 0) - offset.x), space.right - width);
9941
9967
  let above = this.above[i];
9942
9968
  if (!tooltip.strictSide && (above
9943
- ? pos.top - (size.bottom - size.top) - offset.y < space.top
9944
- : pos.bottom + (size.bottom - size.top) + offset.y > space.bottom) &&
9969
+ ? pos.top - height - arrowHeight - offset.y < space.top
9970
+ : pos.bottom + height + arrowHeight + offset.y > space.bottom) &&
9945
9971
  above == (space.bottom - pos.bottom > pos.top - space.top))
9946
9972
  above = this.above[i] = !above;
9947
9973
  let spaceVert = (above ? pos.top - space.top : space.bottom - pos.bottom) - arrowHeight;
@@ -10001,7 +10027,7 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
10001
10027
  });
10002
10028
  const baseTheme = EditorView.baseTheme({
10003
10029
  ".cm-tooltip": {
10004
- zIndex: 100,
10030
+ zIndex: 500,
10005
10031
  boxSizing: "border-box"
10006
10032
  },
10007
10033
  "&light .cm-tooltip": {
package/dist/index.js CHANGED
@@ -6482,7 +6482,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
6482
6482
  display: "none"
6483
6483
  },
6484
6484
  "&dark .cm-cursor": {
6485
- borderLeftColor: "#444"
6485
+ borderLeftColor: "#ddd"
6486
6486
  },
6487
6487
  ".cm-dropCursor": {
6488
6488
  position: "absolute"
@@ -7150,6 +7150,9 @@ class EditContextManager {
7150
7150
  // user action on some Android keyboards)
7151
7151
  this.pendingContextChange = null;
7152
7152
  this.handlers = Object.create(null);
7153
+ // Kludge to work around the fact that EditContext does not respond
7154
+ // well to having its content updated during a composition (see #1472)
7155
+ this.composing = null;
7153
7156
  this.resetRange(view.state);
7154
7157
  let context = this.editContext = new window.EditContext({
7155
7158
  text: view.state.doc.sliceString(this.from, this.to),
@@ -7158,9 +7161,10 @@ class EditContextManager {
7158
7161
  });
7159
7162
  this.handlers.textupdate = e => {
7160
7163
  let { anchor } = view.state.selection.main;
7161
- let change = { from: this.toEditorPos(e.updateRangeStart),
7162
- to: this.toEditorPos(e.updateRangeEnd),
7163
- insert: Text.of(e.text.split("\n")) };
7164
+ let from = this.toEditorPos(e.updateRangeStart), to = this.toEditorPos(e.updateRangeEnd);
7165
+ if (view.inputState.composing >= 0 && !this.composing)
7166
+ this.composing = { contextBase: e.updateRangeStart, editorBase: from, drifted: false };
7167
+ let change = { from, to, insert: Text.of(e.text.split("\n")) };
7164
7168
  // If the window doesn't include the anchor, assume changes
7165
7169
  // adjacent to a side go up to the anchor.
7166
7170
  if (change.from == this.from && anchor < this.from)
@@ -7211,6 +7215,12 @@ class EditContextManager {
7211
7215
  this.handlers.compositionend = () => {
7212
7216
  view.inputState.composing = -1;
7213
7217
  view.inputState.compositionFirstChange = null;
7218
+ if (this.composing) {
7219
+ let { drifted } = this.composing;
7220
+ this.composing = null;
7221
+ if (drifted)
7222
+ this.reset(view.state);
7223
+ }
7214
7224
  };
7215
7225
  for (let event in this.handlers)
7216
7226
  context.addEventListener(event, this.handlers[event]);
@@ -7261,11 +7271,13 @@ class EditContextManager {
7261
7271
  }
7262
7272
  update(update) {
7263
7273
  let reverted = this.pendingContextChange;
7264
- if (!this.applyEdits(update) || !this.rangeIsValid(update.state)) {
7274
+ if (this.composing && (this.composing.drifted || update.transactions.some(tr => !tr.isUserEvent("input.type") && tr.changes.touchesRange(this.from, this.to)))) {
7275
+ this.composing.drifted = true;
7276
+ this.composing.editorBase = update.changes.mapPos(this.composing.editorBase);
7277
+ }
7278
+ else if (!this.applyEdits(update) || !this.rangeIsValid(update.state)) {
7265
7279
  this.pendingContextChange = null;
7266
- this.resetRange(update.state);
7267
- this.editContext.updateText(0, this.editContext.text.length, update.state.doc.sliceString(this.from, this.to));
7268
- this.setSelection(update.state);
7280
+ this.reset(update.state);
7269
7281
  }
7270
7282
  else if (update.docChanged || update.selectionSet || reverted) {
7271
7283
  this.setSelection(update.state);
@@ -7278,6 +7290,11 @@ class EditContextManager {
7278
7290
  this.from = Math.max(0, head - 10000 /* CxVp.Margin */);
7279
7291
  this.to = Math.min(state.doc.length, head + 10000 /* CxVp.Margin */);
7280
7292
  }
7293
+ reset(state) {
7294
+ this.resetRange(state);
7295
+ this.editContext.updateText(0, this.editContext.text.length, state.doc.sliceString(this.from, this.to));
7296
+ this.setSelection(state);
7297
+ }
7281
7298
  revertPending(state) {
7282
7299
  let pending = this.pendingContextChange;
7283
7300
  this.pendingContextChange = null;
@@ -7296,8 +7313,14 @@ class EditContextManager {
7296
7313
  this.to < state.doc.length && this.to - head < 500 /* CxVp.MinMargin */ ||
7297
7314
  this.to - this.from > 10000 /* CxVp.Margin */ * 3);
7298
7315
  }
7299
- toEditorPos(contextPos) { return contextPos + this.from; }
7300
- toContextPos(editorPos) { return editorPos - this.from; }
7316
+ toEditorPos(contextPos) {
7317
+ let c = this.composing;
7318
+ return c && c.drifted ? c.editorBase + (contextPos - c.contextBase) : contextPos + this.from;
7319
+ }
7320
+ toContextPos(editorPos) {
7321
+ let c = this.composing;
7322
+ return c && c.drifted ? c.contextBase + (editorPos - c.editorBase) : editorPos - this.from;
7323
+ }
7301
7324
  destroy() {
7302
7325
  for (let event in this.handlers)
7303
7326
  this.editContext.removeEventListener(event, this.handlers[event]);
@@ -9863,7 +9886,6 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9863
9886
  clearTimeout(this.measureTimeout);
9864
9887
  }
9865
9888
  readMeasure() {
9866
- let editor = this.view.dom.getBoundingClientRect();
9867
9889
  let scaleX = 1, scaleY = 1, makeAbsolute = false;
9868
9890
  if (this.position == "fixed" && this.manager.tooltipViews.length) {
9869
9891
  let { dom } = this.manager.tooltipViews[0];
@@ -9892,9 +9914,13 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9892
9914
  ({ scaleX, scaleY } = this.view.viewState);
9893
9915
  }
9894
9916
  }
9917
+ let visible = this.view.scrollDOM.getBoundingClientRect(), margins = getScrollMargins(this.view);
9895
9918
  return {
9896
- editor,
9897
- parent: this.parent ? this.container.getBoundingClientRect() : editor,
9919
+ visible: {
9920
+ left: visible.left + margins.left, top: visible.top + margins.top,
9921
+ right: visible.right - margins.right, bottom: visible.bottom - margins.bottom
9922
+ },
9923
+ parent: this.parent ? this.container.getBoundingClientRect() : this.view.dom.getBoundingClientRect(),
9898
9924
  pos: this.manager.tooltips.map((t, i) => {
9899
9925
  let tv = this.manager.tooltipViews[i];
9900
9926
  return tv.getCoords ? tv.getCoords(t.pos) : this.view.coordsAtPos(t.pos);
@@ -9912,16 +9938,16 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9912
9938
  for (let t of this.manager.tooltipViews)
9913
9939
  t.dom.style.position = "absolute";
9914
9940
  }
9915
- let { editor, space, scaleX, scaleY } = measured;
9941
+ let { visible, space, scaleX, scaleY } = measured;
9916
9942
  let others = [];
9917
9943
  for (let i = 0; i < this.manager.tooltips.length; i++) {
9918
9944
  let tooltip = this.manager.tooltips[i], tView = this.manager.tooltipViews[i], { dom } = tView;
9919
9945
  let pos = measured.pos[i], size = measured.size[i];
9920
9946
  // Hide tooltips that are outside of the editor.
9921
- if (!pos || pos.bottom <= Math.max(editor.top, space.top) ||
9922
- pos.top >= Math.min(editor.bottom, space.bottom) ||
9923
- pos.right < Math.max(editor.left, space.left) - .1 ||
9924
- pos.left > Math.min(editor.right, space.right) + .1) {
9947
+ if (!pos || pos.bottom <= Math.max(visible.top, space.top) ||
9948
+ pos.top >= Math.min(visible.bottom, space.bottom) ||
9949
+ pos.right < Math.max(visible.left, space.left) - .1 ||
9950
+ pos.left > Math.min(visible.right, space.right) + .1) {
9925
9951
  dom.style.top = Outside;
9926
9952
  continue;
9927
9953
  }
@@ -9935,8 +9961,8 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9935
9961
  : Math.min(Math.max(space.left, pos.left - width + (arrow ? 14 /* Arrow.Offset */ : 0) - offset.x), space.right - width);
9936
9962
  let above = this.above[i];
9937
9963
  if (!tooltip.strictSide && (above
9938
- ? pos.top - (size.bottom - size.top) - offset.y < space.top
9939
- : pos.bottom + (size.bottom - size.top) + offset.y > space.bottom) &&
9964
+ ? pos.top - height - arrowHeight - offset.y < space.top
9965
+ : pos.bottom + height + arrowHeight + offset.y > space.bottom) &&
9940
9966
  above == (space.bottom - pos.bottom > pos.top - space.top))
9941
9967
  above = this.above[i] = !above;
9942
9968
  let spaceVert = (above ? pos.top - space.top : space.bottom - pos.bottom) - arrowHeight;
@@ -9996,7 +10022,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
9996
10022
  });
9997
10023
  const baseTheme = /*@__PURE__*/EditorView.baseTheme({
9998
10024
  ".cm-tooltip": {
9999
- zIndex: 100,
10025
+ zIndex: 500,
10000
10026
  boxSizing: "border-box"
10001
10027
  },
10002
10028
  "&light .cm-tooltip": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.34.1",
3
+ "version": "6.34.3",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",