import { DeesElement, property, html, customElement, type TemplateResult, css, cssManager, } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; import type * as monaco from 'monaco-editor'; declare global { interface HTMLElementTagNameMap { 'dees-editor': DeesEditor; } } @customElement('dees-editor') export class DeesEditor extends DeesElement { // DEMO public static demo = () => html` <dees-editor></dees-editor> `; // STATIC public static monacoDeferred: ReturnType<typeof domtools.plugins.smartpromise.defer>; // INSTANCE public editorDeferred = domtools.plugins.smartpromise.defer<monaco.editor.IStandaloneCodeEditor>(); public language = 'typescript'; @property({ type: String }) public content = "function hello() {\n\talert('Hello world!');\n}"; @property({ type: Object }) public contentSubject = new domtools.plugins.smartrx.rxjs.Subject<string>(); @property({ type: Boolean }) public wordWrap: monaco.editor.IStandaloneEditorConstructionOptions['wordWrap'] = 'off'; constructor() { super(); domtools.DomTools.setupDomTools(); } public static styles = [ cssManager.defaultStyles, css` :host { } * { box-sizing: border-box; } #container { position: absolute; height: 100%; width: 100%; } `, ]; public render(): TemplateResult { return html` <div class="mainbox"> <div id="container"></div> </div> `; } public async firstUpdated( _changedProperties: Map<string | number | symbol, unknown> ): Promise<void> { super.firstUpdated(_changedProperties); const container = this.shadowRoot.getElementById('container'); if (!DeesEditor.monacoDeferred) { DeesEditor.monacoDeferred = domtools.plugins.smartpromise.defer(); const scriptUrl = `https://cdn.jsdelivr.net/npm/monaco-editor/min/vs/loader.js`; const script = document.createElement('script'); script.src = scriptUrl; script.onload = () => { DeesEditor.monacoDeferred.resolve(); }; document.head.appendChild(script); } await DeesEditor.monacoDeferred.promise; (window as any).require.config({ paths: { vs: 'https://cdn.jsdelivr.net/npm/monaco-editor/min/vs' }, }); (window as any).require(['vs/editor/editor.main'], async () => { const editor = ((window as any).monaco.editor as typeof monaco.editor).create(container, { value: this.content, language: this.language, theme: 'vs-dark', useShadowDOM: true, fontSize: 16, automaticLayout: true, wordWrap: this.wordWrap }); this.editorDeferred.resolve(editor); }); const css = await ( await fetch('https://cdn.jsdelivr.net/npm/monaco-editor/min/vs/editor/editor.main.css') ).text(); const styleElement = document.createElement('style'); styleElement.textContent = css; this.shadowRoot.append(styleElement); // editor is setup let do the rest const editor = await this.editorDeferred.promise; editor.onDidChangeModelContent(async eventArg => { this.contentSubject.next(editor.getValue()); }); this.contentSubject.next(editor.getValue()); } }