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` `; // STATIC public static monacoDeferred: ReturnType; // INSTANCE public editorDeferred = domtools.plugins.smartpromise.defer(); public language = 'typescript'; @property({ type: String }) public content = "function hello() {\n\talert('Hello world!');\n}"; @property({ type: Object }) public contentSubject = new domtools.rxjs.Subject(); @property({ type: Boolean }) public wordWrap: monaco.editor.IStandaloneEditorConstructionOptions['wordWrap'] = 'off'; constructor() { super(); domtools.DomTools.setupDomTools(); } public static styles = [ domtools.elementBasic.staticStyles, css` :host { } * { box-sizing: border-box; } #container { position: absolute; height: 100%; width: 100%; } `, ]; public render(): TemplateResult { return html`
`; } public async firstUpdated( _changedProperties: Map ): Promise { 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()); } }