11import React , { useRef , useEffect , useState } from 'react' ;
22
33import { basicSetup } from 'codemirror' ;
4- import { EditorState , Prec } from '@codemirror/state' ;
5- import { EditorView , keymap , lineNumbers } from '@codemirror/view' ;
4+ import { EditorState , Compartment } from '@codemirror/state' ;
5+ import { EditorView , keymap , lineNumbers , tooltips } from '@codemirror/view' ;
66import { indentWithTab , history } from '@codemirror/commands' ;
77import { json } from '@codemirror/lang-json' ;
88import { defaultKeymap } from '@codemirror/commands' ;
99import { syntaxHighlighting , defaultHighlightStyle } from '@codemirror/language' ;
10+ import { isEqual } from 'lodash' ;
11+ import { autocompletion , CompletionContext } from '@codemirror/autocomplete' ;
12+
13+ // Function to dynamically generate autocomplete options
14+ const createAutocompleteSource = ( options ) => {
15+ return ( context ) => {
16+ let word = context . matchBefore ( / \{ \{ \w * $ / ) ;
17+ if ( ! word ) return null ;
18+
19+ return {
20+ from : word . from ,
21+ options : options . map ( ( option ) => ( { label : `{{${ option } }}` , type : 'keyword' } ) ) ,
22+ } ;
23+ } ;
24+ } ;
25+
26+ // Create a Compartment for autocomplete
27+ const autocompleteCompartment = new Compartment ( ) ;
28+
29+ // Function to update autocomplete options
30+ const updateAutocompleteOptions = ( view , newOptions ) => {
31+ view . dispatch ( {
32+ effects : autocompleteCompartment . reconfigure ( autocompletion ( { override : [ createAutocompleteSource ( newOptions ) ] } ) ) ,
33+ } ) ;
34+ } ;
35+
36+ // Custom styles to hide scrollbar
37+ const hideScrollbar = EditorView . theme ( {
38+ '.cm-scroller' : {
39+ overflowX : 'auto' ,
40+ overflowY : 'hidden' ,
41+ whiteSpace : 'nowrap' ,
42+ scrollbarWidth : 'none' /* For Firefox */ ,
43+ } ,
44+ } ) ;
1045
1146export const Editor = ( { ...props } ) => {
1247 const editor = useRef ( ) ;
1348 const [ view , setView ] = useState ( null ) ;
49+ const [ dynamicOptions , setDynamicOptions ] = useState ( [ ] ) ;
1450
1551 if ( view ) {
52+ if ( ! isEqual ( dynamicOptions , props . completionOptions ) ) {
53+ updateAutocompleteOptions ( view , props . completionOptions ) ;
54+ setDynamicOptions ( props . completionOptions ) ;
55+ }
1656 if ( props . value != view . state . doc . toString ( ) ) {
1757 view . dispatch ( { changes : { from : 0 , to : view . state . doc . length , insert : props . value } } ) ;
1858 }
@@ -35,6 +75,11 @@ export const Editor = ({ ...props }) => {
3575 onUpdate ,
3676 EditorState . readOnly . of ( props . readOnly || false ) ,
3777 history ( ) ,
78+ hideScrollbar ,
79+ autocompleteCompartment . of ( autocompletion ( { override : [ createAutocompleteSource ( dynamicOptions ) ] } ) ) ,
80+ tooltips ( {
81+ parent : document . body ,
82+ } ) ,
3883 ] ,
3984 } ) ;
4085
0 commit comments