@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
237 lines (232 loc) • 10 kB
JavaScript
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