@codemirror/view 0.20.1 → 0.20.4

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,23 @@
1
+ ## 0.20.4 (2022-05-03)
2
+
3
+ ### Bug fixes
4
+
5
+ Prevent Mac-style behavior of inserting a period when the user inserts two spaces.
6
+
7
+ Fix an issue where the editor would sometimes not restore the DOM selection when refocused with a selection identical to the one it held when it lost focus.
8
+
9
+ ## 0.20.3 (2022-04-27)
10
+
11
+ ### Bug fixes
12
+
13
+ Fix a bug where the input handling could crash on repeated (or held) backspace presses on Chrome Android.
14
+
15
+ ## 0.20.2 (2022-04-22)
16
+
17
+ ### New features
18
+
19
+ The new `hideOn` option to `hoverTooltip` allows more fine-grained control over when the tooltip should hide.
20
+
1
21
  ## 0.20.1 (2022-04-20)
2
22
 
3
23
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1157,9 +1157,6 @@ of content. You'll usually use it wrapped in a
1157
1157
  @nonabstract
1158
1158
  */
1159
1159
  class Decoration extends state.RangeValue {
1160
- /**
1161
- @internal
1162
- */
1163
1160
  constructor(
1164
1161
  /**
1165
1162
  @internal
@@ -1704,7 +1701,6 @@ class NullWidget extends WidgetType {
1704
1701
  updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
1705
1702
  }
1706
1703
 
1707
- const none = [];
1708
1704
  const clickAddsSelectionRange = state.Facet.define();
1709
1705
  const dragMovesSelection$1 = state.Facet.define();
1710
1706
  const mouseSelectionStyle = state.Facet.define();
@@ -1923,9 +1919,6 @@ View [plugins](https://codemirror.net/6/docs/ref/#view.ViewPlugin) are given ins
1923
1919
  class, which describe what happened, whenever the view is updated.
1924
1920
  */
1925
1921
  class ViewUpdate {
1926
- /**
1927
- @internal
1928
- */
1929
1922
  constructor(
1930
1923
  /**
1931
1924
  The editor view that the update is associated with.
@@ -1938,7 +1931,7 @@ class ViewUpdate {
1938
1931
  /**
1939
1932
  The transactions involved in the update. May be empty.
1940
1933
  */
1941
- transactions = none) {
1934
+ transactions) {
1942
1935
  this.view = view;
1943
1936
  this.state = state$1;
1944
1937
  this.transactions = transactions;
@@ -1960,6 +1953,12 @@ class ViewUpdate {
1960
1953
  }
1961
1954
  }
1962
1955
  /**
1956
+ @internal
1957
+ */
1958
+ static create(view, state, transactions) {
1959
+ return new ViewUpdate(view, state, transactions);
1960
+ }
1961
+ /**
1963
1962
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
1964
1963
  [visible ranges](https://codemirror.net/6/docs/ref/#view.EditorView.visibleRanges) changed in this
1965
1964
  update.
@@ -2880,7 +2879,8 @@ function computeCompositionDeco(view, changes) {
2880
2879
  topView = topView.widget.topView;
2881
2880
  else if (topView)
2882
2881
  topView.parent = null;
2883
- return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView) }).range(newFrom, newTo));
2882
+ return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView), inclusive: true })
2883
+ .range(newFrom, newTo));
2884
2884
  }
2885
2885
  class CompositionWidget extends WidgetType {
2886
2886
  constructor(top, text, topView) {
@@ -3844,11 +3844,16 @@ handlers.copy = handlers.cut = (view, event) => {
3844
3844
  userEvent: "delete.cut"
3845
3845
  });
3846
3846
  };
3847
- handlers.focus = handlers.blur = view => {
3847
+ function updateForFocusChange(view) {
3848
3848
  setTimeout(() => {
3849
3849
  if (view.hasFocus != view.inputState.notifiedFocused)
3850
3850
  view.update([]);
3851
3851
  }, 10);
3852
+ }
3853
+ handlers.focus = updateForFocusChange;
3854
+ handlers.blur = view => {
3855
+ view.observer.clearSelectionRange();
3856
+ updateForFocusChange(view);
3852
3857
  };
3853
3858
  function forceClearComposition(view, rapid) {
3854
3859
  if (view.docView.compositionDeco.size) {
@@ -5486,6 +5491,9 @@ class DOMObserver {
5486
5491
  this.selectionRange.set(anchor.node, anchor.offset, head.node, head.offset);
5487
5492
  this.selectionChanged = false;
5488
5493
  }
5494
+ clearSelectionRange() {
5495
+ this.selectionRange.set(null, 0, null, 0);
5496
+ }
5489
5497
  listenForScroll() {
5490
5498
  this.parentCheck = -1;
5491
5499
  let i = 0, changed = null;
@@ -5563,6 +5571,7 @@ class DOMObserver {
5563
5571
  let key = this.delayedAndroidKey;
5564
5572
  this.delayedAndroidKey = null;
5565
5573
  let startState = this.view.state;
5574
+ this.readSelectionRange();
5566
5575
  if (dispatchKey(this.view.contentDOM, key.key, key.keyCode))
5567
5576
  this.processRecords();
5568
5577
  else
@@ -5764,6 +5773,11 @@ function applyDOMChange(view, start, end, typeOver) {
5764
5773
  from: sel.from, to: sel.to,
5765
5774
  insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
5766
5775
  };
5776
+ // Detect insert-period-on-double-space Mac behavior, and transform
5777
+ // it into a regular space insert.
5778
+ else if (browser.mac && change && change.from == change.to && change.from == sel.head - 1 &&
5779
+ change.insert.toString() == ".")
5780
+ change = { from: sel.from, to: sel.to, insert: state.Text.of([" "]) };
5767
5781
  if (change) {
5768
5782
  let startState = view.state;
5769
5783
  if (browser.ios && view.inputState.flushIOSKey(view))
@@ -6052,7 +6066,7 @@ class EditorView {
6052
6066
  // When the phrases change, redraw the editor
6053
6067
  if (state$1.facet(state.EditorState.phrases) != this.state.facet(state.EditorState.phrases))
6054
6068
  return this.setState(state$1);
6055
- update = new ViewUpdate(this, state$1, transactions);
6069
+ update = ViewUpdate.create(this, state$1, transactions);
6056
6070
  let scrollTarget = this.viewState.scrollTarget;
6057
6071
  try {
6058
6072
  this.updateState = 2 /* Updating */;
@@ -6195,7 +6209,7 @@ class EditorView {
6195
6209
  return BadMeasure;
6196
6210
  }
6197
6211
  });
6198
- let update = new ViewUpdate(this, this.state), redrawn = false, scrolled = false;
6212
+ let update = ViewUpdate.create(this, this.state, []), redrawn = false, scrolled = false;
6199
6213
  update.flags |= changed;
6200
6214
  if (!updated)
6201
6215
  updated = update;
@@ -6655,8 +6669,8 @@ EditorView.inputHandler = inputHandler;
6655
6669
  /**
6656
6670
  By default, the editor assumes all its content has the same
6657
6671
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
6658
- value to make it read and store the text direction of every
6659
- (rendered) line separately.
6672
+ value to make it read the text direction of every (rendered)
6673
+ line separately.
6660
6674
  */
6661
6675
  EditorView.perLineTextDirection = perLineTextDirection;
6662
6676
  /**
@@ -8261,7 +8275,8 @@ function hoverTooltip(source, options = {}) {
8261
8275
  let hoverState = state.StateField.define({
8262
8276
  create() { return null; },
8263
8277
  update(value, tr) {
8264
- if (value && (options.hideOnChange && (tr.docChanged || tr.selection)))
8278
+ if (value && (options.hideOnChange && (tr.docChanged || tr.selection) ||
8279
+ options.hideOn && options.hideOn(tr, value)))
8265
8280
  return null;
8266
8281
  if (value && tr.docChanged) {
8267
8282
  let newPos = tr.changes.mapPos(value.pos, -1, state.MapMode.TrackDel);
package/dist/index.d.ts CHANGED
@@ -214,6 +214,25 @@ declare abstract class Decoration extends RangeValue {
214
214
  your decoration.
215
215
  */
216
216
  readonly spec: any;
217
+ protected constructor(
218
+ /**
219
+ @internal
220
+ */
221
+ startSide: number,
222
+ /**
223
+ @internal
224
+ */
225
+ endSide: number,
226
+ /**
227
+ @internal
228
+ */
229
+ widget: WidgetType | null,
230
+ /**
231
+ The config object used to create this decoration. You can
232
+ include additional properties in there to store metadata about
233
+ your decoration.
234
+ */
235
+ spec: any);
217
236
  abstract eq(other: Decoration): boolean;
218
237
  /**
219
238
  Create a mark decoration, which influences the styling of the
@@ -324,10 +343,10 @@ interface PluginSpec<V extends PluginValue> {
324
343
  provide?: (plugin: ViewPlugin<V>) => Extension;
325
344
  /**
326
345
  Allow the plugin to provide decorations. When given, this should
327
- a function that take the plugin value and return a [decoration
328
- set](https://codemirror.net/6/docs/ref/#view.DecorationSet). See also the caveat about
329
- [layout-changing decorations](https://codemirror.net/6/docs/ref/#view.EditorView^decorations)
330
- that depend on the view.
346
+ be a function that take the plugin value and return a
347
+ [decoration set](https://codemirror.net/6/docs/ref/#view.DecorationSet). See also the caveat about
348
+ [layout-changing decorations](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) that
349
+ depend on the view.
331
350
  */
332
351
  decorations?: (value: V) => DecorationSet;
333
352
  }
@@ -398,6 +417,7 @@ declare class ViewUpdate {
398
417
  The previous editor state.
399
418
  */
400
419
  readonly startState: EditorState;
420
+ private constructor();
401
421
  /**
402
422
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
403
423
  [visible ranges](https://codemirror.net/6/docs/ref/#view.EditorView.visibleRanges) changed in this
@@ -968,8 +988,8 @@ declare class EditorView {
968
988
  /**
969
989
  By default, the editor assumes all its content has the same
970
990
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
971
- value to make it read and store the text direction of every
972
- (rendered) line separately.
991
+ value to make it read the text direction of every (rendered)
992
+ line separately.
973
993
  */
974
994
  static perLineTextDirection: Facet<boolean, boolean>;
975
995
  /**
@@ -1546,11 +1566,16 @@ container element. This allows multiple tooltips over the same
1546
1566
  range to be "merged" together without overlapping.
1547
1567
  */
1548
1568
  declare function hoverTooltip(source: (view: EditorView, pos: number, side: -1 | 1) => Tooltip | null | Promise<Tooltip | null>, options?: {
1569
+ /**
1570
+ Controls whether a transaction hides the tooltip. The default
1571
+ is to not hide.
1572
+ */
1573
+ hideOn?: (tr: Transaction, tooltip: Tooltip) => boolean;
1549
1574
  /**
1550
1575
  When enabled (this defaults to false), close the tooltip
1551
- whenever the document changes.
1576
+ whenever the document changes or the selection is set.
1552
1577
  */
1553
- hideOnChange?: boolean;
1578
+ hideOnChange?: boolean | "touch";
1554
1579
  /**
1555
1580
  Hover time after which the tooltip should appear, in
1556
1581
  milliseconds. Defaults to 300ms.
package/dist/index.js CHANGED
@@ -1152,9 +1152,6 @@ of content. You'll usually use it wrapped in a
1152
1152
  @nonabstract
1153
1153
  */
1154
1154
  class Decoration extends RangeValue {
1155
- /**
1156
- @internal
1157
- */
1158
1155
  constructor(
1159
1156
  /**
1160
1157
  @internal
@@ -1699,7 +1696,6 @@ class NullWidget extends WidgetType {
1699
1696
  updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
1700
1697
  }
1701
1698
 
1702
- const none = [];
1703
1699
  const clickAddsSelectionRange = /*@__PURE__*/Facet.define();
1704
1700
  const dragMovesSelection$1 = /*@__PURE__*/Facet.define();
1705
1701
  const mouseSelectionStyle = /*@__PURE__*/Facet.define();
@@ -1918,9 +1914,6 @@ View [plugins](https://codemirror.net/6/docs/ref/#view.ViewPlugin) are given ins
1918
1914
  class, which describe what happened, whenever the view is updated.
1919
1915
  */
1920
1916
  class ViewUpdate {
1921
- /**
1922
- @internal
1923
- */
1924
1917
  constructor(
1925
1918
  /**
1926
1919
  The editor view that the update is associated with.
@@ -1933,7 +1926,7 @@ class ViewUpdate {
1933
1926
  /**
1934
1927
  The transactions involved in the update. May be empty.
1935
1928
  */
1936
- transactions = none) {
1929
+ transactions) {
1937
1930
  this.view = view;
1938
1931
  this.state = state;
1939
1932
  this.transactions = transactions;
@@ -1955,6 +1948,12 @@ class ViewUpdate {
1955
1948
  }
1956
1949
  }
1957
1950
  /**
1951
+ @internal
1952
+ */
1953
+ static create(view, state, transactions) {
1954
+ return new ViewUpdate(view, state, transactions);
1955
+ }
1956
+ /**
1958
1957
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
1959
1958
  [visible ranges](https://codemirror.net/6/docs/ref/#view.EditorView.visibleRanges) changed in this
1960
1959
  update.
@@ -2874,7 +2873,8 @@ function computeCompositionDeco(view, changes) {
2874
2873
  topView = topView.widget.topView;
2875
2874
  else if (topView)
2876
2875
  topView.parent = null;
2877
- return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView) }).range(newFrom, newTo));
2876
+ return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView), inclusive: true })
2877
+ .range(newFrom, newTo));
2878
2878
  }
2879
2879
  class CompositionWidget extends WidgetType {
2880
2880
  constructor(top, text, topView) {
@@ -3838,11 +3838,16 @@ handlers.copy = handlers.cut = (view, event) => {
3838
3838
  userEvent: "delete.cut"
3839
3839
  });
3840
3840
  };
3841
- handlers.focus = handlers.blur = view => {
3841
+ function updateForFocusChange(view) {
3842
3842
  setTimeout(() => {
3843
3843
  if (view.hasFocus != view.inputState.notifiedFocused)
3844
3844
  view.update([]);
3845
3845
  }, 10);
3846
+ }
3847
+ handlers.focus = updateForFocusChange;
3848
+ handlers.blur = view => {
3849
+ view.observer.clearSelectionRange();
3850
+ updateForFocusChange(view);
3846
3851
  };
3847
3852
  function forceClearComposition(view, rapid) {
3848
3853
  if (view.docView.compositionDeco.size) {
@@ -5479,6 +5484,9 @@ class DOMObserver {
5479
5484
  this.selectionRange.set(anchor.node, anchor.offset, head.node, head.offset);
5480
5485
  this.selectionChanged = false;
5481
5486
  }
5487
+ clearSelectionRange() {
5488
+ this.selectionRange.set(null, 0, null, 0);
5489
+ }
5482
5490
  listenForScroll() {
5483
5491
  this.parentCheck = -1;
5484
5492
  let i = 0, changed = null;
@@ -5556,6 +5564,7 @@ class DOMObserver {
5556
5564
  let key = this.delayedAndroidKey;
5557
5565
  this.delayedAndroidKey = null;
5558
5566
  let startState = this.view.state;
5567
+ this.readSelectionRange();
5559
5568
  if (dispatchKey(this.view.contentDOM, key.key, key.keyCode))
5560
5569
  this.processRecords();
5561
5570
  else
@@ -5757,6 +5766,11 @@ function applyDOMChange(view, start, end, typeOver) {
5757
5766
  from: sel.from, to: sel.to,
5758
5767
  insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
5759
5768
  };
5769
+ // Detect insert-period-on-double-space Mac behavior, and transform
5770
+ // it into a regular space insert.
5771
+ else if (browser.mac && change && change.from == change.to && change.from == sel.head - 1 &&
5772
+ change.insert.toString() == ".")
5773
+ change = { from: sel.from, to: sel.to, insert: Text.of([" "]) };
5760
5774
  if (change) {
5761
5775
  let startState = view.state;
5762
5776
  if (browser.ios && view.inputState.flushIOSKey(view))
@@ -6045,7 +6059,7 @@ class EditorView {
6045
6059
  // When the phrases change, redraw the editor
6046
6060
  if (state.facet(EditorState.phrases) != this.state.facet(EditorState.phrases))
6047
6061
  return this.setState(state);
6048
- update = new ViewUpdate(this, state, transactions);
6062
+ update = ViewUpdate.create(this, state, transactions);
6049
6063
  let scrollTarget = this.viewState.scrollTarget;
6050
6064
  try {
6051
6065
  this.updateState = 2 /* Updating */;
@@ -6188,7 +6202,7 @@ class EditorView {
6188
6202
  return BadMeasure;
6189
6203
  }
6190
6204
  });
6191
- let update = new ViewUpdate(this, this.state), redrawn = false, scrolled = false;
6205
+ let update = ViewUpdate.create(this, this.state, []), redrawn = false, scrolled = false;
6192
6206
  update.flags |= changed;
6193
6207
  if (!updated)
6194
6208
  updated = update;
@@ -6648,8 +6662,8 @@ EditorView.inputHandler = inputHandler;
6648
6662
  /**
6649
6663
  By default, the editor assumes all its content has the same
6650
6664
  [text direction](https://codemirror.net/6/docs/ref/#view.Direction). Configure this with a `true`
6651
- value to make it read and store the text direction of every
6652
- (rendered) line separately.
6665
+ value to make it read the text direction of every (rendered)
6666
+ line separately.
6653
6667
  */
6654
6668
  EditorView.perLineTextDirection = perLineTextDirection;
6655
6669
  /**
@@ -8254,7 +8268,8 @@ function hoverTooltip(source, options = {}) {
8254
8268
  let hoverState = StateField.define({
8255
8269
  create() { return null; },
8256
8270
  update(value, tr) {
8257
- if (value && (options.hideOnChange && (tr.docChanged || tr.selection)))
8271
+ if (value && (options.hideOnChange && (tr.docChanged || tr.selection) ||
8272
+ options.hideOn && options.hideOn(tr, value)))
8258
8273
  return null;
8259
8274
  if (value && tr.docChanged) {
8260
8275
  let newPos = tr.changes.mapPos(value.pos, -1, MapMode.TrackDel);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "0.20.1",
3
+ "version": "0.20.4",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",