@codemirror/autocomplete 6.16.2 → 6.17.0

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.17.0 (2024-07-03)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where completions weren't properly reset when starting a new completion through `activateOnCompletion`.
6
+
7
+ ### New features
8
+
9
+ `CompletionContext` objects now have a `view` property that holds the editor view when the query context has a view available.
10
+
11
+ ## 6.16.3 (2024-06-19)
12
+
13
+ ### Bug fixes
14
+
15
+ Avoid adding an `aria-autocomplete` attribute to the editor when there are no active sources active.
16
+
1
17
  ## 6.16.2 (2024-05-31)
2
18
 
3
19
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -28,10 +28,19 @@ class CompletionContext {
28
28
  only return completions when either there is part of a
29
29
  completable entity before the cursor, or `explicit` is true.
30
30
  */
31
- explicit) {
31
+ explicit,
32
+ /**
33
+ The editor view. May be undefined if the context was created
34
+ in a situation where there is no such view available, such as
35
+ in synchronous updates via
36
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
37
+ or when called by test code.
38
+ */
39
+ view) {
32
40
  this.state = state;
33
41
  this.pos = pos;
34
42
  this.explicit = explicit;
43
+ this.view = view;
35
44
  /**
36
45
  @internal
37
46
  */
@@ -852,7 +861,7 @@ class CompletionState {
852
861
  return active == this.active && open == this.open ? this : new CompletionState(active, this.id, open);
853
862
  }
854
863
  get tooltip() { return this.open ? this.open.tooltip : null; }
855
- get attrs() { return this.open ? this.open.attrs : baseAttrs; }
864
+ get attrs() { return this.open ? this.open.attrs : this.active.length ? baseAttrs : noAttrs; }
856
865
  }
857
866
  function sameResults(a, b) {
858
867
  if (a == b)
@@ -872,6 +881,7 @@ function sameResults(a, b) {
872
881
  const baseAttrs = {
873
882
  "aria-autocomplete": "list"
874
883
  };
884
+ const noAttrs = {};
875
885
  function makeAttrs(id, selected) {
876
886
  let result = {
877
887
  "aria-autocomplete": "list",
@@ -883,13 +893,18 @@ function makeAttrs(id, selected) {
883
893
  return result;
884
894
  }
885
895
  const none = [];
886
- function getUserEvent(tr, conf) {
896
+ function getUpdateType(tr, conf) {
887
897
  if (tr.isUserEvent("input.complete")) {
888
898
  let completion = tr.annotation(pickedCompletion);
889
899
  if (completion && conf.activateOnCompletion(completion))
890
- return "input";
900
+ return 4 /* UpdateType.Activate */ | 8 /* UpdateType.Reset */;
891
901
  }
892
- return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null;
902
+ let typing = tr.isUserEvent("input.type");
903
+ return typing && conf.activateOnTyping ? 4 /* UpdateType.Activate */ | 1 /* UpdateType.Typing */
904
+ : typing ? 1 /* UpdateType.Typing */
905
+ : tr.isUserEvent("delete.backward") ? 2 /* UpdateType.Backspacing */
906
+ : tr.selection ? 8 /* UpdateType.Reset */
907
+ : tr.docChanged ? 16 /* UpdateType.ResetIfTouching */ : 0 /* UpdateType.None */;
893
908
  }
894
909
  class ActiveSource {
895
910
  constructor(source, state, explicitPos = -1) {
@@ -899,13 +914,12 @@ class ActiveSource {
899
914
  }
900
915
  hasResult() { return false; }
901
916
  update(tr, conf) {
902
- let event = getUserEvent(tr, conf), value = this;
903
- if (event)
904
- value = value.handleUserEvent(tr, event, conf);
905
- else if (tr.docChanged)
906
- value = value.handleChange(tr);
907
- else if (tr.selection && value.state != 0 /* State.Inactive */)
917
+ let type = getUpdateType(tr, conf), value = this;
918
+ if ((type & 8 /* UpdateType.Reset */) || (type & 16 /* UpdateType.ResetIfTouching */) && this.touches(tr))
908
919
  value = new ActiveSource(value.source, 0 /* State.Inactive */);
920
+ if ((type & 4 /* UpdateType.Activate */) && value.state == 0 /* State.Inactive */)
921
+ value = new ActiveSource(this.source, 1 /* State.Pending */);
922
+ value = value.updateFor(tr, type);
909
923
  for (let effect of tr.effects) {
910
924
  if (effect.is(startCompletionEffect))
911
925
  value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
@@ -918,15 +932,13 @@ class ActiveSource {
918
932
  }
919
933
  return value;
920
934
  }
921
- handleUserEvent(tr, type, conf) {
922
- return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
923
- }
924
- handleChange(tr) {
925
- return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
926
- }
935
+ updateFor(tr, type) { return this.map(tr.changes); }
927
936
  map(changes) {
928
937
  return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
929
938
  }
939
+ touches(tr) {
940
+ return tr.changes.touchesRange(cur(tr.state));
941
+ }
930
942
  }
931
943
  class ActiveResult extends ActiveSource {
932
944
  constructor(source, explicitPos, result, from, to) {
@@ -936,8 +948,10 @@ class ActiveResult extends ActiveSource {
936
948
  this.to = to;
937
949
  }
938
950
  hasResult() { return true; }
939
- handleUserEvent(tr, type, conf) {
951
+ updateFor(tr, type) {
940
952
  var _a;
953
+ if (!(type & 3 /* UpdateType.SimpleInteraction */))
954
+ return this.map(tr.changes);
941
955
  let result = this.result;
942
956
  if (result.map && !tr.changes.empty)
943
957
  result = result.map(result, tr.changes);
@@ -945,8 +959,8 @@ class ActiveResult extends ActiveSource {
945
959
  let pos = cur(tr.state);
946
960
  if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
947
961
  pos > to || !result ||
948
- type == "delete" && cur(tr.startState) == this.from)
949
- return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
962
+ (type & 2 /* UpdateType.Backspacing */) && cur(tr.startState) == this.from)
963
+ return new ActiveSource(this.source, type & 4 /* UpdateType.Activate */ ? 1 /* State.Pending */ : 0 /* State.Inactive */);
950
964
  let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos);
951
965
  if (checkValid(result.validFor, tr.state, from, to))
952
966
  return new ActiveResult(this.source, explicitPos, result, from, to);
@@ -955,9 +969,6 @@ class ActiveResult extends ActiveSource {
955
969
  return new ActiveResult(this.source, explicitPos, result, result.from, (_a = result.to) !== null && _a !== void 0 ? _a : cur(tr.state));
956
970
  return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
957
971
  }
958
- handleChange(tr) {
959
- return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
960
- }
961
972
  map(mapping) {
962
973
  if (mapping.empty)
963
974
  return this;
@@ -966,6 +977,9 @@ class ActiveResult extends ActiveSource {
966
977
  return new ActiveSource(this.source, 0 /* State.Inactive */);
967
978
  return new ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result, mapping.mapPos(this.from), mapping.mapPos(this.to, 1));
968
979
  }
980
+ touches(tr) {
981
+ return tr.changes.touchesRange(this.from, this.to);
982
+ }
969
983
  }
970
984
  function checkValid(validFor, state, from, to) {
971
985
  if (!validFor)
@@ -1082,7 +1096,8 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1082
1096
  if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
1083
1097
  return;
1084
1098
  let doesReset = update.transactions.some(tr => {
1085
- return (tr.selection || tr.docChanged) && !getUserEvent(tr, conf);
1099
+ let type = getUpdateType(tr, conf);
1100
+ return (type & 8 /* UpdateType.Reset */) || (tr.selection || tr.docChanged) && !(type & 3 /* UpdateType.SimpleInteraction */);
1086
1101
  });
1087
1102
  for (let i = 0; i < this.running.length; i++) {
1088
1103
  let query = this.running[i];
@@ -1112,7 +1127,7 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1112
1127
  ? setTimeout(() => this.startUpdate(), delay) : -1;
1113
1128
  if (this.composing != 0 /* CompositionState.None */)
1114
1129
  for (let tr of update.transactions) {
1115
- if (getUserEvent(tr, conf) == "input")
1130
+ if (tr.isUserEvent("input.type"))
1116
1131
  this.composing = 2 /* CompositionState.Changed */;
1117
1132
  else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
1118
1133
  this.composing = 3 /* CompositionState.ChangedAndMoved */;
@@ -1129,7 +1144,7 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1129
1144
  }
1130
1145
  startQuery(active) {
1131
1146
  let { state } = this.view, pos = cur(state);
1132
- let context = new CompletionContext(state, pos, active.explicitPos == pos);
1147
+ let context = new CompletionContext(state, pos, active.explicitPos == pos, this.view);
1133
1148
  let pending = new RunningQuery(active, context);
1134
1149
  this.running.push(pending);
1135
1150
  Promise.resolve(active.source(context)).then(result => {
package/dist/index.d.cts CHANGED
@@ -129,6 +129,14 @@ declare class CompletionContext {
129
129
  */
130
130
  readonly explicit: boolean;
131
131
  /**
132
+ The editor view. May be undefined if the context was created
133
+ in a situation where there is no such view available, such as
134
+ in synchronous updates via
135
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
136
+ or when called by test code.
137
+ */
138
+ readonly view?: EditorView | undefined;
139
+ /**
132
140
  Create a new completion context. (Mostly useful for testing
133
141
  completion sources—in the editor, the extension will create
134
142
  these for you.)
@@ -148,7 +156,15 @@ declare class CompletionContext {
148
156
  only return completions when either there is part of a
149
157
  completable entity before the cursor, or `explicit` is true.
150
158
  */
151
- explicit: boolean);
159
+ explicit: boolean,
160
+ /**
161
+ The editor view. May be undefined if the context was created
162
+ in a situation where there is no such view available, such as
163
+ in synchronous updates via
164
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
165
+ or when called by test code.
166
+ */
167
+ view?: EditorView | undefined);
152
168
  /**
153
169
  Get the extent, content, and (if there is a token) type of the
154
170
  token before `this.pos`.
package/dist/index.d.ts CHANGED
@@ -129,6 +129,14 @@ declare class CompletionContext {
129
129
  */
130
130
  readonly explicit: boolean;
131
131
  /**
132
+ The editor view. May be undefined if the context was created
133
+ in a situation where there is no such view available, such as
134
+ in synchronous updates via
135
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
136
+ or when called by test code.
137
+ */
138
+ readonly view?: EditorView | undefined;
139
+ /**
132
140
  Create a new completion context. (Mostly useful for testing
133
141
  completion sources—in the editor, the extension will create
134
142
  these for you.)
@@ -148,7 +156,15 @@ declare class CompletionContext {
148
156
  only return completions when either there is part of a
149
157
  completable entity before the cursor, or `explicit` is true.
150
158
  */
151
- explicit: boolean);
159
+ explicit: boolean,
160
+ /**
161
+ The editor view. May be undefined if the context was created
162
+ in a situation where there is no such view available, such as
163
+ in synchronous updates via
164
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
165
+ or when called by test code.
166
+ */
167
+ view?: EditorView | undefined);
152
168
  /**
153
169
  Get the extent, content, and (if there is a token) type of the
154
170
  token before `this.pos`.
package/dist/index.js CHANGED
@@ -26,10 +26,19 @@ class CompletionContext {
26
26
  only return completions when either there is part of a
27
27
  completable entity before the cursor, or `explicit` is true.
28
28
  */
29
- explicit) {
29
+ explicit,
30
+ /**
31
+ The editor view. May be undefined if the context was created
32
+ in a situation where there is no such view available, such as
33
+ in synchronous updates via
34
+ [`CompletionResult.update`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.update)
35
+ or when called by test code.
36
+ */
37
+ view) {
30
38
  this.state = state;
31
39
  this.pos = pos;
32
40
  this.explicit = explicit;
41
+ this.view = view;
33
42
  /**
34
43
  @internal
35
44
  */
@@ -850,7 +859,7 @@ class CompletionState {
850
859
  return active == this.active && open == this.open ? this : new CompletionState(active, this.id, open);
851
860
  }
852
861
  get tooltip() { return this.open ? this.open.tooltip : null; }
853
- get attrs() { return this.open ? this.open.attrs : baseAttrs; }
862
+ get attrs() { return this.open ? this.open.attrs : this.active.length ? baseAttrs : noAttrs; }
854
863
  }
855
864
  function sameResults(a, b) {
856
865
  if (a == b)
@@ -870,6 +879,7 @@ function sameResults(a, b) {
870
879
  const baseAttrs = {
871
880
  "aria-autocomplete": "list"
872
881
  };
882
+ const noAttrs = {};
873
883
  function makeAttrs(id, selected) {
874
884
  let result = {
875
885
  "aria-autocomplete": "list",
@@ -881,13 +891,18 @@ function makeAttrs(id, selected) {
881
891
  return result;
882
892
  }
883
893
  const none = [];
884
- function getUserEvent(tr, conf) {
894
+ function getUpdateType(tr, conf) {
885
895
  if (tr.isUserEvent("input.complete")) {
886
896
  let completion = tr.annotation(pickedCompletion);
887
897
  if (completion && conf.activateOnCompletion(completion))
888
- return "input";
898
+ return 4 /* UpdateType.Activate */ | 8 /* UpdateType.Reset */;
889
899
  }
890
- return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null;
900
+ let typing = tr.isUserEvent("input.type");
901
+ return typing && conf.activateOnTyping ? 4 /* UpdateType.Activate */ | 1 /* UpdateType.Typing */
902
+ : typing ? 1 /* UpdateType.Typing */
903
+ : tr.isUserEvent("delete.backward") ? 2 /* UpdateType.Backspacing */
904
+ : tr.selection ? 8 /* UpdateType.Reset */
905
+ : tr.docChanged ? 16 /* UpdateType.ResetIfTouching */ : 0 /* UpdateType.None */;
891
906
  }
892
907
  class ActiveSource {
893
908
  constructor(source, state, explicitPos = -1) {
@@ -897,13 +912,12 @@ class ActiveSource {
897
912
  }
898
913
  hasResult() { return false; }
899
914
  update(tr, conf) {
900
- let event = getUserEvent(tr, conf), value = this;
901
- if (event)
902
- value = value.handleUserEvent(tr, event, conf);
903
- else if (tr.docChanged)
904
- value = value.handleChange(tr);
905
- else if (tr.selection && value.state != 0 /* State.Inactive */)
915
+ let type = getUpdateType(tr, conf), value = this;
916
+ if ((type & 8 /* UpdateType.Reset */) || (type & 16 /* UpdateType.ResetIfTouching */) && this.touches(tr))
906
917
  value = new ActiveSource(value.source, 0 /* State.Inactive */);
918
+ if ((type & 4 /* UpdateType.Activate */) && value.state == 0 /* State.Inactive */)
919
+ value = new ActiveSource(this.source, 1 /* State.Pending */);
920
+ value = value.updateFor(tr, type);
907
921
  for (let effect of tr.effects) {
908
922
  if (effect.is(startCompletionEffect))
909
923
  value = new ActiveSource(value.source, 1 /* State.Pending */, effect.value ? cur(tr.state) : -1);
@@ -916,15 +930,13 @@ class ActiveSource {
916
930
  }
917
931
  return value;
918
932
  }
919
- handleUserEvent(tr, type, conf) {
920
- return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* State.Pending */);
921
- }
922
- handleChange(tr) {
923
- return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
924
- }
933
+ updateFor(tr, type) { return this.map(tr.changes); }
925
934
  map(changes) {
926
935
  return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
927
936
  }
937
+ touches(tr) {
938
+ return tr.changes.touchesRange(cur(tr.state));
939
+ }
928
940
  }
929
941
  class ActiveResult extends ActiveSource {
930
942
  constructor(source, explicitPos, result, from, to) {
@@ -934,8 +946,10 @@ class ActiveResult extends ActiveSource {
934
946
  this.to = to;
935
947
  }
936
948
  hasResult() { return true; }
937
- handleUserEvent(tr, type, conf) {
949
+ updateFor(tr, type) {
938
950
  var _a;
951
+ if (!(type & 3 /* UpdateType.SimpleInteraction */))
952
+ return this.map(tr.changes);
939
953
  let result = this.result;
940
954
  if (result.map && !tr.changes.empty)
941
955
  result = result.map(result, tr.changes);
@@ -943,8 +957,8 @@ class ActiveResult extends ActiveSource {
943
957
  let pos = cur(tr.state);
944
958
  if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
945
959
  pos > to || !result ||
946
- type == "delete" && cur(tr.startState) == this.from)
947
- return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* State.Pending */ : 0 /* State.Inactive */);
960
+ (type & 2 /* UpdateType.Backspacing */) && cur(tr.startState) == this.from)
961
+ return new ActiveSource(this.source, type & 4 /* UpdateType.Activate */ ? 1 /* State.Pending */ : 0 /* State.Inactive */);
948
962
  let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos);
949
963
  if (checkValid(result.validFor, tr.state, from, to))
950
964
  return new ActiveResult(this.source, explicitPos, result, from, to);
@@ -953,9 +967,6 @@ class ActiveResult extends ActiveSource {
953
967
  return new ActiveResult(this.source, explicitPos, result, result.from, (_a = result.to) !== null && _a !== void 0 ? _a : cur(tr.state));
954
968
  return new ActiveSource(this.source, 1 /* State.Pending */, explicitPos);
955
969
  }
956
- handleChange(tr) {
957
- return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* State.Inactive */) : this.map(tr.changes);
958
- }
959
970
  map(mapping) {
960
971
  if (mapping.empty)
961
972
  return this;
@@ -964,6 +975,9 @@ class ActiveResult extends ActiveSource {
964
975
  return new ActiveSource(this.source, 0 /* State.Inactive */);
965
976
  return new ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result, mapping.mapPos(this.from), mapping.mapPos(this.to, 1));
966
977
  }
978
+ touches(tr) {
979
+ return tr.changes.touchesRange(this.from, this.to);
980
+ }
967
981
  }
968
982
  function checkValid(validFor, state, from, to) {
969
983
  if (!validFor)
@@ -1080,7 +1094,8 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1080
1094
  if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
1081
1095
  return;
1082
1096
  let doesReset = update.transactions.some(tr => {
1083
- return (tr.selection || tr.docChanged) && !getUserEvent(tr, conf);
1097
+ let type = getUpdateType(tr, conf);
1098
+ return (type & 8 /* UpdateType.Reset */) || (tr.selection || tr.docChanged) && !(type & 3 /* UpdateType.SimpleInteraction */);
1084
1099
  });
1085
1100
  for (let i = 0; i < this.running.length; i++) {
1086
1101
  let query = this.running[i];
@@ -1110,7 +1125,7 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1110
1125
  ? setTimeout(() => this.startUpdate(), delay) : -1;
1111
1126
  if (this.composing != 0 /* CompositionState.None */)
1112
1127
  for (let tr of update.transactions) {
1113
- if (getUserEvent(tr, conf) == "input")
1128
+ if (tr.isUserEvent("input.type"))
1114
1129
  this.composing = 2 /* CompositionState.Changed */;
1115
1130
  else if (this.composing == 2 /* CompositionState.Changed */ && tr.selection)
1116
1131
  this.composing = 3 /* CompositionState.ChangedAndMoved */;
@@ -1127,7 +1142,7 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1127
1142
  }
1128
1143
  startQuery(active) {
1129
1144
  let { state } = this.view, pos = cur(state);
1130
- let context = new CompletionContext(state, pos, active.explicitPos == pos);
1145
+ let context = new CompletionContext(state, pos, active.explicitPos == pos, this.view);
1131
1146
  let pending = new RunningQuery(active, context);
1132
1147
  this.running.push(pending);
1133
1148
  Promise.resolve(active.source(context)).then(result => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/autocomplete",
3
- "version": "6.16.2",
3
+ "version": "6.17.0",
4
4
  "description": "Autocompletion for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",