@acrodata/gui 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@ import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/but
14
14
  import { MatTabGroup, MatTab, MatTabLabel, MatTabContent, MatTabsModule } from '@angular/material/tabs';
15
15
  import { MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelContent, MatExpansionModule } from '@angular/material/expansion';
16
16
  import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
17
- import { MtxColorpickerInput, MtxColorpicker, MtxColorpickerToggle, MtxColorpickerModule } from '@ng-matero/extensions/colorpicker';
17
+ import { MtxColorpickerInput, MtxColorpicker, MtxColorpickerModule } from '@ng-matero/extensions/colorpicker';
18
18
  import { MtxSelect, MtxSelectOptionTemplate, MtxSelectLabelTemplate, MtxSelectModule } from '@ng-matero/extensions/select';
19
19
  import { Subject, map, finalize, Subscription, of, mergeWith } from 'rxjs';
20
20
  import { CodeEditor } from '@acrodata/code-editor';
@@ -405,11 +405,6 @@ class GuiCodeareaDialog {
405
405
  get theme() {
406
406
  return this.codeareaCfg.theme;
407
407
  }
408
- get extensions() {
409
- return typeof this.codeareaCfg.extensions === 'function'
410
- ? this.codeareaCfg.extensions(this.data)
411
- : this.codeareaCfg.extensions;
412
- }
413
408
  langDesc = this.codeareaCfg.languages.find(lang => this.data.language && lang.alias.includes(this.data.language.toLowerCase()));
414
409
  title = `${this.data.title || ''} (${this.langDesc?.name || 'Plain Text'})`;
415
410
  lineWrapping = false;
@@ -430,7 +425,7 @@ class GuiCodeareaDialog {
430
425
  this.dialogRef.close();
431
426
  }
432
427
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiCodeareaDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
433
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", 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 <gui-codearea-toolbar>\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 </gui-codearea-toolbar>\n</div>\n", styles: [".gui-codearea-dialog-panel{--rnd-dialog-container-color: var(--mat-dialog-container-color, var(--mat-sys-surface, white))}.gui-codearea-dialog{--mat-button-outlined-label-text-size: .75rem;--mat-button-outlined-container-height: 1.5rem;--mat-button-outlined-horizontal-padding: .75rem;--mat-button-outlined-touch-target-display: none;--mat-button-filled-label-text-size: .75rem;--mat-button-filled-container-height: 1.5rem;--mat-button-filled-horizontal-padding: .75rem;--mat-button-filled-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 .gui-codearea-toolbar{display:none}.gui-codearea-dialog-content:hover .gui-codearea-toolbar{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[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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" }, { kind: "component", type: GuiCodeareaToolbar, selector: "gui-codearea-toolbar" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
428
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", 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]=\"data.extensions || []\"\n [lineWrapping]=\"lineWrapping\"\n indentWithTab\n />\n\n <gui-codearea-toolbar>\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 </gui-codearea-toolbar>\n</div>\n", styles: [".gui-codearea-dialog-panel{--rnd-dialog-container-color: var(--mat-dialog-container-color, var(--mat-sys-surface, white))}.gui-codearea-dialog{--mat-button-outlined-label-text-size: .75rem;--mat-button-outlined-container-height: 1.5rem;--mat-button-outlined-horizontal-padding: .75rem;--mat-button-outlined-touch-target-display: none;--mat-button-filled-label-text-size: .75rem;--mat-button-filled-container-height: 1.5rem;--mat-button-filled-horizontal-padding: .75rem;--mat-button-filled-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 .gui-codearea-toolbar{display:none}.gui-codearea-dialog-content:hover .gui-codearea-toolbar{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[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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" }, { kind: "component", type: GuiCodeareaToolbar, selector: "gui-codearea-toolbar" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
434
429
  }
435
430
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiCodeareaDialog, decorators: [{
436
431
  type: Component,
@@ -445,7 +440,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
445
440
  GuiCodeareaToolbar,
446
441
  ], host: {
447
442
  class: 'gui-codearea-dialog',
448
- }, 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 <gui-codearea-toolbar>\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 </gui-codearea-toolbar>\n</div>\n", styles: [".gui-codearea-dialog-panel{--rnd-dialog-container-color: var(--mat-dialog-container-color, var(--mat-sys-surface, white))}.gui-codearea-dialog{--mat-button-outlined-label-text-size: .75rem;--mat-button-outlined-container-height: 1.5rem;--mat-button-outlined-horizontal-padding: .75rem;--mat-button-outlined-touch-target-display: none;--mat-button-filled-label-text-size: .75rem;--mat-button-filled-container-height: 1.5rem;--mat-button-filled-horizontal-padding: .75rem;--mat-button-filled-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 .gui-codearea-toolbar{display:none}.gui-codearea-dialog-content:hover .gui-codearea-toolbar{display:block}\n"] }]
443
+ }, 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]=\"data.extensions || []\"\n [lineWrapping]=\"lineWrapping\"\n indentWithTab\n />\n\n <gui-codearea-toolbar>\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 </gui-codearea-toolbar>\n</div>\n", styles: [".gui-codearea-dialog-panel{--rnd-dialog-container-color: var(--mat-dialog-container-color, var(--mat-sys-surface, white))}.gui-codearea-dialog{--mat-button-outlined-label-text-size: .75rem;--mat-button-outlined-container-height: 1.5rem;--mat-button-outlined-horizontal-padding: .75rem;--mat-button-outlined-touch-target-display: none;--mat-button-filled-label-text-size: .75rem;--mat-button-filled-container-height: 1.5rem;--mat-button-filled-horizontal-padding: .75rem;--mat-button-filled-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 .gui-codearea-toolbar{display:none}.gui-codearea-dialog-content:hover .gui-codearea-toolbar{display:block}\n"] }]
449
444
  }], ctorParameters: () => [] });
450
445
 
451
446
  class GuiCodearea {
@@ -470,6 +465,16 @@ class GuiCodearea {
470
465
  this._language = value;
471
466
  }
472
467
  _language = '';
468
+ get extensions() {
469
+ const globalExtensions = typeof this.codeareaCfg.extensions === 'function'
470
+ ? this.codeareaCfg.extensions({ value: this.value, language: this.language })
471
+ : this.codeareaCfg.extensions;
472
+ return [...globalExtensions, this._extensions];
473
+ }
474
+ set extensions(value) {
475
+ this._extensions = value;
476
+ }
477
+ _extensions = [];
473
478
  get languages() {
474
479
  return this.codeareaCfg.languages;
475
480
  }
@@ -481,13 +486,9 @@ class GuiCodearea {
481
486
  value: this.value,
482
487
  disabled: this.disabled,
483
488
  language: this.language,
489
+ extensions: this.extensions,
484
490
  };
485
491
  }
486
- get extensions() {
487
- return typeof this.codeareaCfg.extensions === 'function'
488
- ? this.codeareaCfg.extensions(this.dialogData)
489
- : this.codeareaCfg.extensions;
490
- }
491
492
  value = '';
492
493
  oldValue = '';
493
494
  lineWrapping = false;
@@ -546,7 +547,7 @@ class GuiCodearea {
546
547
  this.lineWrapping = !this.lineWrapping;
547
548
  }
548
549
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiCodearea, deps: [], target: i0.ɵɵFactoryTarget.Component });
549
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", 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: [
550
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GuiCodearea, isStandalone: true, selector: "gui-codearea", inputs: { config: "config", disabled: "disabled", setup: "setup", height: "height", language: "language", extensions: "extensions" }, host: { classAttribute: "gui-field gui-codearea" }, providers: [
550
551
  {
551
552
  provide: NG_VALUE_ACCESSOR,
552
553
  useExisting: forwardRef(() => GuiCodearea),
@@ -584,6 +585,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
584
585
  type: Input
585
586
  }], language: [{
586
587
  type: Input
588
+ }], extensions: [{
589
+ type: Input
587
590
  }] } });
588
591
 
589
592
  class GuiCombobox {
@@ -877,6 +880,7 @@ class GuiFillPicker {
877
880
  cdr = inject(ChangeDetectorRef);
878
881
  disabled = false;
879
882
  type = 'all';
883
+ valueChangeComplete = new EventEmitter();
880
884
  types = [
881
885
  { label: 'Solid', value: 'solid' },
882
886
  { label: 'Gradient', value: 'gradient' },
@@ -955,35 +959,41 @@ class GuiFillPicker {
955
959
  onTypeChange() {
956
960
  if (this.selectedType === 'solid') {
957
961
  this.onSolidChange();
962
+ this.onSolidChangeComplete();
958
963
  }
959
964
  else if (this.selectedType === 'gradient') {
960
965
  this.onGradientChange();
966
+ this.onGradientChangeComplete();
961
967
  }
962
968
  else if (this.selectedType === 'image') {
963
969
  this.onImageChange();
964
970
  }
965
971
  }
966
- onColorChange() {
967
- this.onSolidChange();
968
- }
969
972
  onSolidChange() {
970
973
  this.onChange(this.fillValue.solid);
971
974
  }
975
+ onSolidChangeComplete() {
976
+ this.valueChangeComplete.emit(this.fillValue.solid);
977
+ }
972
978
  onGradientChange() {
973
979
  this.onChange(this.fillValue.gradient);
974
980
  }
981
+ onGradientChangeComplete() {
982
+ this.valueChangeComplete.emit(this.fillValue.gradient);
983
+ }
975
984
  onImageChange() {
976
985
  const bgImg = `url("${this.fillValue.image}")`;
977
986
  this.onChange(bgImg);
987
+ this.valueChangeComplete.emit(bgImg);
978
988
  }
979
989
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiFillPicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
980
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GuiFillPicker, isStandalone: true, selector: "gui-fill-picker", inputs: { disabled: "disabled", type: "type" }, host: { classAttribute: "gui-fill-picker" }, providers: [
990
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GuiFillPicker, isStandalone: true, selector: "gui-fill-picker", inputs: { disabled: "disabled", type: "type" }, outputs: { valueChangeComplete: "valueChangeComplete" }, host: { classAttribute: "gui-fill-picker" }, providers: [
981
991
  {
982
992
  provide: NG_VALUE_ACCESSOR,
983
993
  useExisting: forwardRef(() => GuiFillPicker),
984
994
  multi: true,
985
995
  },
986
- ], usesOnChanges: true, ngImport: i0, template: "@if (type === 'all') {\n <div class=\"gui-fill-picker-header\">\n <mat-button-toggle-group\n [(ngModel)]=\"selectedType\"\n hideSingleSelectionIndicator\n (ngModelChange)=\"onTypeChange()\"\n >\n @for (t of types; track $index) {\n <mat-button-toggle [value]=\"t.value\" [title]=\"t.label\">\n <mat-icon [svgIcon]=\"t.value\" />\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n}\n\n<div class=\"gui-fill-picker-body\">\n @if (selectedType === 'solid') {\n <color-picker [(ngModel)]=\"fillValue.solid\" (ngModelChange)=\"onColorChange()\" />\n } @else if (selectedType === 'gradient') {\n <gradient-picker [(ngModel)]=\"fillValue.gradient\" (ngModelChange)=\"onGradientChange()\" />\n } @else if (selectedType === 'image') {\n <gui-file-uploader\n type=\"image\"\n [(ngModel)]=\"fillValue.image\"\n (ngModelChange)=\"onImageChange()\"\n />\n }\n</div>\n", styles: [".gui-fill-picker{display:block;width:15rem;border-radius:.5rem;background-color:var(--mat-expansion-container-background-color, var(--mat-sys-surface));color:var(--mat-expansion-container-text-color, var(--mat-sys-on-surface));box-shadow:inset 0 0 1px #ffffffa3,0 2px 4px #00000029,0 8px 16px #0000001f,0 0 1px #0000001f}.gui-fill-picker .color-picker{--cp-container-width: auto;--cp-container-padding: 0;--cp-container-shape: 0;--cp-container-elevation-shadow: none;--cp-container-background-color: transparent;--cp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface))}.gui-fill-picker .gradient-picker{--gp-container-width: auto;--gp-container-vertical-padding: 0;--gp-container-margin: -4px -12px;--gp-container-shape: 0;--gp-container-elevation-shadow: none;--gp-container-background-color: transparent;--gp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface));--gp-input-background-color: var(--mat-form-field-filled-container-color, var(--mat-sys-surface-variant));--gp-radio-button-selected-background-color: var(--mat-button-toggle-selected-state-background-color, var(--mat-sys-secondary-container));--gp-radio-button-selected-outline-color: var(--mat-button-toggle-divider-color, var(--mat-sys-outline))}.gui-fill-picker-header{padding:.375rem .375rem 0;line-height:1;--mat-button-toggle-shape: 0;--mat-button-toggle-height: 1}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard{gap:.25rem;border:none}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard .mat-button-toggle-appearance-standard+.mat-button-toggle-appearance-standard{border:none}.gui-fill-picker-header .mat-button-toggle-appearance-standard{border-radius:.25rem}.gui-fill-picker-header .mat-button-toggle-appearance-standard .mat-button-toggle-label-content{padding:0}.gui-fill-picker-body{padding:.75rem}\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: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ColorPicker, selector: "color-picker", inputs: ["format", "value", "hideAlpha", "disabled"], outputs: ["formatChange", "valueChange", "colorChange"] }, { kind: "component", type: GradientPicker, selector: "gradient-picker", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: GuiFileUploader, selector: "gui-file-uploader", inputs: ["config", "disabled", "type", "name", "accept"], outputs: ["fileChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
996
+ ], usesOnChanges: true, ngImport: i0, template: "@if (type === 'all') {\n <div class=\"gui-fill-picker-header\">\n <mat-button-toggle-group\n hideSingleSelectionIndicator\n [(ngModel)]=\"selectedType\"\n (ngModelChange)=\"onTypeChange()\"\n >\n @for (t of types; track $index) {\n <mat-button-toggle [value]=\"t.value\" [title]=\"t.label\">\n <mat-icon [svgIcon]=\"t.value\" />\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n}\n\n<div class=\"gui-fill-picker-body\">\n @if (selectedType === 'solid') {\n <color-picker\n [(ngModel)]=\"fillValue.solid\"\n (ngModelChange)=\"onSolidChange()\"\n (valueChangeComplete)=\"onSolidChangeComplete()\"\n />\n } @else if (selectedType === 'gradient') {\n <gradient-picker\n [(ngModel)]=\"fillValue.gradient\"\n (ngModelChange)=\"onGradientChange()\"\n (valueChangeComplete)=\"onGradientChangeComplete()\"\n />\n } @else if (selectedType === 'image') {\n <gui-file-uploader\n type=\"image\"\n [(ngModel)]=\"fillValue.image\"\n (ngModelChange)=\"onImageChange()\"\n />\n }\n</div>\n", styles: [".gui-fill-picker{display:block;width:15rem;border-radius:.5rem;background-color:var(--mat-expansion-container-background-color, var(--mat-sys-surface));color:var(--mat-expansion-container-text-color, var(--mat-sys-on-surface));box-shadow:inset 0 0 1px #ffffffa3,0 2px 4px #00000029,0 8px 16px #0000001f,0 0 1px #0000001f}.gui-fill-picker .color-picker{--cp-container-width: auto;--cp-container-padding: 0;--cp-container-shape: 0;--cp-container-elevation-shadow: none;--cp-container-background-color: transparent;--cp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface))}.gui-fill-picker .gradient-picker{--gp-container-width: auto;--gp-container-vertical-padding: 0;--gp-container-margin: -4px -12px;--gp-container-shape: 0;--gp-container-elevation-shadow: none;--gp-container-background-color: transparent;--gp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface));--gp-input-background-color: var(--mat-form-field-filled-container-color, var(--mat-sys-surface-variant));--gp-radio-button-selected-background-color: var(--mat-button-toggle-selected-state-background-color, var(--mat-sys-secondary-container));--gp-radio-button-selected-outline-color: var(--mat-button-toggle-divider-color, var(--mat-sys-outline))}.gui-fill-picker-header{padding:.375rem .375rem 0;line-height:1;--mat-button-toggle-shape: 0;--mat-button-toggle-height: 1}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard{gap:.25rem;border:none}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard .mat-button-toggle-appearance-standard+.mat-button-toggle-appearance-standard{border:none}.gui-fill-picker-header .mat-button-toggle-appearance-standard{border-radius:.25rem}.gui-fill-picker-header .mat-button-toggle-appearance-standard .mat-button-toggle-label-content{padding:0}.gui-fill-picker-body{padding:.75rem}\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: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ColorPicker, selector: "color-picker", inputs: ["format", "value", "hideAlpha", "disabled"], outputs: ["formatChange", "valueChange", "valueChangeComplete", "colorChange", "colorChangeComplete"] }, { kind: "component", type: GradientPicker, selector: "gradient-picker", inputs: ["value", "disabled"], outputs: ["valueChange", "valueChangeComplete"] }, { kind: "component", type: GuiFileUploader, selector: "gui-file-uploader", inputs: ["config", "disabled", "type", "name", "accept"], outputs: ["fileChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
987
997
  }
988
998
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiFillPicker, decorators: [{
989
999
  type: Component,
@@ -1003,15 +1013,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
1003
1013
  ColorPicker,
1004
1014
  GradientPicker,
1005
1015
  GuiFileUploader,
1006
- ], template: "@if (type === 'all') {\n <div class=\"gui-fill-picker-header\">\n <mat-button-toggle-group\n [(ngModel)]=\"selectedType\"\n hideSingleSelectionIndicator\n (ngModelChange)=\"onTypeChange()\"\n >\n @for (t of types; track $index) {\n <mat-button-toggle [value]=\"t.value\" [title]=\"t.label\">\n <mat-icon [svgIcon]=\"t.value\" />\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n}\n\n<div class=\"gui-fill-picker-body\">\n @if (selectedType === 'solid') {\n <color-picker [(ngModel)]=\"fillValue.solid\" (ngModelChange)=\"onColorChange()\" />\n } @else if (selectedType === 'gradient') {\n <gradient-picker [(ngModel)]=\"fillValue.gradient\" (ngModelChange)=\"onGradientChange()\" />\n } @else if (selectedType === 'image') {\n <gui-file-uploader\n type=\"image\"\n [(ngModel)]=\"fillValue.image\"\n (ngModelChange)=\"onImageChange()\"\n />\n }\n</div>\n", styles: [".gui-fill-picker{display:block;width:15rem;border-radius:.5rem;background-color:var(--mat-expansion-container-background-color, var(--mat-sys-surface));color:var(--mat-expansion-container-text-color, var(--mat-sys-on-surface));box-shadow:inset 0 0 1px #ffffffa3,0 2px 4px #00000029,0 8px 16px #0000001f,0 0 1px #0000001f}.gui-fill-picker .color-picker{--cp-container-width: auto;--cp-container-padding: 0;--cp-container-shape: 0;--cp-container-elevation-shadow: none;--cp-container-background-color: transparent;--cp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface))}.gui-fill-picker .gradient-picker{--gp-container-width: auto;--gp-container-vertical-padding: 0;--gp-container-margin: -4px -12px;--gp-container-shape: 0;--gp-container-elevation-shadow: none;--gp-container-background-color: transparent;--gp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface));--gp-input-background-color: var(--mat-form-field-filled-container-color, var(--mat-sys-surface-variant));--gp-radio-button-selected-background-color: var(--mat-button-toggle-selected-state-background-color, var(--mat-sys-secondary-container));--gp-radio-button-selected-outline-color: var(--mat-button-toggle-divider-color, var(--mat-sys-outline))}.gui-fill-picker-header{padding:.375rem .375rem 0;line-height:1;--mat-button-toggle-shape: 0;--mat-button-toggle-height: 1}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard{gap:.25rem;border:none}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard .mat-button-toggle-appearance-standard+.mat-button-toggle-appearance-standard{border:none}.gui-fill-picker-header .mat-button-toggle-appearance-standard{border-radius:.25rem}.gui-fill-picker-header .mat-button-toggle-appearance-standard .mat-button-toggle-label-content{padding:0}.gui-fill-picker-body{padding:.75rem}\n"] }]
1016
+ ], template: "@if (type === 'all') {\n <div class=\"gui-fill-picker-header\">\n <mat-button-toggle-group\n hideSingleSelectionIndicator\n [(ngModel)]=\"selectedType\"\n (ngModelChange)=\"onTypeChange()\"\n >\n @for (t of types; track $index) {\n <mat-button-toggle [value]=\"t.value\" [title]=\"t.label\">\n <mat-icon [svgIcon]=\"t.value\" />\n </mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n}\n\n<div class=\"gui-fill-picker-body\">\n @if (selectedType === 'solid') {\n <color-picker\n [(ngModel)]=\"fillValue.solid\"\n (ngModelChange)=\"onSolidChange()\"\n (valueChangeComplete)=\"onSolidChangeComplete()\"\n />\n } @else if (selectedType === 'gradient') {\n <gradient-picker\n [(ngModel)]=\"fillValue.gradient\"\n (ngModelChange)=\"onGradientChange()\"\n (valueChangeComplete)=\"onGradientChangeComplete()\"\n />\n } @else if (selectedType === 'image') {\n <gui-file-uploader\n type=\"image\"\n [(ngModel)]=\"fillValue.image\"\n (ngModelChange)=\"onImageChange()\"\n />\n }\n</div>\n", styles: [".gui-fill-picker{display:block;width:15rem;border-radius:.5rem;background-color:var(--mat-expansion-container-background-color, var(--mat-sys-surface));color:var(--mat-expansion-container-text-color, var(--mat-sys-on-surface));box-shadow:inset 0 0 1px #ffffffa3,0 2px 4px #00000029,0 8px 16px #0000001f,0 0 1px #0000001f}.gui-fill-picker .color-picker{--cp-container-width: auto;--cp-container-padding: 0;--cp-container-shape: 0;--cp-container-elevation-shadow: none;--cp-container-background-color: transparent;--cp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface))}.gui-fill-picker .gradient-picker{--gp-container-width: auto;--gp-container-vertical-padding: 0;--gp-container-margin: -4px -12px;--gp-container-shape: 0;--gp-container-elevation-shadow: none;--gp-container-background-color: transparent;--gp-container-text-color: var(--mat-form-field-filled-input-text-color, var(--mat-sys-on-surface));--gp-input-background-color: var(--mat-form-field-filled-container-color, var(--mat-sys-surface-variant));--gp-radio-button-selected-background-color: var(--mat-button-toggle-selected-state-background-color, var(--mat-sys-secondary-container));--gp-radio-button-selected-outline-color: var(--mat-button-toggle-divider-color, var(--mat-sys-outline))}.gui-fill-picker-header{padding:.375rem .375rem 0;line-height:1;--mat-button-toggle-shape: 0;--mat-button-toggle-height: 1}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard{gap:.25rem;border:none}.gui-fill-picker-header .mat-button-toggle-group-appearance-standard .mat-button-toggle-appearance-standard+.mat-button-toggle-appearance-standard{border:none}.gui-fill-picker-header .mat-button-toggle-appearance-standard{border-radius:.25rem}.gui-fill-picker-header .mat-button-toggle-appearance-standard .mat-button-toggle-label-content{padding:0}.gui-fill-picker-body{padding:.75rem}\n"] }]
1007
1017
  }], ctorParameters: () => [], propDecorators: { disabled: [{
1008
1018
  type: Input
1009
1019
  }], type: [{
1010
1020
  type: Input
1021
+ }], valueChangeComplete: [{
1022
+ type: Output
1011
1023
  }] } });
1012
1024
 
1013
1025
  class GuiFill {
1014
1026
  cdr = inject(ChangeDetectorRef);
1027
+ colorpicker;
1015
1028
  config = {};
1016
1029
  disabled = false;
1017
1030
  type = 'all';
@@ -1042,6 +1055,10 @@ class GuiFill {
1042
1055
  onValueChange() {
1043
1056
  this.onChange(this.value);
1044
1057
  }
1058
+ openColorPicker(e) {
1059
+ e.stopPropagation();
1060
+ this.colorpicker?.open();
1061
+ }
1045
1062
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiFill, deps: [], target: i0.ɵɵFactoryTarget.Component });
1046
1063
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GuiFill, isStandalone: true, selector: "gui-fill", inputs: { config: "config", disabled: "disabled", type: "type" }, host: { classAttribute: "gui-field gui-fill" }, providers: [
1047
1064
  {
@@ -1049,7 +1066,7 @@ class GuiFill {
1049
1066
  useExisting: forwardRef(() => GuiFill),
1050
1067
  multi: true,
1051
1068
  },
1052
- ], usesOnChanges: true, ngImport: i0, template: "<mat-form-field>\n <ng-container matPrefix>\n <span class=\"gui-color-block\">\n <span\n class=\"gui-color-block-bg\"\n [style.background]=\"value + ' center / contain no-repeat'\"\n ></span>\n </span>\n </ng-container>\n\n <input\n matInput\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [mtxColorpicker]=\"cp\"\n (colorChange)=\"onValueChange()\"\n />\n\n <mtx-colorpicker #cp [content]=\"customPickerContent\" />\n <gui-icon-button-wrapper matSuffix>\n <mtx-colorpicker-toggle [for]=\"cp\" />\n </gui-icon-button-wrapper>\n\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n\n<ng-template #customPickerContent>\n <gui-fill-picker [type]=\"type\" [(ngModel)]=\"cp.selected\" (ngModelChange)=\"cp.select($event)\" />\n</ng-template>\n", styles: [".gui-color-block{position:relative;display:inline-block;width:1.5rem;height:1.5rem;background-color:#fff;background-image:conic-gradient(transparent 25%,#ccc 25% 50%,transparent 50% 75%,#ccc 75%);background-size:.5rem .5rem}.gui-color-block-bg{display:inline-block;width:100%;height:100%}.gui-color-block-bg:after{display:inline-block;width:100%;height:100%;box-sizing:border-box;border:1px solid currentColor;border-top-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));opacity:.24;content:\"\"}[dir=rtl] .gui-color-block-bg:after{border-radius:0;border-top-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small))}.gui-fill .mat-mdc-icon-button{display:inline-flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MtxColorpickerInput, selector: "input[mtxColorpicker]", inputs: ["mtxColorpicker", "disabled", "value", "format"], outputs: ["colorChange", "colorInput"], exportAs: ["mtxColorpickerInput"] }, { kind: "component", type: MtxColorpicker, selector: "mtx-colorpicker", inputs: ["content", "disabled", "xPosition", "yPosition", "restoreFocus", "opened", "color", "format"], outputs: ["opened", "closed"], exportAs: ["mtxColorpicker"] }, { kind: "component", type: MtxColorpickerToggle, selector: "mtx-colorpicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["mtxColorpickerToggle"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }, { kind: "component", type: GuiIconButtonWrapper, selector: "gui-icon-button-wrapper" }, { kind: "component", type: GuiFillPicker, selector: "gui-fill-picker", inputs: ["disabled", "type"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1069
+ ], viewQueries: [{ propertyName: "colorpicker", first: true, predicate: MtxColorpicker, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mat-form-field>\n <ng-container matPrefix>\n <button class=\"gui-color-block\" (click)=\"openColorPicker($event)\">\n <span\n class=\"gui-color-block-bg\"\n [style.background]=\"value + ' center / contain no-repeat'\"\n ></span>\n </button>\n </ng-container>\n\n <input\n matInput\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [mtxColorpicker]=\"cp\"\n (colorChange)=\"onValueChange()\"\n />\n\n <mtx-colorpicker #cp [content]=\"customPickerContent\" />\n\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n\n<ng-template #customPickerContent>\n <gui-fill-picker [type]=\"type\" [(ngModel)]=\"value\" (valueChangeComplete)=\"cp.select($event)\" />\n</ng-template>\n", styles: [".gui-color-block{position:relative;display:inline-block;width:1.5rem;height:1.5rem;padding:0;border:none;background-color:#fff;background-image:conic-gradient(transparent 25%,#ccc 25% 50%,transparent 50% 75%,#ccc 75%);background-size:.5rem .5rem;outline:none;cursor:pointer}.gui-color-block:hover .gui-color-block-bg:after,.gui-color-block:focus .gui-color-block-bg:after{opacity:.4}.gui-color-block-bg{display:inline-block;width:100%;height:100%}.gui-color-block-bg:after{content:\"\";display:inline-block;width:100%;height:100%;box-sizing:border-box;border:1px solid #fff;border-top-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));mix-blend-mode:difference;opacity:.2}[dir=rtl] .gui-color-block-bg:after{border-radius:0;border-top-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small))}.gui-fill .mat-mdc-icon-button{display:inline-flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MtxColorpickerInput, selector: "input[mtxColorpicker]", inputs: ["mtxColorpicker", "disabled", "value", "format"], outputs: ["colorChange", "colorInput"], exportAs: ["mtxColorpickerInput"] }, { kind: "component", type: MtxColorpicker, selector: "mtx-colorpicker", inputs: ["content", "disabled", "xPosition", "yPosition", "restoreFocus", "opened", "color", "format"], outputs: ["opened", "closed"], exportAs: ["mtxColorpicker"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }, { kind: "component", type: GuiFillPicker, selector: "gui-fill-picker", inputs: ["disabled", "type"], outputs: ["valueChangeComplete"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1053
1070
  }
1054
1071
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiFill, decorators: [{
1055
1072
  type: Component,
@@ -1066,16 +1083,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
1066
1083
  MatFormField,
1067
1084
  MatPrefix,
1068
1085
  MatInput,
1069
- MatSuffix,
1070
1086
  MatHint,
1071
1087
  MtxColorpickerInput,
1072
1088
  MtxColorpicker,
1073
- MtxColorpickerToggle,
1074
1089
  GuiFieldLabel,
1075
- GuiIconButtonWrapper,
1076
1090
  GuiFillPicker,
1077
- ], template: "<mat-form-field>\n <ng-container matPrefix>\n <span class=\"gui-color-block\">\n <span\n class=\"gui-color-block-bg\"\n [style.background]=\"value + ' center / contain no-repeat'\"\n ></span>\n </span>\n </ng-container>\n\n <input\n matInput\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [mtxColorpicker]=\"cp\"\n (colorChange)=\"onValueChange()\"\n />\n\n <mtx-colorpicker #cp [content]=\"customPickerContent\" />\n <gui-icon-button-wrapper matSuffix>\n <mtx-colorpicker-toggle [for]=\"cp\" />\n </gui-icon-button-wrapper>\n\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n\n<ng-template #customPickerContent>\n <gui-fill-picker [type]=\"type\" [(ngModel)]=\"cp.selected\" (ngModelChange)=\"cp.select($event)\" />\n</ng-template>\n", styles: [".gui-color-block{position:relative;display:inline-block;width:1.5rem;height:1.5rem;background-color:#fff;background-image:conic-gradient(transparent 25%,#ccc 25% 50%,transparent 50% 75%,#ccc 75%);background-size:.5rem .5rem}.gui-color-block-bg{display:inline-block;width:100%;height:100%}.gui-color-block-bg:after{display:inline-block;width:100%;height:100%;box-sizing:border-box;border:1px solid currentColor;border-top-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));opacity:.24;content:\"\"}[dir=rtl] .gui-color-block-bg:after{border-radius:0;border-top-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small))}.gui-fill .mat-mdc-icon-button{display:inline-flex;justify-content:center;align-items:center}\n"] }]
1078
- }], propDecorators: { config: [{
1091
+ ], template: "<mat-form-field>\n <ng-container matPrefix>\n <button class=\"gui-color-block\" (click)=\"openColorPicker($event)\">\n <span\n class=\"gui-color-block-bg\"\n [style.background]=\"value + ' center / contain no-repeat'\"\n ></span>\n </button>\n </ng-container>\n\n <input\n matInput\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [mtxColorpicker]=\"cp\"\n (colorChange)=\"onValueChange()\"\n />\n\n <mtx-colorpicker #cp [content]=\"customPickerContent\" />\n\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n\n<ng-template #customPickerContent>\n <gui-fill-picker [type]=\"type\" [(ngModel)]=\"value\" (valueChangeComplete)=\"cp.select($event)\" />\n</ng-template>\n", styles: [".gui-color-block{position:relative;display:inline-block;width:1.5rem;height:1.5rem;padding:0;border:none;background-color:#fff;background-image:conic-gradient(transparent 25%,#ccc 25% 50%,transparent 50% 75%,#ccc 75%);background-size:.5rem .5rem;outline:none;cursor:pointer}.gui-color-block:hover .gui-color-block-bg:after,.gui-color-block:focus .gui-color-block-bg:after{opacity:.4}.gui-color-block-bg{display:inline-block;width:100%;height:100%}.gui-color-block-bg:after{content:\"\";display:inline-block;width:100%;height:100%;box-sizing:border-box;border:1px solid #fff;border-top-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));mix-blend-mode:difference;opacity:.2}[dir=rtl] .gui-color-block-bg:after{border-radius:0;border-top-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mat-form-field-filled-container-shape, var(--mat-sys-corner-extra-small))}.gui-fill .mat-mdc-icon-button{display:inline-flex;justify-content:center;align-items:center}\n"] }]
1092
+ }], propDecorators: { colorpicker: [{
1093
+ type: ViewChild,
1094
+ args: [MtxColorpicker]
1095
+ }], config: [{
1079
1096
  type: Input
1080
1097
  }], disabled: [{
1081
1098
  type: Input
@@ -1731,7 +1748,7 @@ class GuiForm {
1731
1748
  tabs.mode = mode;
1732
1749
  }
1733
1750
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1734
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GuiForm, isStandalone: true, selector: "gui-form", inputs: { form: "form", config: "config", model: "model" }, outputs: { modelChange: "modelChange" }, host: { properties: { "attr.id": "uid" }, classAttribute: "gui-form" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n @for (item of formFields; track item) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{$implicit: item, formGroup: form}\" />\n </div>\n }\n</form>\n\n<ng-template #controlType let-item let-parent=\"parent\" let-form=\"formGroup\">\n @if (item.show) {\n <ng-container [formGroup]=\"form\">\n @switch (item.type) {\n @case ('text') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-input-text [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('number') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-input-number [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('select') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-select [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('switch') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-switch [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('slider') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-slider [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('buttonToggle') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-button-toggle [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('fill') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-fill [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('file') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('image') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader type=\"image\" [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('video') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader type=\"video\" [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('audio') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader type=\"audio\" [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('imageSelect') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-image-select [formControlName]=\"item.key\" [config]=\"item\" [appendTo]=\"'#'+uid\" />\n </gui-field-group>\n }\n @case ('combobox') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-combobox [formControlName]=\"item.key\" [config]=\"item\" [appendTo]=\"'#'+uid\" />\n </gui-field-group>\n }\n @case ('textarea') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-textarea [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('codearea') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-codearea [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('hidden') {\n <input type=\"hidden\" [formControlName]=\"item.key\">\n }\n @case ('inline') {\n <gui-inline-group [config]=\"item\" [formGroupName]=\"item.key\">\n @for (child of item.children; track child) {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get(item.key)\n }\" />\n }\n </gui-inline-group>\n }\n @case ('group') {\n <mat-expansion-panel [formGroupName]=\"item.key\"\n [(expanded)]=\"item.expanded\" [disabled]=\"item.disabled\">\n <mat-expansion-panel-header>\n <gui-field-label [config]=\"item\" />\n </mat-expansion-panel-header>\n <!-- Lazy rendering -->\n <ng-template matExpansionPanelContent>\n @for (child of item.children; track child) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get(item.key)\n }\" />\n </div>\n }\n </ng-template>\n </mat-expansion-panel>\n }\n @case ('tabs') {\n <mat-expansion-panel [formArrayName]=\"item.key\"\n [(expanded)]=\"item.expanded\" [disabled]=\"item.disabled\">\n <mat-expansion-panel-header>\n <gui-field-label [config]=\"item\" />\n <!-- Show operation buttons when panel opened -->\n @if (item.expanded) {\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" [color]=\"item.mode!=='list'?'primary':''\"\n (click)=\"changeTabsMode($event, item, 'normal')\">\n <mat-icon svgIcon=\"horizontal\" />\n </button>\n <button mat-icon-button type=\"button\" [color]=\"item.mode==='list'?'primary':''\"\n (click)=\"changeTabsMode($event, item, 'list')\">\n <mat-icon svgIcon=\"vertical\" />\n </button>\n @if (item.template && (item.addable || item.addable===undefined)) {\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item, true)\">\n <mat-icon svgIcon=\"copy\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item)\">\n <mat-icon svgIcon=\"add\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"removeTab($event, form.get(item.key), item)\">\n <mat-icon svgIcon=\"delete\" />\n </button>\n }\n </gui-icon-button-wrapper>\n }\n </mat-expansion-panel-header>\n <!-- Lazy rendering -->\n <ng-template matExpansionPanelContent>\n @if (item.mode!=='list') {\n <!-- Horizontal mode -->\n <mat-tab-group class=\"gui-tabs\" disableRipple\n [mat-stretch-tabs]=\"false\" [(selectedIndex)]=\"item.selectedIndex\">\n @for (tab of item.children; track tab; let i = $index) {\n <mat-tab [disabled]=\"tab.disabled\">\n <ng-template mat-tab-label>\n <div>{{tab.name | ejs:{i} }}</div>\n </ng-template>\n <!-- FormControl & FormArray -->\n @if (!tab.children || tab.children.length===0 || tab.type==='tabs') {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: tab, parent: item, formGroup: form.get([item.key])\n }\" />\n }\n <!-- FormGroup -->\n @if (tab.children?.length>0 && tab.type!=='tabs') {\n @for (child of tab.children; track child) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get([item.key, i])\n }\" />\n </div>\n }\n }\n </mat-tab>\n }\n </mat-tab-group>\n } @else {\n <!-- Vertical mode -->\n <div class=\"gui-list\">\n @for (tab of item.children; track tab; let i = $index) {\n <div class=\"gui-list-item\"\n [class.gui-list-item-active]=\"item.selectedIndex===i\">\n <div class=\"gui-list-item-heading\">\n <button class=\"gui-list-item-title\" type=\"button\"\n (click)=\"item.selectedIndex=i\">{{tab.name | ejs:{i} }}</button>\n @if (item.template && (item.addable || item.addable===undefined)) {\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item, true, i)\">\n <mat-icon svgIcon=\"copy\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item, false, i)\">\n <mat-icon svgIcon=\"add\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"removeTab($event, form.get(item.key), item, i)\">\n <mat-icon svgIcon=\"delete\" />\n </button>\n </gui-icon-button-wrapper>\n }\n </div>\n <div class=\"gui-list-item-content\">\n <!-- FormControl & FormArray -->\n @if (!tab.children || tab.children.length===0 || tab.type==='tabs') {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: tab, parent: item, formGroup: form.get([item.key])\n }\" />\n }\n <!-- FormGroup -->\n @if (tab.children?.length>0 && tab.type!=='tabs') {\n @for (child of tab.children; track child) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get([item.key, i])\n }\" />\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n </ng-template>\n </mat-expansion-panel>\n }\n @case ('menu') {\n <mat-tab-group class=\"gui-menu\" [formGroupName]=\"item.key\" disableRipple>\n @for (menuChild of item.children; track menuChild) {\n <mat-tab [label]=\"menuChild.name\"\n [disabled]=\"menuChild.disabled\">\n <ng-template matTabContent>\n @if (menuChild.type==='menuItem') {\n <!-- Must wrap with div -->\n @for (controlItem of menuChild.children; track controlItem) {\n <div [formGroupName]=\"menuChild.key\">\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: controlItem, formGroup: form.get([item.key, menuChild.key])\n }\" />\n </div>\n }\n }\n <!-- Support for unlimited nesting -->\n @if (menuChild.type==='menu') {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: menuChild, formGroup: form.get(item.key)\n }\" />\n }\n </ng-template>\n </mat-tab>\n }\n </mat-tab-group>\n }\n }\n </ng-container>\n }\n</ng-template>\n", styles: [".gui-form{--mat-expansion-header-text-size: .75rem;--mat-expansion-header-collapsed-state-height: 2rem;--mat-expansion-header-expanded-state-height: 2rem;--mat-expansion-container-text-size: .75rem;--mat-expansion-container-shape: 0;position:relative;display:block;font-size:.75rem}.gui-form .mat-expansion-panel:not([class*=mat-elevation-z]){box-shadow:none}.gui-form .mat-expansion-panel-body{padding:0}.gui-form .mat-expansion-panel-header{padding:0 .75rem}.gui-form .mat-expansion-panel-header .mat-content{align-items:center;padding-right:.5rem}[dir=rtl] .gui-form .mat-expansion-panel-header .mat-content{padding-right:0;padding-left:.5rem}.gui-form .mat-expansion-panel-header .mat-content gui-field-label{flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gui-form .mat-expansion-indicator svg{width:1.5rem;height:1.5rem;margin:0 -.5rem}.gui-form .mat-expansion-indicator:after{vertical-align:.125rem}.gui-form .mat-mdc-tab-header{--mat-tab-label-text-size: .75rem;--mat-tab-container-height: 1.5rem}.gui-form .mat-mdc-tab-header-pagination{min-width:var(--mat-tab-container-height)}.gui-form .mat-mdc-tab{min-width:auto;padding:0 .75rem}.gui-list-item-heading{display:flex;align-items:center;position:relative;padding:0 .75rem;line-height:1.5rem;border-bottom:var(--mat-tab-divider-height, 1px) solid transparent}.gui-list-item-heading:before{position:absolute;left:0;width:.125rem;height:1rem;background-color:var(--mat-expansion-header-text-color, var(--mat-sys-on-surface));content:\"\"}[dir=rtl] .gui-list-item-heading:before{left:auto;right:0}.gui-list-item-title{display:flex;flex:1;padding:0;background-color:transparent;border:none;color:inherit;font-size:inherit;font-family:inherit;letter-spacing:inherit;line-height:inherit;cursor:pointer}.gui-list-item-active .gui-list-item-title{font-weight:700}.gui-menu .mat-mdc-tab-header{--mat-tab-active-indicator-shape: .25rem;padding:.25rem;background-color:var(--mat-form-field-filled-container-color, var(--mat-sys-surface-variant))}.gui-menu .mat-mdc-tab-header .mdc-tab__ripple:before{border-radius:var(--mat-tab-active-indicator-shape)}.gui-menu .mat-mdc-tab-labels{gap:.25rem}.gui-menu .mdc-tab-indicator .mdc-tab-indicator__content{height:100%;background-color:var(--mat-tab-active-indicator-color, var(--mat-sys-primary))}.gui-menu .mdc-tab-indicator--active .mdc-tab-indicator__content{opacity:.24}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "directive", type: MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "directive", type: MatTabContent, selector: "[matTabContent]" }, { kind: "component", type: GuiFieldGroup, selector: "gui-field-group", inputs: ["config"] }, { kind: "directive", type: GuiFlexDirective, selector: "[flex]", inputs: ["flex"] }, { kind: "component", type: GuiInputText, selector: "gui-input-text", inputs: ["config", "disabled"] }, { kind: "component", type: GuiInputNumber, selector: "gui-input-number", inputs: ["config", "disabled"] }, { kind: "component", type: GuiSelect, selector: "gui-select", inputs: ["config", "disabled"] }, { kind: "component", type: GuiSwitch, selector: "gui-switch", inputs: ["config", "disabled"] }, { kind: "component", type: GuiSlider, selector: "gui-slider", inputs: ["config", "disabled"] }, { kind: "component", type: GuiButtonToggle, selector: "gui-button-toggle", inputs: ["config", "disabled"] }, { kind: "component", type: GuiFill, selector: "gui-fill", inputs: ["config", "disabled", "type"] }, { kind: "component", type: GuiFileUploader, selector: "gui-file-uploader", inputs: ["config", "disabled", "type", "name", "accept"], outputs: ["fileChange"] }, { kind: "component", type: GuiImageSelect, selector: "gui-image-select", inputs: ["config", "disabled", "appendTo"] }, { kind: "component", type: GuiTextarea, selector: "gui-textarea", inputs: ["config", "disabled"] }, { kind: "component", type: GuiInlineGroup, selector: "gui-inline-group", inputs: ["config"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }, { kind: "component", type: GuiIconButtonWrapper, selector: "gui-icon-button-wrapper" }, { kind: "component", type: GuiCombobox, selector: "gui-combobox", inputs: ["config", "disabled", "appendTo"] }, { kind: "component", type: GuiCodearea, selector: "gui-codearea", inputs: ["config", "disabled", "setup", "height", "language"] }, { kind: "pipe", type: GuiEjsPipe, name: "ejs" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1751
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: GuiForm, isStandalone: true, selector: "gui-form", inputs: { form: "form", config: "config", model: "model" }, outputs: { modelChange: "modelChange" }, host: { properties: { "attr.id": "uid" }, classAttribute: "gui-form" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\">\n @for (item of formFields; track item) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{$implicit: item, formGroup: form}\" />\n </div>\n }\n</form>\n\n<ng-template #controlType let-item let-parent=\"parent\" let-form=\"formGroup\">\n @if (item.show) {\n <ng-container [formGroup]=\"form\">\n @switch (item.type) {\n @case ('text') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-input-text [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('number') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-input-number [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('select') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-select [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('switch') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-switch [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('slider') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-slider [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('buttonToggle') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-button-toggle [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('fill') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-fill [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('file') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('image') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader type=\"image\" [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('video') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader type=\"video\" [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('audio') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-file-uploader type=\"audio\" [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('imageSelect') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-image-select [formControlName]=\"item.key\" [config]=\"item\" [appendTo]=\"'#'+uid\" />\n </gui-field-group>\n }\n @case ('combobox') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-combobox [formControlName]=\"item.key\" [config]=\"item\" [appendTo]=\"'#'+uid\" />\n </gui-field-group>\n }\n @case ('textarea') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-textarea [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('codearea') {\n <gui-field-group [config]=\"item\" [flex]=\"item.col\">\n <gui-codearea [formControlName]=\"item.key\" [config]=\"item\" />\n </gui-field-group>\n }\n @case ('hidden') {\n <input type=\"hidden\" [formControlName]=\"item.key\">\n }\n @case ('inline') {\n <gui-inline-group [config]=\"item\" [formGroupName]=\"item.key\">\n @for (child of item.children; track child) {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get(item.key)\n }\" />\n }\n </gui-inline-group>\n }\n @case ('group') {\n <mat-expansion-panel [formGroupName]=\"item.key\"\n [(expanded)]=\"item.expanded\" [disabled]=\"item.disabled\">\n <mat-expansion-panel-header>\n <gui-field-label [config]=\"item\" />\n </mat-expansion-panel-header>\n <!-- Lazy rendering -->\n <ng-template matExpansionPanelContent>\n @for (child of item.children; track child) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get(item.key)\n }\" />\n </div>\n }\n </ng-template>\n </mat-expansion-panel>\n }\n @case ('tabs') {\n <mat-expansion-panel [formArrayName]=\"item.key\"\n [(expanded)]=\"item.expanded\" [disabled]=\"item.disabled\">\n <mat-expansion-panel-header>\n <gui-field-label [config]=\"item\" />\n <!-- Show operation buttons when panel opened -->\n @if (item.expanded) {\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" [color]=\"item.mode!=='list'?'primary':''\"\n (click)=\"changeTabsMode($event, item, 'normal')\">\n <mat-icon svgIcon=\"horizontal\" />\n </button>\n <button mat-icon-button type=\"button\" [color]=\"item.mode==='list'?'primary':''\"\n (click)=\"changeTabsMode($event, item, 'list')\">\n <mat-icon svgIcon=\"vertical\" />\n </button>\n @if (item.template && (item.addable || item.addable===undefined)) {\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item, true)\">\n <mat-icon svgIcon=\"copy\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item)\">\n <mat-icon svgIcon=\"add\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"removeTab($event, form.get(item.key), item)\">\n <mat-icon svgIcon=\"delete\" />\n </button>\n }\n </gui-icon-button-wrapper>\n }\n </mat-expansion-panel-header>\n <!-- Lazy rendering -->\n <ng-template matExpansionPanelContent>\n @if (item.mode!=='list') {\n <!-- Horizontal mode -->\n <mat-tab-group class=\"gui-tabs\" disableRipple\n [mat-stretch-tabs]=\"false\" [(selectedIndex)]=\"item.selectedIndex\">\n @for (tab of item.children; track tab; let i = $index) {\n <mat-tab [disabled]=\"tab.disabled\">\n <ng-template mat-tab-label>\n <div>{{tab.name | ejs:{i} }}</div>\n </ng-template>\n <!-- FormControl & FormArray -->\n @if (!tab.children || tab.children.length===0 || tab.type==='tabs') {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: tab, parent: item, formGroup: form.get([item.key])\n }\" />\n }\n <!-- FormGroup -->\n @if (tab.children?.length>0 && tab.type!=='tabs') {\n @for (child of tab.children; track child) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get([item.key, i])\n }\" />\n </div>\n }\n }\n </mat-tab>\n }\n </mat-tab-group>\n } @else {\n <!-- Vertical mode -->\n <div class=\"gui-list\">\n @for (tab of item.children; track tab; let i = $index) {\n <div class=\"gui-list-item\"\n [class.gui-list-item-active]=\"item.selectedIndex===i\">\n <div class=\"gui-list-item-heading\">\n <button class=\"gui-list-item-title\" type=\"button\"\n (click)=\"item.selectedIndex=i\">{{tab.name | ejs:{i} }}</button>\n @if (item.template && (item.addable || item.addable===undefined)) {\n <gui-icon-button-wrapper>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item, true, i)\">\n <mat-icon svgIcon=\"copy\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"addTab($event, form.get(item.key), item, false, i)\">\n <mat-icon svgIcon=\"add\" />\n </button>\n <button mat-icon-button type=\"button\" [disabled]=\"item.disabled\"\n (click)=\"removeTab($event, form.get(item.key), item, i)\">\n <mat-icon svgIcon=\"delete\" />\n </button>\n </gui-icon-button-wrapper>\n }\n </div>\n <div class=\"gui-list-item-content\">\n <!-- FormControl & FormArray -->\n @if (!tab.children || tab.children.length===0 || tab.type==='tabs') {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: tab, parent: item, formGroup: form.get([item.key])\n }\" />\n }\n <!-- FormGroup -->\n @if (tab.children?.length>0 && tab.type!=='tabs') {\n @for (child of tab.children; track child) {\n <div>\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: child, parent: item, formGroup: form.get([item.key, i])\n }\" />\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n </ng-template>\n </mat-expansion-panel>\n }\n @case ('menu') {\n <mat-tab-group class=\"gui-menu\" [formGroupName]=\"item.key\" disableRipple>\n @for (menuChild of item.children; track menuChild) {\n <mat-tab [label]=\"menuChild.name\"\n [disabled]=\"menuChild.disabled\">\n <ng-template matTabContent>\n @if (menuChild.type==='menuItem') {\n <!-- Must wrap with div -->\n @for (controlItem of menuChild.children; track controlItem) {\n <div [formGroupName]=\"menuChild.key\">\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: controlItem, formGroup: form.get([item.key, menuChild.key])\n }\" />\n </div>\n }\n }\n <!-- Support for unlimited nesting -->\n @if (menuChild.type==='menu') {\n <ng-template [ngTemplateOutlet]=\"controlType\"\n [ngTemplateOutletContext]=\"{\n $implicit: menuChild, formGroup: form.get(item.key)\n }\" />\n }\n </ng-template>\n </mat-tab>\n }\n </mat-tab-group>\n }\n }\n </ng-container>\n }\n</ng-template>\n", styles: [".gui-form{--mat-expansion-header-text-size: .75rem;--mat-expansion-header-collapsed-state-height: 2rem;--mat-expansion-header-expanded-state-height: 2rem;--mat-expansion-container-text-size: .75rem;--mat-expansion-container-shape: 0;position:relative;display:block;font-size:.75rem}.gui-form .mat-expansion-panel:not([class*=mat-elevation-z]){box-shadow:none}.gui-form .mat-expansion-panel-body{padding:0}.gui-form .mat-expansion-panel-header{padding:0 .75rem}.gui-form .mat-expansion-panel-header .mat-content{align-items:center;padding-right:.5rem}[dir=rtl] .gui-form .mat-expansion-panel-header .mat-content{padding-right:0;padding-left:.5rem}.gui-form .mat-expansion-panel-header .mat-content gui-field-label{flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.gui-form .mat-expansion-indicator svg{width:1.5rem;height:1.5rem;margin:0 -.5rem}.gui-form .mat-expansion-indicator:after{vertical-align:.125rem}.gui-form .mat-mdc-tab-header{--mat-tab-label-text-size: .75rem;--mat-tab-container-height: 1.5rem}.gui-form .mat-mdc-tab-header-pagination{min-width:var(--mat-tab-container-height)}.gui-form .mat-mdc-tab{min-width:auto;padding:0 .75rem}.gui-list-item-heading{display:flex;align-items:center;position:relative;padding:0 .75rem;line-height:1.5rem;border-bottom:var(--mat-tab-divider-height, 1px) solid transparent}.gui-list-item-heading:before{position:absolute;left:0;width:.125rem;height:1rem;background-color:var(--mat-expansion-header-text-color, var(--mat-sys-on-surface));content:\"\"}[dir=rtl] .gui-list-item-heading:before{left:auto;right:0}.gui-list-item-title{display:flex;flex:1;padding:0;background-color:transparent;border:none;color:inherit;font-size:inherit;font-family:inherit;letter-spacing:inherit;line-height:inherit;cursor:pointer}.gui-list-item-active .gui-list-item-title{font-weight:700}.gui-menu .mat-mdc-tab-header{--mat-tab-active-indicator-shape: .25rem;padding:.25rem;background-color:var(--mat-form-field-filled-container-color, var(--mat-sys-surface-variant))}.gui-menu .mat-mdc-tab-header .mdc-tab__ripple:before{border-radius:var(--mat-tab-active-indicator-shape)}.gui-menu .mat-mdc-tab-labels{gap:.25rem}.gui-menu .mdc-tab-indicator .mdc-tab-indicator__content{height:100%;background-color:var(--mat-tab-active-indicator-color, var(--mat-sys-primary))}.gui-menu .mdc-tab-indicator--active .mdc-tab-indicator__content{opacity:.24}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "directive", type: MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "directive", type: MatTabContent, selector: "[matTabContent]" }, { kind: "component", type: GuiFieldGroup, selector: "gui-field-group", inputs: ["config"] }, { kind: "directive", type: GuiFlexDirective, selector: "[flex]", inputs: ["flex"] }, { kind: "component", type: GuiInputText, selector: "gui-input-text", inputs: ["config", "disabled"] }, { kind: "component", type: GuiInputNumber, selector: "gui-input-number", inputs: ["config", "disabled"] }, { kind: "component", type: GuiSelect, selector: "gui-select", inputs: ["config", "disabled"] }, { kind: "component", type: GuiSwitch, selector: "gui-switch", inputs: ["config", "disabled"] }, { kind: "component", type: GuiSlider, selector: "gui-slider", inputs: ["config", "disabled"] }, { kind: "component", type: GuiButtonToggle, selector: "gui-button-toggle", inputs: ["config", "disabled"] }, { kind: "component", type: GuiFill, selector: "gui-fill", inputs: ["config", "disabled", "type"] }, { kind: "component", type: GuiFileUploader, selector: "gui-file-uploader", inputs: ["config", "disabled", "type", "name", "accept"], outputs: ["fileChange"] }, { kind: "component", type: GuiImageSelect, selector: "gui-image-select", inputs: ["config", "disabled", "appendTo"] }, { kind: "component", type: GuiTextarea, selector: "gui-textarea", inputs: ["config", "disabled"] }, { kind: "component", type: GuiInlineGroup, selector: "gui-inline-group", inputs: ["config"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }, { kind: "component", type: GuiIconButtonWrapper, selector: "gui-icon-button-wrapper" }, { kind: "component", type: GuiCombobox, selector: "gui-combobox", inputs: ["config", "disabled", "appendTo"] }, { kind: "component", type: GuiCodearea, selector: "gui-codearea", inputs: ["config", "disabled", "setup", "height", "language", "extensions"] }, { kind: "pipe", type: GuiEjsPipe, name: "ejs" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1735
1752
  }
1736
1753
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: GuiForm, decorators: [{
1737
1754
  type: Component,