@codemirror/autocomplete 0.19.4 → 0.19.5

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,15 @@
1
+ ## 0.19.5 (2021-11-09)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure info tooltips don't stick out of the bottom of the page.
6
+
7
+ ### New features
8
+
9
+ The package exports a new function `selectedCompletion`, which can be used to find out which completion is currently selected.
10
+
11
+ Transactions created by picking a completion now have an annotation (`pickedCompletion`) holding the original completion.
12
+
1
13
  ## 0.19.4 (2021-10-24)
2
14
 
3
15
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -150,6 +150,11 @@ function ensureAnchor(expr, start) {
150
150
  return expr;
151
151
  return new RegExp(`${addStart ? "^" : ""}(?:${source})${addEnd ? "$" : ""}`, (_a = expr.flags) !== null && _a !== void 0 ? _a : (expr.ignoreCase ? "i" : ""));
152
152
  }
153
+ /**
154
+ This annotation is added to transactions that are produced by
155
+ picking a completion.
156
+ */
157
+ const pickedCompletion = state.Annotation.define();
153
158
  function applyCompletion(view, option) {
154
159
  let apply = option.completion.apply || option.completion.label;
155
160
  let result = option.source;
@@ -157,7 +162,8 @@ function applyCompletion(view, option) {
157
162
  view.dispatch({
158
163
  changes: { from: result.from, to: result.to, insert: apply },
159
164
  selection: { anchor: result.from + apply.length },
160
- userEvent: "input.complete"
165
+ userEvent: "input.complete",
166
+ annotations: pickedCompletion.of(option.completion)
161
167
  });
162
168
  }
163
169
  else {
@@ -317,107 +323,6 @@ function joinClass(a, b) {
317
323
  return a ? b ? a + " " + b : a : b;
318
324
  }
319
325
 
320
- const MaxInfoWidth = 300;
321
- const baseTheme = view.EditorView.baseTheme({
322
- ".cm-tooltip.cm-tooltip-autocomplete": {
323
- "& > ul": {
324
- fontFamily: "monospace",
325
- whiteSpace: "nowrap",
326
- overflow: "auto",
327
- maxWidth_fallback: "700px",
328
- maxWidth: "min(700px, 95vw)",
329
- maxHeight: "10em",
330
- listStyle: "none",
331
- margin: 0,
332
- padding: 0,
333
- "& > li": {
334
- cursor: "pointer",
335
- padding: "1px 1em 1px 3px",
336
- lineHeight: 1.2
337
- },
338
- }
339
- },
340
- "&light .cm-tooltip-autocomplete ul li[aria-selected]": {
341
- background: "#39e",
342
- color: "white",
343
- },
344
- "&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
345
- background: "#347",
346
- color: "white",
347
- },
348
- ".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
349
- content: '"···"',
350
- opacity: 0.5,
351
- display: "block",
352
- textAlign: "center"
353
- },
354
- ".cm-tooltip.cm-completionInfo": {
355
- position: "absolute",
356
- padding: "3px 9px",
357
- width: "max-content",
358
- maxWidth: MaxInfoWidth + "px",
359
- },
360
- ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
361
- ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
362
- "&light .cm-snippetField": { backgroundColor: "#00000022" },
363
- "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
364
- ".cm-snippetFieldPosition": {
365
- verticalAlign: "text-top",
366
- width: 0,
367
- height: "1.15em",
368
- margin: "0 -0.7px -.7em",
369
- borderLeft: "1.4px dotted #888"
370
- },
371
- ".cm-completionMatchedText": {
372
- textDecoration: "underline"
373
- },
374
- ".cm-completionDetail": {
375
- marginLeft: "0.5em",
376
- fontStyle: "italic"
377
- },
378
- ".cm-completionIcon": {
379
- fontSize: "90%",
380
- width: ".8em",
381
- display: "inline-block",
382
- textAlign: "center",
383
- paddingRight: ".6em",
384
- opacity: "0.6"
385
- },
386
- ".cm-completionIcon-function, .cm-completionIcon-method": {
387
- "&:after": { content: "'ƒ'" }
388
- },
389
- ".cm-completionIcon-class": {
390
- "&:after": { content: "'○'" }
391
- },
392
- ".cm-completionIcon-interface": {
393
- "&:after": { content: "'◌'" }
394
- },
395
- ".cm-completionIcon-variable": {
396
- "&:after": { content: "'𝑥'" }
397
- },
398
- ".cm-completionIcon-constant": {
399
- "&:after": { content: "'𝐶'" }
400
- },
401
- ".cm-completionIcon-type": {
402
- "&:after": { content: "'𝑡'" }
403
- },
404
- ".cm-completionIcon-enum": {
405
- "&:after": { content: "'∪'" }
406
- },
407
- ".cm-completionIcon-property": {
408
- "&:after": { content: "'□'" }
409
- },
410
- ".cm-completionIcon-keyword": {
411
- "&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering
412
- },
413
- ".cm-completionIcon-namespace": {
414
- "&:after": { content: "'▢'" }
415
- },
416
- ".cm-completionIcon-text": {
417
- "&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
418
- }
419
- });
420
-
421
326
  function optionContent(config) {
422
327
  let content = config.addToOptions.slice();
423
328
  if (config.icons)
@@ -575,17 +480,17 @@ class CompletionTooltip {
575
480
  }
576
481
  measureInfo() {
577
482
  let sel = this.dom.querySelector("[aria-selected]");
578
- if (!sel)
483
+ if (!sel || !this.info)
579
484
  return null;
580
- let rect = this.dom.getBoundingClientRect();
581
- let top = sel.getBoundingClientRect().top - rect.top;
485
+ let rect = this.dom.getBoundingClientRect(), infoRect = this.info.getBoundingClientRect();
486
+ let top = Math.min(sel.getBoundingClientRect().top, innerHeight - infoRect.height) - rect.top;
582
487
  if (top < 0 || top > this.list.clientHeight - 10)
583
488
  return null;
584
489
  let left = this.view.textDirection == view.Direction.RTL;
585
490
  let spaceLeft = rect.left, spaceRight = innerWidth - rect.right;
586
- if (left && spaceLeft < Math.min(MaxInfoWidth, spaceRight))
491
+ if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
587
492
  left = false;
588
- else if (!left && spaceRight < Math.min(MaxInfoWidth, spaceLeft))
493
+ else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
589
494
  left = true;
590
495
  return { top, left };
591
496
  }
@@ -1058,6 +963,106 @@ const completionPlugin = view.ViewPlugin.fromClass(class {
1058
963
  }
1059
964
  });
1060
965
 
966
+ const baseTheme = view.EditorView.baseTheme({
967
+ ".cm-tooltip.cm-tooltip-autocomplete": {
968
+ "& > ul": {
969
+ fontFamily: "monospace",
970
+ whiteSpace: "nowrap",
971
+ overflow: "auto",
972
+ maxWidth_fallback: "700px",
973
+ maxWidth: "min(700px, 95vw)",
974
+ maxHeight: "10em",
975
+ listStyle: "none",
976
+ margin: 0,
977
+ padding: 0,
978
+ "& > li": {
979
+ cursor: "pointer",
980
+ padding: "1px 1em 1px 3px",
981
+ lineHeight: 1.2
982
+ },
983
+ }
984
+ },
985
+ "&light .cm-tooltip-autocomplete ul li[aria-selected]": {
986
+ background: "#39e",
987
+ color: "white",
988
+ },
989
+ "&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
990
+ background: "#347",
991
+ color: "white",
992
+ },
993
+ ".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
994
+ content: '"···"',
995
+ opacity: 0.5,
996
+ display: "block",
997
+ textAlign: "center"
998
+ },
999
+ ".cm-tooltip.cm-completionInfo": {
1000
+ position: "absolute",
1001
+ padding: "3px 9px",
1002
+ width: "max-content",
1003
+ maxWidth: "300px",
1004
+ },
1005
+ ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
1006
+ ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
1007
+ "&light .cm-snippetField": { backgroundColor: "#00000022" },
1008
+ "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
1009
+ ".cm-snippetFieldPosition": {
1010
+ verticalAlign: "text-top",
1011
+ width: 0,
1012
+ height: "1.15em",
1013
+ margin: "0 -0.7px -.7em",
1014
+ borderLeft: "1.4px dotted #888"
1015
+ },
1016
+ ".cm-completionMatchedText": {
1017
+ textDecoration: "underline"
1018
+ },
1019
+ ".cm-completionDetail": {
1020
+ marginLeft: "0.5em",
1021
+ fontStyle: "italic"
1022
+ },
1023
+ ".cm-completionIcon": {
1024
+ fontSize: "90%",
1025
+ width: ".8em",
1026
+ display: "inline-block",
1027
+ textAlign: "center",
1028
+ paddingRight: ".6em",
1029
+ opacity: "0.6"
1030
+ },
1031
+ ".cm-completionIcon-function, .cm-completionIcon-method": {
1032
+ "&:after": { content: "'ƒ'" }
1033
+ },
1034
+ ".cm-completionIcon-class": {
1035
+ "&:after": { content: "'○'" }
1036
+ },
1037
+ ".cm-completionIcon-interface": {
1038
+ "&:after": { content: "'◌'" }
1039
+ },
1040
+ ".cm-completionIcon-variable": {
1041
+ "&:after": { content: "'𝑥'" }
1042
+ },
1043
+ ".cm-completionIcon-constant": {
1044
+ "&:after": { content: "'𝐶'" }
1045
+ },
1046
+ ".cm-completionIcon-type": {
1047
+ "&:after": { content: "'𝑡'" }
1048
+ },
1049
+ ".cm-completionIcon-enum": {
1050
+ "&:after": { content: "'∪'" }
1051
+ },
1052
+ ".cm-completionIcon-property": {
1053
+ "&:after": { content: "'□'" }
1054
+ },
1055
+ ".cm-completionIcon-keyword": {
1056
+ "&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering
1057
+ },
1058
+ ".cm-completionIcon-namespace": {
1059
+ "&:after": { content: "'▢'" }
1060
+ },
1061
+ ".cm-completionIcon-text": {
1062
+ "&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
1063
+ }
1064
+ });
1065
+
1061
1066
  class FieldPos {
1062
1067
  constructor(field, line, from, to) {
1063
1068
  this.field = field;
@@ -1208,8 +1213,7 @@ function snippet(template) {
1208
1213
  let active = new ActiveSnippet(ranges, 0);
1209
1214
  let effects = spec.effects = [setActive.of(active)];
1210
1215
  if (editor.state.field(snippetState, false) === undefined)
1211
- effects.push(state.StateEffect.appendConfig.of([snippetState.init(() => active), addSnippetKeymap,
1212
- snippetPointerHandler, baseTheme]));
1216
+ effects.push(state.StateEffect.appendConfig.of([snippetState, addSnippetKeymap, snippetPointerHandler, baseTheme]));
1213
1217
  }
1214
1218
  editor.dispatch(editor.state.update(spec));
1215
1219
  };
@@ -1259,7 +1263,7 @@ to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet
1259
1263
  const snippetKeymap = state.Facet.define({
1260
1264
  combine(maps) { return maps.length ? maps[0] : defaultSnippetKeymap; }
1261
1265
  });
1262
- const addSnippetKeymap = state.Prec.override(view.keymap.compute([snippetKeymap], state => state.facet(snippetKeymap)));
1266
+ const addSnippetKeymap = state.Prec.highest(view.keymap.compute([snippetKeymap], state => state.facet(snippetKeymap)));
1263
1267
  /**
1264
1268
  Create a completion from a snippet. Returns an object with the
1265
1269
  properties from `completion`, plus an `apply` function that
@@ -1393,7 +1397,7 @@ const completionKeymap = [
1393
1397
  { key: "PageUp", run: moveCompletionSelection(false, "page") },
1394
1398
  { key: "Enter", run: acceptCompletion }
1395
1399
  ];
1396
- const completionKeymapExt = state.Prec.override(view.keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
1400
+ const completionKeymapExt = state.Prec.highest(view.keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
1397
1401
  /**
1398
1402
  Get the current completion status. When completions are available,
1399
1403
  this will return `"active"`. When completions are pending (in the
@@ -1413,6 +1417,14 @@ function currentCompletions(state) {
1413
1417
  let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
1414
1418
  return open ? open.options.map(o => o.completion) : [];
1415
1419
  }
1420
+ /**
1421
+ Return the currently selected completion, if any.
1422
+ */
1423
+ function selectedCompletion(state) {
1424
+ var _a;
1425
+ let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
1426
+ return open ? open.options[open.selected].completion : null;
1427
+ }
1416
1428
 
1417
1429
  exports.CompletionContext = CompletionContext;
1418
1430
  exports.acceptCompletion = acceptCompletion;
@@ -1428,7 +1440,9 @@ exports.ifIn = ifIn;
1428
1440
  exports.ifNotIn = ifNotIn;
1429
1441
  exports.moveCompletionSelection = moveCompletionSelection;
1430
1442
  exports.nextSnippetField = nextSnippetField;
1443
+ exports.pickedCompletion = pickedCompletion;
1431
1444
  exports.prevSnippetField = prevSnippetField;
1445
+ exports.selectedCompletion = selectedCompletion;
1432
1446
  exports.snippet = snippet;
1433
1447
  exports.snippetCompletion = snippetCompletion;
1434
1448
  exports.snippetKeymap = snippetKeymap;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as _codemirror_state from '@codemirror/state';
1
2
  import { EditorState, Transaction, StateCommand, Facet, Extension } from '@codemirror/state';
2
3
  import { EditorView, KeyBinding, Command } from '@codemirror/view';
3
4
  import * as _lezer_common from '@lezer/common';
@@ -80,7 +81,9 @@ interface Completion {
80
81
  its [label](https://codemirror.net/6/docs/ref/#autocomplete.Completion.label). When this holds a
81
82
  string, the completion range is replaced by that string. When it
82
83
  is a function, that function is called to perform the
83
- completion.
84
+ completion. If it fires a transaction, it is responsible for
85
+ adding the [`pickedCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.pickedCompletion)
86
+ annotation to it.
84
87
  */
85
88
  apply?: string | ((view: EditorView, completion: Completion, from: number, to: number) => void);
86
89
  /**
@@ -235,6 +238,11 @@ interface CompletionResult {
235
238
  */
236
239
  filter?: boolean;
237
240
  }
241
+ /**
242
+ This annotation is added to transactions that are produced by
243
+ picking a completion.
244
+ */
245
+ declare const pickedCompletion: _codemirror_state.AnnotationType<Completion>;
238
246
 
239
247
  /**
240
248
  Convert a snippet template to a function that can apply it.
@@ -344,5 +352,9 @@ declare function completionStatus(state: EditorState): null | "active" | "pendin
344
352
  Returns the available completions as an array.
345
353
  */
346
354
  declare function currentCompletions(state: EditorState): readonly Completion[];
355
+ /**
356
+ Return the currently selected completion, if any.
357
+ */
358
+ declare function selectedCompletion(state: EditorState): Completion | null;
347
359
 
348
- export { Completion, CompletionContext, CompletionResult, CompletionSource, acceptCompletion, autocompletion, clearSnippet, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, ifIn, ifNotIn, moveCompletionSelection, nextSnippetField, prevSnippetField, snippet, snippetCompletion, snippetKeymap, startCompletion };
360
+ export { Completion, CompletionContext, CompletionResult, CompletionSource, acceptCompletion, autocompletion, clearSnippet, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, ifIn, ifNotIn, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Facet, combineConfig, StateEffect, StateField, Prec, EditorSelection, Text } from '@codemirror/state';
2
- import { EditorView, Direction, logException, ViewPlugin, Decoration, WidgetType, keymap } from '@codemirror/view';
1
+ import { Annotation, Facet, combineConfig, StateEffect, StateField, Prec, EditorSelection, Text } from '@codemirror/state';
2
+ import { Direction, logException, EditorView, ViewPlugin, Decoration, WidgetType, keymap } from '@codemirror/view';
3
3
  import { showTooltip } from '@codemirror/tooltip';
4
4
  import { syntaxTree, indentUnit } from '@codemirror/language';
5
5
  import { codePointAt, codePointSize, fromCodePoint } from '@codemirror/text';
@@ -146,6 +146,11 @@ function ensureAnchor(expr, start) {
146
146
  return expr;
147
147
  return new RegExp(`${addStart ? "^" : ""}(?:${source})${addEnd ? "$" : ""}`, (_a = expr.flags) !== null && _a !== void 0 ? _a : (expr.ignoreCase ? "i" : ""));
148
148
  }
149
+ /**
150
+ This annotation is added to transactions that are produced by
151
+ picking a completion.
152
+ */
153
+ const pickedCompletion = /*@__PURE__*/Annotation.define();
149
154
  function applyCompletion(view, option) {
150
155
  let apply = option.completion.apply || option.completion.label;
151
156
  let result = option.source;
@@ -153,7 +158,8 @@ function applyCompletion(view, option) {
153
158
  view.dispatch({
154
159
  changes: { from: result.from, to: result.to, insert: apply },
155
160
  selection: { anchor: result.from + apply.length },
156
- userEvent: "input.complete"
161
+ userEvent: "input.complete",
162
+ annotations: pickedCompletion.of(option.completion)
157
163
  });
158
164
  }
159
165
  else {
@@ -313,107 +319,6 @@ function joinClass(a, b) {
313
319
  return a ? b ? a + " " + b : a : b;
314
320
  }
315
321
 
316
- const MaxInfoWidth = 300;
317
- const baseTheme = /*@__PURE__*/EditorView.baseTheme({
318
- ".cm-tooltip.cm-tooltip-autocomplete": {
319
- "& > ul": {
320
- fontFamily: "monospace",
321
- whiteSpace: "nowrap",
322
- overflow: "auto",
323
- maxWidth_fallback: "700px",
324
- maxWidth: "min(700px, 95vw)",
325
- maxHeight: "10em",
326
- listStyle: "none",
327
- margin: 0,
328
- padding: 0,
329
- "& > li": {
330
- cursor: "pointer",
331
- padding: "1px 1em 1px 3px",
332
- lineHeight: 1.2
333
- },
334
- }
335
- },
336
- "&light .cm-tooltip-autocomplete ul li[aria-selected]": {
337
- background: "#39e",
338
- color: "white",
339
- },
340
- "&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
341
- background: "#347",
342
- color: "white",
343
- },
344
- ".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
345
- content: '"···"',
346
- opacity: 0.5,
347
- display: "block",
348
- textAlign: "center"
349
- },
350
- ".cm-tooltip.cm-completionInfo": {
351
- position: "absolute",
352
- padding: "3px 9px",
353
- width: "max-content",
354
- maxWidth: MaxInfoWidth + "px",
355
- },
356
- ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
357
- ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
358
- "&light .cm-snippetField": { backgroundColor: "#00000022" },
359
- "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
360
- ".cm-snippetFieldPosition": {
361
- verticalAlign: "text-top",
362
- width: 0,
363
- height: "1.15em",
364
- margin: "0 -0.7px -.7em",
365
- borderLeft: "1.4px dotted #888"
366
- },
367
- ".cm-completionMatchedText": {
368
- textDecoration: "underline"
369
- },
370
- ".cm-completionDetail": {
371
- marginLeft: "0.5em",
372
- fontStyle: "italic"
373
- },
374
- ".cm-completionIcon": {
375
- fontSize: "90%",
376
- width: ".8em",
377
- display: "inline-block",
378
- textAlign: "center",
379
- paddingRight: ".6em",
380
- opacity: "0.6"
381
- },
382
- ".cm-completionIcon-function, .cm-completionIcon-method": {
383
- "&:after": { content: "'ƒ'" }
384
- },
385
- ".cm-completionIcon-class": {
386
- "&:after": { content: "'○'" }
387
- },
388
- ".cm-completionIcon-interface": {
389
- "&:after": { content: "'◌'" }
390
- },
391
- ".cm-completionIcon-variable": {
392
- "&:after": { content: "'𝑥'" }
393
- },
394
- ".cm-completionIcon-constant": {
395
- "&:after": { content: "'𝐶'" }
396
- },
397
- ".cm-completionIcon-type": {
398
- "&:after": { content: "'𝑡'" }
399
- },
400
- ".cm-completionIcon-enum": {
401
- "&:after": { content: "'∪'" }
402
- },
403
- ".cm-completionIcon-property": {
404
- "&:after": { content: "'□'" }
405
- },
406
- ".cm-completionIcon-keyword": {
407
- "&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering
408
- },
409
- ".cm-completionIcon-namespace": {
410
- "&:after": { content: "'▢'" }
411
- },
412
- ".cm-completionIcon-text": {
413
- "&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
414
- }
415
- });
416
-
417
322
  function optionContent(config) {
418
323
  let content = config.addToOptions.slice();
419
324
  if (config.icons)
@@ -571,17 +476,17 @@ class CompletionTooltip {
571
476
  }
572
477
  measureInfo() {
573
478
  let sel = this.dom.querySelector("[aria-selected]");
574
- if (!sel)
479
+ if (!sel || !this.info)
575
480
  return null;
576
- let rect = this.dom.getBoundingClientRect();
577
- let top = sel.getBoundingClientRect().top - rect.top;
481
+ let rect = this.dom.getBoundingClientRect(), infoRect = this.info.getBoundingClientRect();
482
+ let top = Math.min(sel.getBoundingClientRect().top, innerHeight - infoRect.height) - rect.top;
578
483
  if (top < 0 || top > this.list.clientHeight - 10)
579
484
  return null;
580
485
  let left = this.view.textDirection == Direction.RTL;
581
486
  let spaceLeft = rect.left, spaceRight = innerWidth - rect.right;
582
- if (left && spaceLeft < Math.min(MaxInfoWidth, spaceRight))
487
+ if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
583
488
  left = false;
584
- else if (!left && spaceRight < Math.min(MaxInfoWidth, spaceLeft))
489
+ else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
585
490
  left = true;
586
491
  return { top, left };
587
492
  }
@@ -1054,6 +959,106 @@ const completionPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
1054
959
  }
1055
960
  });
1056
961
 
962
+ const baseTheme = /*@__PURE__*/EditorView.baseTheme({
963
+ ".cm-tooltip.cm-tooltip-autocomplete": {
964
+ "& > ul": {
965
+ fontFamily: "monospace",
966
+ whiteSpace: "nowrap",
967
+ overflow: "auto",
968
+ maxWidth_fallback: "700px",
969
+ maxWidth: "min(700px, 95vw)",
970
+ maxHeight: "10em",
971
+ listStyle: "none",
972
+ margin: 0,
973
+ padding: 0,
974
+ "& > li": {
975
+ cursor: "pointer",
976
+ padding: "1px 1em 1px 3px",
977
+ lineHeight: 1.2
978
+ },
979
+ }
980
+ },
981
+ "&light .cm-tooltip-autocomplete ul li[aria-selected]": {
982
+ background: "#39e",
983
+ color: "white",
984
+ },
985
+ "&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
986
+ background: "#347",
987
+ color: "white",
988
+ },
989
+ ".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
990
+ content: '"···"',
991
+ opacity: 0.5,
992
+ display: "block",
993
+ textAlign: "center"
994
+ },
995
+ ".cm-tooltip.cm-completionInfo": {
996
+ position: "absolute",
997
+ padding: "3px 9px",
998
+ width: "max-content",
999
+ maxWidth: "300px",
1000
+ },
1001
+ ".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
1002
+ ".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
1003
+ "&light .cm-snippetField": { backgroundColor: "#00000022" },
1004
+ "&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
1005
+ ".cm-snippetFieldPosition": {
1006
+ verticalAlign: "text-top",
1007
+ width: 0,
1008
+ height: "1.15em",
1009
+ margin: "0 -0.7px -.7em",
1010
+ borderLeft: "1.4px dotted #888"
1011
+ },
1012
+ ".cm-completionMatchedText": {
1013
+ textDecoration: "underline"
1014
+ },
1015
+ ".cm-completionDetail": {
1016
+ marginLeft: "0.5em",
1017
+ fontStyle: "italic"
1018
+ },
1019
+ ".cm-completionIcon": {
1020
+ fontSize: "90%",
1021
+ width: ".8em",
1022
+ display: "inline-block",
1023
+ textAlign: "center",
1024
+ paddingRight: ".6em",
1025
+ opacity: "0.6"
1026
+ },
1027
+ ".cm-completionIcon-function, .cm-completionIcon-method": {
1028
+ "&:after": { content: "'ƒ'" }
1029
+ },
1030
+ ".cm-completionIcon-class": {
1031
+ "&:after": { content: "'○'" }
1032
+ },
1033
+ ".cm-completionIcon-interface": {
1034
+ "&:after": { content: "'◌'" }
1035
+ },
1036
+ ".cm-completionIcon-variable": {
1037
+ "&:after": { content: "'𝑥'" }
1038
+ },
1039
+ ".cm-completionIcon-constant": {
1040
+ "&:after": { content: "'𝐶'" }
1041
+ },
1042
+ ".cm-completionIcon-type": {
1043
+ "&:after": { content: "'𝑡'" }
1044
+ },
1045
+ ".cm-completionIcon-enum": {
1046
+ "&:after": { content: "'∪'" }
1047
+ },
1048
+ ".cm-completionIcon-property": {
1049
+ "&:after": { content: "'□'" }
1050
+ },
1051
+ ".cm-completionIcon-keyword": {
1052
+ "&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering
1053
+ },
1054
+ ".cm-completionIcon-namespace": {
1055
+ "&:after": { content: "'▢'" }
1056
+ },
1057
+ ".cm-completionIcon-text": {
1058
+ "&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
1059
+ }
1060
+ });
1061
+
1057
1062
  class FieldPos {
1058
1063
  constructor(field, line, from, to) {
1059
1064
  this.field = field;
@@ -1204,8 +1209,7 @@ function snippet(template) {
1204
1209
  let active = new ActiveSnippet(ranges, 0);
1205
1210
  let effects = spec.effects = [setActive.of(active)];
1206
1211
  if (editor.state.field(snippetState, false) === undefined)
1207
- effects.push(StateEffect.appendConfig.of([snippetState.init(() => active), addSnippetKeymap,
1208
- snippetPointerHandler, baseTheme]));
1212
+ effects.push(StateEffect.appendConfig.of([snippetState, addSnippetKeymap, snippetPointerHandler, baseTheme]));
1209
1213
  }
1210
1214
  editor.dispatch(editor.state.update(spec));
1211
1215
  };
@@ -1255,7 +1259,7 @@ to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet
1255
1259
  const snippetKeymap = /*@__PURE__*/Facet.define({
1256
1260
  combine(maps) { return maps.length ? maps[0] : defaultSnippetKeymap; }
1257
1261
  });
1258
- const addSnippetKeymap = /*@__PURE__*/Prec.override(/*@__PURE__*/keymap.compute([snippetKeymap], state => state.facet(snippetKeymap)));
1262
+ const addSnippetKeymap = /*@__PURE__*/Prec.highest(/*@__PURE__*/keymap.compute([snippetKeymap], state => state.facet(snippetKeymap)));
1259
1263
  /**
1260
1264
  Create a completion from a snippet. Returns an object with the
1261
1265
  properties from `completion`, plus an `apply` function that
@@ -1389,7 +1393,7 @@ const completionKeymap = [
1389
1393
  { key: "PageUp", run: /*@__PURE__*/moveCompletionSelection(false, "page") },
1390
1394
  { key: "Enter", run: acceptCompletion }
1391
1395
  ];
1392
- const completionKeymapExt = /*@__PURE__*/Prec.override(/*@__PURE__*/keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
1396
+ const completionKeymapExt = /*@__PURE__*/Prec.highest(/*@__PURE__*/keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
1393
1397
  /**
1394
1398
  Get the current completion status. When completions are available,
1395
1399
  this will return `"active"`. When completions are pending (in the
@@ -1409,5 +1413,13 @@ function currentCompletions(state) {
1409
1413
  let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
1410
1414
  return open ? open.options.map(o => o.completion) : [];
1411
1415
  }
1416
+ /**
1417
+ Return the currently selected completion, if any.
1418
+ */
1419
+ function selectedCompletion(state) {
1420
+ var _a;
1421
+ let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
1422
+ return open ? open.options[open.selected].completion : null;
1423
+ }
1412
1424
 
1413
- export { CompletionContext, acceptCompletion, autocompletion, clearSnippet, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, ifIn, ifNotIn, moveCompletionSelection, nextSnippetField, prevSnippetField, snippet, snippetCompletion, snippetKeymap, startCompletion };
1425
+ export { CompletionContext, acceptCompletion, autocompletion, clearSnippet, closeCompletion, completeAnyWord, completeFromList, completionKeymap, completionStatus, currentCompletions, ifIn, ifNotIn, moveCompletionSelection, nextSnippetField, pickedCompletion, prevSnippetField, selectedCompletion, snippet, snippetCompletion, snippetKeymap, startCompletion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/autocomplete",
3
- "version": "0.19.4",
3
+ "version": "0.19.5",
4
4
  "description": "Autocompletion for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",
@@ -27,7 +27,7 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@codemirror/language": "^0.19.0",
30
- "@codemirror/state": "^0.19.2",
30
+ "@codemirror/state": "^0.19.4",
31
31
  "@codemirror/text": "^0.19.2",
32
32
  "@codemirror/tooltip": "^0.19.0",
33
33
  "@codemirror/view": "^0.19.0",