@mongodb-js/compass-editor 0.5.0 → 0.7.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.
Files changed (65) hide show
  1. package/dist/ace/aggregation-autocompleter.d.ts +1 -1
  2. package/dist/ace/aggregation-autocompleter.d.ts.map +1 -1
  3. package/dist/ace/aggregation-autocompleter.js +7 -6
  4. package/dist/ace/aggregation-autocompleter.js.map +1 -1
  5. package/dist/actions.d.ts +11 -0
  6. package/dist/actions.d.ts.map +1 -0
  7. package/dist/actions.js +90 -0
  8. package/dist/actions.js.map +1 -0
  9. package/dist/autocompleter.d.ts +11 -8
  10. package/dist/autocompleter.d.ts.map +1 -1
  11. package/dist/autocompleter.js +28 -8
  12. package/dist/autocompleter.js.map +1 -1
  13. package/dist/base-editor.d.ts +1 -1
  14. package/dist/base-editor.d.ts.map +1 -1
  15. package/dist/codemirror/ace-compat-autocompleter.d.ts +26 -0
  16. package/dist/codemirror/ace-compat-autocompleter.d.ts.map +1 -0
  17. package/dist/codemirror/ace-compat-autocompleter.js +67 -0
  18. package/dist/codemirror/ace-compat-autocompleter.js.map +1 -0
  19. package/dist/codemirror/aggregation-autocompleter.d.ts +3 -0
  20. package/dist/codemirror/aggregation-autocompleter.d.ts.map +1 -0
  21. package/dist/codemirror/aggregation-autocompleter.js +58 -0
  22. package/dist/codemirror/aggregation-autocompleter.js.map +1 -0
  23. package/dist/codemirror/document-autocompleter.d.ts +3 -0
  24. package/dist/codemirror/document-autocompleter.d.ts.map +1 -0
  25. package/dist/codemirror/document-autocompleter.js +50 -0
  26. package/dist/codemirror/document-autocompleter.js.map +1 -0
  27. package/dist/codemirror/query-autocompleter.d.ts +4 -0
  28. package/dist/codemirror/query-autocompleter.d.ts.map +1 -0
  29. package/dist/codemirror/query-autocompleter.js +22 -0
  30. package/dist/codemirror/query-autocompleter.js.map +1 -0
  31. package/dist/codemirror/stage-autocompleter.d.ts +6 -0
  32. package/dist/codemirror/stage-autocompleter.d.ts.map +1 -0
  33. package/dist/codemirror/stage-autocompleter.js +58 -0
  34. package/dist/codemirror/stage-autocompleter.js.map +1 -0
  35. package/dist/codemirror/utils.d.ts +14 -0
  36. package/dist/codemirror/utils.d.ts.map +1 -0
  37. package/dist/codemirror/utils.js +80 -0
  38. package/dist/codemirror/utils.js.map +1 -0
  39. package/dist/codemirror/validation-autocompleter.d.ts +4 -0
  40. package/dist/codemirror/validation-autocompleter.d.ts.map +1 -0
  41. package/dist/codemirror/validation-autocompleter.js +123 -0
  42. package/dist/codemirror/validation-autocompleter.js.map +1 -0
  43. package/dist/index.d.ts +9 -4
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +13 -2
  46. package/dist/index.js.map +1 -1
  47. package/dist/inline-editor.d.ts +1 -1
  48. package/dist/inline-editor.d.ts.map +1 -1
  49. package/dist/json-editor.d.ts +53 -16
  50. package/dist/json-editor.d.ts.map +1 -1
  51. package/dist/json-editor.js +394 -48
  52. package/dist/json-editor.js.map +1 -1
  53. package/dist/multiline-editor.d.ts +2 -2
  54. package/dist/multiline-editor.d.ts.map +1 -1
  55. package/dist/multiline-editor.js +4 -60
  56. package/dist/multiline-editor.js.map +1 -1
  57. package/dist/prettify.d.ts +1 -1
  58. package/dist/prettify.d.ts.map +1 -1
  59. package/dist/syntax-highlight.d.ts +2 -2
  60. package/dist/syntax-highlight.d.ts.map +1 -1
  61. package/dist/syntax-highlight.js +2 -2
  62. package/dist/syntax-highlight.js.map +1 -1
  63. package/dist/types.d.ts +3 -2
  64. package/dist/types.d.ts.map +1 -1
  65. package/package.json +9 -9
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.JSONEditor = void 0;
26
+ exports.CodemirrorMultilineEditor = exports.CodemirrorInlineEditor = exports.BaseEditor = exports.languageName = exports.languages = void 0;
27
27
  const react_1 = __importStar(require("react"));
28
28
  const view_1 = require("@codemirror/view");
29
29
  const language_1 = require("@codemirror/language");
@@ -38,10 +38,30 @@ const language_2 = require("@codemirror/language");
38
38
  const highlight_1 = require("@lezer/highlight");
39
39
  const polished_1 = require("polished");
40
40
  const prettify_1 = require("./prettify");
41
+ const actions_1 = require("./actions");
41
42
  const editorStyle = (0, compass_components_1.css)({
42
43
  fontSize: 13,
43
44
  fontFamily: compass_components_1.fontFamilies.code,
44
45
  });
46
+ const hiddenScrollStyle = (0, compass_components_1.css)({
47
+ '& .cm-scroller': {
48
+ overflow: '-moz-scrollbars-none',
49
+ msOverflowStyle: 'none',
50
+ },
51
+ '& .cm-scroller::-webkit-scrollbar': {
52
+ display: 'none',
53
+ },
54
+ });
55
+ const breakFocusOutBinding = {
56
+ ...commands_1.indentWithTab,
57
+ run({ state, dispatch }) {
58
+ dispatch(state.update(state.replaceSelection('\t'), {
59
+ scrollIntoView: true,
60
+ userEvent: 'input',
61
+ }));
62
+ return true;
63
+ },
64
+ };
45
65
  const editorPalette = {
46
66
  light: {
47
67
  color: compass_components_1.codePalette.light[3],
@@ -57,6 +77,13 @@ const editorPalette = {
57
77
  infoGutterIconColor: encodeURIComponent(compass_components_1.palette.blue.base),
58
78
  warningGutterIconColor: encodeURIComponent(compass_components_1.palette.yellow.base),
59
79
  errorGutterIconColor: encodeURIComponent(compass_components_1.palette.red.base),
80
+ foldPlaceholderColor: compass_components_1.palette.gray.base,
81
+ foldPlaceholderBackgroundColor: compass_components_1.palette.gray.light3,
82
+ autocompleteColor: compass_components_1.palette.black,
83
+ autocompleteBackgroundColor: compass_components_1.palette.gray.light3,
84
+ autocompleteBorderColor: compass_components_1.palette.gray.light2,
85
+ autocompleteMatchColor: compass_components_1.palette.green.dark1,
86
+ autocompleteSelectedBackgroundColor: compass_components_1.palette.gray.light2,
60
87
  },
61
88
  dark: {
62
89
  color: compass_components_1.codePalette.dark[3],
@@ -72,6 +99,13 @@ const editorPalette = {
72
99
  infoGutterIconColor: encodeURIComponent(compass_components_1.palette.blue.light1),
73
100
  warningGutterIconColor: encodeURIComponent(compass_components_1.palette.yellow.light2),
74
101
  errorGutterIconColor: encodeURIComponent(compass_components_1.palette.red.light1),
102
+ foldPlaceholderColor: compass_components_1.palette.gray.base,
103
+ foldPlaceholderBackgroundColor: compass_components_1.palette.gray.dark3,
104
+ autocompleteColor: compass_components_1.palette.gray.light1,
105
+ autocompleteBackgroundColor: compass_components_1.palette.gray.dark4,
106
+ autocompleteBorderColor: compass_components_1.palette.gray.dark1,
107
+ autocompleteMatchColor: compass_components_1.palette.gray.light3,
108
+ autocompleteSelectedBackgroundColor: compass_components_1.palette.gray.dark2,
75
109
  },
76
110
  };
77
111
  function getStylesForTheme(theme) {
@@ -79,16 +113,18 @@ function getStylesForTheme(theme) {
79
113
  '&': {
80
114
  color: editorPalette[theme].color,
81
115
  backgroundColor: editorPalette[theme].backgroundColor,
116
+ maxHeight: '100%',
82
117
  },
83
118
  '& .cm-scroller': {
84
119
  fontSize: '13px',
85
120
  fontFamily: compass_components_1.fontFamilies.code,
86
- lineHeight: `${compass_components_1.spacing[3]}px`,
87
121
  },
88
122
  '&.cm-editor.cm-focused': {
89
123
  outline: 'none',
90
124
  },
91
125
  '& .cm-content': {
126
+ paddingTop: `${compass_components_1.spacing[1]}px`,
127
+ paddingBottom: `${compass_components_1.spacing[1]}px`,
92
128
  caretColor: editorPalette[theme].cursorColor,
93
129
  },
94
130
  '& .cm-activeLine': {
@@ -102,14 +138,8 @@ function getStylesForTheme(theme) {
102
138
  backgroundColor: editorPalette[theme].gutterBackgroundColor,
103
139
  border: 'none',
104
140
  },
105
- '& .cm-gutters > .cm-gutter:first-child > .cm-gutterElement': {
106
- paddingLeft: `${compass_components_1.spacing[2]}px`,
107
- },
108
- '& .cm-gutters > .cm-gutter:last-child > .cm-gutterElement': {
109
- paddingRight: `${compass_components_1.spacing[2]}px`,
110
- },
111
141
  '& .cm-gutter-lint': {
112
- width: 'auto',
142
+ width: `${compass_components_1.spacing[3]}px`,
113
143
  },
114
144
  '& .cm-gutter-lint .cm-gutterElement': {
115
145
  padding: '0',
@@ -134,6 +164,14 @@ function getStylesForTheme(theme) {
134
164
  '&.cm-focused .cm-activeLineGutter': {
135
165
  backgroundColor: editorPalette[theme].gutterActiveLineBackgroundColor,
136
166
  },
167
+ '& .cm-foldPlaceholder': {
168
+ display: 'inline-block',
169
+ border: 'none',
170
+ color: editorPalette[theme].foldPlaceholderColor,
171
+ backgroundColor: editorPalette[theme].foldPlaceholderBackgroundColor,
172
+ boxShadow: `inset 0 0 0 1px ${editorPalette[theme].foldPlaceholderColor}`,
173
+ padding: '0 2px',
174
+ },
137
175
  '& .foldMarker': {
138
176
  width: `${compass_components_1.spacing[3]}px`,
139
177
  height: `${compass_components_1.spacing[3]}px`,
@@ -169,6 +207,45 @@ function getStylesForTheme(theme) {
169
207
  borderColor: editorPalette[theme].cursorColor,
170
208
  marginLeft: '-1px',
171
209
  },
210
+ '& .cm-tooltip': {
211
+ color: editorPalette[theme].autocompleteColor,
212
+ backgroundColor: editorPalette[theme].autocompleteBackgroundColor,
213
+ border: `1px solid ${editorPalette[theme].autocompleteBorderColor}`,
214
+ },
215
+ '& .cm-tooltip.cm-tooltip-autocomplete > ul': {
216
+ fontFamily: compass_components_1.fontFamilies.code,
217
+ },
218
+ '& .cm-tooltip-autocomplete ul li[aria-selected]': {
219
+ color: editorPalette[theme].autocompleteColor,
220
+ backgroundColor: editorPalette[theme].autocompleteSelectedBackgroundColor,
221
+ },
222
+ '& .cm-completionIcon': {
223
+ display: 'none',
224
+ },
225
+ '& .cm-completionDetail': {
226
+ color: (0, polished_1.rgba)(editorPalette[theme].autocompleteColor, 0.5),
227
+ fontStyle: 'normal',
228
+ marginRight: '1em',
229
+ },
230
+ '& .cm-completionMatchedText': {
231
+ color: editorPalette[theme].autocompleteMatchColor,
232
+ fontWeight: 'bold',
233
+ textDecoration: 'none',
234
+ },
235
+ '& .cm-tooltip .completion-info p': {
236
+ margin: 0,
237
+ marginTop: `${compass_components_1.spacing[2]}px`,
238
+ marginBottom: `${compass_components_1.spacing[2]}px`,
239
+ },
240
+ '& .cm-tooltip .completion-info p:first-child': {
241
+ marginTop: 0,
242
+ },
243
+ '& .cm-tooltip .completion-info p:last-child': {
244
+ marginBottom: 0,
245
+ },
246
+ '& .cm-widgetBuffer': {
247
+ verticalAlign: 'top',
248
+ },
172
249
  }, { dark: theme === 'dark' });
173
250
  }
174
251
  const themeStyles = {
@@ -253,32 +330,52 @@ function createFoldGutterExtension() {
253
330
  const javascriptExpression = lang_javascript_1.javascriptLanguage.configure({
254
331
  top: 'SingleExpression',
255
332
  });
256
- const languages = {
333
+ exports.languages = {
257
334
  json: lang_json_1.json,
258
335
  javascript() {
259
336
  return new language_2.LanguageSupport(javascriptExpression);
260
337
  },
261
338
  };
262
- const languageName = state_1.Facet.define({});
339
+ exports.languageName = state_1.Facet.define({});
340
+ function sheduleDispatch(editorView, transactions, signal) {
341
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
342
+ return;
343
+ }
344
+ if (editorView.updateState != 0) {
345
+ setTimeout(() => {
346
+ sheduleDispatch(editorView, transactions, signal);
347
+ });
348
+ }
349
+ else {
350
+ transactions = Array.isArray(transactions) ? transactions : [transactions];
351
+ editorView.dispatch(...transactions);
352
+ }
353
+ }
263
354
  function useCodemirrorExtensionCompartment(fn, value, editorViewRef) {
264
355
  var _a, _b;
265
- const extensionCreatorRef = (0, react_1.useRef)();
356
+ const extensionCreatorRef = (0, react_1.useRef)(fn);
266
357
  extensionCreatorRef.current = fn;
267
358
  const compartmentRef = (0, react_1.useRef)();
268
359
  (_a = compartmentRef.current) !== null && _a !== void 0 ? _a : (compartmentRef.current = new state_1.Compartment());
269
360
  const initialExtensionRef = (0, react_1.useRef)();
270
361
  (_b = initialExtensionRef.current) !== null && _b !== void 0 ? _b : (initialExtensionRef.current = compartmentRef.current.of(extensionCreatorRef.current()));
271
362
  (0, compass_components_1.useEffectOnChange)(() => {
272
- var _a, _b;
273
- (_a = editorViewRef.current) === null || _a === void 0 ? void 0 : _a.dispatch({
274
- effects: (_b = compartmentRef.current) === null || _b === void 0 ? void 0 : _b.reconfigure(extensionCreatorRef.current()),
275
- });
363
+ var _a;
364
+ if (!editorViewRef.current) {
365
+ return;
366
+ }
367
+ const controller = new AbortController();
368
+ sheduleDispatch(editorViewRef.current, {
369
+ effects: (_a = compartmentRef.current) === null || _a === void 0 ? void 0 : _a.reconfigure(extensionCreatorRef.current()),
370
+ }, controller.signal);
371
+ return () => {
372
+ controller.abort();
373
+ };
276
374
  }, value);
277
375
  return initialExtensionRef.current;
278
376
  }
279
- const BaseEditor = ({ initialText: _initialText, text, onChangeText = () => {
280
- }, language = 'json', showLineNumbers = true, showFoldGutter = true, annotations = [], darkMode: _darkMode, className, readOnly = false, onLoad = () => {
281
- }, ...props }) => {
377
+ const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText: _initialText, text, onChangeText, language = 'json', showLineNumbers = true, showFoldGutter = true, showAnnotationsGutter = true, showScroll = true, highlightActiveLine: shouldHighlightActiveLine = true, annotations, completer, darkMode: _darkMode, className, readOnly = false, onLoad = () => {
378
+ }, minLines, maxLines, lineHeight = 16, placeholder: placeholderString, commands, ...props }, ref) {
282
379
  const darkMode = (0, compass_components_1.useDarkMode)(_darkMode);
283
380
  const onChangeTextRef = (0, react_1.useRef)(onChangeText);
284
381
  const onLoadRef = (0, react_1.useRef)(onLoad);
@@ -286,48 +383,162 @@ const BaseEditor = ({ initialText: _initialText, text, onChangeText = () => {
286
383
  const initialText = (0, react_1.useRef)(_initialText !== null && _initialText !== void 0 ? _initialText : text);
287
384
  const initialLanguage = (0, react_1.useRef)(language);
288
385
  const containerRef = (0, react_1.useRef)(null);
386
+ const editorContainerRef = (0, react_1.useRef)(null);
289
387
  const editorViewRef = (0, react_1.useRef)();
388
+ const [{ height: contentHeight, hasScroll }, setContentHeight] = (0, react_1.useState)({
389
+ height: 0,
390
+ hasScroll: false,
391
+ });
290
392
  onChangeTextRef.current = onChangeText;
291
393
  onLoadRef.current = onLoad;
394
+ (0, react_1.useImperativeHandle)(ref, () => {
395
+ return {
396
+ foldAll() {
397
+ if (!editorViewRef.current) {
398
+ return false;
399
+ }
400
+ return foldAll(editorViewRef.current);
401
+ },
402
+ unfoldAll() {
403
+ if (!editorViewRef.current) {
404
+ return false;
405
+ }
406
+ return (0, language_1.unfoldAll)(editorViewRef.current);
407
+ },
408
+ copyAll() {
409
+ if (!editorViewRef.current) {
410
+ return false;
411
+ }
412
+ return copyAll(editorViewRef.current);
413
+ },
414
+ prettify() {
415
+ if (!editorViewRef.current) {
416
+ return false;
417
+ }
418
+ return prettify(editorViewRef.current);
419
+ },
420
+ applySnippet(template) {
421
+ if (!editorViewRef.current) {
422
+ return false;
423
+ }
424
+ return applySnippet(editorViewRef.current, template);
425
+ },
426
+ focus() {
427
+ if (!editorViewRef.current) {
428
+ return false;
429
+ }
430
+ editorViewRef.current.focus();
431
+ return true;
432
+ },
433
+ get editor() {
434
+ var _a;
435
+ return (_a = editorViewRef.current) !== null && _a !== void 0 ? _a : null;
436
+ },
437
+ };
438
+ }, []);
292
439
  const languageExtension = useCodemirrorExtensionCompartment(() => {
293
- return [languages[language](), languageName.of(language)];
440
+ return [exports.languages[language](), exports.languageName.of(language)];
294
441
  }, language, editorViewRef);
442
+ const activeLineExtension = useCodemirrorExtensionCompartment(() => {
443
+ return !readOnly && shouldHighlightActiveLine
444
+ ? [(0, view_1.highlightActiveLine)(), (0, view_1.highlightActiveLineGutter)()]
445
+ : [];
446
+ }, [readOnly, shouldHighlightActiveLine], editorViewRef);
295
447
  const readOnlyExtension = useCodemirrorExtensionCompartment(() => {
296
- return [state_1.EditorState.readOnly.of(readOnly)].concat(readOnly ? [] : [(0, view_1.highlightActiveLine)(), (0, view_1.highlightActiveLineGutter)()]);
448
+ return state_1.EditorState.readOnly.of(readOnly);
297
449
  }, readOnly, editorViewRef);
298
450
  const themeConfigExtension = useCodemirrorExtensionCompartment(() => {
299
451
  return themeStyles[darkMode ? 'dark' : 'light'];
300
452
  }, darkMode, editorViewRef);
453
+ const lineHeightExtension = useCodemirrorExtensionCompartment(() => {
454
+ return view_1.EditorView.theme({
455
+ '& .cm-scroller': {
456
+ lineHeight: `${lineHeight}px`,
457
+ ...(maxLines && {
458
+ maxHeight: `${maxLines * lineHeight}px`,
459
+ }),
460
+ height: '100%',
461
+ overflowY: 'auto',
462
+ },
463
+ '& .cm-content, & .cm-gutter': {
464
+ ...(minLines && { minHeight: `${minLines * lineHeight}px` }),
465
+ },
466
+ });
467
+ }, [minLines, maxLines, lineHeight], editorViewRef);
301
468
  const lineNumbersExtension = useCodemirrorExtensionCompartment(() => {
302
469
  return showLineNumbers ? (0, view_1.lineNumbers)() : [];
303
470
  }, showLineNumbers, editorViewRef);
304
471
  const foldGutterExtension = useCodemirrorExtensionCompartment(() => {
305
472
  return showFoldGutter ? createFoldGutterExtension() : [];
306
473
  }, showFoldGutter, editorViewRef);
474
+ const shouldShowAnnotationsGutter = showAnnotationsGutter || (annotations && annotations.length === 0);
307
475
  const annotationsGutterExtension = useCodemirrorExtensionCompartment(() => {
308
- return annotations.length === 0 ? [] : (0, lint_1.lintGutter)();
309
- }, annotations.length === 0, editorViewRef);
476
+ return shouldShowAnnotationsGutter ? (0, lint_1.lintGutter)() : [];
477
+ }, shouldShowAnnotationsGutter, editorViewRef);
478
+ const autocompletionExtension = useCodemirrorExtensionCompartment(() => {
479
+ return completer
480
+ ? (0, autocomplete_1.autocompletion)({
481
+ activateOnTyping: true,
482
+ override: [completer],
483
+ })
484
+ : [];
485
+ }, completer, editorViewRef);
486
+ const placeholderExtension = useCodemirrorExtensionCompartment(() => {
487
+ return placeholderString ? (0, view_1.placeholder)(placeholderString) : [];
488
+ }, placeholderString, editorViewRef);
489
+ const commandsExtension = useCodemirrorExtensionCompartment(() => {
490
+ return commands && commands.length > 0 ? view_1.keymap.of(commands) : [];
491
+ }, commands, editorViewRef);
492
+ const updateEditorContentHeight = (0, react_1.useCallback)(() => {
493
+ var _a;
494
+ (_a = editorViewRef.current) === null || _a === void 0 ? void 0 : _a.requestMeasure({
495
+ read(view) {
496
+ return [
497
+ view.contentHeight,
498
+ view.scrollDOM.scrollWidth > view.scrollDOM.clientWidth,
499
+ ];
500
+ },
501
+ write([height, hasScroll]) {
502
+ setContentHeight((state) => {
503
+ if (height !== state.height || hasScroll !== state.hasScroll) {
504
+ return { height, hasScroll };
505
+ }
506
+ return state;
507
+ });
508
+ },
509
+ });
510
+ }, []);
310
511
  (0, react_1.useLayoutEffect)(() => {
311
- if (!containerRef.current) {
512
+ if (!editorContainerRef.current) {
312
513
  throw new Error("Can't mount editor: DOM node is missing");
313
514
  }
314
- const domNode = containerRef.current;
515
+ const domNode = editorContainerRef.current;
315
516
  const editor = (editorViewRef.current = new view_1.EditorView({
316
517
  doc: initialText.current,
317
518
  extensions: [
519
+ state_1.EditorState.tabSize.of(2),
520
+ annotationsGutterExtension,
318
521
  lineNumbersExtension,
319
- (0, commands_1.history)(),
320
522
  foldGutterExtension,
523
+ (0, commands_1.history)(),
321
524
  (0, view_1.drawSelection)(),
322
525
  (0, language_1.indentOnInput)(),
323
526
  (0, language_1.bracketMatching)(),
324
527
  (0, autocomplete_1.closeBrackets)(),
325
- annotationsGutterExtension,
528
+ autocompletionExtension,
326
529
  languageExtension,
327
530
  (0, language_2.syntaxHighlighting)(highlightStyles['light']),
328
531
  (0, language_2.syntaxHighlighting)(highlightStyles['dark']),
532
+ activeLineExtension,
533
+ lineHeightExtension,
329
534
  themeConfigExtension,
535
+ placeholderExtension,
536
+ commandsExtension,
330
537
  view_1.keymap.of([
538
+ {
539
+ key: 'Tab',
540
+ run: autocomplete_1.acceptCompletion,
541
+ },
331
542
  {
332
543
  key: 'Ctrl-Shift-b',
333
544
  run: prettify,
@@ -340,14 +551,16 @@ const BaseEditor = ({ initialText: _initialText, text, onChangeText = () => {
340
551
  ...autocomplete_1.closeBracketsKeymap,
341
552
  ...commands_1.historyKeymap,
342
553
  ...language_1.foldKeymap,
343
- commands_1.indentWithTab,
554
+ ...autocomplete_1.completionKeymap,
555
+ breakFocusOutBinding,
344
556
  ]),
345
557
  readOnlyExtension,
346
558
  view_1.EditorView.updateListener.of((update) => {
347
559
  var _a, _b;
560
+ updateEditorContentHeight();
348
561
  if (update.docChanged) {
349
- const text = (_b = (_a = editorViewRef.current) === null || _a === void 0 ? void 0 : _a.state.sliceDoc()) !== null && _b !== void 0 ? _b : '';
350
- onChangeTextRef.current(text, update);
562
+ const text = (_a = editor.state.sliceDoc()) !== null && _a !== void 0 ? _a : '';
563
+ (_b = onChangeTextRef.current) === null || _b === void 0 ? void 0 : _b.call(onChangeTextRef, text, update);
351
564
  }
352
565
  }),
353
566
  ],
@@ -365,6 +578,7 @@ const BaseEditor = ({ initialText: _initialText, text, onChangeText = () => {
365
578
  else {
366
579
  }
367
580
  }
581
+ updateEditorContentHeight();
368
582
  return () => {
369
583
  delete domNode._cm;
370
584
  editor.destroy();
@@ -376,31 +590,66 @@ const BaseEditor = ({ initialText: _initialText, text, onChangeText = () => {
376
590
  lineNumbersExtension,
377
591
  readOnlyExtension,
378
592
  themeConfigExtension,
593
+ autocompletionExtension,
594
+ lineHeightExtension,
595
+ activeLineExtension,
596
+ placeholderExtension,
597
+ commandsExtension,
598
+ updateEditorContentHeight,
379
599
  ]);
380
600
  (0, react_1.useEffect)(() => {
381
- var _a, _b;
601
+ var _a;
382
602
  if (initialTextProvided.current) {
383
603
  return;
384
604
  }
385
- if (text !== ((_a = editorViewRef.current) === null || _a === void 0 ? void 0 : _a.state.sliceDoc())) {
386
- (_b = editorViewRef.current) === null || _b === void 0 ? void 0 : _b.dispatch({
605
+ if (editorViewRef.current &&
606
+ text !== ((_a = editorViewRef.current.state.sliceDoc()) !== null && _a !== void 0 ? _a : '')) {
607
+ const controller = new AbortController();
608
+ sheduleDispatch(editorViewRef.current, {
387
609
  changes: {
388
610
  from: 0,
389
611
  to: editorViewRef.current.state.doc.length,
390
612
  insert: text,
391
613
  },
392
- });
614
+ }, controller.signal);
615
+ return () => {
616
+ controller.abort();
617
+ };
393
618
  }
394
619
  }, [text]);
395
620
  (0, react_1.useEffect)(() => {
396
- var _a;
397
- (_a = editorViewRef.current) === null || _a === void 0 ? void 0 : _a.dispatch({
398
- effects: lint_1.setDiagnosticsEffect.of(annotations),
399
- });
621
+ if (!editorViewRef.current) {
622
+ return;
623
+ }
624
+ const controller = new AbortController();
625
+ sheduleDispatch(editorViewRef.current, {
626
+ effects: lint_1.setDiagnosticsEffect.of(annotations !== null && annotations !== void 0 ? annotations : []),
627
+ }, controller.signal);
628
+ return () => {
629
+ controller.abort();
630
+ };
400
631
  }, [annotations]);
401
- return (react_1.default.createElement("div", { ref: containerRef, className: (0, compass_components_1.cx)(editorStyle, className), "data-codemirror": "true", ...props }));
402
- };
403
- exports.JSONEditor = BaseEditor;
632
+ (0, react_1.useLayoutEffect)(() => {
633
+ if (containerRef.current) {
634
+ const scrollHeight = hasScroll && showScroll ? 10 : 0;
635
+ const height = Math.min(contentHeight, (maxLines !== null && maxLines !== void 0 ? maxLines : Infinity) * lineHeight) +
636
+ scrollHeight;
637
+ containerRef.current.style.height = `${height}px`;
638
+ }
639
+ }, [maxLines, contentHeight, hasScroll, lineHeight, showScroll]);
640
+ return (react_1.default.createElement("div", { ref: containerRef, className: className, style: {
641
+ width: '100%',
642
+ minHeight: Math.max(lineHeight, (minLines !== null && minLines !== void 0 ? minLines : 0) * lineHeight),
643
+ position: 'relative',
644
+ maxHeight: '100%',
645
+ } },
646
+ react_1.default.createElement("div", { ref: editorContainerRef, className: (0, compass_components_1.cx)(editorStyle, !showScroll && hiddenScrollStyle), style: {
647
+ position: 'absolute',
648
+ width: '100%',
649
+ height: '100%',
650
+ }, "data-codemirror": "true", ...props })));
651
+ });
652
+ exports.BaseEditor = BaseEditor;
404
653
  function isTopNode(node) {
405
654
  return !node
406
655
  ? true
@@ -410,6 +659,16 @@ function isTopNode(node) {
410
659
  ? true
411
660
  : isTopNode(node.parent);
412
661
  }
662
+ const applySnippet = (editor, template) => {
663
+ const completion = (0, autocomplete_1.snippetCompletion)(template, { label: template });
664
+ if (typeof completion.apply === 'function') {
665
+ completion.apply(editor, completion, 0, editor.state.doc.length);
666
+ return true;
667
+ }
668
+ else {
669
+ return false;
670
+ }
671
+ };
413
672
  const foldAll = (editor) => {
414
673
  const foldableProperties = [];
415
674
  (0, language_1.syntaxTree)(editor.state).iterate({
@@ -429,7 +688,7 @@ const foldAll = (editor) => {
429
688
  },
430
689
  });
431
690
  if (foldableProperties.length > 0) {
432
- editor.dispatch({
691
+ sheduleDispatch(editor, {
433
692
  effects: foldableProperties.map((range) => {
434
693
  return language_1.foldEffect.of(range);
435
694
  }),
@@ -445,17 +704,18 @@ const prettify = (editorView) => {
445
704
  if (editorView.state.facet(state_1.EditorState.readOnly)) {
446
705
  return false;
447
706
  }
448
- const language = editorView.state.facet(languageName)[0];
707
+ const language = editorView.state.facet(exports.languageName)[0];
449
708
  const doc = editorView.state.sliceDoc();
450
709
  try {
451
710
  const formatted = (0, prettify_1.prettify)(doc, language === 'json' ? 'json' : 'javascript-expression');
452
711
  if (formatted !== doc) {
453
- editorView.dispatch({
712
+ sheduleDispatch(editorView, {
454
713
  changes: {
455
714
  from: 0,
456
715
  to: editorView.state.doc.length,
457
716
  insert: formatted,
458
717
  },
718
+ scrollIntoView: true,
459
719
  });
460
720
  return true;
461
721
  }
@@ -464,8 +724,94 @@ const prettify = (editorView) => {
464
724
  }
465
725
  return false;
466
726
  };
467
- BaseEditor.foldAll = foldAll;
468
- BaseEditor.unfoldAll = language_1.unfoldAll;
469
- BaseEditor.copyAll = copyAll;
470
- BaseEditor.prettify = prettify;
727
+ const inlineStyles = (0, compass_components_1.css)({
728
+ '& .cm-editor': {
729
+ backgroundColor: 'transparent',
730
+ },
731
+ });
732
+ const InlineEditor = react_1.default.forwardRef(function InlineEditor({ className, ...props }, forwardRef) {
733
+ return (react_1.default.createElement(BaseEditor, { ref: forwardRef, maxLines: 10, showFoldGutter: false, showLineNumbers: false, showAnnotationsGutter: false, showScroll: false, highlightActiveLine: false, className: (0, compass_components_1.cx)(inlineStyles, className), language: "javascript", ...props }));
734
+ });
735
+ exports.CodemirrorInlineEditor = InlineEditor;
736
+ const multilineEditorContainerStyle = (0, compass_components_1.css)({
737
+ position: 'relative',
738
+ height: '100%',
739
+ [`&:focus-within > .multiline-editor-actions,
740
+ &:hover > .multiline-editor-actions`]: {
741
+ display: 'flex',
742
+ },
743
+ });
744
+ const actionsContainerStyle = (0, compass_components_1.css)({
745
+ position: 'absolute',
746
+ top: compass_components_1.spacing[1],
747
+ right: compass_components_1.spacing[2],
748
+ display: 'none',
749
+ gap: compass_components_1.spacing[2],
750
+ });
751
+ const MultilineEditor = react_1.default.forwardRef(function MultilineEditor({ customActions, copyable = true, formattable = true, className, editorClassName, actionsClassName, ...props }, ref) {
752
+ const containerRef = (0, react_1.useRef)(null);
753
+ const editorRef = (0, react_1.useRef)(null);
754
+ (0, react_1.useImperativeHandle)(ref, () => {
755
+ return {
756
+ foldAll() {
757
+ var _a, _b;
758
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.foldAll()) !== null && _b !== void 0 ? _b : false;
759
+ },
760
+ unfoldAll() {
761
+ var _a, _b;
762
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.unfoldAll()) !== null && _b !== void 0 ? _b : false;
763
+ },
764
+ copyAll() {
765
+ var _a, _b;
766
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.copyAll()) !== null && _b !== void 0 ? _b : false;
767
+ },
768
+ prettify() {
769
+ var _a, _b;
770
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.prettify()) !== null && _b !== void 0 ? _b : false;
771
+ },
772
+ focus() {
773
+ var _a, _b;
774
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.focus()) !== null && _b !== void 0 ? _b : false;
775
+ },
776
+ applySnippet(template) {
777
+ var _a, _b;
778
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.applySnippet(template)) !== null && _b !== void 0 ? _b : false;
779
+ },
780
+ get editor() {
781
+ var _a, _b;
782
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.editor) !== null && _b !== void 0 ? _b : null;
783
+ },
784
+ };
785
+ }, []);
786
+ const actions = (0, react_1.useMemo)(() => {
787
+ return [
788
+ copyable && (react_1.default.createElement(actions_1.ActionButton, { key: "Copy", label: "Copy", icon: "Copy", onClick: () => {
789
+ var _a, _b;
790
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.copyAll()) !== null && _b !== void 0 ? _b : false;
791
+ } })),
792
+ formattable && (react_1.default.createElement(actions_1.ActionButton, { key: "Format", label: "Format", icon: react_1.default.createElement(actions_1.FormatIcon, { size: 14, role: "presentation" }), onClick: () => {
793
+ var _a, _b;
794
+ return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.prettify()) !== null && _b !== void 0 ? _b : false;
795
+ } })),
796
+ ...(customActions !== null && customActions !== void 0 ? customActions : []).map((action) => {
797
+ return (react_1.default.createElement(actions_1.ActionButton, { key: action.label, icon: action.icon, label: action.label, onClick: () => {
798
+ var _a;
799
+ if (!((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.editor)) {
800
+ return false;
801
+ }
802
+ return action.action(editorRef.current.editor);
803
+ } }));
804
+ }),
805
+ ];
806
+ }, [copyable, formattable, customActions]);
807
+ return (react_1.default.createElement("div", { ref: containerRef, className: (0, compass_components_1.cx)(multilineEditorContainerStyle, className), onClick: (evt) => {
808
+ var _a;
809
+ if (evt.target === containerRef.current) {
810
+ (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.focus();
811
+ }
812
+ } },
813
+ react_1.default.createElement(BaseEditor, { ref: editorRef, className: editorClassName, language: "javascript", minLines: 10, ...props }),
814
+ actions.length > 0 && (react_1.default.createElement("div", { className: (0, compass_components_1.cx)('multiline-editor-actions', actionsContainerStyle, actionsClassName) }, actions))));
815
+ });
816
+ exports.CodemirrorMultilineEditor = MultilineEditor;
471
817
  //# sourceMappingURL=json-editor.js.map