umb-code-editor, async loading of monaco editor

This commit is contained in:
leekelleher
2024-07-18 17:56:15 +01:00
committed by Jacob Overgaard
parent 03a2368b49
commit 37a539e143
4 changed files with 72 additions and 24 deletions

View File

@@ -13,20 +13,6 @@ import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker.js?worker';
/* eslint-enable */
import { css, unsafeCSS } from '@umbraco-cms/backoffice/external/lit';
export const monacoEditorStyles = css`
${unsafeCSS(styles)}
`;
export const monacoJumpingCursorHack = css`
/* a hacky workaround this issue: https://github.com/microsoft/monaco-editor/issues/3217
should probably be removed when the issue is fixed */
.view-lines {
font-feature-settings: revert !important;
}
`;
const initializeWorkers = () => {
self.MonacoEnvironment = {
getWorker(workerId: string, label: string): Promise<Worker> | Worker {
@@ -50,3 +36,4 @@ const initializeWorkers = () => {
initializeWorkers();
export * as monaco from 'monaco-editor';
export { styles };

View File

@@ -0,0 +1,7 @@
export class UmbCodeEditorLoadedEvent extends Event {
public static readonly TYPE = 'loaded';
public constructor() {
super(UmbCodeEditorLoadedEvent.TYPE, { bubbles: true, composed: true, cancelable: false });
}
}

View File

@@ -144,6 +144,7 @@ export class UmbCodeEditorController {
this.#editor?.onDidChangeModel(() => {
this.#host.dispatchEvent(new UmbChangeEvent());
});
this.#editor?.onDidChangeCursorPosition((e) => {
this.#position = e.position;
this.#secondaryPositions = e.secondaryPositions;
@@ -192,6 +193,7 @@ export class UmbCodeEditorController {
readOnly: this.#host.readonly,
ariaLabel: this.#host.label,
});
this.#initiateEvents();
}
/**
@@ -376,3 +378,5 @@ export class UmbCodeEditorController {
});
}
}
export default UmbCodeEditorController;

View File

@@ -1,12 +1,24 @@
import { UmbCodeEditorController } from './code-editor.controller.js';
import type { UmbCodeEditorController } from './code-editor.controller.js';
import type { CodeEditorLanguage, CodeEditorSearchOptions, UmbCodeEditorHost } from './code-editor.model.js';
import { CodeEditorTheme } from './code-editor.model.js';
import { UmbCodeEditorLoadedEvent } from './code-editor-loaded.event.js';
import { UMB_THEME_CONTEXT } from '@umbraco-cms/backoffice/themes';
import { monacoEditorStyles, monacoJumpingCursorHack } from '@umbraco-cms/backoffice/external/monaco-editor';
import type { PropertyValues, Ref } from '@umbraco-cms/backoffice/external/lit';
import { css, html, createRef, ref, customElement, property } from '@umbraco-cms/backoffice/external/lit';
import {
createRef,
css,
customElement,
html,
property,
ref,
state,
unsafeCSS,
when,
} from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
const elementName = 'umb-code-editor';
/**
* A custom element that renders a code editor. Code editor is based on the Monaco Editor library.
* The element will listen to the theme context and update the theme accordingly.
@@ -21,7 +33,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
* @fires input - Fired when the value of the editor changes.
* @fires change - Fired when the entire model of editor is replaced.
*/
@customElement('umb-code-editor')
@customElement(elementName)
export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditorHost {
private containerRef: Ref<HTMLElement> = createRef();
@@ -88,8 +100,15 @@ export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditor
@property({ type: Boolean, attribute: 'readonly' })
readonly = false;
@state()
private _loading = true;
@state()
private _styles?: string;
constructor() {
super();
this.consumeContext(UMB_THEME_CONTEXT, (instance) => {
this.observe(
instance.theme,
@@ -101,8 +120,15 @@ export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditor
});
}
override firstUpdated() {
this.#editor = new UmbCodeEditorController(this);
override async firstUpdated() {
const { styles } = await import('@umbraco-cms/backoffice/external/monaco-editor');
this._styles = styles;
const controller = (await import('./code-editor.controller.js')).default;
this.#editor = new controller(this);
this._loading = false;
this.dispatchEvent(new UmbCodeEditorLoadedEvent());
}
protected override updated(_changedProperties: PropertyValues<this>): void {
@@ -149,16 +175,34 @@ export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditor
}
override render() {
return html` <div id="editor-container" ${ref(this.containerRef)}></div> `;
return html`
${this.#renderStyles()}
${when(this._loading, () => html`<div id="loader-container"><uui-loader></uui-loader></div>`)}
<div id="editor-container" ${ref(this.containerRef)}></div>
`;
}
#renderStyles() {
if (!this._styles) return;
return html`
<style>
${unsafeCSS(this._styles)}
</style>
`;
}
static override styles = [
monacoEditorStyles,
monacoJumpingCursorHack,
css`
:host {
display: block;
}
#loader-container {
display: grid;
place-items: center;
min-height: calc(100dvh - 260px);
}
#editor-container {
width: var(--editor-width);
height: var(--editor-height, 100%);
@@ -167,6 +211,12 @@ export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditor
--vscode-scrollbarSlider-background: var(--uui-color-disabled-contrast);
--vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
--vscode-scrollbarSlider-activeBackground: rgba(0, 0, 0, 0.6);
/* a hacky workaround this issue: https://github.com/microsoft/monaco-editor/issues/3217
should probably be removed when the issue is fixed */
.view-lines {
font-feature-settings: revert !important;
}
}
`,
];
@@ -174,6 +224,6 @@ export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditor
declare global {
interface HTMLElementTagNameMap {
'umb-code-editor': UmbCodeEditorElement;
[elementName]: UmbCodeEditorElement;
}
}