@smartbit4all/ng-client 7.1.1 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, reflectComponentType, Injectable, inject, DOCUMENT, PLATFORM_ID, Optional, Inject, RendererStyleFlags2, input, computed, Component, HostListener, HostBinding, Directive, ViewContainerRef, ElementRef, Renderer2, ChangeDetectorRef, Input, output, signal, Injector, ViewChild, ViewChildren, effect, afterNextRender, NgZone, forwardRef, Pipe, ChangeDetectionStrategy, ViewEncapsulation, SkipSelf, NgModule, EnvironmentInjector, EventEmitter, Output, ApplicationRef, viewChild, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
2
+ import { InjectionToken, reflectComponentType, Injectable, inject, DOCUMENT, PLATFORM_ID, Optional, Inject, RendererStyleFlags2, input, computed, Component, HostListener, HostBinding, Directive, ViewContainerRef, ElementRef, Renderer2, ChangeDetectorRef, Input, output, signal, Injector, ViewChild, ViewChildren, effect, afterNextRender, NgZone, forwardRef, createComponent, CSP_NONCE, EnvironmentInjector, ApplicationRef, untracked, DestroyRef, ChangeDetectionStrategy, ViewEncapsulation, Pipe, SkipSelf, NgModule, EventEmitter, Output, viewChild, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
3
3
  import * as i1 from '@angular/common/http';
4
4
  import { HttpHeaders, HttpContext, HttpErrorResponse, HttpParams, provideHttpClient, withInterceptors, withInterceptorsFromDi } from '@angular/common/http';
5
5
  import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
@@ -23,7 +23,7 @@ import { Validators, UntypedFormGroup, UntypedFormControl, NG_VALUE_ACCESSOR, Fo
23
23
  import { ENTER, COMMA } from '@angular/cdk/keycodes';
24
24
  import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
25
25
  import { MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChip } from '@angular/material/chips';
26
- import { set } from 'date-fns';
26
+ import { parseISO, isValid, format, set } from 'date-fns';
27
27
  import { Overlay, OverlayPositionBuilder, ScrollDispatcher } from '@angular/cdk/overlay';
28
28
  import { TemplatePortal } from '@angular/cdk/portal';
29
29
  import { MatLabel, MatFormField, MatSuffix, MatHint, MatPrefix } from '@angular/material/form-field';
@@ -6160,6 +6160,18 @@ const APIS$4 = [DefaultService$1];
6160
6160
  * Do not edit the class manually.
6161
6161
  */
6162
6162
 
6163
+ /**
6164
+ * Form layout definition
6165
+ * Contains form layout definition objects.
6166
+ *
6167
+ * The version of the OpenAPI document: 1.0.0
6168
+ * Contact: info@it4all.hu
6169
+ *
6170
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
6171
+ * https://openapi-generator.tech
6172
+ * Do not edit the class manually.
6173
+ */
6174
+
6163
6175
  var RecordingUploaderPropertiesOpenDirectionEnum;
6164
6176
  (function (RecordingUploaderPropertiesOpenDirectionEnum) {
6165
6177
  RecordingUploaderPropertiesOpenDirectionEnum["RIGHT"] = "RIGHT";
@@ -6267,6 +6279,7 @@ var SmartFormWidgetType;
6267
6279
  SmartFormWidgetType["SVG"] = "SVG";
6268
6280
  SmartFormWidgetType["DIV"] = "DIV";
6269
6281
  SmartFormWidgetType["RECORDING_UPLOADER"] = "RECORDING_UPLOADER";
6282
+ SmartFormWidgetType["HTML"] = "HTML";
6270
6283
  })(SmartFormWidgetType || (SmartFormWidgetType = {}));
6271
6284
 
6272
6285
  /**
@@ -6420,6 +6433,31 @@ function registerSmartWidget(client, registration) {
6420
6433
  });
6421
6434
  }
6422
6435
 
6436
+ /**
6437
+ * The key and display property of a valueSet's values: the preferred name if the values carry it,
6438
+ * then the GenericValue name (`uri` / `name`), then the Value name (`objectUri` / `displayValue`).
6439
+ * With no sample value to look at the preferred name is assumed to exist.
6440
+ */
6441
+ function valueSetKeyProperty(values, preferred) {
6442
+ return firstExisting(values, [preferred ?? 'objectUri', 'uri', 'objectUri']);
6443
+ }
6444
+ function valueSetDisplayProperty(values, preferred) {
6445
+ return firstExisting(values, [preferred ?? 'displayValue', 'name', 'displayValue']);
6446
+ }
6447
+ /** The label of a code in a valueSet, or undefined when the valueSet does not know the code. */
6448
+ function valueSetLabelOf(valueSet, code) {
6449
+ const values = valueSet.valueSetData?.values ?? [];
6450
+ const keyProperty = valueSetKeyProperty(values, valueSet.valueSetData?.keyProperty);
6451
+ const hit = values.find((value) => String(value[keyProperty]) === String(code));
6452
+ return hit?.[valueSetDisplayProperty(values)];
6453
+ }
6454
+ function firstExisting(values, candidates) {
6455
+ if (!values?.length) {
6456
+ return candidates[0];
6457
+ }
6458
+ return candidates.find((c) => c in values[0]) ?? candidates[candidates.length - 1];
6459
+ }
6460
+
6423
6461
  const EMPTY_PARAMS = {};
6424
6462
  const NAMED_VALIDATOR = new InjectionToken('Named validator factory');
6425
6463
 
@@ -6582,7 +6620,8 @@ class SmartFormService {
6582
6620
  if (w.type !== SmartFormWidgetType.CONTAINER &&
6583
6621
  w.type !== SmartFormWidgetType.LABEL &&
6584
6622
  w.type !== SmartFormWidgetType.CHECK_BOX_2 &&
6585
- w.type !== SmartFormWidgetType.YOUTUBE_PLAYER) {
6623
+ w.type !== SmartFormWidgetType.YOUTUBE_PLAYER &&
6624
+ w.type !== SmartFormWidgetType.HTML) {
6586
6625
  keys.push(w.key);
6587
6626
  }
6588
6627
  if (w.type === SmartFormWidgetType.TEXT_FIELD_CHIPS ||
@@ -6718,7 +6757,8 @@ class SmartFormService {
6718
6757
  widget.type !== SmartFormWidgetType.DIVIDER &&
6719
6758
  widget.type !== SmartFormWidgetType.BUTTON &&
6720
6759
  widget.type !== SmartFormWidgetType.COMPONENT &&
6721
- widget.type !== SmartFormWidgetType.YOUTUBE_PLAYER) {
6760
+ widget.type !== SmartFormWidgetType.YOUTUBE_PLAYER &&
6761
+ widget.type !== SmartFormWidgetType.HTML) {
6722
6762
  widget.value = value;
6723
6763
  if (widget.showLabel === undefined && smartForm.showLabel) {
6724
6764
  widget.showLabel = true;
@@ -6762,23 +6802,10 @@ class SmartFormService {
6762
6802
  let valueSetData = valueSet.valueSetData;
6763
6803
  let values = valueSetData.values;
6764
6804
  let selectionDefinition = widget.selection;
6765
- let displayProperty = selectionDefinition?.displayProperty ?? 'displayValue';
6766
- // check is displayProperty exists, fallback for common display properties
6767
- if (!this.checkProperty(values, displayProperty)) {
6768
- displayProperty = 'name'; // GenericValue.name
6769
- if (!this.checkProperty(values, displayProperty)) {
6770
- displayProperty = 'displayValue'; // Value.displayValue
6771
- }
6772
- }
6805
+ let displayProperty = valueSetDisplayProperty(values, selectionDefinition?.displayProperty);
6773
6806
  if (widget.selection.type === SelectionDefinitionTypeEnum.PROPERTY &&
6774
6807
  !widget.selection.mapping.length) {
6775
- let keyProperty = selectionDefinition?.keyProperty ?? valueSetData?.keyProperty ?? 'objectUri';
6776
- if (!this.checkProperty(values, keyProperty)) {
6777
- keyProperty = 'uri'; // GenericValue.uri
6778
- if (!this.checkProperty(values, keyProperty)) {
6779
- keyProperty = 'objectUri'; // Value.objectUri
6780
- }
6781
- }
6808
+ let keyProperty = valueSetKeyProperty(values, selectionDefinition?.keyProperty ?? valueSetData?.keyProperty);
6782
6809
  widget.valueList = values.map((value) => {
6783
6810
  return {
6784
6811
  key: value[keyProperty],
@@ -6805,13 +6832,6 @@ class SmartFormService {
6805
6832
  }
6806
6833
  }
6807
6834
  }
6808
- checkProperty(values, property) {
6809
- if (!values?.length) {
6810
- // no sample data, assume existance
6811
- return true;
6812
- }
6813
- return property in values[0];
6814
- }
6815
6835
  toFormGroup() {
6816
6836
  this.createFormControls(this.smartForm.widgets);
6817
6837
  if (this.formGroup) {
@@ -6835,6 +6855,7 @@ class SmartFormService {
6835
6855
  widget.type !== SmartFormWidgetType.IMAGE &&
6836
6856
  widget.type !== SmartFormWidgetType.SVG &&
6837
6857
  widget.type !== SmartFormWidgetType.DIV &&
6858
+ widget.type !== SmartFormWidgetType.HTML &&
6838
6859
  widget.type !== SmartFormWidgetType.DIVIDER &&
6839
6860
  widget.type !== SmartFormWidgetType.BUTTON &&
6840
6861
  widget.type !== SmartFormWidgetType.CHECK_BOX_2 &&
@@ -6941,6 +6962,7 @@ class SmartFormService {
6941
6962
  widget.type !== SmartFormWidgetType.IMAGE &&
6942
6963
  widget.type !== SmartFormWidgetType.SVG &&
6943
6964
  widget.type !== SmartFormWidgetType.DIV &&
6965
+ widget.type !== SmartFormWidgetType.HTML &&
6944
6966
  widget.type !== SmartFormWidgetType.BUTTON &&
6945
6967
  widget.type !== SmartFormWidgetType.DIVIDER &&
6946
6968
  widget.type !== SmartFormWidgetType.CHECK_BOX_2 &&
@@ -7015,6 +7037,7 @@ class SmartFormService {
7015
7037
  widget.type !== SmartFormWidgetType.IMAGE &&
7016
7038
  widget.type !== SmartFormWidgetType.SVG &&
7017
7039
  widget.type !== SmartFormWidgetType.DIV &&
7040
+ widget.type !== SmartFormWidgetType.HTML &&
7018
7041
  widget.type !== SmartFormWidgetType.DIVIDER &&
7019
7042
  widget.type !== SmartFormWidgetType.BUTTON &&
7020
7043
  widget.type !== SmartFormWidgetType.COMPONENT &&
@@ -7199,6 +7222,81 @@ function coerceToTypeOf(reference, value) {
7199
7222
  * Public API Surface of component-factory-service
7200
7223
  */
7201
7224
 
7225
+ /**
7226
+ * The execution context of a subtree: a nearer source for the toolbars inside it than the
7227
+ * screen component they would otherwise pull from.
7228
+ *
7229
+ * It exists for the one case a template cannot express. A toolbar gets its entries from an
7230
+ * explicit `[uiActionModels]` binding, or — having an `id` — by pulling the list of the client
7231
+ * above it (ADR-0006, decision 1). A layout the backend defined for a single grid row has
7232
+ * neither: its toolbars carry the ids the backend chose, and no template in this library can
7233
+ * bind a list on them, because a general layout knows nothing about grid rows. The component
7234
+ * that owns such a subtree provides this class instead and writes the row's actions into it.
7235
+ *
7236
+ * What it leaves `undefined` falls back to the chain that was there before, which is what
7237
+ * makes providing it unconditionally safe: `undefined` is "I have no list of my own", not an
7238
+ * empty list, so a toolbar under a host nobody filled keeps pulling from the client exactly as
7239
+ * it did.
7240
+ *
7241
+ * Only `actionModels` ships today. The class is named for the whole execution context — the
7242
+ * `executor`, `widgetId`, `nodeId` and `actionParams` of ADR-0006 decision 2 belong here too —
7243
+ * so that ending the per-entry `serviceToUse` leak in 7.1 is an addition rather than a rename.
7244
+ */
7245
+ class SmartActionHost {
7246
+ constructor() {
7247
+ /** The entries the toolbars of this subtree render, or `undefined` for "not my business". */
7248
+ this.actionModels = signal(undefined, /* @ts-ignore */
7249
+ ...(ngDevMode ? [{ debugName: "actionModels" }] : /* istanbul ignore next */ []));
7250
+ }
7251
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartActionHost, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7252
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartActionHost }); }
7253
+ }
7254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartActionHost, decorators: [{
7255
+ type: Injectable
7256
+ }] });
7257
+
7258
+ /**
7259
+ * The one way an offered action gets executed, shared by everything that offers one: the
7260
+ * toolbar and the action trigger of server-sent HTML. Call from an injection context.
7261
+ */
7262
+ function injectUiActionExecution() {
7263
+ const service = inject(UiActionService);
7264
+ const descriptors = inject(UiActionDescriptorService);
7265
+ const actionHost = inject(SmartActionHost, { optional: true });
7266
+ const smartComponent = injectSmartComponent();
7267
+ const running = new Set();
7268
+ return {
7269
+ entries: () => actionHost?.actionModels() ?? smartComponent?.actionModels(),
7270
+ fire: async (entry, overrides) => {
7271
+ const uiAction = entry.uiAction;
7272
+ const key = `${uiAction.code}#${uiAction.identifier ?? ''}`;
7273
+ if (uiAction.disabled || running.has(key)) {
7274
+ return;
7275
+ }
7276
+ running.add(key);
7277
+ try {
7278
+ const params = overrides?.actionParams;
7279
+ // Merging the params here rather than when the entry is built keeps `UiActionService`
7280
+ // untouched, so the ordering against its empty-params branch is unchanged.
7281
+ await service.execute({
7282
+ ...entry,
7283
+ descriptor: overrides?.descriptor ?? descriptors.getActionDescriptor(uiAction),
7284
+ serviceToUse: overrides?.executor ?? smartComponent ?? entry.serviceToUse,
7285
+ uiAction: params
7286
+ ? { ...uiAction, params: { ...uiAction.params, ...params } }
7287
+ : uiAction,
7288
+ }, {
7289
+ nodeId: entry.nodeId ?? overrides?.nodeId,
7290
+ widgetId: entry.widgetId ?? overrides?.widgetId,
7291
+ });
7292
+ }
7293
+ finally {
7294
+ running.delete(key);
7295
+ }
7296
+ },
7297
+ };
7298
+ }
7299
+
7202
7300
  /**
7203
7301
  * Custom HttpParameterCodec
7204
7302
  * Workaround for https://github.com/angular/angular/issues/18261
@@ -8213,39 +8311,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
8213
8311
  args: ['document:click', ['$event']]
8214
8312
  }] } });
8215
8313
 
8216
- /**
8217
- * The execution context of a subtree: a nearer source for the toolbars inside it than the
8218
- * screen component they would otherwise pull from.
8219
- *
8220
- * It exists for the one case a template cannot express. A toolbar gets its entries from an
8221
- * explicit `[uiActionModels]` binding, or — having an `id` — by pulling the list of the client
8222
- * above it (ADR-0006, decision 1). A layout the backend defined for a single grid row has
8223
- * neither: its toolbars carry the ids the backend chose, and no template in this library can
8224
- * bind a list on them, because a general layout knows nothing about grid rows. The component
8225
- * that owns such a subtree provides this class instead and writes the row's actions into it.
8226
- *
8227
- * What it leaves `undefined` falls back to the chain that was there before, which is what
8228
- * makes providing it unconditionally safe: `undefined` is "I have no list of my own", not an
8229
- * empty list, so a toolbar under a host nobody filled keeps pulling from the client exactly as
8230
- * it did.
8231
- *
8232
- * Only `actionModels` ships today. The class is named for the whole execution context — the
8233
- * `executor`, `widgetId`, `nodeId` and `actionParams` of ADR-0006 decision 2 belong here too —
8234
- * so that ending the per-entry `serviceToUse` leak in 7.1 is an addition rather than a rename.
8235
- */
8236
- class SmartActionHost {
8237
- constructor() {
8238
- /** The entries the toolbars of this subtree render, or `undefined` for "not my business". */
8239
- this.actionModels = signal(undefined, /* @ts-ignore */
8240
- ...(ngDevMode ? [{ debugName: "actionModels" }] : /* istanbul ignore next */ []));
8241
- }
8242
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartActionHost, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
8243
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartActionHost }); }
8244
- }
8245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartActionHost, decorators: [{
8246
- type: Injectable
8247
- }] });
8248
-
8249
8314
  class UiActionToolbarComponent {
8250
8315
  /** The list a template hands this toolbar explicitly; that binding is then the source. */
8251
8316
  set uiActionModels(models) {
@@ -8269,12 +8334,11 @@ class UiActionToolbarComponent {
8269
8334
  return this.isScrollableState();
8270
8335
  }
8271
8336
  constructor() {
8272
- this.service = inject(UiActionService);
8337
+ this.execution = injectUiActionExecution();
8273
8338
  this.inject = inject(Injector);
8274
8339
  this.menuService = inject(UiMenuService);
8275
8340
  this.changeDetector = inject(ChangeDetectorRef);
8276
8341
  this._destroy$ = new Subject();
8277
- this.pressedButtonActive = true;
8278
8342
  /**
8279
8343
  * `null` while no template binds the list — that is what lets the toolbar pull instead.
8280
8344
  * A template that binds the input owns the list even when the value is `undefined`.
@@ -8473,56 +8537,35 @@ class UiActionToolbarComponent {
8473
8537
  this.schedules.set(uiAction.code, sub);
8474
8538
  });
8475
8539
  }
8540
+ /**
8541
+ * Fires the entry with this toolbar's execution context: its inputs and the descriptor it
8542
+ * resolved. The descriptor travels here rather than in the entry (which is frozen); its one
8543
+ * reader outside this component is `UiActionService`'s snackbar feedback.
8544
+ */
8476
8545
  async fireAction(entry) {
8477
- if (entry.model.uiAction.disabled) {
8478
- return;
8479
- }
8480
- let options = {
8481
- nodeId: entry.model.nodeId ?? this.nodeId(),
8482
- widgetId: entry.model.widgetId ?? this.widgetId(),
8483
- };
8484
- await this.service.execute(this.forExecution(entry), options);
8546
+ await this.execution.fire(entry.model, {
8547
+ executor: this.executor(),
8548
+ widgetId: this.widgetId(),
8549
+ nodeId: this.nodeId(),
8550
+ actionParams: this.actionParams(),
8551
+ descriptor: entry.descriptor,
8552
+ });
8485
8553
  }
8486
8554
  /** The same entry, offering a different action — a sub-action, or a scheduled firing. */
8487
8555
  withAction(entry, uiAction) {
8488
8556
  return { ...entry, model: { ...entry.model, uiAction } };
8489
8557
  }
8490
- /**
8491
- * The entry as it is executed: this toolbar's executor, the descriptor it resolved and its
8492
- * extra params applied on top of what the entry describes. The entry's own `serviceToUse`
8493
- * is the last resort — it is the deprecated way of saying the same thing.
8494
- *
8495
- * The descriptor travels here rather than in the entry (which is frozen); its one reader
8496
- * outside this component is `UiActionService`'s snackbar feedback.
8497
- *
8498
- * Merging the params here rather than when the entry is built keeps `UiActionService`
8499
- * untouched, so the ordering against its empty-params branch is unchanged.
8500
- */
8501
- forExecution(entry) {
8502
- const params = this.actionParams();
8503
- const uiAction = entry.model.uiAction;
8504
- return {
8505
- ...entry.model,
8506
- descriptor: entry.descriptor,
8507
- serviceToUse: this.executor() ?? this.smartComponent ?? entry.model.serviceToUse,
8508
- uiAction: params ? { ...uiAction, params: { ...uiAction.params, ...params } } : uiAction,
8509
- };
8510
- }
8511
8558
  async onActionClicked(event, entry) {
8512
8559
  // event.stopPropagation();
8513
8560
  this.menuService.closeAllMenus();
8514
8561
  if (entry.model.uiAction.disabled) {
8515
8562
  return;
8516
8563
  }
8517
- if (this.pressedButtonActive) {
8518
- this.pressedButtonActive = false;
8519
- // ui-tiered-menu emits a full UiAction (no 'event' property),
8520
- // ui-action-button emits { event: MouseEvent, code, descriptor }.
8521
- // Use the emitted UiAction only for tiered-menu sub-actions.
8522
- const subAction = !event.event && event.code ? event : undefined;
8523
- await this.fireAction(subAction ? this.withAction(entry, subAction) : entry);
8524
- this.pressedButtonActive = true;
8525
- }
8564
+ // ui-tiered-menu emits a full UiAction (no 'event' property),
8565
+ // ui-action-button emits { event: MouseEvent, code, descriptor }.
8566
+ // Use the emitted UiAction only for tiered-menu sub-actions.
8567
+ const subAction = !event.event && event.code ? event : undefined;
8568
+ await this.fireAction(subAction ? this.withAction(entry, subAction) : entry);
8526
8569
  }
8527
8570
  onActionDoubleClicked(event, entry) {
8528
8571
  // event.stopPropagation();
@@ -8597,11 +8640,11 @@ class UiActionToolbarComponent {
8597
8640
  return MenuTriggerType;
8598
8641
  }
8599
8642
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: UiActionToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8600
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: UiActionToolbarComponent, isStandalone: true, selector: "smart-ui-action-toolbar", inputs: { uiActionModels: { classPropertyName: "uiActionModels", publicName: "uiActionModels", isSignal: false, isRequired: false, transformFunction: null }, uiActionDescriptorService: { classPropertyName: "uiActionDescriptorService", publicName: "uiActionDescriptorService", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: false, isRequired: false, transformFunction: null }, executor: { classPropertyName: "executor", publicName: "executor", isSignal: true, isRequired: false, transformFunction: null }, widgetId: { classPropertyName: "widgetId", publicName: "widgetId", isSignal: true, isRequired: false, transformFunction: null }, nodeId: { classPropertyName: "nodeId", publicName: "nodeId", isSignal: true, isRequired: false, transformFunction: null }, actionParams: { classPropertyName: "actionParams", publicName: "actionParams", isSignal: true, isRequired: false, transformFunction: null }, scrollOnWrap: { classPropertyName: "scrollOnWrap", publicName: "scrollOnWrap", isSignal: false, isRequired: false, transformFunction: null }, toolbarPropertes: { classPropertyName: "toolbarPropertes", publicName: "toolbarPropertes", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonLeft\"\n (actionClick)=\"scrollLeft()\"\n (mousedown)=\"scrollStart('left')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('left')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<div\n #container\n class=\"uiActionButtonsContainer\"\n (click)=\"$event.stopPropagation()\"\n [ngClass]=\"{\n scrollableContent: scrollOnWrap,\n verticalToolbar: isVertical,\n horizontalToolbar: isHorizontal,\n alignedStart: isAlignedStart,\n alignedEnd: isAlignedEnd,\n }\"\n >\n <!--\n Tracked by a synthesized key \u2014 the action code plus its ordinal among the entries with\n the same code \u2014 because a code is not unique inside a toolbar. Unique by construction,\n and a button's DOM node follows its action across reordering and insertion. See A14.\n -->\n @for (entry of entries(); track entry.key) {\n @if (entry.model.uiAction.code === 'themeSelector') {\n <theme-selector [model]=\"entry.model\"></theme-selector>\n } @else if (entry.model.uiAction.subActions && entry.model.uiAction.subActions.length > 0) {\n <ng-container *ngTemplateOutlet=\"menuTypes; context: { entry: entry }\"></ng-container>\n } @else {\n <ui-action-button\n (mouseenter)=\"onHover()\"\n [descriptor]=\"entry.descriptor!\"\n [code]=\"entry.model.uiAction.code\"\n [identifier]=\"entry.model.uiAction.identifier\"\n [disabled]=\"!!entry.model.uiAction.disabled\"\n [addedCssClass]=\"entry.model.cssClass\"\n [viewActivated]=\"entry.model.uiAction.viewActivated\"\n (actionClick)=\"onActionClicked($event, entry)\"\n (actionDoubleClick)=\"onActionDoubleClicked($event, entry)\"\n >\n </ui-action-button>\n }\n }\n</div>\n\n@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonRight\"\n (actionClick)=\"scrollRight()\"\n (mousedown)=\"scrollStart('right')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('right')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<ng-template #menuTypes let-entry=\"entry\">\n @switch ($safeNavigationMigration(entry?.model?.uiAction?.descriptor?.menu?.triggerType)) {\n @case (triggerType.HOVER) {\n <ui-hover-menu\n #menu\n [toolbarId]=\"id\"\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-hover-menu>\n }\n @case (triggerType.CLICK) {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n @default {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n }\n</ng-template>\n", styles: [":host:has(.uiActionButtonsContainer.scrollableContent){display:flex;flex-direction:row;justify-content:space-between;gap:.5rem;width:100%;align-items:center}:host:has(.verticalToolbar){height:100%}:host:has(.horizontalToolbar.alignedEnd){width:100%}.uiActionButtonsContainer{display:flex;flex-direction:row;gap:1rem;flex-wrap:wrap}.uiActionButtonsContainer ::ng-deep button{display:flex;gap:1rem;align-items:center;justify-content:center}.uiActionButtonsContainer ::ng-deep .buttonWrapper{position:relative;width:fit-content;height:fit-content}.scrollableContent{flex:1;flex-wrap:nowrap;overflow-x:auto;overflow-y:visible;display:flex;scrollbar-width:none;padding:.5rem 0;align-items:center}.scrollableContent::-webkit-scrollbar{display:none!important}.verticalToolbar{display:flex;flex-direction:column;height:100%}.verticalToolbar ::ng-deep ui-action-button,.verticalToolbar ::ng-deep button{width:100%}.alignedStart{justify-content:flex-start}.alignedEnd{justify-content:flex-end}\n"], dependencies: [{ kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ThemeSelectorComponent, selector: "theme-selector", inputs: ["model"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HoverMenuComponent, selector: "ui-hover-menu", inputs: ["triggerAction", "isSubmenu", "menuOpenDirection", "toolbarId"], outputs: ["actionClick", "submenuOpened"] }, { kind: "component", type: ClickMenuComponent, selector: "ui-tiered-menu", inputs: ["triggerAction", "isSubmenu", "menuOpenDirection"], outputs: ["actionClick", "submenuOpened"] }] }); }
8643
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: UiActionToolbarComponent, isStandalone: true, selector: "smart-ui-action-toolbar", inputs: { uiActionModels: { classPropertyName: "uiActionModels", publicName: "uiActionModels", isSignal: false, isRequired: false, transformFunction: null }, uiActionDescriptorService: { classPropertyName: "uiActionDescriptorService", publicName: "uiActionDescriptorService", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: false, isRequired: false, transformFunction: null }, executor: { classPropertyName: "executor", publicName: "executor", isSignal: true, isRequired: false, transformFunction: null }, widgetId: { classPropertyName: "widgetId", publicName: "widgetId", isSignal: true, isRequired: false, transformFunction: null }, nodeId: { classPropertyName: "nodeId", publicName: "nodeId", isSignal: true, isRequired: false, transformFunction: null }, actionParams: { classPropertyName: "actionParams", publicName: "actionParams", isSignal: true, isRequired: false, transformFunction: null }, scrollOnWrap: { classPropertyName: "scrollOnWrap", publicName: "scrollOnWrap", isSignal: false, isRequired: false, transformFunction: null }, toolbarPropertes: { classPropertyName: "toolbarPropertes", publicName: "toolbarPropertes", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonLeft\"\n (actionClick)=\"scrollLeft()\"\n (mousedown)=\"scrollStart('left')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('left')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<div\n #container\n class=\"uiActionButtonsContainer\"\n (click)=\"$event.stopPropagation()\"\n (dblclick)=\"$event.stopPropagation()\"\n [ngClass]=\"{\n scrollableContent: scrollOnWrap,\n verticalToolbar: isVertical,\n horizontalToolbar: isHorizontal,\n alignedStart: isAlignedStart,\n alignedEnd: isAlignedEnd,\n }\"\n >\n <!--\n Tracked by a synthesized key \u2014 the action code plus its ordinal among the entries with\n the same code \u2014 because a code is not unique inside a toolbar. Unique by construction,\n and a button's DOM node follows its action across reordering and insertion. See A14.\n -->\n @for (entry of entries(); track entry.key) {\n @if (entry.model.uiAction.code === 'themeSelector') {\n <theme-selector [model]=\"entry.model\"></theme-selector>\n } @else if (entry.model.uiAction.subActions && entry.model.uiAction.subActions.length > 0) {\n <ng-container *ngTemplateOutlet=\"menuTypes; context: { entry: entry }\"></ng-container>\n } @else {\n <ui-action-button\n (mouseenter)=\"onHover()\"\n [descriptor]=\"entry.descriptor!\"\n [code]=\"entry.model.uiAction.code\"\n [identifier]=\"entry.model.uiAction.identifier\"\n [disabled]=\"!!entry.model.uiAction.disabled\"\n [addedCssClass]=\"entry.model.cssClass\"\n [viewActivated]=\"entry.model.uiAction.viewActivated\"\n (actionClick)=\"onActionClicked($event, entry)\"\n (actionDoubleClick)=\"onActionDoubleClicked($event, entry)\"\n >\n </ui-action-button>\n }\n }\n</div>\n\n@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonRight\"\n (actionClick)=\"scrollRight()\"\n (mousedown)=\"scrollStart('right')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('right')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<ng-template #menuTypes let-entry=\"entry\">\n @switch ($safeNavigationMigration(entry?.model?.uiAction?.descriptor?.menu?.triggerType)) {\n @case (triggerType.HOVER) {\n <ui-hover-menu\n #menu\n [toolbarId]=\"id\"\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-hover-menu>\n }\n @case (triggerType.CLICK) {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n @default {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n }\n</ng-template>\n", styles: [":host:has(.uiActionButtonsContainer.scrollableContent){display:flex;flex-direction:row;justify-content:space-between;gap:.5rem;width:100%;align-items:center}:host:has(.verticalToolbar){height:100%}:host:has(.horizontalToolbar.alignedEnd){width:100%}.uiActionButtonsContainer{display:flex;flex-direction:row;gap:1rem;flex-wrap:wrap}.uiActionButtonsContainer ::ng-deep button{display:flex;gap:1rem;align-items:center;justify-content:center}.uiActionButtonsContainer ::ng-deep .buttonWrapper{position:relative;width:fit-content;height:fit-content}.scrollableContent{flex:1;flex-wrap:nowrap;overflow-x:auto;overflow-y:visible;display:flex;scrollbar-width:none;padding:.5rem 0;align-items:center}.scrollableContent::-webkit-scrollbar{display:none!important}.verticalToolbar{display:flex;flex-direction:column;height:100%}.verticalToolbar ::ng-deep ui-action-button,.verticalToolbar ::ng-deep button{width:100%}.alignedStart{justify-content:flex-start}.alignedEnd{justify-content:flex-end}\n"], dependencies: [{ kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ThemeSelectorComponent, selector: "theme-selector", inputs: ["model"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: HoverMenuComponent, selector: "ui-hover-menu", inputs: ["triggerAction", "isSubmenu", "menuOpenDirection", "toolbarId"], outputs: ["actionClick", "submenuOpened"] }, { kind: "component", type: ClickMenuComponent, selector: "ui-tiered-menu", inputs: ["triggerAction", "isSubmenu", "menuOpenDirection"], outputs: ["actionClick", "submenuOpened"] }] }); }
8601
8644
  }
8602
8645
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: UiActionToolbarComponent, decorators: [{
8603
8646
  type: Component,
8604
- args: [{ selector: 'smart-ui-action-toolbar', imports: [UiActionButtonComponent, NgClass, ThemeSelectorComponent, NgTemplateOutlet, HoverMenuComponent, ClickMenuComponent], template: "@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonLeft\"\n (actionClick)=\"scrollLeft()\"\n (mousedown)=\"scrollStart('left')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('left')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<div\n #container\n class=\"uiActionButtonsContainer\"\n (click)=\"$event.stopPropagation()\"\n [ngClass]=\"{\n scrollableContent: scrollOnWrap,\n verticalToolbar: isVertical,\n horizontalToolbar: isHorizontal,\n alignedStart: isAlignedStart,\n alignedEnd: isAlignedEnd,\n }\"\n >\n <!--\n Tracked by a synthesized key \u2014 the action code plus its ordinal among the entries with\n the same code \u2014 because a code is not unique inside a toolbar. Unique by construction,\n and a button's DOM node follows its action across reordering and insertion. See A14.\n -->\n @for (entry of entries(); track entry.key) {\n @if (entry.model.uiAction.code === 'themeSelector') {\n <theme-selector [model]=\"entry.model\"></theme-selector>\n } @else if (entry.model.uiAction.subActions && entry.model.uiAction.subActions.length > 0) {\n <ng-container *ngTemplateOutlet=\"menuTypes; context: { entry: entry }\"></ng-container>\n } @else {\n <ui-action-button\n (mouseenter)=\"onHover()\"\n [descriptor]=\"entry.descriptor!\"\n [code]=\"entry.model.uiAction.code\"\n [identifier]=\"entry.model.uiAction.identifier\"\n [disabled]=\"!!entry.model.uiAction.disabled\"\n [addedCssClass]=\"entry.model.cssClass\"\n [viewActivated]=\"entry.model.uiAction.viewActivated\"\n (actionClick)=\"onActionClicked($event, entry)\"\n (actionDoubleClick)=\"onActionDoubleClicked($event, entry)\"\n >\n </ui-action-button>\n }\n }\n</div>\n\n@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonRight\"\n (actionClick)=\"scrollRight()\"\n (mousedown)=\"scrollStart('right')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('right')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<ng-template #menuTypes let-entry=\"entry\">\n @switch ($safeNavigationMigration(entry?.model?.uiAction?.descriptor?.menu?.triggerType)) {\n @case (triggerType.HOVER) {\n <ui-hover-menu\n #menu\n [toolbarId]=\"id\"\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-hover-menu>\n }\n @case (triggerType.CLICK) {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n @default {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n }\n</ng-template>\n", styles: [":host:has(.uiActionButtonsContainer.scrollableContent){display:flex;flex-direction:row;justify-content:space-between;gap:.5rem;width:100%;align-items:center}:host:has(.verticalToolbar){height:100%}:host:has(.horizontalToolbar.alignedEnd){width:100%}.uiActionButtonsContainer{display:flex;flex-direction:row;gap:1rem;flex-wrap:wrap}.uiActionButtonsContainer ::ng-deep button{display:flex;gap:1rem;align-items:center;justify-content:center}.uiActionButtonsContainer ::ng-deep .buttonWrapper{position:relative;width:fit-content;height:fit-content}.scrollableContent{flex:1;flex-wrap:nowrap;overflow-x:auto;overflow-y:visible;display:flex;scrollbar-width:none;padding:.5rem 0;align-items:center}.scrollableContent::-webkit-scrollbar{display:none!important}.verticalToolbar{display:flex;flex-direction:column;height:100%}.verticalToolbar ::ng-deep ui-action-button,.verticalToolbar ::ng-deep button{width:100%}.alignedStart{justify-content:flex-start}.alignedEnd{justify-content:flex-end}\n"] }]
8647
+ args: [{ selector: 'smart-ui-action-toolbar', imports: [UiActionButtonComponent, NgClass, ThemeSelectorComponent, NgTemplateOutlet, HoverMenuComponent, ClickMenuComponent], template: "@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonLeft\"\n (actionClick)=\"scrollLeft()\"\n (mousedown)=\"scrollStart('left')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('left')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<div\n #container\n class=\"uiActionButtonsContainer\"\n (click)=\"$event.stopPropagation()\"\n (dblclick)=\"$event.stopPropagation()\"\n [ngClass]=\"{\n scrollableContent: scrollOnWrap,\n verticalToolbar: isVertical,\n horizontalToolbar: isHorizontal,\n alignedStart: isAlignedStart,\n alignedEnd: isAlignedEnd,\n }\"\n >\n <!--\n Tracked by a synthesized key \u2014 the action code plus its ordinal among the entries with\n the same code \u2014 because a code is not unique inside a toolbar. Unique by construction,\n and a button's DOM node follows its action across reordering and insertion. See A14.\n -->\n @for (entry of entries(); track entry.key) {\n @if (entry.model.uiAction.code === 'themeSelector') {\n <theme-selector [model]=\"entry.model\"></theme-selector>\n } @else if (entry.model.uiAction.subActions && entry.model.uiAction.subActions.length > 0) {\n <ng-container *ngTemplateOutlet=\"menuTypes; context: { entry: entry }\"></ng-container>\n } @else {\n <ui-action-button\n (mouseenter)=\"onHover()\"\n [descriptor]=\"entry.descriptor!\"\n [code]=\"entry.model.uiAction.code\"\n [identifier]=\"entry.model.uiAction.identifier\"\n [disabled]=\"!!entry.model.uiAction.disabled\"\n [addedCssClass]=\"entry.model.cssClass\"\n [viewActivated]=\"entry.model.uiAction.viewActivated\"\n (actionClick)=\"onActionClicked($event, entry)\"\n (actionDoubleClick)=\"onActionDoubleClicked($event, entry)\"\n >\n </ui-action-button>\n }\n }\n</div>\n\n@if (isScrollable && scrollOnWrap) {\n <ui-action-button\n [disabled]=\"!isScrollable\"\n [descriptor]=\"buttonRight\"\n (actionClick)=\"scrollRight()\"\n (mousedown)=\"scrollStart('right')\"\n (mouseup)=\"stopScroll()\"\n (mouseleave)=\"stopScroll()\"\n (touchstart)=\"scrollStart('right')\"\n (touchend)=\"stopScroll()\"\n />\n}\n\n<ng-template #menuTypes let-entry=\"entry\">\n @switch ($safeNavigationMigration(entry?.model?.uiAction?.descriptor?.menu?.triggerType)) {\n @case (triggerType.HOVER) {\n <ui-hover-menu\n #menu\n [toolbarId]=\"id\"\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-hover-menu>\n }\n @case (triggerType.CLICK) {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n @default {\n <ui-tiered-menu\n #menu\n (mouseenter)=\"onHover()\"\n [triggerAction]=\"entry.model.uiAction\"\n (actionClick)=\"onActionClicked($event, entry)\"\n ></ui-tiered-menu>\n }\n }\n</ng-template>\n", styles: [":host:has(.uiActionButtonsContainer.scrollableContent){display:flex;flex-direction:row;justify-content:space-between;gap:.5rem;width:100%;align-items:center}:host:has(.verticalToolbar){height:100%}:host:has(.horizontalToolbar.alignedEnd){width:100%}.uiActionButtonsContainer{display:flex;flex-direction:row;gap:1rem;flex-wrap:wrap}.uiActionButtonsContainer ::ng-deep button{display:flex;gap:1rem;align-items:center;justify-content:center}.uiActionButtonsContainer ::ng-deep .buttonWrapper{position:relative;width:fit-content;height:fit-content}.scrollableContent{flex:1;flex-wrap:nowrap;overflow-x:auto;overflow-y:visible;display:flex;scrollbar-width:none;padding:.5rem 0;align-items:center}.scrollableContent::-webkit-scrollbar{display:none!important}.verticalToolbar{display:flex;flex-direction:column;height:100%}.verticalToolbar ::ng-deep ui-action-button,.verticalToolbar ::ng-deep button{width:100%}.alignedStart{justify-content:flex-start}.alignedEnd{justify-content:flex-end}\n"] }]
8605
8648
  }], ctorParameters: () => [], propDecorators: { containerRef: [{
8606
8649
  type: ViewChild,
8607
8650
  args: ['container', { static: false }]
@@ -8772,7 +8815,10 @@ class SmartfileuploaderComponent {
8772
8815
  remove(index) {
8773
8816
  this.files.splice(index, 1);
8774
8817
  }
8775
- uploadFile() {
8818
+ uploadFile(event) {
8819
+ // The button sits inside a clickable host (a grid card, a row): the click must not
8820
+ // reach it as well.
8821
+ event?.event.stopPropagation();
8776
8822
  this.uploadCallback()(this.files);
8777
8823
  }
8778
8824
  formatSize(bytes) {
@@ -8832,11 +8878,11 @@ class SmartfileuploaderComponent {
8832
8878
  };
8833
8879
  }
8834
8880
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartfileuploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8835
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartfileuploaderComponent, isStandalone: true, selector: "smartfileuploader", inputs: { uploadCallback: { classPropertyName: "uploadCallback", publicName: "uploadCallback", isSignal: true, isRequired: true, transformFunction: null }, fileFormats: { classPropertyName: "fileFormats", publicName: "fileFormats", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, i18n: { classPropertyName: "i18n", publicName: "i18n", isSignal: false, isRequired: false, transformFunction: null }, useIconButton: { classPropertyName: "useIconButton", publicName: "useIconButton", isSignal: true, isRequired: false, transformFunction: null }, isMultiple: { classPropertyName: "isMultiple", publicName: "isMultiple", isSignal: true, isRequired: false, transformFunction: null }, autoUpload: { classPropertyName: "autoUpload", publicName: "autoUpload", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div\n class=\"container\"\n [ngClass]=\"{ disabledWidget: isDisabled() }\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [class.dragover]=\"isDragOver\"\n >\n <div class=\"fileContainer\" (click)=\"fileInput.click()\">\n <input\n #fileInput\n id=\"addFile\"\n placeholder=\"fileInput\"\n type=\"file\"\n (change)=\"getFile($event)\"\n class=\"file\"\n accept=\"{{ fileFormats()?.join(', ') }}\"\n [size]=\"maxSizeMb()\"\n [multiple]=\"isMultiple()\"\n [disabled]=\"isDisabled()\"\n style=\"display: none\"\n />\n <div class=\"fileUploadContentContainer\">\n <div class=\"icon\">\n @if (useIconButton()) {\n <mat-label class=\"addFileButton\">\n <mat-icon color=\"primary\" class=\"addCircle\">add_circle</mat-icon>\n </mat-label>\n }\n @if (!useIconButton()) {\n <button mat-raised-button color=\"primary\" class=\"addFileButton\">\n {{ i18n!.addFile }}\n </button>\n }\n </div>\n <div class=\"labels\">\n @if (useIconButton()) {\n <mat-label class=\"label primary title\">\n {{ i18n!.addFile }}\n </mat-label>\n }\n <mat-label class=\"label secondary\"> {{ i18n!.browseOrDrag }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.maxSize }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.formats }} </mat-label>\n </div>\n @if (files.length) {\n <div class=\"uploadButton\">\n <ui-action-button\n (actionClick)=\"uploadFile()\"\n [code]=\"'default-upload'\"\n [descriptor]=\"uploadButton\"\n >\n </ui-action-button>\n </div>\n }\n </div>\n </div>\n\n @if (errors.length) {\n <div class=\"errorMessage\">\n <smart-icon [icon]=\"'error'\" [color]=\"'warn'\"></smart-icon>\n <div class=\"errors\">\n @for (error of errors; track error) {\n <span>{{ error }}</span>\n }\n </div>\n </div>\n }\n\n @if (files.length) {\n <div class=\"uploadedFilesContainer\">\n @for (file of files; track file; let i = $index) {\n <div class=\"uploadedFile\">\n @if (filePreviewUrl(file)) {\n <img [src]=\"filePreviewUrl(file)\" [alt]=\"file.name\" width=\"50\" height=\"50\" />\n } @else {\n <smart-icon [icon]=\"'insert_drive_file'\"></smart-icon>\n }\n <div class=\"fileData\">\n <div class=\"fileDataContainer\">\n <span class=\"fileName\">{{ file.name }}</span>\n <span class=\"fileSize\">{{ formatSize(file.size) }}</span>\n </div>\n </div>\n <div class=\"fileActions\">\n <smart-icon\n class=\"downloadIcon\"\n icon=\"download\"\n (click)=\"downloadFile(file)\"\n [attr.data-testid]=\"'default_download'\"\n ></smart-icon>\n <smart-icon\n class=\"removeIcon\"\n icon=\"delete\"\n [attr.data-testid]=\"'default_remove'\"\n (click)=\"remove(i)\"\n ></smart-icon>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{--border-color: #a6aabd60;--warninig-color: #be2d2e;--def-border-radius: .5rem}.container{display:flex;flex-direction:column;border:2px dashed var(--border-color);border-radius:var(--def-border-radius)}.fileContainer{cursor:pointer;padding:1rem;display:flex;flex-direction:column}.fileContainer:hover{background-color:rgb(from var(--border-color) r g b / .1)}.disabledWidget ::ng-deep .fileContainer:hover{background-color:unset;cursor:unset}.disabledWidget ::ng-deep *{opacity:.85}.dragover{background-color:rgb(from var(--border-color) r g b / .1)}.fileUploadContentContainer{display:flex;flex-direction:row;gap:1rem}.icon mat-icon{font-size:3rem;width:unset;height:unset}.icon{align-content:center}.labels{flex:1;display:flex;flex-direction:column;justify-content:center;width:fit-content}.uploadButton{align-content:center}.primary{color:var(--primary-color)}.secondary{color:var(--gray)}.label{margin:unset}.subLabel{font-size:smaller}.title{padding-bottom:.3rem}.errorMessage,.uploadedFilesContainer{border-top:2px solid var(--border-color)}.errorMessage{display:flex;flex-direction:row;align-items:center;color:var(--warninig-color);padding:.5rem 1rem;gap:1rem}.errorMessage ::ng-deep mat-icon{color:var(--warninig-color)}.errors{display:flex;flex-direction:column}.uploadedFile{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;padding:1rem;border-bottom:1px solid #e0e0e0;gap:1rem}.uploadedFile:last-child{border-bottom:none}.fileSize{display:flex;flex-direction:row;font-size:smaller}.fileData{flex:1;display:flex;flex-direction:column}.fileDataContainer{display:flex;flex-direction:column;justify-content:flex-end;width:fit-content}.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}smart-icon ::ng-deep mat-icon{font-size:3rem;width:unset;height:unset}.fileActions{display:flex;flex-direction:row;justify-content:flex-end;gap:.5rem}.removeIcon ::ng-deep i,.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}.removeIcon ::ng-deep mat-icon,.downloadIcon ::ng-deep mat-icon{font-size:2rem}.removeIcon:hover,.downloadIcon:hover{cursor:pointer}smart-icon{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }] }); }
8881
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartfileuploaderComponent, isStandalone: true, selector: "smartfileuploader", inputs: { uploadCallback: { classPropertyName: "uploadCallback", publicName: "uploadCallback", isSignal: true, isRequired: true, transformFunction: null }, fileFormats: { classPropertyName: "fileFormats", publicName: "fileFormats", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, i18n: { classPropertyName: "i18n", publicName: "i18n", isSignal: false, isRequired: false, transformFunction: null }, useIconButton: { classPropertyName: "useIconButton", publicName: "useIconButton", isSignal: true, isRequired: false, transformFunction: null }, isMultiple: { classPropertyName: "isMultiple", publicName: "isMultiple", isSignal: true, isRequired: false, transformFunction: null }, autoUpload: { classPropertyName: "autoUpload", publicName: "autoUpload", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div\n class=\"container\"\n [ngClass]=\"{ disabledWidget: isDisabled() }\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [class.dragover]=\"isDragOver\"\n >\n <div class=\"fileContainer\" (click)=\"fileInput.click()\">\n <input\n #fileInput\n id=\"addFile\"\n placeholder=\"fileInput\"\n type=\"file\"\n (change)=\"getFile($event)\"\n class=\"file\"\n accept=\"{{ fileFormats()?.join(', ') }}\"\n [size]=\"maxSizeMb()\"\n [multiple]=\"isMultiple()\"\n [disabled]=\"isDisabled()\"\n style=\"display: none\"\n />\n <div class=\"fileUploadContentContainer\">\n <div class=\"icon\">\n @if (useIconButton()) {\n <mat-label class=\"addFileButton\">\n <mat-icon color=\"primary\" class=\"addCircle\">add_circle</mat-icon>\n </mat-label>\n }\n @if (!useIconButton()) {\n <button mat-raised-button color=\"primary\" class=\"addFileButton\">\n {{ i18n!.addFile }}\n </button>\n }\n </div>\n <div class=\"labels\">\n @if (useIconButton()) {\n <mat-label class=\"label primary title\">\n {{ i18n!.addFile }}\n </mat-label>\n }\n <mat-label class=\"label secondary\"> {{ i18n!.browseOrDrag }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.maxSize }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.formats }} </mat-label>\n </div>\n @if (files.length) {\n <div class=\"uploadButton\">\n <ui-action-button\n (actionClick)=\"uploadFile($event)\"\n [code]=\"'default-upload'\"\n [descriptor]=\"uploadButton\"\n >\n </ui-action-button>\n </div>\n }\n </div>\n </div>\n\n @if (errors.length) {\n <div class=\"errorMessage\">\n <smart-icon [icon]=\"'error'\" [color]=\"'warn'\"></smart-icon>\n <div class=\"errors\">\n @for (error of errors; track error) {\n <span>{{ error }}</span>\n }\n </div>\n </div>\n }\n\n @if (files.length) {\n <div class=\"uploadedFilesContainer\">\n @for (file of files; track file; let i = $index) {\n <div class=\"uploadedFile\">\n @if (filePreviewUrl(file)) {\n <img [src]=\"filePreviewUrl(file)\" [alt]=\"file.name\" width=\"50\" height=\"50\" />\n } @else {\n <smart-icon [icon]=\"'insert_drive_file'\"></smart-icon>\n }\n <div class=\"fileData\">\n <div class=\"fileDataContainer\">\n <span class=\"fileName\">{{ file.name }}</span>\n <span class=\"fileSize\">{{ formatSize(file.size) }}</span>\n </div>\n </div>\n <div class=\"fileActions\">\n <smart-icon\n class=\"downloadIcon\"\n icon=\"download\"\n (click)=\"downloadFile(file)\"\n [attr.data-testid]=\"'default_download'\"\n ></smart-icon>\n <smart-icon\n class=\"removeIcon\"\n icon=\"delete\"\n [attr.data-testid]=\"'default_remove'\"\n (click)=\"remove(i)\"\n ></smart-icon>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{--border-color: #a6aabd60;--warninig-color: #be2d2e;--def-border-radius: .5rem}.container{display:flex;flex-direction:column;border:2px dashed var(--border-color);border-radius:var(--def-border-radius)}.fileContainer{cursor:pointer;padding:1rem;display:flex;flex-direction:column}.fileContainer:hover{background-color:rgb(from var(--border-color) r g b / .1)}.disabledWidget ::ng-deep .fileContainer:hover{background-color:unset;cursor:unset}.disabledWidget ::ng-deep *{opacity:.85}.dragover{background-color:rgb(from var(--border-color) r g b / .1)}.fileUploadContentContainer{display:flex;flex-direction:row;gap:1rem}.icon mat-icon{font-size:3rem;width:unset;height:unset}.icon{align-content:center}.labels{flex:1;display:flex;flex-direction:column;justify-content:center;width:fit-content}.uploadButton{align-content:center}.primary{color:var(--primary-color)}.secondary{color:var(--gray)}.label{margin:unset}.subLabel{font-size:smaller}.title{padding-bottom:.3rem}.errorMessage,.uploadedFilesContainer{border-top:2px solid var(--border-color)}.errorMessage{display:flex;flex-direction:row;align-items:center;color:var(--warninig-color);padding:.5rem 1rem;gap:1rem}.errorMessage ::ng-deep mat-icon{color:var(--warninig-color)}.errors{display:flex;flex-direction:column}.uploadedFile{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;padding:1rem;border-bottom:1px solid #e0e0e0;gap:1rem}.uploadedFile:last-child{border-bottom:none}.fileSize{display:flex;flex-direction:row;font-size:smaller}.fileData{flex:1;display:flex;flex-direction:column}.fileDataContainer{display:flex;flex-direction:column;justify-content:flex-end;width:fit-content}.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}smart-icon ::ng-deep mat-icon{font-size:3rem;width:unset;height:unset}.fileActions{display:flex;flex-direction:row;justify-content:flex-end;gap:.5rem}.removeIcon ::ng-deep i,.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}.removeIcon ::ng-deep mat-icon,.downloadIcon ::ng-deep mat-icon{font-size:2rem}.removeIcon:hover,.downloadIcon:hover{cursor:pointer}smart-icon{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }] }); }
8836
8882
  }
8837
8883
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartfileuploaderComponent, decorators: [{
8838
8884
  type: Component,
8839
- args: [{ selector: 'smartfileuploader', imports: [NgClass, MatLabel, MatIcon, MatButton, UiActionButtonComponent, SmartIconComponent], template: "<div\n class=\"container\"\n [ngClass]=\"{ disabledWidget: isDisabled() }\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [class.dragover]=\"isDragOver\"\n >\n <div class=\"fileContainer\" (click)=\"fileInput.click()\">\n <input\n #fileInput\n id=\"addFile\"\n placeholder=\"fileInput\"\n type=\"file\"\n (change)=\"getFile($event)\"\n class=\"file\"\n accept=\"{{ fileFormats()?.join(', ') }}\"\n [size]=\"maxSizeMb()\"\n [multiple]=\"isMultiple()\"\n [disabled]=\"isDisabled()\"\n style=\"display: none\"\n />\n <div class=\"fileUploadContentContainer\">\n <div class=\"icon\">\n @if (useIconButton()) {\n <mat-label class=\"addFileButton\">\n <mat-icon color=\"primary\" class=\"addCircle\">add_circle</mat-icon>\n </mat-label>\n }\n @if (!useIconButton()) {\n <button mat-raised-button color=\"primary\" class=\"addFileButton\">\n {{ i18n!.addFile }}\n </button>\n }\n </div>\n <div class=\"labels\">\n @if (useIconButton()) {\n <mat-label class=\"label primary title\">\n {{ i18n!.addFile }}\n </mat-label>\n }\n <mat-label class=\"label secondary\"> {{ i18n!.browseOrDrag }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.maxSize }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.formats }} </mat-label>\n </div>\n @if (files.length) {\n <div class=\"uploadButton\">\n <ui-action-button\n (actionClick)=\"uploadFile()\"\n [code]=\"'default-upload'\"\n [descriptor]=\"uploadButton\"\n >\n </ui-action-button>\n </div>\n }\n </div>\n </div>\n\n @if (errors.length) {\n <div class=\"errorMessage\">\n <smart-icon [icon]=\"'error'\" [color]=\"'warn'\"></smart-icon>\n <div class=\"errors\">\n @for (error of errors; track error) {\n <span>{{ error }}</span>\n }\n </div>\n </div>\n }\n\n @if (files.length) {\n <div class=\"uploadedFilesContainer\">\n @for (file of files; track file; let i = $index) {\n <div class=\"uploadedFile\">\n @if (filePreviewUrl(file)) {\n <img [src]=\"filePreviewUrl(file)\" [alt]=\"file.name\" width=\"50\" height=\"50\" />\n } @else {\n <smart-icon [icon]=\"'insert_drive_file'\"></smart-icon>\n }\n <div class=\"fileData\">\n <div class=\"fileDataContainer\">\n <span class=\"fileName\">{{ file.name }}</span>\n <span class=\"fileSize\">{{ formatSize(file.size) }}</span>\n </div>\n </div>\n <div class=\"fileActions\">\n <smart-icon\n class=\"downloadIcon\"\n icon=\"download\"\n (click)=\"downloadFile(file)\"\n [attr.data-testid]=\"'default_download'\"\n ></smart-icon>\n <smart-icon\n class=\"removeIcon\"\n icon=\"delete\"\n [attr.data-testid]=\"'default_remove'\"\n (click)=\"remove(i)\"\n ></smart-icon>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{--border-color: #a6aabd60;--warninig-color: #be2d2e;--def-border-radius: .5rem}.container{display:flex;flex-direction:column;border:2px dashed var(--border-color);border-radius:var(--def-border-radius)}.fileContainer{cursor:pointer;padding:1rem;display:flex;flex-direction:column}.fileContainer:hover{background-color:rgb(from var(--border-color) r g b / .1)}.disabledWidget ::ng-deep .fileContainer:hover{background-color:unset;cursor:unset}.disabledWidget ::ng-deep *{opacity:.85}.dragover{background-color:rgb(from var(--border-color) r g b / .1)}.fileUploadContentContainer{display:flex;flex-direction:row;gap:1rem}.icon mat-icon{font-size:3rem;width:unset;height:unset}.icon{align-content:center}.labels{flex:1;display:flex;flex-direction:column;justify-content:center;width:fit-content}.uploadButton{align-content:center}.primary{color:var(--primary-color)}.secondary{color:var(--gray)}.label{margin:unset}.subLabel{font-size:smaller}.title{padding-bottom:.3rem}.errorMessage,.uploadedFilesContainer{border-top:2px solid var(--border-color)}.errorMessage{display:flex;flex-direction:row;align-items:center;color:var(--warninig-color);padding:.5rem 1rem;gap:1rem}.errorMessage ::ng-deep mat-icon{color:var(--warninig-color)}.errors{display:flex;flex-direction:column}.uploadedFile{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;padding:1rem;border-bottom:1px solid #e0e0e0;gap:1rem}.uploadedFile:last-child{border-bottom:none}.fileSize{display:flex;flex-direction:row;font-size:smaller}.fileData{flex:1;display:flex;flex-direction:column}.fileDataContainer{display:flex;flex-direction:column;justify-content:flex-end;width:fit-content}.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}smart-icon ::ng-deep mat-icon{font-size:3rem;width:unset;height:unset}.fileActions{display:flex;flex-direction:row;justify-content:flex-end;gap:.5rem}.removeIcon ::ng-deep i,.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}.removeIcon ::ng-deep mat-icon,.downloadIcon ::ng-deep mat-icon{font-size:2rem}.removeIcon:hover,.downloadIcon:hover{cursor:pointer}smart-icon{display:flex;align-items:center}\n"] }]
8885
+ args: [{ selector: 'smartfileuploader', imports: [NgClass, MatLabel, MatIcon, MatButton, UiActionButtonComponent, SmartIconComponent], template: "<div\n class=\"container\"\n [ngClass]=\"{ disabledWidget: isDisabled() }\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [class.dragover]=\"isDragOver\"\n >\n <div class=\"fileContainer\" (click)=\"fileInput.click()\">\n <input\n #fileInput\n id=\"addFile\"\n placeholder=\"fileInput\"\n type=\"file\"\n (change)=\"getFile($event)\"\n class=\"file\"\n accept=\"{{ fileFormats()?.join(', ') }}\"\n [size]=\"maxSizeMb()\"\n [multiple]=\"isMultiple()\"\n [disabled]=\"isDisabled()\"\n style=\"display: none\"\n />\n <div class=\"fileUploadContentContainer\">\n <div class=\"icon\">\n @if (useIconButton()) {\n <mat-label class=\"addFileButton\">\n <mat-icon color=\"primary\" class=\"addCircle\">add_circle</mat-icon>\n </mat-label>\n }\n @if (!useIconButton()) {\n <button mat-raised-button color=\"primary\" class=\"addFileButton\">\n {{ i18n!.addFile }}\n </button>\n }\n </div>\n <div class=\"labels\">\n @if (useIconButton()) {\n <mat-label class=\"label primary title\">\n {{ i18n!.addFile }}\n </mat-label>\n }\n <mat-label class=\"label secondary\"> {{ i18n!.browseOrDrag }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.maxSize }} </mat-label>\n <mat-label class=\"subLabel primary\"> {{ i18n!.formats }} </mat-label>\n </div>\n @if (files.length) {\n <div class=\"uploadButton\">\n <ui-action-button\n (actionClick)=\"uploadFile($event)\"\n [code]=\"'default-upload'\"\n [descriptor]=\"uploadButton\"\n >\n </ui-action-button>\n </div>\n }\n </div>\n </div>\n\n @if (errors.length) {\n <div class=\"errorMessage\">\n <smart-icon [icon]=\"'error'\" [color]=\"'warn'\"></smart-icon>\n <div class=\"errors\">\n @for (error of errors; track error) {\n <span>{{ error }}</span>\n }\n </div>\n </div>\n }\n\n @if (files.length) {\n <div class=\"uploadedFilesContainer\">\n @for (file of files; track file; let i = $index) {\n <div class=\"uploadedFile\">\n @if (filePreviewUrl(file)) {\n <img [src]=\"filePreviewUrl(file)\" [alt]=\"file.name\" width=\"50\" height=\"50\" />\n } @else {\n <smart-icon [icon]=\"'insert_drive_file'\"></smart-icon>\n }\n <div class=\"fileData\">\n <div class=\"fileDataContainer\">\n <span class=\"fileName\">{{ file.name }}</span>\n <span class=\"fileSize\">{{ formatSize(file.size) }}</span>\n </div>\n </div>\n <div class=\"fileActions\">\n <smart-icon\n class=\"downloadIcon\"\n icon=\"download\"\n (click)=\"downloadFile(file)\"\n [attr.data-testid]=\"'default_download'\"\n ></smart-icon>\n <smart-icon\n class=\"removeIcon\"\n icon=\"delete\"\n [attr.data-testid]=\"'default_remove'\"\n (click)=\"remove(i)\"\n ></smart-icon>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{--border-color: #a6aabd60;--warninig-color: #be2d2e;--def-border-radius: .5rem}.container{display:flex;flex-direction:column;border:2px dashed var(--border-color);border-radius:var(--def-border-radius)}.fileContainer{cursor:pointer;padding:1rem;display:flex;flex-direction:column}.fileContainer:hover{background-color:rgb(from var(--border-color) r g b / .1)}.disabledWidget ::ng-deep .fileContainer:hover{background-color:unset;cursor:unset}.disabledWidget ::ng-deep *{opacity:.85}.dragover{background-color:rgb(from var(--border-color) r g b / .1)}.fileUploadContentContainer{display:flex;flex-direction:row;gap:1rem}.icon mat-icon{font-size:3rem;width:unset;height:unset}.icon{align-content:center}.labels{flex:1;display:flex;flex-direction:column;justify-content:center;width:fit-content}.uploadButton{align-content:center}.primary{color:var(--primary-color)}.secondary{color:var(--gray)}.label{margin:unset}.subLabel{font-size:smaller}.title{padding-bottom:.3rem}.errorMessage,.uploadedFilesContainer{border-top:2px solid var(--border-color)}.errorMessage{display:flex;flex-direction:row;align-items:center;color:var(--warninig-color);padding:.5rem 1rem;gap:1rem}.errorMessage ::ng-deep mat-icon{color:var(--warninig-color)}.errors{display:flex;flex-direction:column}.uploadedFile{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;padding:1rem;border-bottom:1px solid #e0e0e0;gap:1rem}.uploadedFile:last-child{border-bottom:none}.fileSize{display:flex;flex-direction:row;font-size:smaller}.fileData{flex:1;display:flex;flex-direction:column}.fileDataContainer{display:flex;flex-direction:column;justify-content:flex-end;width:fit-content}.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}smart-icon ::ng-deep mat-icon{font-size:3rem;width:unset;height:unset}.fileActions{display:flex;flex-direction:row;justify-content:flex-end;gap:.5rem}.removeIcon ::ng-deep i,.removeIcon ::ng-deep mat-icon{color:var(--warninig-color)}.removeIcon ::ng-deep mat-icon,.downloadIcon ::ng-deep mat-icon{font-size:2rem}.removeIcon:hover,.downloadIcon:hover{cursor:pointer}smart-icon{display:flex;align-items:center}\n"] }]
8840
8886
  }], propDecorators: { fileInput: [{
8841
8887
  type: ViewChild,
8842
8888
  args: ['fileInput']
@@ -9522,6 +9568,743 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9522
9568
  type: Input
9523
9569
  }], uploadFilesEvent: [{ type: i0.Output, args: ["uploadFilesEvent"] }] } });
9524
9570
 
9571
+ /**
9572
+ * Turns every toolbar slot (`[data-sb4-toolbar]`) under the container into a live toolbar
9573
+ * rendered into the marker element itself. Only the address and the looks are set: the toolbar
9574
+ * pulls its entries and its executor through the element injector, exactly as one written into
9575
+ * the owner's template would. The caller owns the returned refs and must destroy them before
9576
+ * the container's html is rewritten — rewriting alone leaks them.
9577
+ */
9578
+ function hydrateToolbars(container, ctx) {
9579
+ const refs = [];
9580
+ container.querySelectorAll('[data-sb4-toolbar]').forEach((marker) => {
9581
+ const id = marker.getAttribute('data-sb4-toolbar');
9582
+ if (!id) {
9583
+ ctx.warn('a toolbar slot with an empty data-sb4-toolbar is skipped');
9584
+ return;
9585
+ }
9586
+ const ref = createComponent(UiActionToolbarComponent, {
9587
+ hostElement: marker,
9588
+ elementInjector: ctx.elementInjector,
9589
+ environmentInjector: ctx.environmentInjector,
9590
+ });
9591
+ ref.setInput('id', id);
9592
+ ref.setInput('toolbarPropertes', toolbarProperties(marker, ctx));
9593
+ // Without a zone nothing else would ever refresh a view that is in no template.
9594
+ ctx.appRef.attachView(ref.hostView);
9595
+ ref.changeDetectorRef.detectChanges();
9596
+ refs.push(ref);
9597
+ });
9598
+ return refs;
9599
+ }
9600
+ function toolbarProperties(marker, ctx) {
9601
+ return {
9602
+ direction: enumAttribute(marker, 'data-sb4-toolbar-direction', ToolbarDirection, ctx),
9603
+ alignment: enumAttribute(marker, 'data-sb4-toolbar-alignment', ToolbarAlignment, ctx),
9604
+ scrollable: marker.hasAttribute('data-sb4-toolbar-scrollable'),
9605
+ };
9606
+ }
9607
+ function enumAttribute(marker, name, values, ctx) {
9608
+ const value = marker.getAttribute(name);
9609
+ if (!value) {
9610
+ return undefined;
9611
+ }
9612
+ if (!Object.values(values).includes(value)) {
9613
+ ctx.warn(`${name}="${value}" is not one of ${Object.values(values).join(', ')}, ignored`);
9614
+ return undefined;
9615
+ }
9616
+ return value;
9617
+ }
9618
+
9619
+ /** Pipes that must have an argument, and pipes that must not; the Java scanner checks the same. */
9620
+ const PIPES_REQUIRING_ARGUMENT = ['label'];
9621
+ const PIPES_WITHOUT_ARGUMENT = ['upper', 'lower'];
9622
+ /**
9623
+ * The closed set of formatting pipes; HTML-WIDGET.md is the reference and the Java
9624
+ * HtmlTemplateScanner.PIPES mirrors the names. An empty value passes through every pipe but
9625
+ * `default` untouched, so a missing field stays a silent empty string.
9626
+ */
9627
+ const PIPES = {
9628
+ date: (v, arg, ctx) => formatDate(v, arg ?? 'yyyy.MM.dd', ctx),
9629
+ datetime: (v, arg, ctx) => formatDate(v, arg ?? 'yyyy.MM.dd H:mm', ctx),
9630
+ time: (v, arg, ctx) => formatDate(v, arg ?? 'H:mm', ctx),
9631
+ number: (v, arg, ctx) => formatNumber(v, arg ?? '1.0-3', ctx),
9632
+ label: (v, arg, ctx) => {
9633
+ const valueSet = ctx.valueSets?.[arg];
9634
+ if (isEmpty(v) || !valueSet) {
9635
+ return v;
9636
+ }
9637
+ return valueSetLabelOf(valueSet, v) ?? v;
9638
+ },
9639
+ default: (v, arg) => (isEmpty(v) ? (arg ?? '') : v),
9640
+ upper: (v, _arg, ctx) => (isEmpty(v) ? v : String(v).toLocaleUpperCase(locales(ctx))),
9641
+ lower: (v, _arg, ctx) => (isEmpty(v) ? v : String(v).toLocaleLowerCase(locales(ctx))),
9642
+ };
9643
+ function isEmpty(v) {
9644
+ return v === undefined || v === null || v === '';
9645
+ }
9646
+ // The backend may name the locale the Java way (hu_HU), which Intl rejects.
9647
+ function locales(ctx) {
9648
+ return ctx.locale?.replace('_', '-');
9649
+ }
9650
+ const TIME_ONLY = /^\d{2}:\d{2}/;
9651
+ function formatDate(v, pattern, ctx) {
9652
+ if (isEmpty(v)) {
9653
+ return v;
9654
+ }
9655
+ // A LocalTime travels without a date, which parseISO does not take.
9656
+ const date = typeof v === 'string' ? parseISO(TIME_ONLY.test(v) ? `1970-01-01T${v}` : v) : undefined;
9657
+ if (!date || !isValid(date)) {
9658
+ ctx.warn(`not an ISO date: ${JSON.stringify(v)}`);
9659
+ return v;
9660
+ }
9661
+ try {
9662
+ return format(date, pattern);
9663
+ }
9664
+ catch (e) {
9665
+ // date-fns throws on the protected tokens (YYYY, DD) and on unknown ones.
9666
+ ctx.warn(`invalid date format '${pattern}': ${e.message}`);
9667
+ return v;
9668
+ }
9669
+ }
9670
+ // Angular's digitsInfo: {minInteger}.{minFraction}-{maxFraction}
9671
+ const DIGITS_INFO = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
9672
+ function formatNumber(v, digitsInfo, ctx) {
9673
+ if (isEmpty(v)) {
9674
+ return v;
9675
+ }
9676
+ const n = typeof v === 'number' ? v : typeof v === 'string' && v.trim() !== '' ? +v : NaN;
9677
+ if (isNaN(n)) {
9678
+ ctx.warn(`not a number: ${JSON.stringify(v)}`);
9679
+ return v;
9680
+ }
9681
+ const parts = DIGITS_INFO.exec(digitsInfo);
9682
+ if (!parts) {
9683
+ ctx.warn(`invalid digitsInfo '${digitsInfo}'`);
9684
+ return v;
9685
+ }
9686
+ const minimumFractionDigits = +(parts[3] ?? 0);
9687
+ return new Intl.NumberFormat(locales(ctx), {
9688
+ minimumIntegerDigits: +(parts[1] ?? 1),
9689
+ minimumFractionDigits,
9690
+ maximumFractionDigits: Math.max(+(parts[5] ?? 3), minimumFractionDigits),
9691
+ }).format(n);
9692
+ }
9693
+
9694
+ const IDENTIFIER = '[A-Za-z_][A-Za-z0-9_]*';
9695
+ const PATH = new RegExp(`^((?:\\.\\./)*)(${IDENTIFIER}(?:\\.${IDENTIFIER})*)$`);
9696
+ const PIPE_NAME = new RegExp(IDENTIFIER, 'y');
9697
+ function resolveTemplate(template, scope, ctx) {
9698
+ let nodes;
9699
+ try {
9700
+ nodes = parse(template);
9701
+ }
9702
+ catch (e) {
9703
+ return { html: template, errors: [e.message] };
9704
+ }
9705
+ const out = [];
9706
+ render(nodes, [scope], ctx, out);
9707
+ return { html: out.join(''), errors: [] };
9708
+ }
9709
+ /** Walks a dot-path; a missing, null or non-object step anywhere gives undefined. */
9710
+ function lookupPath(scope, path) {
9711
+ let current = scope;
9712
+ for (const segment of path.split('.')) {
9713
+ if (current === null || typeof current !== 'object') {
9714
+ return undefined;
9715
+ }
9716
+ current = current[segment];
9717
+ }
9718
+ return current;
9719
+ }
9720
+ /**
9721
+ * The scope a root gives: the object it names in the data, the data itself without a root.
9722
+ * `undefined` when that is no object — a list, a single value or nothing at all.
9723
+ */
9724
+ function rootScope(data, root) {
9725
+ const scope = root ? lookupPath(data, root) : data;
9726
+ return scope !== null && typeof scope === 'object' && !Array.isArray(scope) ? scope : undefined;
9727
+ }
9728
+ function parse(template) {
9729
+ const root = [];
9730
+ // Open sections; the last one receives the nodes.
9731
+ const open = [];
9732
+ const target = () => (open.length ? open[open.length - 1].children : root);
9733
+ let pos = 0;
9734
+ while (true) {
9735
+ const start = template.indexOf('{{', pos);
9736
+ if (start < 0) {
9737
+ break;
9738
+ }
9739
+ const end = template.indexOf('}}', start + 2);
9740
+ if (end < 0) {
9741
+ throw new Error(`Unterminated placeholder: ${template.substring(start)}`);
9742
+ }
9743
+ const tag = template.substring(start, end + 2);
9744
+ if (template[start + 2] === '{' || template[start + 2] === '&') {
9745
+ throw new Error(`Raw placeholders are not supported: ${tag}`);
9746
+ }
9747
+ const content = template.substring(start + 2, end).trim();
9748
+ if (!content) {
9749
+ throw new Error(`Empty placeholder: ${tag}`);
9750
+ }
9751
+ if (start > pos) {
9752
+ target().push({ kind: 'text', text: template.substring(pos, start) });
9753
+ }
9754
+ const sigil = content[0];
9755
+ if (sigil === '#' || sigil === '?' || sigil === '^') {
9756
+ const path = content.substring(1).trim();
9757
+ if (path.includes('|')) {
9758
+ throw new Error(`A section tag cannot have pipes: ${tag}`);
9759
+ }
9760
+ const section = {
9761
+ kind: 'section',
9762
+ sigil,
9763
+ source: path,
9764
+ ...parsePath(path, tag, open),
9765
+ children: [],
9766
+ };
9767
+ target().push(section);
9768
+ open.push(section);
9769
+ }
9770
+ else if (sigil === '/') {
9771
+ const path = content.substring(1).trim();
9772
+ const section = open.pop();
9773
+ if (!section) {
9774
+ throw new Error(`Closing tag without an open section: ${tag}`);
9775
+ }
9776
+ if (section.source !== path) {
9777
+ throw new Error(`Closing tag does not match the open section {{/${section.source}}}: ${tag}`);
9778
+ }
9779
+ }
9780
+ else {
9781
+ const pipe = content.indexOf('|');
9782
+ const path = (pipe < 0 ? content : content.substring(0, pipe)).trim();
9783
+ target().push({
9784
+ kind: 'value',
9785
+ ...(path === '.' ? { parents: 0, path } : parsePath(path, tag, open)),
9786
+ pipes: pipe < 0 ? [] : parsePipes(content.substring(pipe + 1), tag),
9787
+ tag,
9788
+ });
9789
+ }
9790
+ pos = end + 2;
9791
+ }
9792
+ if (open.length) {
9793
+ throw new Error(`Section is not closed: {{/${open[open.length - 1].source}}} is missing`);
9794
+ }
9795
+ if (pos < template.length) {
9796
+ root.push({ kind: 'text', text: template.substring(pos) });
9797
+ }
9798
+ return root;
9799
+ }
9800
+ /** Only an entering section is a level for `../`: guards never moved the scope. */
9801
+ function parsePath(path, tag, open) {
9802
+ const match = PATH.exec(path);
9803
+ if (!match) {
9804
+ throw new Error(`Invalid path '${path}' in ${tag}`);
9805
+ }
9806
+ const parents = match[1].length / '../'.length;
9807
+ if (parents > open.filter((section) => section.sigil === '#').length) {
9808
+ throw new Error(`Path '${path}' goes above the root in ${tag}`);
9809
+ }
9810
+ return { parents, path: match[2] };
9811
+ }
9812
+ /**
9813
+ * The pipe chain after the path: `name` or `name:'literal'`, separated by `|`. The literal is
9814
+ * single-quoted with `\'` and `\\` escapes; it is the only place a `|` may appear without starting
9815
+ * the next pipe.
9816
+ */
9817
+ function parsePipes(chain, tag) {
9818
+ const pipes = [];
9819
+ let i = 0;
9820
+ while (true) {
9821
+ i = skipSpaces(chain, i);
9822
+ PIPE_NAME.lastIndex = i;
9823
+ const name = PIPE_NAME.exec(chain)?.[0];
9824
+ if (!name) {
9825
+ throw new Error(`Missing pipe name in ${tag}`);
9826
+ }
9827
+ i = skipSpaces(chain, i + name.length);
9828
+ let arg;
9829
+ if (chain[i] === ':') {
9830
+ i = skipSpaces(chain, i + 1);
9831
+ if (chain[i] !== "'") {
9832
+ throw new Error(`Pipe argument must be a single-quoted literal in ${tag}`);
9833
+ }
9834
+ arg = '';
9835
+ i++;
9836
+ while (i < chain.length && chain[i] !== "'") {
9837
+ if (chain[i] === '\\' && i + 1 < chain.length) {
9838
+ i++;
9839
+ }
9840
+ arg += chain[i];
9841
+ i++;
9842
+ }
9843
+ if (i >= chain.length) {
9844
+ throw new Error(`Unterminated pipe argument in ${tag}`);
9845
+ }
9846
+ i = skipSpaces(chain, i + 1);
9847
+ }
9848
+ if (PIPES_REQUIRING_ARGUMENT.includes(name) && arg === undefined) {
9849
+ throw new Error(`Pipe '${name}' requires an argument in ${tag}`);
9850
+ }
9851
+ if (PIPES_WITHOUT_ARGUMENT.includes(name) && arg !== undefined) {
9852
+ throw new Error(`Pipe '${name}' does not take an argument in ${tag}`);
9853
+ }
9854
+ pipes.push({ name, arg });
9855
+ if (i >= chain.length) {
9856
+ return pipes;
9857
+ }
9858
+ if (chain[i] !== '|') {
9859
+ throw new Error(`Unexpected '${chain[i]}' after pipe '${name}' in ${tag}`);
9860
+ }
9861
+ i++;
9862
+ }
9863
+ }
9864
+ function skipSpaces(s, i) {
9865
+ while (i < s.length && /\s/.test(s[i])) {
9866
+ i++;
9867
+ }
9868
+ return i;
9869
+ }
9870
+ /**
9871
+ * `scopes` holds one entry per open entering section above the root scope, the innermost last;
9872
+ * the parser has already checked that no `../` reaches below its bottom.
9873
+ */
9874
+ function render(nodes, scopes, ctx, out) {
9875
+ const scope = scopes[scopes.length - 1];
9876
+ for (const node of nodes) {
9877
+ if (node.kind === 'text') {
9878
+ out.push(node.text);
9879
+ }
9880
+ else if (node.kind === 'value') {
9881
+ out.push(renderValue(node, scopes, ctx));
9882
+ }
9883
+ else {
9884
+ const value = lookup(scopes, node);
9885
+ if (node.sigil === '^') {
9886
+ if (!truthy(value)) {
9887
+ render(node.children, scopes, ctx, out);
9888
+ }
9889
+ }
9890
+ else if (!truthy(value)) {
9891
+ continue;
9892
+ }
9893
+ else if (node.sigil === '?') {
9894
+ render(node.children, scopes, ctx, out);
9895
+ }
9896
+ else if (Array.isArray(value)) {
9897
+ value.forEach((item) => render(node.children, [...scopes, item], ctx, out));
9898
+ }
9899
+ else if (typeof value === 'object') {
9900
+ render(node.children, [...scopes, value], ctx, out);
9901
+ }
9902
+ else {
9903
+ ctx.warn(`{{#${node.source}}} entered a single value; use {{?${node.source}}} to guard on it`);
9904
+ // Still a level, so `../` inside counts the same as the server's field derivation does.
9905
+ render(node.children, [...scopes, scope], ctx, out);
9906
+ }
9907
+ }
9908
+ }
9909
+ }
9910
+ function lookup(scopes, path) {
9911
+ return lookupPath(scopes[scopes.length - 1 - path.parents], path.path);
9912
+ }
9913
+ function renderValue(node, scopes, ctx) {
9914
+ let value = node.path === '.' ? scopes[scopes.length - 1] : lookup(scopes, node);
9915
+ for (const pipe of node.pipes) {
9916
+ // Own names only: `constructor` and the like must not reach Object.prototype.
9917
+ if (Object.prototype.hasOwnProperty.call(PIPES, pipe.name)) {
9918
+ value = PIPES[pipe.name](value, pipe.arg, ctx);
9919
+ }
9920
+ else {
9921
+ ctx.warn(`unknown pipe '${pipe.name}' in ${node.tag}, the value is left unformatted`);
9922
+ }
9923
+ }
9924
+ if (value === undefined || value === null) {
9925
+ return '';
9926
+ }
9927
+ if (typeof value === 'object') {
9928
+ ctx.warn(`${node.tag} names an object or a list, rendered empty`);
9929
+ return '';
9930
+ }
9931
+ return escapeHtml(String(value));
9932
+ }
9933
+ /** False: undefined, null, false, '' and the empty list. Zero is true, unlike in Mustache. */
9934
+ function truthy(value) {
9935
+ return !(value === undefined ||
9936
+ value === null ||
9937
+ value === false ||
9938
+ value === '' ||
9939
+ (Array.isArray(value) && value.length === 0));
9940
+ }
9941
+ const ESCAPES = {
9942
+ '&': '&amp;',
9943
+ '<': '&lt;',
9944
+ '>': '&gt;',
9945
+ '"': '&quot;',
9946
+ "'": '&#39;',
9947
+ };
9948
+ function escapeHtml(s) {
9949
+ return s.replace(/[&<>"']/g, (c) => ESCAPES[c]);
9950
+ }
9951
+
9952
+ /**
9953
+ * The style sheets of server-sent HTML (`HtmlProperties.css`): one `<style>` element in the
9954
+ * document head per distinct text, however many widgets, cards or cells use it, removed when the
9955
+ * last of them lets it go. See HTML-WIDGET.md.
9956
+ */
9957
+ class SmartHtmlStyles {
9958
+ constructor() {
9959
+ this.document = inject(DOCUMENT);
9960
+ // A host with a strict style-src passes its nonce this way; the sheet is inline otherwise.
9961
+ this.nonce = inject(CSP_NONCE, { optional: true });
9962
+ this.sheets = new Map();
9963
+ }
9964
+ /** Adds the sheet unless it is there already; the returned function lets it go, once. */
9965
+ acquire(css) {
9966
+ let sheet = this.sheets.get(css);
9967
+ if (!sheet) {
9968
+ const element = this.document.createElement('style');
9969
+ element.setAttribute('data-sb4-html-css', '');
9970
+ if (this.nonce) {
9971
+ element.setAttribute('nonce', this.nonce);
9972
+ }
9973
+ element.textContent = css;
9974
+ this.document.head.appendChild(element);
9975
+ sheet = { element, users: 0 };
9976
+ this.sheets.set(css, sheet);
9977
+ }
9978
+ const used = sheet;
9979
+ used.users++;
9980
+ let released = false;
9981
+ return () => {
9982
+ if (released) {
9983
+ return;
9984
+ }
9985
+ released = true;
9986
+ used.users--;
9987
+ if (used.users === 0) {
9988
+ used.element.remove();
9989
+ this.sheets.delete(css);
9990
+ }
9991
+ };
9992
+ }
9993
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlStyles, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
9994
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlStyles, providedIn: 'root' }); }
9995
+ }
9996
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlStyles, decorators: [{
9997
+ type: Injectable,
9998
+ args: [{ providedIn: 'root' }]
9999
+ }] });
10000
+
10001
+ const TRIGGER = '[data-sb4-action]';
10002
+ /** Elements the browser already makes focusable and fires a click on from the keyboard. */
10003
+ const NATIVE = 'button, a[href], input, select, textarea';
10004
+ /**
10005
+ * The action triggers of a container: any element carrying `data-sb4-action` (and optionally
10006
+ * `data-sb4-action-identifier`) fires the action of that address from the nearest action list,
10007
+ * whichever toolbar it is addressed to. One delegated listener per event on the container, so it
10008
+ * survives the html being rewritten; the action is looked up when the click happens.
10009
+ */
10010
+ function attachActionTriggers(container, execution, warn) {
10011
+ // What mark() added, so that it takes back only its own and never the author's attributes.
10012
+ const added = new WeakMap();
10013
+ const warned = new WeakSet();
10014
+ const resolve = (element) => {
10015
+ const code = element.getAttribute('data-sb4-action');
10016
+ const identifier = element.getAttribute('data-sb4-action-identifier') || undefined;
10017
+ const hits = (execution.entries() ?? []).filter(
10018
+ // using equality is a must here, undefined and null should be equal
10019
+ (entry) => entry.uiAction.code === code && entry.uiAction.identifier == identifier);
10020
+ if (hits.length !== 1 && !warned.has(element)) {
10021
+ warned.add(element);
10022
+ const address = `'${code}'${identifier ? ` (identifier '${identifier}')` : ''}`;
10023
+ warn(hits.length
10024
+ ? `action ${address} is offered ${hits.length} times, the first one is fired`
10025
+ : `action ${address} is not offered here, its trigger is inert`);
10026
+ }
10027
+ return hits[0];
10028
+ };
10029
+ /** The innermost trigger at or above the event target whose action is offered. */
10030
+ const triggerOf = (event) => {
10031
+ let element = event.target?.closest?.(TRIGGER) ?? null;
10032
+ while (element && container.contains(element)) {
10033
+ const entry = resolve(element);
10034
+ if (entry) {
10035
+ return { element, entry };
10036
+ }
10037
+ element = element.parentElement?.closest(TRIGGER) ?? null;
10038
+ }
10039
+ return undefined;
10040
+ };
10041
+ const onClick = (event) => {
10042
+ const trigger = triggerOf(event);
10043
+ if (!trigger) {
10044
+ return;
10045
+ }
10046
+ // The trigger is the whole reaction to this click: neither the card around it nor the link
10047
+ // it may sit on gets one.
10048
+ event.stopPropagation();
10049
+ if (trigger.element.matches('a[href]')) {
10050
+ event.preventDefault();
10051
+ }
10052
+ execution.fire(trigger.entry);
10053
+ };
10054
+ const onDoubleClick = (event) => {
10055
+ if (triggerOf(event)) {
10056
+ event.stopPropagation();
10057
+ }
10058
+ };
10059
+ const onKeydown = (event) => {
10060
+ if (event.key !== 'Enter' && event.key !== ' ') {
10061
+ return;
10062
+ }
10063
+ const trigger = triggerOf(event);
10064
+ if (!trigger || trigger.element !== event.target || trigger.element.matches(NATIVE)) {
10065
+ return;
10066
+ }
10067
+ event.stopPropagation();
10068
+ event.preventDefault();
10069
+ execution.fire(trigger.entry);
10070
+ };
10071
+ container.addEventListener('click', onClick);
10072
+ container.addEventListener('dblclick', onDoubleClick);
10073
+ container.addEventListener('keydown', onKeydown);
10074
+ return {
10075
+ mark: () => {
10076
+ container.querySelectorAll(TRIGGER).forEach((element) => {
10077
+ const entry = resolve(element);
10078
+ const own = added.get(element) ?? { role: false, tabindex: false };
10079
+ added.set(element, own);
10080
+ const interactive = !!entry && !element.matches(NATIVE);
10081
+ own.role = ownAttribute(element, 'role', 'button', interactive, own.role);
10082
+ own.tabindex = ownAttribute(element, 'tabindex', '0', interactive, own.tabindex);
10083
+ const disabled = !!entry?.uiAction.disabled;
10084
+ element.classList.toggle('sb4-action-disabled', disabled);
10085
+ element.classList.toggle('sb4-action-inert', !entry);
10086
+ if (disabled) {
10087
+ element.setAttribute('aria-disabled', 'true');
10088
+ }
10089
+ else {
10090
+ element.removeAttribute('aria-disabled');
10091
+ }
10092
+ });
10093
+ },
10094
+ dispose: () => {
10095
+ container.removeEventListener('click', onClick);
10096
+ container.removeEventListener('dblclick', onDoubleClick);
10097
+ container.removeEventListener('keydown', onKeydown);
10098
+ },
10099
+ };
10100
+ }
10101
+ /** Sets or takes back an attribute this module owns; an attribute the author wrote stays. */
10102
+ function ownAttribute(element, name, value, wanted, owned) {
10103
+ if (wanted && !element.hasAttribute(name)) {
10104
+ element.setAttribute(name, value);
10105
+ return true;
10106
+ }
10107
+ if (!wanted && owned) {
10108
+ element.removeAttribute(name);
10109
+ return false;
10110
+ }
10111
+ return owned;
10112
+ }
10113
+
10114
+ /**
10115
+ * The class the container carries while the html on screen is about to be replaced. A style sheet
10116
+ * that gives it an animation or transition plays that before the new html is written; without one
10117
+ * the html is written at once. See HTML-WIDGET.md.
10118
+ */
10119
+ const LEAVING_CLASS = 'sb4-html-leaving';
10120
+ /** The longest a leave animation may hold the new html back, an endless one included. */
10121
+ const LEAVE_TIMEOUT_MS = 600;
10122
+ /** Call from an injection context; registers dispose() on the DestroyRef. */
10123
+ function injectSmartHtmlRenderer(container) {
10124
+ const session = inject(SmartSessionService);
10125
+ const styles = inject(SmartHtmlStyles);
10126
+ const execution = injectUiActionExecution();
10127
+ const hydration = {
10128
+ appRef: inject(ApplicationRef),
10129
+ elementInjector: inject(Injector),
10130
+ environmentInjector: inject(EnvironmentInjector),
10131
+ warn,
10132
+ };
10133
+ let current;
10134
+ // The html waiting for the leave animation of the one on screen, and the leave it belongs to.
10135
+ let pending;
10136
+ let leave = 0;
10137
+ let disposed = false;
10138
+ let template = '';
10139
+ let refs = [];
10140
+ let css;
10141
+ let releaseCss = () => { };
10142
+ // A card re-resolves on every model change; one line per distinct problem is enough.
10143
+ const reported = new Set();
10144
+ function warn(message) {
10145
+ report(message, console.warn);
10146
+ }
10147
+ function report(message, log) {
10148
+ if (!reported.has(message)) {
10149
+ reported.add(message);
10150
+ log(`smart-html: ${message} — in ${template.substring(0, 80)}`);
10151
+ }
10152
+ }
10153
+ function locale() {
10154
+ try {
10155
+ return session.getLocale();
10156
+ }
10157
+ catch {
10158
+ return undefined;
10159
+ }
10160
+ }
10161
+ const triggers = attachActionTriggers(container, execution, warn);
10162
+ // The list may change without the html changing: an action gets disabled, or arrives later.
10163
+ const marking = effect(() => {
10164
+ execution.entries();
10165
+ untracked(() => triggers.mark());
10166
+ }, /* @ts-ignore */
10167
+ ...(ngDevMode ? [{ debugName: "marking" }] : /* istanbul ignore next */ []));
10168
+ const destroyToolbars = () => {
10169
+ refs.forEach((ref) => ref.destroy());
10170
+ refs = [];
10171
+ };
10172
+ const write = (html) => {
10173
+ current = html;
10174
+ // Rewriting the html does not destroy the toolbars hydrated into it.
10175
+ destroyToolbars();
10176
+ // Trusted as authored by the backend; every value the resolver put in is escaped.
10177
+ container.innerHTML = html;
10178
+ refs = hydrateToolbars(container, hydration);
10179
+ triggers.mark();
10180
+ };
10181
+ const cancelLeave = () => {
10182
+ leave++;
10183
+ pending = undefined;
10184
+ container.classList.remove(LEAVING_CLASS);
10185
+ };
10186
+ /** Plays what the style sheets give the leaving class, then writes the latest pending html. */
10187
+ const leaveThenWrite = (html) => {
10188
+ // Only what the class starts counts; an entry or endless animation already running does not.
10189
+ const running = new Set(container.getAnimations({ subtree: true }));
10190
+ container.classList.add(LEAVING_CLASS);
10191
+ const leaving = container
10192
+ .getAnimations({ subtree: true })
10193
+ .filter((animation) => !running.has(animation));
10194
+ if (!leaving.length) {
10195
+ container.classList.remove(LEAVING_CLASS);
10196
+ write(html);
10197
+ return;
10198
+ }
10199
+ pending = html;
10200
+ const token = ++leave;
10201
+ Promise.race([
10202
+ Promise.allSettled(leaving.map((animation) => animation.finished)),
10203
+ new Promise((resolve) => setTimeout(resolve, LEAVE_TIMEOUT_MS)),
10204
+ ]).then(() => {
10205
+ if (disposed || token !== leave) {
10206
+ return;
10207
+ }
10208
+ const next = pending;
10209
+ cancelLeave();
10210
+ write(next);
10211
+ });
10212
+ };
10213
+ const renderer = {
10214
+ // Untracked: a caller rendering from an effect depends on its own inputs only, not on
10215
+ // the action list the triggers read.
10216
+ render: (newTemplate, context) => untracked(() => {
10217
+ template = newTemplate;
10218
+ const { html, errors } = resolveTemplate(template, context.data, {
10219
+ valueSets: context.valueSets,
10220
+ locale: locale(),
10221
+ warn,
10222
+ });
10223
+ errors.forEach((error) => report(`the html is left unresolved: ${error}`, console.error));
10224
+ if (pending !== undefined) {
10225
+ // Mid-leave the latest html wins; back to the one on screen, nothing leaves after all.
10226
+ if (html === current) {
10227
+ cancelLeave();
10228
+ }
10229
+ else {
10230
+ pending = html;
10231
+ }
10232
+ return;
10233
+ }
10234
+ if (html === current) {
10235
+ return;
10236
+ }
10237
+ if (current === undefined) {
10238
+ write(html);
10239
+ return;
10240
+ }
10241
+ leaveThenWrite(html);
10242
+ }),
10243
+ useCss: (newCss) => {
10244
+ const next = newCss || undefined;
10245
+ if (next === css) {
10246
+ return;
10247
+ }
10248
+ releaseCss();
10249
+ releaseCss = next ? styles.acquire(next) : () => { };
10250
+ css = next;
10251
+ },
10252
+ dispose: () => {
10253
+ disposed = true;
10254
+ releaseCss();
10255
+ marking.destroy();
10256
+ destroyToolbars();
10257
+ triggers.dispose();
10258
+ },
10259
+ };
10260
+ inject(DestroyRef).onDestroy(() => renderer.dispose());
10261
+ return renderer;
10262
+ }
10263
+
10264
+ /**
10265
+ * The HTML widget: server-sent HTML whose client placeholders are resolved against the model of
10266
+ * the form it sits on, the widget's `root` applied. It has no control, no label and no value of
10267
+ * its own; it follows the form's revision and re-resolves, which rewrites the html only when the
10268
+ * result differs. See HTML-WIDGET.md.
10269
+ */
10270
+ class SmartHtmlWidgetComponent {
10271
+ constructor() {
10272
+ this.service = inject(SmartFormService);
10273
+ this.renderer = injectSmartHtmlRenderer(inject(ElementRef).nativeElement);
10274
+ this.widgetInstance = input.required(/* @ts-ignore */
10275
+ ...(ngDevMode ? [{ debugName: "widgetInstance" }] : /* istanbul ignore next */ []));
10276
+ effect(() => {
10277
+ this.service.revision();
10278
+ const properties = this.widgetInstance().htmlProperties;
10279
+ const model = this.service.smartForm?.componentModel;
10280
+ this.renderer.useCss(properties?.css);
10281
+ this.renderer.render(properties?.html ?? '', {
10282
+ data: this.scope(model?.data, properties?.root, properties?.html),
10283
+ valueSets: model?.valueSets,
10284
+ });
10285
+ });
10286
+ }
10287
+ /** The object the root names; anything else leaves every placeholder empty. */
10288
+ scope(data, root, html) {
10289
+ const scope = rootScope(data, root);
10290
+ if (scope !== undefined) {
10291
+ return scope;
10292
+ }
10293
+ if (root && this.warnedRoot !== root) {
10294
+ this.warnedRoot = root;
10295
+ console.warn(`smart-html: root '${root}' does not name an object, every placeholder is left empty` +
10296
+ ` — in ${html?.substring(0, 80)}`);
10297
+ }
10298
+ return undefined;
10299
+ }
10300
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10301
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: SmartHtmlWidgetComponent, isStandalone: true, selector: "smart-html-widget", inputs: { widgetInstance: { classPropertyName: "widgetInstance", publicName: "widgetInstance", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: '', isInline: true, styles: ["smart-html-widget{display:block}smart-html-widget [data-sb4-action]{cursor:pointer}smart-html-widget [data-sb4-action].sb4-action-inert{cursor:inherit}smart-html-widget [data-sb4-action].sb4-action-disabled{cursor:default;opacity:.5}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
10302
+ }
10303
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlWidgetComponent, decorators: [{
10304
+ type: Component,
10305
+ args: [{ selector: 'smart-html-widget', template: '', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["smart-html-widget{display:block}smart-html-widget [data-sb4-action]{cursor:pointer}smart-html-widget [data-sb4-action].sb4-action-inert{cursor:inherit}smart-html-widget [data-sb4-action].sb4-action-disabled{cursor:default;opacity:.5}\n"] }]
10306
+ }], ctorParameters: () => [], propDecorators: { widgetInstance: [{ type: i0.Input, args: [{ isSignal: true, alias: "widgetInstance", required: true }] }] } });
10307
+
9525
10308
  class SmartMultiFileEditorComponent {
9526
10309
  constructor() {
9527
10310
  this.cdr = inject(ChangeDetectorRef);
@@ -10434,6 +11217,7 @@ class SmartformwidgetComponent {
10434
11217
  widget.type !== SmartFormWidgetType.IMAGE &&
10435
11218
  widget.type !== SmartFormWidgetType.SVG &&
10436
11219
  widget.type !== SmartFormWidgetType.DIV &&
11220
+ widget.type !== SmartFormWidgetType.HTML &&
10437
11221
  widget.type !== SmartFormWidgetType.DIVIDER &&
10438
11222
  widget.type !== SmartFormWidgetType.BUTTON &&
10439
11223
  widget.type !== SmartFormWidgetType.COMPONENT) {
@@ -10459,6 +11243,7 @@ class SmartformwidgetComponent {
10459
11243
  this.widgetInstance.type !== SmartFormWidgetType.IMAGE &&
10460
11244
  this.widgetInstance.type !== SmartFormWidgetType.SVG &&
10461
11245
  this.widgetInstance.type !== SmartFormWidgetType.DIV &&
11246
+ this.widgetInstance.type !== SmartFormWidgetType.HTML &&
10462
11247
  this.widgetInstance.type !== SmartFormWidgetType.DIVIDER &&
10463
11248
  this.widgetInstance.type !== SmartFormWidgetType.BUTTON &&
10464
11249
  this.widgetInstance.type !== SmartFormWidgetType.COMPONENT &&
@@ -10513,6 +11298,7 @@ class SmartformwidgetComponent {
10513
11298
  widgetInstance.type !== SmartFormWidgetType.IMAGE &&
10514
11299
  widgetInstance.type !== SmartFormWidgetType.SVG &&
10515
11300
  widgetInstance.type !== SmartFormWidgetType.DIV &&
11301
+ widgetInstance.type !== SmartFormWidgetType.HTML &&
10516
11302
  widgetInstance.type !== SmartFormWidgetType.DIVIDER &&
10517
11303
  widgetInstance.type !== SmartFormWidgetType.BUTTON &&
10518
11304
  widgetInstance.type !== SmartFormWidgetType.COMPONENT &&
@@ -10803,11 +11589,11 @@ class SmartformwidgetComponent {
10803
11589
  }
10804
11590
  }
10805
11591
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartformwidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10806
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartformwidgetComponent, isStandalone: true, selector: "smartformwidget", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, widgetInstance: { classPropertyName: "widgetInstance", publicName: "widgetInstance", isSignal: false, isRequired: false, transformFunction: null }, onBlur: { classPropertyName: "onBlur", publicName: "onBlur", isSignal: true, isRequired: false, transformFunction: null }, onValueChange: { classPropertyName: "onValueChange", publicName: "onValueChange", isSignal: false, isRequired: false, transformFunction: null }, labelColor: { classPropertyName: "labelColor", publicName: "labelColor", isSignal: true, isRequired: false, transformFunction: null }, sophisticatedValueChange: { classPropertyName: "sophisticatedValueChange", publicName: "sophisticatedValueChange", isSignal: true, isRequired: true, transformFunction: null }, blurSophisticatedValueChange: { classPropertyName: "blurSophisticatedValueChange", publicName: "blurSophisticatedValueChange", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueCleared: "valueCleared" }, viewQueries: [{ propertyName: "chipInputChild", first: true, predicate: ["chipInput"], descendants: true }, { propertyName: "customComponentVcRef", first: true, predicate: ["customComponent"], descendants: true, read: ViewContainerRef }, { propertyName: "quill", first: true, predicate: ["quillEditor"], descendants: true }, { propertyName: "sb4Textarea", first: true, predicate: ["sb4Textarea"], descendants: true }, { propertyName: "dateInputChild", first: true, predicate: ["dateInput"], descendants: true }, { propertyName: "timeInputChild", first: true, predicate: ["timeInput"], descendants: true }], ngImport: i0, template: "<div class=\"container material\" [formGroup]=\"form()\">\n @if (widgetInstance.isVisible === undefined ? true : widgetInstance.isVisible) {\n <div\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n class=\"container\"\n >\n @if (widgetInstance.type === smartFormWidgetType.CONTAINER) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getDirection()\"\n >\n @for (widget of visibleChildren; track widget) {\n <smartformwidget\n [form]=\"form()\"\n [widgetInstance]=\"widget\"\n class=\"container-item\"\n [ngClass]=\"widget.cssClass ?? ''\"\n [onBlur]=\"onBlur()\"\n [onValueChange]=\"onValueChange\"\n [sophisticatedValueChange]=\"sophisticatedValueChange()\"\n [blurSophisticatedValueChange]=\"blurSophisticatedValueChange()\"\n class=\"{{ widget.key }}\"\n [labelColor]=\"labelColor()\"\n ></smartformwidget>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD) {\n <div\n (capsLock)=\"capsOn = $event\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n @if (!widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [attr.inputmode]=\"\n widgetInstance.inputMode ? widgetInstance.inputMode.toLocaleLowerCase() : 'text'\n \"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? (hidePassword ? 'password' : 'text') : '' }}\"\n (keydown.enter)=\"onKeydown()\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n [mask]=\"widgetInstance.mask\"\n />\n }\n <!-- [mask]=\"widgetInstance.mask ?? ''\" -->\n @if (widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n (click)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? 'password' : '' }}\"\n [matAutocomplete]=\"textFieldAuto\"\n (keydown.enter)=\"onKeydown()\"\n />\n }\n @if (widgetInstance.isPassword) {\n <button\n mat-icon-button\n matSuffix\n (click)=\"togglePasswordVisibility($event)\"\n >\n <mat-icon>{{ hidePassword ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n }\n <mat-autocomplete #textFieldAuto=\"matAutocomplete\">\n @for (option of filteredOptions | async; track option) {\n <mat-option [value]=\"option.label\">\n <span [innerHTML]=\"option.label | highlight: toHighlight\"></span>\n </mat-option>\n }\n </mat-autocomplete>\n @if (capsOn && widgetInstance.isPassword) {\n <span class=\"mat-error\">\n {{ widgetInstance.capsLockWarning }}\n </span>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n @if (capsOn && widgetInstance.isPassword) {\n <smart-icon\n [icon]=\"widgetInstance.capsLockWarningIcon ?? 'keyboard_capslock'\"\n color=\"warn\"\n ></smart-icon>\n }\n @if (widgetInstance.icon && widgetInstance.iconPosition === 'PRE') {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n ></smart-icon>\n }\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <div class=\"textFieldButtons\">\n @if (widgetInstance.textFieldProperties?.clearable) {\n <ui-action-button\n class=\"clearButton\"\n [addBasicClasses]=\"false\"\n [descriptor]=\"clearButtonDescriptor\"\n (actionClick)=\"clearField(widgetInstance.key)\"\n />\n }\n </div>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n [color]=\"widgetInstance.textFieldButton.iconColor\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_NUMBER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n [type]=\"'number'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [min]=\"widgetInstance.minValues ?? null\"\n [max]=\"widgetInstance.maxValues ?? null\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (widgetInstance.icon) {\n <smart-icon [icon]=\"widgetInstance.icon\" matSuffix>\n </smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_CHIPS) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipList aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip-row\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ value }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n #chipInput\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [matChipInputAddOnBlur]=\"addOnBlur\"\n [readonly]=\"widgetInstance.isReadonly\"\n [matAutocomplete]=\"chipAuto\"\n (matChipInputTokenEnd)=\"add($event)\"\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n <mat-autocomplete\n #chipAuto=\"matAutocomplete\"\n (optionSelected)=\"selected($event, widgetInstance)\"\n >\n @for (item of widgetInstance.valueList; track item) {\n <mat-option\n [disabled]=\"widgetInstance.isDisabled\"\n [value]=\"item.value\"\n >\n {{ item.label }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-chip-grid>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_LOOKUP) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipListLookup aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ getChipsValue(value) }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n }\n <input\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipListLookup\"\n [matChipInputSeparatorKeyCodes]=\"emptySeparatorKeysCodes\"\n [matChipInputAddOnBlur]=\"false\"\n [readonly]=\"true\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n </mat-chip-grid>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_BOX) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <textarea\n class=\"sb4-textarea\"\n #sb4Textarea\n cols=\"30\"\n cdkTextareaAutosize\n [cdkAutosizeMinRows]=\"widgetInstance.textBoxProperties?.minRows ?? 1\"\n [cdkAutosizeMaxRows]=\"widgetInstance.textBoxProperties?.maxRows ?? undefined\"\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n ></textarea>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance.hint || widgetInstance.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n <div class=\"checkbox-item-container\">\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key }}\"\n (change)=\"onValueChange?.next(widgetInstance)\"\n (change)=\"onBlur()?.next(widgetInstance)\"\n >\n {{ widgetInstance.label }}\n </mat-checkbox>\n </div>\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX_2) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n @for (checkbox of widgetInstance.valueList; track checkbox; let i = $index) {\n <div\n class=\"checkbox-item-container\"\n >\n @if (checkbox.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"checkbox-item-image\"\n [src]=\"checkbox.imageUrl\"\n />\n }\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key + '.' + checkbox.key }}\"\n [value]=\"checkbox.value\"\n (change)=\"onValueChange?.next(checkbox)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n >\n {{ checkbox.label }}\n </mat-checkbox>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RADIO_BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-radio-group\n class=\"input radio-section widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n [attr.data-testid]=\"widgetInstance.key\"\n aria-label=\"{{ widgetInstance.label }}\"\n appearance=\"outline\"\n formControlName=\"{{ widgetInstance.key }}\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <div [ngClass]=\"getDirection()\">\n @for (radio of widgetInstance.valueList; track radio) {\n <div class=\"radio-item-container\">\n @if (radio.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"radio-item-image\"\n [src]=\"radio.imageUrl\"\n />\n }\n <mat-radio-button\n class=\"selecatbleObject\"\n value=\"{{ radio.value }}\"\n [ngClass]=\"getDirection()\"\n (change)=\"onValueChange?.next(radio.value)\"\n [disabled]=\"widgetInstance.isDisabled\"\n >\n {{ radio.label }}\n </mat-radio-button>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n <div class=\"radio-icon\">\n @if (widgetInstance.icon) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n >\n </smart-icon>\n }\n </div>\n </div>\n </mat-radio-group>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_PICKER) {\n <div\n class=\"datePicker widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n matInput\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (change)=\"handleBlurEvent(widgetInstance)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MONTH_PICKER) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div class=\"{{ labelColor() }} smart-form-widget-label\">\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <lib-smart-month-picker\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (valueChange)=\"handleYearMonthPicked($event)\"\n ></lib-smart-month-picker>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_TIME_PICKER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div class=\"dateTimePickerContainer\">\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n #dateInput\n matInput\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n [id]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (blur)=\"onDatePickerBlur($event)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n @if (hasCreated) {\n <mat-form-field\n class=\"input widgetContent time\"\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n appearance=\"outline\"\n >\n <input\n #timeInput\n [formControlName]=\"widgetInstance.key + '-time'\"\n [attr.data-testid]=\"widgetInstance.key + '-time'\"\n [id]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n (blur)=\"onTimePickerBlur($event)\"\n matInput\n />\n </mat-form-field>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon>\n }\n {{ innerOption.label }}\n </mat-option>\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT_MULTIPLE) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n multiple\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon\n >\n }{{ innerOption.label }}</mat-option\n >\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.LABEL) {\n <div\n class=\"label widgetContainer\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n >\n <div class=\"label-title labelContainer\" [ngClass]=\"widgetInstance.cssClass ?? ''\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance.widgetDescription) {\n <p>{{ widgetInstance.widgetDescription }}</p>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TIME) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent time {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent(widgetInstance)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TOGGLE) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <mat-slide-toggle\n formControlName=\"{{ widgetInstance.key }}\"\n [attr.data-testid]=\"widgetInstance.key\"\n (change)=\"onValueChange?.next($event)\"\n [labelPosition]=\"widgetInstance.toggleLabelPosition ?? 'before'\"\n >{{ !widgetInstance.showLabel ? widgetInstance.label : '' }}</mat-slide-toggle\n ><span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.INDICATOR) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} labelContainer {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"smartIndicator widgetContent\">\n <div class=\"indicatorItems {{ widgetInstance.cssClass ?? '' }}\" [ngClass]=\"getNgClass()\">\n @for (item of indicatorItems; track item; let i = $index) {\n <div\n class=\"indicatorItem\"\n [ngClass]=\"getIndicatorItemClass(i)\"\n ></div>\n }\n </div>\n <p [ngClass]=\"getIndicatorStatusLabelColor()\">\n {{ getIndicatorStatusLabel() }}\n </p>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RECORDING_UPLOADER) {\n <div class=\"widgetContainer\">\n <div class=\"widgetItemContainer\">\n <smart-voice-recorder\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MULTI_FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-multi-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n (fileEvent)=\"executeUiAction($event.uiAction)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.IMAGE) {\n <div class=\"widgetContainer imageContainer\">\n @if (widgetInstance.showLabel && getWidgetLabel(widgetInstance)) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance.imageProperties?.image) {\n <smart-icon\n [imageResource]=\"$safeNavigationMigration(widgetInstance.imageProperties?.image)\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n } @else if (widgetInstance.value) {\n <smart-icon\n [(ngModel)]=\"widgetInstance.value\"\n [imageResource]=\"widgetInstance.value\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIV) {\n <div\n class=\"smartDiv\"\n [innerHTML]=\"sanitizeHtml(getWidgetLabel(widgetInstance))\"\n [ngClass]=\"getNgClass()\"\n [class.clickable]=\"!!widgetInstance.divProperties?.onClick\"\n [ngStyle]=\"getStyle()\"\n (click)=\"onDivClick()\"\n >\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SVG) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [innerHTML]=\"sanitizeHtml(widgetInstance.value)\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIVIDER) {\n <div class=\"widgetContainer\">\n <hr\n class=\"smartDivider {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <button\n mat-button\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getButtonType(widgetInstance.uiActionDescriptor)\"\n [color]=\"$safeNavigationMigration(widgetInstance.uiActionDescriptor?.color)\"\n (click)=\"onButtonClicked(widgetInstance)\"\n >\n @if (isOnlyIcon(widgetInstance.uiActionDescriptor)) {\n @if (widgetInstance.uiActionDescriptor?.icon) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n } @else {\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'PRE'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n {{ widgetInstance.uiActionDescriptor?.title }}\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'POST'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n }\n </button>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.COMPONENT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }}\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"widgetContent\">\n <ng-template #customComponent></ng-template>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RICH_TEXT) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <quill-editor\n #quillEditor\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [modules]=\"widgetInstance.isDisabled ? emptyQuillToolbar : widgetInstance.quillModules\"\n [placeholder]=\"widgetInstance.placeholder ?? ''\"\n [readOnly]=\"widgetInstance.isReadonly ?? false\"\n [maxLength]=\"widgetInstance.maxLength ?? 0\"\n (onContentChanged)=\"onRichTextEditorContentChanged($event)\"\n ></quill-editor>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n class=\"rich-text-editor-leeway-counter\"\n >{{ getRichTextEditorLengthLeeway() }}</mat-hint\n >\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SORTABLE) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <lib-sortable-widget\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n ></lib-sortable-widget>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MATRIX) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <table class=\"matrixTable widgetContent\">\n <tr>\n <th></th>\n @for (option of widgetInstance.value.columns; track option) {\n <th class=\"optionLabel\">\n {{ option.displayValue }}\n </th>\n }\n </tr>\n @for (question of widgetInstance.value.rows; track question; let i = $index) {\n <tr>\n <th class=\"questionLabel\">\n <label>{{ question.displayValue }}</label>\n </th>\n @for (option of widgetInstance.value.columns; track option; let j = $index) {\n <td class=\"selectTd\">\n @if (!widgetInstance.isMultiple) {\n <mat-radio-group\n [formControlName]=\"widgetInstance.key + '.' + question.code\"\n [name]=\"'q' + i\"\n >\n <mat-radio-button [value]=\"option.code\"> </mat-radio-button>\n </mat-radio-group>\n }\n @if (widgetInstance.isMultiple) {\n <div>\n <mat-checkbox\n [formControlName]=\"\n widgetInstance.key + '.data.' + question.code + '.' + option.code\n \"\n [value]=\"widgetInstance.value['data'][question.code][option.code]\"\n [checked]=\"true\"\n ></mat-checkbox>\n </div>\n }\n </td>\n }\n <br />\n @if (widgetInstance.button) {\n <button mat-icon-button (click)=\"removeMatrixRow(question)\"\n ><smart-icon icon=\"close\"></smart-icon\n ></button>\n }\n </tr>\n }\n </table>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.YOUTUBE_PLAYER) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <youtube-player\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n videoId=\"{{ widgetInstance.videoId }}\"\n [width]=\"widgetInstance.width\"\n [height]=\"widgetInstance.height\"\n [startSeconds]=\"widgetInstance.startSeconds\"\n [endSeconds]=\"widgetInstance.endSeconds\"\n ></youtube-player>\n @if (\n !widgetInstance?.hint || widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n </div>\n }\n </div>\n", styles: [".ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container:not(.ql-disabled) li[data-list=checked]>.ql-ui,.ql-container:not(.ql-disabled) li[data-list=unchecked]>.ql-ui{cursor:pointer}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0}@supports (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-set:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor table{border-collapse:collapse}.ql-editor td{border:1px solid #000;padding:2px 5px}.ql-editor ol{padding-left:1.5em}.ql-editor li{list-style-type:none;padding-left:1.5em;position:relative}.ql-editor li>.ql-ui:before{display:inline-block;margin-left:-1.5em;margin-right:.3em;text-align:right;white-space:nowrap;width:1.2em}.ql-editor li[data-list=checked]>.ql-ui,.ql-editor li[data-list=unchecked]>.ql-ui{color:#777}.ql-editor li[data-list=bullet]>.ql-ui:before{content:\"\\2022\"}.ql-editor li[data-list=checked]>.ql-ui:before{content:\"\\2611\"}.ql-editor li[data-list=unchecked]>.ql-ui:before{content:\"\\2610\"}@supports (counter-set:none){.ql-editor li[data-list]{counter-set:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list]{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered]{counter-increment:list-0}.ql-editor li[data-list=ordered]>.ql-ui:before{content:counter(list-0,decimal) \". \"}.ql-editor li[data-list=ordered].ql-indent-1{counter-increment:list-1}.ql-editor li[data-list=ordered].ql-indent-1>.ql-ui:before{content:counter(list-1,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-set:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-2{counter-increment:list-2}.ql-editor li[data-list=ordered].ql-indent-2>.ql-ui:before{content:counter(list-2,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-set:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-3{counter-increment:list-3}.ql-editor li[data-list=ordered].ql-indent-3>.ql-ui:before{content:counter(list-3,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-set:list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-4{counter-increment:list-4}.ql-editor li[data-list=ordered].ql-indent-4>.ql-ui:before{content:counter(list-4,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-set:list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-5{counter-increment:list-5}.ql-editor li[data-list=ordered].ql-indent-5>.ql-ui:before{content:counter(list-5,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-set:list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-6{counter-increment:list-6}.ql-editor li[data-list=ordered].ql-indent-6>.ql-ui:before{content:counter(list-6,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-set:list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-reset:list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-7{counter-increment:list-7}.ql-editor li[data-list=ordered].ql-indent-7>.ql-ui:before{content:counter(list-7,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-set:list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-reset:list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-8{counter-increment:list-8}.ql-editor li[data-list=ordered].ql-indent-8>.ql-ui:before{content:counter(list-8,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-set:list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-reset:list-9}}.ql-editor li[data-list=ordered].ql-indent-9{counter-increment:list-9}.ql-editor li[data-list=ordered].ql-indent-9>.ql-ui:before{content:counter(list-9,decimal) \". \"}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor li.ql-direction-rtl{padding-right:1.5em}.ql-editor li.ql-direction-rtl>.ql-ui:before{margin-left:.3em;margin-right:-1.5em;text-align:left}.ql-editor table{table-layout:fixed;width:100%}.ql-editor table td{outline:none}.ql-editor .ql-code-block-container{font-family:monospace}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor .ql-ui{position:absolute}.ql-editor.ql-blank:before{color:#0009;content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-snow.ql-toolbar:after,.ql-snow .ql-toolbar:after{clear:both;content:\"\";display:table}.ql-snow.ql-toolbar button,.ql-snow .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-snow.ql-toolbar button svg,.ql-snow .ql-toolbar button svg{float:left;height:100%}.ql-snow.ql-toolbar button:active:hover,.ql-snow .ql-toolbar button:active:hover{outline:none}.ql-snow.ql-toolbar input.ql-image[type=file],.ql-snow .ql-toolbar input.ql-image[type=file]{display:none}.ql-snow.ql-toolbar button:hover,.ql-snow .ql-toolbar button:hover,.ql-snow.ql-toolbar button:focus,.ql-snow .ql-toolbar button:focus,.ql-snow.ql-toolbar button.ql-active,.ql-snow .ql-toolbar button.ql-active,.ql-snow.ql-toolbar .ql-picker-label:hover,.ql-snow .ql-toolbar .ql-picker-label:hover,.ql-snow.ql-toolbar .ql-picker-label.ql-active,.ql-snow .ql-toolbar .ql-picker-label.ql-active,.ql-snow.ql-toolbar .ql-picker-item:hover,.ql-snow .ql-toolbar .ql-picker-item:hover,.ql-snow.ql-toolbar .ql-picker-item.ql-selected,.ql-snow .ql-toolbar .ql-picker-item.ql-selected{color:#06c}.ql-snow.ql-toolbar button:hover .ql-fill,.ql-snow .ql-toolbar button:hover .ql-fill,.ql-snow.ql-toolbar button:focus .ql-fill,.ql-snow .ql-toolbar button:focus .ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#06c}.ql-snow.ql-toolbar button:hover .ql-stroke,.ql-snow .ql-toolbar button:hover .ql-stroke,.ql-snow.ql-toolbar button:focus .ql-stroke,.ql-snow .ql-toolbar button:focus .ql-stroke,.ql-snow.ql-toolbar button.ql-active .ql-stroke,.ql-snow .ql-toolbar button.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow.ql-toolbar button:hover .ql-stroke-miter,.ql-snow .ql-toolbar button:hover .ql-stroke-miter,.ql-snow.ql-toolbar button:focus .ql-stroke-miter,.ql-snow .ql-toolbar button:focus .ql-stroke-miter,.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#06c}@media(pointer:coarse){.ql-snow.ql-toolbar button:hover:not(.ql-active),.ql-snow .ql-toolbar button:hover:not(.ql-active){color:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#444}}.ql-snow,.ql-snow *{box-sizing:border-box}.ql-snow .ql-hidden{display:none}.ql-snow .ql-out-bottom,.ql-snow .ql-out-top{visibility:hidden}.ql-snow .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-snow .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-snow .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-snow .ql-formats{display:inline-block;vertical-align:middle}.ql-snow .ql-formats:after{clear:both;content:\"\";display:table}.ql-snow .ql-stroke{fill:none;stroke:#444;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-snow .ql-stroke-miter{fill:none;stroke:#444;stroke-miterlimit:10;stroke-width:2}.ql-snow .ql-fill,.ql-snow .ql-stroke.ql-fill{fill:#444}.ql-snow .ql-empty{fill:none}.ql-snow .ql-even{fill-rule:evenodd}.ql-snow .ql-thin,.ql-snow .ql-stroke.ql-thin{stroke-width:1}.ql-snow .ql-transparent{opacity:.4}.ql-snow .ql-direction svg:last-child{display:none}.ql-snow .ql-direction.ql-active svg:last-child{display:inline}.ql-snow .ql-direction.ql-active svg:first-child{display:none}.ql-snow .ql-editor h1{font-size:2em}.ql-snow .ql-editor h2{font-size:1.5em}.ql-snow .ql-editor h3{font-size:1.17em}.ql-snow .ql-editor h4{font-size:1em}.ql-snow .ql-editor h5{font-size:.83em}.ql-snow .ql-editor h6{font-size:.67em}.ql-snow .ql-editor a{text-decoration:underline}.ql-snow .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-snow .ql-editor code,.ql-snow .ql-editor .ql-code-block-container{background-color:#f0f0f0;border-radius:3px}.ql-snow .ql-editor .ql-code-block-container{margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-snow .ql-editor code{font-size:85%;padding:2px 4px}.ql-snow .ql-editor .ql-code-block-container{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-snow .ql-editor img{max-width:100%}.ql-snow .ql-picker{color:#444;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-snow .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-snow .ql-picker-label:before{display:inline-block;line-height:22px}.ql-snow .ql-picker-options{background-color:#fff;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-snow .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-snow .ql-picker.ql-expanded .ql-picker-label{color:#ccc;z-index:2}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-snow .ql-color-picker,.ql-snow .ql-icon-picker{width:28px}.ql-snow .ql-color-picker .ql-picker-label,.ql-snow .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-label svg,.ql-snow .ql-icon-picker .ql-picker-label svg{right:4px}.ql-snow .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-snow .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-snow .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=\"\"]):before{content:attr(data-label)}.ql-snow .ql-picker.ql-header{width:98px}.ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"1\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{content:\"Heading 1\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"2\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{content:\"Heading 2\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"3\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{content:\"Heading 3\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"4\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{content:\"Heading 4\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"5\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{content:\"Heading 5\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"6\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{content:\"Heading 6\"}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{font-size:2em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{font-size:1.5em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{font-size:1.17em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{font-size:1em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{font-size:.83em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{font-size:.67em}.ql-snow .ql-picker.ql-font{width:108px}.ql-snow .ql-picker.ql-font .ql-picker-label:before,.ql-snow .ql-picker.ql-font .ql-picker-item:before{content:\"Sans Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{content:\"Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{content:\"Monospace\"}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{font-family:Georgia,Times New Roman,serif}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{font-family:Monaco,Courier New,monospace}.ql-snow .ql-picker.ql-size{width:98px}.ql-snow .ql-picker.ql-size .ql-picker-label:before,.ql-snow .ql-picker.ql-size .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{content:\"Small\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{content:\"Large\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{content:\"Huge\"}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{font-size:10px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{font-size:18px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{font-size:32px}.ql-snow .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-snow .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-code-block-container{position:relative}.ql-code-block-container .ql-ui{right:5px;top:5px}.ql-toolbar.ql-snow{border:1px solid #ccc;box-sizing:border-box;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding:8px}.ql-toolbar.ql-snow .ql-formats{margin-right:15px}.ql-toolbar.ql-snow .ql-picker-label{border:1px solid transparent}.ql-toolbar.ql-snow .ql-picker-options{border:1px solid transparent;box-shadow:#0003 0 2px 8px}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label,.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{border-color:#ccc}.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover{border-color:#000}.ql-toolbar.ql-snow+.ql-container.ql-snow{border-top:0}.ql-snow .ql-tooltip{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.ql-snow .ql-tooltip:before{content:\"Visit URL:\";line-height:26px;margin-right:8px}.ql-snow .ql-tooltip input[type=text]{display:none;border:1px solid #ccc;font-size:13px;height:26px;margin:0;padding:3px 5px;width:170px}.ql-snow .ql-tooltip a.ql-preview{display:inline-block;max-width:200px;overflow-x:hidden;text-overflow:ellipsis;vertical-align:top}.ql-snow .ql-tooltip a.ql-action:after{border-right:1px solid #ccc;content:\"Edit\";margin-left:16px;padding-right:8px}.ql-snow .ql-tooltip a.ql-remove:before{content:\"Remove\";margin-left:8px}.ql-snow .ql-tooltip a{line-height:26px}.ql-snow .ql-tooltip.ql-editing a.ql-preview,.ql-snow .ql-tooltip.ql-editing a.ql-remove{display:none}.ql-snow .ql-tooltip.ql-editing input[type=text]{display:inline-block}.ql-snow .ql-tooltip.ql-editing a.ql-action:after{border-right:0;content:\"Save\";padding-right:0}.ql-snow .ql-tooltip[data-mode=link]:before{content:\"Enter link:\"}.ql-snow .ql-tooltip[data-mode=formula]:before{content:\"Enter formula:\"}.ql-snow .ql-tooltip[data-mode=video]:before{content:\"Enter video:\"}.ql-snow a{color:#06c}.ql-container.ql-snow{border:1px solid #ccc}.checkbox-section,.radio-section{display:flex;flex-direction:column}.input{width:100%}.direction-col,.toggle-col{display:flex;flex-direction:column;gap:.5em}.toggle-col>label{font-size:.75rem;color:#6b7280;padding-left:.5em}.direction-row{display:flex;flex-direction:row;align-items:center;gap:.5em}.selecatbleObject{margin:.5em}.radioLabel{color:var(--primary-color);text-align:left!important}.container{height:100%}.input{height:100%;display:flex;flex-direction:column}.checkbox{flex-direction:column}.mat-form-field-wrapper{padding-bottom:0!important}.input .mat-mdc-standard-chip.mat-chip-with-trailing-icon{padding-right:12px}.time-picker{display:flex;flex-direction:row;height:100%;border:solid 2px lightgrey;padding:1em;border-radius:4px}.time-picker:hover{border-color:#000}::ng-deep .mat-h4 .mat-body-1 .mat-typography h4{margin:0}.label{margin:28px 0 8px}.smartIndicator{display:flex;flex-direction:column;gap:.25rem;width:-moz-fit-content;width:fit-content}.indicatorItems{display:flex;flex-direction:row;gap:.25rem}.indicatorItem{width:3rem;height:.25rem;background-color:#d3d3d3;border-radius:.5rem}.radio-error{width:-moz-fit-content;width:fit-content;display:flex;flex-direction:row;gap:.5rem}.mat-calendar-previous-button,.mat-calendar-next-button{padding:0;min-width:0;width:40px!important;height:40px!important;flex-shrink:0;line-height:40px;border-radius:50%}.mat-calendar-arrow{height:36px!important;display:flex!important;flex-direction:column!important;justify-content:center}.radio-item-container,.checkbox-item-container{display:flex;flex-direction:column}.widgetContent::ng-deep .ql-container{height:200px;width:460px}.dateTimePickerContainer{display:flex;flex-direction:row;gap:.25rem}.dateTimePickerContainer mat-form-field{flex:1}.date,.time{width:100%}.date .mat-form-field-infix,.time .mat-form-field-infix{width:inherit!important}::ng-deep .mat-icon.mat-drag-indicator{--drag-indicator: #3b3b3b;color:var(--drag-indicator)}.matrixTable{width:100%;border-spacing:0 1rem}.matrixTable th{padding:.25rem}.matrixTable .optionLabel,.matrixTable td{text-align:center}.example-month-picker .mat-calendar-period-button{pointer-events:none}.example-month-picker .mat-calendar-arrow{display:none}.textFieldContainer{display:flex;flex-direction:row}.textFieldContainer{align-content:center;border:1px solid #cbd5e1;border-radius:3px;background-color:#fff}.textFieldContainer input{border:unset}.textFieldContainer:focus-within:not(:has(input:disabled)){outline:0 none;outline-offset:0;box-shadow:0 0 0 .2rem #a6d5fa;border-color:#2196f3}.textFieldContainer:has(input:disabled) .clearButton{cursor:not-allowed;opacity:.6}.textFieldButtons{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.clearButton .mat-mdc-raised-button,.clearButton button{background-color:unset!important;border:unset;color:#6b7280!important;box-shadow:unset;font-size:1rem!important}.clearButton .mat-icon.mat-primary{color:#6b7280!important}.clearButton .mat-mdc-raised-button:hover,.clearButton button:hover{color:#6b7280cc!important;background-color:unset;border:unset;box-shadow:unset;font-size:1rem!important}.mat-mdc-form-field-infix{display:flex;flex-direction:row}textarea:not(:placeholder-shown)~label{top:-.75em!important;font-size:12px!important}.disabledEditor *{-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only}.sb4-textarea{--sb4-textarea-line-height: 20px;line-height:var(--sb4-textarea-line-height);overflow-y:auto!important}.widgetContainer .imageIcon{max-width:unset!important;height:unset!important}.material .sb4-textarea{resize:vertical!important}.material .smart-form-widget-label{font-weight:700}.material .mat-mdc-form-field-subscript-wrapper{display:none}.label-right{display:flex;gap:.5rem;flex-direction:row-reverse}.label-left{display:flex;gap:.5rem;flex-direction:row}.label-top{display:flex;gap:.5rem;flex-direction:column}.label-bottom{display:flex;gap:.5rem;flex-direction:column-reverse}.smartDiv{width:100%}.clickable{cursor:pointer}\n/*!\n * Quill Editor v2.0.3\n * https://quilljs.com\n * Copyright (c) 2017-2024, Slab\n * Copyright (c) 2014, Jason Chen\n * Copyright (c) 2013, salesforce.com\n */\n"], dependencies: [{ kind: "component", type: SmartformwidgetComponent, selector: "smartformwidget", inputs: ["form", "widgetInstance", "onBlur", "onValueChange", "labelColor", "sophisticatedValueChange", "blurSophisticatedValueChange"], outputs: ["valueCleared"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: TrackCapsDirective, selector: "[capsLock]", outputs: ["capsLock"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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: NgxMaskDirective, selector: "input[mask], textarea[mask]", inputs: ["mask", "specialCharacters", "patterns", "prefix", "suffix", "thousandSeparator", "decimalMarker", "dropSpecialCharacters", "hiddenInput", "showMaskTyped", "placeHolderCharacter", "shownMaskExpression", "clearIfNotMatch", "validation", "separatorLimit", "typeFromDecimals", "allowNegativeNumbers", "leadZeroDateTime", "leadZero", "triggerOnMaskChange", "apm", "inputTransformFn", "outputTransformFn", "keepCharacterPositions", "instantPrefix", "defaultValueOnBlur", "value", "disabled", "touched"], outputs: ["valueChange", "touchedChange", "maskFilled"], exportAs: ["mask", "ngxMask"] }, { kind: "directive", type: MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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: "component", type: MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "component", type: MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "directive", type: MatChipRemove, selector: "[matChipRemove]" }, { kind: "directive", type: MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { 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: "directive", type: MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { 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: "component", type: MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: SmartMonthPickerComponent, selector: "lib-smart-month-picker", inputs: ["widgetInstance"], outputs: ["valueChange"] }, { 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: MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "component", type: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: SmartVoiceRecorderComponent, selector: "smart-voice-recorder", inputs: ["widgetInstance"], outputs: ["uploadFilesEvent"] }, { kind: "component", type: SmartFileEditorComponent, selector: "smart-file-editor", inputs: ["widgetInstance"], outputs: ["uploadFilesEvent"] }, { kind: "component", type: SmartMultiFileEditorComponent, selector: "smart-multi-file-editor", inputs: ["widgetInstance"], outputs: ["uploadFilesEvent", "fileEvent"] }, { kind: "component", type: QuillEditorComponent, selector: "quill-editor" }, { kind: "component", type: SortableWidgetComponent, selector: "lib-sortable-widget", inputs: ["widgetInstance"] }, { kind: "component", type: YouTubePlayer, selector: "youtube-player", inputs: ["videoId", "height", "width", "startSeconds", "endSeconds", "suggestedQuality", "playerVars", "disableCookies", "loadApi", "disablePlaceholder", "showBeforeIframeApiLoads", "placeholderButtonLabel", "placeholderImageQuality"], outputs: ["ready", "stateChange", "error", "apiChange", "playbackQualityChange", "playbackRateChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: HighlightPipe, name: "highlight" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
11592
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartformwidgetComponent, isStandalone: true, selector: "smartformwidget", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, widgetInstance: { classPropertyName: "widgetInstance", publicName: "widgetInstance", isSignal: false, isRequired: false, transformFunction: null }, onBlur: { classPropertyName: "onBlur", publicName: "onBlur", isSignal: true, isRequired: false, transformFunction: null }, onValueChange: { classPropertyName: "onValueChange", publicName: "onValueChange", isSignal: false, isRequired: false, transformFunction: null }, labelColor: { classPropertyName: "labelColor", publicName: "labelColor", isSignal: true, isRequired: false, transformFunction: null }, sophisticatedValueChange: { classPropertyName: "sophisticatedValueChange", publicName: "sophisticatedValueChange", isSignal: true, isRequired: true, transformFunction: null }, blurSophisticatedValueChange: { classPropertyName: "blurSophisticatedValueChange", publicName: "blurSophisticatedValueChange", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueCleared: "valueCleared" }, viewQueries: [{ propertyName: "chipInputChild", first: true, predicate: ["chipInput"], descendants: true }, { propertyName: "customComponentVcRef", first: true, predicate: ["customComponent"], descendants: true, read: ViewContainerRef }, { propertyName: "quill", first: true, predicate: ["quillEditor"], descendants: true }, { propertyName: "sb4Textarea", first: true, predicate: ["sb4Textarea"], descendants: true }, { propertyName: "dateInputChild", first: true, predicate: ["dateInput"], descendants: true }, { propertyName: "timeInputChild", first: true, predicate: ["timeInput"], descendants: true }], ngImport: i0, template: "<div class=\"container material\" [formGroup]=\"form()\">\n @if (widgetInstance.isVisible === undefined ? true : widgetInstance.isVisible) {\n <div\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n class=\"container\"\n >\n @if (widgetInstance.type === smartFormWidgetType.CONTAINER) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getDirection()\"\n >\n @for (widget of visibleChildren; track widget) {\n <smartformwidget\n [form]=\"form()\"\n [widgetInstance]=\"widget\"\n class=\"container-item\"\n [ngClass]=\"widget.cssClass ?? ''\"\n [onBlur]=\"onBlur()\"\n [onValueChange]=\"onValueChange\"\n [sophisticatedValueChange]=\"sophisticatedValueChange()\"\n [blurSophisticatedValueChange]=\"blurSophisticatedValueChange()\"\n class=\"{{ widget.key }}\"\n [labelColor]=\"labelColor()\"\n ></smartformwidget>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD) {\n <div\n (capsLock)=\"capsOn = $event\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n @if (!widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [attr.inputmode]=\"\n widgetInstance.inputMode ? widgetInstance.inputMode.toLocaleLowerCase() : 'text'\n \"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? (hidePassword ? 'password' : 'text') : '' }}\"\n (keydown.enter)=\"onKeydown()\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n [mask]=\"widgetInstance.mask\"\n />\n }\n <!-- [mask]=\"widgetInstance.mask ?? ''\" -->\n @if (widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n (click)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? 'password' : '' }}\"\n [matAutocomplete]=\"textFieldAuto\"\n (keydown.enter)=\"onKeydown()\"\n />\n }\n @if (widgetInstance.isPassword) {\n <button\n mat-icon-button\n matSuffix\n (click)=\"togglePasswordVisibility($event)\"\n >\n <mat-icon>{{ hidePassword ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n }\n <mat-autocomplete #textFieldAuto=\"matAutocomplete\">\n @for (option of filteredOptions | async; track option) {\n <mat-option [value]=\"option.label\">\n <span [innerHTML]=\"option.label | highlight: toHighlight\"></span>\n </mat-option>\n }\n </mat-autocomplete>\n @if (capsOn && widgetInstance.isPassword) {\n <span class=\"mat-error\">\n {{ widgetInstance.capsLockWarning }}\n </span>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n @if (capsOn && widgetInstance.isPassword) {\n <smart-icon\n [icon]=\"widgetInstance.capsLockWarningIcon ?? 'keyboard_capslock'\"\n color=\"warn\"\n ></smart-icon>\n }\n @if (widgetInstance.icon && widgetInstance.iconPosition === 'PRE') {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n ></smart-icon>\n }\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <div class=\"textFieldButtons\">\n @if (widgetInstance.textFieldProperties?.clearable) {\n <ui-action-button\n class=\"clearButton\"\n [addBasicClasses]=\"false\"\n [descriptor]=\"clearButtonDescriptor\"\n (actionClick)=\"clearField(widgetInstance.key)\"\n />\n }\n </div>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n [color]=\"widgetInstance.textFieldButton.iconColor\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_NUMBER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n [type]=\"'number'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [min]=\"widgetInstance.minValues ?? null\"\n [max]=\"widgetInstance.maxValues ?? null\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (widgetInstance.icon) {\n <smart-icon [icon]=\"widgetInstance.icon\" matSuffix>\n </smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_CHIPS) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipList aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip-row\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ value }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n #chipInput\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [matChipInputAddOnBlur]=\"addOnBlur\"\n [readonly]=\"widgetInstance.isReadonly\"\n [matAutocomplete]=\"chipAuto\"\n (matChipInputTokenEnd)=\"add($event)\"\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n <mat-autocomplete\n #chipAuto=\"matAutocomplete\"\n (optionSelected)=\"selected($event, widgetInstance)\"\n >\n @for (item of widgetInstance.valueList; track item) {\n <mat-option\n [disabled]=\"widgetInstance.isDisabled\"\n [value]=\"item.value\"\n >\n {{ item.label }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-chip-grid>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_LOOKUP) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipListLookup aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ getChipsValue(value) }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n }\n <input\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipListLookup\"\n [matChipInputSeparatorKeyCodes]=\"emptySeparatorKeysCodes\"\n [matChipInputAddOnBlur]=\"false\"\n [readonly]=\"true\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n </mat-chip-grid>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_BOX) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <textarea\n class=\"sb4-textarea\"\n #sb4Textarea\n cols=\"30\"\n cdkTextareaAutosize\n [cdkAutosizeMinRows]=\"widgetInstance.textBoxProperties?.minRows ?? 1\"\n [cdkAutosizeMaxRows]=\"widgetInstance.textBoxProperties?.maxRows ?? undefined\"\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n ></textarea>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance.hint || widgetInstance.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n <div class=\"checkbox-item-container\">\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key }}\"\n (change)=\"onValueChange?.next(widgetInstance)\"\n (change)=\"onBlur()?.next(widgetInstance)\"\n >\n {{ widgetInstance.label }}\n </mat-checkbox>\n </div>\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX_2) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n @for (checkbox of widgetInstance.valueList; track checkbox; let i = $index) {\n <div\n class=\"checkbox-item-container\"\n >\n @if (checkbox.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"checkbox-item-image\"\n [src]=\"checkbox.imageUrl\"\n />\n }\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key + '.' + checkbox.key }}\"\n [value]=\"checkbox.value\"\n (change)=\"onValueChange?.next(checkbox)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n >\n {{ checkbox.label }}\n </mat-checkbox>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RADIO_BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-radio-group\n class=\"input radio-section widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n [attr.data-testid]=\"widgetInstance.key\"\n aria-label=\"{{ widgetInstance.label }}\"\n appearance=\"outline\"\n formControlName=\"{{ widgetInstance.key }}\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <div [ngClass]=\"getDirection()\">\n @for (radio of widgetInstance.valueList; track radio) {\n <div class=\"radio-item-container\">\n @if (radio.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"radio-item-image\"\n [src]=\"radio.imageUrl\"\n />\n }\n <mat-radio-button\n class=\"selecatbleObject\"\n value=\"{{ radio.value }}\"\n [ngClass]=\"getDirection()\"\n (change)=\"onValueChange?.next(radio.value)\"\n [disabled]=\"widgetInstance.isDisabled\"\n >\n {{ radio.label }}\n </mat-radio-button>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n <div class=\"radio-icon\">\n @if (widgetInstance.icon) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n >\n </smart-icon>\n }\n </div>\n </div>\n </mat-radio-group>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_PICKER) {\n <div\n class=\"datePicker widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n matInput\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (change)=\"handleBlurEvent(widgetInstance)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MONTH_PICKER) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div class=\"{{ labelColor() }} smart-form-widget-label\">\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <lib-smart-month-picker\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (valueChange)=\"handleYearMonthPicked($event)\"\n ></lib-smart-month-picker>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_TIME_PICKER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div class=\"dateTimePickerContainer\">\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n #dateInput\n matInput\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n [id]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (blur)=\"onDatePickerBlur($event)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n @if (hasCreated) {\n <mat-form-field\n class=\"input widgetContent time\"\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n appearance=\"outline\"\n >\n <input\n #timeInput\n [formControlName]=\"widgetInstance.key + '-time'\"\n [attr.data-testid]=\"widgetInstance.key + '-time'\"\n [id]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n (blur)=\"onTimePickerBlur($event)\"\n matInput\n />\n </mat-form-field>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon>\n }\n {{ innerOption.label }}\n </mat-option>\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT_MULTIPLE) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n multiple\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon\n >\n }{{ innerOption.label }}</mat-option\n >\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.LABEL) {\n <div\n class=\"label widgetContainer\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n >\n <div class=\"label-title labelContainer\" [ngClass]=\"widgetInstance.cssClass ?? ''\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance.widgetDescription) {\n <p>{{ widgetInstance.widgetDescription }}</p>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TIME) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent time {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent(widgetInstance)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TOGGLE) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <mat-slide-toggle\n formControlName=\"{{ widgetInstance.key }}\"\n [attr.data-testid]=\"widgetInstance.key\"\n (change)=\"onValueChange?.next($event)\"\n [labelPosition]=\"widgetInstance.toggleLabelPosition ?? 'before'\"\n >{{ !widgetInstance.showLabel ? widgetInstance.label : '' }}</mat-slide-toggle\n ><span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.INDICATOR) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} labelContainer {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"smartIndicator widgetContent\">\n <div class=\"indicatorItems {{ widgetInstance.cssClass ?? '' }}\" [ngClass]=\"getNgClass()\">\n @for (item of indicatorItems; track item; let i = $index) {\n <div\n class=\"indicatorItem\"\n [ngClass]=\"getIndicatorItemClass(i)\"\n ></div>\n }\n </div>\n <p [ngClass]=\"getIndicatorStatusLabelColor()\">\n {{ getIndicatorStatusLabel() }}\n </p>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RECORDING_UPLOADER) {\n <div class=\"widgetContainer\">\n <div class=\"widgetItemContainer\">\n <smart-voice-recorder\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MULTI_FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-multi-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n (fileEvent)=\"executeUiAction($event.uiAction)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.IMAGE) {\n <div class=\"widgetContainer imageContainer\">\n @if (widgetInstance.showLabel && getWidgetLabel(widgetInstance)) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance.imageProperties?.image) {\n <smart-icon\n [imageResource]=\"$safeNavigationMigration(widgetInstance.imageProperties?.image)\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n } @else if (widgetInstance.value) {\n <smart-icon\n [(ngModel)]=\"widgetInstance.value\"\n [imageResource]=\"widgetInstance.value\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIV) {\n <div\n class=\"smartDiv\"\n [innerHTML]=\"sanitizeHtml(getWidgetLabel(widgetInstance))\"\n [ngClass]=\"getNgClass()\"\n [class.clickable]=\"!!widgetInstance.divProperties?.onClick\"\n [ngStyle]=\"getStyle()\"\n (click)=\"onDivClick()\"\n >\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.HTML) {\n <smart-html-widget\n [widgetInstance]=\"widgetInstance\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-html-widget>\n }\n @if (widgetInstance.type === smartFormWidgetType.SVG) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [innerHTML]=\"sanitizeHtml(widgetInstance.value)\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIVIDER) {\n <div class=\"widgetContainer\">\n <hr\n class=\"smartDivider {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <button\n mat-button\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getButtonType(widgetInstance.uiActionDescriptor)\"\n [color]=\"$safeNavigationMigration(widgetInstance.uiActionDescriptor?.color)\"\n (click)=\"onButtonClicked(widgetInstance)\"\n >\n @if (isOnlyIcon(widgetInstance.uiActionDescriptor)) {\n @if (widgetInstance.uiActionDescriptor?.icon) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n } @else {\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'PRE'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n {{ widgetInstance.uiActionDescriptor?.title }}\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'POST'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n }\n </button>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.COMPONENT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }}\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"widgetContent\">\n <ng-template #customComponent></ng-template>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RICH_TEXT) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <quill-editor\n #quillEditor\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [modules]=\"widgetInstance.isDisabled ? emptyQuillToolbar : widgetInstance.quillModules\"\n [placeholder]=\"widgetInstance.placeholder ?? ''\"\n [readOnly]=\"widgetInstance.isReadonly ?? false\"\n [maxLength]=\"widgetInstance.maxLength ?? 0\"\n (onContentChanged)=\"onRichTextEditorContentChanged($event)\"\n ></quill-editor>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n class=\"rich-text-editor-leeway-counter\"\n >{{ getRichTextEditorLengthLeeway() }}</mat-hint\n >\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SORTABLE) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <lib-sortable-widget\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n ></lib-sortable-widget>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MATRIX) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <table class=\"matrixTable widgetContent\">\n <tr>\n <th></th>\n @for (option of widgetInstance.value.columns; track option) {\n <th class=\"optionLabel\">\n {{ option.displayValue }}\n </th>\n }\n </tr>\n @for (question of widgetInstance.value.rows; track question; let i = $index) {\n <tr>\n <th class=\"questionLabel\">\n <label>{{ question.displayValue }}</label>\n </th>\n @for (option of widgetInstance.value.columns; track option; let j = $index) {\n <td class=\"selectTd\">\n @if (!widgetInstance.isMultiple) {\n <mat-radio-group\n [formControlName]=\"widgetInstance.key + '.' + question.code\"\n [name]=\"'q' + i\"\n >\n <mat-radio-button [value]=\"option.code\"> </mat-radio-button>\n </mat-radio-group>\n }\n @if (widgetInstance.isMultiple) {\n <div>\n <mat-checkbox\n [formControlName]=\"\n widgetInstance.key + '.data.' + question.code + '.' + option.code\n \"\n [value]=\"widgetInstance.value['data'][question.code][option.code]\"\n [checked]=\"true\"\n ></mat-checkbox>\n </div>\n }\n </td>\n }\n <br />\n @if (widgetInstance.button) {\n <button mat-icon-button (click)=\"removeMatrixRow(question)\"\n ><smart-icon icon=\"close\"></smart-icon\n ></button>\n }\n </tr>\n }\n </table>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.YOUTUBE_PLAYER) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <youtube-player\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n videoId=\"{{ widgetInstance.videoId }}\"\n [width]=\"widgetInstance.width\"\n [height]=\"widgetInstance.height\"\n [startSeconds]=\"widgetInstance.startSeconds\"\n [endSeconds]=\"widgetInstance.endSeconds\"\n ></youtube-player>\n @if (\n !widgetInstance?.hint || widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n </div>\n }\n </div>\n", styles: [".ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container:not(.ql-disabled) li[data-list=checked]>.ql-ui,.ql-container:not(.ql-disabled) li[data-list=unchecked]>.ql-ui{cursor:pointer}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0}@supports (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-set:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor table{border-collapse:collapse}.ql-editor td{border:1px solid #000;padding:2px 5px}.ql-editor ol{padding-left:1.5em}.ql-editor li{list-style-type:none;padding-left:1.5em;position:relative}.ql-editor li>.ql-ui:before{display:inline-block;margin-left:-1.5em;margin-right:.3em;text-align:right;white-space:nowrap;width:1.2em}.ql-editor li[data-list=checked]>.ql-ui,.ql-editor li[data-list=unchecked]>.ql-ui{color:#777}.ql-editor li[data-list=bullet]>.ql-ui:before{content:\"\\2022\"}.ql-editor li[data-list=checked]>.ql-ui:before{content:\"\\2611\"}.ql-editor li[data-list=unchecked]>.ql-ui:before{content:\"\\2610\"}@supports (counter-set:none){.ql-editor li[data-list]{counter-set:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list]{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered]{counter-increment:list-0}.ql-editor li[data-list=ordered]>.ql-ui:before{content:counter(list-0,decimal) \". \"}.ql-editor li[data-list=ordered].ql-indent-1{counter-increment:list-1}.ql-editor li[data-list=ordered].ql-indent-1>.ql-ui:before{content:counter(list-1,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-set:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-2{counter-increment:list-2}.ql-editor li[data-list=ordered].ql-indent-2>.ql-ui:before{content:counter(list-2,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-set:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-3{counter-increment:list-3}.ql-editor li[data-list=ordered].ql-indent-3>.ql-ui:before{content:counter(list-3,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-set:list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-4{counter-increment:list-4}.ql-editor li[data-list=ordered].ql-indent-4>.ql-ui:before{content:counter(list-4,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-set:list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-5{counter-increment:list-5}.ql-editor li[data-list=ordered].ql-indent-5>.ql-ui:before{content:counter(list-5,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-set:list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-6{counter-increment:list-6}.ql-editor li[data-list=ordered].ql-indent-6>.ql-ui:before{content:counter(list-6,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-set:list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-reset:list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-7{counter-increment:list-7}.ql-editor li[data-list=ordered].ql-indent-7>.ql-ui:before{content:counter(list-7,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-set:list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-reset:list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-8{counter-increment:list-8}.ql-editor li[data-list=ordered].ql-indent-8>.ql-ui:before{content:counter(list-8,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-set:list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-reset:list-9}}.ql-editor li[data-list=ordered].ql-indent-9{counter-increment:list-9}.ql-editor li[data-list=ordered].ql-indent-9>.ql-ui:before{content:counter(list-9,decimal) \". \"}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor li.ql-direction-rtl{padding-right:1.5em}.ql-editor li.ql-direction-rtl>.ql-ui:before{margin-left:.3em;margin-right:-1.5em;text-align:left}.ql-editor table{table-layout:fixed;width:100%}.ql-editor table td{outline:none}.ql-editor .ql-code-block-container{font-family:monospace}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor .ql-ui{position:absolute}.ql-editor.ql-blank:before{color:#0009;content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-snow.ql-toolbar:after,.ql-snow .ql-toolbar:after{clear:both;content:\"\";display:table}.ql-snow.ql-toolbar button,.ql-snow .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-snow.ql-toolbar button svg,.ql-snow .ql-toolbar button svg{float:left;height:100%}.ql-snow.ql-toolbar button:active:hover,.ql-snow .ql-toolbar button:active:hover{outline:none}.ql-snow.ql-toolbar input.ql-image[type=file],.ql-snow .ql-toolbar input.ql-image[type=file]{display:none}.ql-snow.ql-toolbar button:hover,.ql-snow .ql-toolbar button:hover,.ql-snow.ql-toolbar button:focus,.ql-snow .ql-toolbar button:focus,.ql-snow.ql-toolbar button.ql-active,.ql-snow .ql-toolbar button.ql-active,.ql-snow.ql-toolbar .ql-picker-label:hover,.ql-snow .ql-toolbar .ql-picker-label:hover,.ql-snow.ql-toolbar .ql-picker-label.ql-active,.ql-snow .ql-toolbar .ql-picker-label.ql-active,.ql-snow.ql-toolbar .ql-picker-item:hover,.ql-snow .ql-toolbar .ql-picker-item:hover,.ql-snow.ql-toolbar .ql-picker-item.ql-selected,.ql-snow .ql-toolbar .ql-picker-item.ql-selected{color:#06c}.ql-snow.ql-toolbar button:hover .ql-fill,.ql-snow .ql-toolbar button:hover .ql-fill,.ql-snow.ql-toolbar button:focus .ql-fill,.ql-snow .ql-toolbar button:focus .ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#06c}.ql-snow.ql-toolbar button:hover .ql-stroke,.ql-snow .ql-toolbar button:hover .ql-stroke,.ql-snow.ql-toolbar button:focus .ql-stroke,.ql-snow .ql-toolbar button:focus .ql-stroke,.ql-snow.ql-toolbar button.ql-active .ql-stroke,.ql-snow .ql-toolbar button.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow.ql-toolbar button:hover .ql-stroke-miter,.ql-snow .ql-toolbar button:hover .ql-stroke-miter,.ql-snow.ql-toolbar button:focus .ql-stroke-miter,.ql-snow .ql-toolbar button:focus .ql-stroke-miter,.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#06c}@media(pointer:coarse){.ql-snow.ql-toolbar button:hover:not(.ql-active),.ql-snow .ql-toolbar button:hover:not(.ql-active){color:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#444}}.ql-snow,.ql-snow *{box-sizing:border-box}.ql-snow .ql-hidden{display:none}.ql-snow .ql-out-bottom,.ql-snow .ql-out-top{visibility:hidden}.ql-snow .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-snow .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-snow .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-snow .ql-formats{display:inline-block;vertical-align:middle}.ql-snow .ql-formats:after{clear:both;content:\"\";display:table}.ql-snow .ql-stroke{fill:none;stroke:#444;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-snow .ql-stroke-miter{fill:none;stroke:#444;stroke-miterlimit:10;stroke-width:2}.ql-snow .ql-fill,.ql-snow .ql-stroke.ql-fill{fill:#444}.ql-snow .ql-empty{fill:none}.ql-snow .ql-even{fill-rule:evenodd}.ql-snow .ql-thin,.ql-snow .ql-stroke.ql-thin{stroke-width:1}.ql-snow .ql-transparent{opacity:.4}.ql-snow .ql-direction svg:last-child{display:none}.ql-snow .ql-direction.ql-active svg:last-child{display:inline}.ql-snow .ql-direction.ql-active svg:first-child{display:none}.ql-snow .ql-editor h1{font-size:2em}.ql-snow .ql-editor h2{font-size:1.5em}.ql-snow .ql-editor h3{font-size:1.17em}.ql-snow .ql-editor h4{font-size:1em}.ql-snow .ql-editor h5{font-size:.83em}.ql-snow .ql-editor h6{font-size:.67em}.ql-snow .ql-editor a{text-decoration:underline}.ql-snow .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-snow .ql-editor code,.ql-snow .ql-editor .ql-code-block-container{background-color:#f0f0f0;border-radius:3px}.ql-snow .ql-editor .ql-code-block-container{margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-snow .ql-editor code{font-size:85%;padding:2px 4px}.ql-snow .ql-editor .ql-code-block-container{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-snow .ql-editor img{max-width:100%}.ql-snow .ql-picker{color:#444;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-snow .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-snow .ql-picker-label:before{display:inline-block;line-height:22px}.ql-snow .ql-picker-options{background-color:#fff;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-snow .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-snow .ql-picker.ql-expanded .ql-picker-label{color:#ccc;z-index:2}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-snow .ql-color-picker,.ql-snow .ql-icon-picker{width:28px}.ql-snow .ql-color-picker .ql-picker-label,.ql-snow .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-label svg,.ql-snow .ql-icon-picker .ql-picker-label svg{right:4px}.ql-snow .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-snow .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-snow .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=\"\"]):before{content:attr(data-label)}.ql-snow .ql-picker.ql-header{width:98px}.ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"1\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{content:\"Heading 1\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"2\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{content:\"Heading 2\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"3\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{content:\"Heading 3\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"4\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{content:\"Heading 4\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"5\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{content:\"Heading 5\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"6\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{content:\"Heading 6\"}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{font-size:2em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{font-size:1.5em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{font-size:1.17em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{font-size:1em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{font-size:.83em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{font-size:.67em}.ql-snow .ql-picker.ql-font{width:108px}.ql-snow .ql-picker.ql-font .ql-picker-label:before,.ql-snow .ql-picker.ql-font .ql-picker-item:before{content:\"Sans Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{content:\"Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{content:\"Monospace\"}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{font-family:Georgia,Times New Roman,serif}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{font-family:Monaco,Courier New,monospace}.ql-snow .ql-picker.ql-size{width:98px}.ql-snow .ql-picker.ql-size .ql-picker-label:before,.ql-snow .ql-picker.ql-size .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{content:\"Small\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{content:\"Large\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{content:\"Huge\"}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{font-size:10px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{font-size:18px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{font-size:32px}.ql-snow .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-snow .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-code-block-container{position:relative}.ql-code-block-container .ql-ui{right:5px;top:5px}.ql-toolbar.ql-snow{border:1px solid #ccc;box-sizing:border-box;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding:8px}.ql-toolbar.ql-snow .ql-formats{margin-right:15px}.ql-toolbar.ql-snow .ql-picker-label{border:1px solid transparent}.ql-toolbar.ql-snow .ql-picker-options{border:1px solid transparent;box-shadow:#0003 0 2px 8px}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label,.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{border-color:#ccc}.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover{border-color:#000}.ql-toolbar.ql-snow+.ql-container.ql-snow{border-top:0}.ql-snow .ql-tooltip{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.ql-snow .ql-tooltip:before{content:\"Visit URL:\";line-height:26px;margin-right:8px}.ql-snow .ql-tooltip input[type=text]{display:none;border:1px solid #ccc;font-size:13px;height:26px;margin:0;padding:3px 5px;width:170px}.ql-snow .ql-tooltip a.ql-preview{display:inline-block;max-width:200px;overflow-x:hidden;text-overflow:ellipsis;vertical-align:top}.ql-snow .ql-tooltip a.ql-action:after{border-right:1px solid #ccc;content:\"Edit\";margin-left:16px;padding-right:8px}.ql-snow .ql-tooltip a.ql-remove:before{content:\"Remove\";margin-left:8px}.ql-snow .ql-tooltip a{line-height:26px}.ql-snow .ql-tooltip.ql-editing a.ql-preview,.ql-snow .ql-tooltip.ql-editing a.ql-remove{display:none}.ql-snow .ql-tooltip.ql-editing input[type=text]{display:inline-block}.ql-snow .ql-tooltip.ql-editing a.ql-action:after{border-right:0;content:\"Save\";padding-right:0}.ql-snow .ql-tooltip[data-mode=link]:before{content:\"Enter link:\"}.ql-snow .ql-tooltip[data-mode=formula]:before{content:\"Enter formula:\"}.ql-snow .ql-tooltip[data-mode=video]:before{content:\"Enter video:\"}.ql-snow a{color:#06c}.ql-container.ql-snow{border:1px solid #ccc}.checkbox-section,.radio-section{display:flex;flex-direction:column}.input{width:100%}.direction-col,.toggle-col{display:flex;flex-direction:column;gap:.5em}.toggle-col>label{font-size:.75rem;color:#6b7280;padding-left:.5em}.direction-row{display:flex;flex-direction:row;align-items:center;gap:.5em}.selecatbleObject{margin:.5em}.radioLabel{color:var(--primary-color);text-align:left!important}.container{height:100%}.input{height:100%;display:flex;flex-direction:column}.checkbox{flex-direction:column}.mat-form-field-wrapper{padding-bottom:0!important}.input .mat-mdc-standard-chip.mat-chip-with-trailing-icon{padding-right:12px}.time-picker{display:flex;flex-direction:row;height:100%;border:solid 2px lightgrey;padding:1em;border-radius:4px}.time-picker:hover{border-color:#000}::ng-deep .mat-h4 .mat-body-1 .mat-typography h4{margin:0}.label{margin:28px 0 8px}.smartIndicator{display:flex;flex-direction:column;gap:.25rem;width:-moz-fit-content;width:fit-content}.indicatorItems{display:flex;flex-direction:row;gap:.25rem}.indicatorItem{width:3rem;height:.25rem;background-color:#d3d3d3;border-radius:.5rem}.radio-error{width:-moz-fit-content;width:fit-content;display:flex;flex-direction:row;gap:.5rem}.mat-calendar-previous-button,.mat-calendar-next-button{padding:0;min-width:0;width:40px!important;height:40px!important;flex-shrink:0;line-height:40px;border-radius:50%}.mat-calendar-arrow{height:36px!important;display:flex!important;flex-direction:column!important;justify-content:center}.radio-item-container,.checkbox-item-container{display:flex;flex-direction:column}.widgetContent::ng-deep .ql-container{height:200px;width:460px}.dateTimePickerContainer{display:flex;flex-direction:row;gap:.25rem}.dateTimePickerContainer mat-form-field{flex:1}.date,.time{width:100%}.date .mat-form-field-infix,.time .mat-form-field-infix{width:inherit!important}::ng-deep .mat-icon.mat-drag-indicator{--drag-indicator: #3b3b3b;color:var(--drag-indicator)}.matrixTable{width:100%;border-spacing:0 1rem}.matrixTable th{padding:.25rem}.matrixTable .optionLabel,.matrixTable td{text-align:center}.example-month-picker .mat-calendar-period-button{pointer-events:none}.example-month-picker .mat-calendar-arrow{display:none}.textFieldContainer{display:flex;flex-direction:row}.textFieldContainer{align-content:center;border:1px solid #cbd5e1;border-radius:3px;background-color:#fff}.textFieldContainer input{border:unset}.textFieldContainer:focus-within:not(:has(input:disabled)){outline:0 none;outline-offset:0;box-shadow:0 0 0 .2rem #a6d5fa;border-color:#2196f3}.textFieldContainer:has(input:disabled) .clearButton{cursor:not-allowed;opacity:.6}.textFieldButtons{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.clearButton .mat-mdc-raised-button,.clearButton button{background-color:unset!important;border:unset;color:#6b7280!important;box-shadow:unset;font-size:1rem!important}.clearButton .mat-icon.mat-primary{color:#6b7280!important}.clearButton .mat-mdc-raised-button:hover,.clearButton button:hover{color:#6b7280cc!important;background-color:unset;border:unset;box-shadow:unset;font-size:1rem!important}.mat-mdc-form-field-infix{display:flex;flex-direction:row}textarea:not(:placeholder-shown)~label{top:-.75em!important;font-size:12px!important}.disabledEditor *{-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only}.sb4-textarea{--sb4-textarea-line-height: 20px;line-height:var(--sb4-textarea-line-height);overflow-y:auto!important}.widgetContainer .imageIcon{max-width:unset!important;height:unset!important}.material .sb4-textarea{resize:vertical!important}.material .smart-form-widget-label{font-weight:700}.material .mat-mdc-form-field-subscript-wrapper{display:none}.label-right{display:flex;gap:.5rem;flex-direction:row-reverse}.label-left{display:flex;gap:.5rem;flex-direction:row}.label-top{display:flex;gap:.5rem;flex-direction:column}.label-bottom{display:flex;gap:.5rem;flex-direction:column-reverse}.smartDiv{width:100%}.clickable{cursor:pointer}\n/*!\n * Quill Editor v2.0.3\n * https://quilljs.com\n * Copyright (c) 2017-2024, Slab\n * Copyright (c) 2014, Jason Chen\n * Copyright (c) 2013, salesforce.com\n */\n"], dependencies: [{ kind: "component", type: SmartformwidgetComponent, selector: "smartformwidget", inputs: ["form", "widgetInstance", "onBlur", "onValueChange", "labelColor", "sophisticatedValueChange", "blurSophisticatedValueChange"], outputs: ["valueCleared"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: TrackCapsDirective, selector: "[capsLock]", outputs: ["capsLock"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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: NgxMaskDirective, selector: "input[mask], textarea[mask]", inputs: ["mask", "specialCharacters", "patterns", "prefix", "suffix", "thousandSeparator", "decimalMarker", "dropSpecialCharacters", "hiddenInput", "showMaskTyped", "placeHolderCharacter", "shownMaskExpression", "clearIfNotMatch", "validation", "separatorLimit", "typeFromDecimals", "allowNegativeNumbers", "leadZeroDateTime", "leadZero", "triggerOnMaskChange", "apm", "inputTransformFn", "outputTransformFn", "keepCharacterPositions", "instantPrefix", "defaultValueOnBlur", "value", "disabled", "touched"], outputs: ["valueChange", "touchedChange", "maskFilled"], exportAs: ["mask", "ngxMask"] }, { kind: "directive", type: MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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: "component", type: MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "component", type: MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "directive", type: MatChipRemove, selector: "[matChipRemove]" }, { kind: "directive", type: MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { 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: "directive", type: MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { 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: "component", type: MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: SmartMonthPickerComponent, selector: "lib-smart-month-picker", inputs: ["widgetInstance"], outputs: ["valueChange"] }, { 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: MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "component", type: MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: SmartVoiceRecorderComponent, selector: "smart-voice-recorder", inputs: ["widgetInstance"], outputs: ["uploadFilesEvent"] }, { kind: "component", type: SmartFileEditorComponent, selector: "smart-file-editor", inputs: ["widgetInstance"], outputs: ["uploadFilesEvent"] }, { kind: "component", type: SmartMultiFileEditorComponent, selector: "smart-multi-file-editor", inputs: ["widgetInstance"], outputs: ["uploadFilesEvent", "fileEvent"] }, { kind: "component", type: SmartHtmlWidgetComponent, selector: "smart-html-widget", inputs: ["widgetInstance"] }, { kind: "component", type: QuillEditorComponent, selector: "quill-editor" }, { kind: "component", type: SortableWidgetComponent, selector: "lib-sortable-widget", inputs: ["widgetInstance"] }, { kind: "component", type: YouTubePlayer, selector: "youtube-player", inputs: ["videoId", "height", "width", "startSeconds", "endSeconds", "suggestedQuality", "playerVars", "disableCookies", "loadApi", "disablePlaceholder", "showBeforeIframeApiLoads", "placeholderButtonLabel", "placeholderImageQuality"], outputs: ["ready", "stateChange", "error", "apiChange", "playbackQualityChange", "playbackRateChange"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: HighlightPipe, name: "highlight" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
10807
11593
  }
10808
11594
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartformwidgetComponent, decorators: [{
10809
11595
  type: Component,
10810
- args: [{ selector: 'smartformwidget', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, ReactiveFormsModule, NgClass, TrackCapsDirective, NgStyle, MatHint, MatFormField, MatLabel, MatInput, NgxMaskDirective, MatAutocompleteTrigger, MatIconButton, MatSuffix, MatIcon, MatAutocomplete, MatOption, MatPrefix, SmartIconComponent, UiActionButtonComponent, UiActionToolbarComponent, MatButton, MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChip, CdkTextareaAutosize, MatCheckbox, MatRadioGroup, MatRadioButton, MatDatepickerToggle, MatDatepicker, MatDatepickerInput, SmartMonthPickerComponent, MatSelect, MatOptgroup, MatSlideToggle, SmartVoiceRecorderComponent, SmartFileEditorComponent, SmartMultiFileEditorComponent, QuillEditorComponent, SortableWidgetComponent, YouTubePlayer, AsyncPipe, HighlightPipe], template: "<div class=\"container material\" [formGroup]=\"form()\">\n @if (widgetInstance.isVisible === undefined ? true : widgetInstance.isVisible) {\n <div\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n class=\"container\"\n >\n @if (widgetInstance.type === smartFormWidgetType.CONTAINER) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getDirection()\"\n >\n @for (widget of visibleChildren; track widget) {\n <smartformwidget\n [form]=\"form()\"\n [widgetInstance]=\"widget\"\n class=\"container-item\"\n [ngClass]=\"widget.cssClass ?? ''\"\n [onBlur]=\"onBlur()\"\n [onValueChange]=\"onValueChange\"\n [sophisticatedValueChange]=\"sophisticatedValueChange()\"\n [blurSophisticatedValueChange]=\"blurSophisticatedValueChange()\"\n class=\"{{ widget.key }}\"\n [labelColor]=\"labelColor()\"\n ></smartformwidget>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD) {\n <div\n (capsLock)=\"capsOn = $event\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n @if (!widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [attr.inputmode]=\"\n widgetInstance.inputMode ? widgetInstance.inputMode.toLocaleLowerCase() : 'text'\n \"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? (hidePassword ? 'password' : 'text') : '' }}\"\n (keydown.enter)=\"onKeydown()\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n [mask]=\"widgetInstance.mask\"\n />\n }\n <!-- [mask]=\"widgetInstance.mask ?? ''\" -->\n @if (widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n (click)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? 'password' : '' }}\"\n [matAutocomplete]=\"textFieldAuto\"\n (keydown.enter)=\"onKeydown()\"\n />\n }\n @if (widgetInstance.isPassword) {\n <button\n mat-icon-button\n matSuffix\n (click)=\"togglePasswordVisibility($event)\"\n >\n <mat-icon>{{ hidePassword ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n }\n <mat-autocomplete #textFieldAuto=\"matAutocomplete\">\n @for (option of filteredOptions | async; track option) {\n <mat-option [value]=\"option.label\">\n <span [innerHTML]=\"option.label | highlight: toHighlight\"></span>\n </mat-option>\n }\n </mat-autocomplete>\n @if (capsOn && widgetInstance.isPassword) {\n <span class=\"mat-error\">\n {{ widgetInstance.capsLockWarning }}\n </span>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n @if (capsOn && widgetInstance.isPassword) {\n <smart-icon\n [icon]=\"widgetInstance.capsLockWarningIcon ?? 'keyboard_capslock'\"\n color=\"warn\"\n ></smart-icon>\n }\n @if (widgetInstance.icon && widgetInstance.iconPosition === 'PRE') {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n ></smart-icon>\n }\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <div class=\"textFieldButtons\">\n @if (widgetInstance.textFieldProperties?.clearable) {\n <ui-action-button\n class=\"clearButton\"\n [addBasicClasses]=\"false\"\n [descriptor]=\"clearButtonDescriptor\"\n (actionClick)=\"clearField(widgetInstance.key)\"\n />\n }\n </div>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n [color]=\"widgetInstance.textFieldButton.iconColor\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_NUMBER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n [type]=\"'number'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [min]=\"widgetInstance.minValues ?? null\"\n [max]=\"widgetInstance.maxValues ?? null\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (widgetInstance.icon) {\n <smart-icon [icon]=\"widgetInstance.icon\" matSuffix>\n </smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_CHIPS) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipList aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip-row\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ value }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n #chipInput\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [matChipInputAddOnBlur]=\"addOnBlur\"\n [readonly]=\"widgetInstance.isReadonly\"\n [matAutocomplete]=\"chipAuto\"\n (matChipInputTokenEnd)=\"add($event)\"\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n <mat-autocomplete\n #chipAuto=\"matAutocomplete\"\n (optionSelected)=\"selected($event, widgetInstance)\"\n >\n @for (item of widgetInstance.valueList; track item) {\n <mat-option\n [disabled]=\"widgetInstance.isDisabled\"\n [value]=\"item.value\"\n >\n {{ item.label }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-chip-grid>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_LOOKUP) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipListLookup aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ getChipsValue(value) }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n }\n <input\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipListLookup\"\n [matChipInputSeparatorKeyCodes]=\"emptySeparatorKeysCodes\"\n [matChipInputAddOnBlur]=\"false\"\n [readonly]=\"true\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n </mat-chip-grid>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_BOX) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <textarea\n class=\"sb4-textarea\"\n #sb4Textarea\n cols=\"30\"\n cdkTextareaAutosize\n [cdkAutosizeMinRows]=\"widgetInstance.textBoxProperties?.minRows ?? 1\"\n [cdkAutosizeMaxRows]=\"widgetInstance.textBoxProperties?.maxRows ?? undefined\"\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n ></textarea>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance.hint || widgetInstance.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n <div class=\"checkbox-item-container\">\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key }}\"\n (change)=\"onValueChange?.next(widgetInstance)\"\n (change)=\"onBlur()?.next(widgetInstance)\"\n >\n {{ widgetInstance.label }}\n </mat-checkbox>\n </div>\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX_2) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n @for (checkbox of widgetInstance.valueList; track checkbox; let i = $index) {\n <div\n class=\"checkbox-item-container\"\n >\n @if (checkbox.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"checkbox-item-image\"\n [src]=\"checkbox.imageUrl\"\n />\n }\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key + '.' + checkbox.key }}\"\n [value]=\"checkbox.value\"\n (change)=\"onValueChange?.next(checkbox)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n >\n {{ checkbox.label }}\n </mat-checkbox>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RADIO_BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-radio-group\n class=\"input radio-section widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n [attr.data-testid]=\"widgetInstance.key\"\n aria-label=\"{{ widgetInstance.label }}\"\n appearance=\"outline\"\n formControlName=\"{{ widgetInstance.key }}\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <div [ngClass]=\"getDirection()\">\n @for (radio of widgetInstance.valueList; track radio) {\n <div class=\"radio-item-container\">\n @if (radio.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"radio-item-image\"\n [src]=\"radio.imageUrl\"\n />\n }\n <mat-radio-button\n class=\"selecatbleObject\"\n value=\"{{ radio.value }}\"\n [ngClass]=\"getDirection()\"\n (change)=\"onValueChange?.next(radio.value)\"\n [disabled]=\"widgetInstance.isDisabled\"\n >\n {{ radio.label }}\n </mat-radio-button>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n <div class=\"radio-icon\">\n @if (widgetInstance.icon) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n >\n </smart-icon>\n }\n </div>\n </div>\n </mat-radio-group>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_PICKER) {\n <div\n class=\"datePicker widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n matInput\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (change)=\"handleBlurEvent(widgetInstance)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MONTH_PICKER) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div class=\"{{ labelColor() }} smart-form-widget-label\">\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <lib-smart-month-picker\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (valueChange)=\"handleYearMonthPicked($event)\"\n ></lib-smart-month-picker>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_TIME_PICKER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div class=\"dateTimePickerContainer\">\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n #dateInput\n matInput\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n [id]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (blur)=\"onDatePickerBlur($event)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n @if (hasCreated) {\n <mat-form-field\n class=\"input widgetContent time\"\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n appearance=\"outline\"\n >\n <input\n #timeInput\n [formControlName]=\"widgetInstance.key + '-time'\"\n [attr.data-testid]=\"widgetInstance.key + '-time'\"\n [id]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n (blur)=\"onTimePickerBlur($event)\"\n matInput\n />\n </mat-form-field>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon>\n }\n {{ innerOption.label }}\n </mat-option>\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT_MULTIPLE) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n multiple\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon\n >\n }{{ innerOption.label }}</mat-option\n >\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.LABEL) {\n <div\n class=\"label widgetContainer\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n >\n <div class=\"label-title labelContainer\" [ngClass]=\"widgetInstance.cssClass ?? ''\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance.widgetDescription) {\n <p>{{ widgetInstance.widgetDescription }}</p>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TIME) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent time {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent(widgetInstance)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TOGGLE) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <mat-slide-toggle\n formControlName=\"{{ widgetInstance.key }}\"\n [attr.data-testid]=\"widgetInstance.key\"\n (change)=\"onValueChange?.next($event)\"\n [labelPosition]=\"widgetInstance.toggleLabelPosition ?? 'before'\"\n >{{ !widgetInstance.showLabel ? widgetInstance.label : '' }}</mat-slide-toggle\n ><span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.INDICATOR) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} labelContainer {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"smartIndicator widgetContent\">\n <div class=\"indicatorItems {{ widgetInstance.cssClass ?? '' }}\" [ngClass]=\"getNgClass()\">\n @for (item of indicatorItems; track item; let i = $index) {\n <div\n class=\"indicatorItem\"\n [ngClass]=\"getIndicatorItemClass(i)\"\n ></div>\n }\n </div>\n <p [ngClass]=\"getIndicatorStatusLabelColor()\">\n {{ getIndicatorStatusLabel() }}\n </p>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RECORDING_UPLOADER) {\n <div class=\"widgetContainer\">\n <div class=\"widgetItemContainer\">\n <smart-voice-recorder\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MULTI_FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-multi-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n (fileEvent)=\"executeUiAction($event.uiAction)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.IMAGE) {\n <div class=\"widgetContainer imageContainer\">\n @if (widgetInstance.showLabel && getWidgetLabel(widgetInstance)) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance.imageProperties?.image) {\n <smart-icon\n [imageResource]=\"$safeNavigationMigration(widgetInstance.imageProperties?.image)\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n } @else if (widgetInstance.value) {\n <smart-icon\n [(ngModel)]=\"widgetInstance.value\"\n [imageResource]=\"widgetInstance.value\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIV) {\n <div\n class=\"smartDiv\"\n [innerHTML]=\"sanitizeHtml(getWidgetLabel(widgetInstance))\"\n [ngClass]=\"getNgClass()\"\n [class.clickable]=\"!!widgetInstance.divProperties?.onClick\"\n [ngStyle]=\"getStyle()\"\n (click)=\"onDivClick()\"\n >\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SVG) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [innerHTML]=\"sanitizeHtml(widgetInstance.value)\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIVIDER) {\n <div class=\"widgetContainer\">\n <hr\n class=\"smartDivider {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <button\n mat-button\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getButtonType(widgetInstance.uiActionDescriptor)\"\n [color]=\"$safeNavigationMigration(widgetInstance.uiActionDescriptor?.color)\"\n (click)=\"onButtonClicked(widgetInstance)\"\n >\n @if (isOnlyIcon(widgetInstance.uiActionDescriptor)) {\n @if (widgetInstance.uiActionDescriptor?.icon) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n } @else {\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'PRE'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n {{ widgetInstance.uiActionDescriptor?.title }}\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'POST'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n }\n </button>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.COMPONENT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }}\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"widgetContent\">\n <ng-template #customComponent></ng-template>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RICH_TEXT) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <quill-editor\n #quillEditor\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [modules]=\"widgetInstance.isDisabled ? emptyQuillToolbar : widgetInstance.quillModules\"\n [placeholder]=\"widgetInstance.placeholder ?? ''\"\n [readOnly]=\"widgetInstance.isReadonly ?? false\"\n [maxLength]=\"widgetInstance.maxLength ?? 0\"\n (onContentChanged)=\"onRichTextEditorContentChanged($event)\"\n ></quill-editor>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n class=\"rich-text-editor-leeway-counter\"\n >{{ getRichTextEditorLengthLeeway() }}</mat-hint\n >\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SORTABLE) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <lib-sortable-widget\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n ></lib-sortable-widget>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MATRIX) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <table class=\"matrixTable widgetContent\">\n <tr>\n <th></th>\n @for (option of widgetInstance.value.columns; track option) {\n <th class=\"optionLabel\">\n {{ option.displayValue }}\n </th>\n }\n </tr>\n @for (question of widgetInstance.value.rows; track question; let i = $index) {\n <tr>\n <th class=\"questionLabel\">\n <label>{{ question.displayValue }}</label>\n </th>\n @for (option of widgetInstance.value.columns; track option; let j = $index) {\n <td class=\"selectTd\">\n @if (!widgetInstance.isMultiple) {\n <mat-radio-group\n [formControlName]=\"widgetInstance.key + '.' + question.code\"\n [name]=\"'q' + i\"\n >\n <mat-radio-button [value]=\"option.code\"> </mat-radio-button>\n </mat-radio-group>\n }\n @if (widgetInstance.isMultiple) {\n <div>\n <mat-checkbox\n [formControlName]=\"\n widgetInstance.key + '.data.' + question.code + '.' + option.code\n \"\n [value]=\"widgetInstance.value['data'][question.code][option.code]\"\n [checked]=\"true\"\n ></mat-checkbox>\n </div>\n }\n </td>\n }\n <br />\n @if (widgetInstance.button) {\n <button mat-icon-button (click)=\"removeMatrixRow(question)\"\n ><smart-icon icon=\"close\"></smart-icon\n ></button>\n }\n </tr>\n }\n </table>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.YOUTUBE_PLAYER) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <youtube-player\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n videoId=\"{{ widgetInstance.videoId }}\"\n [width]=\"widgetInstance.width\"\n [height]=\"widgetInstance.height\"\n [startSeconds]=\"widgetInstance.startSeconds\"\n [endSeconds]=\"widgetInstance.endSeconds\"\n ></youtube-player>\n @if (\n !widgetInstance?.hint || widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n </div>\n }\n </div>\n", styles: [".ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container:not(.ql-disabled) li[data-list=checked]>.ql-ui,.ql-container:not(.ql-disabled) li[data-list=unchecked]>.ql-ui{cursor:pointer}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0}@supports (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-set:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor table{border-collapse:collapse}.ql-editor td{border:1px solid #000;padding:2px 5px}.ql-editor ol{padding-left:1.5em}.ql-editor li{list-style-type:none;padding-left:1.5em;position:relative}.ql-editor li>.ql-ui:before{display:inline-block;margin-left:-1.5em;margin-right:.3em;text-align:right;white-space:nowrap;width:1.2em}.ql-editor li[data-list=checked]>.ql-ui,.ql-editor li[data-list=unchecked]>.ql-ui{color:#777}.ql-editor li[data-list=bullet]>.ql-ui:before{content:\"\\2022\"}.ql-editor li[data-list=checked]>.ql-ui:before{content:\"\\2611\"}.ql-editor li[data-list=unchecked]>.ql-ui:before{content:\"\\2610\"}@supports (counter-set:none){.ql-editor li[data-list]{counter-set:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list]{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered]{counter-increment:list-0}.ql-editor li[data-list=ordered]>.ql-ui:before{content:counter(list-0,decimal) \". \"}.ql-editor li[data-list=ordered].ql-indent-1{counter-increment:list-1}.ql-editor li[data-list=ordered].ql-indent-1>.ql-ui:before{content:counter(list-1,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-set:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-2{counter-increment:list-2}.ql-editor li[data-list=ordered].ql-indent-2>.ql-ui:before{content:counter(list-2,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-set:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-3{counter-increment:list-3}.ql-editor li[data-list=ordered].ql-indent-3>.ql-ui:before{content:counter(list-3,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-set:list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-4{counter-increment:list-4}.ql-editor li[data-list=ordered].ql-indent-4>.ql-ui:before{content:counter(list-4,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-set:list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-5{counter-increment:list-5}.ql-editor li[data-list=ordered].ql-indent-5>.ql-ui:before{content:counter(list-5,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-set:list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-6{counter-increment:list-6}.ql-editor li[data-list=ordered].ql-indent-6>.ql-ui:before{content:counter(list-6,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-set:list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-reset:list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-7{counter-increment:list-7}.ql-editor li[data-list=ordered].ql-indent-7>.ql-ui:before{content:counter(list-7,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-set:list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-reset:list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-8{counter-increment:list-8}.ql-editor li[data-list=ordered].ql-indent-8>.ql-ui:before{content:counter(list-8,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-set:list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-reset:list-9}}.ql-editor li[data-list=ordered].ql-indent-9{counter-increment:list-9}.ql-editor li[data-list=ordered].ql-indent-9>.ql-ui:before{content:counter(list-9,decimal) \". \"}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor li.ql-direction-rtl{padding-right:1.5em}.ql-editor li.ql-direction-rtl>.ql-ui:before{margin-left:.3em;margin-right:-1.5em;text-align:left}.ql-editor table{table-layout:fixed;width:100%}.ql-editor table td{outline:none}.ql-editor .ql-code-block-container{font-family:monospace}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor .ql-ui{position:absolute}.ql-editor.ql-blank:before{color:#0009;content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-snow.ql-toolbar:after,.ql-snow .ql-toolbar:after{clear:both;content:\"\";display:table}.ql-snow.ql-toolbar button,.ql-snow .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-snow.ql-toolbar button svg,.ql-snow .ql-toolbar button svg{float:left;height:100%}.ql-snow.ql-toolbar button:active:hover,.ql-snow .ql-toolbar button:active:hover{outline:none}.ql-snow.ql-toolbar input.ql-image[type=file],.ql-snow .ql-toolbar input.ql-image[type=file]{display:none}.ql-snow.ql-toolbar button:hover,.ql-snow .ql-toolbar button:hover,.ql-snow.ql-toolbar button:focus,.ql-snow .ql-toolbar button:focus,.ql-snow.ql-toolbar button.ql-active,.ql-snow .ql-toolbar button.ql-active,.ql-snow.ql-toolbar .ql-picker-label:hover,.ql-snow .ql-toolbar .ql-picker-label:hover,.ql-snow.ql-toolbar .ql-picker-label.ql-active,.ql-snow .ql-toolbar .ql-picker-label.ql-active,.ql-snow.ql-toolbar .ql-picker-item:hover,.ql-snow .ql-toolbar .ql-picker-item:hover,.ql-snow.ql-toolbar .ql-picker-item.ql-selected,.ql-snow .ql-toolbar .ql-picker-item.ql-selected{color:#06c}.ql-snow.ql-toolbar button:hover .ql-fill,.ql-snow .ql-toolbar button:hover .ql-fill,.ql-snow.ql-toolbar button:focus .ql-fill,.ql-snow .ql-toolbar button:focus .ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#06c}.ql-snow.ql-toolbar button:hover .ql-stroke,.ql-snow .ql-toolbar button:hover .ql-stroke,.ql-snow.ql-toolbar button:focus .ql-stroke,.ql-snow .ql-toolbar button:focus .ql-stroke,.ql-snow.ql-toolbar button.ql-active .ql-stroke,.ql-snow .ql-toolbar button.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow.ql-toolbar button:hover .ql-stroke-miter,.ql-snow .ql-toolbar button:hover .ql-stroke-miter,.ql-snow.ql-toolbar button:focus .ql-stroke-miter,.ql-snow .ql-toolbar button:focus .ql-stroke-miter,.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#06c}@media(pointer:coarse){.ql-snow.ql-toolbar button:hover:not(.ql-active),.ql-snow .ql-toolbar button:hover:not(.ql-active){color:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#444}}.ql-snow,.ql-snow *{box-sizing:border-box}.ql-snow .ql-hidden{display:none}.ql-snow .ql-out-bottom,.ql-snow .ql-out-top{visibility:hidden}.ql-snow .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-snow .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-snow .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-snow .ql-formats{display:inline-block;vertical-align:middle}.ql-snow .ql-formats:after{clear:both;content:\"\";display:table}.ql-snow .ql-stroke{fill:none;stroke:#444;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-snow .ql-stroke-miter{fill:none;stroke:#444;stroke-miterlimit:10;stroke-width:2}.ql-snow .ql-fill,.ql-snow .ql-stroke.ql-fill{fill:#444}.ql-snow .ql-empty{fill:none}.ql-snow .ql-even{fill-rule:evenodd}.ql-snow .ql-thin,.ql-snow .ql-stroke.ql-thin{stroke-width:1}.ql-snow .ql-transparent{opacity:.4}.ql-snow .ql-direction svg:last-child{display:none}.ql-snow .ql-direction.ql-active svg:last-child{display:inline}.ql-snow .ql-direction.ql-active svg:first-child{display:none}.ql-snow .ql-editor h1{font-size:2em}.ql-snow .ql-editor h2{font-size:1.5em}.ql-snow .ql-editor h3{font-size:1.17em}.ql-snow .ql-editor h4{font-size:1em}.ql-snow .ql-editor h5{font-size:.83em}.ql-snow .ql-editor h6{font-size:.67em}.ql-snow .ql-editor a{text-decoration:underline}.ql-snow .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-snow .ql-editor code,.ql-snow .ql-editor .ql-code-block-container{background-color:#f0f0f0;border-radius:3px}.ql-snow .ql-editor .ql-code-block-container{margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-snow .ql-editor code{font-size:85%;padding:2px 4px}.ql-snow .ql-editor .ql-code-block-container{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-snow .ql-editor img{max-width:100%}.ql-snow .ql-picker{color:#444;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-snow .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-snow .ql-picker-label:before{display:inline-block;line-height:22px}.ql-snow .ql-picker-options{background-color:#fff;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-snow .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-snow .ql-picker.ql-expanded .ql-picker-label{color:#ccc;z-index:2}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-snow .ql-color-picker,.ql-snow .ql-icon-picker{width:28px}.ql-snow .ql-color-picker .ql-picker-label,.ql-snow .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-label svg,.ql-snow .ql-icon-picker .ql-picker-label svg{right:4px}.ql-snow .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-snow .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-snow .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=\"\"]):before{content:attr(data-label)}.ql-snow .ql-picker.ql-header{width:98px}.ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"1\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{content:\"Heading 1\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"2\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{content:\"Heading 2\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"3\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{content:\"Heading 3\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"4\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{content:\"Heading 4\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"5\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{content:\"Heading 5\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"6\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{content:\"Heading 6\"}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{font-size:2em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{font-size:1.5em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{font-size:1.17em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{font-size:1em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{font-size:.83em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{font-size:.67em}.ql-snow .ql-picker.ql-font{width:108px}.ql-snow .ql-picker.ql-font .ql-picker-label:before,.ql-snow .ql-picker.ql-font .ql-picker-item:before{content:\"Sans Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{content:\"Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{content:\"Monospace\"}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{font-family:Georgia,Times New Roman,serif}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{font-family:Monaco,Courier New,monospace}.ql-snow .ql-picker.ql-size{width:98px}.ql-snow .ql-picker.ql-size .ql-picker-label:before,.ql-snow .ql-picker.ql-size .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{content:\"Small\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{content:\"Large\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{content:\"Huge\"}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{font-size:10px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{font-size:18px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{font-size:32px}.ql-snow .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-snow .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-code-block-container{position:relative}.ql-code-block-container .ql-ui{right:5px;top:5px}.ql-toolbar.ql-snow{border:1px solid #ccc;box-sizing:border-box;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding:8px}.ql-toolbar.ql-snow .ql-formats{margin-right:15px}.ql-toolbar.ql-snow .ql-picker-label{border:1px solid transparent}.ql-toolbar.ql-snow .ql-picker-options{border:1px solid transparent;box-shadow:#0003 0 2px 8px}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label,.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{border-color:#ccc}.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover{border-color:#000}.ql-toolbar.ql-snow+.ql-container.ql-snow{border-top:0}.ql-snow .ql-tooltip{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.ql-snow .ql-tooltip:before{content:\"Visit URL:\";line-height:26px;margin-right:8px}.ql-snow .ql-tooltip input[type=text]{display:none;border:1px solid #ccc;font-size:13px;height:26px;margin:0;padding:3px 5px;width:170px}.ql-snow .ql-tooltip a.ql-preview{display:inline-block;max-width:200px;overflow-x:hidden;text-overflow:ellipsis;vertical-align:top}.ql-snow .ql-tooltip a.ql-action:after{border-right:1px solid #ccc;content:\"Edit\";margin-left:16px;padding-right:8px}.ql-snow .ql-tooltip a.ql-remove:before{content:\"Remove\";margin-left:8px}.ql-snow .ql-tooltip a{line-height:26px}.ql-snow .ql-tooltip.ql-editing a.ql-preview,.ql-snow .ql-tooltip.ql-editing a.ql-remove{display:none}.ql-snow .ql-tooltip.ql-editing input[type=text]{display:inline-block}.ql-snow .ql-tooltip.ql-editing a.ql-action:after{border-right:0;content:\"Save\";padding-right:0}.ql-snow .ql-tooltip[data-mode=link]:before{content:\"Enter link:\"}.ql-snow .ql-tooltip[data-mode=formula]:before{content:\"Enter formula:\"}.ql-snow .ql-tooltip[data-mode=video]:before{content:\"Enter video:\"}.ql-snow a{color:#06c}.ql-container.ql-snow{border:1px solid #ccc}.checkbox-section,.radio-section{display:flex;flex-direction:column}.input{width:100%}.direction-col,.toggle-col{display:flex;flex-direction:column;gap:.5em}.toggle-col>label{font-size:.75rem;color:#6b7280;padding-left:.5em}.direction-row{display:flex;flex-direction:row;align-items:center;gap:.5em}.selecatbleObject{margin:.5em}.radioLabel{color:var(--primary-color);text-align:left!important}.container{height:100%}.input{height:100%;display:flex;flex-direction:column}.checkbox{flex-direction:column}.mat-form-field-wrapper{padding-bottom:0!important}.input .mat-mdc-standard-chip.mat-chip-with-trailing-icon{padding-right:12px}.time-picker{display:flex;flex-direction:row;height:100%;border:solid 2px lightgrey;padding:1em;border-radius:4px}.time-picker:hover{border-color:#000}::ng-deep .mat-h4 .mat-body-1 .mat-typography h4{margin:0}.label{margin:28px 0 8px}.smartIndicator{display:flex;flex-direction:column;gap:.25rem;width:-moz-fit-content;width:fit-content}.indicatorItems{display:flex;flex-direction:row;gap:.25rem}.indicatorItem{width:3rem;height:.25rem;background-color:#d3d3d3;border-radius:.5rem}.radio-error{width:-moz-fit-content;width:fit-content;display:flex;flex-direction:row;gap:.5rem}.mat-calendar-previous-button,.mat-calendar-next-button{padding:0;min-width:0;width:40px!important;height:40px!important;flex-shrink:0;line-height:40px;border-radius:50%}.mat-calendar-arrow{height:36px!important;display:flex!important;flex-direction:column!important;justify-content:center}.radio-item-container,.checkbox-item-container{display:flex;flex-direction:column}.widgetContent::ng-deep .ql-container{height:200px;width:460px}.dateTimePickerContainer{display:flex;flex-direction:row;gap:.25rem}.dateTimePickerContainer mat-form-field{flex:1}.date,.time{width:100%}.date .mat-form-field-infix,.time .mat-form-field-infix{width:inherit!important}::ng-deep .mat-icon.mat-drag-indicator{--drag-indicator: #3b3b3b;color:var(--drag-indicator)}.matrixTable{width:100%;border-spacing:0 1rem}.matrixTable th{padding:.25rem}.matrixTable .optionLabel,.matrixTable td{text-align:center}.example-month-picker .mat-calendar-period-button{pointer-events:none}.example-month-picker .mat-calendar-arrow{display:none}.textFieldContainer{display:flex;flex-direction:row}.textFieldContainer{align-content:center;border:1px solid #cbd5e1;border-radius:3px;background-color:#fff}.textFieldContainer input{border:unset}.textFieldContainer:focus-within:not(:has(input:disabled)){outline:0 none;outline-offset:0;box-shadow:0 0 0 .2rem #a6d5fa;border-color:#2196f3}.textFieldContainer:has(input:disabled) .clearButton{cursor:not-allowed;opacity:.6}.textFieldButtons{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.clearButton .mat-mdc-raised-button,.clearButton button{background-color:unset!important;border:unset;color:#6b7280!important;box-shadow:unset;font-size:1rem!important}.clearButton .mat-icon.mat-primary{color:#6b7280!important}.clearButton .mat-mdc-raised-button:hover,.clearButton button:hover{color:#6b7280cc!important;background-color:unset;border:unset;box-shadow:unset;font-size:1rem!important}.mat-mdc-form-field-infix{display:flex;flex-direction:row}textarea:not(:placeholder-shown)~label{top:-.75em!important;font-size:12px!important}.disabledEditor *{-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only}.sb4-textarea{--sb4-textarea-line-height: 20px;line-height:var(--sb4-textarea-line-height);overflow-y:auto!important}.widgetContainer .imageIcon{max-width:unset!important;height:unset!important}.material .sb4-textarea{resize:vertical!important}.material .smart-form-widget-label{font-weight:700}.material .mat-mdc-form-field-subscript-wrapper{display:none}.label-right{display:flex;gap:.5rem;flex-direction:row-reverse}.label-left{display:flex;gap:.5rem;flex-direction:row}.label-top{display:flex;gap:.5rem;flex-direction:column}.label-bottom{display:flex;gap:.5rem;flex-direction:column-reverse}.smartDiv{width:100%}.clickable{cursor:pointer}\n/*!\n * Quill Editor v2.0.3\n * https://quilljs.com\n * Copyright (c) 2017-2024, Slab\n * Copyright (c) 2014, Jason Chen\n * Copyright (c) 2013, salesforce.com\n */\n"] }]
11596
+ args: [{ selector: 'smartformwidget', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, ReactiveFormsModule, NgClass, TrackCapsDirective, NgStyle, MatHint, MatFormField, MatLabel, MatInput, NgxMaskDirective, MatAutocompleteTrigger, MatIconButton, MatSuffix, MatIcon, MatAutocomplete, MatOption, MatPrefix, SmartIconComponent, UiActionButtonComponent, UiActionToolbarComponent, MatButton, MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChip, CdkTextareaAutosize, MatCheckbox, MatRadioGroup, MatRadioButton, MatDatepickerToggle, MatDatepicker, MatDatepickerInput, SmartMonthPickerComponent, MatSelect, MatOptgroup, MatSlideToggle, SmartVoiceRecorderComponent, SmartFileEditorComponent, SmartMultiFileEditorComponent, SmartHtmlWidgetComponent, QuillEditorComponent, SortableWidgetComponent, YouTubePlayer, AsyncPipe, HighlightPipe], template: "<div class=\"container material\" [formGroup]=\"form()\">\n @if (widgetInstance.isVisible === undefined ? true : widgetInstance.isVisible) {\n <div\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n class=\"container\"\n >\n @if (widgetInstance.type === smartFormWidgetType.CONTAINER) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getDirection()\"\n >\n @for (widget of visibleChildren; track widget) {\n <smartformwidget\n [form]=\"form()\"\n [widgetInstance]=\"widget\"\n class=\"container-item\"\n [ngClass]=\"widget.cssClass ?? ''\"\n [onBlur]=\"onBlur()\"\n [onValueChange]=\"onValueChange\"\n [sophisticatedValueChange]=\"sophisticatedValueChange()\"\n [blurSophisticatedValueChange]=\"blurSophisticatedValueChange()\"\n class=\"{{ widget.key }}\"\n [labelColor]=\"labelColor()\"\n ></smartformwidget>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD) {\n <div\n (capsLock)=\"capsOn = $event\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n @if (!widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [attr.inputmode]=\"\n widgetInstance.inputMode ? widgetInstance.inputMode.toLocaleLowerCase() : 'text'\n \"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? (hidePassword ? 'password' : 'text') : '' }}\"\n (keydown.enter)=\"onKeydown()\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n [mask]=\"widgetInstance.mask\"\n />\n }\n <!-- [mask]=\"widgetInstance.mask ?? ''\" -->\n @if (widgetInstance.selection) {\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n (click)=\"onValueChange?.next($event)\"\n type=\"{{ widgetInstance.isPassword ? 'password' : '' }}\"\n [matAutocomplete]=\"textFieldAuto\"\n (keydown.enter)=\"onKeydown()\"\n />\n }\n @if (widgetInstance.isPassword) {\n <button\n mat-icon-button\n matSuffix\n (click)=\"togglePasswordVisibility($event)\"\n >\n <mat-icon>{{ hidePassword ? 'visibility_off' : 'visibility' }}</mat-icon>\n </button>\n }\n <mat-autocomplete #textFieldAuto=\"matAutocomplete\">\n @for (option of filteredOptions | async; track option) {\n <mat-option [value]=\"option.label\">\n <span [innerHTML]=\"option.label | highlight: toHighlight\"></span>\n </mat-option>\n }\n </mat-autocomplete>\n @if (capsOn && widgetInstance.isPassword) {\n <span class=\"mat-error\">\n {{ widgetInstance.capsLockWarning }}\n </span>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n @if (capsOn && widgetInstance.isPassword) {\n <smart-icon\n [icon]=\"widgetInstance.capsLockWarningIcon ?? 'keyboard_capslock'\"\n color=\"warn\"\n ></smart-icon>\n }\n @if (widgetInstance.icon && widgetInstance.iconPosition === 'PRE') {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n ></smart-icon>\n }\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <div class=\"textFieldButtons\">\n @if (widgetInstance.textFieldProperties?.clearable) {\n <ui-action-button\n class=\"clearButton\"\n [addBasicClasses]=\"false\"\n [descriptor]=\"clearButtonDescriptor\"\n (actionClick)=\"clearField(widgetInstance.key)\"\n />\n }\n </div>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n [color]=\"widgetInstance.textFieldButton.iconColor\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_NUMBER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input textField widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n [type]=\"'number'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [min]=\"widgetInstance.minValues ?? null\"\n [max]=\"widgetInstance.maxValues ?? null\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n <span matPrefix>\n {{ widgetInstance.prefix }}\n </span>\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (widgetInstance.icon) {\n <smart-icon [icon]=\"widgetInstance.icon\" matSuffix>\n </smart-icon>\n }\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.textFieldButton) {\n <button\n matSuffix\n mat-button\n color=\"{{ widgetInstance.textFieldButton.color }}\"\n (click)=\"widgetInstance.textFieldButton.callback(widgetInstance)\"\n >\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().PRE && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n {{ widgetInstance.textFieldButton.label }}\n @if (\n widgetInstance.textFieldButton.iconPosition ===\n smartFormTextFieldButtonIconPosition().POST && widgetInstance.textFieldButton.icon\n ) {\n <smart-icon\n [icon]=\"widgetInstance.textFieldButton.icon\"\n >\n </smart-icon>\n }\n </button>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_CHIPS) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipList aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip-row\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ value }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n #chipInput\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipList\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [matChipInputAddOnBlur]=\"addOnBlur\"\n [readonly]=\"widgetInstance.isReadonly\"\n [matAutocomplete]=\"chipAuto\"\n (matChipInputTokenEnd)=\"add($event)\"\n (change)=\"handleBlurEvent($event)\"\n (input)=\"onValueChange?.next($event)\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n <mat-autocomplete\n #chipAuto=\"matAutocomplete\"\n (optionSelected)=\"selected($event, widgetInstance)\"\n >\n @for (item of widgetInstance.valueList; track item) {\n <mat-option\n [disabled]=\"widgetInstance.isDisabled\"\n [value]=\"item.value\"\n >\n {{ item.label }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-chip-grid>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_FIELD_LOOKUP) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-chip-grid #chipListLookup aria-label=\"{{ widgetInstance.label }}\">\n @for (value of widgetInstance.value; track value) {\n <mat-chip\n [disabled]=\"widgetInstance.isDisabled\"\n (removed)=\"remove(value)\"\n >\n {{ getChipsValue(value) }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n }\n <input\n [attr.data-testid]=\"widgetInstance.key\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matChipInputFor]=\"chipListLookup\"\n [matChipInputSeparatorKeyCodes]=\"emptySeparatorKeysCodes\"\n [matChipInputAddOnBlur]=\"false\"\n [readonly]=\"true\"\n [disabled]=\"widgetInstance.isDisabled\"\n />\n </mat-chip-grid>\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TEXT_BOX) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <textarea\n class=\"sb4-textarea\"\n #sb4Textarea\n cols=\"30\"\n cdkTextareaAutosize\n [cdkAutosizeMinRows]=\"widgetInstance.textBoxProperties?.minRows ?? 1\"\n [cdkAutosizeMaxRows]=\"widgetInstance.textBoxProperties?.maxRows ?? undefined\"\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'string'\"\n [value]=\"widgetInstance.value\"\n [readonly]=\"widgetInstance.isReadonly\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent($event)\"\n maxlength=\"{{ widgetInstance.maxLength }}\"\n ></textarea>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n >{{\n widgetInstance.maxLength - form().controls[widgetInstance.key].value.length\n }}</mat-hint\n >\n }\n </mat-form-field>\n @if (\n !widgetInstance.hint || widgetInstance.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n <div class=\"checkbox-item-container\">\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key }}\"\n (change)=\"onValueChange?.next(widgetInstance)\"\n (change)=\"onBlur()?.next(widgetInstance)\"\n >\n {{ widgetInstance.label }}\n </mat-checkbox>\n </div>\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.CHECK_BOX_2) {\n <div\n [attr.data-testid]=\"widgetInstance.key\"\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"input checkbox widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <section class=\"checkbox-section\" [ngClass]=\"getDirection()\">\n @for (checkbox of widgetInstance.valueList; track checkbox; let i = $index) {\n <div\n class=\"checkbox-item-container\"\n >\n @if (checkbox.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"checkbox-item-image\"\n [src]=\"checkbox.imageUrl\"\n />\n }\n <mat-checkbox\n class=\"selecatbleObject\"\n formControlName=\"{{ widgetInstance.key + '.' + checkbox.key }}\"\n [value]=\"checkbox.value\"\n (change)=\"onValueChange?.next(checkbox)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n >\n {{ checkbox.label }}\n </mat-checkbox>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </section>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RADIO_BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-radio-group\n class=\"input radio-section widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n [attr.data-testid]=\"widgetInstance.key\"\n aria-label=\"{{ widgetInstance.label }}\"\n appearance=\"outline\"\n formControlName=\"{{ widgetInstance.key }}\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label class=\"radioLabel\">\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <div [ngClass]=\"getDirection()\">\n @for (radio of widgetInstance.valueList; track radio) {\n <div class=\"radio-item-container\">\n @if (radio.imageUrl) {\n <img\n title=\"{{ widgetInstance.key }}\"\n class=\"radio-item-image\"\n [src]=\"radio.imageUrl\"\n />\n }\n <mat-radio-button\n class=\"selecatbleObject\"\n value=\"{{ radio.value }}\"\n [ngClass]=\"getDirection()\"\n (change)=\"onValueChange?.next(radio.value)\"\n [disabled]=\"widgetInstance.isDisabled\"\n >\n {{ radio.label }}\n </mat-radio-button>\n </div>\n }\n <div class=\"radio-error\">\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n <div class=\"radio-icon\">\n @if (widgetInstance.icon) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n >\n </smart-icon>\n }\n </div>\n </div>\n </mat-radio-group>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_PICKER) {\n <div\n class=\"datePicker widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n matInput\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (change)=\"handleBlurEvent(widgetInstance)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MONTH_PICKER) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div class=\"{{ labelColor() }} smart-form-widget-label\">\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <lib-smart-month-picker\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (valueChange)=\"handleYearMonthPicked($event)\"\n ></lib-smart-month-picker>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DATE_TIME_PICKER) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div class=\"dateTimePickerContainer\">\n <mat-form-field\n class=\"input widgetContent date {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker (closed)=\"handleBlurEvent(widgetInstance)\"></mat-datepicker>\n <input\n #dateInput\n matInput\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [min]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.minDate ?? null)\"\n [max]=\"convertToLocalDateTime(widgetInstance.dateFieldProperties?.maxDate ?? null)\"\n [id]=\"widgetInstance.key\"\n [value]=\"widgetInstance.value\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n [matDatepicker]=\"picker\"\n (blur)=\"onDatePickerBlur($event)\"\n (dateChange)=\"onValueChange?.next(widgetInstance)\"\n [matDatepickerFilter]=\"widgetInstance.filter ?? dateFilter\"\n />\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n <mat-hint>\n {{ widgetInstance.dateFormatHint }}\n </mat-hint>\n </mat-form-field>\n @if (hasCreated) {\n <mat-form-field\n class=\"input widgetContent time\"\n [ngClass]=\"widgetInstance.cssClass ?? ''\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n appearance=\"outline\"\n >\n <input\n #timeInput\n [formControlName]=\"widgetInstance.key + '-time'\"\n [attr.data-testid]=\"widgetInstance.key + '-time'\"\n [id]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n (blur)=\"onTimePickerBlur($event)\"\n matInput\n />\n </mat-form-field>\n }\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <div\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </div>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon>\n }\n {{ innerOption.label }}\n </mat-option>\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n <span matSuffix>\n {{ widgetInstance.suffix }}\n </span>\n @if (\n widgetInstance.icon &&\n (!widgetInstance.iconPosition || widgetInstance.iconPosition === 'POST')\n ) {\n <smart-icon\n [icon]=\"widgetInstance.icon\"\n [color]=\"widgetInstance.iconColor ?? 'primary'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SELECT_MULTIPLE) {\n <div\n class=\"widgetContainer\"\n >\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <mat-select\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n multiple\n (selectionChange)=\"onValueChange?.next($event.value)\"\n (closed)=\"handleBlurEvent(widgetInstance)\"\n [disabled]=\"widgetInstance.isDisabled!\"\n [compareWith]=\"\n widgetInstance.compareWith == null ? compareItems : widgetInstance.compareWith\n \"\n placeholder=\"{{ widgetInstance.placeholder ? widgetInstance.placeholder : '' }}\"\n >\n @for (option of widgetInstance.valueList; track option) {\n <div>\n @if (option.type === getType().ITEM_GROUP) {\n <mat-optgroup\n [label]=\"option.label\"\n [disabled]=\"option.isDisabled\"\n >\n @for (innerOption of option.valueList; track innerOption) {\n <mat-option\n [value]=\"innerOption.value\"\n [disabled]=\"innerOption.isDisabled\"\n >\n @if (innerOption.icon) {\n <smart-icon\n [icon]=\"innerOption.icon\"\n [color]=\"innerOption.iconColor\"\n ></smart-icon\n >\n }{{ innerOption.label }}</mat-option\n >\n }\n </mat-optgroup>\n }\n @if (option.type === getType().ITEM) {\n <mat-option\n [value]=\"option.value\"\n [disabled]=\"option.isDisabled\"\n >\n @if (option.icon) {\n <smart-icon\n [icon]=\"option.icon\"\n [color]=\"option.iconColor\"\n ></smart-icon\n >\n }{{ option.label }}</mat-option\n >\n }\n </div>\n }\n </mat-select>\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n @if (isToolbarPresent()) {\n <smart-ui-action-toolbar\n class=\"textFieldToolbar\"\n matSuffix\n [id]=\"widgetInstance.toolbarId\"\n ></smart-ui-action-toolbar>\n }\n </mat-form-field>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.LABEL) {\n <div\n class=\"label widgetContainer\"\n [ngStyle]=\"{ width: widgetInstance.minWidth + 'px' }\"\n >\n <div class=\"label-title labelContainer\" [ngClass]=\"widgetInstance.cssClass ?? ''\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance.widgetDescription) {\n <p>{{ widgetInstance.widgetDescription }}</p>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TIME) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <mat-form-field\n class=\"input widgetContent time {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n appearance=\"outline\"\n >\n @if (!widgetInstance.showLabel) {\n <mat-label\n class=\"label\"\n [ngClass]=\"widgetInstance.cssLabelClass ?? ''\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </mat-label>\n }\n <input\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [type]=\"'time'\"\n placeholder=\"{{ widgetInstance.placeholder }}\"\n matInput\n (change)=\"handleBlurEvent(widgetInstance)\"\n />\n <span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n matSuffix\n ></smart-icon>\n }\n </mat-form-field>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.TOGGLE) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <div class=\"labelContainer\">\n <h4\n class=\"{{ labelColor() }} smart-form-widget-label {{\n widgetInstance.cssLabelClass ?? ''\n }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <mat-slide-toggle\n formControlName=\"{{ widgetInstance.key }}\"\n [attr.data-testid]=\"widgetInstance.key\"\n (change)=\"onValueChange?.next($event)\"\n [labelPosition]=\"widgetInstance.toggleLabelPosition ?? 'before'\"\n >{{ !widgetInstance.showLabel ? widgetInstance.label : '' }}</mat-slide-toggle\n ><span class=\"mat-error\">\n {{ widgetInstance.error }}\n </span>\n @if (widgetInstance.error && widgetInstance.errorIcon) {\n <smart-icon\n [icon]=\"widgetInstance.errorIcon\"\n [color]=\"widgetInstance.errorIconColor ?? 'warn'\"\n ></smart-icon>\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.INDICATOR) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} labelContainer {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"smartIndicator widgetContent\">\n <div class=\"indicatorItems {{ widgetInstance.cssClass ?? '' }}\" [ngClass]=\"getNgClass()\">\n @for (item of indicatorItems; track item; let i = $index) {\n <div\n class=\"indicatorItem\"\n [ngClass]=\"getIndicatorItemClass(i)\"\n ></div>\n }\n </div>\n <p [ngClass]=\"getIndicatorStatusLabelColor()\">\n {{ getIndicatorStatusLabel() }}\n </p>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RECORDING_UPLOADER) {\n <div class=\"widgetContainer\">\n <div class=\"widgetItemContainer\">\n <smart-voice-recorder\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MULTI_FILE_UPLOADER) {\n <div class=\"widgetContainer\">\n <smart-multi-file-editor\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n (uploadFilesEvent)=\"upload($event)\"\n (fileEvent)=\"executeUiAction($event.uiAction)\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.IMAGE) {\n <div class=\"widgetContainer imageContainer\">\n @if (widgetInstance.showLabel && getWidgetLabel(widgetInstance)) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance.imageProperties?.image) {\n <smart-icon\n [imageResource]=\"$safeNavigationMigration(widgetInstance.imageProperties?.image)\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n } @else if (widgetInstance.value) {\n <smart-icon\n [(ngModel)]=\"widgetInstance.value\"\n [imageResource]=\"widgetInstance.value\"\n class=\"widgetContent {{ widgetInstance.imageCss ?? '' }}\"\n alt=\"Image\"\n title=\"{{ widgetInstance.key }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-icon>\n }\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIV) {\n <div\n class=\"smartDiv\"\n [innerHTML]=\"sanitizeHtml(getWidgetLabel(widgetInstance))\"\n [ngClass]=\"getNgClass()\"\n [class.clickable]=\"!!widgetInstance.divProperties?.onClick\"\n [ngStyle]=\"getStyle()\"\n (click)=\"onDivClick()\"\n >\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.HTML) {\n <smart-html-widget\n [widgetInstance]=\"widgetInstance\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></smart-html-widget>\n }\n @if (widgetInstance.type === smartFormWidgetType.SVG) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [innerHTML]=\"sanitizeHtml(widgetInstance.value)\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n ></div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.DIVIDER) {\n <div class=\"widgetContainer\">\n <hr\n class=\"smartDivider {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n />\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.BUTTON) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }} {{ widgetInstance.cssLabelClass ?? '' }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div\n class=\"widgetContent {{ widgetInstance.cssClass ?? '' }}\"\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n >\n <button\n mat-button\n [attr.data-testid]=\"widgetInstance.key\"\n [ngClass]=\"getButtonType(widgetInstance.uiActionDescriptor)\"\n [color]=\"$safeNavigationMigration(widgetInstance.uiActionDescriptor?.color)\"\n (click)=\"onButtonClicked(widgetInstance)\"\n >\n @if (isOnlyIcon(widgetInstance.uiActionDescriptor)) {\n @if (widgetInstance.uiActionDescriptor?.icon) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n } @else {\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'PRE'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n {{ widgetInstance.uiActionDescriptor?.title }}\n @if (\n widgetInstance.uiActionDescriptor?.icon &&\n widgetInstance.uiActionDescriptor?.iconPosition === 'POST'\n ) {\n <smart-icon\n [icon]=\"widgetInstance.uiActionDescriptor!.icon!\"\n [color]=\"\n widgetInstance.uiActionDescriptor?.iconColor ??\n widgetInstance.uiActionDescriptor?.color\n \"\n ></smart-icon>\n }\n }\n </button>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.COMPONENT) {\n <div class=\"widgetContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"labelContainer {{ labelColor() }}\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n <div class=\"widgetContent\">\n <ng-template #customComponent></ng-template>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.RICH_TEXT) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <quill-editor\n #quillEditor\n [formControlName]=\"widgetInstance.key\"\n [id]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [modules]=\"widgetInstance.isDisabled ? emptyQuillToolbar : widgetInstance.quillModules\"\n [placeholder]=\"widgetInstance.placeholder ?? ''\"\n [readOnly]=\"widgetInstance.isReadonly ?? false\"\n [maxLength]=\"widgetInstance.maxLength ?? 0\"\n (onContentChanged)=\"onRichTextEditorContentChanged($event)\"\n ></quill-editor>\n @if (\n !widgetInstance?.hint ||\n widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n @if (widgetInstance.showCharacterLimitSuffix && widgetInstance.maxLength) {\n <mat-hint\n matSuffix\n align=\"end\"\n class=\"rich-text-editor-leeway-counter\"\n >{{ getRichTextEditorLengthLeeway() }}</mat-hint\n >\n }\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.SORTABLE) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <div class=\"widgetContent\">\n <lib-sortable-widget\n [formControlName]=\"widgetInstance.key\"\n [attr.data-testid]=\"widgetInstance.key\"\n [widgetInstance]=\"widgetInstance\"\n ></lib-sortable-widget>\n </div>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.MATRIX) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4 class=\"{{ labelColor() }}\">\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <table class=\"matrixTable widgetContent\">\n <tr>\n <th></th>\n @for (option of widgetInstance.value.columns; track option) {\n <th class=\"optionLabel\">\n {{ option.displayValue }}\n </th>\n }\n </tr>\n @for (question of widgetInstance.value.rows; track question; let i = $index) {\n <tr>\n <th class=\"questionLabel\">\n <label>{{ question.displayValue }}</label>\n </th>\n @for (option of widgetInstance.value.columns; track option; let j = $index) {\n <td class=\"selectTd\">\n @if (!widgetInstance.isMultiple) {\n <mat-radio-group\n [formControlName]=\"widgetInstance.key + '.' + question.code\"\n [name]=\"'q' + i\"\n >\n <mat-radio-button [value]=\"option.code\"> </mat-radio-button>\n </mat-radio-group>\n }\n @if (widgetInstance.isMultiple) {\n <div>\n <mat-checkbox\n [formControlName]=\"\n widgetInstance.key + '.data.' + question.code + '.' + option.code\n \"\n [value]=\"widgetInstance.value['data'][question.code][option.code]\"\n [checked]=\"true\"\n ></mat-checkbox>\n </div>\n }\n </td>\n }\n <br />\n @if (widgetInstance.button) {\n <button mat-icon-button (click)=\"removeMatrixRow(question)\"\n ><smart-icon icon=\"close\"></smart-icon\n ></button>\n }\n </tr>\n }\n </table>\n </div>\n }\n @if (widgetInstance.type === smartFormWidgetType.YOUTUBE_PLAYER) {\n <div class=\"widgetContainer\">\n <div class=\"labelContainer\">\n @if (widgetInstance.showLabel) {\n <h4\n class=\"{{ labelColor() }} {{ widgetInstance.cssLabelClass }}\"\n [ngClass]=\"getLabelNgClass()\"\n [ngStyle]=\"getLabelStyle()\"\n >\n {{ getWidgetLabel(widgetInstance) }}\n </h4>\n }\n @if (widgetInstance?.hint?.position === SmartWidgetHintPosition.LABEL) {\n <mat-hint>{{\n widgetInstance.hint?.text\n }}</mat-hint>\n }\n </div>\n <youtube-player\n [ngClass]=\"getNgClass()\"\n [ngStyle]=\"getStyle()\"\n videoId=\"{{ widgetInstance.videoId }}\"\n [width]=\"widgetInstance.width\"\n [height]=\"widgetInstance.height\"\n [startSeconds]=\"widgetInstance.startSeconds\"\n [endSeconds]=\"widgetInstance.endSeconds\"\n ></youtube-player>\n @if (\n !widgetInstance?.hint || widgetInstance?.hint?.position === SmartWidgetHintPosition.INPUT\n ) {\n <mat-hint\n >{{ widgetInstance.hint?.text }}</mat-hint\n >\n }\n </div>\n }\n </div>\n }\n </div>\n", styles: [".ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container:not(.ql-disabled) li[data-list=checked]>.ql-ui,.ql-container:not(.ql-disabled) li[data-list=unchecked]>.ql-ui{cursor:pointer}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;line-height:1.42;height:100%;outline:none;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0}@supports (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-set:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor p,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{counter-reset:list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor table{border-collapse:collapse}.ql-editor td{border:1px solid #000;padding:2px 5px}.ql-editor ol{padding-left:1.5em}.ql-editor li{list-style-type:none;padding-left:1.5em;position:relative}.ql-editor li>.ql-ui:before{display:inline-block;margin-left:-1.5em;margin-right:.3em;text-align:right;white-space:nowrap;width:1.2em}.ql-editor li[data-list=checked]>.ql-ui,.ql-editor li[data-list=unchecked]>.ql-ui{color:#777}.ql-editor li[data-list=bullet]>.ql-ui:before{content:\"\\2022\"}.ql-editor li[data-list=checked]>.ql-ui:before{content:\"\\2611\"}.ql-editor li[data-list=unchecked]>.ql-ui:before{content:\"\\2610\"}@supports (counter-set:none){.ql-editor li[data-list]{counter-set:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list]{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered]{counter-increment:list-0}.ql-editor li[data-list=ordered]>.ql-ui:before{content:counter(list-0,decimal) \". \"}.ql-editor li[data-list=ordered].ql-indent-1{counter-increment:list-1}.ql-editor li[data-list=ordered].ql-indent-1>.ql-ui:before{content:counter(list-1,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-set:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-2{counter-increment:list-2}.ql-editor li[data-list=ordered].ql-indent-2>.ql-ui:before{content:counter(list-2,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-set:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-3{counter-increment:list-3}.ql-editor li[data-list=ordered].ql-indent-3>.ql-ui:before{content:counter(list-3,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-set:list-4 list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-4{counter-increment:list-4}.ql-editor li[data-list=ordered].ql-indent-4>.ql-ui:before{content:counter(list-4,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-set:list-5 list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-5{counter-increment:list-5}.ql-editor li[data-list=ordered].ql-indent-5>.ql-ui:before{content:counter(list-5,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-set:list-6 list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-6{counter-increment:list-6}.ql-editor li[data-list=ordered].ql-indent-6>.ql-ui:before{content:counter(list-6,decimal) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-set:list-7 list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-6{counter-reset:list-7 list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-7{counter-increment:list-7}.ql-editor li[data-list=ordered].ql-indent-7>.ql-ui:before{content:counter(list-7,lower-alpha) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-set:list-8 list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-7{counter-reset:list-8 list-9}}.ql-editor li[data-list=ordered].ql-indent-8{counter-increment:list-8}.ql-editor li[data-list=ordered].ql-indent-8>.ql-ui:before{content:counter(list-8,lower-roman) \". \"}@supports (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-set:list-9}}@supports not (counter-set:none){.ql-editor li[data-list].ql-indent-8{counter-reset:list-9}}.ql-editor li[data-list=ordered].ql-indent-9{counter-increment:list-9}.ql-editor li[data-list=ordered].ql-indent-9>.ql-ui:before{content:counter(list-9,decimal) \". \"}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor li.ql-direction-rtl{padding-right:1.5em}.ql-editor li.ql-direction-rtl>.ql-ui:before{margin-left:.3em;margin-right:-1.5em;text-align:left}.ql-editor table{table-layout:fixed;width:100%}.ql-editor table td{outline:none}.ql-editor .ql-code-block-container{font-family:monospace}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor .ql-ui{position:absolute}.ql-editor.ql-blank:before{color:#0009;content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-snow.ql-toolbar:after,.ql-snow .ql-toolbar:after{clear:both;content:\"\";display:table}.ql-snow.ql-toolbar button,.ql-snow .ql-toolbar button{background:none;border:none;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-snow.ql-toolbar button svg,.ql-snow .ql-toolbar button svg{float:left;height:100%}.ql-snow.ql-toolbar button:active:hover,.ql-snow .ql-toolbar button:active:hover{outline:none}.ql-snow.ql-toolbar input.ql-image[type=file],.ql-snow .ql-toolbar input.ql-image[type=file]{display:none}.ql-snow.ql-toolbar button:hover,.ql-snow .ql-toolbar button:hover,.ql-snow.ql-toolbar button:focus,.ql-snow .ql-toolbar button:focus,.ql-snow.ql-toolbar button.ql-active,.ql-snow .ql-toolbar button.ql-active,.ql-snow.ql-toolbar .ql-picker-label:hover,.ql-snow .ql-toolbar .ql-picker-label:hover,.ql-snow.ql-toolbar .ql-picker-label.ql-active,.ql-snow .ql-toolbar .ql-picker-label.ql-active,.ql-snow.ql-toolbar .ql-picker-item:hover,.ql-snow .ql-toolbar .ql-picker-item:hover,.ql-snow.ql-toolbar .ql-picker-item.ql-selected,.ql-snow .ql-toolbar .ql-picker-item.ql-selected{color:#06c}.ql-snow.ql-toolbar button:hover .ql-fill,.ql-snow .ql-toolbar button:hover .ql-fill,.ql-snow.ql-toolbar button:focus .ql-fill,.ql-snow .ql-toolbar button:focus .ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#06c}.ql-snow.ql-toolbar button:hover .ql-stroke,.ql-snow .ql-toolbar button:hover .ql-stroke,.ql-snow.ql-toolbar button:focus .ql-stroke,.ql-snow .ql-toolbar button:focus .ql-stroke,.ql-snow.ql-toolbar button.ql-active .ql-stroke,.ql-snow .ql-toolbar button.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow.ql-toolbar button:hover .ql-stroke-miter,.ql-snow .ql-toolbar button:hover .ql-stroke-miter,.ql-snow.ql-toolbar button:focus .ql-stroke-miter,.ql-snow .ql-toolbar button:focus .ql-stroke-miter,.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#06c}@media(pointer:coarse){.ql-snow.ql-toolbar button:hover:not(.ql-active),.ql-snow .ql-toolbar button:hover:not(.ql-active){color:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#444}}.ql-snow,.ql-snow *{box-sizing:border-box}.ql-snow .ql-hidden{display:none}.ql-snow .ql-out-bottom,.ql-snow .ql-out-top{visibility:hidden}.ql-snow .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-snow .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-snow .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-snow .ql-formats{display:inline-block;vertical-align:middle}.ql-snow .ql-formats:after{clear:both;content:\"\";display:table}.ql-snow .ql-stroke{fill:none;stroke:#444;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-snow .ql-stroke-miter{fill:none;stroke:#444;stroke-miterlimit:10;stroke-width:2}.ql-snow .ql-fill,.ql-snow .ql-stroke.ql-fill{fill:#444}.ql-snow .ql-empty{fill:none}.ql-snow .ql-even{fill-rule:evenodd}.ql-snow .ql-thin,.ql-snow .ql-stroke.ql-thin{stroke-width:1}.ql-snow .ql-transparent{opacity:.4}.ql-snow .ql-direction svg:last-child{display:none}.ql-snow .ql-direction.ql-active svg:last-child{display:inline}.ql-snow .ql-direction.ql-active svg:first-child{display:none}.ql-snow .ql-editor h1{font-size:2em}.ql-snow .ql-editor h2{font-size:1.5em}.ql-snow .ql-editor h3{font-size:1.17em}.ql-snow .ql-editor h4{font-size:1em}.ql-snow .ql-editor h5{font-size:.83em}.ql-snow .ql-editor h6{font-size:.67em}.ql-snow .ql-editor a{text-decoration:underline}.ql-snow .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-snow .ql-editor code,.ql-snow .ql-editor .ql-code-block-container{background-color:#f0f0f0;border-radius:3px}.ql-snow .ql-editor .ql-code-block-container{margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-snow .ql-editor code{font-size:85%;padding:2px 4px}.ql-snow .ql-editor .ql-code-block-container{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-snow .ql-editor img{max-width:100%}.ql-snow .ql-picker{color:#444;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-snow .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-snow .ql-picker-label:before{display:inline-block;line-height:22px}.ql-snow .ql-picker-options{background-color:#fff;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-snow .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-snow .ql-picker.ql-expanded .ql-picker-label{color:#ccc;z-index:2}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-snow .ql-color-picker,.ql-snow .ql-icon-picker{width:28px}.ql-snow .ql-color-picker .ql-picker-label,.ql-snow .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-label svg,.ql-snow .ql-icon-picker .ql-picker-label svg{right:4px}.ql-snow .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-snow .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-snow .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=\"\"]):before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=\"\"]):before{content:attr(data-label)}.ql-snow .ql-picker.ql-header{width:98px}.ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"1\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{content:\"Heading 1\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"2\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{content:\"Heading 2\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"3\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{content:\"Heading 3\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"4\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{content:\"Heading 4\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"5\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{content:\"Heading 5\"}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=\"6\"]:before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{content:\"Heading 6\"}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"1\"]:before{font-size:2em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"2\"]:before{font-size:1.5em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"3\"]:before{font-size:1.17em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"4\"]:before{font-size:1em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"5\"]:before{font-size:.83em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=\"6\"]:before{font-size:.67em}.ql-snow .ql-picker.ql-font{width:108px}.ql-snow .ql-picker.ql-font .ql-picker-label:before,.ql-snow .ql-picker.ql-font .ql-picker-item:before{content:\"Sans Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{content:\"Serif\"}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]:before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{content:\"Monospace\"}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]:before{font-family:Georgia,Times New Roman,serif}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]:before{font-family:Monaco,Courier New,monospace}.ql-snow .ql-picker.ql-size{width:98px}.ql-snow .ql-picker.ql-size .ql-picker-label:before,.ql-snow .ql-picker.ql-size .ql-picker-item:before{content:\"Normal\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{content:\"Small\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{content:\"Large\"}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]:before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{content:\"Huge\"}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]:before{font-size:10px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]:before{font-size:18px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]:before{font-size:32px}.ql-snow .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-snow .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-code-block-container{position:relative}.ql-code-block-container .ql-ui{right:5px;top:5px}.ql-toolbar.ql-snow{border:1px solid #ccc;box-sizing:border-box;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;padding:8px}.ql-toolbar.ql-snow .ql-formats{margin-right:15px}.ql-toolbar.ql-snow .ql-picker-label{border:1px solid transparent}.ql-toolbar.ql-snow .ql-picker-options{border:1px solid transparent;box-shadow:#0003 0 2px 8px}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label,.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{border-color:#ccc}.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover{border-color:#000}.ql-toolbar.ql-snow+.ql-container.ql-snow{border-top:0}.ql-snow .ql-tooltip{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.ql-snow .ql-tooltip:before{content:\"Visit URL:\";line-height:26px;margin-right:8px}.ql-snow .ql-tooltip input[type=text]{display:none;border:1px solid #ccc;font-size:13px;height:26px;margin:0;padding:3px 5px;width:170px}.ql-snow .ql-tooltip a.ql-preview{display:inline-block;max-width:200px;overflow-x:hidden;text-overflow:ellipsis;vertical-align:top}.ql-snow .ql-tooltip a.ql-action:after{border-right:1px solid #ccc;content:\"Edit\";margin-left:16px;padding-right:8px}.ql-snow .ql-tooltip a.ql-remove:before{content:\"Remove\";margin-left:8px}.ql-snow .ql-tooltip a{line-height:26px}.ql-snow .ql-tooltip.ql-editing a.ql-preview,.ql-snow .ql-tooltip.ql-editing a.ql-remove{display:none}.ql-snow .ql-tooltip.ql-editing input[type=text]{display:inline-block}.ql-snow .ql-tooltip.ql-editing a.ql-action:after{border-right:0;content:\"Save\";padding-right:0}.ql-snow .ql-tooltip[data-mode=link]:before{content:\"Enter link:\"}.ql-snow .ql-tooltip[data-mode=formula]:before{content:\"Enter formula:\"}.ql-snow .ql-tooltip[data-mode=video]:before{content:\"Enter video:\"}.ql-snow a{color:#06c}.ql-container.ql-snow{border:1px solid #ccc}.checkbox-section,.radio-section{display:flex;flex-direction:column}.input{width:100%}.direction-col,.toggle-col{display:flex;flex-direction:column;gap:.5em}.toggle-col>label{font-size:.75rem;color:#6b7280;padding-left:.5em}.direction-row{display:flex;flex-direction:row;align-items:center;gap:.5em}.selecatbleObject{margin:.5em}.radioLabel{color:var(--primary-color);text-align:left!important}.container{height:100%}.input{height:100%;display:flex;flex-direction:column}.checkbox{flex-direction:column}.mat-form-field-wrapper{padding-bottom:0!important}.input .mat-mdc-standard-chip.mat-chip-with-trailing-icon{padding-right:12px}.time-picker{display:flex;flex-direction:row;height:100%;border:solid 2px lightgrey;padding:1em;border-radius:4px}.time-picker:hover{border-color:#000}::ng-deep .mat-h4 .mat-body-1 .mat-typography h4{margin:0}.label{margin:28px 0 8px}.smartIndicator{display:flex;flex-direction:column;gap:.25rem;width:-moz-fit-content;width:fit-content}.indicatorItems{display:flex;flex-direction:row;gap:.25rem}.indicatorItem{width:3rem;height:.25rem;background-color:#d3d3d3;border-radius:.5rem}.radio-error{width:-moz-fit-content;width:fit-content;display:flex;flex-direction:row;gap:.5rem}.mat-calendar-previous-button,.mat-calendar-next-button{padding:0;min-width:0;width:40px!important;height:40px!important;flex-shrink:0;line-height:40px;border-radius:50%}.mat-calendar-arrow{height:36px!important;display:flex!important;flex-direction:column!important;justify-content:center}.radio-item-container,.checkbox-item-container{display:flex;flex-direction:column}.widgetContent::ng-deep .ql-container{height:200px;width:460px}.dateTimePickerContainer{display:flex;flex-direction:row;gap:.25rem}.dateTimePickerContainer mat-form-field{flex:1}.date,.time{width:100%}.date .mat-form-field-infix,.time .mat-form-field-infix{width:inherit!important}::ng-deep .mat-icon.mat-drag-indicator{--drag-indicator: #3b3b3b;color:var(--drag-indicator)}.matrixTable{width:100%;border-spacing:0 1rem}.matrixTable th{padding:.25rem}.matrixTable .optionLabel,.matrixTable td{text-align:center}.example-month-picker .mat-calendar-period-button{pointer-events:none}.example-month-picker .mat-calendar-arrow{display:none}.textFieldContainer{display:flex;flex-direction:row}.textFieldContainer{align-content:center;border:1px solid #cbd5e1;border-radius:3px;background-color:#fff}.textFieldContainer input{border:unset}.textFieldContainer:focus-within:not(:has(input:disabled)){outline:0 none;outline-offset:0;box-shadow:0 0 0 .2rem #a6d5fa;border-color:#2196f3}.textFieldContainer:has(input:disabled) .clearButton{cursor:not-allowed;opacity:.6}.textFieldButtons{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.clearButton .mat-mdc-raised-button,.clearButton button{background-color:unset!important;border:unset;color:#6b7280!important;box-shadow:unset;font-size:1rem!important}.clearButton .mat-icon.mat-primary{color:#6b7280!important}.clearButton .mat-mdc-raised-button:hover,.clearButton button:hover{color:#6b7280cc!important;background-color:unset;border:unset;box-shadow:unset;font-size:1rem!important}.mat-mdc-form-field-infix{display:flex;flex-direction:row}textarea:not(:placeholder-shown)~label{top:-.75em!important;font-size:12px!important}.disabledEditor *{-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only}.sb4-textarea{--sb4-textarea-line-height: 20px;line-height:var(--sb4-textarea-line-height);overflow-y:auto!important}.widgetContainer .imageIcon{max-width:unset!important;height:unset!important}.material .sb4-textarea{resize:vertical!important}.material .smart-form-widget-label{font-weight:700}.material .mat-mdc-form-field-subscript-wrapper{display:none}.label-right{display:flex;gap:.5rem;flex-direction:row-reverse}.label-left{display:flex;gap:.5rem;flex-direction:row}.label-top{display:flex;gap:.5rem;flex-direction:column}.label-bottom{display:flex;gap:.5rem;flex-direction:column-reverse}.smartDiv{width:100%}.clickable{cursor:pointer}\n/*!\n * Quill Editor v2.0.3\n * https://quilljs.com\n * Copyright (c) 2017-2024, Slab\n * Copyright (c) 2014, Jason Chen\n * Copyright (c) 2013, salesforce.com\n */\n"] }]
10811
11597
  }], ctorParameters: () => [], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], widgetInstance: [{
10812
11598
  type: Input
10813
11599
  }], onBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "onBlur", required: false }] }], onValueChange: [{
@@ -10989,6 +11775,7 @@ class SmartformComponent {
10989
11775
  widget.type !== SmartFormWidgetType.RECORDING_UPLOADER &&
10990
11776
  widget.type !== SmartFormWidgetType.IMAGE &&
10991
11777
  widget.type !== SmartFormWidgetType.DIV &&
11778
+ widget.type !== SmartFormWidgetType.HTML &&
10992
11779
  widget.type !== SmartFormWidgetType.SVG &&
10993
11780
  widget.type !== SmartFormWidgetType.DIVIDER &&
10994
11781
  widget.type !== SmartFormWidgetType.BUTTON &&
@@ -11369,8 +12156,19 @@ class SmartObjectUtility {
11369
12156
 
11370
12157
  class SmartGridToolbarActionsUtil {
11371
12158
  static { this.defaultActionToolbarId = 'toolbarDefaultActionColumn'; }
11372
- static showMenu(row, orderedColumns) {
11373
- if (!row.columnActions && row.actions && row.actions.length > 0) {
12159
+ /** The toolbar address of a trigger-only action (`UiActions.NO_TOOLBAR` on the backend). */
12160
+ static { this.noToolbar = '_none'; }
12161
+ /**
12162
+ * The row actions a row menu may offer. A trigger-only action never, and with column templates
12163
+ * in the table no action addressed to a toolbar either: that one belongs to a toolbar slot of
12164
+ * a template. Without templates an addressed action stays in the menu, as it always did.
12165
+ */
12166
+ static menuCandidates(row, columnTemplates = false) {
12167
+ return (row.actions ?? []).filter((action) => action.toolbar !== this.noToolbar && !(columnTemplates && action.toolbar));
12168
+ }
12169
+ static showMenu(row, orderedColumns, columnTemplates = false) {
12170
+ const actions = this.menuCandidates(row, columnTemplates);
12171
+ if (!row.columnActions && actions.length > 0) {
11374
12172
  return true;
11375
12173
  }
11376
12174
  var _columnsToFilter = [
@@ -11383,9 +12181,7 @@ class SmartGridToolbarActionsUtil {
11383
12181
  acc[key] = row.columnActions[key];
11384
12182
  return acc;
11385
12183
  }, {});
11386
- return (row.actions &&
11387
- row.actions.length > 0 &&
11388
- Object.values(filteredActionColumns).flat().length !== row.actions.length);
12184
+ return (actions.length > 0 && Object.values(filteredActionColumns).flat().length !== actions.length);
11389
12185
  }
11390
12186
  static showToolbar(row, columnName) {
11391
12187
  return !!row.actions && row.actions.length > 0 && !!row.columnActions?.[columnName];
@@ -11407,7 +12203,7 @@ class SmartGridToolbarActionsUtil {
11407
12203
  return cellToActionMap;
11408
12204
  }
11409
12205
  // ##### MENU ACTIONS
11410
- static calculateMenuActions(row, orderedColumns) {
12206
+ static calculateMenuActions(row, orderedColumns, columnTemplates = false) {
11411
12207
  var _columnsToFilter = [
11412
12208
  ...orderedColumns.map((col) => col.startsWith('data.') ? col.substring('data.'.length) : col),
11413
12209
  this.defaultActionToolbarId,
@@ -11416,10 +12212,10 @@ class SmartGridToolbarActionsUtil {
11416
12212
  .filter((key) => _columnsToFilter.includes(key))
11417
12213
  .map((key) => row.columnActions[key])
11418
12214
  .flat();
11419
- return row.actions?.filter((action) => !columnCodes.includes(action.code)) ?? [];
12215
+ return this.menuCandidates(row, columnTemplates).filter((action) => !columnCodes.includes(action.code));
11420
12216
  }
11421
- static calculateMenuActionModels(row, orderedColumns) {
11422
- return this.calculateMenuActions(row, orderedColumns).map((uiAction) => this.toActionModel(uiAction));
12217
+ static calculateMenuActionModels(row, orderedColumns, columnTemplates = false) {
12218
+ return this.calculateMenuActions(row, orderedColumns, columnTemplates).map((uiAction) => this.toActionModel(uiAction));
11423
12219
  }
11424
12220
  static getActionModelsFromMap(cellToActionMap, row, header) {
11425
12221
  let key = row.id + header;
@@ -11436,6 +12232,26 @@ class SmartGridToolbarActionsUtil {
11436
12232
  }
11437
12233
  }
11438
12234
 
12235
+ /**
12236
+ * Grid api
12237
+ * The grid api is resposible for the grid components that shows a list of item.
12238
+ *
12239
+ * The version of the OpenAPI document: 1.0.0
12240
+ * Contact: info@it4all.hu
12241
+ *
12242
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
12243
+ * https://openapi-generator.tech
12244
+ * Do not edit the class manually.
12245
+ */
12246
+ /**
12247
+ * The rendering of a table cell value. A missing value behaves as html, the rendering tables always had: sanitized innerHTML, no hydration. Text escapes the value; recommended for data that has to be escaped. Sorting runs on the server on the raw value, so an html column needs a sortOrderPropertyName.
12248
+ */
12249
+ var GridColumnContentType;
12250
+ (function (GridColumnContentType) {
12251
+ GridColumnContentType["TEXT"] = "text";
12252
+ GridColumnContentType["HTML"] = "html";
12253
+ })(GridColumnContentType || (GridColumnContentType = {}));
12254
+
11439
12255
  /** Id of the detail row's collapse animation, so a second leave call can find the running one. */
11440
12256
  const DETAIL_COLLAPSE = 'smart-table-detail-collapse';
11441
12257
  class Table {
@@ -11890,7 +12706,7 @@ class Table {
11890
12706
  }
11891
12707
  showMenuButton(element, button) {
11892
12708
  let headers = this.smartTable.tableHeaders.map((header) => this.originalProperty(header));
11893
- let showMenu = SmartGridToolbarActionsUtil.showMenu(element, headers);
12709
+ let showMenu = SmartGridToolbarActionsUtil.showMenu(element, headers, this.hasColumnTemplates);
11894
12710
  if (!showMenu) {
11895
12711
  return false;
11896
12712
  }
@@ -11911,6 +12727,18 @@ class Table {
11911
12727
  getValue(element, header) {
11912
12728
  return SmartObjectUtility.getValueByPath(element, header);
11913
12729
  }
12730
+ /** The column template of the i-th column; it takes the place of every value rendering. */
12731
+ columnTemplate(i) {
12732
+ return this.smartTable.customSmartTableHeaders?.[i]?.htmlProperties;
12733
+ }
12734
+ /** The i-th column renders its value escaped; any other content type is sanitized html. */
12735
+ isTextContent(i) {
12736
+ return this.smartTable.customSmartTableHeaders?.[i]?.contentType === GridColumnContentType.TEXT;
12737
+ }
12738
+ /** With column templates in the table, an action addressed to a toolbar stays out of the row menu. */
12739
+ get hasColumnTemplates() {
12740
+ return !!this.smartTable.customSmartTableHeaders?.some((header) => header.htmlProperties);
12741
+ }
11914
12742
  showButton(button, element) {
11915
12743
  if (button.showButtonIf) {
11916
12744
  return button.showButtonIf(element);
@@ -11996,7 +12824,7 @@ class Table {
11996
12824
  return SmartGridToolbarActionsUtil.showToolbar(row, this.originalProperty(columnName));
11997
12825
  }
11998
12826
  getRowMenuActionModel(element) {
11999
- const leftoverActions = SmartGridToolbarActionsUtil.calculateMenuActionModels(element, this.smartTable.tableHeaders);
12827
+ const leftoverActions = SmartGridToolbarActionsUtil.calculateMenuActionModels(element, this.smartTable.tableHeaders, this.hasColumnTemplates);
12000
12828
  const menuUiAction = {
12001
12829
  code: 'rowMenu',
12002
12830
  descriptor: {
@@ -12020,7 +12848,7 @@ class Table {
12020
12848
  return arr;
12021
12849
  }
12022
12850
  shouldShowMenuButton(row) {
12023
- return SmartGridToolbarActionsUtil.showMenu(row, this.smartTable.tableHeaders);
12851
+ return SmartGridToolbarActionsUtil.showMenu(row, this.smartTable.tableHeaders, this.hasColumnTemplates);
12024
12852
  }
12025
12853
  initializeExpandedRows(rows) {
12026
12854
  if (this.treeInitialized) {
@@ -12217,22 +13045,82 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
12217
13045
  args: [{ name: 'smartTime' }]
12218
13046
  }] });
12219
13047
 
13048
+ /**
13049
+ * The entries a row offers to what renders inside it — a card's row layout, a cell's column
13050
+ * template — through their `SmartActionHost`. Each action carries the row as its model and is
13051
+ * scoped to the grid and the row, because nothing there binds a scope on the toolbars.
13052
+ */
13053
+ function rowActionModels(row, gridIdentifier, serviceToUse) {
13054
+ return (row.actions ?? []).map((uiAction) => ({
13055
+ serviceToUse,
13056
+ uiAction: { ...uiAction, params: { ...uiAction.params, model: row } },
13057
+ widgetId: gridIdentifier,
13058
+ nodeId: row.id,
13059
+ }));
13060
+ }
13061
+
13062
+ /**
13063
+ * A table cell rendered from a column template: server-sent HTML whose client placeholders are
13064
+ * resolved against the row's data, the template's `root` applied. The toolbar slots and action
13065
+ * triggers in it offer the row's actions, the way a card's row layout does.
13066
+ *
13067
+ * The cell provides the action host itself rather than the row: the table creates its cells
13068
+ * from templates declared in the table, so they inject from there, never from the row element.
13069
+ * See HTML-WIDGET.md.
13070
+ */
13071
+ class SmartHtmlCellComponent {
13072
+ constructor() {
13073
+ this.actionHost = inject(SmartActionHost);
13074
+ this.smartComponent = injectSmartComponent();
13075
+ this.renderer = injectSmartHtmlRenderer(inject(ElementRef).nativeElement);
13076
+ }
13077
+ ngOnChanges() {
13078
+ this.actionHost.actionModels.set(rowActionModels(this.row, this.gridIdentifier));
13079
+ const { html, root, css } = this.template;
13080
+ const scope = rootScope(this.row.data, root);
13081
+ if (scope === undefined && root && this.warnedRoot !== root) {
13082
+ this.warnedRoot = root;
13083
+ console.warn(`smart-html: root '${root}' does not name an object, every placeholder is left empty` +
13084
+ ` — in ${html?.substring(0, 80)}`);
13085
+ }
13086
+ this.renderer.useCss(css);
13087
+ this.renderer.render(html ?? '', {
13088
+ data: scope,
13089
+ valueSets: this.smartComponent?.model?.valueSets,
13090
+ });
13091
+ }
13092
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
13093
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: SmartHtmlCellComponent, isStandalone: true, selector: "smart-html-cell", inputs: { row: "row", template: "template", gridIdentifier: "gridIdentifier" }, providers: [SmartActionHost], usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: ["smart-html-cell{display:block}smart-html-cell [data-sb4-action]{cursor:pointer}smart-html-cell [data-sb4-action].sb4-action-inert{cursor:inherit}smart-html-cell [data-sb4-action].sb4-action-disabled{cursor:default;opacity:.5}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
13094
+ }
13095
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlCellComponent, decorators: [{
13096
+ type: Component,
13097
+ args: [{ selector: 'smart-html-cell', template: '', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [SmartActionHost], styles: ["smart-html-cell{display:block}smart-html-cell [data-sb4-action]{cursor:pointer}smart-html-cell [data-sb4-action].sb4-action-inert{cursor:inherit}smart-html-cell [data-sb4-action].sb4-action-disabled{cursor:default;opacity:.5}\n"] }]
13098
+ }], propDecorators: { row: [{
13099
+ type: Input,
13100
+ args: [{ required: true }]
13101
+ }], template: [{
13102
+ type: Input,
13103
+ args: [{ required: true }]
13104
+ }], gridIdentifier: [{
13105
+ type: Input
13106
+ }] } });
13107
+
12220
13108
  class MaterialTableComponent extends Table {
12221
13109
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MaterialTableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
12222
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MaterialTableComponent, isStandalone: true, selector: "lib-material-table", usesInheritance: true, ngImport: i0, template: "<table #myTable mat-table [dataSource]=\"isTreeGrid ? visibleRows : smartTable.tableRows\" class=\"full-width\"\n multiTemplateDataRows>\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n\n <ng-container matColumnDef=\"{{ header }}\">\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n\n <!-- ==================== TREE ACTIONS ==================== -->\n @if ( isTreeGrid) {\n <div class=\"tree-grid-actions\">\n\n <ui-action-button (actionClick)=\"expandOneLevel()\" [descriptor]=\"expandTreeGridLevel\">\n </ui-action-button>\n\n\n <ui-action-button (actionClick)=\"collapseOneLevel()\" [descriptor]=\"closeTreeGridLevel\">\n </ui-action-button>\n </div>\n }\n <!-- ==================== TREE ACTIONS ==================== -->\n\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div>\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\" mat-button\n class=\"sortableHeaderButton\">\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortIcon(header)!\"></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortNumIcon(header)\"></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n <div class=\"mat-cell-content\">\n\n\n <!-- ==================== TREE TOGGLE ==================== -->\n @if (isTreeGrid && i === 0) {\n <div class=\"tree-grid-first-column\" [style.padding-left.px]=\"(element.level ?? 0) * 24\">\n @if (hasChildren(element)) {\n <button mat-icon-button type=\"button\" (click)=\"toggleRowExpansion(element, $event)\">\n <smart-icon [icon]=\"\n isRowExpanded(element)\n ? 'keyboard_arrow_down'\n : 'keyboard_arrow_right'\n \"></smart-icon>\n </button>\n } @else {\n <span class=\"tree-grid-spacer\"></span>\n }\n\n </div>\n }\n <!-- ==================== TREE TOGGLE ==================== -->\n\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \" [disabled]=\"isDisabled(element)\" [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \" [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \">\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div>\n <smart-icon [smartTooltip]=\"getToolTip(element, i)\" [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\">\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div class=\"smart-table-buttons-col\">\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-icon-button color=\"{{ button.color }}\">\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-button color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-raised-button\n color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getMenuActions(element)\" [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\" [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\">\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div>\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button mat-icon-button aria-label=\"expand row\" (click)=\"onToggle(element, $event)\">\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div>\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img [src]=\"getValue(element, header)\" alt=\"\" class=\"smarttableImg\" />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n <div [innerHtml]=\"getValue(element, header)\"></div>\n }\n </div>\n }\n\n </div>\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (smartTable.expandable) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div class=\"smart-table-detail\" animate.enter=\"smart-table-detail-enter\">\n <div class=\"smart-table-detail-content\">\n <ng-template #expandedArea></ng-template>\n </div>\n </div>\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr mat-row class=\"smart-table-row\" [class.smart-table-row-expanded]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\" [ngStyle]=\"getRowStyles(element)\" (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\" [attr.data-testid]=\"element?.id ?? null\"></tr>\n\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup #defaultActionMenu [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"></lib-default-actions-popup>\n }\n </ng-container>\n <!-- Only the expanded row has a detail row; no host style can give a collapsed one a height. -->\n @if (smartTable.expandable) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpandedRow\" class=\"smart-table-detail-row\"\n (animate.leave)=\"onDetailRowLeave($event)\"></tr>\n }\n</table>", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.smart-table-row:not(.smart-table-row-expanded):hover{background:#f5f5f5}tr.smart-table-row:not(.smart-table-row-expanded):active{background:#efefef}tr.smart-table-row-expanded td{border-bottom-width:0}tr.smart-table-detail-row{height:0}.smart-table-detail{display:grid;grid-template-rows:1fr}.smart-table-detail-enter{animation:smart-table-detail-expand 225ms cubic-bezier(.4,0,.2,1)}.smart-table-detail-content{min-height:0;overflow:hidden}@keyframes smart-table-detail-expand{0%{grid-template-rows:0fr}to{grid-template-rows:1fr}}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}.tree-grid-actions,.mat-cell-content{display:flex;flex-direction:row;align-items:center}.mat-column-my_menu,.tree-grid-column{width:0}.tree-grid-cell{display:flex;align-items:center;min-height:48px}.tree-grid-expand-button{flex:0 0 auto}.tree-grid-spacer{display:inline-block;width:40px;flex:0 0 40px}.tree-grid-label{min-width:0}\n"], dependencies: [{ kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { 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: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: DefaultActionsPopupComponent, selector: "lib-default-actions-popup", inputs: ["buttons", "row", "colIdx"] }, { kind: "pipe", type: SmartDateTimePipe, name: "smartDateTime" }, { kind: "pipe", type: SmartDatePipe, name: "smartDate" }, { kind: "pipe", type: SmartTimePipe, name: "smartTime" }] }); }
13110
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MaterialTableComponent, isStandalone: true, selector: "lib-material-table", usesInheritance: true, ngImport: i0, template: "<table #myTable mat-table [dataSource]=\"isTreeGrid ? visibleRows : smartTable.tableRows\" class=\"full-width\"\n multiTemplateDataRows>\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n\n <ng-container matColumnDef=\"{{ header }}\">\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n\n <!-- ==================== TREE ACTIONS ==================== -->\n @if ( isTreeGrid) {\n <div class=\"tree-grid-actions\">\n\n <ui-action-button (actionClick)=\"expandOneLevel()\" [descriptor]=\"expandTreeGridLevel\">\n </ui-action-button>\n\n\n <ui-action-button (actionClick)=\"collapseOneLevel()\" [descriptor]=\"closeTreeGridLevel\">\n </ui-action-button>\n </div>\n }\n <!-- ==================== TREE ACTIONS ==================== -->\n\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div>\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\" mat-button\n class=\"sortableHeaderButton\">\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortIcon(header)!\"></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortNumIcon(header)\"></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n <div class=\"mat-cell-content\">\n\n\n <!-- ==================== TREE TOGGLE ==================== -->\n @if (isTreeGrid && i === 0) {\n <div class=\"tree-grid-first-column\" [style.padding-left.px]=\"(element.level ?? 0) * 24\">\n @if (hasChildren(element)) {\n <button mat-icon-button type=\"button\" (click)=\"toggleRowExpansion(element, $event)\">\n <smart-icon [icon]=\"\n isRowExpanded(element)\n ? 'keyboard_arrow_down'\n : 'keyboard_arrow_right'\n \"></smart-icon>\n </button>\n } @else {\n <span class=\"tree-grid-spacer\"></span>\n }\n\n </div>\n }\n <!-- ==================== TREE TOGGLE ==================== -->\n\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \" [disabled]=\"isDisabled(element)\" [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \" [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \">\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties &&\n !columnTemplate(i)\n ) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div>\n <smart-icon [smartTooltip]=\"getToolTip(element, i)\" [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\">\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div class=\"smart-table-buttons-col\">\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-icon-button color=\"{{ button.color }}\">\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-button color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-raised-button\n color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getMenuActions(element)\" [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\" [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\">\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div>\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button mat-icon-button aria-label=\"expand row\" (click)=\"onToggle(element, $event)\">\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n (!smartTable.customSmartTableHeaders[i].properties || columnTemplate(i)) &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div>\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img [src]=\"getValue(element, header)\" alt=\"\" class=\"smarttableImg\" />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (columnTemplate(i); as template) {\n <smart-html-cell [row]=\"element\" [template]=\"template\"\n [gridIdentifier]=\"smartTable.getGridId()\"></smart-html-cell>\n } @else if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n @if (isTextContent(i)) {\n <div>{{ getValue(element, header) }}</div>\n } @else {\n <div [innerHtml]=\"getValue(element, header)\"></div>\n }\n }\n </div>\n }\n\n </div>\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (smartTable.expandable) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div class=\"smart-table-detail\" animate.enter=\"smart-table-detail-enter\">\n <div class=\"smart-table-detail-content\">\n <ng-template #expandedArea></ng-template>\n </div>\n </div>\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr mat-row class=\"smart-table-row\" [class.smart-table-row-expanded]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\" [ngStyle]=\"getRowStyles(element)\" (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\" [attr.data-testid]=\"element?.id ?? null\"></tr>\n\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup #defaultActionMenu [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"></lib-default-actions-popup>\n }\n </ng-container>\n <!-- Only the expanded row has a detail row; no host style can give a collapsed one a height. -->\n @if (smartTable.expandable) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpandedRow\" class=\"smart-table-detail-row\"\n (animate.leave)=\"onDetailRowLeave($event)\"></tr>\n }\n</table>", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.smart-table-row:not(.smart-table-row-expanded):hover{background:#f5f5f5}tr.smart-table-row:not(.smart-table-row-expanded):active{background:#efefef}tr.smart-table-row-expanded td{border-bottom-width:0}tr.smart-table-detail-row{height:0}.smart-table-detail{display:grid;grid-template-rows:1fr}.smart-table-detail-enter{animation:smart-table-detail-expand 225ms cubic-bezier(.4,0,.2,1)}.smart-table-detail-content{min-height:0;overflow:hidden}@keyframes smart-table-detail-expand{0%{grid-template-rows:0fr}to{grid-template-rows:1fr}}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}.tree-grid-actions,.mat-cell-content{display:flex;flex-direction:row;align-items:center}.mat-column-my_menu,.tree-grid-column{width:0}.tree-grid-cell{display:flex;align-items:center;min-height:48px}.tree-grid-expand-button{flex:0 0 auto}.tree-grid-spacer{display:inline-block;width:40px;flex:0 0 40px}.tree-grid-label{min-width:0}\n"], dependencies: [{ kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { 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: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: DefaultActionsPopupComponent, selector: "lib-default-actions-popup", inputs: ["buttons", "row", "colIdx"] }, { kind: "component", type: SmartHtmlCellComponent, selector: "smart-html-cell", inputs: ["row", "template", "gridIdentifier"] }, { kind: "pipe", type: SmartDateTimePipe, name: "smartDateTime" }, { kind: "pipe", type: SmartDatePipe, name: "smartDate" }, { kind: "pipe", type: SmartTimePipe, name: "smartTime" }] }); }
12223
13111
  }
12224
13112
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MaterialTableComponent, decorators: [{
12225
13113
  type: Component,
12226
- args: [{ selector: 'lib-material-table', imports: [MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, NgClass, NgStyle, UiActionToolbarComponent, UiActionButtonComponent, MatCheckbox, MatButton, SmartIconComponent, MatCellDef, MatCell, SmartTooltipDirective, MatIconButton, MatMenuTrigger, MatMenu, MatMenuItem, MatDivider, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, DefaultActionsPopupComponent, SmartDateTimePipe, SmartDatePipe, SmartTimePipe], template: "<table #myTable mat-table [dataSource]=\"isTreeGrid ? visibleRows : smartTable.tableRows\" class=\"full-width\"\n multiTemplateDataRows>\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n\n <ng-container matColumnDef=\"{{ header }}\">\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n\n <!-- ==================== TREE ACTIONS ==================== -->\n @if ( isTreeGrid) {\n <div class=\"tree-grid-actions\">\n\n <ui-action-button (actionClick)=\"expandOneLevel()\" [descriptor]=\"expandTreeGridLevel\">\n </ui-action-button>\n\n\n <ui-action-button (actionClick)=\"collapseOneLevel()\" [descriptor]=\"closeTreeGridLevel\">\n </ui-action-button>\n </div>\n }\n <!-- ==================== TREE ACTIONS ==================== -->\n\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div>\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\" mat-button\n class=\"sortableHeaderButton\">\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortIcon(header)!\"></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortNumIcon(header)\"></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n <div class=\"mat-cell-content\">\n\n\n <!-- ==================== TREE TOGGLE ==================== -->\n @if (isTreeGrid && i === 0) {\n <div class=\"tree-grid-first-column\" [style.padding-left.px]=\"(element.level ?? 0) * 24\">\n @if (hasChildren(element)) {\n <button mat-icon-button type=\"button\" (click)=\"toggleRowExpansion(element, $event)\">\n <smart-icon [icon]=\"\n isRowExpanded(element)\n ? 'keyboard_arrow_down'\n : 'keyboard_arrow_right'\n \"></smart-icon>\n </button>\n } @else {\n <span class=\"tree-grid-spacer\"></span>\n }\n\n </div>\n }\n <!-- ==================== TREE TOGGLE ==================== -->\n\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \" [disabled]=\"isDisabled(element)\" [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \" [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \">\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div>\n <smart-icon [smartTooltip]=\"getToolTip(element, i)\" [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\">\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div class=\"smart-table-buttons-col\">\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-icon-button color=\"{{ button.color }}\">\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-button color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-raised-button\n color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getMenuActions(element)\" [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\" [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\">\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div>\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button mat-icon-button aria-label=\"expand row\" (click)=\"onToggle(element, $event)\">\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div>\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img [src]=\"getValue(element, header)\" alt=\"\" class=\"smarttableImg\" />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n <div [innerHtml]=\"getValue(element, header)\"></div>\n }\n </div>\n }\n\n </div>\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (smartTable.expandable) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div class=\"smart-table-detail\" animate.enter=\"smart-table-detail-enter\">\n <div class=\"smart-table-detail-content\">\n <ng-template #expandedArea></ng-template>\n </div>\n </div>\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr mat-row class=\"smart-table-row\" [class.smart-table-row-expanded]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\" [ngStyle]=\"getRowStyles(element)\" (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\" [attr.data-testid]=\"element?.id ?? null\"></tr>\n\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup #defaultActionMenu [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"></lib-default-actions-popup>\n }\n </ng-container>\n <!-- Only the expanded row has a detail row; no host style can give a collapsed one a height. -->\n @if (smartTable.expandable) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpandedRow\" class=\"smart-table-detail-row\"\n (animate.leave)=\"onDetailRowLeave($event)\"></tr>\n }\n</table>", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.smart-table-row:not(.smart-table-row-expanded):hover{background:#f5f5f5}tr.smart-table-row:not(.smart-table-row-expanded):active{background:#efefef}tr.smart-table-row-expanded td{border-bottom-width:0}tr.smart-table-detail-row{height:0}.smart-table-detail{display:grid;grid-template-rows:1fr}.smart-table-detail-enter{animation:smart-table-detail-expand 225ms cubic-bezier(.4,0,.2,1)}.smart-table-detail-content{min-height:0;overflow:hidden}@keyframes smart-table-detail-expand{0%{grid-template-rows:0fr}to{grid-template-rows:1fr}}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}.tree-grid-actions,.mat-cell-content{display:flex;flex-direction:row;align-items:center}.mat-column-my_menu,.tree-grid-column{width:0}.tree-grid-cell{display:flex;align-items:center;min-height:48px}.tree-grid-expand-button{flex:0 0 auto}.tree-grid-spacer{display:inline-block;width:40px;flex:0 0 40px}.tree-grid-label{min-width:0}\n"] }]
13114
+ args: [{ selector: 'lib-material-table', imports: [MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, NgClass, NgStyle, UiActionToolbarComponent, UiActionButtonComponent, MatCheckbox, MatButton, SmartIconComponent, MatCellDef, MatCell, SmartTooltipDirective, MatIconButton, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, DefaultActionsPopupComponent, SmartDateTimePipe, SmartDatePipe, SmartTimePipe, SmartHtmlCellComponent], template: "<table #myTable mat-table [dataSource]=\"isTreeGrid ? visibleRows : smartTable.tableRows\" class=\"full-width\"\n multiTemplateDataRows>\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n\n <ng-container matColumnDef=\"{{ header }}\">\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n\n <!-- ==================== TREE ACTIONS ==================== -->\n @if ( isTreeGrid) {\n <div class=\"tree-grid-actions\">\n\n <ui-action-button (actionClick)=\"expandOneLevel()\" [descriptor]=\"expandTreeGridLevel\">\n </ui-action-button>\n\n\n <ui-action-button (actionClick)=\"collapseOneLevel()\" [descriptor]=\"closeTreeGridLevel\">\n </ui-action-button>\n </div>\n }\n <!-- ==================== TREE ACTIONS ==================== -->\n\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div>\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\" mat-button\n class=\"sortableHeaderButton\">\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortIcon(header)!\"></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortNumIcon(header)\"></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n <div class=\"mat-cell-content\">\n\n\n <!-- ==================== TREE TOGGLE ==================== -->\n @if (isTreeGrid && i === 0) {\n <div class=\"tree-grid-first-column\" [style.padding-left.px]=\"(element.level ?? 0) * 24\">\n @if (hasChildren(element)) {\n <button mat-icon-button type=\"button\" (click)=\"toggleRowExpansion(element, $event)\">\n <smart-icon [icon]=\"\n isRowExpanded(element)\n ? 'keyboard_arrow_down'\n : 'keyboard_arrow_right'\n \"></smart-icon>\n </button>\n } @else {\n <span class=\"tree-grid-spacer\"></span>\n }\n\n </div>\n }\n <!-- ==================== TREE TOGGLE ==================== -->\n\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \" [disabled]=\"isDisabled(element)\" [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \" [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \">\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties &&\n !columnTemplate(i)\n ) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div>\n <smart-icon [smartTooltip]=\"getToolTip(element, i)\" [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\">\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div class=\"smart-table-buttons-col\">\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-icon-button color=\"{{ button.color }}\">\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-button color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-raised-button\n color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getMenuActions(element)\" [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\" [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\">\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div>\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button mat-icon-button aria-label=\"expand row\" (click)=\"onToggle(element, $event)\">\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n (!smartTable.customSmartTableHeaders[i].properties || columnTemplate(i)) &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div>\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img [src]=\"getValue(element, header)\" alt=\"\" class=\"smarttableImg\" />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (columnTemplate(i); as template) {\n <smart-html-cell [row]=\"element\" [template]=\"template\"\n [gridIdentifier]=\"smartTable.getGridId()\"></smart-html-cell>\n } @else if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n @if (isTextContent(i)) {\n <div>{{ getValue(element, header) }}</div>\n } @else {\n <div [innerHtml]=\"getValue(element, header)\"></div>\n }\n }\n </div>\n }\n\n </div>\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (smartTable.expandable) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div class=\"smart-table-detail\" animate.enter=\"smart-table-detail-enter\">\n <div class=\"smart-table-detail-content\">\n <ng-template #expandedArea></ng-template>\n </div>\n </div>\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr mat-row class=\"smart-table-row\" [class.smart-table-row-expanded]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\" [ngStyle]=\"getRowStyles(element)\" (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\" [attr.data-testid]=\"element?.id ?? null\"></tr>\n\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup #defaultActionMenu [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"></lib-default-actions-popup>\n }\n </ng-container>\n <!-- Only the expanded row has a detail row; no host style can give a collapsed one a height. -->\n @if (smartTable.expandable) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpandedRow\" class=\"smart-table-detail-row\"\n (animate.leave)=\"onDetailRowLeave($event)\"></tr>\n }\n</table>", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.smart-table-row:not(.smart-table-row-expanded):hover{background:#f5f5f5}tr.smart-table-row:not(.smart-table-row-expanded):active{background:#efefef}tr.smart-table-row-expanded td{border-bottom-width:0}tr.smart-table-detail-row{height:0}.smart-table-detail{display:grid;grid-template-rows:1fr}.smart-table-detail-enter{animation:smart-table-detail-expand 225ms cubic-bezier(.4,0,.2,1)}.smart-table-detail-content{min-height:0;overflow:hidden}@keyframes smart-table-detail-expand{0%{grid-template-rows:0fr}to{grid-template-rows:1fr}}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}.tree-grid-actions,.mat-cell-content{display:flex;flex-direction:row;align-items:center}.mat-column-my_menu,.tree-grid-column{width:0}.tree-grid-cell{display:flex;align-items:center;min-height:48px}.tree-grid-expand-button{flex:0 0 auto}.tree-grid-spacer{display:inline-block;width:40px;flex:0 0 40px}.tree-grid-label{min-width:0}\n"] }]
12227
13115
  }] });
12228
13116
 
12229
13117
  class MobileTableComponent extends Table {
12230
13118
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MobileTableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
12231
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MobileTableComponent, isStandalone: true, selector: "lib-mobile-table", usesInheritance: true, ngImport: i0, template: "<div class=\"mobileTable\">\n @for (row of smartTable.tableRows; track row) {\n <div\n class=\"mobileTableRow\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowStyles(row)\"\n [attr.data-testid]=\"row?.id ?? null\"\n >\n @for (header of smartTable.customSmartTableHeaders; track header; let i = $index) {\n <div\n class=\"mobileTableCell\"\n (click)=\"handleOnRowClick(row)\"\n (dblclick)=\"handleOnRowDoubleClick($event, row)\"\n >\n <div class=\"mobileTableCellHeader\" [attr.data-testid]=\"header.propertyName\">\n {{ header.label }}\n </div>\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select'\n ) {\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n : null\n \"\n [disabled]=\"isDisabled(row)\"\n [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n >\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div\n >\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox\n [disabled]=\"true\"\n [checked]=\"getValue(row, header.propertyName)\"\n ></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div\n >\n <smart-icon\n [smartTooltip]=\"getToolTip(row, i)\"\n [icon]=\"getIcon(getValue(row, header.propertyName), i)!\"\n [color]=\"getColor(getValue(row, header.propertyName), i)\"\n >\n </smart-icon>\n </div>\n }\n </div>\n }\n @if (isImageResource(row, header.propertyName)) {\n <div>\n <smart-icon\n [icon]=\"getImageResourceIcon(row, header.propertyName)\"\n [color]=\"getImageResourceColor(row, header.propertyName)\"\n >\n </smart-icon>\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div\n class=\"smart-table-buttons-col\"\n >\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, row)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-icon-button\n color=\"{{ button.color }}\"\n >\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-raised-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getMenuActions(element)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n <!------ MENU ------>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon\n [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\"\n >\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div\n >\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(row, header.propertyName)) }}\n </div>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div\n >\n @if (header.propertyName === 'icon') {\n <smart-icon\n [icon]=\"getValue(row, header.propertyName)!\"\n >\n </smart-icon>\n }\n @if (header.propertyName === 'img') {\n <img\n [src]=\"getValue(row, header.propertyName)\"\n alt=\"\"\n class=\"smarttableImg\"\n />\n }\n @if (\n header.propertyName !== 'icon' &&\n header.propertyName !== 'img' &&\n header.propertyName !== 'option' &&\n header.propertyName !== 'button'\n ) {\n <div\n [innerHtml]=\"getValue(row, header.propertyName)\"\n ></div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".mobileTable{display:flex;flex-direction:column}.mobileTableRow{display:flex;flex-direction:column;border-bottom:1px solid #ccc;padding:.5rem;gap:.5rem}.mobileTableCell{display:flex;flex-direction:column;gap:.25rem}.mobileTableCellHeader{font-weight:700;color:var(--primary-color)}.selected{background-color:var(--primary-light-color)}.mat-mdc-menu-item[disabled]{cursor:default!important}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "pipe", type: SmartDateTimePipe, name: "smartDateTime" }, { kind: "pipe", type: SmartDatePipe, name: "smartDate" }, { kind: "pipe", type: SmartTimePipe, name: "smartTime" }] }); }
13119
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MobileTableComponent, isStandalone: true, selector: "lib-mobile-table", usesInheritance: true, ngImport: i0, template: "<div class=\"mobileTable\">\n @for (row of smartTable.tableRows; track row) {\n <div\n class=\"mobileTableRow\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowStyles(row)\"\n [attr.data-testid]=\"row?.id ?? null\"\n >\n @for (header of smartTable.customSmartTableHeaders; track header; let i = $index) {\n <div\n class=\"mobileTableCell\"\n (click)=\"handleOnRowClick(row)\"\n (dblclick)=\"handleOnRowDoubleClick($event, row)\"\n >\n <div class=\"mobileTableCellHeader\" [attr.data-testid]=\"header.propertyName\">\n {{ header.label }}\n </div>\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select'\n ) {\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n : null\n \"\n [disabled]=\"isDisabled(row)\"\n [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n >\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties &&\n !columnTemplate(i)\n ) {\n <div\n >\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox\n [disabled]=\"true\"\n [checked]=\"getValue(row, header.propertyName)\"\n ></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div\n >\n <smart-icon\n [smartTooltip]=\"getToolTip(row, i)\"\n [icon]=\"getIcon(getValue(row, header.propertyName), i)!\"\n [color]=\"getColor(getValue(row, header.propertyName), i)\"\n >\n </smart-icon>\n </div>\n }\n </div>\n }\n @if (isImageResource(row, header.propertyName)) {\n <div>\n <smart-icon\n [icon]=\"getImageResourceIcon(row, header.propertyName)\"\n [color]=\"getImageResourceColor(row, header.propertyName)\"\n >\n </smart-icon>\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div\n class=\"smart-table-buttons-col\"\n >\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, row)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-icon-button\n color=\"{{ button.color }}\"\n >\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-raised-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getMenuActions(element)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n <!------ MENU ------>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon\n [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\"\n >\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div\n >\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(row, header.propertyName)) }}\n </div>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n (!smartTable.customSmartTableHeaders[i].properties || columnTemplate(i)) &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div\n >\n @if (header.propertyName === 'icon') {\n <smart-icon\n [icon]=\"getValue(row, header.propertyName)!\"\n >\n </smart-icon>\n }\n @if (header.propertyName === 'img') {\n <img\n [src]=\"getValue(row, header.propertyName)\"\n alt=\"\"\n class=\"smarttableImg\"\n />\n }\n @if (\n header.propertyName !== 'icon' &&\n header.propertyName !== 'img' &&\n header.propertyName !== 'option' &&\n header.propertyName !== 'button'\n ) {\n @if (columnTemplate(i); as template) {\n <smart-html-cell\n [row]=\"row\"\n [template]=\"template\"\n [gridIdentifier]=\"smartTable.getGridId()\"\n ></smart-html-cell>\n } @else if (isTextContent(i)) {\n <div>{{ getValue(row, header.propertyName) }}</div>\n } @else {\n <div\n [innerHtml]=\"getValue(row, header.propertyName)\"\n ></div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".mobileTable{display:flex;flex-direction:column}.mobileTableRow{display:flex;flex-direction:column;border-bottom:1px solid #ccc;padding:.5rem;gap:.5rem}.mobileTableCell{display:flex;flex-direction:column;gap:.25rem}.mobileTableCellHeader{font-weight:700;color:var(--primary-color)}.selected{background-color:var(--primary-light-color)}.mat-mdc-menu-item[disabled]{cursor:default!important}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: SmartHtmlCellComponent, selector: "smart-html-cell", inputs: ["row", "template", "gridIdentifier"] }, { kind: "pipe", type: SmartDateTimePipe, name: "smartDateTime" }, { kind: "pipe", type: SmartDatePipe, name: "smartDate" }, { kind: "pipe", type: SmartTimePipe, name: "smartTime" }] }); }
12232
13120
  }
12233
13121
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MobileTableComponent, decorators: [{
12234
13122
  type: Component,
12235
- args: [{ selector: 'lib-mobile-table', imports: [NgClass, NgStyle, MatCheckbox, SmartIconComponent, SmartTooltipDirective, MatIconButton, MatButton, UiActionToolbarComponent, SmartDateTimePipe, SmartDatePipe, SmartTimePipe], template: "<div class=\"mobileTable\">\n @for (row of smartTable.tableRows; track row) {\n <div\n class=\"mobileTableRow\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowStyles(row)\"\n [attr.data-testid]=\"row?.id ?? null\"\n >\n @for (header of smartTable.customSmartTableHeaders; track header; let i = $index) {\n <div\n class=\"mobileTableCell\"\n (click)=\"handleOnRowClick(row)\"\n (dblclick)=\"handleOnRowDoubleClick($event, row)\"\n >\n <div class=\"mobileTableCellHeader\" [attr.data-testid]=\"header.propertyName\">\n {{ header.label }}\n </div>\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select'\n ) {\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n : null\n \"\n [disabled]=\"isDisabled(row)\"\n [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n >\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div\n >\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox\n [disabled]=\"true\"\n [checked]=\"getValue(row, header.propertyName)\"\n ></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div\n >\n <smart-icon\n [smartTooltip]=\"getToolTip(row, i)\"\n [icon]=\"getIcon(getValue(row, header.propertyName), i)!\"\n [color]=\"getColor(getValue(row, header.propertyName), i)\"\n >\n </smart-icon>\n </div>\n }\n </div>\n }\n @if (isImageResource(row, header.propertyName)) {\n <div>\n <smart-icon\n [icon]=\"getImageResourceIcon(row, header.propertyName)\"\n [color]=\"getImageResourceColor(row, header.propertyName)\"\n >\n </smart-icon>\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div\n class=\"smart-table-buttons-col\"\n >\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, row)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-icon-button\n color=\"{{ button.color }}\"\n >\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-raised-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getMenuActions(element)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n <!------ MENU ------>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon\n [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\"\n >\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div\n >\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(row, header.propertyName)) }}\n </div>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div\n >\n @if (header.propertyName === 'icon') {\n <smart-icon\n [icon]=\"getValue(row, header.propertyName)!\"\n >\n </smart-icon>\n }\n @if (header.propertyName === 'img') {\n <img\n [src]=\"getValue(row, header.propertyName)\"\n alt=\"\"\n class=\"smarttableImg\"\n />\n }\n @if (\n header.propertyName !== 'icon' &&\n header.propertyName !== 'img' &&\n header.propertyName !== 'option' &&\n header.propertyName !== 'button'\n ) {\n <div\n [innerHtml]=\"getValue(row, header.propertyName)\"\n ></div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".mobileTable{display:flex;flex-direction:column}.mobileTableRow{display:flex;flex-direction:column;border-bottom:1px solid #ccc;padding:.5rem;gap:.5rem}.mobileTableCell{display:flex;flex-direction:column;gap:.25rem}.mobileTableCellHeader{font-weight:700;color:var(--primary-color)}.selected{background-color:var(--primary-light-color)}.mat-mdc-menu-item[disabled]{cursor:default!important}\n"] }]
13123
+ args: [{ selector: 'lib-mobile-table', imports: [NgClass, NgStyle, MatCheckbox, SmartIconComponent, SmartTooltipDirective, MatIconButton, MatButton, UiActionToolbarComponent, SmartDateTimePipe, SmartDatePipe, SmartTimePipe, SmartHtmlCellComponent], template: "<div class=\"mobileTable\">\n @for (row of smartTable.tableRows; track row) {\n <div\n class=\"mobileTableRow\"\n [ngClass]=\"getRowClasses(row)\"\n [ngStyle]=\"getRowStyles(row)\"\n [attr.data-testid]=\"row?.id ?? null\"\n >\n @for (header of smartTable.customSmartTableHeaders; track header; let i = $index) {\n <div\n class=\"mobileTableCell\"\n (click)=\"handleOnRowClick(row)\"\n (dblclick)=\"handleOnRowDoubleClick($event, row)\"\n >\n <div class=\"mobileTableCellHeader\" [attr.data-testid]=\"header.propertyName\">\n {{ header.label }}\n </div>\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select'\n ) {\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n : null\n \"\n [disabled]=\"isDisabled(row)\"\n [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(row, smartTable.selectionProperty)\n : row\n )\n \"\n >\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties &&\n !columnTemplate(i)\n ) {\n <div\n >\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(row, header.propertyName)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox\n [disabled]=\"true\"\n [checked]=\"getValue(row, header.propertyName)\"\n ></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div\n >\n <smart-icon\n [smartTooltip]=\"getToolTip(row, i)\"\n [icon]=\"getIcon(getValue(row, header.propertyName), i)!\"\n [color]=\"getColor(getValue(row, header.propertyName), i)\"\n >\n </smart-icon>\n </div>\n }\n </div>\n }\n @if (isImageResource(row, header.propertyName)) {\n <div>\n <smart-icon\n [icon]=\"getImageResourceIcon(row, header.propertyName)\"\n [color]=\"getImageResourceColor(row, header.propertyName)\"\n >\n </smart-icon>\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div\n class=\"smart-table-buttons-col\"\n >\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, row)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-icon-button\n color=\"{{ button.color }}\"\n >\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button\n (click)=\"customButtonClicked($event, button, row)\"\n mat-raised-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getMenuActions(element)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n <!------ MENU ------>\n </div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon\n [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\"\n >\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div\n >\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(row, header.propertyName)) }}\n </div>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n (!smartTable.customSmartTableHeaders[i].properties || columnTemplate(i)) &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div\n >\n @if (header.propertyName === 'icon') {\n <smart-icon\n [icon]=\"getValue(row, header.propertyName)!\"\n >\n </smart-icon>\n }\n @if (header.propertyName === 'img') {\n <img\n [src]=\"getValue(row, header.propertyName)\"\n alt=\"\"\n class=\"smarttableImg\"\n />\n }\n @if (\n header.propertyName !== 'icon' &&\n header.propertyName !== 'img' &&\n header.propertyName !== 'option' &&\n header.propertyName !== 'button'\n ) {\n @if (columnTemplate(i); as template) {\n <smart-html-cell\n [row]=\"row\"\n [template]=\"template\"\n [gridIdentifier]=\"smartTable.getGridId()\"\n ></smart-html-cell>\n } @else if (isTextContent(i)) {\n <div>{{ getValue(row, header.propertyName) }}</div>\n } @else {\n <div\n [innerHtml]=\"getValue(row, header.propertyName)\"\n ></div>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".mobileTable{display:flex;flex-direction:column}.mobileTableRow{display:flex;flex-direction:column;border-bottom:1px solid #ccc;padding:.5rem;gap:.5rem}.mobileTableCell{display:flex;flex-direction:column;gap:.25rem}.mobileTableCellHeader{font-weight:700;color:var(--primary-color)}.selected{background-color:var(--primary-light-color)}.mat-mdc-menu-item[disabled]{cursor:default!important}\n"] }]
12236
13124
  }] });
12237
13125
 
12238
13126
  class SmarttableComponent {
@@ -13000,6 +13888,8 @@ class SmartformLayoutDefinitionService {
13000
13888
  return this.createSvg(config.layoutDefinition);
13001
13889
  case SmartFormWidgetType.DIV:
13002
13890
  return this.createDiv(config.layoutDefinition);
13891
+ case SmartFormWidgetType.HTML:
13892
+ return this.createHtml(config.layoutDefinition);
13003
13893
  case SmartFormWidgetType.BUTTON:
13004
13894
  return this.createButton(config);
13005
13895
  case SmartFormWidgetType.DIVIDER:
@@ -13548,6 +14438,17 @@ class SmartformLayoutDefinitionService {
13548
14438
  };
13549
14439
  return widget;
13550
14440
  }
14441
+ createHtml(layoutDefinition) {
14442
+ let widget = {
14443
+ type: SmartFormWidgetType.HTML,
14444
+ key: layoutDefinition.key,
14445
+ label: layoutDefinition.label,
14446
+ cssClass: layoutDefinition.cssClass,
14447
+ style: layoutDefinition.style,
14448
+ htmlProperties: layoutDefinition.properties?.['HTML_properties'],
14449
+ };
14450
+ return widget;
14451
+ }
13551
14452
  createButton(config) {
13552
14453
  let uiAction = config.uiActions?.find((uiAction) => uiAction.code === config.layoutDefinition?.key);
13553
14454
  let widget = {
@@ -16595,6 +17496,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
16595
17496
  args: ['pageName']
16596
17497
  }] }] });
16597
17498
 
17499
+ /** The reserved key of the default row layout in a grid view's `rowLayouts` (Layouts.DEFAULT_LAYOUT). */
17500
+ const DEFAULT_ROW_LAYOUT = 'default';
16598
17501
  var GridUiActionType;
16599
17502
  (function (GridUiActionType) {
16600
17503
  GridUiActionType[GridUiActionType["POPUP_MENU"] = 0] = "POPUP_MENU";
@@ -17273,23 +18176,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
17273
18176
 
17274
18177
  const APIS$2 = [GridService];
17275
18178
 
17276
- /**
17277
- * Grid api
17278
- * The grid api is resposible for the grid components that shows a list of item.
17279
- *
17280
- * The version of the OpenAPI document: 1.0.0
17281
- * Contact: info@it4all.hu
17282
- *
17283
- * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
17284
- * https://openapi-generator.tech
17285
- * Do not edit the class manually.
17286
- */
17287
- var GridColumnContentType;
17288
- (function (GridColumnContentType) {
17289
- GridColumnContentType["TEXT"] = "text";
17290
- GridColumnContentType["HTML"] = "html";
17291
- })(GridColumnContentType || (GridColumnContentType = {}));
17292
-
17293
18179
  /**
17294
18180
  * Grid api
17295
18181
  * The grid api is resposible for the grid components that shows a list of item.
@@ -17794,6 +18680,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
17794
18680
  args: ['headerComponent', { read: ViewContainerRef }]
17795
18681
  }] } });
17796
18682
 
18683
+ /**
18684
+ * The component a grid card renders a row layout with: `SmartComponentLayoutComponent`, provided
18685
+ * by `provideSmartNgClient()`. A token because the card cannot import that class without closing
18686
+ * the card -> layout -> grid -> card import cycle.
18687
+ */
18688
+ const SMART_ROW_LAYOUT_COMPONENT = new InjectionToken('SMART_ROW_LAYOUT_COMPONENT');
18689
+
17797
18690
  class SmartGridCardComponent {
17798
18691
  constructor() {
17799
18692
  this.cfService = inject(ComponentFactoryService);
@@ -17813,16 +18706,19 @@ class SmartGridCardComponent {
17813
18706
  * below never looks like the root of an embedded-view tree — a layout with no
17814
18707
  * `parentLayoutComponent` detaches every embedded view of its view (#28870). Typed `any`:
17815
18708
  * this component cannot name the layout class without closing the
17816
- * card -> layout -> grid -> card import cycle.
18709
+ * card -> layout -> grid -> card import cycle; the class itself arrives through
18710
+ * {@link SMART_ROW_LAYOUT_COMPONENT} for the same reason.
17817
18711
  */
17818
18712
  this.parentLayoutComponent = input(/* @ts-ignore */
17819
18713
  ...(ngDevMode ? [undefined, { debugName: "parentLayoutComponent" }] : /* istanbul ignore next */ []));
17820
18714
  /**
17821
- * The layout the backend described for this row, if it described one. Its presence is what
17822
- * decides between the host-registered card component and a layout rendered from the model.
18715
+ * The row layout of this row, as the grid resolved it (`SmartGridComponent.rowLayoutOf`). Its
18716
+ * presence is what decides between the host-registered card component and a layout rendered
18717
+ * from the model.
17823
18718
  */
17824
- this.layout = computed(() => this.item().layoutDescriptor?.componentLayouts?.['GRID_ROW_LAYOUT'], /* @ts-ignore */
17825
- ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
18719
+ this.layout = input(/* @ts-ignore */
18720
+ ...(ngDevMode ? [undefined, { debugName: "layout" }] : /* istanbul ignore next */ []));
18721
+ this.layoutComponent = inject(SMART_ROW_LAYOUT_COMPONENT, { optional: true });
17826
18722
  this.uiActionModels = [];
17827
18723
  this.envInjector = inject(EnvironmentInjector);
17828
18724
  }
@@ -17840,19 +18736,7 @@ class SmartGridCardComponent {
17840
18736
  this.vcRef?.clear();
17841
18737
  }
17842
18738
  constructUiActionModels() {
17843
- this.uiActionModels = this.item().actions.map((_uiAction) => {
17844
- let uiAction = { ..._uiAction };
17845
- uiAction.params = {
17846
- ...uiAction.params,
17847
- model: this.item(),
17848
- };
17849
- return {
17850
- serviceToUse: this.smartGrid().serviceToUse,
17851
- uiAction,
17852
- widgetId: this.smartGrid().gridIdentifier,
17853
- nodeId: this.item().id,
17854
- };
17855
- });
18739
+ this.uiActionModels = rowActionModels(this.item(), this.smartGrid().gridIdentifier, this.smartGrid().serviceToUse);
17856
18740
  }
17857
18741
  constructComponent() {
17858
18742
  const smartGrid = this.smartGrid();
@@ -17874,9 +18758,7 @@ class SmartGridCardComponent {
17874
18758
  // nothing bound on them, so they pull — and this is what they must find. Written before
17875
18759
  // the layout exists, so the first resolution is already the row's own actions.
17876
18760
  this.actionHost.actionModels.set(this.uiActionModels);
17877
- // The layout class travels on the grid model rather than being imported here; see
17878
- // `parentLayoutComponent` above for the cycle.
17879
- this.componentRef = this.cfService.createComponent(this.vcRef, smartGrid.layoutComponent, new Map([
18761
+ this.componentRef = this.cfService.createComponent(this.vcRef, this.layoutComponent, new Map([
17880
18762
  ['smartComponentLayout', layout],
17881
18763
  ['parentLayoutComponent', this.parentLayoutComponent()],
17882
18764
  ['gridRow', this.item()],
@@ -17887,7 +18769,7 @@ class SmartGridCardComponent {
17887
18769
  this.renderer.addClass(this.componentRef.location.nativeElement, 'gridCardLayout');
17888
18770
  }
17889
18771
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartGridCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17890
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: SmartGridCardComponent, isStandalone: true, selector: "app-smart-grid-card", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, smartGrid: { classPropertyName: "smartGrid", publicName: "smartGrid", isSignal: true, isRequired: true, transformFunction: null }, parentLayoutComponent: { classPropertyName: "parentLayoutComponent", publicName: "parentLayoutComponent", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-testid": "this.testId" } }, providers: [SmartActionHost], viewQueries: [{ propertyName: "vcRef", first: true, predicate: ["customCardComponent"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div class=\"smart-grid-card-template\">\n <ng-template #customCardComponent></ng-template>\n</div>\n", styles: [".smart-grid-card-template{display:flex}:host ::ng-deep .gridCardLayout{display:flex;flex:1}\n"] }); }
18772
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: SmartGridCardComponent, isStandalone: true, selector: "app-smart-grid-card", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, smartGrid: { classPropertyName: "smartGrid", publicName: "smartGrid", isSignal: true, isRequired: true, transformFunction: null }, parentLayoutComponent: { classPropertyName: "parentLayoutComponent", publicName: "parentLayoutComponent", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-testid": "this.testId" } }, providers: [SmartActionHost], viewQueries: [{ propertyName: "vcRef", first: true, predicate: ["customCardComponent"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div class=\"smart-grid-card-template\">\n <ng-template #customCardComponent></ng-template>\n</div>\n", styles: [".smart-grid-card-template{display:flex}:host ::ng-deep .gridCardLayout{display:flex;flex:1}\n"] }); }
17891
18773
  }
17892
18774
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartGridCardComponent, decorators: [{
17893
18775
  type: Component,
@@ -17898,7 +18780,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
17898
18780
  }], vcRef: [{
17899
18781
  type: ViewChild,
17900
18782
  args: ['customCardComponent', { read: ViewContainerRef }]
17901
- }] } });
18783
+ }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }] } });
17902
18784
 
17903
18785
  class SmartGridComponent {
17904
18786
  get testId() {
@@ -18033,6 +18915,8 @@ class SmartGridComponent {
18033
18915
  row.level = level;
18034
18916
  return row;
18035
18917
  };
18918
+ //#region Row layouts of a cards grid
18919
+ this.warnedRowLayouts = new Set();
18036
18920
  registerSmartWidget(this.smartComponent, {
18037
18921
  identifier: () => this.smartGrid?.gridIdentifier,
18038
18922
  reload: () => this.refresh(),
@@ -18578,6 +19462,8 @@ class SmartGridComponent {
18578
19462
  orderNumber,
18579
19463
  properties,
18580
19464
  style: descColumn.style,
19465
+ contentType: descColumn.contentType,
19466
+ htmlProperties: descColumn.htmlProperties,
18581
19467
  };
18582
19468
  });
18583
19469
  let complement = this.smartGrid.tableConfig?.customSmartTableHeaders?.filter((tableHeader) => !header.some((tH) => tH.propertyName.includes(tableHeader.propertyName)));
@@ -18720,18 +19606,78 @@ class SmartGridComponent {
18720
19606
  this.handleOnClick(gridRow);
18721
19607
  }
18722
19608
  handleOnClick(gridRow) {
18723
- let defaultRowAction;
18724
- if (this.service.gridModel?.defaultRowActions) {
18725
- for (let index = 0; index < this.service.gridModel.defaultRowActions.length; index++) {
18726
- const defaultRowActionCode = this.service.gridModel.defaultRowActions[index];
18727
- defaultRowAction = gridRow.actions.find((uiAction) => uiAction.code === defaultRowActionCode);
18728
- if (defaultRowAction) {
18729
- this.execute([], gridRow, defaultRowAction);
18730
- return;
18731
- }
19609
+ const defaultRowAction = this.defaultRowActionOf(gridRow);
19610
+ if (defaultRowAction) {
19611
+ this.execute([], gridRow, defaultRowAction);
19612
+ }
19613
+ }
19614
+ /** The first default row action of the grid that this row offers. */
19615
+ defaultRowActionOf(gridRow) {
19616
+ for (const code of this.service.gridModel?.defaultRowActions ?? []) {
19617
+ const defaultRowAction = gridRow.actions.find((uiAction) => uiAction.code === code);
19618
+ if (defaultRowAction) {
19619
+ return defaultRowAction;
19620
+ }
19621
+ }
19622
+ return undefined;
19623
+ }
19624
+ /**
19625
+ * The row layout a card renders this row with: the row's own
19626
+ * `layoutDescriptor.GRID_ROW_LAYOUT`, then the grid view's `rowLayouts` entry the row names,
19627
+ * then the default row layout (the `default` key, or the only entry). `undefined` leaves the
19628
+ * row to the host-registered card component. A key the grid does not know falls back to the
19629
+ * default with a warning, so a mistyped key shows instead of making the card disappear.
19630
+ */
19631
+ rowLayoutOf(row) {
19632
+ const own = row.layoutDescriptor?.componentLayouts?.['GRID_ROW_LAYOUT'];
19633
+ if (own) {
19634
+ return own;
19635
+ }
19636
+ const descriptor = this.smartGrid?.gridModel.view?.descriptor;
19637
+ const rowLayouts = descriptor?.rowLayouts;
19638
+ const keys = Object.keys(rowLayouts ?? {});
19639
+ if (!rowLayouts || !keys.length || descriptor.kind !== GridViewDescriptorKindEnum.CARDS) {
19640
+ return undefined;
19641
+ }
19642
+ const named = row.rowLayout ? rowLayouts[row.rowLayout] : undefined;
19643
+ if (named) {
19644
+ return named;
19645
+ }
19646
+ const fallback = rowLayouts[DEFAULT_ROW_LAYOUT] ?? (keys.length === 1 ? rowLayouts[keys[0]] : undefined);
19647
+ if (row.rowLayout || !fallback) {
19648
+ const warning = `grid ${this.smartGrid?.gridIdentifier}, row ${row.id}: ` +
19649
+ (row.rowLayout ? `unknown row layout '${row.rowLayout}'` : 'the row names no row layout') +
19650
+ (fallback ? ', the default is used' : ' and there is no default');
19651
+ if (!this.warnedRowLayouts.has(warning)) {
19652
+ this.warnedRowLayouts.add(warning);
19653
+ console.warn(warning);
18732
19654
  }
18733
19655
  }
19656
+ return fallback;
19657
+ }
19658
+ /** Whether a click on the card of this row toggles its selection. */
19659
+ isCardSelectable(row) {
19660
+ const selectionMode = this.smartGrid?.gridModel.view?.descriptor?.selectionMode;
19661
+ return (!!this.rowLayoutOf(row) &&
19662
+ !!selectionMode &&
19663
+ selectionMode !== GridSelectionMode.NONE &&
19664
+ row.selectable !== false);
18734
19665
  }
19666
+ /** Whether a double click on the card of this row fires its default row action. */
19667
+ hasCardDefaultAction(row) {
19668
+ return !!this.rowLayoutOf(row) && !!this.defaultRowActionOf(row);
19669
+ }
19670
+ onCardClick(row) {
19671
+ if (this.isCardSelectable(row)) {
19672
+ this.onSelect(row.id);
19673
+ }
19674
+ }
19675
+ onCardDoubleClick(row) {
19676
+ if (this.hasCardDefaultAction(row)) {
19677
+ this.onDoubleClick(row);
19678
+ }
19679
+ }
19680
+ //#endregion
18735
19681
  async onSelect(rowId) {
18736
19682
  this.isBlocked = true;
18737
19683
  const row = this.service.gridModel.page.rows?.find((gridRow) => gridRow.id === rowId);
@@ -18771,6 +19717,12 @@ class SmartGridComponent {
18771
19717
  };
18772
19718
  this.dialog.open(TableLayoutDefinerComponent, { data: dialogData });
18773
19719
  }
19720
+ calcStyle(style) {
19721
+ return SmartStyleUtility.getNgStyles(style);
19722
+ }
19723
+ calcClasses(style) {
19724
+ return SmartStyleUtility.getNgClasses(style);
19725
+ }
18774
19726
  get showEditColumns() {
18775
19727
  return {
18776
19728
  title: '',
@@ -18781,11 +19733,11 @@ class SmartGridComponent {
18781
19733
  };
18782
19734
  }
18783
19735
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
18784
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartGridComponent, isStandalone: true, selector: "smart-grid", inputs: { smartGrid: { classPropertyName: "smartGrid", publicName: "smartGrid", isSignal: false, isRequired: false, transformFunction: null }, uuid: { classPropertyName: "uuid", publicName: "uuid", isSignal: false, isRequired: false, transformFunction: null }, parentLayoutComponent: { classPropertyName: "parentLayoutComponent", publicName: "parentLayoutComponent", isSignal: true, isRequired: false, transformFunction: null }, dev: { classPropertyName: "dev", publicName: "dev", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-testid": "this.testId" } }, providers: [SmartGridService], viewQueries: [{ propertyName: "vcRefTable", first: true, predicate: ["table"], descendants: true, read: ViewContainerRef }, { propertyName: "expandedRowsComps", predicate: ExpandedRowRendererComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (smartGrid) {\n<div class=\"smartGrid-container\">\n <div class=\"smart-grid-toolbar\">\n <smart-ui-action-toolbar [id]=\"toolbarId\"></smart-ui-action-toolbar>\n @if (smartGrid.showEditColumns) {\n <ui-action-button (actionClick)=\"editColumns()\" [descriptor]=\"showEditColumns\">\n </ui-action-button>\n }\n </div>\n <!-- <div [ngClass]=\"isBlocked ? 'blocked' : ''\"></div> -->\n <div class=\"smartGridContent\">\n <div>\n @if (smartGrid.showResultCount) {\n <div>\n <div class=\"smartGrid-data-number\">\n {{ smartGrid.gridModel.totalRowCount }}\n </div>\n </div>\n }\n </div>\n <div class=\"smart-grid-table-container\">\n <ng-template #table></ng-template>\n </div>\n @if (smartGrid.layoutDef === layoutDef().EXPANDABLE) {\n <div>\n @for (expandableSection of expandableSections; track expandableSection) {\n <smart-expandable-section #gridExpandableSection [data]=\"expandableSection\"></smart-expandable-section>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().CARD && smartGrid.dataLayoutDef) {\n <div class=\"cards-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n @for (row of smartGrid.gridModel.page.rows; track row.id) {\n <app-smart-grid-card class=\"smartGrid-card-container\" [class.clickable-row]=\"row.layoutDescriptor\"\n (click)=\"row.layoutDescriptor && onClick(row)\" [item]=\"row\" [smartGrid]=\"smartGrid\"\n [parentLayoutComponent]=\"parentLayoutComponent()\"></app-smart-grid-card>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().TREE && treeControl) {\n <div class=\"tree-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n <mat-tree [dataSource]=\"treeDataSource!\" [treeControl]=\"treeControl!\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button disabled class=\"tree-button\"></button>\n <mat-checkbox class=\"checklist-leaf-node\"\n [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n (change)=\"treeNodeSelectionToggle(node)\">{{ getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button matTreeNodeToggle class=\"tree-button\" [attr.aria-label]=\"'Toggle ' + node.item\">\n <mat-icon class=\"mat-icon-rtl-mirror\">\n {{ treeControl!.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-checkbox [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n [indeterminate]=\"descendantsPartiallySelected(node)\" (change)=\"treeNodeSelectionToggle(node)\">{{\n getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n </mat-tree>\n </div>\n }\n </div>\n @if (smartGrid.paginator) {\n <div class=\"paginator-row-material\">\n @if (smartGrid.gridModel.refreshEnabled) {\n <button mat-icon-button type=\"button\" matTooltip=\"Friss\u00EDt\u00E9s\" (click)=\"refreshPartialResults()\">\n <mat-icon>refresh</mat-icon>\n </button>\n }\n @if (smartGrid.paginator && !treeControl) {\n <mat-paginator #paginator [length]=\"length\" [pageIndex]=\"pageIndex\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" (page)=\"onChangePage($event)\"></mat-paginator>\n }\n </div>\n }\n</div>\n}", styles: [".smartGrid-container{position:relative;padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.smartGrid-data-number{padding-bottom:1rem}.cards-container{display:grid;gap:1rem;padding:1rem}.smartGrid-container ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-underline{bottom:0}.smartGridContent{width:100%;flex:1;overflow:auto}.blocked{position:absolute;width:calc(100% - 3rem);height:calc(100% - 3rem);z-index:110;background-color:#0003}.smart-grid-table-container{display:flex;flex-direction:column;gap:1rem}.smart-grid-toolbar{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.smart-grid-toolbar smart-ui-action-toolbar{width:100%}.smart-grid-edit-icon{color:var(--light-gray)}.tree-button{width:24px!important;height:24px!important}.paginator-row-material{display:flex;align-items:center;align-self:flex-end;gap:.25rem}.clickable-row{cursor:pointer}\n"], dependencies: [{ kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ExpandableSectionComponent, selector: "smart-expandable-section", inputs: ["data", "index"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SmartGridCardComponent, selector: "app-smart-grid-card", inputs: ["item", "smartGrid", "parentLayoutComponent"] }, { kind: "component", type: MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "directive", type: MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "directive", type: MatTreeNodePadding, selector: "[matTreeNodePadding]", inputs: ["matTreeNodePadding", "matTreeNodePaddingIndent"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }] }); }
19736
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartGridComponent, isStandalone: true, selector: "smart-grid", inputs: { smartGrid: { classPropertyName: "smartGrid", publicName: "smartGrid", isSignal: false, isRequired: false, transformFunction: null }, uuid: { classPropertyName: "uuid", publicName: "uuid", isSignal: false, isRequired: false, transformFunction: null }, parentLayoutComponent: { classPropertyName: "parentLayoutComponent", publicName: "parentLayoutComponent", isSignal: true, isRequired: false, transformFunction: null }, dev: { classPropertyName: "dev", publicName: "dev", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-testid": "this.testId" } }, providers: [SmartGridService], viewQueries: [{ propertyName: "vcRefTable", first: true, predicate: ["table"], descendants: true, read: ViewContainerRef }, { propertyName: "expandedRowsComps", predicate: ExpandedRowRendererComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (smartGrid) {\n<div class=\"smartGrid-container\">\n <div class=\"smart-grid-toolbar\">\n <smart-ui-action-toolbar [id]=\"toolbarId\"></smart-ui-action-toolbar>\n @if (smartGrid.showEditColumns) {\n <ui-action-button (actionClick)=\"editColumns()\" [descriptor]=\"showEditColumns\">\n </ui-action-button>\n }\n </div>\n <!-- <div [ngClass]=\"isBlocked ? 'blocked' : ''\"></div> -->\n <div class=\"smartGridContent\">\n <div>\n @if (smartGrid.showResultCount) {\n <div>\n <div class=\"smartGrid-data-number\">\n {{ smartGrid.gridModel.totalRowCount }}\n </div>\n </div>\n }\n </div>\n <div class=\"smart-grid-table-container\">\n <ng-template #table></ng-template>\n </div>\n @if (smartGrid.layoutDef === layoutDef().EXPANDABLE) {\n <div>\n @for (expandableSection of expandableSections; track expandableSection) {\n <smart-expandable-section #gridExpandableSection [data]=\"expandableSection\"></smart-expandable-section>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().CARD && smartGrid.dataLayoutDef) {\n <div class=\"cards-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n @for (row of smartGrid.gridModel.page.rows; track row.id) {\n\n <app-smart-grid-card class=\"smartGrid-card-container\" [ngClass]=\"calcClasses(row.style)\"\n [ngStyle]=\"calcStyle(row.style)\"\n [class.clickable-row]=\"isCardSelectable(row) || hasCardDefaultAction(row)\"\n [class.selected]=\"!!row.selected && !!rowLayoutOf(row)\"\n (click)=\"onCardClick(row)\" (dblclick)=\"onCardDoubleClick(row)\" [item]=\"row\"\n [layout]=\"rowLayoutOf(row)\" [smartGrid]=\"smartGrid\"\n [parentLayoutComponent]=\"parentLayoutComponent()\"></app-smart-grid-card>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().TREE && treeControl) {\n <div class=\"tree-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n <mat-tree [dataSource]=\"treeDataSource!\" [treeControl]=\"treeControl!\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button disabled class=\"tree-button\"></button>\n <mat-checkbox class=\"checklist-leaf-node\"\n [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n (change)=\"treeNodeSelectionToggle(node)\">{{ getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button matTreeNodeToggle class=\"tree-button\" [attr.aria-label]=\"'Toggle ' + node.item\">\n <mat-icon class=\"mat-icon-rtl-mirror\">\n {{ treeControl!.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-checkbox [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n [indeterminate]=\"descendantsPartiallySelected(node)\" (change)=\"treeNodeSelectionToggle(node)\">{{\n getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n </mat-tree>\n </div>\n }\n </div>\n @if (smartGrid.paginator) {\n <div class=\"paginator-row-material\">\n @if (smartGrid.gridModel.refreshEnabled) {\n <button mat-icon-button type=\"button\" matTooltip=\"Friss\u00EDt\u00E9s\" (click)=\"refreshPartialResults()\">\n <mat-icon>refresh</mat-icon>\n </button>\n }\n @if (smartGrid.paginator && !treeControl) {\n <mat-paginator #paginator [length]=\"length\" [pageIndex]=\"pageIndex\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" (page)=\"onChangePage($event)\"></mat-paginator>\n }\n </div>\n }\n</div>\n}", styles: [".smartGrid-container{position:relative;padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.smartGrid-data-number{padding-bottom:1rem}.cards-container{display:grid;gap:1rem;padding:1rem}.smartGrid-container ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-underline{bottom:0}.smartGridContent{width:100%;flex:1;overflow:auto}.blocked{position:absolute;width:calc(100% - 3rem);height:calc(100% - 3rem);z-index:110;background-color:#0003}.smart-grid-table-container{display:flex;flex-direction:column;gap:1rem}.smart-grid-toolbar{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.smart-grid-toolbar smart-ui-action-toolbar{width:100%}.smart-grid-edit-icon{color:var(--light-gray)}.tree-button{width:24px!important;height:24px!important}.paginator-row-material{display:flex;align-items:center;align-self:flex-end;gap:.25rem}.clickable-row{cursor:pointer}.smartGrid-card-container.selected{outline:2px solid var(--mat-sys-primary, currentColor)}\n"], dependencies: [{ kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ExpandableSectionComponent, selector: "smart-expandable-section", inputs: ["data", "index"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: SmartGridCardComponent, selector: "app-smart-grid-card", inputs: ["item", "smartGrid", "parentLayoutComponent", "layout"] }, { kind: "component", type: MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "directive", type: MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "directive", type: MatTreeNodePadding, selector: "[matTreeNodePadding]", inputs: ["matTreeNodePadding", "matTreeNodePaddingIndent"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }] }); }
18785
19737
  }
18786
19738
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartGridComponent, decorators: [{
18787
19739
  type: Component,
18788
- args: [{ selector: 'smart-grid', providers: [SmartGridService], imports: [UiActionToolbarComponent, UiActionButtonComponent, MatMiniFabButton, MatIcon, ExpandableSectionComponent, NgStyle, SmartGridCardComponent, MatTree, MatTreeNodeDef, MatTreeNode, MatTreeNodeToggle, MatTreeNodePadding, MatIconButton, MatCheckbox, MatTooltip, MatPaginator], template: "@if (smartGrid) {\n<div class=\"smartGrid-container\">\n <div class=\"smart-grid-toolbar\">\n <smart-ui-action-toolbar [id]=\"toolbarId\"></smart-ui-action-toolbar>\n @if (smartGrid.showEditColumns) {\n <ui-action-button (actionClick)=\"editColumns()\" [descriptor]=\"showEditColumns\">\n </ui-action-button>\n }\n </div>\n <!-- <div [ngClass]=\"isBlocked ? 'blocked' : ''\"></div> -->\n <div class=\"smartGridContent\">\n <div>\n @if (smartGrid.showResultCount) {\n <div>\n <div class=\"smartGrid-data-number\">\n {{ smartGrid.gridModel.totalRowCount }}\n </div>\n </div>\n }\n </div>\n <div class=\"smart-grid-table-container\">\n <ng-template #table></ng-template>\n </div>\n @if (smartGrid.layoutDef === layoutDef().EXPANDABLE) {\n <div>\n @for (expandableSection of expandableSections; track expandableSection) {\n <smart-expandable-section #gridExpandableSection [data]=\"expandableSection\"></smart-expandable-section>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().CARD && smartGrid.dataLayoutDef) {\n <div class=\"cards-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n @for (row of smartGrid.gridModel.page.rows; track row.id) {\n <app-smart-grid-card class=\"smartGrid-card-container\" [class.clickable-row]=\"row.layoutDescriptor\"\n (click)=\"row.layoutDescriptor && onClick(row)\" [item]=\"row\" [smartGrid]=\"smartGrid\"\n [parentLayoutComponent]=\"parentLayoutComponent()\"></app-smart-grid-card>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().TREE && treeControl) {\n <div class=\"tree-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n <mat-tree [dataSource]=\"treeDataSource!\" [treeControl]=\"treeControl!\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button disabled class=\"tree-button\"></button>\n <mat-checkbox class=\"checklist-leaf-node\"\n [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n (change)=\"treeNodeSelectionToggle(node)\">{{ getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button matTreeNodeToggle class=\"tree-button\" [attr.aria-label]=\"'Toggle ' + node.item\">\n <mat-icon class=\"mat-icon-rtl-mirror\">\n {{ treeControl!.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-checkbox [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n [indeterminate]=\"descendantsPartiallySelected(node)\" (change)=\"treeNodeSelectionToggle(node)\">{{\n getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n </mat-tree>\n </div>\n }\n </div>\n @if (smartGrid.paginator) {\n <div class=\"paginator-row-material\">\n @if (smartGrid.gridModel.refreshEnabled) {\n <button mat-icon-button type=\"button\" matTooltip=\"Friss\u00EDt\u00E9s\" (click)=\"refreshPartialResults()\">\n <mat-icon>refresh</mat-icon>\n </button>\n }\n @if (smartGrid.paginator && !treeControl) {\n <mat-paginator #paginator [length]=\"length\" [pageIndex]=\"pageIndex\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" (page)=\"onChangePage($event)\"></mat-paginator>\n }\n </div>\n }\n</div>\n}", styles: [".smartGrid-container{position:relative;padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.smartGrid-data-number{padding-bottom:1rem}.cards-container{display:grid;gap:1rem;padding:1rem}.smartGrid-container ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-underline{bottom:0}.smartGridContent{width:100%;flex:1;overflow:auto}.blocked{position:absolute;width:calc(100% - 3rem);height:calc(100% - 3rem);z-index:110;background-color:#0003}.smart-grid-table-container{display:flex;flex-direction:column;gap:1rem}.smart-grid-toolbar{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.smart-grid-toolbar smart-ui-action-toolbar{width:100%}.smart-grid-edit-icon{color:var(--light-gray)}.tree-button{width:24px!important;height:24px!important}.paginator-row-material{display:flex;align-items:center;align-self:flex-end;gap:.25rem}.clickable-row{cursor:pointer}\n"] }]
19740
+ args: [{ selector: 'smart-grid', providers: [SmartGridService], imports: [UiActionToolbarComponent, UiActionButtonComponent, MatMiniFabButton, MatIcon, ExpandableSectionComponent, NgStyle, NgClass, SmartGridCardComponent, MatTree, MatTreeNodeDef, MatTreeNode, MatTreeNodeToggle, MatTreeNodePadding, MatIconButton, MatCheckbox, MatTooltip, MatPaginator], template: "@if (smartGrid) {\n<div class=\"smartGrid-container\">\n <div class=\"smart-grid-toolbar\">\n <smart-ui-action-toolbar [id]=\"toolbarId\"></smart-ui-action-toolbar>\n @if (smartGrid.showEditColumns) {\n <ui-action-button (actionClick)=\"editColumns()\" [descriptor]=\"showEditColumns\">\n </ui-action-button>\n }\n </div>\n <!-- <div [ngClass]=\"isBlocked ? 'blocked' : ''\"></div> -->\n <div class=\"smartGridContent\">\n <div>\n @if (smartGrid.showResultCount) {\n <div>\n <div class=\"smartGrid-data-number\">\n {{ smartGrid.gridModel.totalRowCount }}\n </div>\n </div>\n }\n </div>\n <div class=\"smart-grid-table-container\">\n <ng-template #table></ng-template>\n </div>\n @if (smartGrid.layoutDef === layoutDef().EXPANDABLE) {\n <div>\n @for (expandableSection of expandableSections; track expandableSection) {\n <smart-expandable-section #gridExpandableSection [data]=\"expandableSection\"></smart-expandable-section>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().CARD && smartGrid.dataLayoutDef) {\n <div class=\"cards-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n @for (row of smartGrid.gridModel.page.rows; track row.id) {\n\n <app-smart-grid-card class=\"smartGrid-card-container\" [ngClass]=\"calcClasses(row.style)\"\n [ngStyle]=\"calcStyle(row.style)\"\n [class.clickable-row]=\"isCardSelectable(row) || hasCardDefaultAction(row)\"\n [class.selected]=\"!!row.selected && !!rowLayoutOf(row)\"\n (click)=\"onCardClick(row)\" (dblclick)=\"onCardDoubleClick(row)\" [item]=\"row\"\n [layout]=\"rowLayoutOf(row)\" [smartGrid]=\"smartGrid\"\n [parentLayoutComponent]=\"parentLayoutComponent()\"></app-smart-grid-card>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().TREE && treeControl) {\n <div class=\"tree-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n <mat-tree [dataSource]=\"treeDataSource!\" [treeControl]=\"treeControl!\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button disabled class=\"tree-button\"></button>\n <mat-checkbox class=\"checklist-leaf-node\"\n [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n (change)=\"treeNodeSelectionToggle(node)\">{{ getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button matTreeNodeToggle class=\"tree-button\" [attr.aria-label]=\"'Toggle ' + node.item\">\n <mat-icon class=\"mat-icon-rtl-mirror\">\n {{ treeControl!.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-checkbox [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n [indeterminate]=\"descendantsPartiallySelected(node)\" (change)=\"treeNodeSelectionToggle(node)\">{{\n getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n </mat-tree>\n </div>\n }\n </div>\n @if (smartGrid.paginator) {\n <div class=\"paginator-row-material\">\n @if (smartGrid.gridModel.refreshEnabled) {\n <button mat-icon-button type=\"button\" matTooltip=\"Friss\u00EDt\u00E9s\" (click)=\"refreshPartialResults()\">\n <mat-icon>refresh</mat-icon>\n </button>\n }\n @if (smartGrid.paginator && !treeControl) {\n <mat-paginator #paginator [length]=\"length\" [pageIndex]=\"pageIndex\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" (page)=\"onChangePage($event)\"></mat-paginator>\n }\n </div>\n }\n</div>\n}", styles: [".smartGrid-container{position:relative;padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.smartGrid-data-number{padding-bottom:1rem}.cards-container{display:grid;gap:1rem;padding:1rem}.smartGrid-container ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-underline{bottom:0}.smartGridContent{width:100%;flex:1;overflow:auto}.blocked{position:absolute;width:calc(100% - 3rem);height:calc(100% - 3rem);z-index:110;background-color:#0003}.smart-grid-table-container{display:flex;flex-direction:column;gap:1rem}.smart-grid-toolbar{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.smart-grid-toolbar smart-ui-action-toolbar{width:100%}.smart-grid-edit-icon{color:var(--light-gray)}.tree-button{width:24px!important;height:24px!important}.paginator-row-material{display:flex;align-items:center;align-self:flex-end;gap:.25rem}.clickable-row{cursor:pointer}.smartGrid-card-container.selected{outline:2px solid var(--mat-sys-primary, currentColor)}\n"] }]
18789
19741
  }], ctorParameters: () => [], propDecorators: { smartGrid: [{
18790
19742
  type: Input
18791
19743
  }], uuid: [{
@@ -22592,12 +23544,13 @@ class SmartComponentLayoutComponent {
22592
23544
  layoutDefinitions: this.smartComponentLayout?.form,
22593
23545
  });
22594
23546
  const gridRow = this.gridRow;
22595
- if (gridRow && !gridRow.valueSets) {
22596
- gridRow.valueSets = this.smartComponent?.model?.valueSets;
22597
- }
22598
23547
  this.smartForm = {
22599
23548
  direction: this.getFormLayout(),
22600
- componentModel: gridRow ? gridRow : this.smartComponent?.model,
23549
+ // A row gets an envelope rather than being written into: its `data` stays the row's own
23550
+ // object, and the valueSets of the page come along by reference.
23551
+ componentModel: gridRow
23552
+ ? { ...gridRow, valueSets: gridRow.valueSets ?? this.smartComponent?.model?.valueSets }
23553
+ : this.smartComponent?.model,
22601
23554
  widgets,
22602
23555
  };
22603
23556
  }
@@ -22620,9 +23573,6 @@ class SmartComponentLayoutComponent {
22620
23573
  },
22621
23574
  layoutDef: SmartLayoutDef.TABLE,
22622
23575
  paginator: false,
22623
- // What a card of this grid instantiates for a row that carries a layoutDescriptor.
22624
- // The grid model is the only way across: the card cannot import this class.
22625
- layoutComponent: SmartComponentLayoutComponent,
22626
23576
  };
22627
23577
  }
22628
23578
  constructMap() {
@@ -22839,8 +23789,6 @@ class SearchPageComponent extends SmartComponent {
22839
23789
  options: {
22840
23790
  rowUiActionType: GridUiActionType.POPUP_MENU,
22841
23791
  },
22842
- // Card grids render the row's own layout with this class (see SmartGridCardComponent).
22843
- layoutComponent: SmartComponentLayoutComponent,
22844
23792
  };
22845
23793
  }
22846
23794
  isShowNoResultText() {
@@ -23040,6 +23988,8 @@ function provideSmartNgClient(config = {}, ...features) {
23040
23988
  SmartErrorCatchingInterceptor,
23041
23989
  SmartHeaderMaintainerInterceptor,
23042
23990
  { provide: DIALOG_DISABLE_CLOSE, useValue: resolved.dialogDisableClose },
23991
+ // What a grid card renders a row layout with; the card cannot import the class itself.
23992
+ { provide: SMART_ROW_LAYOUT_COMPONENT, useValue: SmartComponentLayoutComponent },
23043
23993
  // The ui-action dialog services, reachable through tokens because service and dialog
23044
23994
  // component import each other (see dialog-service.tokens.ts).
23045
23995
  { provide: UI_ACTION_CONFIRM_DIALOG_SERVICE, useClass: UiActionConfirmDialogService },
@@ -23804,5 +24754,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
23804
24754
  * Generated bundle index. Do not edit.
23805
24755
  */
23806
24756
 
23807
- export { ACLEntry, APIS$5 as APIS, AclEditingViewComponent, ApiQueueService, BASE_PATH$7 as BASE_PATH, COLLECTION_FORMATS$7 as COLLECTION_FORMATS, CUSTOM_DIAGRAM_OPTIONS, CloseResult, ComponentFactoryService, ComponentType, ComponentWidgetType, Configuration$7 as Configuration, DIALOG_DISABLE_CLOSE, DataChangeKind, DefaultChartOptionsProvider, DefaultUiActionCode_CLOSE, DrawTime, EMPTY_PARAMS, ExpandableSectionButtonIconPosition, ExpandableSectionButtonType, ExpandableSectionComponent, FilterExpressionBoolOperator$1 as FilterExpressionBoolOperator, FilterExpressionBuilderGroupBuilderGroupKindEnum, FilterExpressionBuilderUiModelTypeEnum, FilterExpressionDataType, FilterExpressionFieldWidgetType, FilterExpressionOperation, FilterExpressionOrderByOrderEnum, GenericPageComponent, GeoMapDataLoadingMode, GeoMapDataSourceType, GeoMapItemKind, GeoMapOperationMode, GeoMapSelectionMode, GeoMapTextType, GridColumnContentType, GridDataAccessConfigKindEnum, GridSelectionMode, GridSelectionType, GridUiActionType, GridViewDescriptorKindEnum, HighlightPipe, IS_ASYNC_PARAM_NAME, IconPosition, ImageResourceKindEnum, InvalidSmartlinkComponent, LayoutDirection, LinkTargetEnum, MAP_ENGINE, MapEngine, MenuOpenDirection, MenuTriggerType, MessageOptionType, MessageTextType, MessageType, NAMED_VALIDATOR, NamedValidatorOperationEnum, NamedValidatorService, NoPermissionPageComponent, REUSE_ROUTER_SLOT_COMPONENT, ROOT_CONTAINER_UUID, ROUTER_SLOT_ID, RecordingUploaderPropertiesOpenDirectionEnum, SMART_DATE_FORMATS, SMART_DEFAULT_VIEW_COMPONENTS, SMART_NG_CLIENT_CONFIG, SearchPageComponent, SelectionDefinitionTypeEnum, SelectionDefinitionValueSetValueTypeEnum, ServerRequestType, SessionAPIS, SessionErrorBehaviour, SessionService, SmartActionHost, SmartActionType, SmartBackendBootstrapService, SmartComponent, SmartComponentApiClient, SmartComponentDetachedDirective, SmartComponentHost, SmartComponentLayoutComponent, SmartDateFnsAdapter, SmartDatePipe, SmartDateTimePipe, SmartDefaultErrorUiService, SmartDiagramComponent, SmartDialog, SmartEmbeddedSlotDirective, SmartExpandableSectionService, SmartFileEditorComponent, SmartFilterComponent, SmartFilterEditorContentComponent, SmartFilterEditorService, SmartFilterExpressionFieldComponent, SmartFilterPosition, SmartFilterType, SmartFilterWidgetComponent, SmartFormInputMode, SmartFormTextFieldButtonIconPosition, SmartFormWidgetDirection, SmartFormWidgetType, SmartFormWidgetWidth, SmartGridButtonType, SmartGridComponent, SmartGridDataLayout, SmartGridService, SmartGridType, SmartIconComponent, SmartIconService, SmartLayoutDef, SmartLinkChannelVariableInPath, SmartLinkMigrationStatusStatusEnum, SmartLinkUuidVariableInPath, SmartMapComponent, SmartMultiFileEditorComponent, SmartNavbarComponent, SmartNavbarService, SmartNavigationService, SmartNgClientFeatureKind, SmartService, SmartSessionService, SmartSessionTimerComponent, SmartTable, SmartTableButtonType, SmartTableHeaderPropertyType, SmartTableInterfaceTypeEnum, SmartTableOptionButtonDirection, SmartTableOrder, SmartTableType, SmartTimePipe, SmartTooltipDirective, SmartTreeComponent, SmartTreeNodeButtonType, SmartUserSettinsIconPosition, SmartValidatorName, SmartViewContextService, SmartViewRedirect, SmartVoiceRecorderComponent, SmartWidgetHintPosition, SmartWidgetHintPositionEnum, SmartdialogService, SmartfileuploaderComponent, SmartformComponent, SmartformLayoutDefinitionService, SmarttreeGenericService, SmarttreeService, SubjectSelectorComponent, ThemeService, ToggleLabelPosition, ToolbarAlignment, ToolbarDirection, TreeArrowPosition, USE_ADVANCED_FILTER, UiActionButtonComponent, UiActionButtonType, UiActionConfirmDialogService, UiActionDescriptorService, UiActionDialogButtonComponent, UiActionDialogType, UiActionFeedbackType, UiActionInputDialogService, UiActionInputType, UiActionService, UiActionToolbarComponent, UiActionTooltipTooltipPositionEnum, UiBadgeComponent, UiBadgeDirective, UploadWidgetType, ValidationResultPageComponent, ValueChangeMode, ViewContextRebuiltError, ViewEventHandlerViewEventTypeEnum, ViewService, ViewState, ViewType, barChart, bubbleChart, createBasicOptions, doughnutChart, horizontalBarChart, horizontalStackedBarChart, injectSmartComponent, multiAxisLineChart, pieChart, polarAreaChart, provideSmartNgClient, radarChart, registerSmartWidget, resolveDateLocale, resolveSlot, resolveSmartNgClientConfig, resolveViewHandler, scatterChart, stackedBarChart, transformDataToBarLikeDataSet, transformDataToBasicDataSets, transformDataToBubble, transformDataToScatter, withSmartDiagram, withSmartMap };
24757
+ export { ACLEntry, APIS$5 as APIS, AclEditingViewComponent, ApiQueueService, BASE_PATH$7 as BASE_PATH, COLLECTION_FORMATS$7 as COLLECTION_FORMATS, CUSTOM_DIAGRAM_OPTIONS, CloseResult, ComponentFactoryService, ComponentType, ComponentWidgetType, Configuration$7 as Configuration, DEFAULT_ROW_LAYOUT, DIALOG_DISABLE_CLOSE, DataChangeKind, DefaultChartOptionsProvider, DefaultUiActionCode_CLOSE, DrawTime, EMPTY_PARAMS, ExpandableSectionButtonIconPosition, ExpandableSectionButtonType, ExpandableSectionComponent, FilterExpressionBoolOperator$1 as FilterExpressionBoolOperator, FilterExpressionBuilderGroupBuilderGroupKindEnum, FilterExpressionBuilderUiModelTypeEnum, FilterExpressionDataType, FilterExpressionFieldWidgetType, FilterExpressionOperation, FilterExpressionOrderByOrderEnum, GenericPageComponent, GeoMapDataLoadingMode, GeoMapDataSourceType, GeoMapItemKind, GeoMapOperationMode, GeoMapSelectionMode, GeoMapTextType, GridColumnContentType, GridDataAccessConfigKindEnum, GridSelectionMode, GridSelectionType, GridUiActionType, GridViewDescriptorKindEnum, HighlightPipe, IS_ASYNC_PARAM_NAME, IconPosition, ImageResourceKindEnum, InvalidSmartlinkComponent, LayoutDirection, LinkTargetEnum, MAP_ENGINE, MapEngine, MenuOpenDirection, MenuTriggerType, MessageOptionType, MessageTextType, MessageType, NAMED_VALIDATOR, NamedValidatorOperationEnum, NamedValidatorService, NoPermissionPageComponent, REUSE_ROUTER_SLOT_COMPONENT, ROOT_CONTAINER_UUID, ROUTER_SLOT_ID, RecordingUploaderPropertiesOpenDirectionEnum, SMART_DATE_FORMATS, SMART_DEFAULT_VIEW_COMPONENTS, SMART_NG_CLIENT_CONFIG, SMART_ROW_LAYOUT_COMPONENT, SearchPageComponent, SelectionDefinitionTypeEnum, SelectionDefinitionValueSetValueTypeEnum, ServerRequestType, SessionAPIS, SessionErrorBehaviour, SessionService, SmartActionHost, SmartActionType, SmartBackendBootstrapService, SmartComponent, SmartComponentApiClient, SmartComponentDetachedDirective, SmartComponentHost, SmartComponentLayoutComponent, SmartDateFnsAdapter, SmartDatePipe, SmartDateTimePipe, SmartDefaultErrorUiService, SmartDiagramComponent, SmartDialog, SmartEmbeddedSlotDirective, SmartExpandableSectionService, SmartFileEditorComponent, SmartFilterComponent, SmartFilterEditorContentComponent, SmartFilterEditorService, SmartFilterExpressionFieldComponent, SmartFilterPosition, SmartFilterType, SmartFilterWidgetComponent, SmartFormInputMode, SmartFormTextFieldButtonIconPosition, SmartFormWidgetDirection, SmartFormWidgetType, SmartFormWidgetWidth, SmartGridButtonType, SmartGridComponent, SmartGridDataLayout, SmartGridService, SmartGridType, SmartIconComponent, SmartIconService, SmartLayoutDef, SmartLinkChannelVariableInPath, SmartLinkMigrationStatusStatusEnum, SmartLinkUuidVariableInPath, SmartMapComponent, SmartMultiFileEditorComponent, SmartNavbarComponent, SmartNavbarService, SmartNavigationService, SmartNgClientFeatureKind, SmartService, SmartSessionService, SmartSessionTimerComponent, SmartTable, SmartTableButtonType, SmartTableHeaderPropertyType, SmartTableInterfaceTypeEnum, SmartTableOptionButtonDirection, SmartTableOrder, SmartTableType, SmartTimePipe, SmartTooltipDirective, SmartTreeComponent, SmartTreeNodeButtonType, SmartUserSettinsIconPosition, SmartValidatorName, SmartViewContextService, SmartViewRedirect, SmartVoiceRecorderComponent, SmartWidgetHintPosition, SmartWidgetHintPositionEnum, SmartdialogService, SmartfileuploaderComponent, SmartformComponent, SmartformLayoutDefinitionService, SmarttreeGenericService, SmarttreeService, SubjectSelectorComponent, ThemeService, ToggleLabelPosition, ToolbarAlignment, ToolbarDirection, TreeArrowPosition, USE_ADVANCED_FILTER, UiActionButtonComponent, UiActionButtonType, UiActionConfirmDialogService, UiActionDescriptorService, UiActionDialogButtonComponent, UiActionDialogType, UiActionFeedbackType, UiActionInputDialogService, UiActionInputType, UiActionService, UiActionToolbarComponent, UiActionTooltipTooltipPositionEnum, UiBadgeComponent, UiBadgeDirective, UploadWidgetType, ValidationResultPageComponent, ValueChangeMode, ViewContextRebuiltError, ViewEventHandlerViewEventTypeEnum, ViewService, ViewState, ViewType, barChart, bubbleChart, createBasicOptions, doughnutChart, horizontalBarChart, horizontalStackedBarChart, injectSmartComponent, multiAxisLineChart, pieChart, polarAreaChart, provideSmartNgClient, radarChart, registerSmartWidget, resolveDateLocale, resolveSlot, resolveSmartNgClientConfig, resolveViewHandler, scatterChart, stackedBarChart, transformDataToBarLikeDataSet, transformDataToBasicDataSets, transformDataToBubble, transformDataToScatter, withSmartDiagram, withSmartMap };
23808
24758
  //# sourceMappingURL=smartbit4all-ng-client.mjs.map