UNPKG

@acrodata/gui

Version:

JSON powered GUI for configurable panels.

635 lines (625 loc) 201 kB
import * as i0 from '@angular/core'; import { Pipe, Input, Directive, ChangeDetectionStrategy, ViewEncapsulation, Component, forwardRef, Injectable, InjectionToken, Optional, Inject, ViewChild, EventEmitter, Output, NgModule } from '@angular/core'; import { NgTemplateOutlet, CommonModule } from '@angular/common'; import * as i1 from '@angular/forms'; import { FormsModule, NG_VALUE_ACCESSOR, FormGroup, FormControl, FormArray, ReactiveFormsModule } from '@angular/forms'; import { MatHint, MatFormField, MatPrefix, MatSuffix, MatFormFieldModule } from '@angular/material/form-field'; import { MatInput, MatInputModule } from '@angular/material/input'; import * as i1$1 from '@angular/material/icon'; import { MatIcon, MatIconModule } from '@angular/material/icon'; import { MatSelect, MatSelectModule } from '@angular/material/select'; import { MatSlider, MatSliderThumb, MatSliderRangeThumb, MatSliderModule } from '@angular/material/slider'; import { MatSlideToggle, MatSlideToggleModule } from '@angular/material/slide-toggle'; import { MatButtonToggleGroup, MatButtonToggle, MatButtonToggleModule } from '@angular/material/button-toggle'; import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/button'; import { MatTabGroup, MatTab, MatTabLabel, MatTabContent, MatTabsModule } from '@angular/material/tabs'; import { MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelContent, MatExpansionModule } from '@angular/material/expansion'; import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip'; import { MtxColorpickerInput, MtxColorpicker, MtxColorpickerToggle, MtxColorpickerModule } from '@ng-matero/extensions/colorpicker'; import { MtxSelect, MtxSelectOptionTemplate, MtxSelectLabelTemplate, MtxSelectModule } from '@ng-matero/extensions/select'; import { Subject, map, Subscription, of, mergeWith } from 'rxjs'; import { CodeEditor } from '@acrodata/code-editor'; import { coerceCssPixelValue } from '@angular/cdk/coercion'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import * as i1$3 from '@acrodata/rnd-dialog'; import { RndDialogDragHandle } from '@acrodata/rnd-dialog'; import * as i1$2 from '@angular/cdk/dialog'; import { DIALOG_DATA } from '@angular/cdk/dialog'; import * as i2 from '@angular/platform-browser'; import { finalize } from 'rxjs/operators'; import * as i1$4 from '@angular/common/http'; import { HttpResponse } from '@angular/common/http'; import { GradientPicker } from '@acrodata/gradient-picker'; import { TinyColor } from '@ctrl/tinycolor'; import * as i3 from 'ngx-color/chrome'; import { ColorChromeModule } from 'ngx-color/chrome'; import { MatOption } from '@angular/material/core'; /** * Lightweight EJS template engine * * @param str template string * @param data data passed to the template * @returns * * ### Example * * ```ts * const people = ['geddy', 'neil', 'alex']; * const res = ejsTmpl('<%= people.join(", ") %>', {people: people}); * console.log(res); * // => 'geddy, neil, alex' * ``` * */ function ejsTmpl(str, data) { const fn = new Function('obj', 'var p=[],print=function(){p.push.apply(p,arguments);};' + // Introduce the data as local variables using with(){} 'with(obj){p.push("' + // Convert the template into pure JavaScript str .replace(/[\r\t\n]/g, ' ') .split('<%') .join('\t') .replace(/((^|%>)[^\t]*)'/g, '$1\r') .replace(/\t=(.*?)%>/g, '",$1,"') .split('\t') .join('");') .split('%>') .join('p.push("') .split('\r') .join('"') + '");}return p.join("");'); // Provide some basic currying to the user return data ? fn(data) : fn; } class GuiEjsPipe { transform(value, data = {}) { return ejsTmpl(value, data); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiEjsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: GuiEjsPipe, isStandalone: true, name: "ejs" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiEjsPipe, decorators: [{ type: Pipe, args: [{ name: 'ejs', standalone: true, }] }] }); class GuiFlexDirective { constructor(el) { this.el = el; this.flex = 100; } ngOnInit() { this.el.nativeElement.style.flex = `1 1 ${this.flex}%`; this.el.nativeElement.style.maxWidth = `${this.flex}%`; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiFlexDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GuiFlexDirective, isStandalone: true, selector: "[flex]", inputs: { flex: "flex" }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiFlexDirective, decorators: [{ type: Directive, args: [{ selector: '[flex]', standalone: true, }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { flex: [{ type: Input }] } }); function compareValues(a, b, operator) { switch (operator) { case '$eq': return a === b; case '$ne': return a !== b; case '$gt': return (a ?? 0) > (b ?? 0); case '$lt': return (a ?? 0) < (b ?? 0); case '$gte': return (a ?? 0) >= (b ?? 0); case '$lte': return (a ?? 0) <= (b ?? 0); case '$in': return Array.isArray(b) && b.includes(a); case '$nin': return Array.isArray(b) && !b.includes(a); default: return false; } } function getValueByPath(obj, path) { return path.split('.').reduce((acc, key) => { return acc?.['children']?.[key] ? acc['children'][key] : acc?.[key]; }, obj); } function getModelFromConfig(config = {}, model = {}) { for (const [key, fieldCfg] of Object.entries(config)) { if (model[key] != null) { continue; } if (fieldCfg.default != null) { model[key] = fieldCfg.default; } else { if (fieldCfg.type === 'group' || fieldCfg.type === 'inline' || fieldCfg.type === 'menu' || fieldCfg.type === 'menuItem') { model[key] = getModelFromConfig(fieldCfg.children, {}); } else if (fieldCfg.type === 'tabs') { model[key] = []; } else { model[key] = null; } } } return model; } class GuiFieldLabel { constructor() { this.config = {}; this.title = ''; this.styless = false; } ngOnChanges() { const { index, name, parentType, type } = this.config; this.title = index != null && !isNaN(index) ? ejsTmpl(name || '', { i: index }) : name; this.styless = (parentType === 'inline' && type !== 'inline') || type === 'group' || type === 'tabs'; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiFieldLabel, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GuiFieldLabel, isStandalone: true, selector: "gui-field-label", inputs: { config: "config", index: "index" }, host: { properties: { "class.gui-field-label": "!styless", "title": "title" } }, usesOnChanges: true, ngImport: i0, template: "@if (!config.description) {\n <span>{{ title }}</span>\n} @else {\n <span\n [class.gui-field-label-with-description]=\"config.description\"\n [matTooltip]=\"config.description\"\n matTooltipPosition=\"above\"\n matTooltipShowDelay=\"1000\"\n matTooltipClass=\"gui-field-label-tooltip\"\n >\n {{ title }}\n </span>\n}\n", styles: [".gui-field-label{display:inline-block;width:4rem;height:1.5rem;padding:0 .25rem;line-height:1.5rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gui-field-label-with-description{text-decoration:underline dotted;cursor:help}.gui-field-label-tooltip{white-space:pre-wrap}\n"], dependencies: [{ kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiFieldLabel, decorators: [{ type: Component, args: [{ selector: 'gui-field-label', host: { '[class.gui-field-label]': '!styless', '[title]': 'title', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [MatTooltip], template: "@if (!config.description) {\n <span>{{ title }}</span>\n} @else {\n <span\n [class.gui-field-label-with-description]=\"config.description\"\n [matTooltip]=\"config.description\"\n matTooltipPosition=\"above\"\n matTooltipShowDelay=\"1000\"\n matTooltipClass=\"gui-field-label-tooltip\"\n >\n {{ title }}\n </span>\n}\n", styles: [".gui-field-label{display:inline-block;width:4rem;height:1.5rem;padding:0 .25rem;line-height:1.5rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gui-field-label-with-description{text-decoration:underline dotted;cursor:help}.gui-field-label-tooltip{white-space:pre-wrap}\n"] }] }], propDecorators: { config: [{ type: Input }], index: [{ type: Input }] } }); class GuiIcon { constructor() { this.src = ''; } get isUrl() { return /^(https?:\/\/|\.?\/|data:)\w+/.test(this.src); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIcon, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GuiIcon, isStandalone: true, selector: "gui-icon", inputs: { src: "src" }, host: { classAttribute: "gui-icon" }, ngImport: i0, template: ` @if (isUrl) { <img [src]="src" alt="" /> } @else { <i [class]="src"></i> } `, isInline: true, styles: [".gui-icon{display:inline-flex}.gui-icon img,.gui-icon i{display:block;width:var(--mat-standard-button-toggle-height);height:var(--mat-standard-button-toggle-height);line-height:var(--mat-standard-button-toggle-height)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIcon, decorators: [{ type: Component, args: [{ selector: 'gui-icon', template: ` @if (isUrl) { <img [src]="src" alt="" /> } @else { <i [class]="src"></i> } `, host: { class: 'gui-icon', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [".gui-icon{display:inline-flex}.gui-icon img,.gui-icon i{display:block;width:var(--mat-standard-button-toggle-height);height:var(--mat-standard-button-toggle-height);line-height:var(--mat-standard-button-toggle-height)}\n"] }] }], propDecorators: { src: [{ type: Input }] } }); class GuiButtonToggle { constructor(cdr) { this.cdr = cdr; this.config = {}; this.disabled = false; this.value = ''; this.onChange = () => { }; this.onTouched = () => { }; } writeValue(value) { this.value = value; this.cdr.markForCheck(); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.cdr.markForCheck(); } onValueChange() { this.onChange(this.value); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiButtonToggle, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GuiButtonToggle, isStandalone: true, selector: "gui-button-toggle", inputs: { config: "config", disabled: "disabled" }, host: { classAttribute: "gui-field gui-button-toggle" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GuiButtonToggle), multi: true, }, ], ngImport: i0, template: "<mat-button-toggle-group\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [multiple]=\"config.multiple\"\n (change)=\"onValueChange()\"\n hideSingleSelectionIndicator\n hideMultipleSelectionIndicator\n>\n @for (opt of config.options; track $index) {\n <mat-button-toggle\n disableRipple\n [class.gui-icon-toggle]=\"config.useIcon\"\n [flex]=\"opt.col\"\n [value]=\"opt.value\"\n [disabled]=\"opt.disabled\"\n [title]=\"config.useIcon ? opt.label : ''\"\n >\n @if (config.useIcon) {\n <gui-icon [src]=\"opt.src!\" />\n } @else {\n {{ opt.label }}\n }\n </mat-button-toggle>\n }\n</mat-button-toggle-group>\n@if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n}\n", styles: [".gui-button-toggle{--mat-standard-button-toggle-shape: .25rem;--mat-standard-button-toggle-height: 1.5rem;--mat-standard-button-toggle-label-text-size: .75rem;--mat-standard-button-toggle-label-text-weight: 400;--mat-standard-button-toggle-label-text-line-height: var(--mat-standard-button-toggle-height)}.gui-button-toggle .mat-button-toggle-group{flex-wrap:wrap;border-width:0}.gui-button-toggle .mat-button-toggle-group-appearance-standard .mat-button-toggle-appearance-standard+.mat-button-toggle-appearance-standard{border-width:0}.gui-button-toggle .mat-button-toggle-appearance-standard{background-color:var(--mdc-filled-text-field-container-color)}.gui-icon-toggle.mat-button-toggle .mat-button-toggle-label-content{padding:0;line-height:normal}.gui-icon-toggle .mat-button-toggle-button{display:flex}.gui-icon-toggle.mat-button-toggle-checked img{opacity:.64}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: GuiFlexDirective, selector: "[flex]", inputs: ["flex"] }, { kind: "component", type: GuiIcon, selector: "gui-icon", inputs: ["src"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiButtonToggle, decorators: [{ type: Component, args: [{ selector: 'gui-button-toggle', host: { class: 'gui-field gui-button-toggle', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GuiButtonToggle), multi: true, }, ], standalone: true, imports: [ FormsModule, MatButtonToggleGroup, MatButtonToggle, MatHint, GuiFlexDirective, GuiIcon, GuiFieldLabel, ], template: "<mat-button-toggle-group\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [multiple]=\"config.multiple\"\n (change)=\"onValueChange()\"\n hideSingleSelectionIndicator\n hideMultipleSelectionIndicator\n>\n @for (opt of config.options; track $index) {\n <mat-button-toggle\n disableRipple\n [class.gui-icon-toggle]=\"config.useIcon\"\n [flex]=\"opt.col\"\n [value]=\"opt.value\"\n [disabled]=\"opt.disabled\"\n [title]=\"config.useIcon ? opt.label : ''\"\n >\n @if (config.useIcon) {\n <gui-icon [src]=\"opt.src!\" />\n } @else {\n {{ opt.label }}\n }\n </mat-button-toggle>\n }\n</mat-button-toggle-group>\n@if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n}\n", styles: [".gui-button-toggle{--mat-standard-button-toggle-shape: .25rem;--mat-standard-button-toggle-height: 1.5rem;--mat-standard-button-toggle-label-text-size: .75rem;--mat-standard-button-toggle-label-text-weight: 400;--mat-standard-button-toggle-label-text-line-height: var(--mat-standard-button-toggle-height)}.gui-button-toggle .mat-button-toggle-group{flex-wrap:wrap;border-width:0}.gui-button-toggle .mat-button-toggle-group-appearance-standard .mat-button-toggle-appearance-standard+.mat-button-toggle-appearance-standard{border-width:0}.gui-button-toggle .mat-button-toggle-appearance-standard{background-color:var(--mdc-filled-text-field-container-color)}.gui-icon-toggle.mat-button-toggle .mat-button-toggle-label-content{padding:0;line-height:normal}.gui-icon-toggle .mat-button-toggle-button{display:flex}.gui-icon-toggle.mat-button-toggle-checked img{opacity:.64}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { config: [{ type: Input }], disabled: [{ type: Input }] } }); class GuiIconButtonWrapper { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIconButtonWrapper, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GuiIconButtonWrapper, isStandalone: true, selector: "gui-icon-button-wrapper", host: { classAttribute: "gui-icon-button-wrapper" }, ngImport: i0, template: "<ng-content />\n", styles: [".gui-icon-button-wrapper{display:block;line-height:1}.gui-icon-button-wrapper .mat-mdc-icon-button{--mdc-icon-button-state-layer-size: 1.5rem;--mdc-icon-button-icon-size: .875rem;--mat-icon-button-touch-target-display: none;padding:0}.gui-icon-button-wrapper .mat-icon{display:inline-flex;justify-content:center;align-items:center;width:1.5rem;height:1.5rem}.gui-icon-button-wrapper .mat-icon svg{width:.875rem;height:.875rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIconButtonWrapper, decorators: [{ type: Component, args: [{ selector: 'gui-icon-button-wrapper', standalone: true, host: { class: 'gui-icon-button-wrapper', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n", styles: [".gui-icon-button-wrapper{display:block;line-height:1}.gui-icon-button-wrapper .mat-mdc-icon-button{--mdc-icon-button-state-layer-size: 1.5rem;--mdc-icon-button-icon-size: .875rem;--mat-icon-button-touch-target-display: none;padding:0}.gui-icon-button-wrapper .mat-icon{display:inline-flex;justify-content:center;align-items:center;width:1.5rem;height:1.5rem}.gui-icon-button-wrapper .mat-icon svg{width:.875rem;height:.875rem}\n"] }] }] }); class GuiCodeareaConfig { constructor() { this.changes = new Subject(); this.theme = 'light'; this.languages = []; this.extensions = []; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodeareaConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodeareaConfig, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodeareaConfig, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); const svgIcons = { horizontal: ` <svg viewBox="0 0 24 24"> <path d="M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2 0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1 6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z"></path> </svg> `, vertical: ` <svg viewBox="0 0 24 24"> <path d="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"></path> </svg> `, add: ` <svg viewBox="0 0 24 24"> <path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"></path> </svg> `, delete: ` <svg viewBox="0 0 24 24"> <path d="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z"></path> </svg> `, copy: ` <svg viewBox="0 0 24 24"> <path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path> </svg> `, link: ` <svg viewBox="0 0 24 24"> <path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></path> </svg> `, clear: ` <svg viewBox="0 0 24 24"> <path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"></path> </svg> `, file: ` <svg viewBox="0 0 24 24"> <path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z"></path> </svg> `, upload: ` <svg viewBox="0 0 24 24"> <path d="M2 12H4V17H20V12H22V17C22 18.11 21.11 19 20 19H4C2.9 19 2 18.11 2 17V12M12 2L6.46 7.46L7.88 8.88L11 5.75V15H13V5.75L16.13 8.88L17.55 7.45L12 2Z"></path> </svg> `, expand: ` <svg viewBox="0 0 24 24"> <path fill="currentColor" d="M10,21V19H6.41L10.91,14.5L9.5,13.09L5,17.59V14H3V21H10M14.5,10.91L19,6.41V10H21V3H14V5H17.59L13.09,9.5L14.5,10.91Z"></path> </svg>`, wrap: ` <svg viewBox="0 0 24 24"> <path fill="currentColor" d="M21,5H3V7H21V5M3,19H10V17H3V19M3,13H18C19,13 20,13.43 20,15C20,16.57 19,17 18,17H16V15L12,18L16,21V19H18C20.95,19 22,17.73 22,15C22,12.28 21,11 18,11H3V13Z"></path> </svg>`, solid: ` <svg viewBox="0 0 24 24"> <path fill="currentColor" fill-rule="evenodd" d="M9 9h6v6H9z"></path> <path fill="currentColor" fill-rule="evenodd" d="M8 7h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1M6 8a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2zm3 7V9h6v6zM8 8.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5z"></path> </svg>`, gradient: ` <svg viewBox="0 0 24 24"> <path fill="currentColor" fill-rule="evenodd" d="M8 7h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1M6 8a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2zm3.75.875a.875.875 0 1 1-1.75 0 .875.875 0 0 1 1.75 0m3.791.625a.625.625 0 1 0 0-1.25.625.625 0 0 0 0 1.25m-1.458.875a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m0 3.12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.458 2.245a.625.625 0 1 0 0-1.25.625.625 0 0 0 0 1.25m.625-3.865a.625.625 0 1 1-1.25 0 .625.625 0 0 1 1.25 0M8.875 15.99a.875.875 0 1 0 0-1.75.875.875 0 0 0 0 1.75m.875-4.115a.875.875 0 1 1-1.75 0 .875.875 0 0 1 1.75 0m5.75-1a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1m.5 2.623a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0"></path> </svg>`, image: ` <svg viewBox="0 0 24 24"> <path fill="currentColor" fill-rule="evenodd" d="M16 7H8a1 1 0 0 0-1 1v5.668l2.521-2.522a.5.5 0 0 1 .708 0l5.85 5.85A1 1 0 0 0 17 16V8a1 1 0 0 0-1-1M6 14.875V16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2zM8 17h6.668l-4.793-4.793L7 15.082V16a1 1 0 0 0 1 1m7-7a1 1 0 1 1-2 0 1 1 0 0 1 2 0m1 0a2 2 0 1 1-4 0 2 2 0 0 1 4 0"></path> </svg> `, }; /** Injection token that can be used to provide the default icons. */ const GUI_ICONS_CONFIG = new InjectionToken('gui-icons-config'); class GuiIconsRegistry { constructor(_iconRegistry, _sanitizer, _defaultIcons) { this._iconRegistry = _iconRegistry; this._sanitizer = _sanitizer; this._defaultIcons = _defaultIcons; } add(...iconNames) { const icons = Object.assign(svgIcons, this._defaultIcons); iconNames.forEach(k => { this._iconRegistry.addSvgIconLiteral(k, this._sanitizer.bypassSecurityTrustHtml(icons[k])); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIconsRegistry, deps: [{ token: i1$1.MatIconRegistry }, { token: i2.DomSanitizer }, { token: GUI_ICONS_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIconsRegistry, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiIconsRegistry, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1$1.MatIconRegistry }, { type: i2.DomSanitizer }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [GUI_ICONS_CONFIG] }] }] }); class GuiCodeareaDialog { get languages() { return this.codeareaCfg.languages; } get theme() { return this.codeareaCfg.theme; } get extensions() { return typeof this.codeareaCfg.extensions === 'function' ? this.codeareaCfg.extensions(this.data) : this.codeareaCfg.extensions; } constructor(dialogRef, data, cdr, destroyRef, codeareaCfg, iconsRegistry) { this.dialogRef = dialogRef; this.data = data; this.cdr = cdr; this.destroyRef = destroyRef; this.codeareaCfg = codeareaCfg; this.langDesc = this.codeareaCfg.languages.find(lang => this.data.language && lang.alias.includes(this.data.language.toLowerCase())); this.title = `${this.data.title || ''} (${this.langDesc?.name || 'Plain Text'})`; this.lineWrapping = false; iconsRegistry.add('wrap'); this.codeareaCfg.changes.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.cdr.markForCheck(); }); } toggleLineWrapping() { this.lineWrapping = !this.lineWrapping; } save() { this.dialogRef.close(this.data.value); } close() { this.dialogRef.close(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodeareaDialog, deps: [{ token: i1$2.DialogRef }, { token: DIALOG_DATA }, { token: i0.ChangeDetectorRef }, { token: i0.DestroyRef }, { token: GuiCodeareaConfig }, { token: GuiIconsRegistry }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GuiCodeareaDialog, isStandalone: true, selector: "gui-codearea-dialog", host: { classAttribute: "gui-codearea-dialog" }, ngImport: i0, template: "<div\n class=\"gui-codearea-dialog-header\"\n [class.dragging]=\"dragHandle.isDragging\"\n rndDialogDragHandle\n #dragHandle=\"rndDialogDragHandle\"\n>\n <span class=\"gui-codearea-dialog-title\" [title]=\"title\">{{ title }}</span>\n\n <span class=\"gui-codearea-dialog-spacer\"></span>\n\n <button mat-stroked-button (click)=\"close()\">Close</button>\n <button mat-flat-button (click)=\"save()\">Save</button>\n</div>\n\n<div class=\"gui-codearea-dialog-content\">\n <code-editor\n [(ngModel)]=\"data.value\"\n [disabled]=\"data.disabled || false\"\n [readonly]=\"data.readonly || false\"\n [language]=\"data.language || ''\"\n [languages]=\"languages\"\n [theme]=\"theme\"\n [extensions]=\"extensions\"\n [lineWrapping]=\"lineWrapping\"\n indentWithTab\n />\n\n <div class=\"gui-codearea-btns\">\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" (click)=\"toggleLineWrapping()\">\n <mat-icon svgIcon=\"wrap\" />\n </button>\n </gui-icon-button-wrapper>\n </div>\n</div>\n", styles: [".gui-codearea-dialog-panel{--rnd-dialog-container-color: var(--mdc-dialog-container-color)}.gui-codearea-dialog{--mdc-outlined-button-label-text-size: .75rem;--mdc-outlined-button-container-height: 1.5rem;--mat-outlined-button-horizontal-padding: .75rem;--mat-outlined-button-touch-target-display: none;--mdc-filled-button-label-text-size: .75rem;--mdc-filled-button-container-height: 1.5rem;--mat-filled-button-horizontal-padding: .75rem;--mat-filled-button-touch-target-display: none;display:flex;flex-direction:column;height:100%;overflow:hidden;border-radius:inherit;font-size:.75rem}.gui-codearea-dialog-header{display:flex;gap:.5rem;align-items:center;padding:.5rem;cursor:grab;border-bottom:1px solid rgba(0,0,0,.24);box-shadow:0 1px #ffffff3d}.gui-codearea-dialog-header.dragging{cursor:grabbing}.gui-codearea-dialog-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gui-codearea-dialog-spacer{flex:1}.gui-codearea-dialog-content{position:relative;flex:1;overflow:auto}.gui-codearea-dialog-content .code-editor{height:100%;overflow:auto;border:1px solid transparent}.gui-codearea-dialog-content:hover .gui-codearea-btns{display:block}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: RndDialogDragHandle, selector: "[rnd-dialog-drag-handle], [rndDialogDragHandle]", exportAs: ["rndDialogDragHandle"] }, { kind: "component", type: CodeEditor, selector: "code-editor", inputs: ["root", "autoFocus", "value", "disabled", "readonly", "theme", "placeholder", "indentWithTab", "indentUnit", "lineWrapping", "highlightWhitespace", "languages", "language", "setup", "extensions"], outputs: ["change", "focus", "blur"] }, { kind: "component", type: GuiIconButtonWrapper, selector: "gui-icon-button-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodeareaDialog, decorators: [{ type: Component, args: [{ selector: 'gui-codearea-dialog', standalone: true, imports: [ FormsModule, MatButton, MatIconButton, MatIcon, RndDialogDragHandle, CodeEditor, GuiIconButtonWrapper, ], host: { class: 'gui-codearea-dialog', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"gui-codearea-dialog-header\"\n [class.dragging]=\"dragHandle.isDragging\"\n rndDialogDragHandle\n #dragHandle=\"rndDialogDragHandle\"\n>\n <span class=\"gui-codearea-dialog-title\" [title]=\"title\">{{ title }}</span>\n\n <span class=\"gui-codearea-dialog-spacer\"></span>\n\n <button mat-stroked-button (click)=\"close()\">Close</button>\n <button mat-flat-button (click)=\"save()\">Save</button>\n</div>\n\n<div class=\"gui-codearea-dialog-content\">\n <code-editor\n [(ngModel)]=\"data.value\"\n [disabled]=\"data.disabled || false\"\n [readonly]=\"data.readonly || false\"\n [language]=\"data.language || ''\"\n [languages]=\"languages\"\n [theme]=\"theme\"\n [extensions]=\"extensions\"\n [lineWrapping]=\"lineWrapping\"\n indentWithTab\n />\n\n <div class=\"gui-codearea-btns\">\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" (click)=\"toggleLineWrapping()\">\n <mat-icon svgIcon=\"wrap\" />\n </button>\n </gui-icon-button-wrapper>\n </div>\n</div>\n", styles: [".gui-codearea-dialog-panel{--rnd-dialog-container-color: var(--mdc-dialog-container-color)}.gui-codearea-dialog{--mdc-outlined-button-label-text-size: .75rem;--mdc-outlined-button-container-height: 1.5rem;--mat-outlined-button-horizontal-padding: .75rem;--mat-outlined-button-touch-target-display: none;--mdc-filled-button-label-text-size: .75rem;--mdc-filled-button-container-height: 1.5rem;--mat-filled-button-horizontal-padding: .75rem;--mat-filled-button-touch-target-display: none;display:flex;flex-direction:column;height:100%;overflow:hidden;border-radius:inherit;font-size:.75rem}.gui-codearea-dialog-header{display:flex;gap:.5rem;align-items:center;padding:.5rem;cursor:grab;border-bottom:1px solid rgba(0,0,0,.24);box-shadow:0 1px #ffffff3d}.gui-codearea-dialog-header.dragging{cursor:grabbing}.gui-codearea-dialog-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gui-codearea-dialog-spacer{flex:1}.gui-codearea-dialog-content{position:relative;flex:1;overflow:auto}.gui-codearea-dialog-content .code-editor{height:100%;overflow:auto;border:1px solid transparent}.gui-codearea-dialog-content:hover .gui-codearea-btns{display:block}\n"] }] }], ctorParameters: () => [{ type: i1$2.DialogRef }, { type: undefined, decorators: [{ type: Inject, args: [DIALOG_DATA] }] }, { type: i0.ChangeDetectorRef }, { type: i0.DestroyRef }, { type: GuiCodeareaConfig }, { type: GuiIconsRegistry }] }); class GuiCodearea { get height() { return coerceCssPixelValue(this.config.height || this._height); } set height(value) { this._height = value; } get language() { return this.config.language || this._language; } set language(value) { this._language = value; } get languages() { return this.codeareaCfg.languages; } get theme() { return this.codeareaCfg.theme; } get dialogData() { return { value: this.value, disabled: this.disabled, language: this.language, }; } get extensions() { return typeof this.codeareaCfg.extensions === 'function' ? this.codeareaCfg.extensions(this.dialogData) : this.codeareaCfg.extensions; } constructor(rndDialog, cdr, destroyRef, codeareaCfg, iconsRegistry) { this.rndDialog = rndDialog; this.cdr = cdr; this.destroyRef = destroyRef; this.codeareaCfg = codeareaCfg; this.config = {}; this.disabled = false; this.setup = 'minimal'; this._height = 120; this._language = ''; this.value = ''; this.oldValue = ''; this.onChange = () => { }; this.onTouched = () => { }; iconsRegistry.add('expand'); this.codeareaCfg.changes.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.cdr.markForCheck(); }); } writeValue(value) { if (typeof value === 'string' || value == null) { this.value = value || ''; } else { this.value = value.toString(); } this.oldValue = this.value; this.cdr.markForCheck(); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.cdr.markForCheck(); } onValueChange() { if (this.value !== this.oldValue) { this.onChange(this.value); this.oldValue = this.value; } } onExpand() { const dialogRef = this.rndDialog.open(GuiCodeareaDialog, { panelClass: 'gui-codearea-dialog-panel', hasBackdrop: false, width: '600px', data: this.dialogData, }); dialogRef.closed.subscribe(newValue => { if (newValue) { this.value = newValue; this.cdr.detectChanges(); this.onValueChange(); } }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodearea, deps: [{ token: i1$3.RndDialog }, { token: i0.ChangeDetectorRef }, { token: i0.DestroyRef }, { token: GuiCodeareaConfig }, { token: GuiIconsRegistry }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GuiCodearea, isStandalone: true, selector: "gui-codearea", inputs: { config: "config", disabled: "disabled", setup: "setup", height: "height", language: "language" }, host: { classAttribute: "gui-field gui-codearea" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GuiCodearea), multi: true, }, ], ngImport: i0, template: "<code-editor\n [style.height]=\"height\"\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [language]=\"language\"\n [languages]=\"languages\"\n [theme]=\"theme\"\n [setup]=\"setup\"\n [extensions]=\"extensions\"\n (blur)=\"onValueChange()\"\n/>\n\n<div class=\"gui-codearea-btns\">\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" (click)=\"onExpand()\">\n <mat-icon svgIcon=\"expand\" />\n </button>\n </gui-icon-button-wrapper>\n</div>\n\n@if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n}\n", styles: [".gui-codearea{position:relative;overflow:auto;border:1px solid var(--mdc-outlined-text-field-outline-color);border-radius:var(--mdc-outlined-text-field-container-shape)}.gui-codearea .code-editor{width:100%;min-height:1.5rem;overflow:auto;resize:vertical}.gui-codearea:hover .gui-codearea-btns{display:block}.gui-codearea-btns{position:absolute;top:0;right:0;display:none;margin:2px}[dir=rtl] .gui-codearea-btns{left:0;right:auto}.gui-codearea-btns .gui-icon-button-wrapper .mat-mdc-icon-button,.gui-codearea-btns .gui-icon-button-wrapper .mat-icon{width:1.25rem;height:1.25rem}.gui-codearea-btns .mat-mdc-icon-button{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:.25rem}.gui-codearea-btns .mat-mdc-icon-button .mat-mdc-button-persistent-ripple{border-radius:inherit}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: CodeEditor, selector: "code-editor", inputs: ["root", "autoFocus", "value", "disabled", "readonly", "theme", "placeholder", "indentWithTab", "indentUnit", "lineWrapping", "highlightWhitespace", "languages", "language", "setup", "extensions"], outputs: ["change", "focus", "blur"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }, { kind: "component", type: GuiIconButtonWrapper, selector: "gui-icon-button-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCodearea, decorators: [{ type: Component, args: [{ selector: 'gui-codearea', host: { class: 'gui-field gui-codearea', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GuiCodearea), multi: true, }, ], standalone: true, imports: [ FormsModule, MatIcon, MatIconButton, MatHint, CodeEditor, GuiFieldLabel, GuiIconButtonWrapper, ], template: "<code-editor\n [style.height]=\"height\"\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [language]=\"language\"\n [languages]=\"languages\"\n [theme]=\"theme\"\n [setup]=\"setup\"\n [extensions]=\"extensions\"\n (blur)=\"onValueChange()\"\n/>\n\n<div class=\"gui-codearea-btns\">\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" (click)=\"onExpand()\">\n <mat-icon svgIcon=\"expand\" />\n </button>\n </gui-icon-button-wrapper>\n</div>\n\n@if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n}\n", styles: [".gui-codearea{position:relative;overflow:auto;border:1px solid var(--mdc-outlined-text-field-outline-color);border-radius:var(--mdc-outlined-text-field-container-shape)}.gui-codearea .code-editor{width:100%;min-height:1.5rem;overflow:auto;resize:vertical}.gui-codearea:hover .gui-codearea-btns{display:block}.gui-codearea-btns{position:absolute;top:0;right:0;display:none;margin:2px}[dir=rtl] .gui-codearea-btns{left:0;right:auto}.gui-codearea-btns .gui-icon-button-wrapper .mat-mdc-icon-button,.gui-codearea-btns .gui-icon-button-wrapper .mat-icon{width:1.25rem;height:1.25rem}.gui-codearea-btns .mat-mdc-icon-button{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:.25rem}.gui-codearea-btns .mat-mdc-icon-button .mat-mdc-button-persistent-ripple{border-radius:inherit}\n"] }] }], ctorParameters: () => [{ type: i1$3.RndDialog }, { type: i0.ChangeDetectorRef }, { type: i0.DestroyRef }, { type: GuiCodeareaConfig }, { type: GuiIconsRegistry }], propDecorators: { config: [{ type: Input }], disabled: [{ type: Input }], setup: [{ type: Input }], height: [{ type: Input }], language: [{ type: Input }] } }); class GuiCombobox { constructor(cdr) { this.cdr = cdr; this.config = {}; this.disabled = false; this.appendTo = 'body'; this.value = ''; this.onChange = () => { }; this.onTouched = () => { }; } ngAfterViewInit() { // Add additional class for ng-select's dropdown panel const { ngSelect } = this.mtxSelect; ngSelect.classes = (ngSelect.classes || '') + ' gui-combobox'; } writeValue(value) { this.value = value; this.cdr.markForCheck(); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this.cdr.markForCheck(); } onValueChange() { this.onChange(this.value); } addTagFn(label) { return { label, value: label }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiCombobox, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GuiCombobox, isStandalone: true, selector: "gui-combobox", inputs: { config: "config", disabled: "disabled", appendTo: "appendTo" }, host: { classAttribute: "gui-field gui-combobox" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GuiCombobox), multi: true, }, ], viewQueries: [{ propertyName: "mtxSelect", first: true, predicate: MtxSelect, descendants: true }], ngImport: i0, template: "<mat-form-field>\n @if (config.prefix) {\n <span matPrefix>{{ config.prefix }}</span>\n }\n <mtx-select\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [appendTo]=\"appendTo\"\n [items]=\"config.options || []\"\n bindLabel=\"label\"\n bindValue=\"value\"\n [multiple]=\"config.multiple || false\"\n [addTag]=\"addTagFn\"\n [closeOnSelect]=\"!config.multiple\"\n [deselectOnClick]=\"true\"\n (change)=\"onValueChange()\"\n >\n <ng-template ng-option-tmp let-item=\"item\">\n <div class=\"ng-option-label\" [style.font-family]=\"config.useFont ? item.value : ''\">\n {{ item.label }}\n </div>\n </ng-template>\n </mtx-select>\n @if (config.suffix) {\n <span matSuffix>{{ config.suffix }}</span>\n }\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n", styles: [".gui-combobox .ng-select{padding-left:.5rem;padding-right:.5rem;margin-left:-.5rem;margin-right:-.5rem}.gui-combobox .ng-select.ng-select-multiple .ng-value{flex-direction:row-reverse}.gui-combobox .ng-select .ng-value-icon{font-family:math;font-size:10px}.gui-combobox .ng-select .ng-clear-wrapper .ng-clear{font-family:math;font-size:12px}.gui-combobox .ng-select .ng-arrow{vertical-align:-1px}.gui-combobox.ng-dropdown-panel{padding:.5rem 0}.gui-combobox.ng-dropdown-panel .ng-dropdown-panel-items .ng-option{padding:0 .5rem;line-height:var(--mat-option-label-text-line-height)}.gui-combobox.ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{line-height:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: MtxSelect, selector: "mtx-select", inputs: ["addTag", "addTagText", "appearance",