@monaco-editor/react
Advanced tools
Comparing version 4.0.2 to 4.0.3
### Versions | ||
## 4.0.3 | ||
###### *Jan 18, 2021* | ||
- Editor: enable multi-model support | ||
- types: add `path`, `defaultLanguage` and `saveViewState` for multi-model support | ||
## 4.0.2 | ||
@@ -4,0 +10,0 @@ ###### *Jan 18, 2021* |
@@ -29,5 +29,6 @@ 'use strict'; | ||
defaultValue, | ||
defaultLanguage, | ||
defaultPath, | ||
value, | ||
language, | ||
defaultModelPath, | ||
path, | ||
@@ -41,2 +42,3 @@ | ||
overrideServices, | ||
saveViewState, | ||
@@ -71,8 +73,8 @@ /* === */ | ||
index$2['default'](() => { | ||
const model = index$3.getOrCreateModel(monacoRef.current, defaultValue || value, language, path); | ||
const model = index$3.getOrCreateModel(monacoRef.current, defaultValue || value, defaultLanguage || language, path); | ||
if (model !== editorRef.current.getModel()) { | ||
viewStates.set(previousPath, editorRef.current.saveViewState()); | ||
saveViewState && viewStates.set(previousPath, editorRef.current.saveViewState()); | ||
editorRef.current.setModel(model); | ||
editorRef.current.restoreViewState(viewStates.get(path)); | ||
saveViewState && editorRef.current.restoreViewState(viewStates.get(path)); | ||
} | ||
@@ -84,14 +86,12 @@ }, [path], isEditorReady); | ||
index$2['default'](() => { | ||
if (path === previousPath) { | ||
if (editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)) { | ||
editorRef.current.setValue(value); | ||
} else { | ||
if (value !== editorRef.current.getValue()) { | ||
editorRef.current.executeEdits('', [{ | ||
range: editorRef.current.getModel().getFullModelRange(), | ||
text: value, | ||
forceMoveMarkers: true | ||
}]); | ||
editorRef.current.pushUndoStop(); | ||
} | ||
if (editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)) { | ||
editorRef.current.setValue(value); | ||
} else { | ||
if (value !== editorRef.current.getValue()) { | ||
editorRef.current.executeEdits('', [{ | ||
range: editorRef.current.getModel().getFullModelRange(), | ||
text: value, | ||
forceMoveMarkers: true | ||
}]); | ||
editorRef.current.pushUndoStop(); | ||
} | ||
@@ -101,5 +101,3 @@ } | ||
index$2['default'](() => { | ||
if (path === previousPath) { | ||
monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(), language); | ||
} | ||
monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(), language); | ||
}, [language], isEditorReady); | ||
@@ -116,3 +114,3 @@ index$2['default'](() => { | ||
beforeMountRef.current(monacoRef.current); | ||
const defaultModel = index$3.getOrCreateModel(monacoRef.current, defaultValue || value, language, path || defaultModelPath); | ||
const defaultModel = index$3.getOrCreateModel(monacoRef.current, value || defaultValue, defaultLanguage || language, path || defaultPath); | ||
editorRef.current = monacoRef.current.editor.create(containerRef.current, { | ||
@@ -132,3 +130,3 @@ model: defaultModel, | ||
setIsEditorReady(true); | ||
}, [language, options, overrideServices, theme, value, defaultValue, defaultModelPath, path]); | ||
}, [defaultValue, defaultLanguage, defaultPath, value, language, path, options, overrideServices, theme]); | ||
React.useEffect(() => { | ||
@@ -195,7 +193,9 @@ if (isEditorReady) { | ||
defaultValue: PropTypes__default['default'].string, | ||
defaultPath: PropTypes__default['default'].string, | ||
defaultLanguage: PropTypes__default['default'].string, | ||
value: PropTypes__default['default'].string, | ||
language: PropTypes__default['default'].string, | ||
path: PropTypes__default['default'].string, | ||
/* === */ | ||
defaultModelPath: PropTypes__default['default'].string, | ||
theme: PropTypes__default['default'].string, | ||
@@ -206,2 +206,3 @@ line: PropTypes__default['default'].number, | ||
overrideServices: PropTypes__default['default'].object, | ||
saveViewState: PropTypes__default['default'].bool, | ||
@@ -221,3 +222,5 @@ /* === */ | ||
Editor.defaultProps = { | ||
defaultModelPath: 'inmemory://model/1', | ||
defaultPath: 'inmemory://model/1', | ||
/* === */ | ||
theme: 'light', | ||
@@ -227,2 +230,3 @@ loading: 'Loading...', | ||
overrideServices: {}, | ||
saveViewState: true, | ||
@@ -229,0 +233,0 @@ /* === */ |
@@ -18,5 +18,6 @@ import loader from '@monaco-editor/loader'; | ||
defaultValue, | ||
defaultLanguage, | ||
defaultPath, | ||
value, | ||
language, | ||
defaultModelPath, | ||
path, | ||
@@ -30,2 +31,3 @@ | ||
overrideServices, | ||
saveViewState, | ||
@@ -60,8 +62,8 @@ /* === */ | ||
useUpdate(() => { | ||
const model = getOrCreateModel(monacoRef.current, defaultValue || value, language, path); | ||
const model = getOrCreateModel(monacoRef.current, defaultValue || value, defaultLanguage || language, path); | ||
if (model !== editorRef.current.getModel()) { | ||
viewStates.set(previousPath, editorRef.current.saveViewState()); | ||
saveViewState && viewStates.set(previousPath, editorRef.current.saveViewState()); | ||
editorRef.current.setModel(model); | ||
editorRef.current.restoreViewState(viewStates.get(path)); | ||
saveViewState && editorRef.current.restoreViewState(viewStates.get(path)); | ||
} | ||
@@ -73,14 +75,12 @@ }, [path], isEditorReady); | ||
useUpdate(() => { | ||
if (path === previousPath) { | ||
if (editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)) { | ||
editorRef.current.setValue(value); | ||
} else { | ||
if (value !== editorRef.current.getValue()) { | ||
editorRef.current.executeEdits('', [{ | ||
range: editorRef.current.getModel().getFullModelRange(), | ||
text: value, | ||
forceMoveMarkers: true | ||
}]); | ||
editorRef.current.pushUndoStop(); | ||
} | ||
if (editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)) { | ||
editorRef.current.setValue(value); | ||
} else { | ||
if (value !== editorRef.current.getValue()) { | ||
editorRef.current.executeEdits('', [{ | ||
range: editorRef.current.getModel().getFullModelRange(), | ||
text: value, | ||
forceMoveMarkers: true | ||
}]); | ||
editorRef.current.pushUndoStop(); | ||
} | ||
@@ -90,5 +90,3 @@ } | ||
useUpdate(() => { | ||
if (path === previousPath) { | ||
monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(), language); | ||
} | ||
monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(), language); | ||
}, [language], isEditorReady); | ||
@@ -105,3 +103,3 @@ useUpdate(() => { | ||
beforeMountRef.current(monacoRef.current); | ||
const defaultModel = getOrCreateModel(monacoRef.current, defaultValue || value, language, path || defaultModelPath); | ||
const defaultModel = getOrCreateModel(monacoRef.current, value || defaultValue, defaultLanguage || language, path || defaultPath); | ||
editorRef.current = monacoRef.current.editor.create(containerRef.current, { | ||
@@ -121,3 +119,3 @@ model: defaultModel, | ||
setIsEditorReady(true); | ||
}, [language, options, overrideServices, theme, value, defaultValue, defaultModelPath, path]); | ||
}, [defaultValue, defaultLanguage, defaultPath, value, language, path, options, overrideServices, theme]); | ||
useEffect(() => { | ||
@@ -184,7 +182,9 @@ if (isEditorReady) { | ||
defaultValue: PropTypes.string, | ||
defaultPath: PropTypes.string, | ||
defaultLanguage: PropTypes.string, | ||
value: PropTypes.string, | ||
language: PropTypes.string, | ||
path: PropTypes.string, | ||
/* === */ | ||
defaultModelPath: PropTypes.string, | ||
theme: PropTypes.string, | ||
@@ -195,2 +195,3 @@ line: PropTypes.number, | ||
overrideServices: PropTypes.object, | ||
saveViewState: PropTypes.bool, | ||
@@ -210,3 +211,5 @@ /* === */ | ||
Editor.defaultProps = { | ||
defaultModelPath: 'inmemory://model/1', | ||
defaultPath: 'inmemory://model/1', | ||
/* === */ | ||
theme: 'light', | ||
@@ -216,2 +219,3 @@ loading: 'Loading...', | ||
overrideServices: {}, | ||
saveViewState: true, | ||
@@ -218,0 +222,0 @@ /* === */ |
@@ -35,3 +35,3 @@ // TODO: the whole content should be improved in the next version. | ||
/** | ||
* The initial value of the default (auto created) model | ||
* Default value of the current model | ||
*/ | ||
@@ -41,2 +41,14 @@ defaultValue?: string; | ||
/** | ||
* Default language of the current model | ||
*/ | ||
defaultLanguage?: string; | ||
/** | ||
* Default path of the current model | ||
* Will be passed as the third argument to `.createModel` method | ||
* `monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultPath))` | ||
*/ | ||
defaultPath?: string; | ||
/** | ||
* Value of the current model | ||
@@ -52,7 +64,7 @@ */ | ||
/** | ||
* Path for the default (auto created) model | ||
* Path of the current model | ||
* Will be passed as the third argument to `.createModel` method | ||
* `monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultModelPath))` | ||
* `monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultPath))` | ||
*/ | ||
defaultModelPath?: string; | ||
path?: string; | ||
@@ -89,2 +101,8 @@ /** | ||
/** | ||
* Indicator whether to save the models' view states between model changes or not | ||
* Defaults to true | ||
*/ | ||
saveViewState?: boolean; | ||
/** | ||
* Width of the editor wrapper | ||
@@ -91,0 +109,0 @@ * Defaults to 100% |
@@ -286,5 +286,6 @@ (function (global, factory) { | ||
defaultValue, | ||
defaultLanguage, | ||
defaultPath, | ||
value, | ||
language, | ||
defaultModelPath, | ||
path, | ||
@@ -298,2 +299,3 @@ | ||
overrideServices, | ||
saveViewState, | ||
@@ -328,8 +330,8 @@ /* === */ | ||
useUpdate(() => { | ||
const model = getOrCreateModel(monacoRef.current, defaultValue || value, language, path); | ||
const model = getOrCreateModel(monacoRef.current, defaultValue || value, defaultLanguage || language, path); | ||
if (model !== editorRef.current.getModel()) { | ||
viewStates.set(previousPath, editorRef.current.saveViewState()); | ||
saveViewState && viewStates.set(previousPath, editorRef.current.saveViewState()); | ||
editorRef.current.setModel(model); | ||
editorRef.current.restoreViewState(viewStates.get(path)); | ||
saveViewState && editorRef.current.restoreViewState(viewStates.get(path)); | ||
} | ||
@@ -341,14 +343,12 @@ }, [path], isEditorReady); | ||
useUpdate(() => { | ||
if (path === previousPath) { | ||
if (editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)) { | ||
editorRef.current.setValue(value); | ||
} else { | ||
if (value !== editorRef.current.getValue()) { | ||
editorRef.current.executeEdits('', [{ | ||
range: editorRef.current.getModel().getFullModelRange(), | ||
text: value, | ||
forceMoveMarkers: true | ||
}]); | ||
editorRef.current.pushUndoStop(); | ||
} | ||
if (editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)) { | ||
editorRef.current.setValue(value); | ||
} else { | ||
if (value !== editorRef.current.getValue()) { | ||
editorRef.current.executeEdits('', [{ | ||
range: editorRef.current.getModel().getFullModelRange(), | ||
text: value, | ||
forceMoveMarkers: true | ||
}]); | ||
editorRef.current.pushUndoStop(); | ||
} | ||
@@ -358,5 +358,3 @@ } | ||
useUpdate(() => { | ||
if (path === previousPath) { | ||
monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(), language); | ||
} | ||
monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(), language); | ||
}, [language], isEditorReady); | ||
@@ -373,3 +371,3 @@ useUpdate(() => { | ||
beforeMountRef.current(monacoRef.current); | ||
const defaultModel = getOrCreateModel(monacoRef.current, defaultValue || value, language, path || defaultModelPath); | ||
const defaultModel = getOrCreateModel(monacoRef.current, value || defaultValue, defaultLanguage || language, path || defaultPath); | ||
editorRef.current = monacoRef.current.editor.create(containerRef.current, { | ||
@@ -389,3 +387,3 @@ model: defaultModel, | ||
setIsEditorReady(true); | ||
}, [language, options, overrideServices, theme, value, defaultValue, defaultModelPath, path]); | ||
}, [defaultValue, defaultLanguage, defaultPath, value, language, path, options, overrideServices, theme]); | ||
React.useEffect(() => { | ||
@@ -452,7 +450,9 @@ if (isEditorReady) { | ||
defaultValue: PropTypes__default['default'].string, | ||
defaultPath: PropTypes__default['default'].string, | ||
defaultLanguage: PropTypes__default['default'].string, | ||
value: PropTypes__default['default'].string, | ||
language: PropTypes__default['default'].string, | ||
path: PropTypes__default['default'].string, | ||
/* === */ | ||
defaultModelPath: PropTypes__default['default'].string, | ||
theme: PropTypes__default['default'].string, | ||
@@ -463,2 +463,3 @@ line: PropTypes__default['default'].number, | ||
overrideServices: PropTypes__default['default'].object, | ||
saveViewState: PropTypes__default['default'].bool, | ||
@@ -478,3 +479,5 @@ /* === */ | ||
Editor.defaultProps = { | ||
defaultModelPath: 'inmemory://model/1', | ||
defaultPath: 'inmemory://model/1', | ||
/* === */ | ||
theme: 'light', | ||
@@ -484,2 +487,3 @@ loading: 'Loading...', | ||
overrideServices: {}, | ||
saveViewState: true, | ||
@@ -486,0 +490,0 @@ /* === */ |
@@ -1,1 +0,1 @@ | ||
!function(global,factory){"object"==typeof exports&&"undefined"!=typeof module?factory(exports,require("@monaco-editor/loader"),require("react"),require("prop-types"),require("state-local")):"function"==typeof define&&define.amd?define(["exports","@monaco-editor/loader","react","prop-types","state-local"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).monaco_react={},global.monaco_loader,global.React,global.PropTypes,global.state)}(this,(function(exports,loader,React,PropTypes,state){"use strict";function _interopDefaultLegacy(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var loader__default=_interopDefaultLegacy(loader),React__default=_interopDefaultLegacy(React),PropTypes__default=_interopDefaultLegacy(PropTypes),state__default=_interopDefaultLegacy(state);const loadingStyles={display:"flex",height:"100%",width:"100%",justifyContent:"center",alignItems:"center"};function Loading({content:content}){return React__default.default.createElement("div",{style:loadingStyles},content)}const styles_wrapper={display:"flex",position:"relative",textAlign:"initial"},styles_fullWidth={width:"100%"},styles_hide={display:"none"};function MonacoContainer({width:width,height:height,isEditorReady:isEditorReady,loading:loading,_ref:_ref,className:className,wrapperClassName:wrapperClassName}){return React__default.default.createElement("section",{style:{...styles_wrapper,width:width,height:height},className:wrapperClassName},!isEditorReady&&React__default.default.createElement(Loading,{content:loading}),React__default.default.createElement("div",{ref:_ref,style:{...styles_fullWidth,...!isEditorReady&&styles_hide},className:className}))}MonacoContainer.propTypes={width:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]).isRequired,height:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]).isRequired,loading:PropTypes__default.default.oneOfType([PropTypes__default.default.element,PropTypes__default.default.string]).isRequired,isEditorReady:PropTypes__default.default.bool.isRequired,className:PropTypes__default.default.string,wrapperClassName:PropTypes__default.default.string};var MonacoContainer$1=React.memo(MonacoContainer);function useMount(effect){React.useEffect(effect,[])}function useUpdate(effect,deps,applyChanges=!0){const isInitialMount=React.useRef(!0);React.useEffect(isInitialMount.current||!applyChanges?()=>{isInitialMount.current=!1}:effect,deps)}function noop(){}function getOrCreateModel(monaco,value,language,path){return function(monaco,path){return monaco.editor.getModel(crateModelUri(monaco,path))}(monaco,path)||function(monaco,value,language,path){return monaco.editor.createModel(value,language,crateModelUri(monaco,path))}(monaco,value,language,path)}function crateModelUri(monaco,path){return monaco.Uri.parse(path)}function DiffEditor({original:original,modified:modified,language:language,originalLanguage:originalLanguage,modifiedLanguage:modifiedLanguage,originalModelPath:originalModelPath,modifiedModelPath:modifiedModelPath,theme:theme,loading:loading,options:options,height:height,width:width,className:className,wrapperClassName:wrapperClassName,beforeMount:beforeMount,onMount:onMount}){const[isEditorReady,setIsEditorReady]=React.useState(!1),[isMonacoMounting,setIsMonacoMounting]=React.useState(!0),editorRef=React.useRef(null),monacoRef=React.useRef(null),containerRef=React.useRef(null),onMountRef=React.useRef(onMount),beforeMountRef=React.useRef(beforeMount);useMount((()=>{const cancelable=loader__default.default.init();return cancelable.then((monaco=>(monacoRef.current=monaco)&&setIsMonacoMounting(!1))).catch((error=>"cancelation"!==(null==error?void 0:error.type)&&console.error("Monaco initialization: error:",error))),()=>editorRef.current?disposeEditor():cancelable.cancel()})),useUpdate((()=>{editorRef.current.getModel().modified.setValue(modified)}),[modified],isEditorReady),useUpdate((()=>{editorRef.current.getModel().original.setValue(original)}),[original],isEditorReady),useUpdate((()=>{const{original:original,modified:modified}=editorRef.current.getModel();monacoRef.current.editor.setModelLanguage(original,originalLanguage||language),monacoRef.current.editor.setModelLanguage(modified,modifiedLanguage||language)}),[language,originalLanguage,modifiedLanguage],isEditorReady),useUpdate((()=>{monacoRef.current.editor.setTheme(theme)}),[theme],isEditorReady),useUpdate((()=>{editorRef.current.updateOptions(options)}),[options],isEditorReady);const setModels=React.useCallback((()=>{beforeMountRef.current(monacoRef.current);const originalModel=monacoRef.current.editor.createModel(original,originalLanguage||language,monacoRef.current.Uri.parse(originalModelPath)),modifiedModel=monacoRef.current.editor.createModel(modified,modifiedLanguage||language,monacoRef.current.Uri.parse(modifiedModelPath));editorRef.current.setModel({original:originalModel,modified:modifiedModel})}),[language,modified,modifiedLanguage,original,originalLanguage,originalModelPath,modifiedModelPath]),createEditor=React.useCallback((()=>{editorRef.current=monacoRef.current.editor.createDiffEditor(containerRef.current,{automaticLayout:!0,...options}),setModels(),monacoRef.current.editor.setTheme(theme),setIsEditorReady(!0)}),[options,theme,setModels]);React.useEffect((()=>{isEditorReady&&onMountRef.current(editorRef.current,monacoRef.current)}),[isEditorReady]),React.useEffect((()=>{!isMonacoMounting&&!isEditorReady&&createEditor()}),[isMonacoMounting,isEditorReady,createEditor]);const disposeEditor=()=>editorRef.current.dispose();return React__default.default.createElement(MonacoContainer$1,{width:width,height:height,isEditorReady:isEditorReady,loading:loading,_ref:containerRef,className:className,wrapperClassName:wrapperClassName})}DiffEditor.propTypes={original:PropTypes__default.default.string,modified:PropTypes__default.default.string,language:PropTypes__default.default.string,originalLanguage:PropTypes__default.default.string,modifiedLanguage:PropTypes__default.default.string,originalModelPath:PropTypes__default.default.string,modifiedModelPath:PropTypes__default.default.string,theme:PropTypes__default.default.string,loading:PropTypes__default.default.oneOfType([PropTypes__default.default.element,PropTypes__default.default.string]),options:PropTypes__default.default.object,width:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),height:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),className:PropTypes__default.default.string,wrapperClassName:PropTypes__default.default.string,beforeMount:PropTypes__default.default.func,onMount:PropTypes__default.default.func},DiffEditor.defaultProps={originalModelPath:"inmemory://model/1",modifiedModelPath:"inmemory://model/2",theme:"light",loading:"Loading...",options:{},width:"100%",height:"100%",beforeMount:noop,onMount:noop};var index=React.memo(DiffEditor);const[getModelMarkersSetter,setModelMarkersSetter]=state__default.default.create({backup:null}),viewStates=new Map;function Editor({defaultValue:defaultValue,value:value,language:language,defaultModelPath:defaultModelPath,path:path,theme:theme,line:line,loading:loading,options:options,overrideServices:overrideServices,width:width,height:height,className:className,wrapperClassName:wrapperClassName,beforeMount:beforeMount,onMount:onMount,onChange:onChange,onValidate:onValidate}){const[isEditorReady,setIsEditorReady]=React.useState(!1),[isMonacoMounting,setIsMonacoMounting]=React.useState(!0),monacoRef=React.useRef(null),editorRef=React.useRef(null),containerRef=React.useRef(null),onMountRef=React.useRef(onMount),beforeMountRef=React.useRef(beforeMount),subscriptionRef=React.useRef(null),valueRef=React.useRef(value),previousPath=function(value){const ref=React.useRef();return React.useEffect((()=>{ref.current=value}),[value]),ref.current}(path);useMount((()=>{const cancelable=loader__default.default.init();return cancelable.then((monaco=>(monacoRef.current=monaco)&&setIsMonacoMounting(!1))).catch((error=>"cancelation"!==(null==error?void 0:error.type)&&console.error("Monaco initialization: error:",error))),()=>{return editorRef.current?(null===(_subscriptionRef$curr2=subscriptionRef.current)||void 0===_subscriptionRef$curr2||_subscriptionRef$curr2.dispose(),null===(_editorRef$current$ge=editorRef.current.getModel())||void 0===_editorRef$current$ge||_editorRef$current$ge.dispose(),void editorRef.current.dispose()):cancelable.cancel();var _subscriptionRef$curr2,_editorRef$current$ge}})),useUpdate((()=>{const model=getOrCreateModel(monacoRef.current,defaultValue||value,language,path);model!==editorRef.current.getModel()&&(viewStates.set(previousPath,editorRef.current.saveViewState()),editorRef.current.setModel(model),editorRef.current.restoreViewState(viewStates.get(path)))}),[path],isEditorReady),useUpdate((()=>{editorRef.current.updateOptions(options)}),[options],isEditorReady),useUpdate((()=>{path===previousPath&&(editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)?editorRef.current.setValue(value):value!==editorRef.current.getValue()&&(editorRef.current.executeEdits("",[{range:editorRef.current.getModel().getFullModelRange(),text:value,forceMoveMarkers:!0}]),editorRef.current.pushUndoStop()))}),[value],isEditorReady),useUpdate((()=>{path===previousPath&&monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(),language)}),[language],isEditorReady),useUpdate((()=>{editorRef.current.setScrollPosition({scrollTop:line})}),[line],isEditorReady),useUpdate((()=>{monacoRef.current.editor.setTheme(theme)}),[theme],isEditorReady);const createEditor=React.useCallback((()=>{beforeMountRef.current(monacoRef.current);const defaultModel=getOrCreateModel(monacoRef.current,defaultValue||value,language,path||defaultModelPath);editorRef.current=monacoRef.current.editor.create(containerRef.current,{model:defaultModel,automaticLayout:!0,...options},overrideServices),monacoRef.current.editor.setTheme(theme),getModelMarkersSetter().backup||setModelMarkersSetter({backup:monacoRef.current.editor.setModelMarkers}),setIsEditorReady(!0)}),[language,options,overrideServices,theme,value,defaultValue,defaultModelPath,path]);return React.useEffect((()=>{isEditorReady&&onMountRef.current(editorRef.current,monacoRef.current)}),[isEditorReady]),React.useEffect((()=>{!isMonacoMounting&&!isEditorReady&&createEditor()}),[isMonacoMounting,isEditorReady,createEditor]),valueRef.current=value,React.useEffect((()=>{var _subscriptionRef$curr,_editorRef$current;isEditorReady&&onChange&&(null===(_subscriptionRef$curr=subscriptionRef.current)||void 0===_subscriptionRef$curr||_subscriptionRef$curr.dispose(),subscriptionRef.current=null===(_editorRef$current=editorRef.current)||void 0===_editorRef$current?void 0:_editorRef$current.onDidChangeModelContent((event=>{const editorValue=editorRef.current.getValue();valueRef.current!==editorValue&&onChange(editorValue,event)})))}),[isEditorReady,onChange]),React.useEffect((()=>{isEditorReady&&(monacoRef.current.editor.setModelMarkers=function(model,owner,markers){var _getModelMarkersSette;null===(_getModelMarkersSette=getModelMarkersSetter().backup)||void 0===_getModelMarkersSette||_getModelMarkersSette.call(monacoRef.current.editor,model,owner,markers),0!==markers.length&&(null==onValidate||onValidate(markers))})}),[isEditorReady,onValidate]),React__default.default.createElement(MonacoContainer$1,{width:width,height:height,isEditorReady:isEditorReady,loading:loading,_ref:containerRef,className:className,wrapperClassName:wrapperClassName})}Editor.propTypes={defaultValue:PropTypes__default.default.string,value:PropTypes__default.default.string,language:PropTypes__default.default.string,defaultModelPath:PropTypes__default.default.string,theme:PropTypes__default.default.string,line:PropTypes__default.default.number,loading:PropTypes__default.default.oneOfType([PropTypes__default.default.element,PropTypes__default.default.string]),options:PropTypes__default.default.object,overrideServices:PropTypes__default.default.object,width:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),height:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),className:PropTypes__default.default.string,wrapperClassName:PropTypes__default.default.string,beforeMount:PropTypes__default.default.func,onMount:PropTypes__default.default.func,onChange:PropTypes__default.default.func,onValidate:PropTypes__default.default.func},Editor.defaultProps={defaultModelPath:"inmemory://model/1",theme:"light",loading:"Loading...",options:{},overrideServices:{},width:"100%",height:"100%",beforeMount:noop,onMount:noop,onValidate:noop};var index$1=React.memo(Editor);Object.defineProperty(exports,"loader",{enumerable:!0,get:function(){return loader__default.default}}),exports.DiffEditor=index,exports.default=index$1,exports.useMonaco=function(){const[monaco,setMonaco]=React.useState(loader__default.default.__getMonacoInstance());return useMount((()=>{let cancelable;return monaco||(cancelable=loader__default.default.init(),cancelable.then((monaco=>{setMonaco(monaco)}))),()=>{var _cancelable;return null===(_cancelable=cancelable)||void 0===_cancelable?void 0:_cancelable.cancel()}})),monaco},Object.defineProperty(exports,"__esModule",{value:!0})})); | ||
!function(global,factory){"object"==typeof exports&&"undefined"!=typeof module?factory(exports,require("@monaco-editor/loader"),require("react"),require("prop-types"),require("state-local")):"function"==typeof define&&define.amd?define(["exports","@monaco-editor/loader","react","prop-types","state-local"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).monaco_react={},global.monaco_loader,global.React,global.PropTypes,global.state)}(this,(function(exports,loader,React,PropTypes,state){"use strict";function _interopDefaultLegacy(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var loader__default=_interopDefaultLegacy(loader),React__default=_interopDefaultLegacy(React),PropTypes__default=_interopDefaultLegacy(PropTypes),state__default=_interopDefaultLegacy(state);const loadingStyles={display:"flex",height:"100%",width:"100%",justifyContent:"center",alignItems:"center"};function Loading({content:content}){return React__default.default.createElement("div",{style:loadingStyles},content)}const styles_wrapper={display:"flex",position:"relative",textAlign:"initial"},styles_fullWidth={width:"100%"},styles_hide={display:"none"};function MonacoContainer({width:width,height:height,isEditorReady:isEditorReady,loading:loading,_ref:_ref,className:className,wrapperClassName:wrapperClassName}){return React__default.default.createElement("section",{style:{...styles_wrapper,width:width,height:height},className:wrapperClassName},!isEditorReady&&React__default.default.createElement(Loading,{content:loading}),React__default.default.createElement("div",{ref:_ref,style:{...styles_fullWidth,...!isEditorReady&&styles_hide},className:className}))}MonacoContainer.propTypes={width:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]).isRequired,height:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]).isRequired,loading:PropTypes__default.default.oneOfType([PropTypes__default.default.element,PropTypes__default.default.string]).isRequired,isEditorReady:PropTypes__default.default.bool.isRequired,className:PropTypes__default.default.string,wrapperClassName:PropTypes__default.default.string};var MonacoContainer$1=React.memo(MonacoContainer);function useMount(effect){React.useEffect(effect,[])}function useUpdate(effect,deps,applyChanges=!0){const isInitialMount=React.useRef(!0);React.useEffect(isInitialMount.current||!applyChanges?()=>{isInitialMount.current=!1}:effect,deps)}function noop(){}function getOrCreateModel(monaco,value,language,path){return function(monaco,path){return monaco.editor.getModel(crateModelUri(monaco,path))}(monaco,path)||function(monaco,value,language,path){return monaco.editor.createModel(value,language,crateModelUri(monaco,path))}(monaco,value,language,path)}function crateModelUri(monaco,path){return monaco.Uri.parse(path)}function DiffEditor({original:original,modified:modified,language:language,originalLanguage:originalLanguage,modifiedLanguage:modifiedLanguage,originalModelPath:originalModelPath,modifiedModelPath:modifiedModelPath,theme:theme,loading:loading,options:options,height:height,width:width,className:className,wrapperClassName:wrapperClassName,beforeMount:beforeMount,onMount:onMount}){const[isEditorReady,setIsEditorReady]=React.useState(!1),[isMonacoMounting,setIsMonacoMounting]=React.useState(!0),editorRef=React.useRef(null),monacoRef=React.useRef(null),containerRef=React.useRef(null),onMountRef=React.useRef(onMount),beforeMountRef=React.useRef(beforeMount);useMount((()=>{const cancelable=loader__default.default.init();return cancelable.then((monaco=>(monacoRef.current=monaco)&&setIsMonacoMounting(!1))).catch((error=>"cancelation"!==(null==error?void 0:error.type)&&console.error("Monaco initialization: error:",error))),()=>editorRef.current?disposeEditor():cancelable.cancel()})),useUpdate((()=>{editorRef.current.getModel().modified.setValue(modified)}),[modified],isEditorReady),useUpdate((()=>{editorRef.current.getModel().original.setValue(original)}),[original],isEditorReady),useUpdate((()=>{const{original:original,modified:modified}=editorRef.current.getModel();monacoRef.current.editor.setModelLanguage(original,originalLanguage||language),monacoRef.current.editor.setModelLanguage(modified,modifiedLanguage||language)}),[language,originalLanguage,modifiedLanguage],isEditorReady),useUpdate((()=>{monacoRef.current.editor.setTheme(theme)}),[theme],isEditorReady),useUpdate((()=>{editorRef.current.updateOptions(options)}),[options],isEditorReady);const setModels=React.useCallback((()=>{beforeMountRef.current(monacoRef.current);const originalModel=monacoRef.current.editor.createModel(original,originalLanguage||language,monacoRef.current.Uri.parse(originalModelPath)),modifiedModel=monacoRef.current.editor.createModel(modified,modifiedLanguage||language,monacoRef.current.Uri.parse(modifiedModelPath));editorRef.current.setModel({original:originalModel,modified:modifiedModel})}),[language,modified,modifiedLanguage,original,originalLanguage,originalModelPath,modifiedModelPath]),createEditor=React.useCallback((()=>{editorRef.current=monacoRef.current.editor.createDiffEditor(containerRef.current,{automaticLayout:!0,...options}),setModels(),monacoRef.current.editor.setTheme(theme),setIsEditorReady(!0)}),[options,theme,setModels]);React.useEffect((()=>{isEditorReady&&onMountRef.current(editorRef.current,monacoRef.current)}),[isEditorReady]),React.useEffect((()=>{!isMonacoMounting&&!isEditorReady&&createEditor()}),[isMonacoMounting,isEditorReady,createEditor]);const disposeEditor=()=>editorRef.current.dispose();return React__default.default.createElement(MonacoContainer$1,{width:width,height:height,isEditorReady:isEditorReady,loading:loading,_ref:containerRef,className:className,wrapperClassName:wrapperClassName})}DiffEditor.propTypes={original:PropTypes__default.default.string,modified:PropTypes__default.default.string,language:PropTypes__default.default.string,originalLanguage:PropTypes__default.default.string,modifiedLanguage:PropTypes__default.default.string,originalModelPath:PropTypes__default.default.string,modifiedModelPath:PropTypes__default.default.string,theme:PropTypes__default.default.string,loading:PropTypes__default.default.oneOfType([PropTypes__default.default.element,PropTypes__default.default.string]),options:PropTypes__default.default.object,width:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),height:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),className:PropTypes__default.default.string,wrapperClassName:PropTypes__default.default.string,beforeMount:PropTypes__default.default.func,onMount:PropTypes__default.default.func},DiffEditor.defaultProps={originalModelPath:"inmemory://model/1",modifiedModelPath:"inmemory://model/2",theme:"light",loading:"Loading...",options:{},width:"100%",height:"100%",beforeMount:noop,onMount:noop};var index=React.memo(DiffEditor);const[getModelMarkersSetter,setModelMarkersSetter]=state__default.default.create({backup:null}),viewStates=new Map;function Editor({defaultValue:defaultValue,defaultLanguage:defaultLanguage,defaultPath:defaultPath,value:value,language:language,path:path,theme:theme,line:line,loading:loading,options:options,overrideServices:overrideServices,saveViewState:saveViewState,width:width,height:height,className:className,wrapperClassName:wrapperClassName,beforeMount:beforeMount,onMount:onMount,onChange:onChange,onValidate:onValidate}){const[isEditorReady,setIsEditorReady]=React.useState(!1),[isMonacoMounting,setIsMonacoMounting]=React.useState(!0),monacoRef=React.useRef(null),editorRef=React.useRef(null),containerRef=React.useRef(null),onMountRef=React.useRef(onMount),beforeMountRef=React.useRef(beforeMount),subscriptionRef=React.useRef(null),valueRef=React.useRef(value),previousPath=function(value){const ref=React.useRef();return React.useEffect((()=>{ref.current=value}),[value]),ref.current}(path);useMount((()=>{const cancelable=loader__default.default.init();return cancelable.then((monaco=>(monacoRef.current=monaco)&&setIsMonacoMounting(!1))).catch((error=>"cancelation"!==(null==error?void 0:error.type)&&console.error("Monaco initialization: error:",error))),()=>{return editorRef.current?(null===(_subscriptionRef$curr2=subscriptionRef.current)||void 0===_subscriptionRef$curr2||_subscriptionRef$curr2.dispose(),null===(_editorRef$current$ge=editorRef.current.getModel())||void 0===_editorRef$current$ge||_editorRef$current$ge.dispose(),void editorRef.current.dispose()):cancelable.cancel();var _subscriptionRef$curr2,_editorRef$current$ge}})),useUpdate((()=>{const model=getOrCreateModel(monacoRef.current,defaultValue||value,defaultLanguage||language,path);model!==editorRef.current.getModel()&&(saveViewState&&viewStates.set(previousPath,editorRef.current.saveViewState()),editorRef.current.setModel(model),saveViewState&&editorRef.current.restoreViewState(viewStates.get(path)))}),[path],isEditorReady),useUpdate((()=>{editorRef.current.updateOptions(options)}),[options],isEditorReady),useUpdate((()=>{editorRef.current.getOption(monacoRef.current.editor.EditorOption.readOnly)?editorRef.current.setValue(value):value!==editorRef.current.getValue()&&(editorRef.current.executeEdits("",[{range:editorRef.current.getModel().getFullModelRange(),text:value,forceMoveMarkers:!0}]),editorRef.current.pushUndoStop())}),[value],isEditorReady),useUpdate((()=>{monacoRef.current.editor.setModelLanguage(editorRef.current.getModel(),language)}),[language],isEditorReady),useUpdate((()=>{editorRef.current.setScrollPosition({scrollTop:line})}),[line],isEditorReady),useUpdate((()=>{monacoRef.current.editor.setTheme(theme)}),[theme],isEditorReady);const createEditor=React.useCallback((()=>{beforeMountRef.current(monacoRef.current);const defaultModel=getOrCreateModel(monacoRef.current,value||defaultValue,defaultLanguage||language,path||defaultPath);editorRef.current=monacoRef.current.editor.create(containerRef.current,{model:defaultModel,automaticLayout:!0,...options},overrideServices),monacoRef.current.editor.setTheme(theme),getModelMarkersSetter().backup||setModelMarkersSetter({backup:monacoRef.current.editor.setModelMarkers}),setIsEditorReady(!0)}),[defaultValue,defaultLanguage,defaultPath,value,language,path,options,overrideServices,theme]);return React.useEffect((()=>{isEditorReady&&onMountRef.current(editorRef.current,monacoRef.current)}),[isEditorReady]),React.useEffect((()=>{!isMonacoMounting&&!isEditorReady&&createEditor()}),[isMonacoMounting,isEditorReady,createEditor]),valueRef.current=value,React.useEffect((()=>{var _subscriptionRef$curr,_editorRef$current;isEditorReady&&onChange&&(null===(_subscriptionRef$curr=subscriptionRef.current)||void 0===_subscriptionRef$curr||_subscriptionRef$curr.dispose(),subscriptionRef.current=null===(_editorRef$current=editorRef.current)||void 0===_editorRef$current?void 0:_editorRef$current.onDidChangeModelContent((event=>{const editorValue=editorRef.current.getValue();valueRef.current!==editorValue&&onChange(editorValue,event)})))}),[isEditorReady,onChange]),React.useEffect((()=>{isEditorReady&&(monacoRef.current.editor.setModelMarkers=function(model,owner,markers){var _getModelMarkersSette;null===(_getModelMarkersSette=getModelMarkersSetter().backup)||void 0===_getModelMarkersSette||_getModelMarkersSette.call(monacoRef.current.editor,model,owner,markers),0!==markers.length&&(null==onValidate||onValidate(markers))})}),[isEditorReady,onValidate]),React__default.default.createElement(MonacoContainer$1,{width:width,height:height,isEditorReady:isEditorReady,loading:loading,_ref:containerRef,className:className,wrapperClassName:wrapperClassName})}Editor.propTypes={defaultValue:PropTypes__default.default.string,defaultPath:PropTypes__default.default.string,defaultLanguage:PropTypes__default.default.string,value:PropTypes__default.default.string,language:PropTypes__default.default.string,path:PropTypes__default.default.string,theme:PropTypes__default.default.string,line:PropTypes__default.default.number,loading:PropTypes__default.default.oneOfType([PropTypes__default.default.element,PropTypes__default.default.string]),options:PropTypes__default.default.object,overrideServices:PropTypes__default.default.object,saveViewState:PropTypes__default.default.bool,width:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),height:PropTypes__default.default.oneOfType([PropTypes__default.default.number,PropTypes__default.default.string]),className:PropTypes__default.default.string,wrapperClassName:PropTypes__default.default.string,beforeMount:PropTypes__default.default.func,onMount:PropTypes__default.default.func,onChange:PropTypes__default.default.func,onValidate:PropTypes__default.default.func},Editor.defaultProps={defaultPath:"inmemory://model/1",theme:"light",loading:"Loading...",options:{},overrideServices:{},saveViewState:!0,width:"100%",height:"100%",beforeMount:noop,onMount:noop,onValidate:noop};var index$1=React.memo(Editor);Object.defineProperty(exports,"loader",{enumerable:!0,get:function(){return loader__default.default}}),exports.DiffEditor=index,exports.default=index$1,exports.useMonaco=function(){const[monaco,setMonaco]=React.useState(loader__default.default.__getMonacoInstance());return useMount((()=>{let cancelable;return monaco||(cancelable=loader__default.default.init(),cancelable.then((monaco=>{setMonaco(monaco)}))),()=>{var _cancelable;return null===(_cancelable=cancelable)||void 0===_cancelable?void 0:_cancelable.cancel()}})),monaco},Object.defineProperty(exports,"__esModule",{value:!0})})); |
{ | ||
"name": "@monaco-editor/react", | ||
"version": "4.0.2", | ||
"description": "Monaco editor wrapper for easy/one-line integration with React applications (e.g. powered by create-react-app) without need of webpack configuration files", | ||
"version": "4.0.3", | ||
"description": "Monaco Editor for React - use the monaco-editor in any React application without needing to use webpack (or rollup/parcel/etc) configuration files / plugins", | ||
"author": "Suren Atoyan <contact@surenatoyan.com>", | ||
@@ -6,0 +6,0 @@ "main": "lib/cjs/index.js", |
@@ -1,2 +0,2 @@ | ||
import React, { useState, useRef } from 'react'; | ||
import React, { useState, useRef, useCallback } from 'react'; | ||
import { TreeView, TreeItem } from '@material-ui/lab'; | ||
@@ -6,6 +6,24 @@ import { makeStyles } from '@material-ui/core/styles'; | ||
import Fb from './Fb'; | ||
import files from './files'; | ||
import { someCSSCodeExample, someHTMLCodeExample, someJSCodeExample } from './files'; | ||
import Editor, { useMonaco } from '../../lib/es'; | ||
// import Editor from '@monaco-editor/react'; | ||
const files = { | ||
"script.js": { | ||
name: "script.js", | ||
language: "javascript", | ||
value: someJSCodeExample, | ||
}, | ||
"style.css": { | ||
name: "style.css", | ||
language: "css", | ||
value: someCSSCodeExample, | ||
}, | ||
"index.html": { | ||
name: "index.html", | ||
language: "html", | ||
value: someHTMLCodeExample, | ||
}, | ||
}; | ||
const useStyles = makeStyles({ | ||
@@ -23,106 +41,23 @@ root: { | ||
// function App() { | ||
// const classes = useStyles(); | ||
// const [file, setFile] = useState(null); | ||
// const editorRef = useRef(); | ||
// const monaco = useMonaco(); | ||
// function handleEditorDidMount(editor) { | ||
// editorRef.current = editor; | ||
// window.editor = editor; | ||
// editor.focus(); | ||
// } | ||
// function handleFileOpen(_, fileName) { | ||
// const nextFile = getFile(files.children, fileName); | ||
// if (nextFile) setFile(nextFile); | ||
// } | ||
// function handleValidation(markers) { | ||
// markers.forEach(marker => console.log('on validate', marker.message)); | ||
// } | ||
// function getTree(children) { | ||
// return children.map(item => { | ||
// if (item.children) { | ||
// return <TreeItem | ||
// key={item.name} | ||
// nodeId={item.name} | ||
// label={item.name} | ||
// > | ||
// {getTree(item.children)} | ||
// </TreeItem> | ||
// } else { | ||
// return <TreeItem | ||
// key={item.name} | ||
// nodeId={item.name} | ||
// label={item.name} | ||
// />; | ||
// } | ||
// }); | ||
// } | ||
// return ( | ||
// <Fb className={classes.fullSize} mt={10} ml={10}> | ||
// <TreeView | ||
// className={classes.root} | ||
// defaultCollapseIcon={"🕛"} | ||
// defaultExpandIcon={"🕡"} | ||
// onNodeSelect={handleFileOpen} | ||
// > | ||
// { | ||
// files.children && getTree(files.children) | ||
// } | ||
// </TreeView> | ||
// { | ||
// file && ( | ||
// // <Editor | ||
// // height="100vh" | ||
// // width="50%" | ||
// // theme="vs-dark" | ||
// // path={file.name} | ||
// // language={file.language} | ||
// // value={rTabs(file.value)} | ||
// // editorDidMount={handleEditorDidMount} | ||
// // /> | ||
// <Editor | ||
// height="100vh" | ||
// width="50%" | ||
// theme="vs-dark" | ||
// path={file.name} | ||
// language={file.language} | ||
// value={rTabs(file.value)} | ||
// onMount={handleEditorDidMount} | ||
// onValidate={handleValidation} | ||
// /> | ||
// ) | ||
// } | ||
// </Fb> | ||
// ); | ||
// } | ||
function App() { | ||
const [language, setLanguage] = useState('javascript'); | ||
const [value, setValue] = useState(''); | ||
const [fileName, setFileName] = useState('script.js'); | ||
function toggleLanguage() { | ||
setLanguage(language => language === 'javascript' ? 'python' : 'javascript'); | ||
} | ||
const file = files[fileName]; | ||
function handleEditorChange(value) { | ||
if (value.includes('eval')) { | ||
setValue('no no no'); | ||
} else { | ||
setValue(value); | ||
} | ||
} | ||
const handleEditorChange = useCallback((markers) => { | ||
markers.forEach(marker => console.log(marker.message)) | ||
}, []); | ||
return ( | ||
<React.Fragment> | ||
<button onClick={toggleLanguage}>language</button> | ||
<button disabled={fileName === 'script.js'} onClick={() => setFileName('script.js')}>script.js</button> | ||
<button disabled={fileName === 'style.css'} onClick={() => setFileName('style.css')}>style.css</button> | ||
<button disabled={fileName === 'index.html'} onClick={() => setFileName('index.html')}>index.html</button> | ||
<Editor | ||
language={language} | ||
value={value} | ||
height="100vh" | ||
onChange={handleEditorChange} | ||
height="80vh" | ||
theme="vs-dark" | ||
path={file.name} | ||
defaultLanguage={file.language} | ||
defaultValue={file.value} | ||
onValidate={handleEditorChange} | ||
/> | ||
@@ -129,0 +64,0 @@ </React.Fragment> |
@@ -0,1 +1,204 @@ | ||
const someJSCodeExample = ` | ||
// The source (has been changed) is https://github.com/facebook/react/issues/5465#issuecomment-157888325 | ||
const CANCELATION_MESSAGE = { | ||
type: 'cancelation', | ||
msg: 'operation is manually canceled', | ||
}; | ||
function makeCancelable(promise) { | ||
let hasCanceled_ = false; | ||
const wrappedPromise = new Promise((resolve, reject) => { | ||
promise.then(val => hasCanceled_ ? reject(CANCELATION_MESSAGE) : resolve(val)); | ||
promise.catch(reject); | ||
}); | ||
return (wrappedPromise.cancel = () => (hasCanceled_ = true), wrappedPromise); | ||
} | ||
export default makeCancelable; | ||
`; | ||
const someCSSCodeExample = ` | ||
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); | ||
* { | ||
margin: 0; | ||
padding: 0; | ||
box-sizing: border-box; | ||
outline: none; | ||
-ms-overflow-style: none; | ||
scrollbar-width: none; | ||
} | ||
*::-webkit-scrollbar { | ||
display: none; | ||
} | ||
body { | ||
margin: 0; | ||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', | ||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', | ||
sans-serif; | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
} | ||
[type=reset], [type=submit], button, html [type=button] { | ||
-webkit-appearance: button; | ||
} | ||
[type=button]{ | ||
-webkit-appearance: none; | ||
} | ||
.full-width { | ||
width: 100%; | ||
} | ||
.full-height { | ||
height: 100%; | ||
} | ||
.full-size { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
.ql-editor a { | ||
color: rgba(255, 255, 255, 0.20); | ||
cursor: pointer; | ||
padding-left: 8px; | ||
padding-right: 8px; | ||
text-decoration: none; | ||
} | ||
.ql-editor ul, .ql-editor li, .ql-editor ol { | ||
margin-left: 16px; | ||
} | ||
.ql-editor object { | ||
color: #d32f2f; | ||
} | ||
.ql-editor blockquote { | ||
border-left: 3px solid rgba(255, 255, 255, 0.12); | ||
padding-top: 8px; | ||
padding-left: 24px; | ||
padding-right: 16px; | ||
padding-bottom: 8px; | ||
} | ||
.ql-editor .ql-align-center { | ||
text-align: center; | ||
} | ||
.ql-editor .ql-align-justify { | ||
text-align: justify; | ||
} | ||
.ql-editor .ql-align-right { | ||
text-align: right; | ||
} | ||
.ql-editor a:hover { | ||
text-decoration: underline; | ||
} | ||
`; | ||
const someHTMLCodeExample = ` | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> | ||
<!-- https://web.dev/uses-rel-preconnect --> | ||
<link rel="preconnect" href="https://storage.googleapis.com"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<meta name="theme-color" content="#111" /> | ||
<meta name="keywords" content="wlist, wishes, wishes list" /> | ||
<meta | ||
name="description" | ||
content="Wlist" | ||
data-react-helmet="true" | ||
/> | ||
<meta | ||
property="og:title" | ||
content="Wlist" | ||
data-react-helmet="true" | ||
> | ||
<meta | ||
property="og:description" | ||
content="Wlist" | ||
data-react-helmet="true" | ||
> | ||
<meta | ||
property="og:url" | ||
content="%PUBLIC_URL%" | ||
data-react-helmet="true" | ||
> | ||
<meta | ||
property="og:image" | ||
content="%PUBLIC_URL%/images/cover.png" | ||
data-react-helmet="true" | ||
/> | ||
<meta | ||
name="twitter:card" | ||
content="summary" | ||
data-react-helmet="true" | ||
/> | ||
<meta property="og:type" content="website" /> | ||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> | ||
<!-- | ||
manifest.json provides metadata used when your web app is installed on a | ||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ | ||
--> | ||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" crossorigin="use-credentials" /> | ||
<!-- https://web.dev/defer-non-critical-css/ --> | ||
<link rel="preload" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'"> | ||
<title>Wlist</title> | ||
<!-- ie --> | ||
<script type="text/javascript"> | ||
var ua = navigator.userAgent; | ||
var is_ie = ua.indexOf('MSIE ') > -1 || ua.indexOf('Trident/') > -1; | ||
if (is_ie) { | ||
document.ie = 'true'; | ||
var ie_script = document.createElement('script'); | ||
var ie_styles = document.createElement('link'); | ||
ie_script.src = 'no-ie/init.js'; | ||
ie_styles.rel = 'stylesheet'; | ||
ie_styles.href = 'no-ie/styles.css'; | ||
function injectScripts() { | ||
document.body.innerHTML = ''; | ||
document.body.appendChild(ie_styles); | ||
document.body.appendChild(ie_script); | ||
} | ||
if (document.addEventListener) { | ||
document.addEventListener('DOMContentLoaded', injectScripts); | ||
} else { // before IE 9 | ||
document.attachEvent('DOMContentLoaded', injectScripts); | ||
} | ||
} | ||
</script> | ||
</head> | ||
<body> | ||
<noscript>You need to enable JavaScript to run this app.</noscript> | ||
<script type="text/javascript"> | ||
// set the body color before app initialization, to avoid blinking | ||
var themeMode = localStorage.getItem('theme-mode'); | ||
var initialBodyStyles = document.createElement('style'); | ||
var currentThemeColor = themeMode === 'light' ? '#fafafa': '#111'; | ||
initialBodyStyles.innerText = 'body { background-color: ' + currentThemeColor + ' }'; | ||
document.head.appendChild(initialBodyStyles); | ||
// also set meta[name="theme-color"] content | ||
var metaTheme = document.querySelector('meta[name="theme-color"]'); | ||
metaTheme.content = currentThemeColor; | ||
</script> | ||
<div id="root"></div> | ||
</body> | ||
</html> | ||
`; | ||
const files = { | ||
@@ -282,2 +485,4 @@ "children": [ | ||
export { someCSSCodeExample, someHTMLCodeExample, someJSCodeExample }; | ||
export default files; |
@@ -36,3 +36,3 @@ # @monaco-editor/react · [![monthly downloads](https://img.shields.io/npm/dm/@monaco-editor/react)](https://www.npmjs.com/package/@monaco-editor/react) [![gitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/suren-atoyan/monaco-react/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/@monaco-editor/react.svg?style=flat)](https://www.npmjs.com/package/@monaco-editor/react) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/suren-atoyan/monaco-react/pulls) | ||
* [`loader/config`](#loader-config) | ||
* [`uncontrolled/controlled` modes](#uncontrolled-controlled-modes) | ||
* [Multi-model editor](#multi-model-editor) | ||
* [`onValidate`](#onvalidate) | ||
@@ -409,8 +409,73 @@ * [Notes](#notes) | ||
#### `uncontrolled-controlled modes` | ||
#### Multi-model editor | ||
Like usual `input` element, `monaco` editor also maintains its state. But, unlike `input` element, it's uncommon to circulate the whole state of the editor in your component. Usually you don't need it. If you specify the `value` property, the component behaves in `controlled` mode, otherwise - in `uncontrolled` mode. Generally `uncontrolled` mode is used to keep the nature of the `monaco` editor as much as it is possible. And based on our experience we can say that in most cases it will cover your needs. And we highly recommend using that one. | ||
When you render the `Editor` component, a default model is being created. It's important to mention that when you change the `language` or `value` props, they affect the same model that has been auto-created at the mount of the component. In most cases it's okay, but the developers face problems when they want to implement a multi-model editor to support tabs/files like in `IDE`s. And previously to handle multiple models they had to do it manually and out of the component. Now, the multi-model `API` is supported :tada: Let's check how it works. There are three parameters to create a model - `value`, `language` and `path` (`monaco.editor.createModel(value, language, monaco.Uri.parse(path))`). You can consider last one (`path`) as an identifier for the model. The `Editor` component, now, has a `path` prop. When you specify a `path` prop, the `Editor` component checks if it has a model by that path or not. If yes, the existing model will be shown, otherwise, a new one will be created (and stored). Using this technique you can correspond your files with paths, and create a fully multi-model editor. You can open your file, do some changes, choose another file, and when you come back to the first one the previous model will be shown with the whole view state, text selection, undo stack, scroll position, etc. | ||
So, if you want to get the current value, you always can use the `editor` instance to do so - `editor.getValue()` or use `onChange` prop to get it. [Here](#get-value) are the examples. But in any case `controlled` mode is also available | ||
Here is a simple example: let's imagine we have a `JSON` like representation of some file structure, something like this: | ||
```javascript | ||
const files = { | ||
"script.js": { | ||
name: "script.js", | ||
language: "javascript", | ||
value: someJSCodeExample, | ||
}, | ||
"style.css": { | ||
name: "style.css", | ||
language: "css", | ||
value: someCSSCodeExample, | ||
}, | ||
"index.html": { | ||
name: "index.html", | ||
language: "html", | ||
value: someHTMLCodeExample, | ||
}, | ||
} | ||
``` | ||
And here is our simple multi-model editor implementation: | ||
```javascript | ||
import React from "react"; | ||
import ReactDOM from "react-dom"; | ||
import Editor from "@monaco-editor/react"; | ||
function App() { | ||
const [fileName, setFileName] = useState('script.js'); | ||
const file = files[fileName]; | ||
return ( | ||
<> | ||
<button disabled={fileName === 'script.js'} onClick={() => setFileName('script.js')}>script.js</button> | ||
<button disabled={fileName === 'style.css'} onClick={() => setFileName('style.css')}>style.css</button> | ||
<button disabled={fileName === 'index.html'} onClick={() => setFileName('index.html')}>index.html</button> | ||
<Editor | ||
height="80vh" | ||
theme="vs-dark" | ||
path={file.name} | ||
defaultLanguage={file.language} | ||
defaultValue={file.value} | ||
/> | ||
</> | ||
); | ||
} | ||
const rootElement = document.getElementById("root"); | ||
ReactDOM.render(<App />, rootElement); | ||
``` | ||
The properties: | ||
- `defaultValue` | ||
- `defaultLanguage` | ||
- `defaultPath` | ||
- `value` | ||
- `language` | ||
- `path` | ||
- `saveViewState` | ||
will give you more flexibility in working with a multi-model editor | ||
#### `onValidate` | ||
@@ -612,6 +677,8 @@ | ||
|:----------|:-------------|:------|:------| | ||
| defaultValue | string || The initial value of the default (auto created) model | | ||
| defaultValue | string || Default value of the current model | | ||
| defaultLanguage | string || Default language of the current model | | ||
| defaultPath | string || Default path of the current model. Will be passed as the third argument to `.createModel` method - `monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultPath))` | | ||
| value | string || Value of the current model | | ||
| language | enum: ... | | Language of the current model (all languages that are [supported](https://github.com/microsoft/monaco-languages) by monaco-editor) | | ||
| defaultModelPath | string || Path for the default (auto created) model. Will be passed as the third argument to `.createModel` method - `monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultModelPath))` | | ||
| path | string || Path of the current model. Will be passed as the third argument to `.createModel` method - `monaco.editor.createModel(..., ..., monaco.Uri.parse(defaultPath))` | | ||
| theme | enum: "light" \| "vs-dark" | "light" | The theme for the monaco. Available options "vs-dark" \| "light". Define new themes by `monaco.editor.defineTheme` | | ||
@@ -622,2 +689,3 @@ | line | number | | The line to jump on it | | ||
| overrideServices | object | {} | [IEditorOverrideServices ](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditoroverrideservices.html) | | ||
| saveViewState | boolean | true | Indicator whether to save the models' view states between model changes or not | | ||
| width | union: number \| string | "100%" | Width of the editor wrapper | | ||
@@ -624,0 +692,0 @@ | height | union: number \| string | "100%" | Height of the editor wrapper | |
185256
83
3542
721