@codemirror/autocomplete 6.9.0 → 6.9.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,11 @@
1
+ ## 6.9.1 (2023-09-14)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure the cursor is scrolled into view after inserting completion text.
6
+
7
+ Make sure scrolling completions into view doesn't get confused when the tooltip is scaled.
8
+
1
9
  ## 6.9.0 (2023-07-18)
2
10
 
3
11
  ### New features
package/dist/index.cjs CHANGED
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var state = require('@codemirror/state');
6
4
  var view = require('@codemirror/view');
7
5
  var language = require('@codemirror/language');
@@ -175,7 +173,7 @@ function insertCompletionText(state$1, text, from, to) {
175
173
  changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
176
174
  range: state.EditorSelection.cursor(range.from + fromOff + text.length)
177
175
  };
178
- })), { userEvent: "input.complete" });
176
+ })), { scrollIntoView: true, userEvent: "input.complete" });
179
177
  }
180
178
  const SourceCache = new WeakMap();
181
179
  function asSource(source) {
@@ -227,7 +225,7 @@ class FuzzyMatcher {
227
225
  // is. See `Penalty` above.
228
226
  match(word) {
229
227
  if (this.pattern.length == 0)
230
- return this.ret(-100 /* NotFull */, []);
228
+ return this.ret(-100 /* Penalty.NotFull */, []);
231
229
  if (word.length < this.pattern.length)
232
230
  return false;
233
231
  let { chars, folded, any, precise, byWord } = this;
@@ -235,17 +233,17 @@ class FuzzyMatcher {
235
233
  // at the start
236
234
  if (chars.length == 1) {
237
235
  let first = state.codePointAt(word, 0), firstSize = state.codePointSize(first);
238
- let score = firstSize == word.length ? 0 : -100 /* NotFull */;
236
+ let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
239
237
  if (first == chars[0]) ;
240
238
  else if (first == folded[0])
241
- score += -200 /* CaseFold */;
239
+ score += -200 /* Penalty.CaseFold */;
242
240
  else
243
241
  return false;
244
242
  return this.ret(score, [0, firstSize]);
245
243
  }
246
244
  let direct = word.indexOf(this.pattern);
247
245
  if (direct == 0)
248
- return this.ret(word.length == this.pattern.length ? 0 : -100 /* NotFull */, [0, this.pattern.length]);
246
+ return this.ret(word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, [0, this.pattern.length]);
249
247
  let len = chars.length, anyTo = 0;
250
248
  if (direct < 0) {
251
249
  for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
@@ -269,7 +267,7 @@ class FuzzyMatcher {
269
267
  let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
270
268
  let hasLower = /[a-z]/.test(word), wordAdjacent = true;
271
269
  // Go over the option's text, scanning for the various kinds of matches
272
- for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
270
+ for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) {
273
271
  let next = state.codePointAt(word, i);
274
272
  if (direct < 0) {
275
273
  if (preciseTo < len && next == chars[preciseTo])
@@ -287,9 +285,9 @@ class FuzzyMatcher {
287
285
  }
288
286
  }
289
287
  let ch, type = next < 0xff
290
- ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
291
- : ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
292
- if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
288
+ ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */)
289
+ : ((ch = state.fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */);
290
+ if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) {
293
291
  if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
294
292
  byWord[byWordTo++] = i;
295
293
  else if (byWord.length)
@@ -299,18 +297,18 @@ class FuzzyMatcher {
299
297
  i += state.codePointSize(next);
300
298
  }
301
299
  if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
302
- return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
300
+ return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
303
301
  if (adjacentTo == len && adjacentStart == 0)
304
- return this.ret(-200 /* CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* NotFull */), [0, adjacentEnd]);
302
+ return this.ret(-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), [0, adjacentEnd]);
305
303
  if (direct > -1)
306
- return this.ret(-700 /* NotStart */ - word.length, [direct, direct + this.pattern.length]);
304
+ return this.ret(-700 /* Penalty.NotStart */ - word.length, [direct, direct + this.pattern.length]);
307
305
  if (adjacentTo == len)
308
- return this.ret(-200 /* CaseFold */ + -700 /* NotStart */ - word.length, [adjacentStart, adjacentEnd]);
306
+ return this.ret(-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, [adjacentStart, adjacentEnd]);
309
307
  if (byWordTo == len)
310
- return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
311
- (wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
308
+ return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ +
309
+ (wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word);
312
310
  return chars.length == 2 ? false
313
- : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
311
+ : this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word);
314
312
  }
315
313
  result(score, positions, word) {
316
314
  let result = [], i = 0;
@@ -357,7 +355,7 @@ const completionConfig = state.Facet.define({
357
355
  function joinClass(a, b) {
358
356
  return a ? b ? a + " " + b : a : b;
359
357
  }
360
- function defaultPositionInfo(view$1, list, option, info, space) {
358
+ function defaultPositionInfo(view$1, list, option, info, space, tooltip) {
361
359
  let rtl = view$1.textDirection == view.Direction.RTL, left = rtl, narrow = false;
362
360
  let side = "top", offset, maxWidth;
363
361
  let spaceLeft = list.left - space.left, spaceRight = space.right - list.right;
@@ -368,11 +366,11 @@ function defaultPositionInfo(view$1, list, option, info, space) {
368
366
  left = true;
369
367
  if (infoWidth <= (left ? spaceLeft : spaceRight)) {
370
368
  offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
371
- maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
369
+ maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight);
372
370
  }
373
371
  else {
374
372
  narrow = true;
375
- maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
373
+ maxWidth = Math.min(400 /* Info.Width */, (rtl ? list.right : space.right - list.left) - 30 /* Info.Margin */);
376
374
  let spaceBelow = space.bottom - list.bottom;
377
375
  if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
378
376
  offset = option.bottom - list.top;
@@ -382,8 +380,10 @@ function defaultPositionInfo(view$1, list, option, info, space) {
382
380
  offset = list.bottom - option.top;
383
381
  }
384
382
  }
383
+ let scaleY = (list.bottom - list.top) / tooltip.offsetHeight;
384
+ let scaleX = (list.right - list.left) / tooltip.offsetWidth;
385
385
  return {
386
- style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
386
+ style: `${side}: ${offset / scaleY}px; max-width: ${maxWidth / scaleX}px`,
387
387
  class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right")
388
388
  };
389
389
  }
@@ -603,7 +603,7 @@ class CompletionTooltip {
603
603
  if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
604
604
  selRect.bottom < Math.max(space.top, listRect.top) + 10)
605
605
  return null;
606
- return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space);
606
+ return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space, this.dom);
607
607
  }
608
608
  placeInfo(pos) {
609
609
  if (this.info) {
@@ -677,10 +677,11 @@ function completionTooltip(stateField, applyCompletion) {
677
677
  function scrollIntoView(container, element) {
678
678
  let parent = container.getBoundingClientRect();
679
679
  let self = element.getBoundingClientRect();
680
+ let scaleY = parent.height / container.offsetHeight;
680
681
  if (self.top < parent.top)
681
- container.scrollTop -= parent.top - self.top;
682
+ container.scrollTop -= (parent.top - self.top) / scaleY;
682
683
  else if (self.bottom > parent.bottom)
683
- container.scrollTop += self.bottom - parent.bottom;
684
+ container.scrollTop += (self.bottom - parent.bottom) / scaleY;
684
685
  }
685
686
 
686
687
  // Used to pick a preferred option when two options with the same
@@ -763,7 +764,7 @@ class CompletionDialog {
763
764
  static build(active, state, id, prev, conf) {
764
765
  let options = sortOptions(active, state);
765
766
  if (!options.length) {
766
- return prev && active.some(a => a.state == 1 /* Pending */) ?
767
+ return prev && active.some(a => a.state == 1 /* State.Pending */) ?
767
768
  new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
768
769
  }
769
770
  let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
@@ -800,7 +801,7 @@ class CompletionState {
800
801
  state.languageDataAt("autocomplete", cur(state)).map(asSource);
801
802
  let active = sources.map(source => {
802
803
  let value = this.active.find(s => s.source == source) ||
803
- new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
804
+ new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
804
805
  return value.update(tr, conf);
805
806
  });
806
807
  if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
@@ -811,10 +812,10 @@ class CompletionState {
811
812
  if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
812
813
  !sameResults(active, this.active))
813
814
  open = CompletionDialog.build(active, state, this.id, open, conf);
814
- else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
815
+ else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */))
815
816
  open = null;
816
- if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
817
- active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
817
+ if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult()))
818
+ active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a);
818
819
  for (let effect of tr.effects)
819
820
  if (effect.is(setSelectedEffect))
820
821
  open = open && open.setSelected(effect.value, this.id);
@@ -868,13 +869,13 @@ class ActiveSource {
868
869
  value = value.handleUserEvent(tr, event, conf);
869
870
  else if (tr.docChanged)
870
871
  value = value.handleChange(tr);
871
- else if (tr.selection && value.state != 0 /* Inactive */)
872
- value = new ActiveSource(value.source, 0 /* Inactive */);
872
+ else if (tr.selection && value.state != 0 /* State.Inactive */)
873
+ value = new ActiveSource(value.source, 0 /* State.Inactive */);
873
874
  for (let effect of tr.effects) {
874
875
  if (effect.is(startCompletionEffect))
875
- value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
876
+ value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
876
877
  else if (effect.is(closeCompletionEffect))
877
- value = new ActiveSource(value.source, 0 /* Inactive */);
878
+ value = new ActiveSource(value.source, 0 /* State.Inactive */);
878
879
  else if (effect.is(setActiveEffect))
879
880
  for (let active of effect.value)
880
881
  if (active.source == value.source)
@@ -883,10 +884,10 @@ class ActiveSource {
883
884
  return value;
884
885
  }
885
886
  handleUserEvent(tr, type, conf) {
886
- return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
887
+ return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
887
888
  }
888
889
  handleChange(tr) {
889
- return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
890
+ return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
890
891
  }
891
892
  map(changes) {
892
893
  return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
@@ -894,7 +895,7 @@ class ActiveSource {
894
895
  }
895
896
  class ActiveResult extends ActiveSource {
896
897
  constructor(source, explicitPos, result, from, to) {
897
- super(source, 2 /* Result */, explicitPos);
898
+ super(source, 2 /* State.Result */, explicitPos);
898
899
  this.result = result;
899
900
  this.from = from;
900
901
  this.to = to;
@@ -907,17 +908,17 @@ class ActiveResult extends ActiveSource {
907
908
  if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
908
909
  pos > to ||
909
910
  type == "delete" && cur(tr.startState) == this.from)
910
- return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
911
+ return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
911
912
  let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
912
913
  if (checkValid(this.result.validFor, tr.state, from, to))
913
914
  return new ActiveResult(this.source, explicitPos, this.result, from, to);
914
915
  if (this.result.update &&
915
916
  (updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
916
917
  return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
917
- return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
918
+ return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
918
919
  }
919
920
  handleChange(tr) {
920
- return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
921
+ return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
921
922
  }
922
923
  map(mapping) {
923
924
  return mapping.empty ? this :
@@ -1003,7 +1004,7 @@ Close the currently active completion.
1003
1004
  */
1004
1005
  const closeCompletion = (view) => {
1005
1006
  let cState = view.state.field(completionState, false);
1006
- if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
1007
+ if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
1007
1008
  return false;
1008
1009
  view.dispatch({ effects: closeCompletionEffect.of(null) });
1009
1010
  return true;
@@ -1026,9 +1027,9 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1026
1027
  this.debounceUpdate = -1;
1027
1028
  this.running = [];
1028
1029
  this.debounceAccept = -1;
1029
- this.composing = 0 /* None */;
1030
+ this.composing = 0 /* CompositionState.None */;
1030
1031
  for (let active of view.state.field(completionState).active)
1031
- if (active.state == 1 /* Pending */)
1032
+ if (active.state == 1 /* State.Pending */)
1032
1033
  this.startQuery(active);
1033
1034
  }
1034
1035
  update(update) {
@@ -1059,21 +1060,21 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1059
1060
  }
1060
1061
  if (this.debounceUpdate > -1)
1061
1062
  clearTimeout(this.debounceUpdate);
1062
- this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
1063
+ this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
1063
1064
  ? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
1064
- if (this.composing != 0 /* None */)
1065
+ if (this.composing != 0 /* CompositionState.None */)
1065
1066
  for (let tr of update.transactions) {
1066
1067
  if (getUserEvent(tr) == "input")
1067
- this.composing = 2 /* Changed */;
1068
- else if (this.composing == 2 /* Changed */ && tr.selection)
1069
- this.composing = 3 /* ChangedAndMoved */;
1068
+ this.composing = 2 /* CompositionState.Changed */;
1069
+ else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
1070
+ this.composing = 3 /* CompositionState.ChangedAndMoved */;
1070
1071
  }
1071
1072
  }
1072
1073
  startUpdate() {
1073
1074
  this.debounceUpdate = -1;
1074
1075
  let { state } = this.view, cState = state.field(completionState);
1075
1076
  for (let active of cState.active) {
1076
- if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
1077
+ if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
1077
1078
  this.startQuery(active);
1078
1079
  }
1079
1080
  }
@@ -1124,14 +1125,14 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1124
1125
  }
1125
1126
  }
1126
1127
  let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
1127
- if (current && current.state == 1 /* Pending */) {
1128
+ if (current && current.state == 1 /* State.Pending */) {
1128
1129
  if (query.done == null) {
1129
1130
  // Explicitly failed. Should clear the pending status if it
1130
1131
  // hasn't been re-set in the meantime.
1131
- let active = new ActiveSource(query.active.source, 0 /* Inactive */);
1132
+ let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
1132
1133
  for (let tr of query.updates)
1133
1134
  active = active.update(tr, conf);
1134
- if (active.state != 1 /* Pending */)
1135
+ if (active.state != 1 /* State.Pending */)
1135
1136
  updated.push(active);
1136
1137
  }
1137
1138
  else {
@@ -1154,15 +1155,15 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1154
1155
  }
1155
1156
  },
1156
1157
  compositionstart() {
1157
- this.composing = 1 /* Started */;
1158
+ this.composing = 1 /* CompositionState.Started */;
1158
1159
  },
1159
1160
  compositionend() {
1160
- if (this.composing == 3 /* ChangedAndMoved */) {
1161
+ if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
1161
1162
  // Safari fires compositionend events synchronously, possibly
1162
1163
  // from inside an update, so dispatch asynchronously to avoid reentrancy
1163
1164
  setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
1164
1165
  }
1165
- this.composing = 0 /* None */;
1166
+ this.composing = 0 /* CompositionState.None */;
1166
1167
  }
1167
1168
  }
1168
1169
  });
@@ -1222,13 +1223,13 @@ const baseTheme = view.EditorView.baseTheme({
1222
1223
  position: "absolute",
1223
1224
  padding: "3px 9px",
1224
1225
  width: "max-content",
1225
- maxWidth: `${400 /* Width */}px`,
1226
+ maxWidth: `${400 /* Info.Width */}px`,
1226
1227
  boxSizing: "border-box"
1227
1228
  },
1228
1229
  ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
1229
1230
  ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
1230
- ".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
1231
- ".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
1231
+ ".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
1232
+ ".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
1232
1233
  "&light .cm-snippetField": { backgroundColor: "#00000022" },
1233
1234
  "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
1234
1235
  ".cm-snippetFieldPosition": {
@@ -1479,7 +1480,8 @@ function moveField(dir) {
1479
1480
  let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir);
1480
1481
  dispatch(state.update({
1481
1482
  selection: fieldSelection(active.ranges, next),
1482
- effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next))
1483
+ effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next)),
1484
+ scrollIntoView: true
1483
1485
  }));
1484
1486
  return true;
1485
1487
  };
@@ -1551,7 +1553,9 @@ const snippetPointerHandler = view.EditorView.domEventHandlers({
1551
1553
  return false;
1552
1554
  view.dispatch({
1553
1555
  selection: fieldSelection(active.ranges, match.field),
1554
- effects: setActive.of(active.ranges.some(r => r.field > match.field) ? new ActiveSnippet(active.ranges, match.field) : null)
1556
+ effects: setActive.of(active.ranges.some(r => r.field > match.field)
1557
+ ? new ActiveSnippet(active.ranges, match.field) : null),
1558
+ scrollIntoView: true
1555
1559
  });
1556
1560
  return true;
1557
1561
  }
@@ -1581,7 +1585,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
1581
1585
  if (!seen[m[0]] && pos + m.index != ignoreAt) {
1582
1586
  result.push({ type: "text", label: m[0] });
1583
1587
  seen[m[0]] = true;
1584
- if (result.length >= 2000 /* MaxList */)
1588
+ if (result.length >= 2000 /* C.MaxList */)
1585
1589
  return;
1586
1590
  }
1587
1591
  }
@@ -1589,7 +1593,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
1589
1593
  }
1590
1594
  }
1591
1595
  function collectWords(doc, cache, wordRE, to, ignoreAt) {
1592
- let big = doc.length >= 1000 /* MinCacheLen */;
1596
+ let big = doc.length >= 1000 /* C.MinCacheLen */;
1593
1597
  let cached = big && cache.get(doc);
1594
1598
  if (cached)
1595
1599
  return cached;
@@ -1597,7 +1601,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
1597
1601
  if (doc.children) {
1598
1602
  let pos = 0;
1599
1603
  for (let ch of doc.children) {
1600
- if (ch.length >= 1000 /* MinCacheLen */) {
1604
+ if (ch.length >= 1000 /* C.MinCacheLen */) {
1601
1605
  for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
1602
1606
  if (!seen[c.label]) {
1603
1607
  seen[c.label] = true;
@@ -1614,7 +1618,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
1614
1618
  else {
1615
1619
  storeWords(doc, wordRE, result, seen, ignoreAt);
1616
1620
  }
1617
- if (big && result.length < 2000 /* MaxList */)
1621
+ if (big && result.length < 2000 /* C.MaxList */)
1618
1622
  cache.set(doc, result);
1619
1623
  return result;
1620
1624
  }
@@ -1630,7 +1634,7 @@ const completeAnyWord = context => {
1630
1634
  if (!token && !context.explicit)
1631
1635
  return null;
1632
1636
  let from = token ? token.from : context.pos;
1633
- let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
1637
+ let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from);
1634
1638
  return { from, options, validFor: mapRE(re, s => "^" + s) };
1635
1639
  };
1636
1640
 
@@ -1922,8 +1926,8 @@ returns `null`.
1922
1926
  */
1923
1927
  function completionStatus(state) {
1924
1928
  let cState = state.field(completionState, false);
1925
- return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
1926
- : cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
1929
+ return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
1930
+ : cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
1927
1931
  }
1928
1932
  const completionArrayCache = new WeakMap;
1929
1933
  /**
package/dist/index.d.cts CHANGED
@@ -9,7 +9,7 @@ Objects type used to represent individual completions.
9
9
  interface Completion {
10
10
  /**
11
11
  The label to show in the completion picker. This is what input
12
- is matched agains to determine whether a completion matches (and
12
+ is matched against to determine whether a completion matches (and
13
13
  how well it matches).
14
14
  */
15
15
  label: string;
@@ -75,7 +75,7 @@ The type returned from
75
75
  node, null to indicate there is no info, or an object with an
76
76
  optional `destroy` method that cleans up the node.
77
77
  */
78
- declare type CompletionInfo = Node | null | {
78
+ type CompletionInfo = Node | null | {
79
79
  dom: Node;
80
80
  destroy?(): void;
81
81
  };
@@ -196,7 +196,7 @@ may return its [result](https://codemirror.net/6/docs/ref/#autocomplete.Completi
196
196
  synchronously or as a promise. Returning null indicates no
197
197
  completions are available.
198
198
  */
199
- declare type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
199
+ type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
200
200
  /**
201
201
  Interface for objects returned by completion sources.
202
202
  */
@@ -344,13 +344,13 @@ interface CompletionConfig {
344
344
  position: number;
345
345
  }[];
346
346
  /**
347
- By default, [info](https://codemirror.net/6/docs/ref/#autocomplet.Completion.info) tooltips are
348
- placed to the side of the selected. This option can be used to
349
- override that. It will be given rectangles for the list of
350
- completions, the selected option, the info element, and the
351
- availble [tooltip space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace),
352
- and should return style and/or class strings for the info
353
- element.
347
+ By default, [info](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info) tooltips are
348
+ placed to the side of the selected completion. This option can
349
+ be used to override that. It will be given rectangles for the
350
+ list of completions, the selected option, the info element, and
351
+ the availble [tooltip
352
+ space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace), and should return
353
+ style and/or class strings for the info element.
354
354
  */
355
355
  positionInfo?: (view: EditorView, list: Rect, option: Rect, info: Rect, space: Rect) => {
356
356
  style?: string;
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ Objects type used to represent individual completions.
9
9
  interface Completion {
10
10
  /**
11
11
  The label to show in the completion picker. This is what input
12
- is matched agains to determine whether a completion matches (and
12
+ is matched against to determine whether a completion matches (and
13
13
  how well it matches).
14
14
  */
15
15
  label: string;
@@ -75,7 +75,7 @@ The type returned from
75
75
  node, null to indicate there is no info, or an object with an
76
76
  optional `destroy` method that cleans up the node.
77
77
  */
78
- declare type CompletionInfo = Node | null | {
78
+ type CompletionInfo = Node | null | {
79
79
  dom: Node;
80
80
  destroy?(): void;
81
81
  };
@@ -196,7 +196,7 @@ may return its [result](https://codemirror.net/6/docs/ref/#autocomplete.Completi
196
196
  synchronously or as a promise. Returning null indicates no
197
197
  completions are available.
198
198
  */
199
- declare type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
199
+ type CompletionSource = (context: CompletionContext) => CompletionResult | null | Promise<CompletionResult | null>;
200
200
  /**
201
201
  Interface for objects returned by completion sources.
202
202
  */
@@ -344,13 +344,13 @@ interface CompletionConfig {
344
344
  position: number;
345
345
  }[];
346
346
  /**
347
- By default, [info](https://codemirror.net/6/docs/ref/#autocomplet.Completion.info) tooltips are
348
- placed to the side of the selected. This option can be used to
349
- override that. It will be given rectangles for the list of
350
- completions, the selected option, the info element, and the
351
- availble [tooltip space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace),
352
- and should return style and/or class strings for the info
353
- element.
347
+ By default, [info](https://codemirror.net/6/docs/ref/#autocomplete.Completion.info) tooltips are
348
+ placed to the side of the selected completion. This option can
349
+ be used to override that. It will be given rectangles for the
350
+ list of completions, the selected option, the info element, and
351
+ the availble [tooltip
352
+ space](https://codemirror.net/6/docs/ref/#view.tooltips^config.tooltipSpace), and should return
353
+ style and/or class strings for the info element.
354
354
  */
355
355
  positionInfo?: (view: EditorView, list: Rect, option: Rect, info: Rect, space: Rect) => {
356
356
  style?: string;
package/dist/index.js CHANGED
@@ -171,7 +171,7 @@ function insertCompletionText(state, text, from, to) {
171
171
  changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: text },
172
172
  range: EditorSelection.cursor(range.from + fromOff + text.length)
173
173
  };
174
- })), { userEvent: "input.complete" });
174
+ })), { scrollIntoView: true, userEvent: "input.complete" });
175
175
  }
176
176
  const SourceCache = /*@__PURE__*/new WeakMap();
177
177
  function asSource(source) {
@@ -223,7 +223,7 @@ class FuzzyMatcher {
223
223
  // is. See `Penalty` above.
224
224
  match(word) {
225
225
  if (this.pattern.length == 0)
226
- return this.ret(-100 /* NotFull */, []);
226
+ return this.ret(-100 /* Penalty.NotFull */, []);
227
227
  if (word.length < this.pattern.length)
228
228
  return false;
229
229
  let { chars, folded, any, precise, byWord } = this;
@@ -231,17 +231,17 @@ class FuzzyMatcher {
231
231
  // at the start
232
232
  if (chars.length == 1) {
233
233
  let first = codePointAt(word, 0), firstSize = codePointSize(first);
234
- let score = firstSize == word.length ? 0 : -100 /* NotFull */;
234
+ let score = firstSize == word.length ? 0 : -100 /* Penalty.NotFull */;
235
235
  if (first == chars[0]) ;
236
236
  else if (first == folded[0])
237
- score += -200 /* CaseFold */;
237
+ score += -200 /* Penalty.CaseFold */;
238
238
  else
239
239
  return false;
240
240
  return this.ret(score, [0, firstSize]);
241
241
  }
242
242
  let direct = word.indexOf(this.pattern);
243
243
  if (direct == 0)
244
- return this.ret(word.length == this.pattern.length ? 0 : -100 /* NotFull */, [0, this.pattern.length]);
244
+ return this.ret(word.length == this.pattern.length ? 0 : -100 /* Penalty.NotFull */, [0, this.pattern.length]);
245
245
  let len = chars.length, anyTo = 0;
246
246
  if (direct < 0) {
247
247
  for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
@@ -265,7 +265,7 @@ class FuzzyMatcher {
265
265
  let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
266
266
  let hasLower = /[a-z]/.test(word), wordAdjacent = true;
267
267
  // Go over the option's text, scanning for the various kinds of matches
268
- for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
268
+ for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* Tp.NonWord */; i < e && byWordTo < len;) {
269
269
  let next = codePointAt(word, i);
270
270
  if (direct < 0) {
271
271
  if (preciseTo < len && next == chars[preciseTo])
@@ -283,9 +283,9 @@ class FuzzyMatcher {
283
283
  }
284
284
  }
285
285
  let ch, type = next < 0xff
286
- ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
287
- : ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
288
- if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
286
+ ? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Tp.Lower */ : next >= 65 && next <= 90 ? 1 /* Tp.Upper */ : 0 /* Tp.NonWord */)
287
+ : ((ch = fromCodePoint(next)) != ch.toLowerCase() ? 1 /* Tp.Upper */ : ch != ch.toUpperCase() ? 2 /* Tp.Lower */ : 0 /* Tp.NonWord */);
288
+ if (!i || type == 1 /* Tp.Upper */ && hasLower || prevType == 0 /* Tp.NonWord */ && type != 0 /* Tp.NonWord */) {
289
289
  if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
290
290
  byWord[byWordTo++] = i;
291
291
  else if (byWord.length)
@@ -295,18 +295,18 @@ class FuzzyMatcher {
295
295
  i += codePointSize(next);
296
296
  }
297
297
  if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
298
- return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
298
+ return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0), byWord, word);
299
299
  if (adjacentTo == len && adjacentStart == 0)
300
- return this.ret(-200 /* CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* NotFull */), [0, adjacentEnd]);
300
+ return this.ret(-200 /* Penalty.CaseFold */ - word.length + (adjacentEnd == word.length ? 0 : -100 /* Penalty.NotFull */), [0, adjacentEnd]);
301
301
  if (direct > -1)
302
- return this.ret(-700 /* NotStart */ - word.length, [direct, direct + this.pattern.length]);
302
+ return this.ret(-700 /* Penalty.NotStart */ - word.length, [direct, direct + this.pattern.length]);
303
303
  if (adjacentTo == len)
304
- return this.ret(-200 /* CaseFold */ + -700 /* NotStart */ - word.length, [adjacentStart, adjacentEnd]);
304
+ return this.ret(-200 /* Penalty.CaseFold */ + -700 /* Penalty.NotStart */ - word.length, [adjacentStart, adjacentEnd]);
305
305
  if (byWordTo == len)
306
- return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
307
- (wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
306
+ return this.result(-100 /* Penalty.ByWord */ + (byWordFolded ? -200 /* Penalty.CaseFold */ : 0) + -700 /* Penalty.NotStart */ +
307
+ (wordAdjacent ? 0 : -1100 /* Penalty.Gap */), byWord, word);
308
308
  return chars.length == 2 ? false
309
- : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
309
+ : this.result((any[0] ? -700 /* Penalty.NotStart */ : 0) + -200 /* Penalty.CaseFold */ + -1100 /* Penalty.Gap */, any, word);
310
310
  }
311
311
  result(score, positions, word) {
312
312
  let result = [], i = 0;
@@ -353,7 +353,7 @@ const completionConfig = /*@__PURE__*/Facet.define({
353
353
  function joinClass(a, b) {
354
354
  return a ? b ? a + " " + b : a : b;
355
355
  }
356
- function defaultPositionInfo(view, list, option, info, space) {
356
+ function defaultPositionInfo(view, list, option, info, space, tooltip) {
357
357
  let rtl = view.textDirection == Direction.RTL, left = rtl, narrow = false;
358
358
  let side = "top", offset, maxWidth;
359
359
  let spaceLeft = list.left - space.left, spaceRight = space.right - list.right;
@@ -364,11 +364,11 @@ function defaultPositionInfo(view, list, option, info, space) {
364
364
  left = true;
365
365
  if (infoWidth <= (left ? spaceLeft : spaceRight)) {
366
366
  offset = Math.max(space.top, Math.min(option.top, space.bottom - infoHeight)) - list.top;
367
- maxWidth = Math.min(400 /* Width */, left ? spaceLeft : spaceRight);
367
+ maxWidth = Math.min(400 /* Info.Width */, left ? spaceLeft : spaceRight);
368
368
  }
369
369
  else {
370
370
  narrow = true;
371
- maxWidth = Math.min(400 /* Width */, (rtl ? list.right : space.right - list.left) - 30 /* Margin */);
371
+ maxWidth = Math.min(400 /* Info.Width */, (rtl ? list.right : space.right - list.left) - 30 /* Info.Margin */);
372
372
  let spaceBelow = space.bottom - list.bottom;
373
373
  if (spaceBelow >= infoHeight || spaceBelow > list.top) { // Below the completion
374
374
  offset = option.bottom - list.top;
@@ -378,8 +378,10 @@ function defaultPositionInfo(view, list, option, info, space) {
378
378
  offset = list.bottom - option.top;
379
379
  }
380
380
  }
381
+ let scaleY = (list.bottom - list.top) / tooltip.offsetHeight;
382
+ let scaleX = (list.right - list.left) / tooltip.offsetWidth;
381
383
  return {
382
- style: `${side}: ${offset}px; max-width: ${maxWidth}px`,
384
+ style: `${side}: ${offset / scaleY}px; max-width: ${maxWidth / scaleX}px`,
383
385
  class: "cm-completionInfo-" + (narrow ? (rtl ? "left-narrow" : "right-narrow") : left ? "left" : "right")
384
386
  };
385
387
  }
@@ -599,7 +601,7 @@ class CompletionTooltip {
599
601
  if (selRect.top > Math.min(space.bottom, listRect.bottom) - 10 ||
600
602
  selRect.bottom < Math.max(space.top, listRect.top) + 10)
601
603
  return null;
602
- return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space);
604
+ return this.view.state.facet(completionConfig).positionInfo(this.view, listRect, selRect, infoRect, space, this.dom);
603
605
  }
604
606
  placeInfo(pos) {
605
607
  if (this.info) {
@@ -673,10 +675,11 @@ function completionTooltip(stateField, applyCompletion) {
673
675
  function scrollIntoView(container, element) {
674
676
  let parent = container.getBoundingClientRect();
675
677
  let self = element.getBoundingClientRect();
678
+ let scaleY = parent.height / container.offsetHeight;
676
679
  if (self.top < parent.top)
677
- container.scrollTop -= parent.top - self.top;
680
+ container.scrollTop -= (parent.top - self.top) / scaleY;
678
681
  else if (self.bottom > parent.bottom)
679
- container.scrollTop += self.bottom - parent.bottom;
682
+ container.scrollTop += (self.bottom - parent.bottom) / scaleY;
680
683
  }
681
684
 
682
685
  // Used to pick a preferred option when two options with the same
@@ -759,7 +762,7 @@ class CompletionDialog {
759
762
  static build(active, state, id, prev, conf) {
760
763
  let options = sortOptions(active, state);
761
764
  if (!options.length) {
762
- return prev && active.some(a => a.state == 1 /* Pending */) ?
765
+ return prev && active.some(a => a.state == 1 /* State.Pending */) ?
763
766
  new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null;
764
767
  }
765
768
  let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
@@ -796,7 +799,7 @@ class CompletionState {
796
799
  state.languageDataAt("autocomplete", cur(state)).map(asSource);
797
800
  let active = sources.map(source => {
798
801
  let value = this.active.find(s => s.source == source) ||
799
- new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
802
+ new ActiveSource(source, this.active.some(a => a.state != 0 /* State.Inactive */) ? 1 /* State.Pending */ : 0 /* State.Inactive */);
800
803
  return value.update(tr, conf);
801
804
  });
802
805
  if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
@@ -807,10 +810,10 @@ class CompletionState {
807
810
  if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
808
811
  !sameResults(active, this.active))
809
812
  open = CompletionDialog.build(active, state, this.id, open, conf);
810
- else if (open && open.disabled && !active.some(a => a.state == 1 /* Pending */))
813
+ else if (open && open.disabled && !active.some(a => a.state == 1 /* State.Pending */))
811
814
  open = null;
812
- if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
813
- active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
815
+ if (!open && active.every(a => a.state != 1 /* State.Pending */) && active.some(a => a.hasResult()))
816
+ active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* State.Inactive */) : a);
814
817
  for (let effect of tr.effects)
815
818
  if (effect.is(setSelectedEffect))
816
819
  open = open && open.setSelected(effect.value, this.id);
@@ -864,13 +867,13 @@ class ActiveSource {
864
867
  value = value.handleUserEvent(tr, event, conf);
865
868
  else if (tr.docChanged)
866
869
  value = value.handleChange(tr);
867
- else if (tr.selection && value.state != 0 /* Inactive */)
868
- value = new ActiveSource(value.source, 0 /* Inactive */);
870
+ else if (tr.selection && value.state != 0 /* State.Inactive */)
871
+ value = new ActiveSource(value.source, 0 /* State.Inactive */);
869
872
  for (let effect of tr.effects) {
870
873
  if (effect.is(startCompletionEffect))
871
- value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
874
+ value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
872
875
  else if (effect.is(closeCompletionEffect))
873
- value = new ActiveSource(value.source, 0 /* Inactive */);
876
+ value = new ActiveSource(value.source, 0 /* State.Inactive */);
874
877
  else if (effect.is(setActiveEffect))
875
878
  for (let active of effect.value)
876
879
  if (active.source == value.source)
@@ -879,10 +882,10 @@ class ActiveSource {
879
882
  return value;
880
883
  }
881
884
  handleUserEvent(tr, type, conf) {
882
- return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
885
+ return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
883
886
  }
884
887
  handleChange(tr) {
885
- return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
888
+ return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
886
889
  }
887
890
  map(changes) {
888
891
  return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
@@ -890,7 +893,7 @@ class ActiveSource {
890
893
  }
891
894
  class ActiveResult extends ActiveSource {
892
895
  constructor(source, explicitPos, result, from, to) {
893
- super(source, 2 /* Result */, explicitPos);
896
+ super(source, 2 /* State.Result */, explicitPos);
894
897
  this.result = result;
895
898
  this.from = from;
896
899
  this.to = to;
@@ -903,17 +906,17 @@ class ActiveResult extends ActiveSource {
903
906
  if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
904
907
  pos > to ||
905
908
  type == "delete" && cur(tr.startState) == this.from)
906
- return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
909
+ return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
907
910
  let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
908
911
  if (checkValid(this.result.validFor, tr.state, from, to))
909
912
  return new ActiveResult(this.source, explicitPos, this.result, from, to);
910
913
  if (this.result.update &&
911
914
  (updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
912
915
  return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
913
- return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
916
+ return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
914
917
  }
915
918
  handleChange(tr) {
916
- return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
919
+ return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
917
920
  }
918
921
  map(mapping) {
919
922
  return mapping.empty ? this :
@@ -999,7 +1002,7 @@ Close the currently active completion.
999
1002
  */
1000
1003
  const closeCompletion = (view) => {
1001
1004
  let cState = view.state.field(completionState, false);
1002
- if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
1005
+ if (!cState || !cState.active.some(a => a.state != 0 /* State.Inactive */))
1003
1006
  return false;
1004
1007
  view.dispatch({ effects: closeCompletionEffect.of(null) });
1005
1008
  return true;
@@ -1022,9 +1025,9 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1022
1025
  this.debounceUpdate = -1;
1023
1026
  this.running = [];
1024
1027
  this.debounceAccept = -1;
1025
- this.composing = 0 /* None */;
1028
+ this.composing = 0 /* CompositionState.None */;
1026
1029
  for (let active of view.state.field(completionState).active)
1027
- if (active.state == 1 /* Pending */)
1030
+ if (active.state == 1 /* State.Pending */)
1028
1031
  this.startQuery(active);
1029
1032
  }
1030
1033
  update(update) {
@@ -1055,21 +1058,21 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1055
1058
  }
1056
1059
  if (this.debounceUpdate > -1)
1057
1060
  clearTimeout(this.debounceUpdate);
1058
- this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
1061
+ this.debounceUpdate = cState.active.some(a => a.state == 1 /* State.Pending */ && !this.running.some(q => q.active.source == a.source))
1059
1062
  ? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
1060
- if (this.composing != 0 /* None */)
1063
+ if (this.composing != 0 /* CompositionState.None */)
1061
1064
  for (let tr of update.transactions) {
1062
1065
  if (getUserEvent(tr) == "input")
1063
- this.composing = 2 /* Changed */;
1064
- else if (this.composing == 2 /* Changed */ && tr.selection)
1065
- this.composing = 3 /* ChangedAndMoved */;
1066
+ this.composing = 2 /* CompositionState.Changed */;
1067
+ else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
1068
+ this.composing = 3 /* CompositionState.ChangedAndMoved */;
1066
1069
  }
1067
1070
  }
1068
1071
  startUpdate() {
1069
1072
  this.debounceUpdate = -1;
1070
1073
  let { state } = this.view, cState = state.field(completionState);
1071
1074
  for (let active of cState.active) {
1072
- if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
1075
+ if (active.state == 1 /* State.Pending */ && !this.running.some(r => r.active.source == active.source))
1073
1076
  this.startQuery(active);
1074
1077
  }
1075
1078
  }
@@ -1120,14 +1123,14 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1120
1123
  }
1121
1124
  }
1122
1125
  let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
1123
- if (current && current.state == 1 /* Pending */) {
1126
+ if (current && current.state == 1 /* State.Pending */) {
1124
1127
  if (query.done == null) {
1125
1128
  // Explicitly failed. Should clear the pending status if it
1126
1129
  // hasn't been re-set in the meantime.
1127
- let active = new ActiveSource(query.active.source, 0 /* Inactive */);
1130
+ let active = new ActiveSource(query.active.source, 0 /* State.Inactive */);
1128
1131
  for (let tr of query.updates)
1129
1132
  active = active.update(tr, conf);
1130
- if (active.state != 1 /* Pending */)
1133
+ if (active.state != 1 /* State.Pending */)
1131
1134
  updated.push(active);
1132
1135
  }
1133
1136
  else {
@@ -1150,15 +1153,15 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1150
1153
  }
1151
1154
  },
1152
1155
  compositionstart() {
1153
- this.composing = 1 /* Started */;
1156
+ this.composing = 1 /* CompositionState.Started */;
1154
1157
  },
1155
1158
  compositionend() {
1156
- if (this.composing == 3 /* ChangedAndMoved */) {
1159
+ if (this.composing == 3 /* CompositionState.ChangedAndMoved */) {
1157
1160
  // Safari fires compositionend events synchronously, possibly
1158
1161
  // from inside an update, so dispatch asynchronously to avoid reentrancy
1159
1162
  setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
1160
1163
  }
1161
- this.composing = 0 /* None */;
1164
+ this.composing = 0 /* CompositionState.None */;
1162
1165
  }
1163
1166
  }
1164
1167
  });
@@ -1218,13 +1221,13 @@ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
1218
1221
  position: "absolute",
1219
1222
  padding: "3px 9px",
1220
1223
  width: "max-content",
1221
- maxWidth: `${400 /* Width */}px`,
1224
+ maxWidth: `${400 /* Info.Width */}px`,
1222
1225
  boxSizing: "border-box"
1223
1226
  },
1224
1227
  ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
1225
1228
  ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
1226
- ".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Margin */}px` },
1227
- ".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Margin */}px` },
1229
+ ".cm-completionInfo.cm-completionInfo-left-narrow": { right: `${30 /* Info.Margin */}px` },
1230
+ ".cm-completionInfo.cm-completionInfo-right-narrow": { left: `${30 /* Info.Margin */}px` },
1228
1231
  "&light .cm-snippetField": { backgroundColor: "#00000022" },
1229
1232
  "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
1230
1233
  ".cm-snippetFieldPosition": {
@@ -1475,7 +1478,8 @@ function moveField(dir) {
1475
1478
  let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir);
1476
1479
  dispatch(state.update({
1477
1480
  selection: fieldSelection(active.ranges, next),
1478
- effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next))
1481
+ effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next)),
1482
+ scrollIntoView: true
1479
1483
  }));
1480
1484
  return true;
1481
1485
  };
@@ -1547,7 +1551,9 @@ const snippetPointerHandler = /*@__PURE__*/EditorView.domEventHandlers({
1547
1551
  return false;
1548
1552
  view.dispatch({
1549
1553
  selection: fieldSelection(active.ranges, match.field),
1550
- effects: setActive.of(active.ranges.some(r => r.field > match.field) ? new ActiveSnippet(active.ranges, match.field) : null)
1554
+ effects: setActive.of(active.ranges.some(r => r.field > match.field)
1555
+ ? new ActiveSnippet(active.ranges, match.field) : null),
1556
+ scrollIntoView: true
1551
1557
  });
1552
1558
  return true;
1553
1559
  }
@@ -1577,7 +1583,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
1577
1583
  if (!seen[m[0]] && pos + m.index != ignoreAt) {
1578
1584
  result.push({ type: "text", label: m[0] });
1579
1585
  seen[m[0]] = true;
1580
- if (result.length >= 2000 /* MaxList */)
1586
+ if (result.length >= 2000 /* C.MaxList */)
1581
1587
  return;
1582
1588
  }
1583
1589
  }
@@ -1585,7 +1591,7 @@ function storeWords(doc, wordRE, result, seen, ignoreAt) {
1585
1591
  }
1586
1592
  }
1587
1593
  function collectWords(doc, cache, wordRE, to, ignoreAt) {
1588
- let big = doc.length >= 1000 /* MinCacheLen */;
1594
+ let big = doc.length >= 1000 /* C.MinCacheLen */;
1589
1595
  let cached = big && cache.get(doc);
1590
1596
  if (cached)
1591
1597
  return cached;
@@ -1593,7 +1599,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
1593
1599
  if (doc.children) {
1594
1600
  let pos = 0;
1595
1601
  for (let ch of doc.children) {
1596
- if (ch.length >= 1000 /* MinCacheLen */) {
1602
+ if (ch.length >= 1000 /* C.MinCacheLen */) {
1597
1603
  for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
1598
1604
  if (!seen[c.label]) {
1599
1605
  seen[c.label] = true;
@@ -1610,7 +1616,7 @@ function collectWords(doc, cache, wordRE, to, ignoreAt) {
1610
1616
  else {
1611
1617
  storeWords(doc, wordRE, result, seen, ignoreAt);
1612
1618
  }
1613
- if (big && result.length < 2000 /* MaxList */)
1619
+ if (big && result.length < 2000 /* C.MaxList */)
1614
1620
  cache.set(doc, result);
1615
1621
  return result;
1616
1622
  }
@@ -1626,7 +1632,7 @@ const completeAnyWord = context => {
1626
1632
  if (!token && !context.explicit)
1627
1633
  return null;
1628
1634
  let from = token ? token.from : context.pos;
1629
- let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
1635
+ let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* C.Range */, from);
1630
1636
  return { from, options, validFor: mapRE(re, s => "^" + s) };
1631
1637
  };
1632
1638
 
@@ -1918,8 +1924,8 @@ returns `null`.
1918
1924
  */
1919
1925
  function completionStatus(state) {
1920
1926
  let cState = state.field(completionState, false);
1921
- return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
1922
- : cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
1927
+ return cState && cState.active.some(a => a.state == 1 /* State.Pending */) ? "pending"
1928
+ : cState && cState.active.some(a => a.state != 0 /* State.Inactive */) ? "active" : null;
1923
1929
  }
1924
1930
  const completionArrayCache = /*@__PURE__*/new WeakMap;
1925
1931
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/autocomplete",
3
- "version": "6.9.0",
3
+ "version": "6.9.1",
4
4
  "description": "Autocompletion for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",
@@ -28,7 +28,7 @@
28
28
  "dependencies": {
29
29
  "@codemirror/language": "^6.0.0",
30
30
  "@codemirror/state": "^6.0.0",
31
- "@codemirror/view": "^6.6.0",
31
+ "@codemirror/view": "^6.17.0",
32
32
  "@lezer/common": "^1.0.0"
33
33
  },
34
34
  "peerDependencies": {