use-monaco
Version:
[](https://npm.im/use-monaco)
130 lines • 5.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useRefWithEffect = exports.useMonaco = exports.useMonacoContext = exports.MonacoProvider = void 0;
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importDefault(require("react"));
const monaco_1 = require("../monaco");
const ayu_light_1 = tslib_1.__importDefault(require("../themes/monaco/ayu-light"));
const create_hook_context_1 = require("create-hook-context");
const plugins_1 = require("../plugins");
const [MonacoProvider, _, __, MonacoContext] = create_hook_context_1.createContext((config) => exports.useMonaco(config), undefined, 'Monaco');
exports.MonacoProvider = MonacoProvider;
function useMonacoContext() {
return react_1.default.useContext(MonacoContext);
}
exports.useMonacoContext = useMonacoContext;
let startedLoading = false;
const useMonaco = ({ themes, onThemeChange = () => { }, onLoad, defaultEditorOptions = {
automaticLayout: true,
minimap: {
enabled: false,
},
}, theme = 'ayu-light', plugins = [], languages = ['javascript', 'typescript', 'html', 'css', 'json'], ...loaderOptions } = {}) => {
const contextMonaco = useMonacoContext();
const [monaco, setMonaco] = react_1.default.useState(contextMonaco === undefined ? null : contextMonaco.monaco);
const [monacoRef, useMonacoEffect] = useRefWithEffect(monaco);
monacoRef.current = contextMonaco?.monaco || monaco;
react_1.default.useEffect(() => {
let onLoadDisposable;
async function initializeMonaco(monaco, plugins, languages) {
let pluginDisposables = await monaco.plugin.install(...plugins
.map((plug) => typeof plug === 'string' ||
(Array.isArray(plug) && plug.length === 2)
? plugins_1.pluginMap[Array.isArray(plug) ? plug[0] : plug]
? plugins_1.pluginMap[Array.isArray(plug) ? plug[0] : plug](Array.isArray(plug) ? plug[1] : {})
: undefined
: plug)
.filter(Boolean), ...languages
.map((plug) => typeof plug === 'string'
? monaco_1.basicLanguagePlugins[plug]
? monaco_1.basicLanguagePlugins[plug]
: undefined
: plug)
.filter(Boolean));
monaco.editor.defineTheme('ayu-light', ayu_light_1.default);
setMonaco(monaco);
let disposables = onLoad ? await onLoad(monaco) : null;
onLoadDisposable = monaco_1.asDisposable([pluginDisposables, disposables].filter(Boolean));
window.monaco = monaco;
}
// only loading once
if (contextMonaco === undefined && startedLoading) {
return;
// console.warn(
// `Detected trying to load monaco from multiple hooks. If you want to use monaco with multiple editors or from multiple components, its better to use a MonacoProvider that wraps your components and initializes monaco.`
// );
}
if (!monacoRef.current && window.monaco) {
initializeMonaco(window.monaco, plugins, languages);
return () => {
onLoadDisposable?.dispose?.();
};
}
if (contextMonaco === undefined && !monacoRef.current) {
startedLoading = true;
const cancelable = monaco_1.loadMonaco(loaderOptions ?? {});
cancelable
.then(async (monaco) => {
await initializeMonaco(monaco, plugins, languages);
return monaco;
})
.catch((error) => console.error('An error occurred during initialization of Monaco:', error));
return () => {
onLoadDisposable?.dispose?.();
cancelable.cancel?.();
};
}
}, []);
useMonacoEffect((monaco) => {
if (themes) {
monaco.editor.defineThemes(themes);
return () => { };
}
}, [themes]);
useMonacoEffect((monaco) => {
if (onThemeChange) {
const disposable = monaco.editor.onDidChangeTheme((theme) => {
onThemeChange(theme, monaco);
});
return () => {
disposable?.dispose?.();
};
}
}, [onThemeChange]);
useMonacoEffect((monaco) => {
if (typeof theme === 'function') {
const returnedTheme = theme();
if (returnedTheme.then) {
returnedTheme.then((result) => {
monaco.editor.setTheme(result);
});
}
else {
monaco.editor.setTheme(returnedTheme);
}
}
else if (theme) {
monaco.editor.setTheme(theme);
}
}, [theme]);
return {
monaco: monacoRef.current,
useMonacoEffect,
defaultEditorOptions,
isLoading: Boolean(monacoRef.current),
};
};
exports.useMonaco = useMonaco;
function useRefWithEffect(initialValue) {
const ref = react_1.default.useRef(initialValue);
const useRefEffect = (effect, deps) => {
react_1.default.useEffect(() => {
if (ref.current) {
return effect(ref.current);
}
}, [ref.current, ...deps]);
};
return [ref, useRefEffect];
}
exports.useRefWithEffect = useRefWithEffect;
//# sourceMappingURL=useMonaco.js.map