@codemirror/autocomplete 0.20.0 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/index.cjs +42 -24
- package/dist/index.d.ts +21 -2
- package/dist/index.js +42 -25
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 0.20.3 (2022-05-30)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Add an aria-label to the completion listbox.
|
|
6
|
+
|
|
7
|
+
Fix a regression that caused transactions generated for completion to not have a `userEvent` annotation.
|
|
8
|
+
|
|
9
|
+
## 0.20.2 (2022-05-24)
|
|
10
|
+
|
|
11
|
+
### New features
|
|
12
|
+
|
|
13
|
+
The package now exports an `insertCompletionText` helper that implements the default behavior for applying a completion.
|
|
14
|
+
|
|
15
|
+
## 0.20.1 (2022-05-16)
|
|
16
|
+
|
|
17
|
+
### New features
|
|
18
|
+
|
|
19
|
+
The new `closeOnBlur` option determines whether the completion tooltip is closed when the editor loses focus.
|
|
20
|
+
|
|
21
|
+
`CompletionResult` objects with `filter: false` may now have a `getMatch` property that determines the matched range in the options.
|
|
22
|
+
|
|
1
23
|
## 0.20.0 (2022-04-20)
|
|
2
24
|
|
|
3
25
|
### Breaking changes
|
package/dist/index.cjs
CHANGED
|
@@ -153,32 +153,35 @@ This annotation is added to transactions that are produced by
|
|
|
153
153
|
picking a completion.
|
|
154
154
|
*/
|
|
155
155
|
const pickedCompletion = state.Annotation.define();
|
|
156
|
+
/**
|
|
157
|
+
Helper function that returns a transaction spec which inserts a
|
|
158
|
+
completion's text in the main selection range, and any other
|
|
159
|
+
selection range that has the same text in front of it.
|
|
160
|
+
*/
|
|
161
|
+
function insertCompletionText(state$1, text, from, to) {
|
|
162
|
+
return Object.assign(Object.assign({}, state$1.changeByRange(range => {
|
|
163
|
+
if (range == state$1.selection.main)
|
|
164
|
+
return {
|
|
165
|
+
changes: { from: from, to: to, insert: text },
|
|
166
|
+
range: state.EditorSelection.cursor(from + text.length)
|
|
167
|
+
};
|
|
168
|
+
let len = to - from;
|
|
169
|
+
if (!range.empty ||
|
|
170
|
+
len && state$1.sliceDoc(range.from - len, range.from) != state$1.sliceDoc(from, to))
|
|
171
|
+
return { range };
|
|
172
|
+
return {
|
|
173
|
+
changes: { from: range.from - len, to: range.from, insert: text },
|
|
174
|
+
range: state.EditorSelection.cursor(range.from - len + text.length)
|
|
175
|
+
};
|
|
176
|
+
})), { userEvent: "input.complete" });
|
|
177
|
+
}
|
|
156
178
|
function applyCompletion(view, option) {
|
|
157
179
|
const apply = option.completion.apply || option.completion.label;
|
|
158
180
|
let result = option.source;
|
|
159
|
-
if (typeof apply == "string")
|
|
160
|
-
view.dispatch(view.state.
|
|
161
|
-
|
|
162
|
-
return {
|
|
163
|
-
changes: { from: result.from, to: result.to, insert: apply },
|
|
164
|
-
range: state.EditorSelection.cursor(result.from + apply.length)
|
|
165
|
-
};
|
|
166
|
-
let len = result.to - result.from;
|
|
167
|
-
if (!range.empty ||
|
|
168
|
-
len && view.state.sliceDoc(range.from - len, range.from) != view.state.sliceDoc(result.from, result.to))
|
|
169
|
-
return { range };
|
|
170
|
-
return {
|
|
171
|
-
changes: { from: range.from - len, to: range.from, insert: apply },
|
|
172
|
-
range: state.EditorSelection.cursor(range.from - len + apply.length)
|
|
173
|
-
};
|
|
174
|
-
}), {
|
|
175
|
-
userEvent: "input.complete",
|
|
176
|
-
annotations: pickedCompletion.of(option.completion)
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
181
|
+
if (typeof apply == "string")
|
|
182
|
+
view.dispatch(insertCompletionText(view.state, apply, result.from, result.to));
|
|
183
|
+
else
|
|
180
184
|
apply(view, option.completion, result.from, result.to);
|
|
181
|
-
}
|
|
182
185
|
}
|
|
183
186
|
const SourceCache = new WeakMap();
|
|
184
187
|
function asSource(source) {
|
|
@@ -320,6 +323,7 @@ const completionConfig = state.Facet.define({
|
|
|
320
323
|
return state.combineConfig(configs, {
|
|
321
324
|
activateOnTyping: true,
|
|
322
325
|
override: null,
|
|
326
|
+
closeOnBlur: true,
|
|
323
327
|
maxRenderedOptions: 100,
|
|
324
328
|
defaultKeymap: true,
|
|
325
329
|
optionClass: () => "",
|
|
@@ -328,6 +332,7 @@ const completionConfig = state.Facet.define({
|
|
|
328
332
|
addToOptions: []
|
|
329
333
|
}, {
|
|
330
334
|
defaultKeymap: (a, b) => a && b,
|
|
335
|
+
closeOnBlur: (a, b) => a && b,
|
|
331
336
|
icons: (a, b) => a && b,
|
|
332
337
|
optionClass: (a, b) => c => joinClass(a(c), b(c)),
|
|
333
338
|
addToOptions: (a, b) => a.concat(b)
|
|
@@ -527,6 +532,7 @@ class CompletionTooltip {
|
|
|
527
532
|
ul.id = id;
|
|
528
533
|
ul.setAttribute("role", "listbox");
|
|
529
534
|
ul.setAttribute("aria-expanded", "true");
|
|
535
|
+
ul.setAttribute("aria-label", this.view.state.phrase("Completions"));
|
|
530
536
|
for (let i = range.from; i < range.to; i++) {
|
|
531
537
|
let { completion, match } = options[i];
|
|
532
538
|
const li = ul.appendChild(document.createElement("li"));
|
|
@@ -573,8 +579,14 @@ function sortOptions(active, state) {
|
|
|
573
579
|
for (let a of active)
|
|
574
580
|
if (a.hasResult()) {
|
|
575
581
|
if (a.result.filter === false) {
|
|
576
|
-
|
|
577
|
-
|
|
582
|
+
let getMatch = a.result.getMatch;
|
|
583
|
+
for (let option of a.result.options) {
|
|
584
|
+
let match = [1e9 - i++];
|
|
585
|
+
if (getMatch)
|
|
586
|
+
for (let n of getMatch(option))
|
|
587
|
+
match.push(n);
|
|
588
|
+
options.push(new Option(option, a, match));
|
|
589
|
+
}
|
|
578
590
|
}
|
|
579
591
|
else {
|
|
580
592
|
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to)), match;
|
|
@@ -982,6 +994,11 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
|
|
|
982
994
|
}
|
|
983
995
|
}, {
|
|
984
996
|
eventHandlers: {
|
|
997
|
+
blur() {
|
|
998
|
+
let state = this.view.state.field(completionState, false);
|
|
999
|
+
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur)
|
|
1000
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
1001
|
+
},
|
|
985
1002
|
compositionstart() {
|
|
986
1003
|
this.composing = 1 /* Started */;
|
|
987
1004
|
},
|
|
@@ -1740,6 +1757,7 @@ exports.deleteBracketPair = deleteBracketPair;
|
|
|
1740
1757
|
exports.ifIn = ifIn;
|
|
1741
1758
|
exports.ifNotIn = ifNotIn;
|
|
1742
1759
|
exports.insertBracket = insertBracket;
|
|
1760
|
+
exports.insertCompletionText = insertCompletionText;
|
|
1743
1761
|
exports.moveCompletionSelection = moveCompletionSelection;
|
|
1744
1762
|
exports.nextSnippetField = nextSnippetField;
|
|
1745
1763
|
exports.pickedCompletion = pickedCompletion;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _codemirror_state from '@codemirror/state';
|
|
2
|
-
import { EditorState, Transaction, StateCommand, Facet, Extension, StateEffect } from '@codemirror/state';
|
|
2
|
+
import { EditorState, TransactionSpec, Transaction, StateCommand, Facet, Extension, StateEffect } from '@codemirror/state';
|
|
3
3
|
import { EditorView, KeyBinding, Command } from '@codemirror/view';
|
|
4
4
|
import * as _lezer_common from '@lezer/common';
|
|
5
5
|
|
|
@@ -18,6 +18,11 @@ interface CompletionConfig {
|
|
|
18
18
|
*/
|
|
19
19
|
override?: readonly CompletionSource[] | null;
|
|
20
20
|
/**
|
|
21
|
+
Determines whether the completion tooltip is closed when the
|
|
22
|
+
editor loses focus. Defaults to true.
|
|
23
|
+
*/
|
|
24
|
+
closeOnBlur?: boolean;
|
|
25
|
+
/**
|
|
21
26
|
The maximum number of options to render to the DOM.
|
|
22
27
|
*/
|
|
23
28
|
maxRenderedOptions?: number;
|
|
@@ -243,6 +248,14 @@ interface CompletionResult {
|
|
|
243
248
|
*/
|
|
244
249
|
filter?: boolean;
|
|
245
250
|
/**
|
|
251
|
+
When [`filter`](https://codemirror.net/6/docs/ref/#autocomplete.CompletionResult.filter) is set to
|
|
252
|
+
`false`, this may be provided to compute the ranges on the label
|
|
253
|
+
that match the input. Should return an array of numbers where
|
|
254
|
+
each pair of adjacent numbers provide the start and end of a
|
|
255
|
+
range.
|
|
256
|
+
*/
|
|
257
|
+
getMatch?: (completion: Completion) => readonly number[];
|
|
258
|
+
/**
|
|
246
259
|
Synchronously update the completion result after typing or
|
|
247
260
|
deletion. If given, this should not do any expensive work, since
|
|
248
261
|
it will be called during editor state updates. The function
|
|
@@ -257,6 +270,12 @@ This annotation is added to transactions that are produced by
|
|
|
257
270
|
picking a completion.
|
|
258
271
|
*/
|
|
259
272
|
declare const pickedCompletion: _codemirror_state.AnnotationType<Completion>;
|
|
273
|
+
/**
|
|
274
|
+
Helper function that returns a transaction spec which inserts a
|
|
275
|
+
completion's text in the main selection range, and any other
|
|
276
|
+
selection range that has the same text in front of it.
|
|
277
|
+
*/
|
|
278
|
+
declare function insertCompletionText(state: EditorState, text: string, from: number, to: number): TransactionSpec;
|
|
260
279
|
|
|
261
280
|
/**
|
|
262
281
|
Convert a snippet template to a function that can
|
|
@@ -432,4 +451,4 @@ the currently selected completion.
|
|
|
432
451
|
*/
|
|
433
452
|
declare function setSelectedCompletion(index: number): StateEffect<unknown>;
|
|
434
453
|
|
|
435
|
-
export { CloseBracketConfig, Completion, CompletionContext, CompletionResult, CompletionSource, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, ifIn, ifNotIn, insertBracket, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
|
|
454
|
+
export { CloseBracketConfig, Completion, CompletionContext, CompletionResult, CompletionSource, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, ifIn, ifNotIn, insertBracket, insertCompletionText, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
|
package/dist/index.js
CHANGED
|
@@ -149,32 +149,35 @@ This annotation is added to transactions that are produced by
|
|
|
149
149
|
picking a completion.
|
|
150
150
|
*/
|
|
151
151
|
const pickedCompletion = /*@__PURE__*/Annotation.define();
|
|
152
|
+
/**
|
|
153
|
+
Helper function that returns a transaction spec which inserts a
|
|
154
|
+
completion's text in the main selection range, and any other
|
|
155
|
+
selection range that has the same text in front of it.
|
|
156
|
+
*/
|
|
157
|
+
function insertCompletionText(state, text, from, to) {
|
|
158
|
+
return Object.assign(Object.assign({}, state.changeByRange(range => {
|
|
159
|
+
if (range == state.selection.main)
|
|
160
|
+
return {
|
|
161
|
+
changes: { from: from, to: to, insert: text },
|
|
162
|
+
range: EditorSelection.cursor(from + text.length)
|
|
163
|
+
};
|
|
164
|
+
let len = to - from;
|
|
165
|
+
if (!range.empty ||
|
|
166
|
+
len && state.sliceDoc(range.from - len, range.from) != state.sliceDoc(from, to))
|
|
167
|
+
return { range };
|
|
168
|
+
return {
|
|
169
|
+
changes: { from: range.from - len, to: range.from, insert: text },
|
|
170
|
+
range: EditorSelection.cursor(range.from - len + text.length)
|
|
171
|
+
};
|
|
172
|
+
})), { userEvent: "input.complete" });
|
|
173
|
+
}
|
|
152
174
|
function applyCompletion(view, option) {
|
|
153
175
|
const apply = option.completion.apply || option.completion.label;
|
|
154
176
|
let result = option.source;
|
|
155
|
-
if (typeof apply == "string")
|
|
156
|
-
view.dispatch(view.state.
|
|
157
|
-
|
|
158
|
-
return {
|
|
159
|
-
changes: { from: result.from, to: result.to, insert: apply },
|
|
160
|
-
range: EditorSelection.cursor(result.from + apply.length)
|
|
161
|
-
};
|
|
162
|
-
let len = result.to - result.from;
|
|
163
|
-
if (!range.empty ||
|
|
164
|
-
len && view.state.sliceDoc(range.from - len, range.from) != view.state.sliceDoc(result.from, result.to))
|
|
165
|
-
return { range };
|
|
166
|
-
return {
|
|
167
|
-
changes: { from: range.from - len, to: range.from, insert: apply },
|
|
168
|
-
range: EditorSelection.cursor(range.from - len + apply.length)
|
|
169
|
-
};
|
|
170
|
-
}), {
|
|
171
|
-
userEvent: "input.complete",
|
|
172
|
-
annotations: pickedCompletion.of(option.completion)
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
177
|
+
if (typeof apply == "string")
|
|
178
|
+
view.dispatch(insertCompletionText(view.state, apply, result.from, result.to));
|
|
179
|
+
else
|
|
176
180
|
apply(view, option.completion, result.from, result.to);
|
|
177
|
-
}
|
|
178
181
|
}
|
|
179
182
|
const SourceCache = /*@__PURE__*/new WeakMap();
|
|
180
183
|
function asSource(source) {
|
|
@@ -316,6 +319,7 @@ const completionConfig = /*@__PURE__*/Facet.define({
|
|
|
316
319
|
return combineConfig(configs, {
|
|
317
320
|
activateOnTyping: true,
|
|
318
321
|
override: null,
|
|
322
|
+
closeOnBlur: true,
|
|
319
323
|
maxRenderedOptions: 100,
|
|
320
324
|
defaultKeymap: true,
|
|
321
325
|
optionClass: () => "",
|
|
@@ -324,6 +328,7 @@ const completionConfig = /*@__PURE__*/Facet.define({
|
|
|
324
328
|
addToOptions: []
|
|
325
329
|
}, {
|
|
326
330
|
defaultKeymap: (a, b) => a && b,
|
|
331
|
+
closeOnBlur: (a, b) => a && b,
|
|
327
332
|
icons: (a, b) => a && b,
|
|
328
333
|
optionClass: (a, b) => c => joinClass(a(c), b(c)),
|
|
329
334
|
addToOptions: (a, b) => a.concat(b)
|
|
@@ -523,6 +528,7 @@ class CompletionTooltip {
|
|
|
523
528
|
ul.id = id;
|
|
524
529
|
ul.setAttribute("role", "listbox");
|
|
525
530
|
ul.setAttribute("aria-expanded", "true");
|
|
531
|
+
ul.setAttribute("aria-label", this.view.state.phrase("Completions"));
|
|
526
532
|
for (let i = range.from; i < range.to; i++) {
|
|
527
533
|
let { completion, match } = options[i];
|
|
528
534
|
const li = ul.appendChild(document.createElement("li"));
|
|
@@ -569,8 +575,14 @@ function sortOptions(active, state) {
|
|
|
569
575
|
for (let a of active)
|
|
570
576
|
if (a.hasResult()) {
|
|
571
577
|
if (a.result.filter === false) {
|
|
572
|
-
|
|
573
|
-
|
|
578
|
+
let getMatch = a.result.getMatch;
|
|
579
|
+
for (let option of a.result.options) {
|
|
580
|
+
let match = [1e9 - i++];
|
|
581
|
+
if (getMatch)
|
|
582
|
+
for (let n of getMatch(option))
|
|
583
|
+
match.push(n);
|
|
584
|
+
options.push(new Option(option, a, match));
|
|
585
|
+
}
|
|
574
586
|
}
|
|
575
587
|
else {
|
|
576
588
|
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to)), match;
|
|
@@ -978,6 +990,11 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
978
990
|
}
|
|
979
991
|
}, {
|
|
980
992
|
eventHandlers: {
|
|
993
|
+
blur() {
|
|
994
|
+
let state = this.view.state.field(completionState, false);
|
|
995
|
+
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur)
|
|
996
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
997
|
+
},
|
|
981
998
|
compositionstart() {
|
|
982
999
|
this.composing = 1 /* Started */;
|
|
983
1000
|
},
|
|
@@ -1720,4 +1737,4 @@ function setSelectedCompletion(index) {
|
|
|
1720
1737
|
return setSelectedEffect.of(index);
|
|
1721
1738
|
}
|
|
1722
1739
|
|
|
1723
|
-
export { CompletionContext, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, ifIn, ifNotIn, insertBracket, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
|
|
1740
|
+
export { CompletionContext, acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, deleteBracketPair, ifIn, ifNotIn, insertBracket, insertCompletionText, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, selectedCompletionIndex, setSelectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
|