@xiriframework/xiri-ng 0.4.9 → 0.4.10

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.
@@ -1,6 +1,6 @@
1
1
  import { DomSanitizer } from '@angular/platform-browser';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, Pipe, input, computed, Directive, Injectable, ElementRef, ChangeDetectorRef, Input, Component, PLATFORM_ID, signal, effect, Service, output, numberAttribute, afterRenderEffect, untracked, booleanAttribute, viewChild, DestroyRef, forwardRef, Injector, afterNextRender, ViewEncapsulation, linkedSignal, ChangeDetectionStrategy, NgZone, makeEnvironmentProviders } from '@angular/core';
3
+ import { inject, Pipe, input, computed, Directive, Injectable, ElementRef, ChangeDetectorRef, Input, Component, PLATFORM_ID, signal, effect, Service, output, numberAttribute, afterRenderEffect, untracked, booleanAttribute, viewChild, DestroyRef, forwardRef, InjectionToken, Injector, afterNextRender, ViewEncapsulation, linkedSignal, ChangeDetectionStrategy, NgZone, makeEnvironmentProviders } from '@angular/core';
4
4
  import { DefaultUrlSerializer, RouterLink, Router, NavigationEnd } from '@angular/router';
5
5
  import { takeUntilDestroyed, toSignal, rxResource } from '@angular/core/rxjs-interop';
6
6
  import * as i1 from '@angular/forms';
@@ -2230,6 +2230,10 @@ class XiriSelectDirective {
2230
2230
  get filter() {
2231
2231
  return this._filteredValuesSubject.asObservable();
2232
2232
  }
2233
+ emit(list) {
2234
+ this._filtered = list;
2235
+ this._filteredValuesSubject.next(list);
2236
+ }
2233
2237
  constructor() {
2234
2238
  this.dataService = inject(XiriDataService);
2235
2239
  this.cdr = inject(ChangeDetectorRef);
@@ -2237,6 +2241,8 @@ class XiriSelectDirective {
2237
2241
  this._filterFormControl = new UntypedFormControl();
2238
2242
  /** list of _allValues filtered by search keyword */
2239
2243
  this._filteredValuesSubject = new ReplaySubject(1);
2244
+ /** what the panel currently shows — the basis for the select-all toggle */
2245
+ this._filtered = [];
2240
2246
  /** indicate search operation is in progress */
2241
2247
  this.searching = false;
2242
2248
  // @ViewChild('multiSelect', { static: true }) multiSelect: MatSelect;
@@ -2261,7 +2267,7 @@ class XiriSelectDirective {
2261
2267
  if (value === undefined)
2262
2268
  value = [];
2263
2269
  this._allValues = value;
2264
- this._filteredValuesSubject.next(this._allValues.slice());
2270
+ this.emit(this._allValues.slice());
2265
2271
  });
2266
2272
  }
2267
2273
  ngOnInit() {
@@ -2277,7 +2283,7 @@ class XiriSelectDirective {
2277
2283
  return of([]);
2278
2284
  }));
2279
2285
  }), tap((filteredList) => {
2280
- this._filteredValuesSubject.next(this._allValues.slice().concat(filteredList));
2286
+ this.emit(this._allValues.slice().concat(filteredList));
2281
2287
  }), tap(() => {
2282
2288
  this.searching = false;
2283
2289
  this.cdr.markForCheck();
@@ -2305,14 +2311,52 @@ class XiriSelectDirective {
2305
2311
  // get the search keyword
2306
2312
  let search = this._filterFormControl.value;
2307
2313
  if (!search) {
2308
- this._filteredValuesSubject.next(this._allValues.slice());
2314
+ this.emit(this._allValues.slice());
2309
2315
  return;
2310
2316
  }
2311
2317
  else {
2312
2318
  search = search.toLowerCase();
2313
2319
  }
2314
2320
  // filter the _allValues
2315
- this._filteredValuesSubject.next(this._allValues.filter(el => this.predicate()(search, el)));
2321
+ this.emit(this._allValues.filter(el => this.predicate()(search, el)));
2322
+ }
2323
+ // ---- select all / none (ngx-mat-select-search toggle-all checkbox) ----
2324
+ // Contract: "visible" = what the panel currently shows (_filtered). Disabled and group
2325
+ // options are never toggled; already selected disabled options survive a "none".
2326
+ selectableIds() {
2327
+ return new Set(this._filtered.filter(o => !o.disabled && !o.isGroup).map(o => o.id));
2328
+ }
2329
+ static ids(value) {
2330
+ return Array.isArray(value) ? value : [];
2331
+ }
2332
+ /** false when nothing is selectable — the checkbox is hidden then, otherwise MatCheckbox would stay checked after a no-op click */
2333
+ hasSelectable() {
2334
+ return this.selectableIds().size > 0;
2335
+ }
2336
+ allSelected(value) {
2337
+ const sel = this.selectableIds();
2338
+ const cur = new Set(XiriSelectDirective.ids(value));
2339
+ return sel.size > 0 && [...sel].every(id => cur.has(id));
2340
+ }
2341
+ someSelected(value) {
2342
+ const sel = this.selectableIds();
2343
+ const cur = new Set(XiriSelectDirective.ids(value));
2344
+ const hits = [...sel].filter(id => cur.has(id)).length;
2345
+ return hits > 0 && hits < sel.size;
2346
+ }
2347
+ toggleSelectAll(selectAll, control) {
2348
+ if (!control || control.disabled)
2349
+ return;
2350
+ const sel = this.selectableIds();
2351
+ const cur = XiriSelectDirective.ids(control.value);
2352
+ const next = selectAll
2353
+ ? cur.concat([...sel].filter(id => !cur.includes(id)))
2354
+ : cur.filter(id => !sel.has(id));
2355
+ if (next.length === cur.length && next.every((id, i) => id === cur[i]))
2356
+ return;
2357
+ control.setValue(next);
2358
+ control.markAsDirty();
2359
+ control.markAsTouched();
2316
2360
  }
2317
2361
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriSelectDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2318
2362
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.5", type: XiriSelectDirective, isStandalone: true, selector: "[xiriSelect]", inputs: { predicate: { classPropertyName: "predicate", publicName: "predicate", isSignal: true, isRequired: false, transformFunction: null }, compare: { classPropertyName: "compare", publicName: "compare", isSignal: true, isRequired: false, transformFunction: null }, serverSideSearch: { classPropertyName: "serverSideSearch", publicName: "serverSideSearch", isSignal: true, isRequired: false, transformFunction: null }, serverUrl: { classPropertyName: "serverUrl", publicName: "serverUrl", isSignal: true, isRequired: false, transformFunction: null }, serverParams: { classPropertyName: "serverParams", publicName: "serverParams", isSignal: true, isRequired: false, transformFunction: null }, values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["xiriSelect"], ngImport: i0 }); }
@@ -3059,7 +3103,7 @@ class XiriFormFieldsComponent {
3059
3103
  }
3060
3104
  }
3061
3105
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriFormFieldsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3062
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: XiriFormFieldsComponent, isStandalone: true, selector: "xiri-form-fields", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, check: { classPropertyName: "check", publicName: "check", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formChange: "formChange" }, ngImport: i0, template: "@if (reloading()) {\n\t<mat-progress-bar class=\"reloadbar\" mode=\"indeterminate\"></mat-progress-bar>\n}\n<form class=\"xrow dynamic-form\" [formGroup]=\"formGroup\" [class]=\"display()\">\n\t@for (field of displayFields(); track field.id) {\n\t\t@if (isFieldVisible(field)) {\n\t\t@switch (field.type) {\n\t\t\t@case ('text') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.subtype || 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('number') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [autocomplete]=\"field.name || field.id\"\n\t\t\t\t\t [lang]=\"field.locale || ''\"\n\t\t\t\t\t [type]=\"field.type\"\n\t\t\t\t\t [attr.min]=\"field.min\"\n\t\t\t\t\t [attr.max]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('password') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.pwdhide ? 'password' : 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t<button mat-icon-button matSuffix class=\"form-field-button\" (click)=\"field.pwdhide = !field.pwdhide\" [attr.aria-label]=\"'Hide password'\"\n\t\t\t\t\t [attr.aria-pressed]=\"field.pwdhide\">\n\t\t\t\t\t\t<mat-icon>{{ field.pwdhide ? 'visibility_off' : 'visibility' }}</mat-icon>\n\t\t\t\t\t</button>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('select') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t@if (field.search === false) {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t<mat-option>\n\t\t\t\t\t\t\t\t<ngx-mat-select-search [formControl]=\"xiriSelect.formControl\" xiriSelect #xiriSelect=\"xiriSelect\"\n\t\t\t\t\t\t\t\t [values]=\"field.list || []\" [searching]=\"xiriSelect.searching\"\n\t\t\t\t\t\t\t\t [serverSideSearch]=\"!!field.serverSideSearch\" [serverUrl]=\"field.url || ''\"\n\t\t\t\t\t\t\t\t [serverParams]=\"field.params || {}\"></ngx-mat-select-search>\n\t\t\t\t\t\t\t</mat-option>\n\t\t\t\t\t\t\t@for (x of xiriSelect.filter | async; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('treeselect') {\n\t\t\t\t<div class=\"treeselect\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-treeselect [field]=\"field\" [formControlName]=\"field.id\"\n\t\t\t\t\t [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\"></xiri-treeselect>\n\t\t\t\t\t<div class=\"xhint\" aria-live=\"polite\" [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\">\n\t\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.touched && formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('date') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"date\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date [field]=\"field\" [formControlName]=\"field.id\"></xiri-date>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('yearmonth') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"yearmonth\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-yearmonth [field]=\"field\" [formControlName]=\"field.id\"></xiri-yearmonth>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('daterange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"daterange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('datetimerange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"datetimerange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-time-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-time-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('bool') {\n\t\t\t\t<div class=\"bool\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-checkbox [formControlName]=\"field.id\">{{ field.name }}</mat-checkbox>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('radio') {\n\t\t\t\t<div class=\"radio\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<span class=\"radio-label\" [id]=\"field.id + '-label'\">{{ field.name }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<mat-radio-group\n\t\t\t\t\t\t[formControlName]=\"field.id\"\n\t\t\t\t\t\t[attr.aria-labelledby]=\"field.name ? field.id + '-label' : null\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t<mat-radio-button [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-radio-button>\n\t\t\t\t\t\t}\n\t\t\t\t\t</mat-radio-group>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('volume') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-volume [field]=\"field\" [formControlName]=\"field.id\"></xiri-volume>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('timelimit') {\n\t\t\t\t<div [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-timelimit matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [texts]=\"field.texts || {}\"></xiri-timelimit>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('textarea') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<textarea matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [rows]=\"field.rows || 5\"></textarea>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('file') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-file [field]=\"field\" [formControlName]=\"field.id\"></xiri-file>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('info') {\n\t\t\t\t<div class=\"info\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t}\n\t\t\t@case ('header') {\n\t\t\t\t@if (field.collapsible) {\n\t\t\t\t\t<div class=\"header collapsible\" [class]=\"field.class\" role=\"button\" tabindex=\"0\"\n\t\t\t\t\t [attr.aria-expanded]=\"!isSectionCollapsed(field.id)\"\n\t\t\t\t\t (click)=\"toggleSection(field)\" (keydown.enter)=\"toggleSection(field)\" (keydown.space)=\"toggleSection(field); $event.preventDefault()\">\n\t\t\t\t\t\t<mat-icon class=\"collapse-icon\" [class.collapsed]=\"isSectionCollapsed(field.id)\">expand_more</mat-icon>\n\t\t\t\t\t\t{{ field.value }}\n\t\t\t\t\t</div>\n\t\t\t\t} @else {\n\t\t\t\t\t<div class=\"header\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t\t}\n\t\t\t}\n\t\t\t@case ('divider') {\n\t\t\t\t<div class=\"divider\" [class]=\"field.class\">\n\t\t\t\t\t@if (field.value) {\n\t\t\t\t\t\t<span class=\"divider-text\">{{ field.value }}</span>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('html') {\n\t\t\t\t<div class=\"html\" [class]=\"field.class\" [innerHtml]=\"$any(field.value) | safeHtml\"></div>\n\t\t\t}\n\t\t\t@case ('question') {\n\t\t\t\t<div class=\"xcol question\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t<mat-icon [class]=\"field.iconColor || 'warn'\" inline=\"true\">{{ field.icon }}</mat-icon>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('waiting') {\n\t\t\t\t<div class=\"xcol waiting\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t@if (!field.done) {\n\t\t\t\t\t\t\t<mat-spinner diameter=\"40\"></mat-spinner>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.done) {\n\t\t\t\t\t\t\t<mat-icon inline=\"true\">done</mat-icon>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('chips') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-chips [field]=\"field\" [formControlName]=\"field.id\"></xiri-chips>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@default {\n\t\t\t\t<div>default: {{ field.type }}</div>\n\t\t\t}\n\t\t}\n\t\t}\n\t}\n</form>\n", styles: [":host{position:relative}.reloadbar{position:absolute;top:0;left:0;right:0;z-index:1}.dynamic-form{grid-row-gap:7px}.dynamic-form mat-form-field mat-icon{--mat-icon-color: var(--xiri-formfield-icon-color)}.dynamic-form.line{grid-row-gap:5px}.dynamic-form.small{grid-row-gap:2px}.dynamic-form textarea{white-space:pre}.dynamic-form .xhint{display:flex;min-height:20px;margin-top:4px}.dynamic-form .xhint mat-hint{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint mat-hint.mat-mdc-form-field-hint-end{flex:1;text-align:right}.dynamic-form .xhint mat-error{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint.error mat-hint{display:none}.dynamic-form .date{align-self:start;min-width:min(9.5rem,100%)}.dynamic-form .date.datetime{min-width:min(14.5rem,100%)}.dynamic-form .daterange{align-self:start;min-width:min(14.5rem,100%)}.dynamic-form .datetimerange{align-self:start;min-width:min(18.5rem,100%)}.dynamic-form .bool{display:flex;flex-direction:column}.dynamic-form .bool mat-hint{font-size:var(--xiri-font-size-helper);margin-top:-8px;padding-left:44px}.dynamic-form .radio{display:flex;flex-direction:column;gap:var(--xiri-spacing-xs)}.dynamic-form .radio .radio-label{font-size:var(--xiri-font-size-label)}.dynamic-form .radio mat-radio-group{display:flex;flex-wrap:wrap;gap:var(--xiri-spacing-xs) var(--xiri-spacing-md)}.dynamic-form .radio mat-hint{font-size:var(--xiri-font-size-helper)}.dynamic-form .info{padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header{font-size:var(--xiri-font-size-title);padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header.collapsible{cursor:pointer;display:flex;align-items:center;gap:.25rem;-webkit-user-select:none;user-select:none;border-radius:var(--xiri-radius-xs);padding:.5rem .25rem;margin:.25rem 0}.dynamic-form .header.collapsible:hover{background:color-mix(in srgb,var(--primary, #2892D9) 8%,transparent)}.dynamic-form .header.collapsible .collapse-icon{transition:transform var(--xiri-duration-fast) var(--xiri-easing-standard)}.dynamic-form .header.collapsible .collapse-icon.collapsed{transform:rotate(-90deg)}.dynamic-form .divider{width:100%;display:flex;align-items:center;padding:.5rem 0;margin:.25rem 0}.dynamic-form .divider:before,.dynamic-form .divider:after{content:\"\";flex:1;height:1px;background:var(--outline-variant, var(--mat-sys-outline-variant, rgba(0, 0, 0, .12)))}.dynamic-form .divider .divider-text{padding:0 1rem;font-size:var(--xiri-font-size-helper);color:var(--on-surface-variant, var(--mat-sys-on-surface-variant, rgba(0, 0, 0, .6)));white-space:nowrap}.dynamic-form .question,.dynamic-form .waiting{display:flex}.dynamic-form .question .left,.dynamic-form .waiting .left{font-size:var(--xiri-font-size-display);padding-right:1rem}.dynamic-form .question{align-items:center}.dynamic-form .question .left mat-icon{height:auto;width:auto;line-height:1;overflow:visible}.dynamic-form .form-field-button{margin-left:12px;margin-right:12px}.mat-mdc-select-panel.selectPanel{max-height:max(50vh,256px)}[hidden]{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { 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: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: NgxMatSelectSearchModule }, { kind: "component", type: i2.MatSelectSearchComponent, selector: "ngx-mat-select-search", inputs: ["placeholderLabel", "type", "closeIcon", "closeSvgIcon", "noEntriesFoundLabel", "clearSearchInput", "searching", "disableInitialFocus", "enableClearOnEscapePressed", "preventHomeEndKeyPropagation", "disableScrollToActiveOnOptionsChanged", "ariaLabel", "showToggleAllCheckbox", "toggleAllCheckboxChecked", "toggleAllCheckboxIndeterminate", "toggleAllCheckboxTooltipMessage", "toggleAllCheckboxTooltipPosition", "hideClearSearchButton", "alwaysRestoreSelectedOptionsMulti", "recreateValuesArray"], outputs: ["toggleAll"] }, { kind: "directive", type: XiriSelectDirective, selector: "[xiriSelect]", inputs: ["predicate", "compare", "serverSideSearch", "serverUrl", "serverParams", "values"], exportAs: ["xiriSelect"] }, { kind: "component", type: XiriTreeselectComponent, selector: "xiri-treeselect", inputs: ["field", "value"] }, { kind: "component", type: XiriDateComponent, selector: "xiri-date", inputs: ["field", "value"] }, { kind: "component", type: XiriYearMonthComponent, selector: "xiri-yearmonth", inputs: ["field", "value"] }, { kind: "component", type: XiriDateRangeComponent, selector: "xiri-date-range", inputs: ["field", "value"] }, { kind: "component", type: XiriDateTimeRangeComponent, selector: "xiri-date-time-range", inputs: ["field", "value"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "directive", type: MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: XiriVolumeComponent, selector: "xiri-volume", inputs: ["field", "value"] }, { kind: "component", type: XiriTimelimitComponent, selector: "xiri-timelimit", inputs: ["placeholder", "required", "disabled", "value", "texts"] }, { kind: "component", type: XiriFileComponent, selector: "xiri-file", inputs: ["value", "field"] }, { kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: XiriChipsComponent, selector: "xiri-chips", inputs: ["field"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: SafehtmlPipe, name: "safeHtml" }] }); }
3106
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: XiriFormFieldsComponent, isStandalone: true, selector: "xiri-form-fields", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, check: { classPropertyName: "check", publicName: "check", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formChange: "formChange" }, ngImport: i0, template: "@if (reloading()) {\n\t<mat-progress-bar class=\"reloadbar\" mode=\"indeterminate\"></mat-progress-bar>\n}\n<form class=\"xrow dynamic-form\" [formGroup]=\"formGroup\" [class]=\"display()\">\n\t@for (field of displayFields(); track field.id) {\n\t\t@if (isFieldVisible(field)) {\n\t\t@switch (field.type) {\n\t\t\t@case ('text') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.subtype || 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('number') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [autocomplete]=\"field.name || field.id\"\n\t\t\t\t\t [lang]=\"field.locale || ''\"\n\t\t\t\t\t [type]=\"field.type\"\n\t\t\t\t\t [attr.min]=\"field.min\"\n\t\t\t\t\t [attr.max]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('password') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.pwdhide ? 'password' : 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t<button mat-icon-button matSuffix class=\"form-field-button\" (click)=\"field.pwdhide = !field.pwdhide\" [attr.aria-label]=\"'Hide password'\"\n\t\t\t\t\t [attr.aria-pressed]=\"field.pwdhide\">\n\t\t\t\t\t\t<mat-icon>{{ field.pwdhide ? 'visibility_off' : 'visibility' }}</mat-icon>\n\t\t\t\t\t</button>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('select') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t@if (field.search === false && !field.selectAll) {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t<mat-option>\n\t\t\t\t\t\t\t\t<ngx-mat-select-search [formControl]=\"xiriSelect.formControl\" xiriSelect #xiriSelect=\"xiriSelect\"\n\t\t\t\t\t\t\t\t [values]=\"field.list || []\" [searching]=\"xiriSelect.searching\"\n\t\t\t\t\t\t\t\t [serverSideSearch]=\"!!field.serverSideSearch\" [serverUrl]=\"field.url || ''\"\n\t\t\t\t\t\t\t\t [serverParams]=\"field.params || {}\"\n\t\t\t\t\t\t\t\t [showToggleAllCheckbox]=\"!!field.multiple && !!field.selectAll && xiriSelect.hasSelectable()\"\n\t\t\t\t\t\t\t\t [toggleAllCheckboxChecked]=\"!!field.multiple && !!field.selectAll && xiriSelect.allSelected(formGroup.get(field.id)?.value)\"\n\t\t\t\t\t\t\t\t [toggleAllCheckboxIndeterminate]=\"!!field.multiple && !!field.selectAll && xiriSelect.someSelected(formGroup.get(field.id)?.value)\"\n\t\t\t\t\t\t\t\t (toggleAll)=\"xiriSelect.toggleSelectAll($event, formGroup.get(field.id))\"></ngx-mat-select-search>\n\t\t\t\t\t\t\t</mat-option>\n\t\t\t\t\t\t\t@for (x of xiriSelect.filter | async; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('treeselect') {\n\t\t\t\t<div class=\"treeselect\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-treeselect [field]=\"field\" [formControlName]=\"field.id\"\n\t\t\t\t\t [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\"></xiri-treeselect>\n\t\t\t\t\t<div class=\"xhint\" aria-live=\"polite\" [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\">\n\t\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.touched && formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('date') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"date\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date [field]=\"field\" [formControlName]=\"field.id\"></xiri-date>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('yearmonth') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"yearmonth\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-yearmonth [field]=\"field\" [formControlName]=\"field.id\"></xiri-yearmonth>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('daterange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"daterange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('datetimerange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"datetimerange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-time-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-time-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('bool') {\n\t\t\t\t<div class=\"bool\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-checkbox [formControlName]=\"field.id\">{{ field.name }}</mat-checkbox>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('radio') {\n\t\t\t\t<div class=\"radio\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<span class=\"radio-label\" [id]=\"field.id + '-label'\">{{ field.name }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<mat-radio-group\n\t\t\t\t\t\t[formControlName]=\"field.id\"\n\t\t\t\t\t\t[attr.aria-labelledby]=\"field.name ? field.id + '-label' : null\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t<mat-radio-button [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-radio-button>\n\t\t\t\t\t\t}\n\t\t\t\t\t</mat-radio-group>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('volume') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-volume [field]=\"field\" [formControlName]=\"field.id\"></xiri-volume>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('timelimit') {\n\t\t\t\t<div [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-timelimit matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [texts]=\"field.texts || {}\"></xiri-timelimit>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('textarea') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<textarea matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [rows]=\"field.rows || 5\"></textarea>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('file') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-file [field]=\"field\" [formControlName]=\"field.id\"></xiri-file>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('info') {\n\t\t\t\t<div class=\"info\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t}\n\t\t\t@case ('header') {\n\t\t\t\t@if (field.collapsible) {\n\t\t\t\t\t<div class=\"header collapsible\" [class]=\"field.class\" role=\"button\" tabindex=\"0\"\n\t\t\t\t\t [attr.aria-expanded]=\"!isSectionCollapsed(field.id)\"\n\t\t\t\t\t (click)=\"toggleSection(field)\" (keydown.enter)=\"toggleSection(field)\" (keydown.space)=\"toggleSection(field); $event.preventDefault()\">\n\t\t\t\t\t\t<mat-icon class=\"collapse-icon\" [class.collapsed]=\"isSectionCollapsed(field.id)\">expand_more</mat-icon>\n\t\t\t\t\t\t{{ field.value }}\n\t\t\t\t\t</div>\n\t\t\t\t} @else {\n\t\t\t\t\t<div class=\"header\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t\t}\n\t\t\t}\n\t\t\t@case ('divider') {\n\t\t\t\t<div class=\"divider\" [class]=\"field.class\">\n\t\t\t\t\t@if (field.value) {\n\t\t\t\t\t\t<span class=\"divider-text\">{{ field.value }}</span>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('html') {\n\t\t\t\t<div class=\"html\" [class]=\"field.class\" [innerHtml]=\"$any(field.value) | safeHtml\"></div>\n\t\t\t}\n\t\t\t@case ('question') {\n\t\t\t\t<div class=\"xcol question\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t<mat-icon [class]=\"field.iconColor || 'warn'\" inline=\"true\">{{ field.icon }}</mat-icon>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('waiting') {\n\t\t\t\t<div class=\"xcol waiting\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t@if (!field.done) {\n\t\t\t\t\t\t\t<mat-spinner diameter=\"40\"></mat-spinner>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.done) {\n\t\t\t\t\t\t\t<mat-icon inline=\"true\">done</mat-icon>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('chips') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-chips [field]=\"field\" [formControlName]=\"field.id\"></xiri-chips>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@default {\n\t\t\t\t<div>default: {{ field.type }}</div>\n\t\t\t}\n\t\t}\n\t\t}\n\t}\n</form>\n", styles: [":host{position:relative}.reloadbar{position:absolute;top:0;left:0;right:0;z-index:1}.dynamic-form{grid-row-gap:7px}.dynamic-form>mat-form-field{align-self:start}.dynamic-form mat-form-field mat-icon{--mat-icon-color: var(--xiri-formfield-icon-color)}.dynamic-form.line{grid-row-gap:5px}.dynamic-form.small{grid-row-gap:2px}.dynamic-form textarea{white-space:pre}.dynamic-form .xhint{display:flex;min-height:20px;margin-top:4px}.dynamic-form .xhint mat-hint{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint mat-hint.mat-mdc-form-field-hint-end{flex:1;text-align:right}.dynamic-form .xhint mat-error{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint.error mat-hint{display:none}.dynamic-form .date{min-width:min(9.5rem,100%)}.dynamic-form .date.datetime,.dynamic-form .daterange{min-width:min(14.5rem,100%)}.dynamic-form .datetimerange{min-width:min(18.5rem,100%)}.dynamic-form .bool{display:flex;flex-direction:column}.dynamic-form .bool mat-hint{font-size:var(--xiri-font-size-helper);margin-top:-8px;padding-left:44px}.dynamic-form .radio{display:flex;flex-direction:column;gap:var(--xiri-spacing-xs)}.dynamic-form .radio .radio-label{font-size:var(--xiri-font-size-label)}.dynamic-form .radio mat-radio-group{display:flex;flex-wrap:wrap;gap:var(--xiri-spacing-xs) var(--xiri-spacing-md)}.dynamic-form .radio mat-hint{font-size:var(--xiri-font-size-helper)}.dynamic-form .info{padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header{font-size:var(--xiri-font-size-title);padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header.collapsible{cursor:pointer;display:flex;align-items:center;gap:.25rem;-webkit-user-select:none;user-select:none;border-radius:var(--xiri-radius-xs);padding:.5rem .25rem;margin:.25rem 0}.dynamic-form .header.collapsible:hover{background:color-mix(in srgb,var(--primary, #2892D9) 8%,transparent)}.dynamic-form .header.collapsible .collapse-icon{transition:transform var(--xiri-duration-fast) var(--xiri-easing-standard)}.dynamic-form .header.collapsible .collapse-icon.collapsed{transform:rotate(-90deg)}.dynamic-form .divider{width:100%;display:flex;align-items:center;padding:.5rem 0;margin:.25rem 0}.dynamic-form .divider:before,.dynamic-form .divider:after{content:\"\";flex:1;height:1px;background:var(--outline-variant, var(--mat-sys-outline-variant, rgba(0, 0, 0, .12)))}.dynamic-form .divider .divider-text{padding:0 1rem;font-size:var(--xiri-font-size-helper);color:var(--on-surface-variant, var(--mat-sys-on-surface-variant, rgba(0, 0, 0, .6)));white-space:nowrap}.dynamic-form .question,.dynamic-form .waiting{display:flex}.dynamic-form .question .left,.dynamic-form .waiting .left{font-size:var(--xiri-font-size-display);padding-right:1rem}.dynamic-form .question{align-items:center}.dynamic-form .question .left mat-icon{height:auto;width:auto;line-height:1;overflow:visible}.dynamic-form .form-field-button{margin-left:12px;margin-right:12px}.mat-mdc-select-panel.selectPanel{max-height:max(50vh,256px)}[hidden]{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { 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: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: NgxMatSelectSearchModule }, { kind: "component", type: i2.MatSelectSearchComponent, selector: "ngx-mat-select-search", inputs: ["placeholderLabel", "type", "closeIcon", "closeSvgIcon", "noEntriesFoundLabel", "clearSearchInput", "searching", "disableInitialFocus", "enableClearOnEscapePressed", "preventHomeEndKeyPropagation", "disableScrollToActiveOnOptionsChanged", "ariaLabel", "showToggleAllCheckbox", "toggleAllCheckboxChecked", "toggleAllCheckboxIndeterminate", "toggleAllCheckboxTooltipMessage", "toggleAllCheckboxTooltipPosition", "hideClearSearchButton", "alwaysRestoreSelectedOptionsMulti", "recreateValuesArray"], outputs: ["toggleAll"] }, { kind: "directive", type: XiriSelectDirective, selector: "[xiriSelect]", inputs: ["predicate", "compare", "serverSideSearch", "serverUrl", "serverParams", "values"], exportAs: ["xiriSelect"] }, { kind: "component", type: XiriTreeselectComponent, selector: "xiri-treeselect", inputs: ["field", "value"] }, { kind: "component", type: XiriDateComponent, selector: "xiri-date", inputs: ["field", "value"] }, { kind: "component", type: XiriYearMonthComponent, selector: "xiri-yearmonth", inputs: ["field", "value"] }, { kind: "component", type: XiriDateRangeComponent, selector: "xiri-date-range", inputs: ["field", "value"] }, { kind: "component", type: XiriDateTimeRangeComponent, selector: "xiri-date-time-range", inputs: ["field", "value"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "directive", type: MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: XiriVolumeComponent, selector: "xiri-volume", inputs: ["field", "value"] }, { kind: "component", type: XiriTimelimitComponent, selector: "xiri-timelimit", inputs: ["placeholder", "required", "disabled", "value", "texts"] }, { kind: "component", type: XiriFileComponent, selector: "xiri-file", inputs: ["value", "field"] }, { kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: XiriChipsComponent, selector: "xiri-chips", inputs: ["field"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: SafehtmlPipe, name: "safeHtml" }] }); }
3063
3107
  }
3064
3108
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriFormFieldsComponent, decorators: [{
3065
3109
  type: Component,
@@ -3095,7 +3139,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
3095
3139
  AsyncPipe,
3096
3140
  SafehtmlPipe,
3097
3141
  XiriChipsComponent,
3098
- ], template: "@if (reloading()) {\n\t<mat-progress-bar class=\"reloadbar\" mode=\"indeterminate\"></mat-progress-bar>\n}\n<form class=\"xrow dynamic-form\" [formGroup]=\"formGroup\" [class]=\"display()\">\n\t@for (field of displayFields(); track field.id) {\n\t\t@if (isFieldVisible(field)) {\n\t\t@switch (field.type) {\n\t\t\t@case ('text') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.subtype || 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('number') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [autocomplete]=\"field.name || field.id\"\n\t\t\t\t\t [lang]=\"field.locale || ''\"\n\t\t\t\t\t [type]=\"field.type\"\n\t\t\t\t\t [attr.min]=\"field.min\"\n\t\t\t\t\t [attr.max]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('password') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.pwdhide ? 'password' : 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t<button mat-icon-button matSuffix class=\"form-field-button\" (click)=\"field.pwdhide = !field.pwdhide\" [attr.aria-label]=\"'Hide password'\"\n\t\t\t\t\t [attr.aria-pressed]=\"field.pwdhide\">\n\t\t\t\t\t\t<mat-icon>{{ field.pwdhide ? 'visibility_off' : 'visibility' }}</mat-icon>\n\t\t\t\t\t</button>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('select') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t@if (field.search === false) {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t<mat-option>\n\t\t\t\t\t\t\t\t<ngx-mat-select-search [formControl]=\"xiriSelect.formControl\" xiriSelect #xiriSelect=\"xiriSelect\"\n\t\t\t\t\t\t\t\t [values]=\"field.list || []\" [searching]=\"xiriSelect.searching\"\n\t\t\t\t\t\t\t\t [serverSideSearch]=\"!!field.serverSideSearch\" [serverUrl]=\"field.url || ''\"\n\t\t\t\t\t\t\t\t [serverParams]=\"field.params || {}\"></ngx-mat-select-search>\n\t\t\t\t\t\t\t</mat-option>\n\t\t\t\t\t\t\t@for (x of xiriSelect.filter | async; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('treeselect') {\n\t\t\t\t<div class=\"treeselect\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-treeselect [field]=\"field\" [formControlName]=\"field.id\"\n\t\t\t\t\t [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\"></xiri-treeselect>\n\t\t\t\t\t<div class=\"xhint\" aria-live=\"polite\" [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\">\n\t\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.touched && formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('date') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"date\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date [field]=\"field\" [formControlName]=\"field.id\"></xiri-date>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('yearmonth') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"yearmonth\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-yearmonth [field]=\"field\" [formControlName]=\"field.id\"></xiri-yearmonth>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('daterange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"daterange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('datetimerange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"datetimerange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-time-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-time-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('bool') {\n\t\t\t\t<div class=\"bool\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-checkbox [formControlName]=\"field.id\">{{ field.name }}</mat-checkbox>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('radio') {\n\t\t\t\t<div class=\"radio\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<span class=\"radio-label\" [id]=\"field.id + '-label'\">{{ field.name }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<mat-radio-group\n\t\t\t\t\t\t[formControlName]=\"field.id\"\n\t\t\t\t\t\t[attr.aria-labelledby]=\"field.name ? field.id + '-label' : null\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t<mat-radio-button [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-radio-button>\n\t\t\t\t\t\t}\n\t\t\t\t\t</mat-radio-group>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('volume') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-volume [field]=\"field\" [formControlName]=\"field.id\"></xiri-volume>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('timelimit') {\n\t\t\t\t<div [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-timelimit matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [texts]=\"field.texts || {}\"></xiri-timelimit>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('textarea') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<textarea matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [rows]=\"field.rows || 5\"></textarea>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('file') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-file [field]=\"field\" [formControlName]=\"field.id\"></xiri-file>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('info') {\n\t\t\t\t<div class=\"info\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t}\n\t\t\t@case ('header') {\n\t\t\t\t@if (field.collapsible) {\n\t\t\t\t\t<div class=\"header collapsible\" [class]=\"field.class\" role=\"button\" tabindex=\"0\"\n\t\t\t\t\t [attr.aria-expanded]=\"!isSectionCollapsed(field.id)\"\n\t\t\t\t\t (click)=\"toggleSection(field)\" (keydown.enter)=\"toggleSection(field)\" (keydown.space)=\"toggleSection(field); $event.preventDefault()\">\n\t\t\t\t\t\t<mat-icon class=\"collapse-icon\" [class.collapsed]=\"isSectionCollapsed(field.id)\">expand_more</mat-icon>\n\t\t\t\t\t\t{{ field.value }}\n\t\t\t\t\t</div>\n\t\t\t\t} @else {\n\t\t\t\t\t<div class=\"header\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t\t}\n\t\t\t}\n\t\t\t@case ('divider') {\n\t\t\t\t<div class=\"divider\" [class]=\"field.class\">\n\t\t\t\t\t@if (field.value) {\n\t\t\t\t\t\t<span class=\"divider-text\">{{ field.value }}</span>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('html') {\n\t\t\t\t<div class=\"html\" [class]=\"field.class\" [innerHtml]=\"$any(field.value) | safeHtml\"></div>\n\t\t\t}\n\t\t\t@case ('question') {\n\t\t\t\t<div class=\"xcol question\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t<mat-icon [class]=\"field.iconColor || 'warn'\" inline=\"true\">{{ field.icon }}</mat-icon>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('waiting') {\n\t\t\t\t<div class=\"xcol waiting\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t@if (!field.done) {\n\t\t\t\t\t\t\t<mat-spinner diameter=\"40\"></mat-spinner>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.done) {\n\t\t\t\t\t\t\t<mat-icon inline=\"true\">done</mat-icon>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('chips') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-chips [field]=\"field\" [formControlName]=\"field.id\"></xiri-chips>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@default {\n\t\t\t\t<div>default: {{ field.type }}</div>\n\t\t\t}\n\t\t}\n\t\t}\n\t}\n</form>\n", styles: [":host{position:relative}.reloadbar{position:absolute;top:0;left:0;right:0;z-index:1}.dynamic-form{grid-row-gap:7px}.dynamic-form mat-form-field mat-icon{--mat-icon-color: var(--xiri-formfield-icon-color)}.dynamic-form.line{grid-row-gap:5px}.dynamic-form.small{grid-row-gap:2px}.dynamic-form textarea{white-space:pre}.dynamic-form .xhint{display:flex;min-height:20px;margin-top:4px}.dynamic-form .xhint mat-hint{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint mat-hint.mat-mdc-form-field-hint-end{flex:1;text-align:right}.dynamic-form .xhint mat-error{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint.error mat-hint{display:none}.dynamic-form .date{align-self:start;min-width:min(9.5rem,100%)}.dynamic-form .date.datetime{min-width:min(14.5rem,100%)}.dynamic-form .daterange{align-self:start;min-width:min(14.5rem,100%)}.dynamic-form .datetimerange{align-self:start;min-width:min(18.5rem,100%)}.dynamic-form .bool{display:flex;flex-direction:column}.dynamic-form .bool mat-hint{font-size:var(--xiri-font-size-helper);margin-top:-8px;padding-left:44px}.dynamic-form .radio{display:flex;flex-direction:column;gap:var(--xiri-spacing-xs)}.dynamic-form .radio .radio-label{font-size:var(--xiri-font-size-label)}.dynamic-form .radio mat-radio-group{display:flex;flex-wrap:wrap;gap:var(--xiri-spacing-xs) var(--xiri-spacing-md)}.dynamic-form .radio mat-hint{font-size:var(--xiri-font-size-helper)}.dynamic-form .info{padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header{font-size:var(--xiri-font-size-title);padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header.collapsible{cursor:pointer;display:flex;align-items:center;gap:.25rem;-webkit-user-select:none;user-select:none;border-radius:var(--xiri-radius-xs);padding:.5rem .25rem;margin:.25rem 0}.dynamic-form .header.collapsible:hover{background:color-mix(in srgb,var(--primary, #2892D9) 8%,transparent)}.dynamic-form .header.collapsible .collapse-icon{transition:transform var(--xiri-duration-fast) var(--xiri-easing-standard)}.dynamic-form .header.collapsible .collapse-icon.collapsed{transform:rotate(-90deg)}.dynamic-form .divider{width:100%;display:flex;align-items:center;padding:.5rem 0;margin:.25rem 0}.dynamic-form .divider:before,.dynamic-form .divider:after{content:\"\";flex:1;height:1px;background:var(--outline-variant, var(--mat-sys-outline-variant, rgba(0, 0, 0, .12)))}.dynamic-form .divider .divider-text{padding:0 1rem;font-size:var(--xiri-font-size-helper);color:var(--on-surface-variant, var(--mat-sys-on-surface-variant, rgba(0, 0, 0, .6)));white-space:nowrap}.dynamic-form .question,.dynamic-form .waiting{display:flex}.dynamic-form .question .left,.dynamic-form .waiting .left{font-size:var(--xiri-font-size-display);padding-right:1rem}.dynamic-form .question{align-items:center}.dynamic-form .question .left mat-icon{height:auto;width:auto;line-height:1;overflow:visible}.dynamic-form .form-field-button{margin-left:12px;margin-right:12px}.mat-mdc-select-panel.selectPanel{max-height:max(50vh,256px)}[hidden]{display:none!important}\n"] }]
3142
+ ], template: "@if (reloading()) {\n\t<mat-progress-bar class=\"reloadbar\" mode=\"indeterminate\"></mat-progress-bar>\n}\n<form class=\"xrow dynamic-form\" [formGroup]=\"formGroup\" [class]=\"display()\">\n\t@for (field of displayFields(); track field.id) {\n\t\t@if (isFieldVisible(field)) {\n\t\t@switch (field.type) {\n\t\t\t@case ('text') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.subtype || 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('number') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [autocomplete]=\"field.name || field.id\"\n\t\t\t\t\t [lang]=\"field.locale || ''\"\n\t\t\t\t\t [type]=\"field.type\"\n\t\t\t\t\t [attr.min]=\"field.min\"\n\t\t\t\t\t [attr.max]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t@if (field.textPrefix) {\n\t\t\t\t\t\t<span matTextPrefix=\"\">{{ field.textPrefix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.textSuffix) {\n\t\t\t\t\t\t<span matTextSuffix=\"\">{{ field.textSuffix }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconPrefix) {\n\t\t\t\t\t\t<mat-icon matPrefix>{{ field.iconPrefix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.iconSuffix) {\n\t\t\t\t\t\t<mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('password') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<input matInput\n\t\t\t\t\t [formControlName]=\"field.id\"\n\t\t\t\t\t [type]=\"field.pwdhide ? 'password' : 'text'\"\n\t\t\t\t\t [autocomplete]=\"field.name\"\n\t\t\t\t\t [attr.minlength]=\"field.min\"\n\t\t\t\t\t [attr.maxlength]=\"field.max\"\n\t\t\t\t\t [required]=\"!!field.required\">\n\t\t\t\t\t<button mat-icon-button matSuffix class=\"form-field-button\" (click)=\"field.pwdhide = !field.pwdhide\" [attr.aria-label]=\"'Hide password'\"\n\t\t\t\t\t [attr.aria-pressed]=\"field.pwdhide\">\n\t\t\t\t\t\t<mat-icon>{{ field.pwdhide ? 'visibility_off' : 'visibility' }}</mat-icon>\n\t\t\t\t\t</button>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('select') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" floatLabel=\"auto\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t@if (field.search === false && !field.selectAll) {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<mat-select [formControlName]=\"field.id\" [multiple]=\"field.multiple\" [required]=\"!!field.required\" panelClass=\"selectPanel\">\n\t\t\t\t\t\t\t<mat-option>\n\t\t\t\t\t\t\t\t<ngx-mat-select-search [formControl]=\"xiriSelect.formControl\" xiriSelect #xiriSelect=\"xiriSelect\"\n\t\t\t\t\t\t\t\t [values]=\"field.list || []\" [searching]=\"xiriSelect.searching\"\n\t\t\t\t\t\t\t\t [serverSideSearch]=\"!!field.serverSideSearch\" [serverUrl]=\"field.url || ''\"\n\t\t\t\t\t\t\t\t [serverParams]=\"field.params || {}\"\n\t\t\t\t\t\t\t\t [showToggleAllCheckbox]=\"!!field.multiple && !!field.selectAll && xiriSelect.hasSelectable()\"\n\t\t\t\t\t\t\t\t [toggleAllCheckboxChecked]=\"!!field.multiple && !!field.selectAll && xiriSelect.allSelected(formGroup.get(field.id)?.value)\"\n\t\t\t\t\t\t\t\t [toggleAllCheckboxIndeterminate]=\"!!field.multiple && !!field.selectAll && xiriSelect.someSelected(formGroup.get(field.id)?.value)\"\n\t\t\t\t\t\t\t\t (toggleAll)=\"xiriSelect.toggleSelectAll($event, formGroup.get(field.id))\"></ngx-mat-select-search>\n\t\t\t\t\t\t\t</mat-option>\n\t\t\t\t\t\t\t@for (x of xiriSelect.filter | async; track x.id) {\n\t\t\t\t\t\t\t\t<mat-option [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-option>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</mat-select>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('treeselect') {\n\t\t\t\t<div class=\"treeselect\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-treeselect [field]=\"field\" [formControlName]=\"field.id\"\n\t\t\t\t\t [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\"></xiri-treeselect>\n\t\t\t\t\t<div class=\"xhint\" aria-live=\"polite\" [class.error]=\"formGroup.get(field.id)?.touched && formGroup.get(field.id)?.invalid\">\n\t\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.touched && formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('date') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"date\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date [field]=\"field\" [formControlName]=\"field.id\"></xiri-date>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('yearmonth') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"yearmonth\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-yearmonth [field]=\"field\" [formControlName]=\"field.id\"></xiri-yearmonth>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('daterange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"daterange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('datetimerange') {\n\t\t\t\t<mat-form-field [formGroup]=\"formGroup\" class=\"datetimerange\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t<xiri-date-time-range [field]=\"field\" [formControlName]=\"field.id\"></xiri-date-time-range>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('bool') {\n\t\t\t\t<div class=\"bool\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<mat-checkbox [formControlName]=\"field.id\">{{ field.name }}</mat-checkbox>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('radio') {\n\t\t\t\t<div class=\"radio\" [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<span class=\"radio-label\" [id]=\"field.id + '-label'\">{{ field.name }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<mat-radio-group\n\t\t\t\t\t\t[formControlName]=\"field.id\"\n\t\t\t\t\t\t[attr.aria-labelledby]=\"field.name ? field.id + '-label' : null\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (x of field.list; track x.id) {\n\t\t\t\t\t\t\t<mat-radio-button [value]=\"x.id\" [disabled]=\"x.disabled\">{{ x.name }}</mat-radio-button>\n\t\t\t\t\t\t}\n\t\t\t\t\t</mat-radio-group>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('volume') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-volume [field]=\"field\" [formControlName]=\"field.id\"></xiri-volume>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('timelimit') {\n\t\t\t\t<div [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-timelimit matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [texts]=\"field.texts || {}\"></xiri-timelimit>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('textarea') {\n\t\t\t\t<mat-form-field [class]=\"field.class\" [formGroup]=\"formGroup\" [hidden]=\"field.hide\">\n\t\t\t\t\t@if (field.name) {\n\t\t\t\t\t\t<mat-label>{{ field.name }}</mat-label>\n\t\t\t\t\t}\n\t\t\t\t\t<textarea matInput [formControlName]=\"field.id\" [required]=\"!!field.required\" [rows]=\"field.rows || 5\"></textarea>\n\t\t\t\t\t@if (field.hint) {\n\t\t\t\t\t\t<mat-hint>{{ field.hint }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@if (field.max) {\n\t\t\t\t\t\t<mat-hint align=\"end\">{{ formGroup.get(field.id)?.value?.length || 0 }} / {{ field.max }}</mat-hint>\n\t\t\t\t\t}\n\t\t\t\t\t@for (vali of field.validations; track vali.id) {\n\t\t\t\t\t\t<ng-container ngProjectAs=\"mat-error\">\n\t\t\t\t\t\t\t@if (formGroup.get(field.id)?.hasError(vali.id)) {\n\t\t\t\t\t\t\t\t<mat-error>{{ vali.message }}</mat-error>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t}\n\t\t\t\t</mat-form-field>\n\t\t\t}\n\t\t\t@case ('file') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-file [field]=\"field\" [formControlName]=\"field.id\"></xiri-file>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('info') {\n\t\t\t\t<div class=\"info\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t}\n\t\t\t@case ('header') {\n\t\t\t\t@if (field.collapsible) {\n\t\t\t\t\t<div class=\"header collapsible\" [class]=\"field.class\" role=\"button\" tabindex=\"0\"\n\t\t\t\t\t [attr.aria-expanded]=\"!isSectionCollapsed(field.id)\"\n\t\t\t\t\t (click)=\"toggleSection(field)\" (keydown.enter)=\"toggleSection(field)\" (keydown.space)=\"toggleSection(field); $event.preventDefault()\">\n\t\t\t\t\t\t<mat-icon class=\"collapse-icon\" [class.collapsed]=\"isSectionCollapsed(field.id)\">expand_more</mat-icon>\n\t\t\t\t\t\t{{ field.value }}\n\t\t\t\t\t</div>\n\t\t\t\t} @else {\n\t\t\t\t\t<div class=\"header\" [class]=\"field.class\">{{ field.value }}</div>\n\t\t\t\t}\n\t\t\t}\n\t\t\t@case ('divider') {\n\t\t\t\t<div class=\"divider\" [class]=\"field.class\">\n\t\t\t\t\t@if (field.value) {\n\t\t\t\t\t\t<span class=\"divider-text\">{{ field.value }}</span>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('html') {\n\t\t\t\t<div class=\"html\" [class]=\"field.class\" [innerHtml]=\"$any(field.value) | safeHtml\"></div>\n\t\t\t}\n\t\t\t@case ('question') {\n\t\t\t\t<div class=\"xcol question\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t<mat-icon [class]=\"field.iconColor || 'warn'\" inline=\"true\">{{ field.icon }}</mat-icon>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('waiting') {\n\t\t\t\t<div class=\"xcol waiting\" [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<div class=\"left\">\n\t\t\t\t\t\t@if (!field.done) {\n\t\t\t\t\t\t\t<mat-spinner diameter=\"40\"></mat-spinner>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@if (field.done) {\n\t\t\t\t\t\t\t<mat-icon inline=\"true\">done</mat-icon>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"right\">{{ field.value }}</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@case ('chips') {\n\t\t\t\t<div [class]=\"field.class\" [hidden]=\"field.hide\">\n\t\t\t\t\t<xiri-chips [field]=\"field\" [formControlName]=\"field.id\"></xiri-chips>\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t@default {\n\t\t\t\t<div>default: {{ field.type }}</div>\n\t\t\t}\n\t\t}\n\t\t}\n\t}\n</form>\n", styles: [":host{position:relative}.reloadbar{position:absolute;top:0;left:0;right:0;z-index:1}.dynamic-form{grid-row-gap:7px}.dynamic-form>mat-form-field{align-self:start}.dynamic-form mat-form-field mat-icon{--mat-icon-color: var(--xiri-formfield-icon-color)}.dynamic-form.line{grid-row-gap:5px}.dynamic-form.small{grid-row-gap:2px}.dynamic-form textarea{white-space:pre}.dynamic-form .xhint{display:flex;min-height:20px;margin-top:4px}.dynamic-form .xhint mat-hint{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint mat-hint.mat-mdc-form-field-hint-end{flex:1;text-align:right}.dynamic-form .xhint mat-error{font-size:var(--xiri-font-size-helper);padding:1px 16px 0}.dynamic-form .xhint.error mat-hint{display:none}.dynamic-form .date{min-width:min(9.5rem,100%)}.dynamic-form .date.datetime,.dynamic-form .daterange{min-width:min(14.5rem,100%)}.dynamic-form .datetimerange{min-width:min(18.5rem,100%)}.dynamic-form .bool{display:flex;flex-direction:column}.dynamic-form .bool mat-hint{font-size:var(--xiri-font-size-helper);margin-top:-8px;padding-left:44px}.dynamic-form .radio{display:flex;flex-direction:column;gap:var(--xiri-spacing-xs)}.dynamic-form .radio .radio-label{font-size:var(--xiri-font-size-label)}.dynamic-form .radio mat-radio-group{display:flex;flex-wrap:wrap;gap:var(--xiri-spacing-xs) var(--xiri-spacing-md)}.dynamic-form .radio mat-hint{font-size:var(--xiri-font-size-helper)}.dynamic-form .info{padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header{font-size:var(--xiri-font-size-title);padding-top:.8rem;padding-bottom:.4rem;color:var(--primary, #2892D9)}.dynamic-form .header.collapsible{cursor:pointer;display:flex;align-items:center;gap:.25rem;-webkit-user-select:none;user-select:none;border-radius:var(--xiri-radius-xs);padding:.5rem .25rem;margin:.25rem 0}.dynamic-form .header.collapsible:hover{background:color-mix(in srgb,var(--primary, #2892D9) 8%,transparent)}.dynamic-form .header.collapsible .collapse-icon{transition:transform var(--xiri-duration-fast) var(--xiri-easing-standard)}.dynamic-form .header.collapsible .collapse-icon.collapsed{transform:rotate(-90deg)}.dynamic-form .divider{width:100%;display:flex;align-items:center;padding:.5rem 0;margin:.25rem 0}.dynamic-form .divider:before,.dynamic-form .divider:after{content:\"\";flex:1;height:1px;background:var(--outline-variant, var(--mat-sys-outline-variant, rgba(0, 0, 0, .12)))}.dynamic-form .divider .divider-text{padding:0 1rem;font-size:var(--xiri-font-size-helper);color:var(--on-surface-variant, var(--mat-sys-on-surface-variant, rgba(0, 0, 0, .6)));white-space:nowrap}.dynamic-form .question,.dynamic-form .waiting{display:flex}.dynamic-form .question .left,.dynamic-form .waiting .left{font-size:var(--xiri-font-size-display);padding-right:1rem}.dynamic-form .question{align-items:center}.dynamic-form .question .left mat-icon{height:auto;width:auto;line-height:1;overflow:visible}.dynamic-form .form-field-button{margin-left:12px;margin-right:12px}.mat-mdc-select-panel.selectPanel{max-height:max(50vh,256px)}[hidden]{display:none!important}\n"] }]
3099
3143
  }], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], formChange: [{ type: i0.Output, args: ["formChange"] }], check: [{ type: i0.Input, args: [{ isSignal: true, alias: "check", required: false }] }] } });
3100
3144
  // Was ein Reload-Patch am Feld ändern darf, jeweils mit Typprüfung. Der Server ist eine
3101
3145
  // Trust-Boundary: eine kaputte `list` oder ein `min: "3"` dürfen weder das Pruning noch den
@@ -3739,6 +3783,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
3739
3783
  MatIcon], template: "<div class=\"dialog\">\n\t<div class=\"dialog-header\">\n\t\t<h1 mat-dialog-title>{{ header() }}</h1>\n\t\t@if (type() !== 'waiting') {\n\t\t\t<button mat-icon-button aria-label=\"Schlie\u00DFen\" (click)=\"dialogRef.close(null)\"><mat-icon>close</mat-icon></button>\n\t\t}\n\t</div>\n\t<mat-dialog-content>\n\t\t@if (loading() && formFields() === null) {\n\t\t\t<mat-spinner diameter=\"30\"></mat-spinner>\n\t\t}\n\t\t@if (formFields() !== null) {\n\t\t\t@if (type() === 'table') {\n\t\t\t\t<xiri-raw-table [settings]=\"rawTable\"></xiri-raw-table>\n\t\t\t} @else {\n\t\t\t\t<xiri-form-fields [form]=\"formFields()\" (formChange)=\"formChanged($event)\" [disabled]=\"loading()\"\n\t\t\t\t [check]=\"checkSubject.asObservable()\"></xiri-form-fields>\n\t\t\t}\n\t\t}\n\t\t@if (componentData() !== null && dynComponentType() !== null) {\n\t\t\t<ng-container [ngComponentOutlet]=\"dynComponentType()\"\n\t\t\t [ngComponentOutletInputs]=\"{ data: componentData() }\"></ng-container>\n\t\t}\n\t\t@if (error()) {\n\t\t\t<xiri-error class=\"error\" [text]=\"error()\"></xiri-error>\n\t\t}\n\t\t@if (done()) {\n\t\t\t<div class=\"xcol done\">\n\t\t\t\t<xiri-done></xiri-done>\n\t\t\t</div>\n\t\t}\n\t</mat-dialog-content>\n\t@if (!done() && !(loading() && formFields() === null) && (loading() || buttons().length > 0)) {\n\t\t<mat-divider></mat-divider>\n\t\t<mat-dialog-actions [class.one]=\"buttons().length===1\">\n\t\t\t@if (loading()) {\n\t\t\t\t<mat-spinner diameter=\"30\" class=\"actions-spinner\"></mat-spinner>\n\t\t\t} @else {\n\t\t\t\t@for (button of buttons(); track $index) {\n\t\t\t\t\t<xiri-buttonstyle [button]=\"button\" (click)=\"clickButton( button )\" [disabled]=\"!!button.default && !formValid()\"></xiri-buttonstyle>\n\t\t\t\t}\n\t\t\t}\n\t\t</mat-dialog-actions>\n\t}\n</div>", styles: ["mat-spinner{margin:var(--xiri-spacing-md)}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding-inline-end:var(--xiri-spacing-lg)}.dialog-header h1[mat-dialog-title]{margin-bottom:0;flex:0 1 auto;min-width:0;overflow-wrap:anywhere}mat-dialog-content{overflow-x:auto}.dynamic-form{margin-bottom:var(--xiri-spacing-md)}.dynamic-form .field{width:100%;margin-top:var(--xiri-spacing-sm)}.question,.waiting{display:flex}.question .left,.waiting .left{font-size:var(--xiri-font-size-display);padding-right:var(--xiri-spacing-md)}.waiting mat-icon{color:var(--color-success, #2ECC71);font-size:var(--xiri-font-size-headline)}.error{color:var(--error, red);font-size:var(--xiri-font-size-title);margin-top:var(--xiri-spacing-md);margin-bottom:var(--xiri-spacing-md)}mat-dialog-actions{justify-content:space-between;padding-left:var(--xiri-spacing-lg);padding-right:var(--xiri-spacing-lg)}mat-dialog-actions.one{justify-content:end}mat-dialog-actions .actions-spinner{margin:0 0 0 auto}mat-dialog-content{min-height:4rem}mat-dialog-content.mat-mdc-dialog-content{padding-bottom:var(--xiri-spacing-md)}mat-dialog-content>*{animation:fadeIn var(--xiri-duration-fast, .15s) var(--xiri-easing-standard, cubic-bezier(.4, 0, .2, 1))}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.done{text-align:center;font-size:var(--xiri-font-size-display)}[hidden]{display:none!important}\n"] }]
3740
3784
  }], ctorParameters: () => [] });
3741
3785
 
3786
+ const XIRI_PANEL_HOST = new InjectionToken('XIRI_PANEL_HOST');
3742
3787
  class XiriResponseHandlerService {
3743
3788
  constructor() {
3744
3789
  this.router = inject(Router);
@@ -3755,6 +3800,8 @@ class XiriResponseHandlerService {
3755
3800
  else
3756
3801
  this.router.navigate([this.router.url]).then();
3757
3802
  }
3803
+ else if (res.refresh == 'panel')
3804
+ callbacks?.onPanelRefresh?.();
3758
3805
  else if (res.goto)
3759
3806
  this.router.navigate([res.goto]).then();
3760
3807
  else if (res.table == 'update' || res.update == 'table')
@@ -3818,6 +3865,8 @@ class XiriButtonComponent {
3818
3865
  this.dialog = inject(MatDialog);
3819
3866
  this.downloadService = inject(XiriDownloadService);
3820
3867
  this.responseHandler = inject(XiriResponseHandlerService);
3868
+ // Nächstgelegene Card; null außerhalb einer Card. Ziel für refresh:'panel'.
3869
+ this.panelHost = inject(XIRI_PANEL_HOST, { optional: true });
3821
3870
  this._disabled = computed(() => {
3822
3871
  if (this.filterData() === null)
3823
3872
  return true;
@@ -3960,7 +4009,7 @@ class XiriButtonComponent {
3960
4009
  return;
3961
4010
  }
3962
4011
  this.stopPolling();
3963
- this.responseHandler.handle(result);
4012
+ this.responseHandler.handle(result, { onPanelRefresh: () => this.refreshPanel() });
3964
4013
  this.result.emit({
3965
4014
  button: this.button(),
3966
4015
  result: result,
@@ -3968,6 +4017,12 @@ class XiriButtonComponent {
3968
4017
  loading: false,
3969
4018
  });
3970
4019
  }
4020
+ refreshPanel() {
4021
+ if (this.panelHost)
4022
+ this.panelHost.reloadPanel();
4023
+ else
4024
+ console.warn('xiri-button: refresh:panel ohne umschließende Card', this.button().url);
4025
+ }
3971
4026
  startPolling(url, intervalMs, text) {
3972
4027
  this.cancelPollTimers();
3973
4028
  const now = Date.now();
@@ -4102,6 +4157,8 @@ class XiriTableInlineEditService {
4102
4157
  this.displayedOptions = signal([], /* @ts-ignore */
4103
4158
  ...(ngDevMode ? [{ debugName: "displayedOptions" }] : /* istanbul ignore next */ []));
4104
4159
  this.editingOriginalValue = null;
4160
+ // Hochgezählt bei jedem start()/cancel(): ein verspäteter Save-Fehler öffnet die Zelle nur wieder, wenn seitdem nichts passiert ist.
4161
+ this.editSeq = 0;
4105
4162
  this.editableOptionsSub = null;
4106
4163
  this.optionCache = new Map();
4107
4164
  this.searchSub = null;
@@ -4116,10 +4173,12 @@ class XiriTableInlineEditService {
4116
4173
  this.onSaved = config.onSaved;
4117
4174
  this.onDataUpdate = config.onDataUpdate;
4118
4175
  this.onCallReturn = config.onCallReturn;
4176
+ this.isRowLive = config.isRowLive;
4119
4177
  }
4120
4178
  start(row, column, skipSavingCheck = false) {
4121
4179
  if (!column.editable || !this.editUrl || (!skipSavingCheck && this.savingCell()))
4122
4180
  return;
4181
+ this.editSeq++;
4123
4182
  const val = row[column.id];
4124
4183
  this.editingOriginalValue = Array.isArray(val) ? JSON.parse(JSON.stringify(val)) : val;
4125
4184
  if (column.format === 'chips' && Array.isArray(val) && !column.editableOptionsUrl) {
@@ -4222,6 +4281,7 @@ class XiriTableInlineEditService {
4222
4281
  return column.editableOptions ?? this.loadedEditableOptions();
4223
4282
  }
4224
4283
  cancel() {
4284
+ this.editSeq++;
4225
4285
  const editing = this.editingCell();
4226
4286
  if (editing) {
4227
4287
  editing.row[editing.field] = this.editingOriginalValue;
@@ -4240,6 +4300,12 @@ class XiriTableInlineEditService {
4240
4300
  return;
4241
4301
  const newValue = row[column.id];
4242
4302
  const originalValue = this.editingOriginalValue;
4303
+ const seq = this.editSeq;
4304
+ const snapshot = {
4305
+ chips: this.editingChipsValues(),
4306
+ options: this.loadedEditableOptions(),
4307
+ cache: new Map(this.optionCache), // enthält auch nur per editableSearchUrl gefundene Optionen
4308
+ };
4243
4309
  this.editingCell.set(null);
4244
4310
  this.editingOriginalValue = null;
4245
4311
  this.loadedEditableOptions.set([]);
@@ -4272,8 +4338,21 @@ class XiriTableInlineEditService {
4272
4338
  },
4273
4339
  error: (err) => {
4274
4340
  this.savingCell.set(null);
4275
- row[column.id] = originalValue;
4276
- this.onDataUpdate();
4341
+ if (this.editSeq !== seq || !this.isRowLive(row)) {
4342
+ // User ist schon woanders (Tab, Escape, neue Zelle) oder ein Reload hat die Row ersetzt: nichts kapern, Wert verwerfen
4343
+ row[column.id] = originalValue;
4344
+ this.onDataUpdate();
4345
+ }
4346
+ else {
4347
+ // Abgelehnten Wert stehen lassen und Zelle wieder öffnen; Escape stellt weiterhin das Original her
4348
+ this.loadedEditableOptions.set(snapshot.options);
4349
+ this.editingChipsValues.set(snapshot.chips);
4350
+ this.editingOriginalValue = originalValue;
4351
+ this.editingCell.set({ row, field: column.id });
4352
+ this.initSearch(column, row);
4353
+ snapshot.cache.forEach((o, k) => this.optionCache.set(k, o)); // nach initSearch, das den Cache leert
4354
+ this.focus();
4355
+ }
4277
4356
  this.snackbar.error(errorMessage$1(err) || 'Unknown Error');
4278
4357
  }
4279
4358
  });
@@ -4304,7 +4383,8 @@ class XiriTableInlineEditService {
4304
4383
  const direction = event.shiftKey ? -1 : 1;
4305
4384
  const nextColumn = this.getAdjacentEditableColumn(column.id, direction);
4306
4385
  this.save(row, column);
4307
- if (nextColumn) {
4386
+ // Nur weiterspringen, wenn der Save die Zelle nicht (synchron abgelehnt) wieder geöffnet hat
4387
+ if (nextColumn && !this.editingCell()) {
4308
4388
  this.start(row, nextColumn, true);
4309
4389
  }
4310
4390
  }
@@ -4823,6 +4903,8 @@ class XiriTableComponent {
4823
4903
  this.numberService = inject(XiriLocaleService);
4824
4904
  this.snackbar = inject(XiriSnackbarService);
4825
4905
  this.responseHandler = inject(XiriResponseHandlerService);
4906
+ // Nächstgelegene Card; null außerhalb einer Card. Ziel für refresh:'panel' aus eigenen Aktionspfaden.
4907
+ this.panelHost = inject(XIRI_PANEL_HOST, { optional: true });
4826
4908
  this.downloadService = inject(XiriDownloadService);
4827
4909
  this.inlineEdit = inject(XiriTableInlineEditService);
4828
4910
  this.tree = inject(XiriTableTreeService);
@@ -4958,6 +5040,7 @@ class XiriTableComponent {
4958
5040
  onSaved: (row, fieldId) => this.inlineEdit.flashSaved(row, fieldId, this.dataSource),
4959
5041
  onDataUpdate: () => this.dataSource._updateChangeSubscription(),
4960
5042
  onCallReturn: (result) => this.callReturn(result),
5043
+ isRowLive: (row) => this.dataSource.data.includes(row),
4961
5044
  });
4962
5045
  if (this.options.pagination)
4963
5046
  this.paginator().pageSize = this.options.itemsPerPage;
@@ -5516,9 +5599,10 @@ class XiriTableComponent {
5516
5599
  buttonReturn(event) {
5517
5600
  if (!event.done)
5518
5601
  return;
5519
- this.callReturn(event.result);
5602
+ // xiri-button hat refresh:'panel' schon an den Panel-Host gegeben – hier nicht noch einmal.
5603
+ this.callReturn(event.result, true);
5520
5604
  }
5521
- callReturn(result) {
5605
+ callReturn(result, fromButton = false) {
5522
5606
  this.responseHandler.handle(result, {
5523
5607
  onTableRefresh: () => this.reload(),
5524
5608
  onTableUpdate: (id, field, content) => {
@@ -5527,9 +5611,16 @@ class XiriTableComponent {
5527
5611
  return;
5528
5612
  this.dataSource.data[i][field] = content;
5529
5613
  this.dataSource._updateChangeSubscription();
5530
- }
5614
+ },
5615
+ onPanelRefresh: fromButton ? undefined : () => this.refreshPanel(),
5531
5616
  });
5532
5617
  }
5618
+ refreshPanel() {
5619
+ if (this.panelHost)
5620
+ this.panelHost.reloadPanel();
5621
+ else
5622
+ console.warn('xiri-table: refresh:panel ohne umschließende Card');
5623
+ }
5533
5624
  // Row ids are backend values (int64 or string) and are passed through untouched.
5534
5625
  // Coercing them to number would round anything above 2^53 and turn a non-numeric
5535
5626
  // id into NaN; rows without an id are dropped rather than sent as undefined.
@@ -6560,6 +6651,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6560
6651
  XiriUrlPipe], host: { '[class.compact]': 'compact()' }, template: "@let cardUrl = settings().link | xiriUrl;\n<a [routerLink]=\"cardUrl?.path\" [queryParams]=\"cardUrl?.queryParams\">\n\t@if (compact()) {\n\t\t<div class=\"card xiri-cardlink-flat\" matRipple>\n\t\t\t<mat-card-header>\n\t\t\t\t@if (settings().icon) {\n\t\t\t\t\t<div mat-card-avatar>\n\t\t\t\t\t\t<mat-icon [fontSet]=\"settings().iconSet\">{{ settings().icon }}</mat-icon>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t\t@if (settings().text) {\n\t\t\t\t\t<mat-card-title>{{ settings().text }}</mat-card-title>\n\t\t\t\t}\n\t\t\t\t@if (settings().sub) {\n\t\t\t\t\t<mat-card-subtitle>{{ settings().sub }}</mat-card-subtitle>\n\t\t\t\t}\n\t\t\t</mat-card-header>\n\t\t</div>\n\t} @else {\n\t\t<mat-card class=\"card mat-mdc-elevation-specific mat-elevation-z2\" matRipple>\n\t\t\t<mat-card-header>\n\t\t\t\t@if (settings().icon) {\n\t\t\t\t\t<div mat-card-avatar>\n\t\t\t\t\t\t<mat-icon [fontSet]=\"settings().iconSet\">{{ settings().icon }}</mat-icon>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t\t@if (settings().text) {\n\t\t\t\t\t<mat-card-title>{{ settings().text }}</mat-card-title>\n\t\t\t\t}\n\t\t\t\t@if (settings().sub) {\n\t\t\t\t\t<mat-card-subtitle>{{ settings().sub }}</mat-card-subtitle>\n\t\t\t\t}\n\t\t\t</mat-card-header>\n\t\t</mat-card>\n\t}\n</a>\n", styles: [":host{margin-bottom:2rem}mat-card{transition:background-color var(--xiri-duration-fast, .15s) var(--xiri-easing-standard, cubic-bezier(.4, 0, .2, 1))}mat-card:hover{background-color:var(--surface-variant, #DEE3EB)}:host(.compact){margin-bottom:0}:host(.compact) .xiri-cardlink-flat{background:transparent;box-shadow:none;padding:0;display:block;transition:background-color var(--xiri-duration-fast, .15s) var(--xiri-easing-standard, cubic-bezier(.4, 0, .2, 1))}:host(.compact) .xiri-cardlink-flat:hover{background-color:var(--surface-variant, #DEE3EB)}.mat-mdc-card-avatar{background-color:var(--primary, #2892D9);border-radius:50%;color:var(--on-primary, white);text-align:center;width:4rem;height:4rem}.mat-mdc-card-avatar mat-icon{font-size:2rem;line-height:4rem;width:2rem;height:4rem}\n"] }]
6561
6652
  }], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: true }] }] } });
6562
6653
 
6654
+ /**
6655
+ * Lädt ein Panel (Card, Expansion-Panel) von einer URL und puffert die letzte erfolgreiche Antwort.
6656
+ * Gemeinsame Logik der XIRI_PANEL_HOST-Implementierungen; muss im Injection-Context aufgerufen werden.
6657
+ *
6658
+ * - `raw`: rohe Antwort, nur gelesen, wenn die Resource einen Wert hat (value() wirft im Fehlerzustand).
6659
+ * - `loaded`: das Objekt unter `opts.key` der letzten erfolgreichen Antwort. Bleibt bei Reload-Fehler
6660
+ * stehen, wird bei url-Wechsel und bei einer erfolgreichen Antwort ohne `opts.key` geleert.
6661
+ * - `reloadOrQueue`: lädt neu; läuft der erste Load noch, wird der Reload nachgeholt, sobald er fertig ist.
6662
+ */
6663
+ function createPanelLoader(opts) {
6664
+ // XiriDataService erst beim ersten Request auflösen: Hosts ohne url (statische Card, Shell-Panel) brauchen so
6665
+ // weiterhin keinen HttpClient-Provider.
6666
+ const injector = inject(Injector);
6667
+ // Signal, kein Boolean: der Effect muss darauf reagieren, wenn es gesetzt wird.
6668
+ const pendingReload = signal(false, /* @ts-ignore */
6669
+ ...(ngDevMode ? [{ debugName: "pendingReload" }] : /* istanbul ignore next */ []));
6670
+ const resource = rxResource({
6671
+ params: opts.url,
6672
+ stream: ({ params }) => injector.get(XiriDataService).post(params, null),
6673
+ });
6674
+ const errorMsg = computed(() => {
6675
+ const e = resource.error();
6676
+ if (!e)
6677
+ return '';
6678
+ const http = (e.cause ?? e);
6679
+ return http.error?.error || 'Fehler beim Laden';
6680
+ }, /* @ts-ignore */
6681
+ ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
6682
+ const raw = computed(() => resource.hasValue() ? resource.value() : undefined, /* @ts-ignore */
6683
+ ...(ngDevMode ? [{ debugName: "raw" }] : /* istanbul ignore next */ []));
6684
+ /** Objekt unter `key` in der aktuellen Antwort (Top-Level), sonst null. */
6685
+ const response = computed(() => {
6686
+ const r = raw();
6687
+ const c = r && typeof r === 'object' && !Array.isArray(r) ? r[opts.key] : undefined;
6688
+ return c && typeof c === 'object' && !Array.isArray(c) ? c : null;
6689
+ }, /* @ts-ignore */
6690
+ ...(ngDevMode ? [{ debugName: "response" }] : /* istanbul ignore next */ []));
6691
+ const loaded = linkedSignal({ ...(ngDevMode ? { debugName: "loaded" } : /* istanbul ignore next */ {}), source: () => ({ url: opts.url(), item: response(), hasValue: raw() != null }),
6692
+ computation: (s, prev) => {
6693
+ if (s.item)
6694
+ return s.item;
6695
+ if (s.hasValue)
6696
+ return null;
6697
+ return prev && prev.source.url === s.url ? prev.value : null;
6698
+ } });
6699
+ // pendingReload zuerst lesen, damit beide Signale als Abhängigkeit registriert sind.
6700
+ effect(() => {
6701
+ const pending = pendingReload();
6702
+ const loading = resource.isLoading();
6703
+ if (pending && !loading) {
6704
+ pendingReload.set(false);
6705
+ resource.reload();
6706
+ }
6707
+ });
6708
+ return {
6709
+ loading: resource.isLoading,
6710
+ errorMsg,
6711
+ raw,
6712
+ loaded,
6713
+ /** Manueller Reload (Reload-Button): kein Doppelstart, solange geladen wird. */
6714
+ reload: () => {
6715
+ if (!resource.isLoading())
6716
+ resource.reload();
6717
+ },
6718
+ /** refresh:'panel': reload() gibt false zurück, solange der erste Load läuft – dann nachholen. */
6719
+ // ponytail: bei url-Wechsel während pending läuft danach ein Reload zu viel; harmlos.
6720
+ reloadOrQueue: () => {
6721
+ if (!resource.reload())
6722
+ pendingReload.set(true);
6723
+ },
6724
+ };
6725
+ }
6726
+
6563
6727
  class XiriSkeletonComponent {
6564
6728
  constructor() {
6565
6729
  this.type = input('text', /* @ts-ignore */
@@ -6591,45 +6755,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6591
6755
 
6592
6756
  class XiriCardComponent {
6593
6757
  constructor() {
6594
- this.dataService = inject(XiriDataService);
6758
+ this.responseHandler = inject(XiriResponseHandlerService);
6759
+ // Nächste äußere Card (Provider dieser Card übersprungen). Ziel für refresh:'panel', wenn diese Card keine url hat.
6760
+ this.parentPanel = inject(XIRI_PANEL_HOST, { optional: true, skipSelf: true });
6595
6761
  this.settings = input.required(/* @ts-ignore */
6596
6762
  ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
6763
+ // Lädt {card: …} von settings().url; puffert die letzte komplette Card (siehe panel-loader.ts).
6764
+ this.loader = createPanelLoader({ url: () => this.settings().url, key: 'card' });
6597
6765
  // Bei flat nur rendern, wenn der Header Inhalt hat; sonst bliebe eine leere 32px-Leiste.
6598
6766
  this.showHeader = computed(() => {
6599
- const s = this.settings();
6767
+ const s = this.card();
6600
6768
  return !s.flat || !!(s.header || s.headerSub || s.headerIcon || s.buttonsTop?.buttons?.length
6601
6769
  || s.collapsible || (s.reload && s.url));
6602
6770
  }, /* @ts-ignore */
6603
6771
  ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
6604
- this.isCollapsed = linkedSignal({ ...(ngDevMode ? { debugName: "isCollapsed" } : /* istanbul ignore next */ {}), source: () => this.settings().collapsed,
6772
+ this.isCollapsed = linkedSignal({ ...(ngDevMode ? { debugName: "isCollapsed" } : /* istanbul ignore next */ {}), source: () => this.card().collapsed,
6605
6773
  computation: (collapsed, previous) => collapsed ?? previous?.value ?? false });
6606
- this.cardResource = rxResource({
6607
- params: () => this.settings().url,
6608
- stream: ({ params }) => this.dataService.post(params, null),
6609
- });
6610
- this.loading = this.cardResource.isLoading;
6611
- this.errorMsg = computed(() => {
6612
- const e = this.cardResource.error();
6613
- if (!e)
6614
- return '';
6615
- const http = (e.cause ?? e);
6616
- return http.error?.error || 'Fehler beim Laden';
6617
- }, /* @ts-ignore */
6618
- ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
6774
+ this.loading = this.loader.loading;
6775
+ this.errorMsg = this.loader.errorMsg;
6776
+ this._raw = this.loader.raw;
6777
+ /** Zuletzt erfolgreich geladene komplette Card ({card: …}); null bei Zeilen-Antworten. */
6778
+ this.loadedCard = this.loader.loaded;
6779
+ /** Inhaltszeilen aus einer Nicht-Card-Antwort: {data: rows} → rows, sonst die Antwort selbst. */
6619
6780
  this._loaded = computed(() => {
6620
- const res = this.cardResource.value();
6781
+ if (this.loadedCard())
6782
+ return undefined;
6783
+ const res = this._raw();
6621
6784
  if (res == null)
6622
6785
  return res;
6623
6786
  return res.data ?? res;
6624
6787
  }, /* @ts-ignore */
6625
6788
  ...(ngDevMode ? [{ debugName: "_loaded" }] : /* istanbul ignore next */ []));
6626
- this.cardData = computed(() => this._loaded() ?? this.settings().data, /* @ts-ignore */
6789
+ /** settings(), überlagert von einer nachgeladenen kompletten Card. Inhaltsfelder kommen dann nur aus der Antwort. */
6790
+ this.card = computed(() => {
6791
+ const s = this.settings();
6792
+ const c = this.loadedCard();
6793
+ if (!c)
6794
+ return s;
6795
+ return { ...s, ...c, fields: c.fields, data: c.data, dense: c.dense, components: c.components,
6796
+ showHeader: c.showHeader, forceMinWidth: c.forceMinWidth };
6797
+ }, /* @ts-ignore */
6798
+ ...(ngDevMode ? [{ debugName: "card" }] : /* istanbul ignore next */ []));
6799
+ this.cardData = computed(() => this.loadedCard() ? this.loadedCard().data : (this._loaded() ?? this.settings().data), /* @ts-ignore */
6627
6800
  ...(ngDevMode ? [{ debugName: "cardData" }] : /* istanbul ignore next */ []));
6628
- this.hasComponents = computed(() => (this.settings().components?.length ?? 0) > 0, /* @ts-ignore */
6801
+ /** Skeleton nur, solange noch nie etwas geladen wurde (auch nicht gepuffert) und kein statischer Inhalt da ist. */
6802
+ this.showSkeleton = computed(() => this.loading() && this._raw() == null && !this.loadedCard()
6803
+ && this.settings().data == null && !(this.settings().components?.length), /* @ts-ignore */
6804
+ ...(ngDevMode ? [{ debugName: "showSkeleton" }] : /* istanbul ignore next */ []));
6805
+ this.hasComponents = computed(() => (this.card().components?.length ?? 0) > 0, /* @ts-ignore */
6629
6806
  ...(ngDevMode ? [{ debugName: "hasComponents" }] : /* istanbul ignore next */ []));
6630
6807
  /** Resolves padding setting (token or free CSS value) into a CSS length string. */
6631
6808
  this.componentsPadding = computed(() => {
6632
- const v = this.settings().padding;
6809
+ const v = this.card().padding;
6633
6810
  if (!v)
6634
6811
  return 'var(--xiri-spacing-md, 16px)';
6635
6812
  switch (v) {
@@ -6648,12 +6825,12 @@ class XiriCardComponent {
6648
6825
  return null;
6649
6826
  const rt = {
6650
6827
  data: data,
6651
- fields: this.settings().fields,
6652
- dense: this.settings().dense,
6653
- forceMinWidth: this.settings().forceMinWidth,
6654
- showHeader: this.settings().showHeader,
6828
+ fields: this.card().fields,
6829
+ dense: this.card().dense,
6830
+ forceMinWidth: this.card().forceMinWidth,
6831
+ showHeader: this.card().showHeader,
6655
6832
  };
6656
- if (!this.settings().fields && data.length !== 0) {
6833
+ if (!this.card().fields && data.length !== 0) {
6657
6834
  const fields = [];
6658
6835
  if (Array.isArray(data)) {
6659
6836
  fields.push({
@@ -6709,19 +6886,28 @@ class XiriCardComponent {
6709
6886
  }
6710
6887
  /** Klick irgendwo im Header toggelt; Buttons/Links (Collapse, Reload, buttonsTop) behalten ihre eigene Aktion. */
6711
6888
  onHeaderClick(event) {
6712
- if (!this.settings().collapsible)
6889
+ if (!this.card().collapsible)
6713
6890
  return;
6714
6891
  if (event.target.closest('button, a'))
6715
6892
  return;
6716
6893
  this.toggleCollapse();
6717
6894
  }
6718
6895
  reload() {
6719
- if (this.loading())
6896
+ this.loader.reload();
6897
+ }
6898
+ /** refresh:'panel' aus Button/Tabelle in dieser Card. Ohne url: äußere Card, sonst Page-Reload. */
6899
+ reloadPanel() {
6900
+ if (!this.settings().url) {
6901
+ if (this.parentPanel)
6902
+ this.parentPanel.reloadPanel();
6903
+ else
6904
+ this.responseHandler.handle({ refresh: 'page' });
6720
6905
  return;
6721
- this.cardResource.reload();
6906
+ }
6907
+ this.loader.reloadOrQueue();
6722
6908
  }
6723
6909
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6724
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: XiriCardComponent, isStandalone: true, selector: "xiri-card", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<mat-card class=\"card mat-mdc-elevation-specific\" [class.mat-elevation-z2]=\"!settings().flat\" [class.flat]=\"settings().flat\">\n\t@if (showHeader()) {\n\t<mat-card-header (click)=\"onHeaderClick($event)\" [class.collapsible]=\"settings().collapsible\">\n\t\t@if (settings().headerIcon) {\n\t\t\t<div mat-card-avatar class=\"header-image\">\n\t\t\t\t<mat-icon [class]=\"settings().headerIconColor || 'primary'\">{{ settings().headerIcon }}</mat-icon>\n\t\t\t</div>\n\t\t}\n\t\t@if (settings().header) {\n\t\t\t<mat-card-title [class]=\"{hasHeaderSub: settings().headerSub}\">{{ settings().header }}</mat-card-title>\n\t\t}\n\t\t@if (settings().headerSub) {\n\t\t\t<mat-card-subtitle>{{ settings().headerSub }}</mat-card-subtitle>\n\t\t}\n\t\t@if (settings().buttonsTop) {\n\t\t\t<xiri-buttonline [settings]=\"settings().buttonsTop!\"></xiri-buttonline>\n\t\t}\n\t\t@if (settings().collapsible) {\n\t\t\t<button mat-icon-button (click)=\"toggleCollapse()\" class=\"collapse-btn\" aria-label=\"Auf-/Zuklappen\">\n\t\t\t\t<mat-icon>{{ isCollapsed() ? 'expand_more' : 'expand_less' }}</mat-icon>\n\t\t\t</button>\n\t\t}\n\t\t@if (settings().reload && settings().url) {\n\t\t\t<button mat-icon-button (click)=\"reload()\" [disabled]=\"loading()\" class=\"reload-btn\" aria-label=\"Neu laden\">\n\t\t\t\t<mat-icon [class.spinning]=\"loading()\">autorenew</mat-icon>\n\t\t\t</button>\n\t\t}\n\t</mat-card-header>\n\t}\n\t<div class=\"collapse-wrapper\" [class.collapsed]=\"isCollapsed()\">\n\t\t<div class=\"collapse-inner\">\n\t\t\t@if (loading() && !cardData()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<xiri-skeleton type=\"table-row\" [columns]=\"2\" [lines]=\"3\"></xiri-skeleton>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (errorMsg()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<div class=\"load-error\">{{ errorMsg() }}</div>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (hasComponents()) {\n\t\t\t\t<mat-card-content class=\"hasComponents\" [style.--xiri-card-padding]=\"componentsPadding()\">\n\t\t\t\t\t<xiri-dyncomponent [data]=\"settings().components!\" class=\"xrow\"></xiri-dyncomponent>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else {\n\t\t\t\t<mat-card-content class=\"hasTable\" [style.max-height]=\"settings().maxHeight || '50vh'\">\n\t\t\t\t\t@if (rawTable()) {\n\t\t\t\t\t\t<xiri-raw-table [settings]=\"rawTable()!\"></xiri-raw-table>\n\t\t\t\t\t}\n\t\t\t\t</mat-card-content>\n\t\t\t}\n\t\t\t@if (settings().buttonsBottom) {\n\t\t\t\t<mat-card-actions align=\"end\">\n\t\t\t\t\t<xiri-buttonline [settings]=\"settings().buttonsBottom!\"></xiri-buttonline>\n\t\t\t\t</mat-card-actions>\n\t\t\t}\n\t\t</div>\n\t</div>\n</mat-card>\n", styles: [":host{animation:fadeIn var(--xiri-duration-fast) var(--xiri-easing-standard)}.collapse-wrapper{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--xiri-duration-normal) var(--xiri-easing-standard)}.collapse-wrapper.collapsed{grid-template-rows:0fr}.collapse-inner{overflow:hidden;min-height:0}.spinning{animation:spin 1s linear infinite}.card{overflow:hidden}.card.flat{box-shadow:none;background:transparent;border-radius:0}.card.flat mat-card-header{box-shadow:none}.card mat-card-header{margin:0 0 2px;box-shadow:var(--xiri-shadow-xs);padding:4px 8px 4px 16px;align-items:center;min-height:32px}.card mat-card-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}.card mat-card-header .header-image{margin-bottom:0;width:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);align-items:center;display:flex}.card mat-card-header .header-image mat-icon{font-size:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);width:var(--xiri-icon-size-lg);color:var(--primary)}.card mat-card-header mat-card-title.hasHeaderSub{padding-top:2px}.card mat-card-header mat-card-subtitle{padding-bottom:2px}.card mat-card-header xiri-buttonline{display:flex;justify-content:flex-end;flex:1}.card mat-card-header xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-header xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .collapse-btn{margin-left:auto;width:32px;height:32px;padding:4px}.card .collapse-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .reload-btn{width:32px;height:32px;padding:4px}.card .reload-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card mat-card-content{padding:0}.card mat-card-content.hasTable{overflow-x:auto}.card mat-card-content.hasComponents{padding:var(--xiri-card-padding, var(--xiri-spacing-md, 16px))}@media(max-width:575.98px){.card mat-card-content.hasComponents{padding:8px}}.card mat-card-content xiri-skeleton{padding:16px}.card mat-card-content .load-error{padding:16px;color:var(--error, #B3261E)}.card mat-card-actions{padding:4px 8px;min-height:32px;border-top:1px solid var(--outline-variant, rgba(0, 0, 0, .12))}.card mat-card-actions xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-actions xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => MatCard), selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: i0.forwardRef(() => MatCardHeader), selector: "mat-card-header" }, { kind: "directive", type: i0.forwardRef(() => MatCardAvatar), selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "component", type: i0.forwardRef(() => MatIcon), selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i0.forwardRef(() => MatIconButton), selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i0.forwardRef(() => MatCardTitle), selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "directive", type: i0.forwardRef(() => MatCardSubtitle), selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "component", type: i0.forwardRef(() => XiriButtonlineComponent), selector: "xiri-buttonline", inputs: ["settings", "disabled", "filterData"], outputs: ["result"] }, { kind: "directive", type: i0.forwardRef(() => MatCardContent), selector: "mat-card-content" }, { kind: "component", type: i0.forwardRef(() => XiriRawTableComponent), selector: "xiri-raw-table", inputs: ["settings"] }, { kind: "component", type: i0.forwardRef(() => XiriSkeletonComponent), selector: "xiri-skeleton", inputs: ["type", "width", "height", "lines", "columns", "animate", "fill"] }, { kind: "directive", type: i0.forwardRef(() => MatCardActions), selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "component", type: i0.forwardRef(() => XiriDynComponentComponent), selector: "xiri-dyncomponent", inputs: ["data", "filterData", "dyncomponent"] }] }); }
6910
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: XiriCardComponent, isStandalone: true, selector: "xiri-card", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: true, transformFunction: null } }, providers: [{ provide: XIRI_PANEL_HOST, useExisting: forwardRef(() => XiriCardComponent) }], ngImport: i0, template: "<mat-card class=\"card mat-mdc-elevation-specific\" [class.mat-elevation-z2]=\"!card().flat\" [class.flat]=\"card().flat\">\n\t@if (showHeader()) {\n\t<mat-card-header (click)=\"onHeaderClick($event)\" [class.collapsible]=\"card().collapsible\">\n\t\t@if (card().headerIcon) {\n\t\t\t<div mat-card-avatar class=\"header-image\">\n\t\t\t\t<mat-icon [class]=\"card().headerIconColor || 'primary'\">{{ card().headerIcon }}</mat-icon>\n\t\t\t</div>\n\t\t}\n\t\t@if (card().header) {\n\t\t\t<mat-card-title [class]=\"{hasHeaderSub: card().headerSub}\">{{ card().header }}</mat-card-title>\n\t\t}\n\t\t@if (card().headerSub) {\n\t\t\t<mat-card-subtitle>{{ card().headerSub }}</mat-card-subtitle>\n\t\t}\n\t\t@if (card().buttonsTop) {\n\t\t\t<xiri-buttonline [settings]=\"card().buttonsTop!\"></xiri-buttonline>\n\t\t}\n\t\t@if (card().collapsible) {\n\t\t\t<button mat-icon-button (click)=\"toggleCollapse()\" class=\"collapse-btn\" aria-label=\"Auf-/Zuklappen\">\n\t\t\t\t<mat-icon>{{ isCollapsed() ? 'expand_more' : 'expand_less' }}</mat-icon>\n\t\t\t</button>\n\t\t}\n\t\t@if (card().reload && card().url) {\n\t\t\t<button mat-icon-button (click)=\"reload()\" [disabled]=\"loading()\" class=\"reload-btn\" aria-label=\"Neu laden\">\n\t\t\t\t<mat-icon [class.spinning]=\"loading()\">autorenew</mat-icon>\n\t\t\t</button>\n\t\t}\n\t</mat-card-header>\n\t}\n\t<div class=\"collapse-wrapper\" [class.collapsed]=\"isCollapsed()\">\n\t\t<div class=\"collapse-inner\">\n\t\t\t@if (showSkeleton()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<xiri-skeleton type=\"table-row\" [columns]=\"2\" [lines]=\"3\"></xiri-skeleton>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (errorMsg()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<div class=\"load-error\">{{ errorMsg() }}</div>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (hasComponents()) {\n\t\t\t\t<mat-card-content class=\"hasComponents\" [style.--xiri-card-padding]=\"componentsPadding()\">\n\t\t\t\t\t<xiri-dyncomponent [data]=\"card().components!\" class=\"xrow\"></xiri-dyncomponent>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else {\n\t\t\t\t<mat-card-content class=\"hasTable\" [style.max-height]=\"card().maxHeight || '50vh'\">\n\t\t\t\t\t@if (rawTable()) {\n\t\t\t\t\t\t<xiri-raw-table [settings]=\"rawTable()!\"></xiri-raw-table>\n\t\t\t\t\t}\n\t\t\t\t</mat-card-content>\n\t\t\t}\n\t\t\t@if (card().buttonsBottom) {\n\t\t\t\t<mat-card-actions align=\"end\">\n\t\t\t\t\t<xiri-buttonline [settings]=\"card().buttonsBottom!\"></xiri-buttonline>\n\t\t\t\t</mat-card-actions>\n\t\t\t}\n\t\t</div>\n\t</div>\n</mat-card>\n", styles: [":host{animation:fadeIn var(--xiri-duration-fast) var(--xiri-easing-standard)}.collapse-wrapper{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--xiri-duration-normal) var(--xiri-easing-standard)}.collapse-wrapper.collapsed{grid-template-rows:0fr}.collapse-inner{overflow:hidden;min-height:0}.spinning{animation:spin 1s linear infinite}.card{overflow:hidden}.card.flat{box-shadow:none;background:transparent;border-radius:0}.card.flat mat-card-header{box-shadow:none}.card mat-card-header{margin:0 0 2px;box-shadow:var(--xiri-shadow-xs);padding:4px 8px 4px 16px;align-items:center;min-height:32px}.card mat-card-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}.card mat-card-header .header-image{margin-bottom:0;width:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);align-items:center;display:flex}.card mat-card-header .header-image mat-icon{font-size:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);width:var(--xiri-icon-size-lg);color:var(--primary)}.card mat-card-header mat-card-title.hasHeaderSub{padding-top:2px}.card mat-card-header mat-card-subtitle{padding-bottom:2px}.card mat-card-header xiri-buttonline{display:flex;justify-content:flex-end;flex:1}.card mat-card-header xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-header xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .collapse-btn{margin-left:auto;width:32px;height:32px;padding:4px}.card .collapse-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .reload-btn{width:32px;height:32px;padding:4px}.card .reload-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card mat-card-content{padding:0}.card mat-card-content.hasTable{overflow-x:auto}.card mat-card-content.hasComponents{padding:var(--xiri-card-padding, var(--xiri-spacing-md, 16px))}@media(max-width:575.98px){.card mat-card-content.hasComponents{padding:8px}}.card mat-card-content xiri-skeleton{padding:16px}.card mat-card-content .load-error{padding:16px;color:var(--error, #B3261E)}.card mat-card-actions{padding:4px 8px;min-height:32px;border-top:1px solid var(--outline-variant, rgba(0, 0, 0, .12))}.card mat-card-actions xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-actions xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => MatCard), selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: i0.forwardRef(() => MatCardHeader), selector: "mat-card-header" }, { kind: "directive", type: i0.forwardRef(() => MatCardAvatar), selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "component", type: i0.forwardRef(() => MatIcon), selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i0.forwardRef(() => MatIconButton), selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i0.forwardRef(() => MatCardTitle), selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "directive", type: i0.forwardRef(() => MatCardSubtitle), selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "component", type: i0.forwardRef(() => XiriButtonlineComponent), selector: "xiri-buttonline", inputs: ["settings", "disabled", "filterData"], outputs: ["result"] }, { kind: "directive", type: i0.forwardRef(() => MatCardContent), selector: "mat-card-content" }, { kind: "component", type: i0.forwardRef(() => XiriRawTableComponent), selector: "xiri-raw-table", inputs: ["settings"] }, { kind: "component", type: i0.forwardRef(() => XiriSkeletonComponent), selector: "xiri-skeleton", inputs: ["type", "width", "height", "lines", "columns", "animate", "fill"] }, { kind: "directive", type: i0.forwardRef(() => MatCardActions), selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "component", type: i0.forwardRef(() => XiriDynComponentComponent), selector: "xiri-dyncomponent", inputs: ["data", "filterData", "dyncomponent"] }] }); }
6725
6911
  }
6726
6912
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriCardComponent, decorators: [{
6727
6913
  type: Component,
@@ -6737,7 +6923,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6737
6923
  XiriRawTableComponent,
6738
6924
  XiriSkeletonComponent,
6739
6925
  MatCardActions,
6740
- forwardRef(() => XiriDynComponentComponent)], template: "<mat-card class=\"card mat-mdc-elevation-specific\" [class.mat-elevation-z2]=\"!settings().flat\" [class.flat]=\"settings().flat\">\n\t@if (showHeader()) {\n\t<mat-card-header (click)=\"onHeaderClick($event)\" [class.collapsible]=\"settings().collapsible\">\n\t\t@if (settings().headerIcon) {\n\t\t\t<div mat-card-avatar class=\"header-image\">\n\t\t\t\t<mat-icon [class]=\"settings().headerIconColor || 'primary'\">{{ settings().headerIcon }}</mat-icon>\n\t\t\t</div>\n\t\t}\n\t\t@if (settings().header) {\n\t\t\t<mat-card-title [class]=\"{hasHeaderSub: settings().headerSub}\">{{ settings().header }}</mat-card-title>\n\t\t}\n\t\t@if (settings().headerSub) {\n\t\t\t<mat-card-subtitle>{{ settings().headerSub }}</mat-card-subtitle>\n\t\t}\n\t\t@if (settings().buttonsTop) {\n\t\t\t<xiri-buttonline [settings]=\"settings().buttonsTop!\"></xiri-buttonline>\n\t\t}\n\t\t@if (settings().collapsible) {\n\t\t\t<button mat-icon-button (click)=\"toggleCollapse()\" class=\"collapse-btn\" aria-label=\"Auf-/Zuklappen\">\n\t\t\t\t<mat-icon>{{ isCollapsed() ? 'expand_more' : 'expand_less' }}</mat-icon>\n\t\t\t</button>\n\t\t}\n\t\t@if (settings().reload && settings().url) {\n\t\t\t<button mat-icon-button (click)=\"reload()\" [disabled]=\"loading()\" class=\"reload-btn\" aria-label=\"Neu laden\">\n\t\t\t\t<mat-icon [class.spinning]=\"loading()\">autorenew</mat-icon>\n\t\t\t</button>\n\t\t}\n\t</mat-card-header>\n\t}\n\t<div class=\"collapse-wrapper\" [class.collapsed]=\"isCollapsed()\">\n\t\t<div class=\"collapse-inner\">\n\t\t\t@if (loading() && !cardData()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<xiri-skeleton type=\"table-row\" [columns]=\"2\" [lines]=\"3\"></xiri-skeleton>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (errorMsg()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<div class=\"load-error\">{{ errorMsg() }}</div>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (hasComponents()) {\n\t\t\t\t<mat-card-content class=\"hasComponents\" [style.--xiri-card-padding]=\"componentsPadding()\">\n\t\t\t\t\t<xiri-dyncomponent [data]=\"settings().components!\" class=\"xrow\"></xiri-dyncomponent>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else {\n\t\t\t\t<mat-card-content class=\"hasTable\" [style.max-height]=\"settings().maxHeight || '50vh'\">\n\t\t\t\t\t@if (rawTable()) {\n\t\t\t\t\t\t<xiri-raw-table [settings]=\"rawTable()!\"></xiri-raw-table>\n\t\t\t\t\t}\n\t\t\t\t</mat-card-content>\n\t\t\t}\n\t\t\t@if (settings().buttonsBottom) {\n\t\t\t\t<mat-card-actions align=\"end\">\n\t\t\t\t\t<xiri-buttonline [settings]=\"settings().buttonsBottom!\"></xiri-buttonline>\n\t\t\t\t</mat-card-actions>\n\t\t\t}\n\t\t</div>\n\t</div>\n</mat-card>\n", styles: [":host{animation:fadeIn var(--xiri-duration-fast) var(--xiri-easing-standard)}.collapse-wrapper{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--xiri-duration-normal) var(--xiri-easing-standard)}.collapse-wrapper.collapsed{grid-template-rows:0fr}.collapse-inner{overflow:hidden;min-height:0}.spinning{animation:spin 1s linear infinite}.card{overflow:hidden}.card.flat{box-shadow:none;background:transparent;border-radius:0}.card.flat mat-card-header{box-shadow:none}.card mat-card-header{margin:0 0 2px;box-shadow:var(--xiri-shadow-xs);padding:4px 8px 4px 16px;align-items:center;min-height:32px}.card mat-card-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}.card mat-card-header .header-image{margin-bottom:0;width:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);align-items:center;display:flex}.card mat-card-header .header-image mat-icon{font-size:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);width:var(--xiri-icon-size-lg);color:var(--primary)}.card mat-card-header mat-card-title.hasHeaderSub{padding-top:2px}.card mat-card-header mat-card-subtitle{padding-bottom:2px}.card mat-card-header xiri-buttonline{display:flex;justify-content:flex-end;flex:1}.card mat-card-header xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-header xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .collapse-btn{margin-left:auto;width:32px;height:32px;padding:4px}.card .collapse-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .reload-btn{width:32px;height:32px;padding:4px}.card .reload-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card mat-card-content{padding:0}.card mat-card-content.hasTable{overflow-x:auto}.card mat-card-content.hasComponents{padding:var(--xiri-card-padding, var(--xiri-spacing-md, 16px))}@media(max-width:575.98px){.card mat-card-content.hasComponents{padding:8px}}.card mat-card-content xiri-skeleton{padding:16px}.card mat-card-content .load-error{padding:16px;color:var(--error, #B3261E)}.card mat-card-actions{padding:4px 8px;min-height:32px;border-top:1px solid var(--outline-variant, rgba(0, 0, 0, .12))}.card mat-card-actions xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-actions xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}\n"] }]
6926
+ forwardRef(() => XiriDynComponentComponent)], providers: [{ provide: XIRI_PANEL_HOST, useExisting: forwardRef(() => XiriCardComponent) }], template: "<mat-card class=\"card mat-mdc-elevation-specific\" [class.mat-elevation-z2]=\"!card().flat\" [class.flat]=\"card().flat\">\n\t@if (showHeader()) {\n\t<mat-card-header (click)=\"onHeaderClick($event)\" [class.collapsible]=\"card().collapsible\">\n\t\t@if (card().headerIcon) {\n\t\t\t<div mat-card-avatar class=\"header-image\">\n\t\t\t\t<mat-icon [class]=\"card().headerIconColor || 'primary'\">{{ card().headerIcon }}</mat-icon>\n\t\t\t</div>\n\t\t}\n\t\t@if (card().header) {\n\t\t\t<mat-card-title [class]=\"{hasHeaderSub: card().headerSub}\">{{ card().header }}</mat-card-title>\n\t\t}\n\t\t@if (card().headerSub) {\n\t\t\t<mat-card-subtitle>{{ card().headerSub }}</mat-card-subtitle>\n\t\t}\n\t\t@if (card().buttonsTop) {\n\t\t\t<xiri-buttonline [settings]=\"card().buttonsTop!\"></xiri-buttonline>\n\t\t}\n\t\t@if (card().collapsible) {\n\t\t\t<button mat-icon-button (click)=\"toggleCollapse()\" class=\"collapse-btn\" aria-label=\"Auf-/Zuklappen\">\n\t\t\t\t<mat-icon>{{ isCollapsed() ? 'expand_more' : 'expand_less' }}</mat-icon>\n\t\t\t</button>\n\t\t}\n\t\t@if (card().reload && card().url) {\n\t\t\t<button mat-icon-button (click)=\"reload()\" [disabled]=\"loading()\" class=\"reload-btn\" aria-label=\"Neu laden\">\n\t\t\t\t<mat-icon [class.spinning]=\"loading()\">autorenew</mat-icon>\n\t\t\t</button>\n\t\t}\n\t</mat-card-header>\n\t}\n\t<div class=\"collapse-wrapper\" [class.collapsed]=\"isCollapsed()\">\n\t\t<div class=\"collapse-inner\">\n\t\t\t@if (showSkeleton()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<xiri-skeleton type=\"table-row\" [columns]=\"2\" [lines]=\"3\"></xiri-skeleton>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (errorMsg()) {\n\t\t\t\t<mat-card-content>\n\t\t\t\t\t<div class=\"load-error\">{{ errorMsg() }}</div>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else if (hasComponents()) {\n\t\t\t\t<mat-card-content class=\"hasComponents\" [style.--xiri-card-padding]=\"componentsPadding()\">\n\t\t\t\t\t<xiri-dyncomponent [data]=\"card().components!\" class=\"xrow\"></xiri-dyncomponent>\n\t\t\t\t</mat-card-content>\n\t\t\t} @else {\n\t\t\t\t<mat-card-content class=\"hasTable\" [style.max-height]=\"card().maxHeight || '50vh'\">\n\t\t\t\t\t@if (rawTable()) {\n\t\t\t\t\t\t<xiri-raw-table [settings]=\"rawTable()!\"></xiri-raw-table>\n\t\t\t\t\t}\n\t\t\t\t</mat-card-content>\n\t\t\t}\n\t\t\t@if (card().buttonsBottom) {\n\t\t\t\t<mat-card-actions align=\"end\">\n\t\t\t\t\t<xiri-buttonline [settings]=\"card().buttonsBottom!\"></xiri-buttonline>\n\t\t\t\t</mat-card-actions>\n\t\t\t}\n\t\t</div>\n\t</div>\n</mat-card>\n", styles: [":host{animation:fadeIn var(--xiri-duration-fast) var(--xiri-easing-standard)}.collapse-wrapper{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--xiri-duration-normal) var(--xiri-easing-standard)}.collapse-wrapper.collapsed{grid-template-rows:0fr}.collapse-inner{overflow:hidden;min-height:0}.spinning{animation:spin 1s linear infinite}.card{overflow:hidden}.card.flat{box-shadow:none;background:transparent;border-radius:0}.card.flat mat-card-header{box-shadow:none}.card mat-card-header{margin:0 0 2px;box-shadow:var(--xiri-shadow-xs);padding:4px 8px 4px 16px;align-items:center;min-height:32px}.card mat-card-header.collapsible{cursor:pointer;-webkit-user-select:none;user-select:none}.card mat-card-header .header-image{margin-bottom:0;width:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);align-items:center;display:flex}.card mat-card-header .header-image mat-icon{font-size:var(--xiri-icon-size-lg);height:var(--xiri-icon-size-lg);width:var(--xiri-icon-size-lg);color:var(--primary)}.card mat-card-header mat-card-title.hasHeaderSub{padding-top:2px}.card mat-card-header mat-card-subtitle{padding-bottom:2px}.card mat-card-header xiri-buttonline{display:flex;justify-content:flex-end;flex:1}.card mat-card-header xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-header xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .collapse-btn{margin-left:auto;width:32px;height:32px;padding:4px}.card .collapse-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card .reload-btn{width:32px;height:32px;padding:4px}.card .reload-btn mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.card mat-card-content{padding:0}.card mat-card-content.hasTable{overflow-x:auto}.card mat-card-content.hasComponents{padding:var(--xiri-card-padding, var(--xiri-spacing-md, 16px))}@media(max-width:575.98px){.card mat-card-content.hasComponents{padding:8px}}.card mat-card-content xiri-skeleton{padding:16px}.card mat-card-content .load-error{padding:16px;color:var(--error, #B3261E)}.card mat-card-actions{padding:4px 8px;min-height:32px;border-top:1px solid var(--outline-variant, rgba(0, 0, 0, .12))}.card mat-card-actions xiri-buttonline ::ng-deep button{width:32px;height:32px;padding:4px}.card mat-card-actions xiri-buttonline ::ng-deep button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}\n"] }]
6741
6927
  }], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: true }] }] } });
6742
6928
 
6743
6929
  class XiriTabsComponent {
@@ -6795,6 +6981,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6795
6981
  ], template: "<mat-tab-group\n\t[selectedIndex]=\"selectedIndex()\"\n\t[dynamicHeight]=\"settings().dynamicHeight ?? false\"\n\t[animationDuration]=\"settings().animationDuration ?? '225ms'\"\n\t[headerPosition]=\"settings().headerPosition ?? 'above'\"\n\t[mat-align-tabs]=\"settings().alignTabs ?? 'start'\"\n\t[mat-stretch-tabs]=\"settings().stretchTabs ?? false\"\n\t(selectedIndexChange)=\"onTabChange($event)\">\n\n\t@for (tab of settings().tabs; track tab.label; let i = $index) {\n\t\t<mat-tab [disabled]=\"tab.disabled ?? false\" [bodyClass]=\"tab.noPadding ? 'xiri-tab-no-padding' : ''\">\n\t\t\t<ng-template mat-tab-label>\n\t\t\t\t@if (tab.icon) {\n\t\t\t\t\t<mat-icon>{{ tab.icon }}</mat-icon>\n\t\t\t\t}\n\t\t\t\t{{ tab.label }}\n\t\t\t</ng-template>\n\n\t\t\t@if (shouldRenderContent(i, tab)) {\n\t\t\t\t<ng-container *ngTemplateOutlet=\"dyncomponent(); context: { $implicit: { data: tab.data, filterData: filterData() } }\"></ng-container>\n\t\t\t}\n\t\t</mat-tab>\n\t}\n</mat-tab-group>\n", styles: [":host{display:block}mat-icon{margin-right:8px}\n"] }]
6796
6982
  }], ctorParameters: () => [], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: true }] }], filterData: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterData", required: false }] }], dyncomponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "dyncomponent", required: false }] }] } });
6797
6983
 
6984
+ /**
6985
+ * Macht ein mat-expansion-panel zum Panel-Host für refresh:'panel' und lädt es bei gesetzter url nach.
6986
+ * Sitzt als Directive direkt auf dem Material-Panel, damit der Element-Injector des Panels den Token trägt:
6987
+ * Header-Buttons und (über ngTemplateOutletInjector) der Inhalt finden so genau dieses Panel.
6988
+ */
6989
+ class XiriExpansionPanelDirective {
6990
+ constructor() {
6991
+ /**
6992
+ * Shell-Settings des Panels aus XiriExpansionSettings.panels. Nicht `required`: der Loader-Effect einer Directive
6993
+ * läuft in der Host-View und kann vor dem ersten Setzen der Inputs feuern (NG0950) – der leere Default hat keine url.
6994
+ */
6995
+ this.settings = input({ title: '', data: [] }, { ...(ngDevMode ? { debugName: "settings" } : /* istanbul ignore next */ {}), alias: 'xiriExpansionPanel' });
6996
+ /** Element-Injector des Panels – als ngTemplateOutletInjector für den Inhalt, sonst löst der über die deklarierende View auf. */
6997
+ this.injector = inject(Injector);
6998
+ this.responseHandler = inject(XiriResponseHandlerService);
6999
+ // Nächster äußerer Host (z. B. eine url-Card um das Akkordeon). Ziel für refresh:'panel', wenn dieses Panel keine url hat.
7000
+ // Innerhalb eingebetteter Views überspringt skipSelf Zwischenknoten – ein Reload landet dann höchstens zu grob, nie falsch.
7001
+ this.parentPanel = inject(XIRI_PANEL_HOST, { optional: true, skipSelf: true });
7002
+ // ponytail: lädt beim Init, unabhängig von lazy. Upgrade: params erst setzen, wenn das Panel zum ersten Mal offen war.
7003
+ this.loader = createPanelLoader({ url: () => this.settings().url, key: 'panel' });
7004
+ this.loading = this.loader.loading;
7005
+ this.errorMsg = this.loader.errorMsg;
7006
+ /**
7007
+ * Shell, überlagert von title/description/icon/buttons/data der letzten Antwort.
7008
+ * expanded/disabled/lazy/unload bleiben Shell-Werte – sonst klappte ein Reload ohne `expanded` das Panel zu.
7009
+ */
7010
+ this.panel = computed(() => {
7011
+ const s = this.settings();
7012
+ const l = this.loader.loaded();
7013
+ if (!l)
7014
+ return s;
7015
+ return { ...s, title: l.title, description: l.description, icon: l.icon, buttons: l.buttons, data: l.data ?? [] };
7016
+ }, /* @ts-ignore */
7017
+ ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
7018
+ /** Skeleton nur, solange noch nie etwas geladen wurde (auch nicht gepuffert) und die Shell keinen Inhalt hat. */
7019
+ this.showSkeleton = computed(() => this.loading() && this.loader.raw() == null && !this.loader.loaded()
7020
+ && !(this.settings().data?.length), /* @ts-ignore */
7021
+ ...(ngDevMode ? [{ debugName: "showSkeleton" }] : /* istanbul ignore next */ []));
7022
+ }
7023
+ /** refresh:'panel' aus Header-Button, Inhalt oder Tabelle in diesem Panel. Ohne url: äußerer Host, sonst Page-Reload. */
7024
+ reloadPanel() {
7025
+ if (!this.settings().url) {
7026
+ if (this.parentPanel)
7027
+ this.parentPanel.reloadPanel();
7028
+ else
7029
+ this.responseHandler.handle({ refresh: 'page' });
7030
+ return;
7031
+ }
7032
+ this.loader.reloadOrQueue();
7033
+ }
7034
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriExpansionPanelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
7035
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.5", type: XiriExpansionPanelDirective, isStandalone: true, selector: "mat-expansion-panel[xiriExpansionPanel]", inputs: { settings: { classPropertyName: "settings", publicName: "xiriExpansionPanel", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: XIRI_PANEL_HOST, useExisting: forwardRef(() => XiriExpansionPanelDirective) }], exportAs: ["xiriExpansionPanel"], ngImport: i0 }); }
7036
+ }
7037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriExpansionPanelDirective, decorators: [{
7038
+ type: Directive,
7039
+ args: [{
7040
+ selector: 'mat-expansion-panel[xiriExpansionPanel]',
7041
+ exportAs: 'xiriExpansionPanel',
7042
+ providers: [{ provide: XIRI_PANEL_HOST, useExisting: forwardRef(() => XiriExpansionPanelDirective) }],
7043
+ }]
7044
+ }], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "xiriExpansionPanel", required: false }] }] } });
7045
+
6798
7046
  class XiriExpansionComponent {
6799
7047
  constructor() {
6800
7048
  this.settings = input.required(/* @ts-ignore */
@@ -6846,7 +7094,7 @@ class XiriExpansionComponent {
6846
7094
  return this.visitedPanels().has(index);
6847
7095
  }
6848
7096
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriExpansionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6849
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: XiriExpansionComponent, isStandalone: true, selector: "xiri-expansion", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: true, transformFunction: null }, filterData: { classPropertyName: "filterData", publicName: "filterData", isSignal: true, isRequired: false, transformFunction: null }, dyncomponent: { classPropertyName: "dyncomponent", publicName: "dyncomponent", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-accordion\n\t[multi]=\"settings().multi ?? false\"\n\t[displayMode]=\"settings().displayMode ?? 'default'\"\n\t[hideToggle]=\"settings().hideToggle ?? false\"\n\t[togglePosition]=\"settings().togglePosition ?? 'after'\">\n\n\t@for (panel of settings().panels; track panel.title; let i = $index) {\n\t\t<mat-expansion-panel\n\t\t\t[class.flat-content]=\"hasFlatContent(panel)\"\n\t\t\t[disabled]=\"panel.disabled ?? false\"\n\t\t\t[expanded]=\"panel.expanded ?? false\"\n\t\t\t(opened)=\"onPanelOpened(i)\"\n\t\t\t(closed)=\"onPanelClosed(i)\">\n\n\t\t\t<mat-expansion-panel-header>\n\t\t\t\t@if (panel.icon) {\n\t\t\t\t\t<mat-icon>{{ panel.icon }}</mat-icon>\n\t\t\t\t}\n\t\t\t\t<mat-panel-title>{{ panel.title }}</mat-panel-title>\n\t\t\t\t@if (panel.description) {\n\t\t\t\t\t<mat-panel-description>{{ panel.description }}</mat-panel-description>\n\t\t\t\t}\n\t\t\t\t@if (panel.buttons) {\n\t\t\t\t\t<xiri-buttonline class=\"panel-buttons\" [settings]=\"panel.buttons\" [filterData]=\"filterData()\"\n\t\t\t\t\t\t(click)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"></xiri-buttonline>\n\t\t\t\t}\n\t\t\t</mat-expansion-panel-header>\n\n\t\t\t@if (shouldRenderContent(i, panel)) {\n\t\t\t\t<ng-container *ngTemplateOutlet=\"dyncomponent(); context: { $implicit: { data: panel.data, filterData: filterData() } }\"></ng-container>\n\t\t\t}\n\t\t</mat-expansion-panel>\n\t}\n</mat-accordion>\n", styles: [":host{display:block}mat-icon{margin-right:8px;align-self:center}.panel-buttons{display:flex;align-items:center;justify-content:flex-end;margin-left:auto;margin-right:16px}.panel-buttons ::ng-deep .buttonline{display:flex;align-items:center}.panel-buttons ::ng-deep button.mat-mdc-icon-button{width:32px;height:32px;padding:4px}.panel-buttons ::ng-deep button.mat-mdc-icon-button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.panel-buttons ::ng-deep button.mat-mdc-button-base:not(.mat-mdc-icon-button){height:32px}mat-expansion-panel.flat-content ::ng-deep .mat-expansion-panel-body{padding-left:12px;padding-right:12px}\n"], dependencies: [{ kind: "directive", type: MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { 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: MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: XiriButtonlineComponent, selector: "xiri-buttonline", inputs: ["settings", "disabled", "filterData"], outputs: ["result"] }] }); }
7097
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: XiriExpansionComponent, isStandalone: true, selector: "xiri-expansion", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: true, transformFunction: null }, filterData: { classPropertyName: "filterData", publicName: "filterData", isSignal: true, isRequired: false, transformFunction: null }, dyncomponent: { classPropertyName: "dyncomponent", publicName: "dyncomponent", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mat-accordion\n\t[multi]=\"settings().multi ?? false\"\n\t[displayMode]=\"settings().displayMode ?? 'default'\"\n\t[hideToggle]=\"settings().hideToggle ?? false\"\n\t[togglePosition]=\"settings().togglePosition ?? 'after'\">\n\n\t@for (panel of settings().panels; track $index; let i = $index) {\n\t\t<mat-expansion-panel\n\t\t\t[xiriExpansionPanel]=\"panel\" #p=\"xiriExpansionPanel\"\n\t\t\t[class.flat-content]=\"hasFlatContent(p.panel())\"\n\t\t\t[disabled]=\"panel.disabled ?? false\"\n\t\t\t[expanded]=\"panel.expanded ?? false\"\n\t\t\t(opened)=\"onPanelOpened(i)\"\n\t\t\t(closed)=\"onPanelClosed(i)\">\n\n\t\t\t<mat-expansion-panel-header>\n\t\t\t\t@if (p.panel().icon) {\n\t\t\t\t\t<mat-icon>{{ p.panel().icon }}</mat-icon>\n\t\t\t\t}\n\t\t\t\t<mat-panel-title>{{ p.panel().title }}</mat-panel-title>\n\t\t\t\t@if (p.panel().description) {\n\t\t\t\t\t<mat-panel-description>{{ p.panel().description }}</mat-panel-description>\n\t\t\t\t}\n\t\t\t\t@if (p.panel().buttons) {\n\t\t\t\t\t<xiri-buttonline class=\"panel-buttons\" [settings]=\"p.panel().buttons!\" [filterData]=\"filterData()\"\n\t\t\t\t\t\t(click)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"></xiri-buttonline>\n\t\t\t\t}\n\t\t\t</mat-expansion-panel-header>\n\n\t\t\t@if (p.showSkeleton()) {\n\t\t\t\t<xiri-skeleton type=\"text\" [lines]=\"3\"></xiri-skeleton>\n\t\t\t} @else if (p.errorMsg()) {\n\t\t\t\t<div class=\"load-error\">{{ p.errorMsg() }}</div>\n\t\t\t} @else if (shouldRenderContent(i, panel)) {\n\t\t\t\t<!-- injector: Element-Injector des Panels, sonst f\u00E4nde ein Button im Inhalt (eingebettete View) das Panel nicht. -->\n\t\t\t\t<ng-container *ngTemplateOutlet=\"dyncomponent();\n\t\t\t\t\tcontext: { $implicit: { data: p.panel().data ?? [], filterData: filterData() } };\n\t\t\t\t\tinjector: p.injector\"></ng-container>\n\t\t\t}\n\t\t</mat-expansion-panel>\n\t}\n</mat-accordion>\n", styles: [":host{display:block}mat-icon{margin-right:8px;align-self:center}.panel-buttons{display:flex;align-items:center;justify-content:flex-end;margin-left:auto;margin-right:16px}.panel-buttons ::ng-deep .buttonline{display:flex;align-items:center}.panel-buttons ::ng-deep button.mat-mdc-icon-button{width:32px;height:32px;padding:4px}.panel-buttons ::ng-deep button.mat-mdc-icon-button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.panel-buttons ::ng-deep button.mat-mdc-button-base:not(.mat-mdc-icon-button){height:32px}.load-error{padding:16px;color:var(--error, #B3261E)}mat-expansion-panel.flat-content ::ng-deep .mat-expansion-panel-body{padding-left:12px;padding-right:12px}\n"], dependencies: [{ kind: "directive", type: MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { 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: MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: XiriButtonlineComponent, selector: "xiri-buttonline", inputs: ["settings", "disabled", "filterData"], outputs: ["result"] }, { kind: "component", type: XiriSkeletonComponent, selector: "xiri-skeleton", inputs: ["type", "width", "height", "lines", "columns", "animate", "fill"] }, { kind: "directive", type: XiriExpansionPanelDirective, selector: "mat-expansion-panel[xiriExpansionPanel]", inputs: ["xiriExpansionPanel"], exportAs: ["xiriExpansionPanel"] }] }); }
6850
7098
  }
6851
7099
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: XiriExpansionComponent, decorators: [{
6852
7100
  type: Component,
@@ -6857,8 +7105,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.5", ngImpor
6857
7105
  MatExpansionPanelTitle,
6858
7106
  MatExpansionPanelDescription,
6859
7107
  MatIcon,
6860
- NgTemplateOutlet, XiriButtonlineComponent
6861
- ], template: "<mat-accordion\n\t[multi]=\"settings().multi ?? false\"\n\t[displayMode]=\"settings().displayMode ?? 'default'\"\n\t[hideToggle]=\"settings().hideToggle ?? false\"\n\t[togglePosition]=\"settings().togglePosition ?? 'after'\">\n\n\t@for (panel of settings().panels; track panel.title; let i = $index) {\n\t\t<mat-expansion-panel\n\t\t\t[class.flat-content]=\"hasFlatContent(panel)\"\n\t\t\t[disabled]=\"panel.disabled ?? false\"\n\t\t\t[expanded]=\"panel.expanded ?? false\"\n\t\t\t(opened)=\"onPanelOpened(i)\"\n\t\t\t(closed)=\"onPanelClosed(i)\">\n\n\t\t\t<mat-expansion-panel-header>\n\t\t\t\t@if (panel.icon) {\n\t\t\t\t\t<mat-icon>{{ panel.icon }}</mat-icon>\n\t\t\t\t}\n\t\t\t\t<mat-panel-title>{{ panel.title }}</mat-panel-title>\n\t\t\t\t@if (panel.description) {\n\t\t\t\t\t<mat-panel-description>{{ panel.description }}</mat-panel-description>\n\t\t\t\t}\n\t\t\t\t@if (panel.buttons) {\n\t\t\t\t\t<xiri-buttonline class=\"panel-buttons\" [settings]=\"panel.buttons\" [filterData]=\"filterData()\"\n\t\t\t\t\t\t(click)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"></xiri-buttonline>\n\t\t\t\t}\n\t\t\t</mat-expansion-panel-header>\n\n\t\t\t@if (shouldRenderContent(i, panel)) {\n\t\t\t\t<ng-container *ngTemplateOutlet=\"dyncomponent(); context: { $implicit: { data: panel.data, filterData: filterData() } }\"></ng-container>\n\t\t\t}\n\t\t</mat-expansion-panel>\n\t}\n</mat-accordion>\n", styles: [":host{display:block}mat-icon{margin-right:8px;align-self:center}.panel-buttons{display:flex;align-items:center;justify-content:flex-end;margin-left:auto;margin-right:16px}.panel-buttons ::ng-deep .buttonline{display:flex;align-items:center}.panel-buttons ::ng-deep button.mat-mdc-icon-button{width:32px;height:32px;padding:4px}.panel-buttons ::ng-deep button.mat-mdc-icon-button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.panel-buttons ::ng-deep button.mat-mdc-button-base:not(.mat-mdc-icon-button){height:32px}mat-expansion-panel.flat-content ::ng-deep .mat-expansion-panel-body{padding-left:12px;padding-right:12px}\n"] }]
7108
+ NgTemplateOutlet, XiriButtonlineComponent, XiriSkeletonComponent, XiriExpansionPanelDirective
7109
+ ], template: "<mat-accordion\n\t[multi]=\"settings().multi ?? false\"\n\t[displayMode]=\"settings().displayMode ?? 'default'\"\n\t[hideToggle]=\"settings().hideToggle ?? false\"\n\t[togglePosition]=\"settings().togglePosition ?? 'after'\">\n\n\t@for (panel of settings().panels; track $index; let i = $index) {\n\t\t<mat-expansion-panel\n\t\t\t[xiriExpansionPanel]=\"panel\" #p=\"xiriExpansionPanel\"\n\t\t\t[class.flat-content]=\"hasFlatContent(p.panel())\"\n\t\t\t[disabled]=\"panel.disabled ?? false\"\n\t\t\t[expanded]=\"panel.expanded ?? false\"\n\t\t\t(opened)=\"onPanelOpened(i)\"\n\t\t\t(closed)=\"onPanelClosed(i)\">\n\n\t\t\t<mat-expansion-panel-header>\n\t\t\t\t@if (p.panel().icon) {\n\t\t\t\t\t<mat-icon>{{ p.panel().icon }}</mat-icon>\n\t\t\t\t}\n\t\t\t\t<mat-panel-title>{{ p.panel().title }}</mat-panel-title>\n\t\t\t\t@if (p.panel().description) {\n\t\t\t\t\t<mat-panel-description>{{ p.panel().description }}</mat-panel-description>\n\t\t\t\t}\n\t\t\t\t@if (p.panel().buttons) {\n\t\t\t\t\t<xiri-buttonline class=\"panel-buttons\" [settings]=\"p.panel().buttons!\" [filterData]=\"filterData()\"\n\t\t\t\t\t\t(click)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"></xiri-buttonline>\n\t\t\t\t}\n\t\t\t</mat-expansion-panel-header>\n\n\t\t\t@if (p.showSkeleton()) {\n\t\t\t\t<xiri-skeleton type=\"text\" [lines]=\"3\"></xiri-skeleton>\n\t\t\t} @else if (p.errorMsg()) {\n\t\t\t\t<div class=\"load-error\">{{ p.errorMsg() }}</div>\n\t\t\t} @else if (shouldRenderContent(i, panel)) {\n\t\t\t\t<!-- injector: Element-Injector des Panels, sonst f\u00E4nde ein Button im Inhalt (eingebettete View) das Panel nicht. -->\n\t\t\t\t<ng-container *ngTemplateOutlet=\"dyncomponent();\n\t\t\t\t\tcontext: { $implicit: { data: p.panel().data ?? [], filterData: filterData() } };\n\t\t\t\t\tinjector: p.injector\"></ng-container>\n\t\t\t}\n\t\t</mat-expansion-panel>\n\t}\n</mat-accordion>\n", styles: [":host{display:block}mat-icon{margin-right:8px;align-self:center}.panel-buttons{display:flex;align-items:center;justify-content:flex-end;margin-left:auto;margin-right:16px}.panel-buttons ::ng-deep .buttonline{display:flex;align-items:center}.panel-buttons ::ng-deep button.mat-mdc-icon-button{width:32px;height:32px;padding:4px}.panel-buttons ::ng-deep button.mat-mdc-icon-button mat-icon{font-size:var(--xiri-icon-size-md);width:var(--xiri-icon-size-md);height:var(--xiri-icon-size-md)}.panel-buttons ::ng-deep button.mat-mdc-button-base:not(.mat-mdc-icon-button){height:32px}.load-error{padding:16px;color:var(--error, #B3261E)}mat-expansion-panel.flat-content ::ng-deep .mat-expansion-panel-body{padding-left:12px;padding-right:12px}\n"] }]
6862
7110
  }], propDecorators: { settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: true }] }], filterData: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterData", required: false }] }], dyncomponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "dyncomponent", required: false }] }] } });
6863
7111
 
6864
7112
  class XiriStatComponent {
@@ -8933,5 +9181,5 @@ function provideXiriServices(config) {
8933
9181
  * Generated bundle index. Do not edit.
8934
9182
  */
8935
9183
 
8936
- export { COLOR_CSS_VAR, DEFAULT_COMPARE, DEFAULT_PREDICATE, FALLBACK_COLORS, SafehtmlPipe, ThemeService, XiriAlertComponent, XiriBarChartComponent, XiriBreadcrumbComponent, XiriBulletChartComponent, XiriButtonComponent, XiriButtonlineComponent, XiriButtonstyleComponent, XiriCalendarComponent, XiriCalloutComponent, XiriCardComponent, XiriCardlinkComponent, XiriColsDirective, XiriDataService, XiriDataServiceConfig, XiriDescriptionListComponent, XiriDialogComponent, XiriDividerComponent, XiriDoneComponent, XiriDownloadService, XiriDynComponentComponent, XiriEchartsHostComponent, XiriEmptyStateComponent, XiriErrorComponent, XiriExpansionComponent, XiriFormComponent, XiriFormFieldsComponent, XiriFormService, XiriGanttComponent, XiriGaugeChartComponent, XiriHeaderComponent, XiriHeatmapComponent, XiriImagetextComponent, XiriInfopointComponent, XiriLineChartComponent, XiriLinksComponent, XiriListComponent, XiriLocalStorageService, XiriLocaleService, XiriMultiStatComponent, XiriMultiprogressComponent, XiriPageHeaderComponent, XiriPieChartComponent, XiriProgressComponent, XiriQueryComponent, XiriRawTableComponent, XiriResponseHandlerService, XiriSankeyComponent, XiriSearchComponent, XiriSectionComponent, XiriSelectDirective, XiriSessionStorageService, XiriSidenavComponent, XiriSidepanelComponent, XiriSidepanelRef, XiriSidepanelService, XiriSkeletonComponent, XiriSnackbarService, XiriStatComponent, XiriStatGridComponent, XiriStatusComponent, XiriStepperComponent, XiriTableComponent, XiriTabsComponent, XiriTimelineComponent, XiriToolbarComponent, XiriTreeComponent, XiriUrlPipe, colsToClasses, defaultXiriDataServiceConfig, escapeHtml, notifyThemeChanged, provideXiriServices, resolveColor };
9184
+ export { COLOR_CSS_VAR, DEFAULT_COMPARE, DEFAULT_PREDICATE, FALLBACK_COLORS, SafehtmlPipe, ThemeService, XIRI_PANEL_HOST, XiriAlertComponent, XiriBarChartComponent, XiriBreadcrumbComponent, XiriBulletChartComponent, XiriButtonComponent, XiriButtonlineComponent, XiriButtonstyleComponent, XiriCalendarComponent, XiriCalloutComponent, XiriCardComponent, XiriCardlinkComponent, XiriColsDirective, XiriDataService, XiriDataServiceConfig, XiriDescriptionListComponent, XiriDialogComponent, XiriDividerComponent, XiriDoneComponent, XiriDownloadService, XiriDynComponentComponent, XiriEchartsHostComponent, XiriEmptyStateComponent, XiriErrorComponent, XiriExpansionComponent, XiriExpansionPanelDirective, XiriFormComponent, XiriFormFieldsComponent, XiriFormService, XiriGanttComponent, XiriGaugeChartComponent, XiriHeaderComponent, XiriHeatmapComponent, XiriImagetextComponent, XiriInfopointComponent, XiriLineChartComponent, XiriLinksComponent, XiriListComponent, XiriLocalStorageService, XiriLocaleService, XiriMultiStatComponent, XiriMultiprogressComponent, XiriPageHeaderComponent, XiriPieChartComponent, XiriProgressComponent, XiriQueryComponent, XiriRawTableComponent, XiriResponseHandlerService, XiriSankeyComponent, XiriSearchComponent, XiriSectionComponent, XiriSelectDirective, XiriSessionStorageService, XiriSidenavComponent, XiriSidepanelComponent, XiriSidepanelRef, XiriSidepanelService, XiriSkeletonComponent, XiriSnackbarService, XiriStatComponent, XiriStatGridComponent, XiriStatusComponent, XiriStepperComponent, XiriTableComponent, XiriTabsComponent, XiriTimelineComponent, XiriToolbarComponent, XiriTreeComponent, XiriUrlPipe, colsToClasses, createPanelLoader, defaultXiriDataServiceConfig, escapeHtml, notifyThemeChanged, provideXiriServices, resolveColor };
8937
9185
  //# sourceMappingURL=xiriframework-xiri-ng.mjs.map