UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

237 lines (232 loc) 10 kB
import * as i0 from '@angular/core'; import { EventEmitter, forwardRef, ViewChild, Output, Input, Component, Directive } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import * as i1 from '@c8y/ngx-components'; import { LoadingComponent } from '@c8y/ngx-components'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NgIf } from '@angular/common'; function initializeMonacoEnvironment() { if (typeof window.MonacoEnvironment === 'undefined') { window.MonacoEnvironment = { getWorkerUrl: function (moduleId, label) { const base = MONACO_WORKERS_BASE; switch (label) { case 'json': return `${base}json.worker.bundle.js`; case 'css': return `${base}css.worker.bundle.js`; case 'html': return `${base}html.worker.bundle.js`; case 'typescript': case 'javascript': return `${base}ts.worker.bundle.js`; default: return `${base}editor.worker.bundle.js`; } } }; } } async function loadMonacoEditor() { initializeMonacoEnvironment(); const monaco = await import('monaco-editor'); return monaco.default || monaco; } /** * Editor component for displaying and editing code * * Based on the monaco editor (the same editor as in VS Code) * Supports syntax highlighting for various languages (default: JSON) * and can be extended with additional features like JSON schema validation */ class EditorComponent { constructor(zone, themeSwitcher) { this.zone = zone; this.themeSwitcher = themeSwitcher; /** * Options to pass to the monaco editor instance * Allows to e.g. set a different language. */ this.editorOptions = {}; /** * Emits the editor instance once it is initialized * Can be used to e.g. access the monaco instance and add a JSON schema for validation */ this.editorInit = new EventEmitter(); this._readOnly = false; this._currentValue = ''; this.themeChanges$ = this.themeSwitcher.currentlyAppliedTheme$.pipe(takeUntilDestroyed()); } writeValue(obj) { if (typeof obj === 'string') { this._currentValue = obj; } else { this._currentValue = JSON.stringify(obj, null, 2); } if (this.editor) { this.editor.setValue(this._currentValue); } } registerOnChange(fn) { this._onChanges = fn; this.register(); } registerOnTouched(fn) { this._onTouched = fn; this.register(); } setDisabledState(isDisabled) { this._readOnly = isDisabled; } async ngAfterViewInit() { this.monaco = await loadMonacoEditor(); this.editor = this.monaco.editor.create(this._editorContainer.nativeElement, Object.assign({ value: this._currentValue || '', language: 'json', automaticLayout: true, readOnly: this._readOnly }, this.editorOptions)); window.monacoEditor = this.editor; this.editorInit.emit(this.editor); this.register(); if (this.theme) { this.setTheme(this.theme); } else { this.themeChanges$.subscribe(theme => { this.setTheme(theme); }); } } ngOnChanges(changes) { if (changes.editorOptions && this.editor) { this.updateOptionsAndLanguage(changes); } } register() { if (!this.editor) { return; } if (this._onChanges) { const onChanges = this._onChanges; this.editor.onDidChangeModelContent(() => { this.zone.run(() => { const value = this.editor.getValue(); this._currentValue = value; onChanges(value); }); }); this._onChanges = undefined; } if (this._onTouched) { const onTouched = this._onTouched; this.editor.onDidChangeModelContent(() => { this.zone.run(() => { onTouched(); }); }); this._onTouched = undefined; } } ngOnDestroy() { this.editor?.getModel().dispose(); this.editor?.dispose(); } setTheme(theme) { const themeToSet = theme === 'dark' ? `vs-dark` : 'vs'; this.monaco.editor.setTheme(themeToSet); } updateOptionsAndLanguage(changes) { this.editor.updateOptions(this.editorOptions); if (this.editorOptions.language !== changes.editorOptions.previousValue.language) { const model = this.editor.getModel(); if (model) { this.monaco.editor.setModelLanguage(model, this.editorOptions.language); } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorComponent, deps: [{ token: i0.NgZone }, { token: i1.ThemeSwitcherService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: EditorComponent, isStandalone: true, selector: "c8y-editor", inputs: { editorOptions: "editorOptions", theme: "theme" }, outputs: { editorInit: "editorInit" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => EditorComponent), multi: true } ], viewQueries: [{ propertyName: "_editorContainer", first: true, predicate: ["editorContainer"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<c8y-loading *ngIf=\"!monaco\"></c8y-loading>\n<div class=\"editor-container\" style=\"height: 100%\" #editorContainer></div>\n", dependencies: [{ kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: EditorComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-editor', standalone: true, imports: [LoadingComponent, NgIf], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => EditorComponent), multi: true } ], template: "<c8y-loading *ngIf=\"!monaco\"></c8y-loading>\n<div class=\"editor-container\" style=\"height: 100%\" #editorContainer></div>\n" }] }], ctorParameters: () => [{ type: i0.NgZone }, { type: i1.ThemeSwitcherService }], propDecorators: { editorOptions: [{ type: Input }], theme: [{ type: Input }], editorInit: [{ type: Output }], _editorContainer: [{ type: ViewChild, args: ['editorContainer', { static: true }] }] } }); class MonacoEditorMarkerValidatorDirective { constructor(editorComponent, zone) { this.editorComponent = editorComponent; this.zone = zone; } ngOnDestroy() { this.editorInitSubscription?.unsubscribe(); } validate(_control) { if (!this.editorComponent.monaco || !this.editorComponent.editor) { return null; } const uri = this.editorComponent.editor.getModel().uri; const markers = this.editorComponent.monaco.editor.getModelMarkers({ resource: uri }); if (markers.length) { return markers; } return null; } registerOnValidatorChange(fn) { this.editorInitSubscription = this.editorComponent.editorInit.subscribe(editor => { editor.onDidChangeModelDecorations(() => { this.zone.run(() => { fn(); }); }); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MonacoEditorMarkerValidatorDirective, deps: [{ token: EditorComponent }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: MonacoEditorMarkerValidatorDirective, isStandalone: true, selector: "c8y-editor [monacoEditorMarkerValidator]", providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => MonacoEditorMarkerValidatorDirective), multi: true } ], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MonacoEditorMarkerValidatorDirective, decorators: [{ type: Directive, args: [{ selector: 'c8y-editor [monacoEditorMarkerValidator]', standalone: true, providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => MonacoEditorMarkerValidatorDirective), multi: true } ] }] }], ctorParameters: () => [{ type: EditorComponent }, { type: i0.NgZone }] }); /** * Generated bundle index. Do not edit. */ export { EditorComponent, MonacoEditorMarkerValidatorDirective, initializeMonacoEnvironment, loadMonacoEditor }; //# sourceMappingURL=c8y-ngx-components-editor.mjs.map