@quadrel-enterprise-ui/framework 20.27.6 → 20.28.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,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, Directive, InjectionToken, HostBinding, Input, ViewEncapsulation, Component, Injectable, Injector, HostListener, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, NgModule, EventEmitter, Output, Renderer2, Pipe, ViewContainerRef, NO_ERRORS_SCHEMA, DestroyRef, SecurityContext, NgZone, ViewChildren, forwardRef, ContentChildren, ContentChild, isDevMode, QueryList, TemplateRef, CUSTOM_ELEMENTS_SCHEMA, provideAppInitializer } from '@angular/core';
3
- import { Dialog, DialogRef, DialogModule } from '@angular/cdk/dialog';
2
+ import { inject, ElementRef, Directive, InjectionToken, HostBinding, Input, ViewEncapsulation, Component, Injectable, Injector, HostListener, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, NgModule, EventEmitter, Output, Renderer2, Pipe, ViewContainerRef, NO_ERRORS_SCHEMA, DestroyRef, SecurityContext, NgZone, ViewChildren, forwardRef, ContentChildren, ContentChild, afterNextRender, isDevMode, QueryList, TemplateRef, CUSTOM_ELEMENTS_SCHEMA, provideAppInitializer } from '@angular/core';
3
+ import { Dialog, DialogRef, DIALOG_DATA, DialogModule } from '@angular/cdk/dialog';
4
4
  import * as i1 from '@angular/common';
5
- import { CommonModule, NgFor, NgIf, NgClass, NgTemplateOutlet, AsyncPipe } from '@angular/common';
6
- import { BehaviorSubject, pairwise, from, switchMap, map as map$1, Subject, throwError, of, ReplaySubject, merge, fromEvent, isObservable, NEVER, Observable, EMPTY, shareReplay, Subscription, distinctUntilChanged as distinctUntilChanged$1, debounce, timer, startWith as startWith$1, debounceTime as debounceTime$1, takeUntil as takeUntil$1, firstValueFrom, combineLatest, concat, take as take$1, tap as tap$1, delay, first, scan, queueScheduler, filter as filter$1, concatMap as concatMap$1, exhaustMap, finalize, forkJoin, delayWhen, combineLatestWith, withLatestFrom as withLatestFrom$1, async } from 'rxjs';
5
+ import { CommonModule, DOCUMENT, NgFor, NgIf, NgClass, NgTemplateOutlet, AsyncPipe } from '@angular/common';
6
+ import { BehaviorSubject, pairwise, map as map$1, Subject, throwError, of, ReplaySubject, merge, fromEvent, isObservable, NEVER, Observable, EMPTY, shareReplay, Subscription, distinctUntilChanged as distinctUntilChanged$1, debounce, timer, switchMap, startWith as startWith$1, debounceTime as debounceTime$1, takeUntil as takeUntil$1, firstValueFrom, combineLatest, concat, take as take$1, tap as tap$1, from, delay, first, scan, queueScheduler, filter as filter$1, concatMap as concatMap$1, exhaustMap, finalize, forkJoin, delayWhen, combineLatestWith, withLatestFrom as withLatestFrom$1, async } from 'rxjs';
7
7
  import { map, takeUntil, take, filter, catchError, debounceTime, startWith, distinctUntilChanged, concatMap, skip, tap, auditTime, withLatestFrom, observeOn, switchMap as switchMap$1, pairwise as pairwise$1, mergeMap, delay as delay$1 } from 'rxjs/operators';
8
8
  import { v4 } from 'uuid';
9
9
  import * as i3 from '@ngx-translate/core';
@@ -1143,13 +1143,41 @@ var QdDialogSize;
1143
1143
  QdDialogSize["FullWidth"] = "100%";
1144
1144
  })(QdDialogSize || (QdDialogSize = {}));
1145
1145
 
1146
+ /**
1147
+ * Tracks which dialogs currently hold unsaved changes.
1148
+ *
1149
+ * Pending changes are always bound to the dialog that owns them. A dialog is
1150
+ * identified by its `DialogRef`, so two dialogs open at the same time never
1151
+ * read or overwrite each other's state.
1152
+ *
1153
+ * #### Notes & Best Practices:
1154
+ *
1155
+ * - A dialog can hold several sources of pending changes, for example one per
1156
+ * form. The dialog counts as changed while at least one source is marked.
1157
+ * - Every source that marks changes must clear them again when it is destroyed.
1158
+ * - A dialog without any marked source reports no pending changes. This is why
1159
+ * the discard confirmation dialog can always close itself.
1160
+ * - Owners are held weakly, so a dialog that is destroyed without clearing its
1161
+ * sources cannot keep them alive.
1162
+ */
1146
1163
  class QdDialogChangeGuardService {
1147
- _hasChanges = false;
1148
- get hasPendingChanges() {
1149
- return this._hasChanges;
1150
- }
1151
- setPendingChangesStatus(status) {
1152
- this._hasChanges = status;
1164
+ _pendingChangeSourcesByOwner = new WeakMap();
1165
+ hasPendingChanges(owner) {
1166
+ const sources = this._pendingChangeSourcesByOwner.get(owner);
1167
+ return !!sources?.size;
1168
+ }
1169
+ markPendingChanges(source, owner) {
1170
+ const sources = this._pendingChangeSourcesByOwner.get(owner) ?? new Set();
1171
+ sources.add(source);
1172
+ this._pendingChangeSourcesByOwner.set(owner, sources);
1173
+ }
1174
+ clearPendingChanges(source, owner) {
1175
+ const sources = this._pendingChangeSourcesByOwner.get(owner);
1176
+ if (!sources)
1177
+ return;
1178
+ sources.delete(source);
1179
+ if (!sources.size)
1180
+ this._pendingChangeSourcesByOwner.delete(owner);
1153
1181
  }
1154
1182
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogChangeGuardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1155
1183
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogChangeGuardService, providedIn: 'root' });
@@ -1161,6 +1189,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
1161
1189
  }]
1162
1190
  }] });
1163
1191
 
1192
+ /**
1193
+ * DI token that provides the component rendered inside the discard-confirmation
1194
+ * dialog.
1195
+ *
1196
+ * The discard dialog renders `<qd-dialog>`, `<qd-dialog>` opens the discard
1197
+ * dialog through this service, and the service opens the discard dialog
1198
+ * component — a compile-time template cycle. Binding the component through this
1199
+ * token (instead of the service importing it directly) breaks that cycle, so
1200
+ * the dialog can be bundled eagerly instead of lazy-loaded. This is the one
1201
+ * place a token is genuinely required.
1202
+ */
1203
+ const QD_DISCARD_CONFIRM_DIALOG_COMPONENT_TOKEN = new InjectionToken('QD_DISCARD_CONFIRM_DIALOG_COMPONENT_TOKEN');
1204
+
1164
1205
  const GENERIC_DEFAULTS = {
1165
1206
  title: { i18n: 'i18n.qd.dialog.confirm.title' },
1166
1207
  confirm: { i18n: 'i18n.qd.dialog.confirm.proceed' },
@@ -1174,6 +1215,7 @@ const CANCEL_DEFAULTS = {
1174
1215
  };
1175
1216
  class QdConfirmationDialogOpenerService {
1176
1217
  dialog = inject(Dialog);
1218
+ confirmDialogComponent = inject(QD_DISCARD_CONFIRM_DIALOG_COMPONENT_TOKEN);
1177
1219
  showConfirmDialog(config, testId = 'dialog-confirm') {
1178
1220
  const resolved = {
1179
1221
  title: config.title ?? GENERIC_DEFAULTS.title,
@@ -1181,14 +1223,12 @@ class QdConfirmationDialogOpenerService {
1181
1223
  confirm: config.confirm ?? GENERIC_DEFAULTS.confirm,
1182
1224
  cancel: config.cancel ?? GENERIC_DEFAULTS.cancel
1183
1225
  };
1184
- return from(import('./quadrel-enterprise-ui-framework-dialog-confirm.module-BQLiEzSo.mjs').then(m => m.QdDialogConfirmComponent)).pipe(switchMap(component => {
1185
- const dialogRef = this.open(component, {
1186
- title: resolved.title,
1187
- dialogSize: QdDialogSize.Small,
1188
- data: { ...resolved, testId }
1189
- });
1190
- return dialogRef.closed.pipe(map$1(result => !!result));
1191
- }));
1226
+ const dialogRef = this.open(this.confirmDialogComponent, {
1227
+ title: resolved.title,
1228
+ dialogSize: QdDialogSize.Small,
1229
+ data: { ...resolved, testId }
1230
+ });
1231
+ return dialogRef.closed.pipe(map$1(result => !!result));
1192
1232
  }
1193
1233
  showDiscardConfirmDialog(message, testId = 'cancel-confirmation') {
1194
1234
  return this.showConfirmDialog({
@@ -1458,6 +1498,15 @@ class QdDialogComponent {
1458
1498
  changeDetectorRef = inject(ChangeDetectorRef);
1459
1499
  dialogChangeGuard = inject(QdDialogChangeGuardService);
1460
1500
  dialogService = inject(QdDialogService);
1501
+ /**
1502
+ * A static test ID for integration tests can be set. <br />
1503
+ * The value for the HTML attribute [data-test-id].
1504
+ *
1505
+ * Every element of the dialog derives its own test ID from this root,
1506
+ * for example `<root>-close-button`. A nested dialog passes its own root
1507
+ * down, so a stacked dialog stays reachable without structural selectors.
1508
+ */
1509
+ testId = 'dialog';
1461
1510
  body;
1462
1511
  infoBanners;
1463
1512
  get hasSectionsClass() {
@@ -1468,6 +1517,7 @@ class QdDialogComponent {
1468
1517
  hasInfoBanner;
1469
1518
  _destroyed$ = new Subject();
1470
1519
  _pageDialogCanCloseFn = null;
1520
+ _isConfirmingClose = false;
1471
1521
  get isFullWidth() {
1472
1522
  return this.config.dialogSize === QdDialogSize.FullWidth;
1473
1523
  }
@@ -1509,10 +1559,14 @@ class QdDialogComponent {
1509
1559
  this.dialogRef.close();
1510
1560
  }
1511
1561
  confirmAndClose() {
1562
+ if (this._isConfirmingClose)
1563
+ return;
1564
+ this._isConfirmingClose = true;
1512
1565
  this.dialog
1513
1566
  .showDiscardConfirmDialog(this.config.cancel?.confirmationMessage, 'dialog-cancel-confirmation')
1514
1567
  .pipe(take(1))
1515
1568
  .subscribe(confirmed => {
1569
+ this._isConfirmingClose = false;
1516
1570
  if (!confirmed)
1517
1571
  return;
1518
1572
  this.config.cancel?.handler?.();
@@ -1533,7 +1587,7 @@ class QdDialogComponent {
1533
1587
  });
1534
1588
  }
1535
1589
  handleLegacyDialogClose() {
1536
- if (!this.dialogChangeGuard.hasPendingChanges)
1590
+ if (!this.dialogChangeGuard.hasPendingChanges(this.dialogRef))
1537
1591
  return this.runCancelHandlerAndClose();
1538
1592
  this.confirmAndClose();
1539
1593
  }
@@ -1550,12 +1604,15 @@ class QdDialogComponent {
1550
1604
  });
1551
1605
  }
1552
1606
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1553
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogComponent, isStandalone: false, selector: "qd-dialog", host: { properties: { "class.full-width": "isFullWidth", "class.has-sections": "this.hasSectionsClass" } }, providers: [QdDialogComponent], viewQueries: [{ propertyName: "body", first: true, predicate: ["body"], descendants: true }, { propertyName: "infoBanners", first: true, predicate: ["banners"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"!isFullWidth\" class=\"dialog-header\">\n <div class=\"title-container\">\n {{ config?.title?.i18n | translate }}\n </div>\n <button\n *ngIf=\"!config?.hideCloseHeaderButton\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n >\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n </button>\n</div>\n\n<button\n *ngIf=\"!config?.hideCloseHeaderButton && isFullWidth\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n>\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n</button>\n\n<div class=\"wrapper-body\">\n <div [class.has-dialog-info-banners]=\"hasInfoBanner\" #banners>\n <ng-content select=\"qd-page-info-banner\"></ng-content>\n </div>\n <div class=\"body\" [class.full-width]=\"isFullWidth\" #body>\n <ng-content></ng-content>\n </div>\n</div>\n\n<div class=\"qd-dialog-actions\">\n <button *ngIf=\"config.cancel\" qdButton qdButtonGhost color=\"secondary\" (click)=\"close()\">\n {{ config?.cancel?.label?.i18n ?? \"i18n.qd.dialog.action.cancel\" | translate }}\n </button>\n <button *ngIf=\"config.primary\" qdButton (click)=\"primaryActionClicked()\">\n {{ config?.primary?.label?.i18n ?? \"i18n.qd.dialog.action.primary\" | translate }}\n </button>\n <ng-content select=\"qd-dialog-action\"></ng-content>\n</div>\n", styles: ["qd-dialog{display:flex;width:100%;height:100%;flex-direction:column;background:#efefef}qd-dialog.full-width{position:relative;width:calc(100% - 3rem)!important;height:calc(100% - 3rem)!important;margin:1.5rem}qd-dialog.full-width .close{position:absolute;z-index:9999;top:1.25rem;right:1rem;color:#454545;cursor:pointer}.dialog-header{display:flex;height:3.125rem;flex-direction:row;align-items:center;justify-content:space-between;padding:.5rem 1.5rem;border-bottom:2px solid rgb(213,213,213);background:#fff}.dialog-header .title-container{display:block;color:#171717;font-weight:500}.dialog-header .close{cursor:pointer}.wrapper-body{overflow:auto;flex:1;background:#efefef}.wrapper-body .has-dialog-info-banners{padding:1rem 1.25rem .5rem;border-bottom:rgb(213,213,213) solid .0625rem;background-color:#fff}.wrapper-body .has-dialog-info-banners qd-page-info-banner:last-child{margin-bottom:0}.wrapper-body .body.full-width{height:100%}.wrapper-body .body:not(.full-width){max-height:80vh;padding:1rem 1.5rem}.wrapper-body .body:not(.full-width) qd-section{padding-right:1.5rem;padding-left:1.5rem}.wrapper-body .body:not(.full-width) qd-text-section{margin-right:0;margin-left:0}qd-dialog.has-sections .wrapper-body .body:not(.full-width){padding:0}.qd-dialog-actions{display:flex;justify-content:flex-end;padding:.5rem 1.5rem;border-top:2px solid rgb(213,213,213);background:#efefef;column-gap:.625rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdIconButtonComponent, selector: "button[qdIconButton], a[qdIconButton], button[qd-icon-button]", inputs: ["color", "data-test-id"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
1607
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogComponent, isStandalone: false, selector: "qd-dialog", inputs: { testId: ["data-test-id", "testId"] }, host: { properties: { "class.full-width": "isFullWidth", "class.has-sections": "this.hasSectionsClass" } }, providers: [QdDialogComponent], viewQueries: [{ propertyName: "body", first: true, predicate: ["body"], descendants: true }, { propertyName: "infoBanners", first: true, predicate: ["banners"], descendants: true }], ngImport: i0, template: "<div *ngIf=\"!isFullWidth\" class=\"dialog-header\">\n <div class=\"title-container\">\n {{ config?.title?.i18n | translate }}\n </div>\n <button\n *ngIf=\"!config?.hideCloseHeaderButton\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n [attr.aria-label]=\"'i18n.qd.dialog.action.close' | translate\"\n [data-test-id]=\"testId + '-close-button'\"\n >\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n </button>\n</div>\n\n<button\n *ngIf=\"!config?.hideCloseHeaderButton && isFullWidth\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n [attr.aria-label]=\"'i18n.qd.dialog.action.close' | translate\"\n [data-test-id]=\"testId + '-close-button'\"\n>\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n</button>\n\n<div class=\"wrapper-body\">\n <div [class.has-dialog-info-banners]=\"hasInfoBanner\" #banners>\n <ng-content select=\"qd-page-info-banner\"></ng-content>\n </div>\n <div class=\"body\" [class.full-width]=\"isFullWidth\" #body>\n <ng-content></ng-content>\n </div>\n</div>\n\n<div class=\"qd-dialog-actions\">\n <button\n *ngIf=\"config.cancel\"\n qdButton\n qdButtonGhost\n color=\"secondary\"\n (click)=\"close()\"\n [data-test-id]=\"testId + '-cancel-button'\"\n >\n {{ config?.cancel?.label?.i18n ?? \"i18n.qd.dialog.action.cancel\" | translate }}\n </button>\n <button *ngIf=\"config.primary\" qdButton (click)=\"primaryActionClicked()\" [data-test-id]=\"testId + '-primary-button'\">\n {{ config?.primary?.label?.i18n ?? \"i18n.qd.dialog.action.primary\" | translate }}\n </button>\n <ng-content select=\"qd-dialog-action\"></ng-content>\n</div>\n", styles: ["qd-dialog{display:flex;width:100%;height:100%;flex-direction:column;background:#efefef}qd-dialog.full-width{position:relative;width:calc(100% - 3rem)!important;height:calc(100% - 3rem)!important;margin:1.5rem}qd-dialog.full-width .close{position:absolute;z-index:9999;top:1.25rem;right:1rem;color:#454545;cursor:pointer}.dialog-header{display:flex;height:3.125rem;flex-direction:row;align-items:center;justify-content:space-between;padding:.5rem 1.5rem;border-bottom:2px solid rgb(213,213,213);background:#fff}.dialog-header .title-container{display:block;color:#171717;font-weight:500}.dialog-header .close{cursor:pointer}.wrapper-body{overflow:auto;flex:1;background:#efefef}.wrapper-body .has-dialog-info-banners{padding:1rem 1.25rem .5rem;border-bottom:rgb(213,213,213) solid .0625rem;background-color:#fff}.wrapper-body .has-dialog-info-banners qd-page-info-banner:last-child{margin-bottom:0}.wrapper-body .body.full-width{height:100%}.wrapper-body .body:not(.full-width){max-height:80vh;padding:1rem 1.5rem}.wrapper-body .body:not(.full-width) qd-section{padding-right:1.5rem;padding-left:1.5rem}.wrapper-body .body:not(.full-width) qd-text-section{margin-right:0;margin-left:0}qd-dialog.has-sections .wrapper-body .body:not(.full-width){padding:0}.qd-dialog-actions{display:flex;justify-content:flex-end;padding:.5rem 1.5rem;border-top:2px solid rgb(213,213,213);background:#efefef;column-gap:.625rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdIconButtonComponent, selector: "button[qdIconButton], a[qdIconButton], button[qd-icon-button]", inputs: ["color", "data-test-id"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
1554
1608
  }
1555
1609
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogComponent, decorators: [{
1556
1610
  type: Component,
1557
- args: [{ selector: 'qd-dialog', host: { '[class.full-width]': 'isFullWidth' }, encapsulation: ViewEncapsulation.None, providers: [QdDialogComponent], standalone: false, template: "<div *ngIf=\"!isFullWidth\" class=\"dialog-header\">\n <div class=\"title-container\">\n {{ config?.title?.i18n | translate }}\n </div>\n <button\n *ngIf=\"!config?.hideCloseHeaderButton\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n >\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n </button>\n</div>\n\n<button\n *ngIf=\"!config?.hideCloseHeaderButton && isFullWidth\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n>\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n</button>\n\n<div class=\"wrapper-body\">\n <div [class.has-dialog-info-banners]=\"hasInfoBanner\" #banners>\n <ng-content select=\"qd-page-info-banner\"></ng-content>\n </div>\n <div class=\"body\" [class.full-width]=\"isFullWidth\" #body>\n <ng-content></ng-content>\n </div>\n</div>\n\n<div class=\"qd-dialog-actions\">\n <button *ngIf=\"config.cancel\" qdButton qdButtonGhost color=\"secondary\" (click)=\"close()\">\n {{ config?.cancel?.label?.i18n ?? \"i18n.qd.dialog.action.cancel\" | translate }}\n </button>\n <button *ngIf=\"config.primary\" qdButton (click)=\"primaryActionClicked()\">\n {{ config?.primary?.label?.i18n ?? \"i18n.qd.dialog.action.primary\" | translate }}\n </button>\n <ng-content select=\"qd-dialog-action\"></ng-content>\n</div>\n", styles: ["qd-dialog{display:flex;width:100%;height:100%;flex-direction:column;background:#efefef}qd-dialog.full-width{position:relative;width:calc(100% - 3rem)!important;height:calc(100% - 3rem)!important;margin:1.5rem}qd-dialog.full-width .close{position:absolute;z-index:9999;top:1.25rem;right:1rem;color:#454545;cursor:pointer}.dialog-header{display:flex;height:3.125rem;flex-direction:row;align-items:center;justify-content:space-between;padding:.5rem 1.5rem;border-bottom:2px solid rgb(213,213,213);background:#fff}.dialog-header .title-container{display:block;color:#171717;font-weight:500}.dialog-header .close{cursor:pointer}.wrapper-body{overflow:auto;flex:1;background:#efefef}.wrapper-body .has-dialog-info-banners{padding:1rem 1.25rem .5rem;border-bottom:rgb(213,213,213) solid .0625rem;background-color:#fff}.wrapper-body .has-dialog-info-banners qd-page-info-banner:last-child{margin-bottom:0}.wrapper-body .body.full-width{height:100%}.wrapper-body .body:not(.full-width){max-height:80vh;padding:1rem 1.5rem}.wrapper-body .body:not(.full-width) qd-section{padding-right:1.5rem;padding-left:1.5rem}.wrapper-body .body:not(.full-width) qd-text-section{margin-right:0;margin-left:0}qd-dialog.has-sections .wrapper-body .body:not(.full-width){padding:0}.qd-dialog-actions{display:flex;justify-content:flex-end;padding:.5rem 1.5rem;border-top:2px solid rgb(213,213,213);background:#efefef;column-gap:.625rem}\n"] }]
1558
- }], propDecorators: { body: [{
1611
+ args: [{ selector: 'qd-dialog', host: { '[class.full-width]': 'isFullWidth' }, encapsulation: ViewEncapsulation.None, providers: [QdDialogComponent], standalone: false, template: "<div *ngIf=\"!isFullWidth\" class=\"dialog-header\">\n <div class=\"title-container\">\n {{ config?.title?.i18n | translate }}\n </div>\n <button\n *ngIf=\"!config?.hideCloseHeaderButton\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n [attr.aria-label]=\"'i18n.qd.dialog.action.close' | translate\"\n [data-test-id]=\"testId + '-close-button'\"\n >\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n </button>\n</div>\n\n<button\n *ngIf=\"!config?.hideCloseHeaderButton && isFullWidth\"\n qdIconButton\n class=\"close\"\n color=\"secondary\"\n tabindex=\"-1\"\n (click)=\"close()\"\n [attr.aria-label]=\"'i18n.qd.dialog.action.close' | translate\"\n [data-test-id]=\"testId + '-close-button'\"\n>\n <qd-icon icon=\"timesLargeLight\"></qd-icon>\n</button>\n\n<div class=\"wrapper-body\">\n <div [class.has-dialog-info-banners]=\"hasInfoBanner\" #banners>\n <ng-content select=\"qd-page-info-banner\"></ng-content>\n </div>\n <div class=\"body\" [class.full-width]=\"isFullWidth\" #body>\n <ng-content></ng-content>\n </div>\n</div>\n\n<div class=\"qd-dialog-actions\">\n <button\n *ngIf=\"config.cancel\"\n qdButton\n qdButtonGhost\n color=\"secondary\"\n (click)=\"close()\"\n [data-test-id]=\"testId + '-cancel-button'\"\n >\n {{ config?.cancel?.label?.i18n ?? \"i18n.qd.dialog.action.cancel\" | translate }}\n </button>\n <button *ngIf=\"config.primary\" qdButton (click)=\"primaryActionClicked()\" [data-test-id]=\"testId + '-primary-button'\">\n {{ config?.primary?.label?.i18n ?? \"i18n.qd.dialog.action.primary\" | translate }}\n </button>\n <ng-content select=\"qd-dialog-action\"></ng-content>\n</div>\n", styles: ["qd-dialog{display:flex;width:100%;height:100%;flex-direction:column;background:#efefef}qd-dialog.full-width{position:relative;width:calc(100% - 3rem)!important;height:calc(100% - 3rem)!important;margin:1.5rem}qd-dialog.full-width .close{position:absolute;z-index:9999;top:1.25rem;right:1rem;color:#454545;cursor:pointer}.dialog-header{display:flex;height:3.125rem;flex-direction:row;align-items:center;justify-content:space-between;padding:.5rem 1.5rem;border-bottom:2px solid rgb(213,213,213);background:#fff}.dialog-header .title-container{display:block;color:#171717;font-weight:500}.dialog-header .close{cursor:pointer}.wrapper-body{overflow:auto;flex:1;background:#efefef}.wrapper-body .has-dialog-info-banners{padding:1rem 1.25rem .5rem;border-bottom:rgb(213,213,213) solid .0625rem;background-color:#fff}.wrapper-body .has-dialog-info-banners qd-page-info-banner:last-child{margin-bottom:0}.wrapper-body .body.full-width{height:100%}.wrapper-body .body:not(.full-width){max-height:80vh;padding:1rem 1.5rem}.wrapper-body .body:not(.full-width) qd-section{padding-right:1.5rem;padding-left:1.5rem}.wrapper-body .body:not(.full-width) qd-text-section{margin-right:0;margin-left:0}qd-dialog.has-sections .wrapper-body .body:not(.full-width){padding:0}.qd-dialog-actions{display:flex;justify-content:flex-end;padding:.5rem 1.5rem;border-top:2px solid rgb(213,213,213);background:#efefef;column-gap:.625rem}\n"] }]
1612
+ }], propDecorators: { testId: [{
1613
+ type: Input,
1614
+ args: ['data-test-id']
1615
+ }], body: [{
1559
1616
  type: ViewChild,
1560
1617
  args: ['body']
1561
1618
  }], infoBanners: [{
@@ -1579,7 +1636,7 @@ class QdDialogAuthSessionEndComponent {
1579
1636
  this.dialogRef.close({ doLogoutViaIdentityBroker: true });
1580
1637
  }
1581
1638
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogAuthSessionEndComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1582
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogAuthSessionEndComponent, isStandalone: false, selector: "qd-dialog-auth-session-end", ngImport: i0, template: "<qd-dialog>\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ \"i18n.qd.authSupport.dialog.content\" | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button qdButton color=\"secondary\" (click)=\"backToEPortal()\">\n {{ \"i18n.qd.authSupport.dialog.action.backToEPortal\" | translate }}\n </button>\n <button qdButton (click)=\"reAuthenticate()\">\n {{ \"i18n.qd.authSupport.dialog.action.reAuthenticate\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
1639
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogAuthSessionEndComponent, isStandalone: false, selector: "qd-dialog-auth-session-end", ngImport: i0, template: "<qd-dialog>\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ \"i18n.qd.authSupport.dialog.content\" | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button qdButton color=\"secondary\" (click)=\"backToEPortal()\">\n {{ \"i18n.qd.authSupport.dialog.action.backToEPortal\" | translate }}\n </button>\n <button qdButton (click)=\"reAuthenticate()\">\n {{ \"i18n.qd.authSupport.dialog.action.reAuthenticate\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
1583
1640
  }
1584
1641
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogAuthSessionEndComponent, decorators: [{
1585
1642
  type: Component,
@@ -8593,6 +8650,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
8593
8650
  }]
8594
8651
  }] });
8595
8652
 
8653
+ class QdIconButtonModule {
8654
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdIconButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
8655
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdIconButtonModule, declarations: [QdIconButtonComponent], imports: [CommonModule], exports: [QdIconButtonComponent] });
8656
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdIconButtonModule, imports: [CommonModule] });
8657
+ }
8658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdIconButtonModule, decorators: [{
8659
+ type: NgModule,
8660
+ args: [{
8661
+ imports: [CommonModule],
8662
+ declarations: [QdIconButtonComponent],
8663
+ exports: [QdIconButtonComponent]
8664
+ }]
8665
+ }] });
8666
+
8596
8667
  class QdAutofocusService {
8597
8668
  _isAutofocusActivated = false;
8598
8669
  set isAutofocusActivated(hasInstance) {
@@ -9446,8 +9517,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
9446
9517
  args: ['class.qd-form-error']
9447
9518
  }] } });
9448
9519
 
9520
+ class QdKeyboardDetectionService {
9521
+ static KEYBOARD_ACTIVE_CLASS = 'qd-keyboard-active';
9522
+ document = inject(DOCUMENT);
9523
+ ngZone = inject(NgZone);
9524
+ onKeydown = () => {
9525
+ this.document?.documentElement?.classList.add(QdKeyboardDetectionService.KEYBOARD_ACTIVE_CLASS);
9526
+ };
9527
+ onPointerdown = () => {
9528
+ this.document?.documentElement?.classList.remove(QdKeyboardDetectionService.KEYBOARD_ACTIVE_CLASS);
9529
+ };
9530
+ constructor() {
9531
+ const root = this.document?.documentElement;
9532
+ if (!root)
9533
+ return;
9534
+ root.classList.add(QdKeyboardDetectionService.KEYBOARD_ACTIVE_CLASS);
9535
+ this.ngZone.runOutsideAngular(() => {
9536
+ this.document.addEventListener('keydown', this.onKeydown, true);
9537
+ this.document.addEventListener('pointerdown', this.onPointerdown, true);
9538
+ });
9539
+ }
9540
+ ngOnDestroy() {
9541
+ this.document?.removeEventListener('keydown', this.onKeydown, true);
9542
+ this.document?.removeEventListener('pointerdown', this.onPointerdown, true);
9543
+ }
9544
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdKeyboardDetectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
9545
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdKeyboardDetectionService, providedIn: 'root' });
9546
+ }
9547
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdKeyboardDetectionService, decorators: [{
9548
+ type: Injectable,
9549
+ args: [{ providedIn: 'root' }]
9550
+ }], ctorParameters: () => [] });
9551
+
9449
9552
  // @ts-strict-ignore
9450
9553
  class QdCheckboxComponent {
9554
+ keyboardDetection = inject(QdKeyboardDetectionService);
9451
9555
  // TODO: Refactor FormInput for better internal interface
9452
9556
  inputData;
9453
9557
  value;
@@ -9506,7 +9610,7 @@ class QdCheckboxComponent {
9506
9610
  useExisting: QdCheckboxComponent,
9507
9611
  multi: true
9508
9612
  }
9509
- ], ngImport: i0, template: "<label\n [for]=\"inputData.value\"\n [attr.data-test-id]=\"testId + '-label'\"\n [ngClass]=\"\n 'qd-checkbox__label' +\n (inputData.disabled || disabled ? ' qd-checkbox__label--disabled' : '') +\n (checked ? ' qd-checkbox__label--checked' : '')\n \"\n>\n <input\n type=\"checkbox\"\n qdVisuallyHidden\n [qdAutofocus]=\"hasAutofocus\"\n [id]=\"inputData.value\"\n [attr.data-test-id]=\"testId + '-input'\"\n [ngClass]=\"'qd-checkbox__checkbox'\"\n [name]=\"id\"\n [value]=\"inputData.value\"\n [disabled]=\"inputData.disabled || disabled\"\n (click)=\"handleClick(inputData.value, $event)\"\n [checked]=\"checked\"\n />\n\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"checked\"\n [icon]=\"'timesSquareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-checked'\"\n ></qd-icon>\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"!checked\"\n [icon]=\"'squareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-unchecked'\"\n ></qd-icon>\n\n <span [ngClass]=\"'qd-checkbox__caption qd-intersection-target'\">{{ inputData.i18n | translate }}</span>\n</label>\n", styles: [".qd-checkbox{display:flex;align-items:center;margin-right:1rem}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled){border:.0625rem solid rgb(180,180,180);margin-right:0;margin-bottom:.75rem;background:#fff}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label{width:100%;padding-left:.75rem;line-height:2.25rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label .qd-checkbox__indicator.qd-icon{margin-right:.75rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label--disabled .qd-checkbox__caption{color:#d5d5d5}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{margin-right:.75rem;color:#171717;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{padding:.375rem 0;line-height:1.25rem}}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled):last-child{margin-bottom:0}}.qd-checkbox:last-child{margin-right:0}.qd-checkbox .qd-checkbox__label{position:relative;display:flex;max-width:100%;align-items:center;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400}.qd-checkbox .qd-checkbox__label .qd-checkbox__indicator{margin-right:.375rem;color:#b4b4b4;font-size:1.25rem}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus{color:#171717}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover .qd-checkbox__indicator,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus .qd-checkbox__indicator{color:#757575}.qd-checkbox .qd-checkbox__label--checked{color:#171717}.qd-checkbox .qd-checkbox__label--checked .qd-checkbox__indicator{color:#069}.qd-checkbox .qd-checkbox__label--disabled{color:#d5d5d5;cursor:default}.qd-checkbox .qd-checkbox__label--disabled .qd-checkbox__indicator{color:#d5d5d5}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "directive", type: QdVisuallyHiddenDirective, selector: "[qdVisuallyHidden]" }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
9613
+ ], ngImport: i0, template: "<label\n [for]=\"inputData.value + id\"\n [attr.data-test-id]=\"testId + '-label'\"\n [ngClass]=\"\n 'qd-checkbox__label' +\n (inputData.disabled || disabled ? ' qd-checkbox__label--disabled' : '') +\n (checked ? ' qd-checkbox__label--checked' : '')\n \"\n>\n <input\n type=\"checkbox\"\n tabindex=\"0\"\n qdVisuallyHidden\n [qdAutofocus]=\"hasAutofocus\"\n [id]=\"inputData.value + id\"\n [attr.data-test-id]=\"testId + '-input'\"\n [ngClass]=\"'qd-checkbox__checkbox'\"\n [name]=\"id\"\n [value]=\"inputData.value\"\n [disabled]=\"inputData.disabled || disabled\"\n (click)=\"handleClick(inputData.value, $event)\"\n [checked]=\"checked\"\n />\n\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"checked\"\n [icon]=\"'timesSquareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-checked'\"\n ></qd-icon>\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"!checked\"\n [icon]=\"'squareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-unchecked'\"\n ></qd-icon>\n\n <span [ngClass]=\"'qd-checkbox__caption qd-intersection-target'\">{{ inputData.i18n | translate }}</span>\n</label>\n", styles: [".qd-checkbox{display:flex;align-items:center;margin-right:1rem}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled){border:.0625rem solid rgb(180,180,180);margin-right:0;margin-bottom:.75rem;background:#fff}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label{width:100%;padding-left:.75rem;line-height:2.25rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label .qd-checkbox__indicator.qd-icon{margin-right:.75rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label--disabled .qd-checkbox__caption{color:#d5d5d5}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{margin-right:.75rem;color:#171717;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{padding:.375rem 0;line-height:1.25rem}}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled):last-child{margin-bottom:0}}.qd-checkbox:last-child{margin-right:0}.qd-checkbox .qd-checkbox__label{position:relative;display:flex;max-width:100%;align-items:center;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400}.qd-checkbox .qd-checkbox__label .qd-checkbox__indicator{position:relative;margin-right:.375rem;color:#b4b4b4;font-size:1.25rem}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus{color:#171717}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover .qd-checkbox__indicator,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus .qd-checkbox__indicator{color:#757575}.qd-checkbox .qd-checkbox__label--checked{color:#171717}.qd-checkbox .qd-checkbox__label--checked .qd-checkbox__indicator{color:#069}.qd-checkbox .qd-checkbox__label--disabled{color:#d5d5d5;cursor:default}.qd-checkbox .qd-checkbox__label--disabled .qd-checkbox__indicator{color:#d5d5d5}.qd-keyboard-active .qd-checkbox__checkbox:focus~.qd-checkbox__indicator:after{position:absolute;top:50%;left:50%;width:1.25rem;height:1.25rem;content:\"\";outline:.125rem solid rgb(23,23,23);outline-offset:0;transform:translate(-50%,-50%)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "directive", type: QdVisuallyHiddenDirective, selector: "[qdVisuallyHidden]" }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
9510
9614
  }
9511
9615
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCheckboxComponent, decorators: [{
9512
9616
  type: Component,
@@ -9516,7 +9620,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
9516
9620
  useExisting: QdCheckboxComponent,
9517
9621
  multi: true
9518
9622
  }
9519
- ], encapsulation: ViewEncapsulation.None, host: { class: 'qd-checkbox' }, standalone: false, template: "<label\n [for]=\"inputData.value\"\n [attr.data-test-id]=\"testId + '-label'\"\n [ngClass]=\"\n 'qd-checkbox__label' +\n (inputData.disabled || disabled ? ' qd-checkbox__label--disabled' : '') +\n (checked ? ' qd-checkbox__label--checked' : '')\n \"\n>\n <input\n type=\"checkbox\"\n qdVisuallyHidden\n [qdAutofocus]=\"hasAutofocus\"\n [id]=\"inputData.value\"\n [attr.data-test-id]=\"testId + '-input'\"\n [ngClass]=\"'qd-checkbox__checkbox'\"\n [name]=\"id\"\n [value]=\"inputData.value\"\n [disabled]=\"inputData.disabled || disabled\"\n (click)=\"handleClick(inputData.value, $event)\"\n [checked]=\"checked\"\n />\n\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"checked\"\n [icon]=\"'timesSquareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-checked'\"\n ></qd-icon>\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"!checked\"\n [icon]=\"'squareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-unchecked'\"\n ></qd-icon>\n\n <span [ngClass]=\"'qd-checkbox__caption qd-intersection-target'\">{{ inputData.i18n | translate }}</span>\n</label>\n", styles: [".qd-checkbox{display:flex;align-items:center;margin-right:1rem}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled){border:.0625rem solid rgb(180,180,180);margin-right:0;margin-bottom:.75rem;background:#fff}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label{width:100%;padding-left:.75rem;line-height:2.25rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label .qd-checkbox__indicator.qd-icon{margin-right:.75rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label--disabled .qd-checkbox__caption{color:#d5d5d5}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{margin-right:.75rem;color:#171717;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{padding:.375rem 0;line-height:1.25rem}}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled):last-child{margin-bottom:0}}.qd-checkbox:last-child{margin-right:0}.qd-checkbox .qd-checkbox__label{position:relative;display:flex;max-width:100%;align-items:center;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400}.qd-checkbox .qd-checkbox__label .qd-checkbox__indicator{margin-right:.375rem;color:#b4b4b4;font-size:1.25rem}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus{color:#171717}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover .qd-checkbox__indicator,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus .qd-checkbox__indicator{color:#757575}.qd-checkbox .qd-checkbox__label--checked{color:#171717}.qd-checkbox .qd-checkbox__label--checked .qd-checkbox__indicator{color:#069}.qd-checkbox .qd-checkbox__label--disabled{color:#d5d5d5;cursor:default}.qd-checkbox .qd-checkbox__label--disabled .qd-checkbox__indicator{color:#d5d5d5}\n"] }]
9623
+ ], encapsulation: ViewEncapsulation.None, host: { class: 'qd-checkbox' }, standalone: false, template: "<label\n [for]=\"inputData.value + id\"\n [attr.data-test-id]=\"testId + '-label'\"\n [ngClass]=\"\n 'qd-checkbox__label' +\n (inputData.disabled || disabled ? ' qd-checkbox__label--disabled' : '') +\n (checked ? ' qd-checkbox__label--checked' : '')\n \"\n>\n <input\n type=\"checkbox\"\n tabindex=\"0\"\n qdVisuallyHidden\n [qdAutofocus]=\"hasAutofocus\"\n [id]=\"inputData.value + id\"\n [attr.data-test-id]=\"testId + '-input'\"\n [ngClass]=\"'qd-checkbox__checkbox'\"\n [name]=\"id\"\n [value]=\"inputData.value\"\n [disabled]=\"inputData.disabled || disabled\"\n (click)=\"handleClick(inputData.value, $event)\"\n [checked]=\"checked\"\n />\n\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"checked\"\n [icon]=\"'timesSquareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-checked'\"\n ></qd-icon>\n <qd-icon\n [ngClass]=\"'qd-checkbox__indicator'\"\n *ngIf=\"!checked\"\n [icon]=\"'squareSolid'\"\n [attr.data-test-id]=\"testId + '-indicator-unchecked'\"\n ></qd-icon>\n\n <span [ngClass]=\"'qd-checkbox__caption qd-intersection-target'\">{{ inputData.i18n | translate }}</span>\n</label>\n", styles: [".qd-checkbox{display:flex;align-items:center;margin-right:1rem}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled){border:.0625rem solid rgb(180,180,180);margin-right:0;margin-bottom:.75rem;background:#fff}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label{width:100%;padding-left:.75rem;line-height:2.25rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label .qd-checkbox__indicator.qd-icon{margin-right:.75rem}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__label--disabled .qd-checkbox__caption{color:#d5d5d5}.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{margin-right:.75rem;color:#171717;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled) .qd-checkbox__caption{padding:.375rem 0;line-height:1.25rem}}@media (max-width: 959.98px){.qd-checkbox:not(.qd-rwd-disabled):last-child{margin-bottom:0}}.qd-checkbox:last-child{margin-right:0}.qd-checkbox .qd-checkbox__label{position:relative;display:flex;max-width:100%;align-items:center;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400}.qd-checkbox .qd-checkbox__label .qd-checkbox__indicator{position:relative;margin-right:.375rem;color:#b4b4b4;font-size:1.25rem}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus{color:#171717}.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):hover .qd-checkbox__indicator,.qd-checkbox .qd-checkbox__label:not(.qd-checkbox__label--checked,.qd-checkbox__label--disabled):focus .qd-checkbox__indicator{color:#757575}.qd-checkbox .qd-checkbox__label--checked{color:#171717}.qd-checkbox .qd-checkbox__label--checked .qd-checkbox__indicator{color:#069}.qd-checkbox .qd-checkbox__label--disabled{color:#d5d5d5;cursor:default}.qd-checkbox .qd-checkbox__label--disabled .qd-checkbox__indicator{color:#d5d5d5}.qd-keyboard-active .qd-checkbox__checkbox:focus~.qd-checkbox__indicator:after{position:absolute;top:50%;left:50%;width:1.25rem;height:1.25rem;content:\"\";outline:.125rem solid rgb(23,23,23);outline-offset:0;transform:translate(-50%,-50%)}\n"] }]
9520
9624
  }], ctorParameters: () => [], propDecorators: { inputData: [{
9521
9625
  type: Input
9522
9626
  }], value: [{
@@ -9588,14 +9692,10 @@ class QdCheckboxesService {
9588
9692
  this.checkboxesListForView = this.checkboxesList;
9589
9693
  }
9590
9694
  updateCheckboxesListForView(value) {
9591
- this.checkboxesListForView = this.checkboxesListForView.map(checkbox => {
9592
- if (checkbox.value === value) {
9593
- return { ...checkbox, ...{ checked: !checkbox.checked }, ...{ index: checkbox.index } };
9594
- }
9595
- else {
9596
- return checkbox;
9597
- }
9598
- });
9695
+ const checkbox = this.checkboxesListForView.find(option => option.value === value);
9696
+ if (checkbox) {
9697
+ checkbox.checked = !checkbox.checked;
9698
+ }
9599
9699
  }
9600
9700
  getCheckboxesListForView() {
9601
9701
  return this.checkboxesListForView;
@@ -9838,6 +9938,9 @@ class QdCheckboxesComponent {
9838
9938
  setDisabledState(disabled) {
9839
9939
  this.disabled = disabled;
9840
9940
  }
9941
+ getCheckboxId(_index, checkbox) {
9942
+ return checkbox.index;
9943
+ }
9841
9944
  handleClick(checkbox) {
9842
9945
  if (checkbox.disabled || this.config.disabled)
9843
9946
  return;
@@ -9918,7 +10021,7 @@ class QdCheckboxesComponent {
9918
10021
  },
9919
10022
  QdCheckboxesService,
9920
10023
  QdFormsActionEmitterService
9921
- ], viewQueries: [{ propertyName: "checkboxes", predicate: QdCheckboxComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<div class=\"qd-checkboxes__input-section\" *ngIf=\"!readonly && !viewonly\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n ></qd-filter-form-items>\n\n <div class=\"qd-checkboxes__checkbox-section\">\n <qd-checkbox\n *ngFor=\"let checkbox of checkboxesListForView\"\n [inputData]=\"checkbox\"\n [value]=\"checkboxesValues[checkbox.index]\"\n [disabled]=\"checkbox.disabled || disabled\"\n [hasAutofocus]=\"hasAutofocus && checkbox.index === 0\"\n (valueChange)=\"handleClick(checkbox)\"\n [data-test-id]=\"testId + '-checkbox-' + checkbox.index\"\n ></qd-checkbox>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"selectedValuesTranslated\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"selectedValuesTranslated\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-checkboxes{display:block;margin-bottom:.75rem}@media (max-width: 959.98px){.qd-checkboxes{height:initial}}.qd-checkboxes .qd-checkboxes__input-section{display:block;flex-direction:column;margin-bottom:.3125rem}.qd-checkboxes .qd-checkboxes__checkbox-section{display:flex;min-height:2.25rem;flex-direction:row}@media (max-width: 959.98px){.qd-checkboxes .qd-checkboxes__checkbox-section{height:initial;flex-direction:column}}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section{display:flex;flex-direction:column}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section .qd-checkbox:not(:last-child){margin-bottom:.5rem}.qd-checkboxes.qd-checkboxes-disabled{pointer-events:none}.qd-checkboxes-readonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--readonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--readonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}.qd-checkboxes-viewonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdCheckboxComponent, selector: "qd-checkbox", inputs: ["inputData", "value", "data-test-id", "disabled", "hasAutofocus"], outputs: ["valueChange"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }], encapsulation: i0.ViewEncapsulation.None });
10024
+ ], viewQueries: [{ propertyName: "checkboxes", predicate: QdCheckboxComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<div class=\"qd-checkboxes__input-section\" *ngIf=\"!readonly && !viewonly\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n ></qd-filter-form-items>\n\n <div class=\"qd-checkboxes__checkbox-section\">\n <qd-checkbox\n *ngFor=\"let checkbox of checkboxesListForView; trackBy: getCheckboxId\"\n [inputData]=\"checkbox\"\n [value]=\"checkboxesValues[checkbox.index]\"\n [disabled]=\"checkbox.disabled || disabled\"\n [hasAutofocus]=\"hasAutofocus && checkbox.index === 0\"\n (valueChange)=\"handleClick(checkbox)\"\n [data-test-id]=\"testId + '-checkbox-' + checkbox.index\"\n ></qd-checkbox>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"selectedValuesTranslated\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"selectedValuesTranslated\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-checkboxes{display:block;margin-bottom:.75rem}@media (max-width: 959.98px){.qd-checkboxes{height:initial}}.qd-checkboxes .qd-checkboxes__input-section{display:block;flex-direction:column;margin-bottom:.3125rem}.qd-checkboxes .qd-checkboxes__checkbox-section{display:flex;min-height:2.25rem;flex-direction:row}@media (max-width: 959.98px){.qd-checkboxes .qd-checkboxes__checkbox-section{height:initial;flex-direction:column}}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section{display:flex;flex-direction:column}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section .qd-checkbox:not(:last-child){margin-bottom:.5rem}.qd-checkboxes.qd-checkboxes-disabled{pointer-events:none}.qd-checkboxes-readonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--readonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--readonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}.qd-checkboxes-viewonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdCheckboxComponent, selector: "qd-checkbox", inputs: ["inputData", "value", "data-test-id", "disabled", "hasAutofocus"], outputs: ["valueChange"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }], encapsulation: i0.ViewEncapsulation.None });
9922
10025
  }
9923
10026
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCheckboxesComponent, decorators: [{
9924
10027
  type: Component,
@@ -9930,7 +10033,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
9930
10033
  },
9931
10034
  QdCheckboxesService,
9932
10035
  QdFormsActionEmitterService
9933
- ], encapsulation: ViewEncapsulation.None, host: { class: 'qd-checkboxes' }, standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<div class=\"qd-checkboxes__input-section\" *ngIf=\"!readonly && !viewonly\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n ></qd-filter-form-items>\n\n <div class=\"qd-checkboxes__checkbox-section\">\n <qd-checkbox\n *ngFor=\"let checkbox of checkboxesListForView\"\n [inputData]=\"checkbox\"\n [value]=\"checkboxesValues[checkbox.index]\"\n [disabled]=\"checkbox.disabled || disabled\"\n [hasAutofocus]=\"hasAutofocus && checkbox.index === 0\"\n (valueChange)=\"handleClick(checkbox)\"\n [data-test-id]=\"testId + '-checkbox-' + checkbox.index\"\n ></qd-checkbox>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"selectedValuesTranslated\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"selectedValuesTranslated\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-checkboxes{display:block;margin-bottom:.75rem}@media (max-width: 959.98px){.qd-checkboxes{height:initial}}.qd-checkboxes .qd-checkboxes__input-section{display:block;flex-direction:column;margin-bottom:.3125rem}.qd-checkboxes .qd-checkboxes__checkbox-section{display:flex;min-height:2.25rem;flex-direction:row}@media (max-width: 959.98px){.qd-checkboxes .qd-checkboxes__checkbox-section{height:initial;flex-direction:column}}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section{display:flex;flex-direction:column}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section .qd-checkbox:not(:last-child){margin-bottom:.5rem}.qd-checkboxes.qd-checkboxes-disabled{pointer-events:none}.qd-checkboxes-readonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--readonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--readonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}.qd-checkboxes-viewonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}\n"] }]
10036
+ ], encapsulation: ViewEncapsulation.None, host: { class: 'qd-checkboxes' }, standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<div class=\"qd-checkboxes__input-section\" *ngIf=\"!readonly && !viewonly\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n ></qd-filter-form-items>\n\n <div class=\"qd-checkboxes__checkbox-section\">\n <qd-checkbox\n *ngFor=\"let checkbox of checkboxesListForView; trackBy: getCheckboxId\"\n [inputData]=\"checkbox\"\n [value]=\"checkboxesValues[checkbox.index]\"\n [disabled]=\"checkbox.disabled || disabled\"\n [hasAutofocus]=\"hasAutofocus && checkbox.index === 0\"\n (valueChange)=\"handleClick(checkbox)\"\n [data-test-id]=\"testId + '-checkbox-' + checkbox.index\"\n ></qd-checkbox>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"selectedValuesTranslated\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"selectedValuesTranslated\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-checkboxes{display:block;margin-bottom:.75rem}@media (max-width: 959.98px){.qd-checkboxes{height:initial}}.qd-checkboxes .qd-checkboxes__input-section{display:block;flex-direction:column;margin-bottom:.3125rem}.qd-checkboxes .qd-checkboxes__checkbox-section{display:flex;min-height:2.25rem;flex-direction:row}@media (max-width: 959.98px){.qd-checkboxes .qd-checkboxes__checkbox-section{height:initial;flex-direction:column}}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section{display:flex;flex-direction:column}.qd-checkboxes.qd-checkboxes-vertical .qd-checkboxes__checkbox-section .qd-checkbox:not(:last-child){margin-bottom:.5rem}.qd-checkboxes.qd-checkboxes-disabled{pointer-events:none}.qd-checkboxes-readonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--readonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--readonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--readonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}.qd-checkboxes-viewonly .qd-checkboxes__input-section{font-size:.875rem;line-height:2.25rem}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section{color:#069;cursor:pointer}.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:hover,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:active,.qd-checkboxes--viewonly-action .qd-checkboxes__input-section:focus{text-decoration:underline}\n"] }]
9934
10037
  }], ctorParameters: () => [], propDecorators: { formControlName: [{
9935
10038
  type: Input
9936
10039
  }], values: [{
@@ -10875,9 +10978,18 @@ class QdDropdownComponent {
10875
10978
  */
10876
10979
  valueChange = new EventEmitter();
10877
10980
  /**
10878
- * Emits event when the value has changed. Note: Emits on keyup.
10981
+ * Emits when the dropdown is opened.
10982
+ *
10983
+ * @deprecated The name no longer reflects the behavior (it fires on every open, not just on a
10984
+ * click). Use {@link dropdownOpened} instead. Will be removed in v22.
10879
10985
  */
10880
10986
  enterClick = new EventEmitter();
10987
+ /**
10988
+ * Emits whenever the dropdown opens or closes, regardless of input modality
10989
+ * (mouse click or keyboard Enter/Space). The boolean payload is the open state:
10990
+ * `true` when opened, `false` when closed.
10991
+ */
10992
+ dropdownOpened = new EventEmitter();
10881
10993
  /**
10882
10994
  * Emits event when the hint is clicked/tapped. `hintAction` must be set to `true` for this.
10883
10995
  */
@@ -11030,11 +11142,17 @@ class QdDropdownComponent {
11030
11142
  }
11031
11143
  onOpenDropdown() {
11032
11144
  this.isOpen = true;
11145
+ // Emitted whenever the trigger opens — by mouse click or by keyboard (Enter/Space) — so the
11146
+ // open event fires consistently regardless of input modality. `enterClick` is kept for
11147
+ // backward compatibility (deprecated, removed in v22); `dropdownOpened` is the replacement.
11148
+ this.enterClick.emit();
11149
+ this.dropdownOpened.emit(true);
11033
11150
  this.loadOptionsForCurrentConfig();
11034
11151
  this.dropdownOptions?.onOpen();
11035
11152
  }
11036
11153
  onDropdownClosed() {
11037
11154
  this.isOpen = false;
11155
+ this.dropdownOpened.emit(false);
11038
11156
  if (this.control && this._value != null) {
11039
11157
  this._onChange(this._value);
11040
11158
  this._onTouch();
@@ -11094,7 +11212,7 @@ class QdDropdownComponent {
11094
11212
  });
11095
11213
  }
11096
11214
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11097
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDropdownComponent, isStandalone: false, selector: "qd-dropdown", inputs: { value: "value", id: "id", formControlName: "formControlName", config: "config", testId: ["data-test-id", "testId"], qdPopoverMaxHeight: "qdPopoverMaxHeight", dense: "dense" }, outputs: { valueChange: "valueChange", enterClick: "enterClick", clickHint: "clickHint", clickReadonly: "clickReadonly", clickViewonly: "clickViewonly", optionsResolved: "optionsResolved" }, host: { properties: { "class.qd-dropdown-readonly": "this.readonly", "class.qd-dropdown--readonly-action": "this.readonlyAction", "class.qd-dropdown-viewonly": "this.viewonly", "class.qd-dropdown--viewonly-action": "this.viewonlyAction", "class.qd-form-hint-action": "this.hintAction", "class.qd-dropdown--hint-action": "this.hintAction", "class.qd-form-disabled": "this.disabled", "class.qd-dropdown-disabled": "this.disabled", "class.dense": "this.dense", "class.qd-dropdown-open": "this.isOpen", "class.qd-form-error": "this.hasError", "class.qd-dropdown-error": "this.hasError", "class.qd-dropdown-selected": "this.isSelected" }, classAttribute: "qd-dropdown" }, providers: [
11215
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDropdownComponent, isStandalone: false, selector: "qd-dropdown", inputs: { value: "value", id: "id", formControlName: "formControlName", config: "config", testId: ["data-test-id", "testId"], qdPopoverMaxHeight: "qdPopoverMaxHeight", dense: "dense" }, outputs: { valueChange: "valueChange", enterClick: "enterClick", dropdownOpened: "dropdownOpened", clickHint: "clickHint", clickReadonly: "clickReadonly", clickViewonly: "clickViewonly", optionsResolved: "optionsResolved" }, host: { properties: { "class.qd-dropdown-readonly": "this.readonly", "class.qd-dropdown--readonly-action": "this.readonlyAction", "class.qd-dropdown-viewonly": "this.viewonly", "class.qd-dropdown--viewonly-action": "this.viewonlyAction", "class.qd-form-hint-action": "this.hintAction", "class.qd-dropdown--hint-action": "this.hintAction", "class.qd-form-disabled": "this.disabled", "class.qd-dropdown-disabled": "this.disabled", "class.dense": "this.dense", "class.qd-dropdown-open": "this.isOpen", "class.qd-form-error": "this.hasError", "class.qd-dropdown-error": "this.hasError", "class.qd-dropdown-selected": "this.isSelected" }, classAttribute: "qd-dropdown" }, providers: [
11098
11216
  QdFormsActionEmitterService,
11099
11217
  QdFormOptionsResolverRegistry,
11100
11218
  QdFormKeyboardService,
@@ -11108,7 +11226,7 @@ class QdDropdownComponent {
11108
11226
  provide: QD_FOCUSABLE_TOKEN,
11109
11227
  useExisting: QdDropdownComponent
11110
11228
  }
11111
- ], viewQueries: [{ propertyName: "dropdownOptions", first: true, predicate: QdDropdownOptionsComponent, descendants: true }, { propertyName: "dropdownDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }, { propertyName: "box", first: true, predicate: ["box"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<div class=\"qd-dropdown__wrapper\">\n <div\n class=\"qd-dropdown__box\"\n tabindex=\"0\"\n *ngIf=\"!readonly && !viewonly && hasOptions\"\n [qdPopoverOnClick]=\"dropdownMenu\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverDisabled]=\"disabled\"\n [qdPopoverMaxHeight]=\"qdPopoverMaxHeight\"\n [qdPopoverAutoSize]=\"{ width: true }\"\n [qdPopoverEnableKeyControl]=\"true\"\n [qdPopoverFlipIntoViewport]=\"true\"\n (opened)=\"onOpenDropdown()\"\n (closed)=\"onDropdownClosed()\"\n (click)=\"enterClick.emit()\"\n qdPopoverPlacement=\"bottom-start\"\n >\n {{ (selectedOption?.i18n | translate) || placeholder }}\n\n <div class=\"qd-dropdown-suffix\">\n <qd-icon *ngIf=\"hasError\" class=\"qd-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[selectedOption]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[selectedOption]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #dropdownMenu>\n <qd-dropdown-options\n [filter]=\"filter\"\n [filterText]=\"filterText\"\n [testId]=\"testId\"\n [id]=\"id\"\n (filterChange)=\"handleFilterChange($event)\"\n (optionClick)=\"handleClick($event)\"\n ></qd-dropdown-options>\n</ng-template>\n", styles: [".qd-dropdown__wrapper{position:relative;margin-bottom:.375rem}.qd-dropdown__wrapper.dense{margin-bottom:0}.qd-dropdown__wrapper .qd-dropdown__box{display:flex;overflow:hidden;width:100%;height:2.25rem;justify-content:space-between;padding:0 .75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.25rem;background:#fff;color:#fff;font-size:.875rem;font-weight:400;line-height:2.25rem;text-overflow:ellipsis;white-space:nowrap}.qd-dropdown__wrapper .qd-dropdown__box.dense{margin-bottom:0}.qd-dropdown-selected .qd-dropdown__wrapper .qd-dropdown__box{color:#171717}.qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown__wrapper .qd-dropdown__box:active,.qd-dropdown__wrapper .qd-dropdown__box:hover{padding:0 .6875rem;border-width:.125rem;border-color:#171717;line-height:2.125rem;outline:0}.qd-dropdown__wrapper .qd-dropdown__box:active{color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:hover:after{border-top-color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:after{position:absolute;z-index:5;top:1rem;right:.75rem;width:0;height:0;border-top:.3125rem solid rgb(180,180,180);border-right:.3125rem solid rgba(255,255,255,0);border-left:.3125rem solid rgba(255,255,255,0);content:\"\";pointer-events:none}.qd-dropdown__wrapper .qd-dropdown__box .qd-dropdown-suffix{position:relative;z-index:8;margin-right:1rem;background:#fff}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box{background:#f5f5f5;color:#979797}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:active{padding:0 .75rem;border:.0625rem solid rgb(180,180,180);line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly{color:#069;cursor:pointer}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:hover,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:active,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:focus{color:#069;text-decoration:underline}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly{color:#069;cursor:pointer}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:hover,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:active,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:focus{color:#069;text-decoration:underline}.qd-dropdown-error .qd-dropdown__box{padding:0 .75rem;border:.0625rem solid rgb(199,0,35);line-height:2.25rem}.qd-dropdown-error .qd-dropdown__box:focus,.qd-dropdown-error .qd-dropdown__box:hover,.qd-dropdown-error .qd-dropdown__box:active{padding:0 .6875rem;border:.125rem solid rgb(199,0,35);line-height:2.125rem}.qd-dropdown-error .qd-dropdown__box .qd-error-icon{color:#c70023}.qd-dropdown{display:block;height:4.5rem;margin-bottom:.75rem}.qd-dropdown.dense{width:100%;height:auto;margin-bottom:0}.qd-dropdown.dense .qd-dropdown__wrapper,.qd-dropdown.dense .qd-dropdown__box{margin-bottom:0}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box{padding:0 .6875rem;border-width:.125rem;border-color:#069;line-height:2.125rem}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box:after{border-top:none;border-bottom:.3125rem solid rgb(23,23,23)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdDropdownOptionsComponent, selector: "qd-dropdown-options", inputs: ["filter", "filterText", "testId", "id"], outputs: ["filterChange", "optionClick"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
11229
+ ], viewQueries: [{ propertyName: "dropdownOptions", first: true, predicate: QdDropdownOptionsComponent, descendants: true }, { propertyName: "dropdownDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }, { propertyName: "box", first: true, predicate: ["box"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<div class=\"qd-dropdown__wrapper\">\n <div\n class=\"qd-dropdown__box\"\n tabindex=\"0\"\n *ngIf=\"!readonly && !viewonly && hasOptions\"\n [qdPopoverOnClick]=\"dropdownMenu\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverDisabled]=\"disabled\"\n [qdPopoverMaxHeight]=\"qdPopoverMaxHeight\"\n [qdPopoverAutoSize]=\"{ width: true }\"\n [qdPopoverEnableKeyControl]=\"true\"\n [qdPopoverFlipIntoViewport]=\"true\"\n (opened)=\"onOpenDropdown()\"\n (closed)=\"onDropdownClosed()\"\n qdPopoverPlacement=\"bottom-start\"\n >\n {{ (selectedOption?.i18n | translate) || placeholder }}\n\n <div class=\"qd-dropdown-suffix\">\n <qd-icon *ngIf=\"hasError\" class=\"qd-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[selectedOption]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[selectedOption]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #dropdownMenu>\n <qd-dropdown-options\n [filter]=\"filter\"\n [filterText]=\"filterText\"\n [testId]=\"testId\"\n [id]=\"id\"\n (filterChange)=\"handleFilterChange($event)\"\n (optionClick)=\"handleClick($event)\"\n ></qd-dropdown-options>\n</ng-template>\n", styles: [".qd-dropdown__wrapper{position:relative;margin-bottom:.375rem}.qd-dropdown__wrapper.dense{margin-bottom:0}.qd-dropdown__wrapper .qd-dropdown__box{display:flex;overflow:hidden;width:100%;height:2.25rem;justify-content:space-between;padding:0 .75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.25rem;background:#fff;color:#fff;font-size:.875rem;font-weight:400;line-height:2.25rem;text-overflow:ellipsis;white-space:nowrap}.qd-dropdown__wrapper .qd-dropdown__box.dense{margin-bottom:0}.qd-dropdown-selected .qd-dropdown__wrapper .qd-dropdown__box{color:#171717}.qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown__wrapper .qd-dropdown__box:active,.qd-dropdown__wrapper .qd-dropdown__box:hover{padding:0 .6875rem;border-width:.125rem;border-color:#171717;line-height:2.125rem;outline:0}.qd-dropdown__wrapper .qd-dropdown__box:active{color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:hover:after{border-top-color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:after{position:absolute;z-index:5;top:1rem;right:.75rem;width:0;height:0;border-top:.3125rem solid rgb(180,180,180);border-right:.3125rem solid rgba(255,255,255,0);border-left:.3125rem solid rgba(255,255,255,0);content:\"\";pointer-events:none}.qd-dropdown__wrapper .qd-dropdown__box .qd-dropdown-suffix{position:relative;z-index:8;margin-right:1rem;background:#fff}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box{background:#f5f5f5;color:#979797}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:active{padding:0 .75rem;border:.0625rem solid rgb(180,180,180);line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly{color:#069;cursor:pointer}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:hover,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:active,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:focus{color:#069;text-decoration:underline}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly{color:#069;cursor:pointer}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:hover,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:active,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:focus{color:#069;text-decoration:underline}.qd-dropdown-error .qd-dropdown__box{padding:0 .75rem;border:.0625rem solid rgb(199,0,35);line-height:2.25rem}.qd-dropdown-error .qd-dropdown__box:focus,.qd-dropdown-error .qd-dropdown__box:hover,.qd-dropdown-error .qd-dropdown__box:active{padding:0 .6875rem;border:.125rem solid rgb(199,0,35);line-height:2.125rem}.qd-dropdown-error .qd-dropdown__box .qd-error-icon{color:#c70023}.qd-dropdown{display:block;height:4.5rem;margin-bottom:.75rem}.qd-dropdown.dense{width:100%;height:auto;margin-bottom:0}.qd-dropdown.dense .qd-dropdown__wrapper,.qd-dropdown.dense .qd-dropdown__box{margin-bottom:0}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box{padding:0 .6875rem;border-width:.125rem;border-color:#069;line-height:2.125rem}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box:after{border-top:none;border-bottom:.3125rem solid rgb(23,23,23)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdDropdownOptionsComponent, selector: "qd-dropdown-options", inputs: ["filter", "filterText", "testId", "id"], outputs: ["filterChange", "optionClick"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
11112
11230
  }
11113
11231
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDropdownComponent, decorators: [{
11114
11232
  type: Component,
@@ -11126,7 +11244,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
11126
11244
  provide: QD_FOCUSABLE_TOKEN,
11127
11245
  useExisting: QdDropdownComponent
11128
11246
  }
11129
- ], encapsulation: ViewEncapsulation.None, host: { class: 'qd-dropdown' }, standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<div class=\"qd-dropdown__wrapper\">\n <div\n class=\"qd-dropdown__box\"\n tabindex=\"0\"\n *ngIf=\"!readonly && !viewonly && hasOptions\"\n [qdPopoverOnClick]=\"dropdownMenu\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverDisabled]=\"disabled\"\n [qdPopoverMaxHeight]=\"qdPopoverMaxHeight\"\n [qdPopoverAutoSize]=\"{ width: true }\"\n [qdPopoverEnableKeyControl]=\"true\"\n [qdPopoverFlipIntoViewport]=\"true\"\n (opened)=\"onOpenDropdown()\"\n (closed)=\"onDropdownClosed()\"\n (click)=\"enterClick.emit()\"\n qdPopoverPlacement=\"bottom-start\"\n >\n {{ (selectedOption?.i18n | translate) || placeholder }}\n\n <div class=\"qd-dropdown-suffix\">\n <qd-icon *ngIf=\"hasError\" class=\"qd-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[selectedOption]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[selectedOption]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #dropdownMenu>\n <qd-dropdown-options\n [filter]=\"filter\"\n [filterText]=\"filterText\"\n [testId]=\"testId\"\n [id]=\"id\"\n (filterChange)=\"handleFilterChange($event)\"\n (optionClick)=\"handleClick($event)\"\n ></qd-dropdown-options>\n</ng-template>\n", styles: [".qd-dropdown__wrapper{position:relative;margin-bottom:.375rem}.qd-dropdown__wrapper.dense{margin-bottom:0}.qd-dropdown__wrapper .qd-dropdown__box{display:flex;overflow:hidden;width:100%;height:2.25rem;justify-content:space-between;padding:0 .75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.25rem;background:#fff;color:#fff;font-size:.875rem;font-weight:400;line-height:2.25rem;text-overflow:ellipsis;white-space:nowrap}.qd-dropdown__wrapper .qd-dropdown__box.dense{margin-bottom:0}.qd-dropdown-selected .qd-dropdown__wrapper .qd-dropdown__box{color:#171717}.qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown__wrapper .qd-dropdown__box:active,.qd-dropdown__wrapper .qd-dropdown__box:hover{padding:0 .6875rem;border-width:.125rem;border-color:#171717;line-height:2.125rem;outline:0}.qd-dropdown__wrapper .qd-dropdown__box:active{color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:hover:after{border-top-color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:after{position:absolute;z-index:5;top:1rem;right:.75rem;width:0;height:0;border-top:.3125rem solid rgb(180,180,180);border-right:.3125rem solid rgba(255,255,255,0);border-left:.3125rem solid rgba(255,255,255,0);content:\"\";pointer-events:none}.qd-dropdown__wrapper .qd-dropdown__box .qd-dropdown-suffix{position:relative;z-index:8;margin-right:1rem;background:#fff}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box{background:#f5f5f5;color:#979797}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:active{padding:0 .75rem;border:.0625rem solid rgb(180,180,180);line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly{color:#069;cursor:pointer}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:hover,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:active,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:focus{color:#069;text-decoration:underline}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly{color:#069;cursor:pointer}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:hover,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:active,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:focus{color:#069;text-decoration:underline}.qd-dropdown-error .qd-dropdown__box{padding:0 .75rem;border:.0625rem solid rgb(199,0,35);line-height:2.25rem}.qd-dropdown-error .qd-dropdown__box:focus,.qd-dropdown-error .qd-dropdown__box:hover,.qd-dropdown-error .qd-dropdown__box:active{padding:0 .6875rem;border:.125rem solid rgb(199,0,35);line-height:2.125rem}.qd-dropdown-error .qd-dropdown__box .qd-error-icon{color:#c70023}.qd-dropdown{display:block;height:4.5rem;margin-bottom:.75rem}.qd-dropdown.dense{width:100%;height:auto;margin-bottom:0}.qd-dropdown.dense .qd-dropdown__wrapper,.qd-dropdown.dense .qd-dropdown__box{margin-bottom:0}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box{padding:0 .6875rem;border-width:.125rem;border-color:#069;line-height:2.125rem}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box:after{border-top:none;border-bottom:.3125rem solid rgb(23,23,23)}\n"] }]
11247
+ ], encapsulation: ViewEncapsulation.None, host: { class: 'qd-dropdown' }, standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<div class=\"qd-dropdown__wrapper\">\n <div\n class=\"qd-dropdown__box\"\n tabindex=\"0\"\n *ngIf=\"!readonly && !viewonly && hasOptions\"\n [qdPopoverOnClick]=\"dropdownMenu\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverDisabled]=\"disabled\"\n [qdPopoverMaxHeight]=\"qdPopoverMaxHeight\"\n [qdPopoverAutoSize]=\"{ width: true }\"\n [qdPopoverEnableKeyControl]=\"true\"\n [qdPopoverFlipIntoViewport]=\"true\"\n (opened)=\"onOpenDropdown()\"\n (closed)=\"onDropdownClosed()\"\n qdPopoverPlacement=\"bottom-start\"\n >\n {{ (selectedOption?.i18n | translate) || placeholder }}\n\n <div class=\"qd-dropdown-suffix\">\n <qd-icon *ngIf=\"hasError\" class=\"qd-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n </div>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[selectedOption]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[selectedOption]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #dropdownMenu>\n <qd-dropdown-options\n [filter]=\"filter\"\n [filterText]=\"filterText\"\n [testId]=\"testId\"\n [id]=\"id\"\n (filterChange)=\"handleFilterChange($event)\"\n (optionClick)=\"handleClick($event)\"\n ></qd-dropdown-options>\n</ng-template>\n", styles: [".qd-dropdown__wrapper{position:relative;margin-bottom:.375rem}.qd-dropdown__wrapper.dense{margin-bottom:0}.qd-dropdown__wrapper .qd-dropdown__box{display:flex;overflow:hidden;width:100%;height:2.25rem;justify-content:space-between;padding:0 .75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.25rem;background:#fff;color:#fff;font-size:.875rem;font-weight:400;line-height:2.25rem;text-overflow:ellipsis;white-space:nowrap}.qd-dropdown__wrapper .qd-dropdown__box.dense{margin-bottom:0}.qd-dropdown-selected .qd-dropdown__wrapper .qd-dropdown__box{color:#171717}.qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown__wrapper .qd-dropdown__box:active,.qd-dropdown__wrapper .qd-dropdown__box:hover{padding:0 .6875rem;border-width:.125rem;border-color:#171717;line-height:2.125rem;outline:0}.qd-dropdown__wrapper .qd-dropdown__box:active{color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:hover:after{border-top-color:#b4b4b4}.qd-dropdown__wrapper .qd-dropdown__box:after{position:absolute;z-index:5;top:1rem;right:.75rem;width:0;height:0;border-top:.3125rem solid rgb(180,180,180);border-right:.3125rem solid rgba(255,255,255,0);border-left:.3125rem solid rgba(255,255,255,0);content:\"\";pointer-events:none}.qd-dropdown__wrapper .qd-dropdown__box .qd-dropdown-suffix{position:relative;z-index:8;margin-right:1rem;background:#fff}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box{background:#f5f5f5;color:#979797}.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-disabled .qd-dropdown__wrapper .qd-dropdown__box:active{padding:0 .75rem;border:.0625rem solid rgb(180,180,180);line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-readonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box{height:inherit;padding:0;border:none;line-height:2.25rem}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:focus,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:hover,.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:active{color:inherit}.qd-dropdown-viewonly .qd-dropdown__wrapper .qd-dropdown__box:after{display:none}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly{color:#069;cursor:pointer}.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:hover,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:active,.qd-dropdown--readonly-action .qd-dropdown__box.qd-dropdown__box--readonly:focus{color:#069;text-decoration:underline}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly{color:#069;cursor:pointer}.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:hover,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:active,.qd-dropdown--viewonly-action .qd-dropdown__box.qd-dropdown__box--viewonly:focus{color:#069;text-decoration:underline}.qd-dropdown-error .qd-dropdown__box{padding:0 .75rem;border:.0625rem solid rgb(199,0,35);line-height:2.25rem}.qd-dropdown-error .qd-dropdown__box:focus,.qd-dropdown-error .qd-dropdown__box:hover,.qd-dropdown-error .qd-dropdown__box:active{padding:0 .6875rem;border:.125rem solid rgb(199,0,35);line-height:2.125rem}.qd-dropdown-error .qd-dropdown__box .qd-error-icon{color:#c70023}.qd-dropdown{display:block;height:4.5rem;margin-bottom:.75rem}.qd-dropdown.dense{width:100%;height:auto;margin-bottom:0}.qd-dropdown.dense .qd-dropdown__wrapper,.qd-dropdown.dense .qd-dropdown__box{margin-bottom:0}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box{padding:0 .6875rem;border-width:.125rem;border-color:#069;line-height:2.125rem}.qd-dropdown-open .qd-dropdown__wrapper .qd-dropdown__box:after{border-top:none;border-bottom:.3125rem solid rgb(23,23,23)}\n"] }]
11130
11248
  }], ctorParameters: () => [], propDecorators: { value: [{
11131
11249
  type: Input
11132
11250
  }], id: [{
@@ -11144,6 +11262,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
11144
11262
  type: Output
11145
11263
  }], enterClick: [{
11146
11264
  type: Output
11265
+ }], dropdownOpened: [{
11266
+ type: Output
11147
11267
  }], clickHint: [{
11148
11268
  type: Output
11149
11269
  }], clickReadonly: [{
@@ -11768,41 +11888,47 @@ class QdInputComponent {
11768
11888
  if (input?.validity?.badInput)
11769
11889
  return;
11770
11890
  const value = event.target.value;
11771
- if (this.inputType === 'number' && value && !this.numberInputService.isValidNumber(value)) {
11772
- this.control?.setErrors({
11773
- ...this.control.errors,
11774
- invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11775
- });
11891
+ if (this.inputType === 'number' && value && !this.handleNumberInput(value))
11776
11892
  return;
11777
- }
11778
- if (this.inputType === 'number' && value) {
11779
- const valueWithoutGroups = value.split(this.numberInputService.groupSeparator).join('');
11780
- const filtered = this.numberInputService.filterValue(valueWithoutGroups);
11781
- const hasInvalidChars = filtered !== valueWithoutGroups;
11782
- if (hasInvalidChars) {
11783
- this._value = { ...this._value, value: filtered };
11784
- if (this.control) {
11785
- this.control.setErrors({
11786
- ...this.control.errors,
11787
- invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11788
- });
11789
- }
11790
- this._isUserTyped = true;
11791
- this._onTouch();
11792
- this.emitValue();
11793
- return;
11794
- }
11795
- if (this.control?.errors?.['invalidCharacters']) {
11796
- const remainingErrors = Object.fromEntries(Object.entries(this.control.errors).filter(([key]) => key !== 'invalidCharacters'));
11797
- this.control.setErrors(Object.keys(remainingErrors).length ? remainingErrors : null);
11798
- }
11799
- }
11800
11893
  this._isUserTyped = true;
11801
11894
  this._value = { ...this._value, value };
11895
+ this._displayValue = String(value ?? '');
11802
11896
  this.loadOptionsForTypedValue(value);
11803
11897
  this.emitValue();
11804
11898
  this._onTouch();
11805
11899
  }
11900
+ handleNumberInput(value) {
11901
+ if (!this.numberInputService.isValidNumber(value)) {
11902
+ this.setInvalidCharactersError();
11903
+ return false;
11904
+ }
11905
+ const valueWithoutGroups = value.split(this.numberInputService.groupSeparator).join('');
11906
+ const filtered = this.numberInputService.filterValue(valueWithoutGroups);
11907
+ if (filtered !== valueWithoutGroups) {
11908
+ this._value = { ...this._value, value: filtered };
11909
+ this.setInvalidCharactersError();
11910
+ this._isUserTyped = true;
11911
+ this._onTouch();
11912
+ this.emitValue();
11913
+ return false;
11914
+ }
11915
+ this.clearInvalidCharactersError();
11916
+ return true;
11917
+ }
11918
+ setInvalidCharactersError() {
11919
+ if (!this.control)
11920
+ return;
11921
+ this.control.setErrors({
11922
+ ...this.control.errors,
11923
+ invalidCharacters: this.numberInputService.invalidCharactersErrorKey
11924
+ });
11925
+ }
11926
+ clearInvalidCharactersError() {
11927
+ if (!this.control?.errors?.['invalidCharacters'])
11928
+ return;
11929
+ const remainingErrors = Object.fromEntries(Object.entries(this.control.errors).filter(([key]) => key !== 'invalidCharacters'));
11930
+ this.control.setErrors(Object.keys(remainingErrors).length ? remainingErrors : null);
11931
+ }
11806
11932
  handleOptionSelected(option) {
11807
11933
  this._value = { ...this._value, value: option.i18n };
11808
11934
  this.popover?.close();
@@ -12183,6 +12309,7 @@ class QdDatepickerComponent {
12183
12309
  displayedDateTime = '';
12184
12310
  label;
12185
12311
  hint;
12312
+ hasAutofocus = false;
12186
12313
  readonlyAction = false;
12187
12314
  viewonlyAction = false;
12188
12315
  language = DEFAULT_LANGUAGE;
@@ -12364,6 +12491,7 @@ class QdDatepickerComponent {
12364
12491
  updateConfiguration() {
12365
12492
  this.label = getLabel(this.config);
12366
12493
  this.hint = getHint(this.config);
12494
+ this.hasAutofocus = getHasAutofocus(this.config);
12367
12495
  this.readonly = getReadonly(this.config, this.readonly);
12368
12496
  this.viewonly = getViewonly(this.config, this.viewonly);
12369
12497
  this.hintAction = getHintAction(this.config);
@@ -12472,7 +12600,7 @@ class QdDatepickerComponent {
12472
12600
  useValue: true
12473
12601
  },
12474
12602
  QdFormsActionEmitterService
12475
- ], viewQueries: [{ propertyName: "popover", first: true, predicate: ["qdPopoverOnClick"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<qd-input\n *ngIf=\"!readonly && !viewonly\"\n [value]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n (valueChange)=\"config?.timePicker ? handleUpdatedDateTime($event) : handleUpdatedDate($event)\"\n [config]=\"{ disabled, readonly, viewonly, placeholder: config?.placeholder }\"\n [isError]=\"hasError\"\n>\n <button\n type=\"button\"\n class=\"datepicker-toggle\"\n qdIconButton\n [qdPopoverOnClick]=\"disabled ? null : calendar\"\n [qdPopoverMaxWidth]=\"332\"\n qdPopoverCloseStrategy=\"onOutsideClick\"\n #qdPopoverOnClick=\"qdPopoverOnClick\"\n >\n <qd-icon [icon]=\"'calendar'\"></qd-icon>\n </button>\n</qd-input>\n\n<ng-template #calendar>\n <qd-calendar\n [selectedDate]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n [language]=\"language\"\n [disabledDates]=\"config?.disabledDates\"\n (selectedChange)=\"handleUpdatedDate($event)\"\n ></qd-calendar>\n <qd-dropdown\n class=\"timepicker-dropdown\"\n *ngIf=\"timePicker\"\n [value]=\"displayedTime\"\n (valueChange)=\"handleUpdatedTime($event)\"\n [config]=\"timePicker\"\n [qdPopoverMaxHeight]=\"300\"\n ></qd-dropdown>\n</ng-template>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[displayedDate]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[displayedDate]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: ["qd-datepicker{position:relative;display:block;width:100%;margin-bottom:.75rem}qd-datepicker .calendar{padding:1rem}qd-datepicker .calendar mat-calendar{display:block}qd-datepicker .datepicker-toggle{background-color:unset;color:inherit}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input{height:2.25rem;margin-bottom:.375rem!important}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-label,qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-hint{display:none}qd-datepicker .qd-form-disabled .datepicker-toggle{color:#979797;cursor:default}qd-datepicker.qd-datepicker-calendar-only{margin-bottom:0}qd-datepicker.qd-datepicker-calendar-only qd-input{margin:0}qd-datepicker.qd-datepicker-calendar-only .qd-form-label,qd-datepicker.qd-datepicker-calendar-only .qd-form-hint,qd-datepicker.qd-datepicker-calendar-only .qd-input-input input{display:none}qd-datepicker.qd-datepicker-calendar-only .qd-input-input{height:initial!important;padding:0!important;border:none!important;margin:0!important}qd-datepicker.qd-datepicker-calendar-only .qd-input-suffix{margin-left:0!important}.timepicker-dropdown{margin:.75rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdCalendarComponent, selector: "qd-calendar", inputs: ["selectedDate", "language", "disabledDates"], outputs: ["selectedChange"] }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }], encapsulation: i0.ViewEncapsulation.None });
12603
+ ], viewQueries: [{ propertyName: "popover", first: true, predicate: ["qdPopoverOnClick"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<qd-input\n *ngIf=\"!readonly && !viewonly\"\n [value]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n (valueChange)=\"config?.timePicker ? handleUpdatedDateTime($event) : handleUpdatedDate($event)\"\n [config]=\"{\n disabled,\n readonly,\n viewonly,\n placeholder: config?.placeholder,\n hasAutofocus\n }\"\n [isError]=\"hasError\"\n>\n <button\n type=\"button\"\n class=\"datepicker-toggle\"\n qdIconButton\n [qdPopoverOnClick]=\"disabled ? null : calendar\"\n [qdPopoverMaxWidth]=\"332\"\n qdPopoverCloseStrategy=\"onOutsideClick\"\n #qdPopoverOnClick=\"qdPopoverOnClick\"\n >\n <qd-icon [icon]=\"'calendar'\"></qd-icon>\n </button>\n</qd-input>\n\n<ng-template #calendar>\n <qd-calendar\n [selectedDate]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n [language]=\"language\"\n [disabledDates]=\"config?.disabledDates\"\n (selectedChange)=\"handleUpdatedDate($event)\"\n ></qd-calendar>\n <qd-dropdown\n class=\"timepicker-dropdown\"\n *ngIf=\"timePicker\"\n [value]=\"displayedTime\"\n (valueChange)=\"handleUpdatedTime($event)\"\n [config]=\"timePicker\"\n [qdPopoverMaxHeight]=\"300\"\n ></qd-dropdown>\n</ng-template>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[displayedDate]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[displayedDate]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: ["qd-datepicker{position:relative;display:block;width:100%;margin-bottom:.75rem}qd-datepicker .calendar{padding:1rem}qd-datepicker button.datepicker-toggle{width:1.75rem;height:1.75rem;justify-content:center;padding:.25rem;margin-right:.125rem}qd-datepicker button.datepicker-toggle .qd-icon{display:flex;align-items:center;justify-content:center;font-size:1.125rem;line-height:1}qd-datepicker button.datepicker-toggle:focus-visible{background:#fff0;box-shadow:inset 0 0 0 .125rem #069;outline:none}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input{height:2.25rem;margin-bottom:.375rem!important}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-label,qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-hint{display:none}qd-datepicker .qd-form-disabled .datepicker-toggle{color:#979797;cursor:default}qd-datepicker.qd-datepicker-calendar-only{margin-bottom:0}qd-datepicker.qd-datepicker-calendar-only qd-input{margin:0}qd-datepicker.qd-datepicker-calendar-only .qd-form-label,qd-datepicker.qd-datepicker-calendar-only .qd-form-hint,qd-datepicker.qd-datepicker-calendar-only .qd-input-input input{display:none}qd-datepicker.qd-datepicker-calendar-only .qd-input-input{height:initial!important;padding:0!important;border:none!important;margin:0!important}qd-datepicker.qd-datepicker-calendar-only .qd-input-suffix{margin-left:0!important}.timepicker-dropdown{margin:.75rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconButtonComponent, selector: "button[qdIconButton], a[qdIconButton], button[qd-icon-button]", inputs: ["color", "data-test-id"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdCalendarComponent, selector: "qd-calendar", inputs: ["selectedDate", "language", "disabledDates"], outputs: ["selectedChange"] }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "dropdownOpened", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }], encapsulation: i0.ViewEncapsulation.None });
12476
12604
  }
12477
12605
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDatepickerComponent, decorators: [{
12478
12606
  type: Component,
@@ -12487,7 +12615,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
12487
12615
  useValue: true
12488
12616
  },
12489
12617
  QdFormsActionEmitterService
12490
- ], standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<qd-input\n *ngIf=\"!readonly && !viewonly\"\n [value]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n (valueChange)=\"config?.timePicker ? handleUpdatedDateTime($event) : handleUpdatedDate($event)\"\n [config]=\"{ disabled, readonly, viewonly, placeholder: config?.placeholder }\"\n [isError]=\"hasError\"\n>\n <button\n type=\"button\"\n class=\"datepicker-toggle\"\n qdIconButton\n [qdPopoverOnClick]=\"disabled ? null : calendar\"\n [qdPopoverMaxWidth]=\"332\"\n qdPopoverCloseStrategy=\"onOutsideClick\"\n #qdPopoverOnClick=\"qdPopoverOnClick\"\n >\n <qd-icon [icon]=\"'calendar'\"></qd-icon>\n </button>\n</qd-input>\n\n<ng-template #calendar>\n <qd-calendar\n [selectedDate]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n [language]=\"language\"\n [disabledDates]=\"config?.disabledDates\"\n (selectedChange)=\"handleUpdatedDate($event)\"\n ></qd-calendar>\n <qd-dropdown\n class=\"timepicker-dropdown\"\n *ngIf=\"timePicker\"\n [value]=\"displayedTime\"\n (valueChange)=\"handleUpdatedTime($event)\"\n [config]=\"timePicker\"\n [qdPopoverMaxHeight]=\"300\"\n ></qd-dropdown>\n</ng-template>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[displayedDate]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[displayedDate]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: ["qd-datepicker{position:relative;display:block;width:100%;margin-bottom:.75rem}qd-datepicker .calendar{padding:1rem}qd-datepicker .calendar mat-calendar{display:block}qd-datepicker .datepicker-toggle{background-color:unset;color:inherit}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input{height:2.25rem;margin-bottom:.375rem!important}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-label,qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-hint{display:none}qd-datepicker .qd-form-disabled .datepicker-toggle{color:#979797;cursor:default}qd-datepicker.qd-datepicker-calendar-only{margin-bottom:0}qd-datepicker.qd-datepicker-calendar-only qd-input{margin:0}qd-datepicker.qd-datepicker-calendar-only .qd-form-label,qd-datepicker.qd-datepicker-calendar-only .qd-form-hint,qd-datepicker.qd-datepicker-calendar-only .qd-input-input input{display:none}qd-datepicker.qd-datepicker-calendar-only .qd-input-input{height:initial!important;padding:0!important;border:none!important;margin:0!important}qd-datepicker.qd-datepicker-calendar-only .qd-input-suffix{margin-left:0!important}.timepicker-dropdown{margin:.75rem}\n"] }]
12618
+ ], standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<qd-input\n *ngIf=\"!readonly && !viewonly\"\n [value]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n (valueChange)=\"config?.timePicker ? handleUpdatedDateTime($event) : handleUpdatedDate($event)\"\n [config]=\"{\n disabled,\n readonly,\n viewonly,\n placeholder: config?.placeholder,\n hasAutofocus\n }\"\n [isError]=\"hasError\"\n>\n <button\n type=\"button\"\n class=\"datepicker-toggle\"\n qdIconButton\n [qdPopoverOnClick]=\"disabled ? null : calendar\"\n [qdPopoverMaxWidth]=\"332\"\n qdPopoverCloseStrategy=\"onOutsideClick\"\n #qdPopoverOnClick=\"qdPopoverOnClick\"\n >\n <qd-icon [icon]=\"'calendar'\"></qd-icon>\n </button>\n</qd-input>\n\n<ng-template #calendar>\n <qd-calendar\n [selectedDate]=\"config?.timePicker && displayedDateTime ? displayedDateTime : displayedDate\"\n [language]=\"language\"\n [disabledDates]=\"config?.disabledDates\"\n (selectedChange)=\"handleUpdatedDate($event)\"\n ></qd-calendar>\n <qd-dropdown\n class=\"timepicker-dropdown\"\n *ngIf=\"timePicker\"\n [value]=\"displayedTime\"\n (valueChange)=\"handleUpdatedTime($event)\"\n [config]=\"timePicker\"\n [qdPopoverMaxHeight]=\"300\"\n ></qd-dropdown>\n</ng-template>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hint || hasError)\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"[displayedDate]\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"[displayedDate]\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: ["qd-datepicker{position:relative;display:block;width:100%;margin-bottom:.75rem}qd-datepicker .calendar{padding:1rem}qd-datepicker button.datepicker-toggle{width:1.75rem;height:1.75rem;justify-content:center;padding:.25rem;margin-right:.125rem}qd-datepicker button.datepicker-toggle .qd-icon{display:flex;align-items:center;justify-content:center;font-size:1.125rem;line-height:1}qd-datepicker button.datepicker-toggle:focus-visible{background:#fff0;box-shadow:inset 0 0 0 .125rem #069;outline:none}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input{height:2.25rem;margin-bottom:.375rem!important}qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-label,qd-datepicker:not(.qd-datepicker-calendar-only) qd-input .qd-form-hint{display:none}qd-datepicker .qd-form-disabled .datepicker-toggle{color:#979797;cursor:default}qd-datepicker.qd-datepicker-calendar-only{margin-bottom:0}qd-datepicker.qd-datepicker-calendar-only qd-input{margin:0}qd-datepicker.qd-datepicker-calendar-only .qd-form-label,qd-datepicker.qd-datepicker-calendar-only .qd-form-hint,qd-datepicker.qd-datepicker-calendar-only .qd-input-input input{display:none}qd-datepicker.qd-datepicker-calendar-only .qd-input-input{height:initial!important;padding:0!important;border:none!important;margin:0!important}qd-datepicker.qd-datepicker-calendar-only .qd-input-suffix{margin-left:0!important}.timepicker-dropdown{margin:.75rem}\n"] }]
12491
12619
  }], propDecorators: { config: [{
12492
12620
  type: Input
12493
12621
  }], formControlName: [{
@@ -15086,6 +15214,7 @@ class QdRadioButtonsComponent {
15086
15214
  controlContainer = inject(ControlContainer, { optional: true, host: true, skipSelf: true });
15087
15215
  ngZone = inject(NgZone);
15088
15216
  eventBrokerService = inject(QdEventBrokerService, { optional: true });
15217
+ keyboardDetection = inject(QdKeyboardDetectionService);
15089
15218
  /**
15090
15219
  * The current form item value, if you are working with Model Binding.
15091
15220
  *
@@ -15155,9 +15284,15 @@ class QdRadioButtonsComponent {
15155
15284
  get activeOptionAsList() {
15156
15285
  return this.options.filter(o => o.value === this.value);
15157
15286
  }
15287
+ get tabStopValue() {
15288
+ const enabled = (this.radioButtonsListForView ?? []).filter(option => !(option.disabled || this.disabled));
15289
+ const selected = this.value ? enabled.find(option => option.value === this.value) : undefined;
15290
+ return (selected ?? enabled[0])?.value ?? null;
15291
+ }
15158
15292
  label;
15159
15293
  align;
15160
15294
  filter = false;
15295
+ hasAutofocus = false;
15161
15296
  options;
15162
15297
  isLabelDisabled;
15163
15298
  id;
@@ -15226,6 +15361,7 @@ class QdRadioButtonsComponent {
15226
15361
  this.align = getAlign(this.config);
15227
15362
  this.label = getLabel(this.config);
15228
15363
  this.filter = getFilter$1(this.config);
15364
+ this.hasAutofocus = getHasAutofocus(this.config);
15229
15365
  this.options = getOptions(this.config);
15230
15366
  this.initRadioButtonList();
15231
15367
  this.disabled = getDisabled(this.config) || !!this.control?.disabled;
@@ -15267,7 +15403,7 @@ class QdRadioButtonsComponent {
15267
15403
  },
15268
15404
  QdRadioButtonsService,
15269
15405
  QdFormsActionEmitterService
15270
- ], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n></qd-filter-form-items>\n\n<div class=\"qd-radio-buttons__button-section\" *ngIf=\"!readonly && !viewonly\">\n <label\n *ngFor=\"let option of radioButtonsListForView; trackBy: getOptionId\"\n [for]=\"option.value + id\"\n [ngClass]=\"\n 'qd-radio-buttons__label' +\n (option.disabled || disabled ? ' qd-radio-buttons__label--disabled' : '') +\n (option.value === value ? ' qd-radio-buttons__label--checked' : '')\n \"\n [attr.data-test-id]=\"testId + '-label'\"\n >\n <input\n type=\"radio\"\n qdVisuallyHidden\n [id]=\"option.value + id\"\n [ngClass]=\"'qd-radio-buttons__radio-button'\"\n [name]=\"id\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled || disabled\"\n (click)=\"handleClick(option.value)\"\n [checked]=\"option.value === value\"\n [attr.data-test-id]=\"testId + '-input-' + option.i18n\"\n />\n\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value === value\" [icon]=\"'circleRadio'\"></qd-icon>\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value !== value\" [icon]=\"'circleSolid'\"></qd-icon>\n\n <span [ngClass]=\"'qd-radio-buttons__caption qd-intersection-target'\">{{ option.i18n | translate }}</span>\n </label>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"activeOptionAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"activeOptionAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-radio-buttons{display:block;flex-direction:column;margin-bottom:.75rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__button-section{display:flex;min-height:2.25rem;flex-wrap:wrap;align-items:center;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__label:not(:last-child) .qd-radio-buttons__caption{padding-right:1rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section{display:flex;flex-direction:column;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section .qd-radio-buttons__caption{flex:auto}.qd-radio-buttons .qd-radio-buttons__label{display:flex;max-width:100%;padding:.625rem 0;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400;line-height:1rem}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__indicator{padding:0 .375rem 0 0;color:#b4b4b4;font-size:1.25rem}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus{color:#171717}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover .qd-radio-buttons__indicator,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus .qd-radio-buttons__indicator{color:#757575}.qd-radio-buttons .qd-radio-buttons__label--checked{color:#171717}.qd-radio-buttons .qd-radio-buttons__label--checked .qd-radio-buttons__indicator{color:#069}.qd-radio-buttons .qd-radio-buttons__label--disabled{color:#d5d5d5;cursor:default}.qd-radio-buttons .qd-radio-buttons__label--disabled .qd-radio-buttons__indicator{color:#d5d5d5}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__caption{padding:0}.qd-radio-buttons__input-section{margin-bottom:.375rem}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__button-section{flex-direction:column}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label{width:100%;padding-top:.0625rem;padding-bottom:.0625rem;padding-left:.75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.75rem;background:#fff}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding-right:.75rem!important;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding:.375rem .375rem .375rem 0!important;line-height:1.25rem}}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label:last-child{margin-bottom:0}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__indicator{display:flex;align-items:center}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: QdVisuallyHiddenDirective, selector: "[qdVisuallyHidden]" }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
15406
+ ], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n></qd-filter-form-items>\n\n<div class=\"qd-radio-buttons__button-section\" *ngIf=\"!readonly && !viewonly\">\n <label\n *ngFor=\"let option of radioButtonsListForView; let i = index; trackBy: getOptionId\"\n [for]=\"option.value + id\"\n [ngClass]=\"\n 'qd-radio-buttons__label' +\n (option.disabled || disabled ? ' qd-radio-buttons__label--disabled' : '') +\n (option.value === value ? ' qd-radio-buttons__label--checked' : '')\n \"\n [attr.data-test-id]=\"testId + '-label'\"\n >\n <input\n type=\"radio\"\n qdVisuallyHidden\n [qdAutofocus]=\"hasAutofocus && i === 0\"\n [id]=\"option.value + id\"\n [ngClass]=\"'qd-radio-buttons__radio-button'\"\n [attr.tabindex]=\"option.value === tabStopValue ? 0 : -1\"\n [name]=\"id\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled || disabled\"\n (change)=\"handleClick(option.value)\"\n [checked]=\"option.value === value\"\n [attr.data-test-id]=\"testId + '-input-' + option.i18n\"\n />\n\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value === value\" [icon]=\"'circleRadio'\"></qd-icon>\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value !== value\" [icon]=\"'circleSolid'\"></qd-icon>\n\n <span [ngClass]=\"'qd-radio-buttons__caption qd-intersection-target'\">{{ option.i18n | translate }}</span>\n </label>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"activeOptionAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"activeOptionAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-radio-buttons{display:block;flex-direction:column;margin-bottom:.75rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__button-section{display:flex;min-height:2.25rem;flex-wrap:wrap;align-items:center;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__label:not(:last-child) .qd-radio-buttons__caption{padding-right:1rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section{display:flex;flex-direction:column;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section .qd-radio-buttons__caption{flex:auto}.qd-radio-buttons .qd-radio-buttons__label{display:flex;max-width:100%;padding:.625rem 0;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400;line-height:1rem}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__indicator{position:relative;margin:0 .375rem 0 0;color:#b4b4b4;font-size:1.25rem}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus{color:#171717}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover .qd-radio-buttons__indicator,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus .qd-radio-buttons__indicator{color:#757575}.qd-radio-buttons .qd-radio-buttons__label--checked{color:#171717}.qd-radio-buttons .qd-radio-buttons__label--checked .qd-radio-buttons__indicator{color:#069}.qd-radio-buttons .qd-radio-buttons__label--disabled{color:#d5d5d5;cursor:default}.qd-radio-buttons .qd-radio-buttons__label--disabled .qd-radio-buttons__indicator{color:#d5d5d5}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__caption{padding:0}.qd-radio-buttons__input-section{margin-bottom:.375rem}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__button-section{flex-direction:column}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label{width:100%;padding-top:.0625rem;padding-bottom:.0625rem;padding-left:.75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.75rem;background:#fff}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding-right:.75rem!important;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding:.375rem .375rem .375rem 0!important;line-height:1.25rem}}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label:last-child{margin-bottom:0}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__indicator{display:flex;align-items:center}}.qd-keyboard-active .qd-radio-buttons__radio-button:focus~.qd-radio-buttons__indicator:after{position:absolute;top:50%;left:50%;width:1.25rem;height:1.25rem;content:\"\";outline:.125rem solid rgb(23,23,23);outline-offset:0;transform:translate(-50%,-50%)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "directive", type: QdVisuallyHiddenDirective, selector: "[qdVisuallyHidden]" }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
15271
15407
  }
15272
15408
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRadioButtonsComponent, decorators: [{
15273
15409
  type: Component,
@@ -15279,7 +15415,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
15279
15415
  },
15280
15416
  QdRadioButtonsService,
15281
15417
  QdFormsActionEmitterService
15282
- ], encapsulation: ViewEncapsulation.None, standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n></qd-filter-form-items>\n\n<div class=\"qd-radio-buttons__button-section\" *ngIf=\"!readonly && !viewonly\">\n <label\n *ngFor=\"let option of radioButtonsListForView; trackBy: getOptionId\"\n [for]=\"option.value + id\"\n [ngClass]=\"\n 'qd-radio-buttons__label' +\n (option.disabled || disabled ? ' qd-radio-buttons__label--disabled' : '') +\n (option.value === value ? ' qd-radio-buttons__label--checked' : '')\n \"\n [attr.data-test-id]=\"testId + '-label'\"\n >\n <input\n type=\"radio\"\n qdVisuallyHidden\n [id]=\"option.value + id\"\n [ngClass]=\"'qd-radio-buttons__radio-button'\"\n [name]=\"id\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled || disabled\"\n (click)=\"handleClick(option.value)\"\n [checked]=\"option.value === value\"\n [attr.data-test-id]=\"testId + '-input-' + option.i18n\"\n />\n\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value === value\" [icon]=\"'circleRadio'\"></qd-icon>\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value !== value\" [icon]=\"'circleSolid'\"></qd-icon>\n\n <span [ngClass]=\"'qd-radio-buttons__caption qd-intersection-target'\">{{ option.i18n | translate }}</span>\n </label>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"activeOptionAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"activeOptionAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-radio-buttons{display:block;flex-direction:column;margin-bottom:.75rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__button-section{display:flex;min-height:2.25rem;flex-wrap:wrap;align-items:center;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__label:not(:last-child) .qd-radio-buttons__caption{padding-right:1rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section{display:flex;flex-direction:column;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section .qd-radio-buttons__caption{flex:auto}.qd-radio-buttons .qd-radio-buttons__label{display:flex;max-width:100%;padding:.625rem 0;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400;line-height:1rem}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__indicator{padding:0 .375rem 0 0;color:#b4b4b4;font-size:1.25rem}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus{color:#171717}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover .qd-radio-buttons__indicator,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus .qd-radio-buttons__indicator{color:#757575}.qd-radio-buttons .qd-radio-buttons__label--checked{color:#171717}.qd-radio-buttons .qd-radio-buttons__label--checked .qd-radio-buttons__indicator{color:#069}.qd-radio-buttons .qd-radio-buttons__label--disabled{color:#d5d5d5;cursor:default}.qd-radio-buttons .qd-radio-buttons__label--disabled .qd-radio-buttons__indicator{color:#d5d5d5}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__caption{padding:0}.qd-radio-buttons__input-section{margin-bottom:.375rem}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__button-section{flex-direction:column}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label{width:100%;padding-top:.0625rem;padding-bottom:.0625rem;padding-left:.75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.75rem;background:#fff}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding-right:.75rem!important;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding:.375rem .375rem .375rem 0!important;line-height:1.25rem}}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label:last-child{margin-bottom:0}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__indicator{display:flex;align-items:center}}\n"] }]
15418
+ ], encapsulation: ViewEncapsulation.None, standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n [isDisabled]=\"isLabelDisabled\"\n></qd-form-label>\n\n<qd-filter-form-items\n *ngIf=\"filter\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId + '-filter-form'\"\n></qd-filter-form-items>\n\n<div class=\"qd-radio-buttons__button-section\" *ngIf=\"!readonly && !viewonly\">\n <label\n *ngFor=\"let option of radioButtonsListForView; let i = index; trackBy: getOptionId\"\n [for]=\"option.value + id\"\n [ngClass]=\"\n 'qd-radio-buttons__label' +\n (option.disabled || disabled ? ' qd-radio-buttons__label--disabled' : '') +\n (option.value === value ? ' qd-radio-buttons__label--checked' : '')\n \"\n [attr.data-test-id]=\"testId + '-label'\"\n >\n <input\n type=\"radio\"\n qdVisuallyHidden\n [qdAutofocus]=\"hasAutofocus && i === 0\"\n [id]=\"option.value + id\"\n [ngClass]=\"'qd-radio-buttons__radio-button'\"\n [attr.tabindex]=\"option.value === tabStopValue ? 0 : -1\"\n [name]=\"id\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled || disabled\"\n (change)=\"handleClick(option.value)\"\n [checked]=\"option.value === value\"\n [attr.data-test-id]=\"testId + '-input-' + option.i18n\"\n />\n\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value === value\" [icon]=\"'circleRadio'\"></qd-icon>\n <qd-icon class=\"qd-radio-buttons__indicator\" *ngIf=\"option.value !== value\" [icon]=\"'circleSolid'\"></qd-icon>\n\n <span [ngClass]=\"'qd-radio-buttons__caption qd-intersection-target'\">{{ option.i18n | translate }}</span>\n </label>\n</div>\n\n<qd-form-hint\n *ngIf=\"!readonly && !viewonly && (hasHint || hasError)\"\n [hint]=\"hasHint ? config.hint.i18n : ''\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n></qd-form-hint>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"activeOptionAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"activeOptionAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n", styles: [".qd-radio-buttons{display:block;flex-direction:column;margin-bottom:.75rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__button-section{display:flex;min-height:2.25rem;flex-wrap:wrap;align-items:center;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--horizontal .qd-radio-buttons__label:not(:last-child) .qd-radio-buttons__caption{padding-right:1rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section{display:flex;flex-direction:column;margin-bottom:.375rem}.qd-radio-buttons.qd-radio-align--vertical .qd-radio-buttons__button-section .qd-radio-buttons__caption{flex:auto}.qd-radio-buttons .qd-radio-buttons__label{display:flex;max-width:100%;padding:.625rem 0;color:#454545;cursor:pointer;font-size:.875rem;font-weight:400;line-height:1rem}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__indicator{position:relative;margin:0 .375rem 0 0;color:#b4b4b4;font-size:1.25rem}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus{color:#171717}.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):hover .qd-radio-buttons__indicator,.qd-radio-buttons .qd-radio-buttons__label:not(.qd-radio-buttons__label--checked,.qd-radio-buttons__label--disabled):focus .qd-radio-buttons__indicator{color:#757575}.qd-radio-buttons .qd-radio-buttons__label--checked{color:#171717}.qd-radio-buttons .qd-radio-buttons__label--checked .qd-radio-buttons__indicator{color:#069}.qd-radio-buttons .qd-radio-buttons__label--disabled{color:#d5d5d5;cursor:default}.qd-radio-buttons .qd-radio-buttons__label--disabled .qd-radio-buttons__indicator{color:#d5d5d5}.qd-radio-buttons .qd-radio-buttons__label .qd-radio-buttons__caption{padding:0}.qd-radio-buttons__input-section{margin-bottom:.375rem}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__button-section{flex-direction:column}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label{width:100%;padding-top:.0625rem;padding-bottom:.0625rem;padding-left:.75rem;border:.0625rem solid rgb(180,180,180);margin-bottom:.75rem;background:#fff}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding-right:.75rem!important;transform:translateY(.0625rem)}}@media (max-width: 959.98px) and (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__caption{padding:.375rem .375rem .375rem 0!important;line-height:1.25rem}}@media (max-width: 959.98px){.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label:last-child{margin-bottom:0}.qd-radio-buttons:not(.qd-rwd-disabled) .qd-radio-buttons__label .qd-radio-buttons__indicator{display:flex;align-items:center}}.qd-keyboard-active .qd-radio-buttons__radio-button:focus~.qd-radio-buttons__indicator:after{position:absolute;top:50%;left:50%;width:1.25rem;height:1.25rem;content:\"\";outline:.125rem solid rgb(23,23,23);outline-offset:0;transform:translate(-50%,-50%)}\n"] }]
15283
15419
  }], ctorParameters: () => [], propDecorators: { value: [{
15284
15420
  type: Input
15285
15421
  }], config: [{
@@ -16405,6 +16541,7 @@ class QdFormModule {
16405
16541
  QdAutofocusModule,
16406
16542
  QdChipModule,
16407
16543
  QdCoreModule,
16544
+ QdIconButtonModule,
16408
16545
  QdIconModule,
16409
16546
  QdPopoverModule,
16410
16547
  QdTooltipModule,
@@ -16430,6 +16567,7 @@ class QdFormModule {
16430
16567
  QdAutofocusModule,
16431
16568
  QdChipModule,
16432
16569
  QdCoreModule,
16570
+ QdIconButtonModule,
16433
16571
  QdIconModule,
16434
16572
  QdPopoverModule,
16435
16573
  QdTooltipModule,
@@ -16446,6 +16584,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
16446
16584
  QdAutofocusModule,
16447
16585
  QdChipModule,
16448
16586
  QdCoreModule,
16587
+ QdIconButtonModule,
16449
16588
  QdIconModule,
16450
16589
  QdPopoverModule,
16451
16590
  QdTooltipModule,
@@ -17409,7 +17548,6 @@ class QdButtonModule {
17409
17548
  QdButtonLinkDirective,
17410
17549
  QdButtonStackButtonComponent,
17411
17550
  QdButtonStackComponent,
17412
- QdIconButtonComponent,
17413
17551
  QdMenuButtonComponent,
17414
17552
  QdButtonAdditionalInfoComponent,
17415
17553
  QdSanitizeHtmlPipe], imports: [CommonModule,
@@ -17418,7 +17556,8 @@ class QdButtonModule {
17418
17556
  QdTextSectionModule,
17419
17557
  QdPopoverModule,
17420
17558
  QdCoreModule,
17421
- QdNotificationsModule], exports: [QdButtonComponent,
17559
+ QdNotificationsModule,
17560
+ QdIconButtonModule], exports: [QdButtonComponent,
17422
17561
  QdButtonGhostDirective,
17423
17562
  QdButtonGridComponent,
17424
17563
  QdButtonLinkDirective,
@@ -17432,7 +17571,8 @@ class QdButtonModule {
17432
17571
  QdTextSectionModule,
17433
17572
  QdPopoverModule,
17434
17573
  QdCoreModule,
17435
- QdNotificationsModule] });
17574
+ QdNotificationsModule,
17575
+ QdIconButtonModule] });
17436
17576
  }
17437
17577
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdButtonModule, decorators: [{
17438
17578
  type: NgModule,
@@ -17444,7 +17584,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
17444
17584
  QdTextSectionModule,
17445
17585
  QdPopoverModule,
17446
17586
  QdCoreModule,
17447
- QdNotificationsModule
17587
+ QdNotificationsModule,
17588
+ QdIconButtonModule
17448
17589
  ],
17449
17590
  declarations: [
17450
17591
  QdButtonComponent,
@@ -17453,7 +17594,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
17453
17594
  QdButtonLinkDirective,
17454
17595
  QdButtonStackButtonComponent,
17455
17596
  QdButtonStackComponent,
17456
- QdIconButtonComponent,
17457
17597
  QdMenuButtonComponent,
17458
17598
  QdButtonAdditionalInfoComponent,
17459
17599
  QdSanitizeHtmlPipe
@@ -18846,6 +18986,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
18846
18986
  }]
18847
18987
  }] });
18848
18988
 
18989
+ class QdDialogConfirmComponent {
18990
+ dialogRef = inject(DialogRef);
18991
+ data = inject(DIALOG_DATA);
18992
+ config = this.data;
18993
+ testId = this.data?.testId ?? 'dialog-confirm';
18994
+ close() {
18995
+ this.dialogRef.close(false);
18996
+ }
18997
+ confirm() {
18998
+ this.dialogRef.close(true);
18999
+ }
19000
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19001
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogConfirmComponent, isStandalone: false, selector: "qd-dialog-confirm", ngImport: i0, template: "<qd-dialog [data-test-id]=\"testId\">\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ config.message.i18n | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button qdButton qdButtonGhost color=\"secondary\" (click)=\"close()\" [data-test-id]=\"testId + '-close'\">\n {{ config.cancel.i18n | translate }}\n </button>\n\n <button qdButton color=\"error\" (click)=\"confirm()\" [data-test-id]=\"testId + '-proceed'\">\n {{ config.confirm.i18n | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
19002
+ }
19003
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogConfirmComponent, decorators: [{
19004
+ type: Component,
19005
+ args: [{ selector: 'qd-dialog-confirm', standalone: false, template: "<qd-dialog [data-test-id]=\"testId\">\n <qd-text-section>\n <qd-text-section-paragraph>\n {{ config.message.i18n | translate }}\n </qd-text-section-paragraph>\n </qd-text-section>\n\n <qd-dialog-action>\n <button qdButton qdButtonGhost color=\"secondary\" (click)=\"close()\" [data-test-id]=\"testId + '-close'\">\n {{ config.cancel.i18n | translate }}\n </button>\n\n <button qdButton color=\"error\" (click)=\"confirm()\" [data-test-id]=\"testId + '-proceed'\">\n {{ config.confirm.i18n | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n" }]
19006
+ }] });
19007
+
18849
19008
  /**
18850
19009
  * **QdDialogRecordStepperComponent** provides a pagination for the fullscreen version of **QdDialog**. <br />
18851
19010
  * It is possible to navigate through a list of data provided by the dialog.
@@ -19108,7 +19267,7 @@ class QdDialogConfirmationComponent {
19108
19267
  });
19109
19268
  }
19110
19269
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogConfirmationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19111
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogConfirmationComponent, isStandalone: false, selector: "qd-dialog-confirmation", inputs: { config: "config", testId: ["data-test-id", "testId"] }, ngImport: i0, template: "<qd-dialog [attr.data-test-id]=\"testId\">\n <div class=\"loading-overlay\" *ngIf=\"isLoading\">\n <qd-spinner></qd-spinner>\n </div>\n\n <div class=\"headline\" *ngIf=\"isInfoState\">{{ config.info.headline.i18n | translate }}</div>\n\n <div class=\"headline\" *ngIf=\"isSuccessState\">\n {{ (config.success.headline.i18n | translate) || (config.info.headline.i18n | translate) }}\n </div>\n\n <div class=\"headline\" *ngIf=\"isErrorState && config.error.headline.i18n\">\n {{ config.error.headline.i18n | translate }}\n </div>\n\n <div class=\"info\">\n <ng-container *ngIf=\"isInfoState\"> {{ config.info.info.i18n | translate }} </ng-container>\n\n <ng-container *ngIf=\"isSuccessState\">\n <qd-icon class=\"success\" [icon]=\"'checkCircleSolid'\"></qd-icon>\n <span>{{ (config.success.info.i18n | translate) || (config.info.info.i18n | translate) }} </span>\n </ng-container>\n\n <ng-container *ngIf=\"isErrorState && config.error?.info?.i18n\">\n <qd-icon class=\"error\" [icon]=\"'timesCircleSolid'\"></qd-icon>\n <span>{{ config.error?.info?.i18n | translate }}</span>\n </ng-container>\n </div>\n\n <div class=\"confirm-content\">\n <ng-container *ngIf=\"isInfoState\">\n <ng-content select=\"[qdDialogConfirmInfo]\"></ng-content>\n <qd-checkboxes\n [attr.data-test-id]=\"testId + '-checkbox'\"\n *ngIf=\"useCheckbox\"\n [config]=\"checkboxConfig\"\n [(values)]=\"confirmChecked\"\n ></qd-checkboxes>\n </ng-container>\n\n <ng-container *ngIf=\"isSuccessState\">\n <ng-content select=\"[qdDialogConfirmSuccess]\"></ng-content>\n </ng-container>\n\n <ng-container *ngIf=\"isErrorState\">\n <ng-content select=\"[qdDialogConfirmError]\"></ng-content>\n </ng-container>\n\n <qd-notifications [context]=\"notificationContext\"></qd-notifications>\n </div>\n\n <qd-dialog-action>\n <ng-container *ngIf=\"isInfoState\">\n <button qdButton qdButtonGhost (click)=\"close()\" [disabled]=\"isLoading\">\n {{ config.buttons.cancel.i18n | translate }}\n </button>\n\n <button qdButton color=\"primary\" (click)=\"confirm()\" [disabled]=\"(useCheckbox && !isConfirmed) || isLoading\">\n {{ config.buttons.next.i18n | translate }}\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"isSuccessState\">\n <button qdButton color=\"primary\" (click)=\"submit()\">\n {{ (config.buttons.success?.i18n | translate) || (config.buttons.next.i18n | translate) }}\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"isErrorState\">\n <button qdButton color=\"primary\" (click)=\"submit()\">\n {{ (config.buttons.error?.i18n | translate) || (config.buttons.next.i18n | translate) }}\n </button>\n </ng-container>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host .headline{color:#171717;font-size:1rem;font-weight:700;line-height:1.5rem;margin-bottom:.75rem}:host .info{color:#171717;font-size:1rem;font-weight:400;line-height:1.5rem;display:flex}:host .info ::ng-deep .qd-icon{width:.875rem;margin-right:.75rem;font-size:1.25rem;font-weight:300}:host .info ::ng-deep .qd-icon.success{color:#00813a}:host .info ::ng-deep .qd-icon.error{color:#c70023}:host .loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background-color:#0003}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdCheckboxesComponent, selector: "qd-checkboxes", inputs: ["formControlName", "values", "config", "data-test-id"], outputs: ["valuesChange", "clickHint", "clickReadonly", "clickViewonly"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "component", type: QdNotificationsComponent, selector: "qd-notifications", inputs: ["context"] }, { kind: "component", type: QdSpinnerComponent, selector: "qd-spinner" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
19270
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDialogConfirmationComponent, isStandalone: false, selector: "qd-dialog-confirmation", inputs: { config: "config", testId: ["data-test-id", "testId"] }, ngImport: i0, template: "<qd-dialog [attr.data-test-id]=\"testId\">\n <div class=\"loading-overlay\" *ngIf=\"isLoading\">\n <qd-spinner></qd-spinner>\n </div>\n\n <div class=\"headline\" *ngIf=\"isInfoState\">{{ config.info.headline.i18n | translate }}</div>\n\n <div class=\"headline\" *ngIf=\"isSuccessState\">\n {{ (config.success.headline.i18n | translate) || (config.info.headline.i18n | translate) }}\n </div>\n\n <div class=\"headline\" *ngIf=\"isErrorState && config.error.headline.i18n\">\n {{ config.error.headline.i18n | translate }}\n </div>\n\n <div class=\"info\">\n <ng-container *ngIf=\"isInfoState\"> {{ config.info.info.i18n | translate }} </ng-container>\n\n <ng-container *ngIf=\"isSuccessState\">\n <qd-icon class=\"success\" [icon]=\"'checkCircleSolid'\"></qd-icon>\n <span>{{ (config.success.info.i18n | translate) || (config.info.info.i18n | translate) }} </span>\n </ng-container>\n\n <ng-container *ngIf=\"isErrorState && config.error?.info?.i18n\">\n <qd-icon class=\"error\" [icon]=\"'timesCircleSolid'\"></qd-icon>\n <span>{{ config.error?.info?.i18n | translate }}</span>\n </ng-container>\n </div>\n\n <div class=\"confirm-content\">\n <ng-container *ngIf=\"isInfoState\">\n <ng-content select=\"[qdDialogConfirmInfo]\"></ng-content>\n <qd-checkboxes\n [attr.data-test-id]=\"testId + '-checkbox'\"\n *ngIf=\"useCheckbox\"\n [config]=\"checkboxConfig\"\n [(values)]=\"confirmChecked\"\n ></qd-checkboxes>\n </ng-container>\n\n <ng-container *ngIf=\"isSuccessState\">\n <ng-content select=\"[qdDialogConfirmSuccess]\"></ng-content>\n </ng-container>\n\n <ng-container *ngIf=\"isErrorState\">\n <ng-content select=\"[qdDialogConfirmError]\"></ng-content>\n </ng-container>\n\n <qd-notifications [context]=\"notificationContext\"></qd-notifications>\n </div>\n\n <qd-dialog-action>\n <ng-container *ngIf=\"isInfoState\">\n <button qdButton qdButtonGhost (click)=\"close()\" [disabled]=\"isLoading\">\n {{ config.buttons.cancel.i18n | translate }}\n </button>\n\n <button qdButton color=\"primary\" (click)=\"confirm()\" [disabled]=\"(useCheckbox && !isConfirmed) || isLoading\">\n {{ config.buttons.next.i18n | translate }}\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"isSuccessState\">\n <button qdButton color=\"primary\" (click)=\"submit()\">\n {{ (config.buttons.success?.i18n | translate) || (config.buttons.next.i18n | translate) }}\n </button>\n </ng-container>\n\n <ng-container *ngIf=\"isErrorState\">\n <button qdButton color=\"primary\" (click)=\"submit()\">\n {{ (config.buttons.error?.i18n | translate) || (config.buttons.next.i18n | translate) }}\n </button>\n </ng-container>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host .headline{color:#171717;font-size:1rem;font-weight:700;line-height:1.5rem;margin-bottom:.75rem}:host .info{color:#171717;font-size:1rem;font-weight:400;line-height:1.5rem;display:flex}:host .info ::ng-deep .qd-icon{width:.875rem;margin-right:.75rem;font-size:1.25rem;font-weight:300}:host .info ::ng-deep .qd-icon.success{color:#00813a}:host .info ::ng-deep .qd-icon.error{color:#c70023}:host .loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background-color:#0003}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdCheckboxesComponent, selector: "qd-checkboxes", inputs: ["formControlName", "values", "config", "data-test-id"], outputs: ["valuesChange", "clickHint", "clickReadonly", "clickViewonly"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "component", type: QdNotificationsComponent, selector: "qd-notifications", inputs: ["context"] }, { kind: "component", type: QdSpinnerComponent, selector: "qd-spinner" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
19112
19271
  }
19113
19272
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDialogConfirmationComponent, decorators: [{
19114
19273
  type: Component,
@@ -19123,7 +19282,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
19123
19282
 
19124
19283
  class QdPageDialogWithBreadcrumbsComponent {
19125
19284
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageDialogWithBreadcrumbsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19126
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageDialogWithBreadcrumbsComponent, isStandalone: false, selector: "ng-component", ngImport: i0, template: "<qd-dialog>\n <div class=\"wrapper\">\n <qd-breadcrumbs></qd-breadcrumbs>\n <div class=\"router-outlet-wrapper\">\n <router-outlet name=\"dialog\"></router-outlet>\n </div>\n </div>\n</qd-dialog>\n", styles: [".wrapper{display:flex;height:100%;flex-flow:column}qd-breadcrumbs{z-index:99;flex:0 1 auto;padding-right:2.25rem;padding-bottom:.75rem;margin-bottom:-.75rem}.router-outlet-wrapper{position:relative;height:100%;flex:1 1 auto}\n"], dependencies: [{ kind: "directive", type: i2$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: QdBreadcrumbsComponent, selector: "qd-breadcrumbs" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }] });
19285
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageDialogWithBreadcrumbsComponent, isStandalone: false, selector: "ng-component", ngImport: i0, template: "<qd-dialog>\n <div class=\"wrapper\">\n <qd-breadcrumbs></qd-breadcrumbs>\n <div class=\"router-outlet-wrapper\">\n <router-outlet name=\"dialog\"></router-outlet>\n </div>\n </div>\n</qd-dialog>\n", styles: [".wrapper{display:flex;height:100%;flex-flow:column}qd-breadcrumbs{z-index:99;flex:0 1 auto;padding-right:2.25rem;padding-bottom:.75rem;margin-bottom:-.75rem}.router-outlet-wrapper{position:relative;height:100%;flex:1 1 auto}\n"], dependencies: [{ kind: "directive", type: i2$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: QdBreadcrumbsComponent, selector: "qd-breadcrumbs" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }] });
19127
19286
  }
19128
19287
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageDialogWithBreadcrumbsComponent, decorators: [{
19129
19288
  type: Component,
@@ -19134,10 +19293,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
19134
19293
  * Tracks pending changes inside a QdDialog by comparing the current form value with the initial value.
19135
19294
  * Supports both Reactive Forms (FormGroupDirective) and Template-Driven Forms (NgForm).
19136
19295
  *
19137
- * Relevant when closing the dialog (X icon or Cancel button):
19296
+ * Relevant when closing the dialog (X icon, ESC or Cancel button):
19138
19297
  * - if the current value equals the initial value, closing will not trigger a pending-changes warning
19139
19298
  * - the form is reset to pristine, so the dialog behaves like “unchanged”
19140
19299
  *
19300
+ * #### Notes & Best Practices:
19301
+ *
19302
+ * - Pending changes are reported for the dialog that hosts the form. Other open
19303
+ * dialogs are never affected.
19304
+ * - Outside a dialog there is nothing to guard. The form is still reset to
19305
+ * pristine, but no pending changes are reported.
19306
+ *
19141
19307
  * #### **Usage (Reactive Form)**
19142
19308
  *
19143
19309
  * ```html
@@ -19151,6 +19317,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
19151
19317
  class QdPendingChangesGuardDirective {
19152
19318
  ngForm = inject(NgForm, { optional: true });
19153
19319
  formGroupDirective = inject(FormGroupDirective, { optional: true });
19320
+ dialogRef = inject(DialogRef, { optional: true });
19154
19321
  changeGuard = inject(QdDialogChangeGuardService);
19155
19322
  statusSubscription;
19156
19323
  initialValue;
@@ -19170,19 +19337,25 @@ class QdPendingChangesGuardDirective {
19170
19337
  });
19171
19338
  }
19172
19339
  }
19340
+ ngOnDestroy() {
19341
+ this.statusSubscription?.unsubscribe();
19342
+ this.reportPendingChanges(false);
19343
+ }
19173
19344
  updateStatus() {
19174
19345
  if (!this.formGroup)
19175
19346
  return;
19176
19347
  const isPristine = isEqual(this.formGroup.value, this.initialValue);
19177
- const hasChanges = !isPristine;
19178
- this.changeGuard.setPendingChangesStatus(hasChanges);
19348
+ this.reportPendingChanges(!isPristine);
19179
19349
  if (isPristine && this.formGroup.dirty) {
19180
19350
  this.formGroup.markAsPristine();
19181
19351
  }
19182
19352
  }
19183
- ngOnDestroy() {
19184
- this.statusSubscription?.unsubscribe();
19185
- this.changeGuard.setPendingChangesStatus(false);
19353
+ reportPendingChanges(hasChanges) {
19354
+ if (!this.dialogRef)
19355
+ return;
19356
+ if (hasChanges)
19357
+ return this.changeGuard.markPendingChanges(this, this.dialogRef);
19358
+ this.changeGuard.clearPendingChanges(this, this.dialogRef);
19186
19359
  }
19187
19360
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPendingChangesGuardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
19188
19361
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdPendingChangesGuardDirective, isStandalone: false, selector: "[qdPendingChangesGuard]", ngImport: i0 });
@@ -19200,6 +19373,7 @@ class QdDialogModule {
19200
19373
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdDialogModule, declarations: [QdDialogActionComponent,
19201
19374
  QdDialogAuthSessionEndComponent,
19202
19375
  QdDialogComponent,
19376
+ QdDialogConfirmComponent,
19203
19377
  QdDialogConfirmationComponent,
19204
19378
  QdDialogConfirmationErrorDirective,
19205
19379
  QdDialogConfirmationInfoDirective,
@@ -19229,6 +19403,10 @@ class QdDialogModule {
19229
19403
  {
19230
19404
  provide: QD_PAGE_DIALOG_WITH_BREADCRUMBS_HOST,
19231
19405
  useValue: QdPageDialogWithBreadcrumbsComponent
19406
+ },
19407
+ {
19408
+ provide: QD_DISCARD_CONFIRM_DIALOG_COMPONENT_TOKEN,
19409
+ useValue: QdDialogConfirmComponent
19232
19410
  }
19233
19411
  ], imports: [CommonModule,
19234
19412
  TranslateModule,
@@ -19264,6 +19442,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
19264
19442
  QdDialogActionComponent,
19265
19443
  QdDialogAuthSessionEndComponent,
19266
19444
  QdDialogComponent,
19445
+ QdDialogConfirmComponent,
19267
19446
  QdDialogConfirmationComponent,
19268
19447
  QdDialogConfirmationErrorDirective,
19269
19448
  QdDialogConfirmationInfoDirective,
@@ -19286,6 +19465,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
19286
19465
  {
19287
19466
  provide: QD_PAGE_DIALOG_WITH_BREADCRUMBS_HOST,
19288
19467
  useValue: QdPageDialogWithBreadcrumbsComponent
19468
+ },
19469
+ {
19470
+ provide: QD_DISCARD_CONFIRM_DIALOG_COMPONENT_TOKEN,
19471
+ useValue: QdDialogConfirmComponent
19289
19472
  }
19290
19473
  ]
19291
19474
  }]
@@ -19721,7 +19904,7 @@ class QdFileCollectorDialogComponent {
19721
19904
  return !!fileUpload.error || fileUpload.progress === 100;
19722
19905
  }
19723
19906
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19724
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogComponent, isStandalone: false, selector: "qd-file-collector-dialog", providers: [QdFileCollectorService], ngImport: i0, template: "<qd-dialog>\n <qd-file-collector-dialog-item\n *ngFor=\"let fileUpload of this.fileUploads; let i = index\"\n [progress]=\"fileUpload.progress\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [data-test-id]=\"'file-collector-dialog-item-' + i\"\n ></qd-file-collector-dialog-item>\n <qd-dialog-action>\n <button\n qdButton\n (click)=\"close()\"\n [disabled]=\"isCloseButtonDisabled()\"\n data-test-id=\"file-collector-dialog-button-finish\"\n >\n {{ \"i18n.qd.fileCollector.button.finish\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "component", type: QdFileCollectorDialogItemComponent, selector: "qd-file-collector-dialog-item", inputs: ["progress", "collectedFile", "error", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
19907
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogComponent, isStandalone: false, selector: "qd-file-collector-dialog", providers: [QdFileCollectorService], ngImport: i0, template: "<qd-dialog>\n <qd-file-collector-dialog-item\n *ngFor=\"let fileUpload of this.fileUploads; let i = index\"\n [progress]=\"fileUpload.progress\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [data-test-id]=\"'file-collector-dialog-item-' + i\"\n ></qd-file-collector-dialog-item>\n <qd-dialog-action>\n <button\n qdButton\n (click)=\"close()\"\n [disabled]=\"isCloseButtonDisabled()\"\n data-test-id=\"file-collector-dialog-button-finish\"\n >\n {{ \"i18n.qd.fileCollector.button.finish\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "component", type: QdFileCollectorDialogItemComponent, selector: "qd-file-collector-dialog-item", inputs: ["progress", "collectedFile", "error", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
19725
19908
  }
19726
19909
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogComponent, decorators: [{
19727
19910
  type: Component,
@@ -19924,7 +20107,7 @@ class QdFileDeleteDialogComponent {
19924
20107
  this.dialogRef.close(true);
19925
20108
  }
19926
20109
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileDeleteDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19927
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileDeleteDialogComponent, isStandalone: false, selector: "qd-file-delete-dialog", ngImport: i0, template: "<qd-dialog>\n {{ deleteHint }}\n\n <qd-dialog-action>\n <button (click)=\"cancel()\" qdButton qdButtonGhost color=\"secondary\" data-test-id=\"file-delete-dialog-button-cancel\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.cancel\" | translate }}\n </button>\n\n <button (click)=\"delete()\" qdButton color=\"error\" data-test-id=\"file-delete-dialog-button-delete\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.delete\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host{overflow-wrap:break-word}\n"], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
20110
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileDeleteDialogComponent, isStandalone: false, selector: "qd-file-delete-dialog", ngImport: i0, template: "<qd-dialog>\n {{ deleteHint }}\n\n <qd-dialog-action>\n <button (click)=\"cancel()\" qdButton qdButtonGhost color=\"secondary\" data-test-id=\"file-delete-dialog-button-cancel\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.cancel\" | translate }}\n </button>\n\n <button (click)=\"delete()\" qdButton color=\"error\" data-test-id=\"file-delete-dialog-button-delete\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.delete\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host{overflow-wrap:break-word}\n"], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
19928
20111
  }
19929
20112
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileDeleteDialogComponent, decorators: [{
19930
20113
  type: Component,
@@ -21900,11 +22083,11 @@ class QdFilterItemSelectCategoryComponent {
21900
22083
  }));
21901
22084
  }
21902
22085
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterItemSelectCategoryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21903
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterItemSelectCategoryComponent, isStandalone: false, selector: "qd-filter-category-select", inputs: { filterId: "filterId", categoryIndex: "categoryIndex", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-filter__category-select" }, viewQueries: [{ propertyName: "popoverDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n qdPopoverPlacement=\"bottom-start\"\n [qdPopoverOffsetY]=\"-1\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngIf=\"(isMobile$ | async) && type === 'multiSelect'; else desktopChips\">\n <qd-chip\n *ngIf=\"activeItemCount > 0\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"clearAll()\"\n [data-test-id]=\"testId + '-selected-chip-count'\"\n >{{ activeItemCount }}</qd-chip\n >\n </ng-container>\n <ng-template #desktopChips>\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n </ng-template>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'ctrlTop'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container *ngIf=\"itemsLoading$ | async; else categoryContent\" [ngTemplateOutlet]=\"loadingState\"></ng-container>\n\n <ng-template #categoryContent>\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container\n *ngFor=\"let entry of selectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <div\n *ngIf=\"showSelectedSeparator\"\n class=\"qd-filter__category-layer-separator\"\n [attr.data-test-id]=\"testId + '-selected-separator'\"\n ></div>\n\n <ng-container\n *ngFor=\"let entry of unselectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n </ng-container>\n </ng-template>\n </div>\n</ng-template>\n\n<ng-template #emptyState>\n <p class=\"qd-filter__category-layer-empty\" [attr.data-test-id]=\"testId + '-no-results'\">\n {{ \"i18n.qd.filter.noResults\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #loadingState>\n <p class=\"qd-filter__category-layer-loading\" [attr.data-test-id]=\"testId + '-items-loading'\">\n {{ \"i18n.qd.filter.loading\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #multiSelectItem let-item=\"item\" let-itemIndex=\"itemIndex\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n ></qd-filter-item-multi-select>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{position:relative;display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-separator{height:.0625rem;flex-shrink:0;background:#d5d5d5}::ng-deep .qd-filter__category-layer-empty,::ng-deep .qd-filter__category-layer-loading{padding:0 .9375rem;margin:0;color:#757575;font-size:.875rem;line-height:2.5rem}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:.5rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: QdChipComponent, selector: "qd-chip", inputs: ["state", "close", "data", "data-test-id"], outputs: ["closeClickEmitter"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdFilterItemMultiSelectComponent, selector: "qd-filter-item-multi-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"] }, { kind: "component", type: QdFilterItemSingleSelectComponent, selector: "qd-filter-item-single-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"], outputs: ["closeEventEmitter"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22086
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterItemSelectCategoryComponent, isStandalone: false, selector: "qd-filter-category-select", inputs: { filterId: "filterId", categoryIndex: "categoryIndex", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-filter__category-select" }, viewQueries: [{ propertyName: "popoverDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n tabindex=\"0\"\n role=\"button\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-label]=\"i18n | translate\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverEnableKeyControl]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n qdPopoverPlacement=\"bottom-start\"\n [qdPopoverOffsetY]=\"-1\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngIf=\"(isMobile$ | async) && type === 'multiSelect'; else desktopChips\">\n <qd-chip\n *ngIf=\"activeItemCount > 0\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"clearAll()\"\n [data-test-id]=\"testId + '-selected-chip-count'\"\n >{{ activeItemCount }}</qd-chip\n >\n </ng-container>\n <ng-template #desktopChips>\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n </ng-template>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'ctrlTop'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container *ngIf=\"itemsLoading$ | async; else categoryContent\" [ngTemplateOutlet]=\"loadingState\"></ng-container>\n\n <ng-template #categoryContent>\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container\n *ngFor=\"let entry of selectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <div\n *ngIf=\"showSelectedSeparator\"\n class=\"qd-filter__category-layer-separator\"\n [attr.data-test-id]=\"testId + '-selected-separator'\"\n ></div>\n\n <ng-container\n *ngFor=\"let entry of unselectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n </ng-container>\n </ng-template>\n </div>\n</ng-template>\n\n<ng-template #emptyState>\n <p class=\"qd-filter__category-layer-empty\" [attr.data-test-id]=\"testId + '-no-results'\">\n {{ \"i18n.qd.filter.noResults\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #loadingState>\n <p class=\"qd-filter__category-layer-loading\" [attr.data-test-id]=\"testId + '-items-loading'\">\n {{ \"i18n.qd.filter.loading\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #multiSelectItem let-item=\"item\" let-itemIndex=\"itemIndex\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n ></qd-filter-item-multi-select>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{position:relative;display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-separator{height:.0625rem;flex-shrink:0;background:#d5d5d5}::ng-deep .qd-filter__category-layer-empty,::ng-deep .qd-filter__category-layer-loading{padding:0 .9375rem;margin:0;color:#757575;font-size:.875rem;line-height:2.5rem}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:.5rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: QdChipComponent, selector: "qd-chip", inputs: ["state", "close", "data", "data-test-id"], outputs: ["closeClickEmitter"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdFilterItemMultiSelectComponent, selector: "qd-filter-item-multi-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"] }, { kind: "component", type: QdFilterItemSingleSelectComponent, selector: "qd-filter-item-single-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"], outputs: ["closeEventEmitter"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
21904
22087
  }
21905
22088
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterItemSelectCategoryComponent, decorators: [{
21906
22089
  type: Component,
21907
- args: [{ selector: 'qd-filter-category-select', host: { class: 'qd-filter__category-select' }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n qdPopoverPlacement=\"bottom-start\"\n [qdPopoverOffsetY]=\"-1\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngIf=\"(isMobile$ | async) && type === 'multiSelect'; else desktopChips\">\n <qd-chip\n *ngIf=\"activeItemCount > 0\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"clearAll()\"\n [data-test-id]=\"testId + '-selected-chip-count'\"\n >{{ activeItemCount }}</qd-chip\n >\n </ng-container>\n <ng-template #desktopChips>\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n </ng-template>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'ctrlTop'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container *ngIf=\"itemsLoading$ | async; else categoryContent\" [ngTemplateOutlet]=\"loadingState\"></ng-container>\n\n <ng-template #categoryContent>\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container\n *ngFor=\"let entry of selectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <div\n *ngIf=\"showSelectedSeparator\"\n class=\"qd-filter__category-layer-separator\"\n [attr.data-test-id]=\"testId + '-selected-separator'\"\n ></div>\n\n <ng-container\n *ngFor=\"let entry of unselectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n </ng-container>\n </ng-template>\n </div>\n</ng-template>\n\n<ng-template #emptyState>\n <p class=\"qd-filter__category-layer-empty\" [attr.data-test-id]=\"testId + '-no-results'\">\n {{ \"i18n.qd.filter.noResults\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #loadingState>\n <p class=\"qd-filter__category-layer-loading\" [attr.data-test-id]=\"testId + '-items-loading'\">\n {{ \"i18n.qd.filter.loading\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #multiSelectItem let-item=\"item\" let-itemIndex=\"itemIndex\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n ></qd-filter-item-multi-select>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{position:relative;display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-separator{height:.0625rem;flex-shrink:0;background:#d5d5d5}::ng-deep .qd-filter__category-layer-empty,::ng-deep .qd-filter__category-layer-loading{padding:0 .9375rem;margin:0;color:#757575;font-size:.875rem;line-height:2.5rem}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:.5rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"] }]
22090
+ args: [{ selector: 'qd-filter-category-select', host: { class: 'qd-filter__category-select' }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n tabindex=\"0\"\n role=\"button\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-label]=\"i18n | translate\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverEnableKeyControl]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n qdPopoverPlacement=\"bottom-start\"\n [qdPopoverOffsetY]=\"-1\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngIf=\"(isMobile$ | async) && type === 'multiSelect'; else desktopChips\">\n <qd-chip\n *ngIf=\"activeItemCount > 0\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"clearAll()\"\n [data-test-id]=\"testId + '-selected-chip-count'\"\n >{{ activeItemCount }}</qd-chip\n >\n </ng-container>\n <ng-template #desktopChips>\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n </ng-template>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'ctrlTop'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container *ngIf=\"itemsLoading$ | async; else categoryContent\" [ngTemplateOutlet]=\"loadingState\"></ng-container>\n\n <ng-template #categoryContent>\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container\n *ngFor=\"let entry of selectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <div\n *ngIf=\"showSelectedSeparator\"\n class=\"qd-filter__category-layer-separator\"\n [attr.data-test-id]=\"testId + '-selected-separator'\"\n ></div>\n\n <ng-container\n *ngFor=\"let entry of unselectedDropdownEntries; trackBy: trackByItem\"\n [ngTemplateOutlet]=\"multiSelectItem\"\n [ngTemplateOutletContext]=\"{ item: entry.item, itemIndex: entry.itemIndex }\"\n ></ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n\n <ng-container *ngIf=\"hasNoVisibleItems\" [ngTemplateOutlet]=\"emptyState\"></ng-container>\n </div>\n </ng-container>\n </ng-container>\n </ng-template>\n </div>\n</ng-template>\n\n<ng-template #emptyState>\n <p class=\"qd-filter__category-layer-empty\" [attr.data-test-id]=\"testId + '-no-results'\">\n {{ \"i18n.qd.filter.noResults\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #loadingState>\n <p class=\"qd-filter__category-layer-loading\" [attr.data-test-id]=\"testId + '-items-loading'\">\n {{ \"i18n.qd.filter.loading\" | translate }}\n </p>\n</ng-template>\n\n<ng-template #multiSelectItem let-item=\"item\" let-itemIndex=\"itemIndex\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n ></qd-filter-item-multi-select>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{position:relative;display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-separator{height:.0625rem;flex-shrink:0;background:#d5d5d5}::ng-deep .qd-filter__category-layer-empty,::ng-deep .qd-filter__category-layer-loading{padding:0 .9375rem;margin:0;color:#757575;font-size:.875rem;line-height:2.5rem}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:.5rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"] }]
21908
22091
  }], propDecorators: { filterId: [{
21909
22092
  type: Input
21910
22093
  }], categoryIndex: [{
@@ -23627,7 +23810,7 @@ class QdSearchComponent {
23627
23810
  return this.configData.emitEmptySearch ?? !!this.configData.clearable;
23628
23811
  }
23629
23812
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23630
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdSearchComponent, isStandalone: false, selector: "qd-search", inputs: { configData: "configData" }, host: { properties: { "class.hidden": "!hasConfig" }, classAttribute: "qd-search" }, providers: [QdSearchService, QdSearchRouterConnectorService], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"hasConfig\">\n <div class=\"search-field\">\n <qd-dropdown\n *ngIf=\"preSelectedEnabled\"\n class=\"preselect\"\n [(value)]=\"preSelect\"\n [config]=\"dropdownConfig\"\n ></qd-dropdown>\n\n <qd-input\n class=\"search-input\"\n [(value)]=\"search\"\n [config]=\"inputConfig\"\n (keydown.enter)=\"startSearch()\"\n (clickClear)=\"handleDelete()\"\n data-test-id=\"search-input\"\n ></qd-input>\n <button\n type=\"button\"\n qdIconButton\n qdStopPropagation\n data-test-id=\"search-button\"\n class=\"search-button\"\n (click)=\"startSearch()\"\n [attr.aria-label]=\"'i18n.qd.container.toolbar.search' | translate\"\n >\n <qd-icon [icon]=\"'magnifier'\"></qd-icon>\n </button>\n </div>\n\n <qd-icon\n *ngIf=\"hasAdditionalInfo\"\n icon=\"circleInfo\"\n class=\"additional-info\"\n qdTooltipOnClick\n [qdTooltipContent]=\"configData.additionalInfo.content\"\n ></qd-icon>\n</ng-container>\n", styles: [".qd-search{position:relative;display:flex;height:2.25rem}.qd-search.hidden{display:none}.qd-search .search-field{position:relative;display:flex;flex-wrap:nowrap}@media (max-width: 959.98px){.qd-search .search-field,.qd-search .search-field .search-input{width:100%}}.qd-search .preselect{display:flex;height:2.25rem}.qd-search .preselect .qd-dropdown__wrapper{height:2.25rem;margin-bottom:0}.qd-search .preselect .qd-dropdown__wrapper .qd-dropdown__box{background:#e5e5e5;color:#171717;font-size:.8125rem}.qd-search .search-input{display:flex;overflow:hidden;width:16.25rem;margin:0}.qd-search .search-input .qd-form-label,.qd-search .search-input .qd-form-hint{display:none;margin:0}.qd-search .search-input .qd-input-input{padding-right:1.25rem;margin:0!important}.qd-search .search-input .qd-input-input .qd-input-clearable-icon{margin-right:1.75rem!important}.qd-search .search-button{position:absolute;top:0;right:0;width:1.875rem;height:2.25rem;padding:0!important;padding-right:.375rem!important;padding-left:.375rem!important;margin:0!important;background:none}.qd-search .search-button:hover,.qd-search .search-button:focus,.qd-search .search-button:active{background:none}.qd-search .search-button .qd-icon{color:#979797!important;font-size:1.125rem!important;line-height:2.25rem;transform:translate(-.125rem,.0625rem)}.qd-search .search-button .qd-icon:hover,.qd-search .search-button .qd-icon:focus,.qd-search .search-button .qd-icon:active{color:#171717!important}.qd-search .additional-info{align-self:center;padding:0 .375rem 0 0;margin-right:-.375rem;margin-left:.5rem;color:#069;cursor:pointer;font-size:1.3125rem;line-height:2.25rem}.qd-search .additional-info:hover,.qd-search .additional-info:focus,.qd-search .additional-info:active{color:#14516f}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconButtonComponent, selector: "button[qdIconButton], a[qdIconButton], button[qd-icon-button]", inputs: ["color", "data-test-id"] }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdTooltipOnClickDirective, selector: "[qdTooltipOnClick]", inputs: ["qdTooltipContent"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
23813
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdSearchComponent, isStandalone: false, selector: "qd-search", inputs: { configData: "configData" }, host: { properties: { "class.hidden": "!hasConfig" }, classAttribute: "qd-search" }, providers: [QdSearchService, QdSearchRouterConnectorService], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"hasConfig\">\n <div class=\"search-field\">\n <qd-dropdown\n *ngIf=\"preSelectedEnabled\"\n class=\"preselect\"\n [(value)]=\"preSelect\"\n [config]=\"dropdownConfig\"\n ></qd-dropdown>\n\n <qd-input\n class=\"search-input\"\n [(value)]=\"search\"\n [config]=\"inputConfig\"\n (keydown.enter)=\"startSearch()\"\n (clickClear)=\"handleDelete()\"\n data-test-id=\"search-input\"\n ></qd-input>\n <button\n type=\"button\"\n qdIconButton\n qdStopPropagation\n data-test-id=\"search-button\"\n class=\"search-button\"\n (click)=\"startSearch()\"\n [attr.aria-label]=\"'i18n.qd.container.toolbar.search' | translate\"\n >\n <qd-icon [icon]=\"'magnifier'\"></qd-icon>\n </button>\n </div>\n\n <qd-icon\n *ngIf=\"hasAdditionalInfo\"\n icon=\"circleInfo\"\n class=\"additional-info\"\n qdTooltipOnClick\n [qdTooltipContent]=\"configData.additionalInfo.content\"\n ></qd-icon>\n</ng-container>\n", styles: [".qd-search{position:relative;display:flex;height:2.25rem}.qd-search.hidden{display:none}.qd-search .search-field{position:relative;display:flex;flex-wrap:nowrap}@media (max-width: 959.98px){.qd-search .search-field,.qd-search .search-field .search-input{width:100%}}.qd-search .preselect{display:flex;height:2.25rem}.qd-search .preselect .qd-dropdown__wrapper{height:2.25rem;margin-bottom:0}.qd-search .preselect .qd-dropdown__wrapper .qd-dropdown__box{background:#e5e5e5;color:#171717;font-size:.8125rem}.qd-search .search-input{display:flex;overflow:hidden;width:16.25rem;margin:0}.qd-search .search-input .qd-form-label,.qd-search .search-input .qd-form-hint{display:none;margin:0}.qd-search .search-input .qd-input-input{padding-right:1.25rem;margin:0!important}.qd-search .search-input .qd-input-input .qd-input-clearable-icon{margin-right:1.75rem!important}.qd-search .search-button{position:absolute;top:0;right:0;width:1.875rem;height:2.25rem;padding:0!important;padding-right:.375rem!important;padding-left:.375rem!important;margin:0!important;background:none}.qd-search .search-button:hover,.qd-search .search-button:focus,.qd-search .search-button:active{background:none}.qd-search .search-button .qd-icon{color:#979797!important;font-size:1.125rem!important;line-height:2.25rem;transform:translate(-.125rem,.0625rem)}.qd-search .search-button .qd-icon:hover,.qd-search .search-button .qd-icon:focus,.qd-search .search-button .qd-icon:active{color:#171717!important}.qd-search .additional-info{align-self:center;padding:0 .375rem 0 0;margin-right:-.375rem;margin-left:.5rem;color:#069;cursor:pointer;font-size:1.3125rem;line-height:2.25rem}.qd-search .additional-info:hover,.qd-search .additional-info:focus,.qd-search .additional-info:active{color:#14516f}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconButtonComponent, selector: "button[qdIconButton], a[qdIconButton], button[qd-icon-button]", inputs: ["color", "data-test-id"] }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "dropdownOpened", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdTooltipOnClickDirective, selector: "[qdTooltipOnClick]", inputs: ["qdTooltipContent"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
23631
23814
  }
23632
23815
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdSearchComponent, decorators: [{
23633
23816
  type: Component,
@@ -28284,6 +28467,7 @@ class QdTableModule {
28284
28467
  TranslateModule, i1$1.StoreFeatureModule, QdButtonModule,
28285
28468
  QdChipModule,
28286
28469
  QdDataFacetsModule,
28470
+ QdDialogModule,
28287
28471
  QdIconModule,
28288
28472
  QdPopoverModule,
28289
28473
  QdStatusIndicatorModule,
@@ -28296,6 +28480,7 @@ class QdTableModule {
28296
28480
  QdButtonModule,
28297
28481
  QdChipModule,
28298
28482
  QdDataFacetsModule,
28483
+ QdDialogModule,
28299
28484
  QdIconModule,
28300
28485
  QdPopoverModule,
28301
28486
  QdStatusIndicatorModule,
@@ -28313,6 +28498,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
28313
28498
  QdButtonModule,
28314
28499
  QdChipModule,
28315
28500
  QdDataFacetsModule,
28501
+ QdDialogModule,
28316
28502
  QdIconModule,
28317
28503
  QdPopoverModule,
28318
28504
  QdStatusIndicatorModule,
@@ -28718,7 +28904,7 @@ class QdContextSelectDialogComponent {
28718
28904
  });
28719
28905
  }
28720
28906
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdContextSelectDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
28721
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdContextSelectDialogComponent, isStandalone: false, selector: "qd-context-select-dialog", providers: [QdSearchService], ngImport: i0, template: "<qd-dialog>\n <div class=\"search\" *ngIf=\"data.config.hasSearch\">\n <qd-search [configData]=\"searchConfig\"></qd-search>\n </div>\n <qd-table\n [data]=\"tableData\"\n [config]=\"tableConfig\"\n (selectedRowsOutput)=\"select($event)\"\n data-test-id=\"context-select-dialog-table\"\n ></qd-table>\n <qd-dialog-action>\n <button qdButton qdButtonGhost color=\"secondary\" (click)=\"cancel()\">\n {{ \"i18n.qd.context.dialog.cancelButtonLabel\" | translate }}\n </button>\n <button qdButton (click)=\"confirm()\" data-test-id=\"context-select-dialog-submit\">\n {{ \"i18n.qd.context.dialog.confirmButtonLabel\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [".search{display:flex;justify-content:end;padding-bottom:.9375rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "component", type: QdTableComponent, selector: "qd-table", inputs: ["config", "data", "data-test-id"], outputs: ["secondaryActionOutput", "selectedRowsOutput", "emptyStateActionOutput"] }, { kind: "component", type: QdSearchComponent, selector: "qd-search", inputs: ["configData"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
28907
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdContextSelectDialogComponent, isStandalone: false, selector: "qd-context-select-dialog", providers: [QdSearchService], ngImport: i0, template: "<qd-dialog>\n <div class=\"search\" *ngIf=\"data.config.hasSearch\">\n <qd-search [configData]=\"searchConfig\"></qd-search>\n </div>\n <qd-table\n [data]=\"tableData\"\n [config]=\"tableConfig\"\n (selectedRowsOutput)=\"select($event)\"\n data-test-id=\"context-select-dialog-table\"\n ></qd-table>\n <qd-dialog-action>\n <button qdButton qdButtonGhost color=\"secondary\" (click)=\"cancel()\">\n {{ \"i18n.qd.context.dialog.cancelButtonLabel\" | translate }}\n </button>\n <button qdButton (click)=\"confirm()\" data-test-id=\"context-select-dialog-submit\">\n {{ \"i18n.qd.context.dialog.confirmButtonLabel\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [".search{display:flex;justify-content:end;padding-bottom:.9375rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "component", type: QdTableComponent, selector: "qd-table", inputs: ["config", "data", "data-test-id"], outputs: ["secondaryActionOutput", "selectedRowsOutput", "emptyStateActionOutput"] }, { kind: "component", type: QdSearchComponent, selector: "qd-search", inputs: ["configData"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
28722
28908
  }
28723
28909
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdContextSelectDialogComponent, decorators: [{
28724
28910
  type: Component,
@@ -29002,8 +29188,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
29002
29188
 
29003
29189
  class QdPageCommitActionExecutor {
29004
29190
  static execute(action, values, context) {
29005
- const { formGroupManager, navigationInterceptor, destroyed$, onAfterSnapshot } = context;
29006
- const captured = formGroupManager.captureFormValues();
29191
+ const { formGroupManager, navigationInterceptor, destroyed$, onAfterSnapshot, scheduleFrameworkRebuildStop } = context;
29192
+ const captured = formGroupManager.createCurrentValuesSnapshot();
29007
29193
  let result$;
29008
29194
  navigationInterceptor.executeWithBypass(() => {
29009
29195
  const handlerResult = action.handler(values);
@@ -29011,7 +29197,9 @@ class QdPageCommitActionExecutor {
29011
29197
  result$ = handlerResult;
29012
29198
  });
29013
29199
  const applySuccess = () => {
29014
- formGroupManager.setFormGroupsSnapshot(captured);
29200
+ formGroupManager.updateSavedSnapshotFromValues(captured);
29201
+ formGroupManager.startAdoptingFrameworkRebuild();
29202
+ scheduleFrameworkRebuildStop?.();
29015
29203
  navigationInterceptor.executeWithBypass(() => {
29016
29204
  try {
29017
29205
  onAfterSnapshot?.();
@@ -29055,136 +29243,173 @@ class QdPageCommitActionExecutor {
29055
29243
  }
29056
29244
 
29057
29245
  /**
29058
- * The QdFormGroupManagerService provides centralized registration, snapshotting, and value tracking
29059
- * for multiple Angular `FormGroup` instances. It supports efficient state restoration, including dynamic
29060
- * resizing of embedded `FormArray` controls, while avoiding any structural cloning in snapshots.
29061
- *
29062
- * #### Purpose:
29063
- * This service is useful when managing multiple reactive forms that must be:
29064
- * - Observed for changes
29065
- * - Checked for validity
29066
- * - Compared against a previous state (snapshot)
29067
- * - Reset to a previous state, including dynamic form arrays
29068
- *
29069
- * #### Value Snapshot
29070
- * Snapshots store only **raw values** (via `getRawValue()`), not any control instances.
29071
- * This allows for minimal memory usage and easy comparison using deep equality checks.
29072
- *
29073
- * #### Smart FormArray Reset
29074
- * When restoring a `FormArray`, the service ensures that the number and structure of controls
29075
- * matches the snapshot values. Controls are cloned dynamically from an existing prototype.
29076
- * If a `FormArray` was emptied (e.g. via `removeAt()`), a minimal control structure is inferred
29077
- * from the snapshot data.
29078
- *
29079
- * #### Example Usage:
29080
- *
29081
- * **Register a FormGroup**
29082
- * ```ts
29083
- * service.setFormGroup('userForm', formGroup);
29084
- * ```
29085
- *
29086
- * **Take a Snapshot**
29087
- * ```ts
29088
- * service.takeFormGroupsSnapshot();
29089
- * ```
29090
- *
29091
- * **Detect Changes**
29092
- * ```ts
29093
- * service.$hasValuesChanged().subscribe(changed => {
29094
- * if (changed) {
29095
- * console.log('Form data has changed');
29096
- * }
29097
- * });
29098
- * ```
29099
- *
29100
- * **Restore from Snapshot**
29101
- * ```ts
29102
- * service.restoreFormGroupsFromSnapshot();
29103
- * ```
29104
- *
29105
- * **Check if All Forms Are Valid**
29106
- * ```ts
29107
- * service.$areFormGroupsValid().subscribe(valid => {
29108
- * if (valid) {
29109
- * console.log('All forms valid!');
29110
- * }
29111
- * });
29112
- * ```
29113
- *
29114
- * #### Notes:
29115
- * - FormArrays are not replaced during restore. Their length is adjusted and their content reset.
29116
- * - Control cloning is recursive and structure-preserving.
29117
- * - No structural information is stored in the snapshot; only data.
29246
+ * Central tracker for all reactive forms on a single QdPage.
29247
+ *
29248
+ * Its main job is to answer one question: **has the user changed anything since the last save?**
29249
+ * The page uses that answer to warn before leaving with unsaved changes.
29250
+ *
29251
+ * #### What it does
29252
+ * - **Registry** holds every form of the page and gives access to it.
29253
+ * - **Change detection** — keeps a snapshot of the saved values and compares the live form against it.
29254
+ * - **Restore** resets the forms back to the snapshot when the user discards changes.
29255
+ * - **Validity** reports whether all forms are valid and can cancel in-flight async validators.
29256
+ *
29257
+ * #### Adopting framework rebuilds
29258
+ * After a save, the consumer often rebuilds the form itself — a `FormArray` cleared and pushed
29259
+ * again, or a control replaced via `setControl`. A plain value compare would wrongly read that as a
29260
+ * user edit. To prevent that:
29261
+ *
29262
+ * - **What it does** right after each save or snapshot write, the framework briefly *adopts its
29263
+ * own rebuild* (`startAdoptingFrameworkRebuild`) and folds those control replacements into the
29264
+ * snapshot, so they count as already saved.
29265
+ * - **Why it is needed** — otherwise a rebuilt value (text `"99"` becoming number `99`) would look
29266
+ * like an unsaved change.
29267
+ * - **When it ends** — the page stops adopting once the rebuild has rendered
29268
+ * (`stopAdoptingFrameworkRebuild`).
29269
+ * - **User edits stay unsaved** — they always happen after that window, so they are still reported.
29270
+ * - **New keys need no window** — a control added under a key the snapshot does not know yet is
29271
+ * folded in right away, as long as it is pristine. So a conditionally shown empty field never
29272
+ * counts as an unsaved change. Only replacements of already known controls need the window.
29273
+ *
29274
+ * #### Notes
29275
+ * - Snapshots store only **raw values** (`getRawValue()`), never control instances — cheap to keep and compare.
29276
+ * - Restoring a `FormArray` adjusts its length and resets its contents; it never replaces the array instance.
29277
+ * - No structural information is stored in the snapshot, only data.
29118
29278
  */
29119
29279
  class QdFormGroupManagerService {
29120
29280
  _formGroups = new Map();
29121
29281
  _formGroupsSnapshot = new Map();
29282
+ _knownControlInstances = new Map();
29283
+ _isAdoptingFrameworkRebuild = false;
29284
+ _frameworkRebuildSub;
29122
29285
  _formGroupsChanged$ = new BehaviorSubject(undefined);
29286
+ _keysInInitialBuildup = new Set();
29287
+ /**
29288
+ * Registers a form under a key so the manager can track it.
29289
+ *
29290
+ * On first registration it also seeds the saved snapshot from the current values, so a freshly
29291
+ * registered form counts as unchanged until the user actually edits it.
29292
+ */
29123
29293
  setFormGroup(key, formGroup) {
29124
29294
  this._formGroups.set(key, formGroup);
29295
+ if (!this._formGroupsSnapshot.has(key)) {
29296
+ this._formGroupsSnapshot.set(key, formGroup.getRawValue());
29297
+ this.rememberControlInstances(key, formGroup);
29298
+ this._keysInInitialBuildup.add(key);
29299
+ }
29125
29300
  this._formGroupsChanged$.next();
29126
29301
  }
29302
+ /**
29303
+ * Returns the form registered under the given key, or `undefined` if none is registered.
29304
+ */
29127
29305
  getFormGroup(key) {
29128
29306
  return this._formGroups.get(key);
29129
29307
  }
29308
+ /**
29309
+ * Returns all registered forms, keyed by their registration key.
29310
+ */
29130
29311
  getAllFormGroups() {
29131
29312
  return this._formGroups;
29132
29313
  }
29133
- tryRemoveFormGroup(key) {
29134
- this._formGroups.delete(key);
29135
- this._formGroupsChanged$.next();
29136
- }
29314
+ /**
29315
+ * Returns `true` if at least one form is registered.
29316
+ */
29137
29317
  hasFormGroups() {
29138
29318
  return this._formGroups.size > 0;
29139
29319
  }
29320
+ /**
29321
+ * Returns `true` if no form is registered under the given key yet.
29322
+ */
29323
+ isFormGroupKeyUnique(key) {
29324
+ return !this._formGroups.has(key);
29325
+ }
29326
+ /**
29327
+ * Returns the current `.value` of every registered form, keyed by registration key.
29328
+ *
29329
+ * Uses Angular's `.value`, so disabled controls are omitted. Use the snapshot methods when you
29330
+ * need the raw values including disabled controls.
29331
+ */
29140
29332
  getAllValues() {
29141
29333
  const allValues = {};
29142
29334
  this._formGroups.forEach((formGroup, key) => (allValues[key] = formGroup.value));
29143
29335
  return allValues;
29144
29336
  }
29145
- isFormGroupKeyUnique(key) {
29146
- return !this._formGroups.has(key);
29337
+ /**
29338
+ * Unregisters the form under the given key and drops its instance tracking.
29339
+ *
29340
+ * Does nothing if no form is registered for the key.
29341
+ */
29342
+ tryRemoveFormGroup(key) {
29343
+ this._formGroups.delete(key);
29344
+ this._knownControlInstances.delete(key);
29345
+ this._keysInInitialBuildup.delete(key);
29346
+ this._formGroupsChanged$.next();
29147
29347
  }
29148
- $areFormGroupsValid() {
29149
- return this._formGroupsChanged$.pipe(observeOn(queueScheduler), switchMap$1(() => {
29150
- if (!this.hasFormGroups())
29151
- return of(false);
29152
- const obs = Array.from(this._formGroups.values()).map(fg => fg.statusChanges.pipe(startWith(fg.status), map(() => this.areFormGroupsValid(fg))));
29153
- return combineLatest(obs).pipe(map(valids => valids.every(Boolean)));
29154
- }));
29348
+ /**
29349
+ * Ends the initial-buildup phase for a key and fixes its baseline from the form as it is now.
29350
+ *
29351
+ * During that phase the key never counts as changed, so a form filled right after registration
29352
+ * (e.g. by an `effect`) is not flagged as unsaved. This stores the current values as the baseline,
29353
+ * so later edits are measured against the filled form.
29354
+ *
29355
+ * Does nothing if the key is not in its initial-buildup phase.
29356
+ */
29357
+ endInitialBuildup(key) {
29358
+ if (!this._keysInInitialBuildup.delete(key))
29359
+ return;
29360
+ const formGroup = this._formGroups.get(key);
29361
+ if (formGroup) {
29362
+ this._formGroupsSnapshot.set(key, formGroup.getRawValue());
29363
+ this.rememberControlInstances(key, formGroup);
29364
+ }
29365
+ this._formGroupsChanged$.next();
29155
29366
  }
29367
+ /**
29368
+ * Emits whether any registered form differs from its saved snapshot — i.e. whether the user has
29369
+ * unsaved changes.
29370
+ *
29371
+ * Framework-driven rebuilds are folded into the snapshot first while the framework is adopting
29372
+ * them (see the class docs), so they are not reported as changes.
29373
+ */
29156
29374
  $hasValuesChanged() {
29157
- return this._formGroupsChanged$.pipe(observeOn(queueScheduler), switchMap$1(() => {
29158
- if (!this.hasFormGroups())
29159
- return of(false);
29160
- const obs = Array.from(this._formGroups.entries()).map(([key, fg]) => fg.valueChanges.pipe(startWith(fg.getRawValue()), map(() => {
29161
- const currentValues = fg.getRawValue();
29162
- const snapshot = this._formGroupsSnapshot.get(key);
29163
- return snapshot ? !isEqual$1(currentValues, snapshot) : true;
29164
- })));
29165
- return combineLatest(obs).pipe(map(changes => changes.some(Boolean)));
29166
- }));
29375
+ return this._formGroupsChanged$.pipe(observeOn(queueScheduler), switchMap$1(() => this.anyRegisteredFormChanged$()));
29167
29376
  }
29168
- takeFormGroupsSnapshot() {
29169
- this._formGroups.forEach((fg, key) => this._formGroupsSnapshot.set(key, fg.getRawValue()));
29377
+ /**
29378
+ * Overwrites the saved snapshot with the **current** form values — for a **synchronous** save
29379
+ * that is already finished.
29380
+ *
29381
+ * - Stores each form's raw values (`getRawValue`) as the new saved snapshot.
29382
+ * - Takes them **directly, without a deep copy** — synchronous means no edits can slip in
29383
+ * between, so the cheap path is safe (only the async path needs the copy).
29384
+ * - Afterwards the current state counts as saved; later edits are measured against it.
29385
+ *
29386
+ * For an **asynchronous** save, use `createCurrentValuesSnapshot()` + `updateSavedSnapshotFromValues()`.
29387
+ */
29388
+ updateSavedSnapshotFromCurrentValues() {
29389
+ this._formGroups.forEach((fg, key) => {
29390
+ this._formGroupsSnapshot.set(key, fg.getRawValue());
29391
+ this.rememberControlInstances(key, fg);
29392
+ });
29170
29393
  }
29171
29394
  /**
29172
- * Captures a deep-cloned snapshot of all current form values without mutating internal state.
29395
+ * Creates an independent snapshot of the **current** form values and returns it — for the
29396
+ * **click moment** of an **asynchronous** save.
29173
29397
  *
29174
- * Used by framework orchestration code that needs to remember the "at click time" state of a form
29175
- * so the snapshot can later be set to exactly those values even if the user edits the form
29176
- * while an async commit action is pending.
29398
+ * - Deep-copies each form's raw values (`structuredClone`), detached from the live form.
29399
+ * - Writes **nothing** internally — the saved snapshot stays unchanged.
29400
+ * - Freezes the click-time state: later edits (while the backend runs) do not change the copy.
29401
+ * - Hand the result to `updateSavedSnapshotFromValues()` once the save succeeds.
29177
29402
  *
29178
29403
  * Throws if any form value is not structured-cloneable (functions, symbols, DOM nodes).
29179
29404
  */
29180
- captureFormValues() {
29405
+ createCurrentValuesSnapshot() {
29181
29406
  const captured = new Map();
29182
29407
  this._formGroups.forEach((fg, key) => {
29183
29408
  try {
29184
29409
  captured.set(key, structuredClone(fg.getRawValue()));
29185
29410
  }
29186
29411
  catch (err) {
29187
- throw new Error(`Quadrel Framework | QdFormGroupManager - captureFormValues() failed for group "${key}". ` +
29412
+ throw new Error(`Quadrel Framework | QdFormGroupManager - createCurrentValuesSnapshot() failed for group "${key}". ` +
29188
29413
  `Form values must be structured-cloneable. Non-cloneable values like functions, ` +
29189
29414
  `symbols, or DOM nodes are not supported. Original error: ${String(err)}`);
29190
29415
  }
@@ -29192,15 +29417,27 @@ class QdFormGroupManagerService {
29192
29417
  return captured;
29193
29418
  }
29194
29419
  /**
29195
- * Replaces the internal saved snapshot with the provided values.
29420
+ * Overwrites the saved snapshot with the **given** snapshot — on **success** of an
29421
+ * **asynchronous** save, using the snapshot taken earlier by `createCurrentValuesSnapshot()`.
29196
29422
  *
29197
- * Intended to be paired with `captureFormValues()` so that the snapshot can be set to the
29198
- * values present when a commit action was initiatedindependent of whether the user edited
29199
- * the form in the meantime.
29200
- */
29201
- setFormGroupsSnapshot(values) {
29202
- values.forEach((snapshot, key) => this._formGroupsSnapshot.set(key, snapshot));
29423
+ * - Stores the passed snapshot as the new saved state.
29424
+ * - Uses the click-time snapshot, **not** the current form so edits the user made while the
29425
+ * backend was running stay correctly marked as unsaved.
29426
+ */
29427
+ updateSavedSnapshotFromValues(snapshot) {
29428
+ snapshot.forEach((values, key) => {
29429
+ this._formGroupsSnapshot.set(key, values);
29430
+ const formGroup = this._formGroups.get(key);
29431
+ if (formGroup)
29432
+ this.rememberControlInstances(key, formGroup);
29433
+ });
29203
29434
  }
29435
+ /**
29436
+ * Resets every registered form back to its saved snapshot — used when the user discards changes.
29437
+ *
29438
+ * FormArrays are resized to match the snapshot length; pending async validators are cancelled
29439
+ * afterwards so no stale validation result survives the restore.
29440
+ */
29204
29441
  restoreFormGroupsFromSnapshot() {
29205
29442
  this._formGroups.forEach((fg, key) => {
29206
29443
  const snapshot = this._formGroupsSnapshot.get(key);
@@ -29211,68 +29448,171 @@ class QdFormGroupManagerService {
29211
29448
  this.cancelPendingAsyncValidation();
29212
29449
  }
29213
29450
  /**
29214
- * Cancels any in-flight async validators on all registered form groups.
29451
+ * Starts adopting framework rebuilds into the snapshot. While active, a framework-driven control
29452
+ * replacement (a `setControl` on a leaf or a whole `FormArray` rebuilt via clear/push) is folded
29453
+ * into the saved snapshot, so it is not reported as an unsaved change.
29454
+ *
29455
+ * User edits never fall in this short window, so they stay dirty. The framework starts it after a
29456
+ * successful commit and after every snapshot write; the page stops it deterministically once the
29457
+ * rebuild has rendered.
29458
+ */
29459
+ startAdoptingFrameworkRebuild() {
29460
+ this._isAdoptingFrameworkRebuild = true;
29461
+ this._frameworkRebuildSub?.unsubscribe();
29462
+ const valueStreams = Array.from(this._formGroups.values()).map(fg => fg.valueChanges);
29463
+ if (valueStreams.length)
29464
+ this._frameworkRebuildSub = merge(...valueStreams).subscribe(() => this.adoptFrameworkRebuild());
29465
+ this.adoptFrameworkRebuild();
29466
+ }
29467
+ /**
29468
+ * Stops adopting framework rebuilds. After this, control replacements count as user edits again.
29469
+ *
29470
+ * The page calls this once the framework rebuild has rendered (via `afterNextRender`).
29471
+ */
29472
+ stopAdoptingFrameworkRebuild() {
29473
+ this._isAdoptingFrameworkRebuild = false;
29474
+ this._frameworkRebuildSub?.unsubscribe();
29475
+ }
29476
+ /**
29477
+ * Emits whether every registered form is currently valid.
29478
+ *
29479
+ * A disabled control without validators is treated as valid.
29480
+ */
29481
+ $areFormGroupsValid() {
29482
+ return this._formGroupsChanged$.pipe(observeOn(queueScheduler), switchMap$1(() => {
29483
+ if (!this.hasFormGroups())
29484
+ return of(false);
29485
+ const obs = Array.from(this._formGroups.values()).map(fg => fg.statusChanges.pipe(startWith(fg.status), map(() => this.areFormGroupsValid(fg))));
29486
+ return combineLatest(obs).pipe(map(valids => valids.every(Boolean)));
29487
+ }));
29488
+ }
29489
+ /**
29490
+ * Cancels every in-flight (PENDING) async validator across all registered forms, so no stale
29491
+ * validation result can land after a restore or a commit.
29215
29492
  *
29216
- * 1. Collect all PENDING controls and their async validators
29217
- * 2. Clear all async validators, then update validity (sync-only, no cascade)
29218
- * 3. Re-attach async validators for future use
29493
+ * The async validators themselves are kept only the pending run is dropped. Each phase runs
29494
+ * over **all** pending controls before the next starts (detach → re-evaluate sync-only, no
29495
+ * cascade → re-attach), so validity is never recomputed while a run is still settling.
29219
29496
  */
29220
29497
  cancelPendingAsyncValidation() {
29221
29498
  this._formGroups.forEach(fg => {
29222
29499
  const pendingControls = this.collectPendingControls(fg);
29223
29500
  if (pendingControls.length === 0)
29224
29501
  return;
29225
- for (const { control } of pendingControls) {
29226
- control.clearAsyncValidators();
29227
- }
29228
- for (const { control } of pendingControls) {
29229
- control.updateValueAndValidity({ onlySelf: true });
29230
- }
29231
- for (const { control, asyncValidator } of pendingControls) {
29232
- control.setAsyncValidators(asyncValidator);
29233
- }
29502
+ pendingControls.forEach(({ control }) => control.clearAsyncValidators());
29503
+ pendingControls.forEach(({ control }) => control.updateValueAndValidity({ onlySelf: true }));
29504
+ pendingControls.forEach(({ control, asyncValidator }) => control.setAsyncValidators(asyncValidator));
29234
29505
  });
29235
29506
  }
29236
- restoreFormGroup(fg, snapshot) {
29237
- Object.entries(fg.controls).forEach(([ctrlKey, ctrl]) => {
29238
- const newValue = snapshot[ctrlKey];
29239
- if (ctrl instanceof FormArray && Array.isArray(newValue)) {
29240
- this.resetFormArrayToValues(ctrl, newValue);
29241
- }
29242
- else if (ctrl instanceof FormGroup && newValue && typeof newValue === 'object') {
29243
- this.restoreFormGroup(ctrl, newValue);
29244
- }
29245
- else {
29246
- ctrl.reset(newValue);
29247
- }
29507
+ anyRegisteredFormChanged$() {
29508
+ if (!this.hasFormGroups())
29509
+ return of(false);
29510
+ const perForm = Array.from(this._formGroups.entries()).map(([key, fg]) => fg.valueChanges.pipe(startWith(null), map(() => this.hasFormChanged(key, fg))));
29511
+ return combineLatest(perForm).pipe(map(flags => flags.some(Boolean)));
29512
+ }
29513
+ hasFormChanged(key, fg) {
29514
+ if (this._keysInInitialBuildup.has(key))
29515
+ return false;
29516
+ const snapshot = this._formGroupsSnapshot.get(key);
29517
+ if (snapshot)
29518
+ this.adoptRebuildInGroup(key, fg, snapshot);
29519
+ return snapshot ? !isEqual$1(fg.getRawValue(), snapshot) : true;
29520
+ }
29521
+ adoptFrameworkRebuild() {
29522
+ this._formGroups.forEach((fg, key) => {
29523
+ const snapshot = this._formGroupsSnapshot.get(key);
29524
+ if (snapshot)
29525
+ this.adoptRebuildInGroup(key, fg, snapshot);
29248
29526
  });
29249
29527
  }
29250
- collectPendingControls(control) {
29251
- const result = [];
29252
- if (control instanceof FormGroup) {
29253
- Object.values(control.controls).forEach(c => result.push(...this.collectPendingControls(c)));
29254
- }
29255
- else if (control instanceof FormArray) {
29256
- control.controls.forEach(c => result.push(...this.collectPendingControls(c)));
29257
- }
29258
- if (control.status === 'PENDING') {
29259
- result.push({ control, asyncValidator: control.asyncValidator });
29528
+ adoptRebuildInGroup(key, formGroup, snapshot) {
29529
+ const tracked = this._knownControlInstances.get(key) ?? new Map();
29530
+ this.adoptRebuiltControls(formGroup, snapshot, tracked, '');
29531
+ this._knownControlInstances.set(key, tracked);
29532
+ }
29533
+ adoptRebuiltControls(group, snapshot, tracked, prefix) {
29534
+ Object.entries(group.controls).forEach(([name, control]) => {
29535
+ const path = prefix ? `${prefix}.${name}` : name;
29536
+ const isNewKey = !(name in snapshot);
29537
+ if (control instanceof FormArray)
29538
+ this.adoptRebuiltList(control, snapshot, name, isNewKey);
29539
+ else if (control instanceof FormGroup)
29540
+ this.adoptRebuiltGroup(control, snapshot, name, isNewKey, tracked, path);
29541
+ else
29542
+ this.adoptRebuiltField(control, snapshot, name, isNewKey, tracked.get(path));
29543
+ tracked.set(path, control);
29544
+ });
29545
+ }
29546
+ adoptRebuiltList(control, snapshot, name, isNewKey) {
29547
+ if (isNewKey) {
29548
+ this.adoptNewPristineControl(control, snapshot, name);
29549
+ return;
29260
29550
  }
29261
- return result;
29551
+ if (!this.isAdoptableArrayRebuild(control, snapshot, name))
29552
+ return;
29553
+ const snapshotArray = snapshot[name];
29554
+ const currentArray = control.getRawValue();
29555
+ if (currentArray.length === snapshotArray.length && !isEqual$1(currentArray, snapshotArray))
29556
+ snapshot[name] = currentArray;
29557
+ }
29558
+ adoptRebuiltGroup(group, snapshot, name, isNewKey, tracked, path) {
29559
+ if (isNewKey)
29560
+ this.adoptNewPristineControl(group, snapshot, name);
29561
+ const nested = snapshot[name];
29562
+ if (this.isPlainObject(nested))
29563
+ this.adoptRebuiltControls(group, nested, tracked, path);
29564
+ }
29565
+ adoptRebuiltField(control, snapshot, name, isNewKey, known) {
29566
+ if (isNewKey)
29567
+ this.adoptNewPristineControl(control, snapshot, name);
29568
+ else if (this.isReplacedPristineControl(control, known))
29569
+ snapshot[name] = control.getRawValue();
29570
+ }
29571
+ adoptNewPristineControl(control, snapshot, name) {
29572
+ if (control.pristine)
29573
+ snapshot[name] = control.getRawValue();
29574
+ }
29575
+ isAdoptableArrayRebuild(control, snapshot, name) {
29576
+ return this._isAdoptingFrameworkRebuild && control.pristine && Array.isArray(snapshot[name]);
29577
+ }
29578
+ isReplacedPristineControl(control, known) {
29579
+ return this._isAdoptingFrameworkRebuild && !!known && known !== control && control.pristine;
29580
+ }
29581
+ rememberControlInstances(key, formGroup) {
29582
+ const tracked = new Map();
29583
+ this.collectControlInstances(formGroup, tracked, '');
29584
+ this._knownControlInstances.set(key, tracked);
29585
+ }
29586
+ collectControlInstances(group, tracked, prefix) {
29587
+ Object.entries(group.controls).forEach(([name, control]) => {
29588
+ const path = prefix ? `${prefix}.${name}` : name;
29589
+ tracked.set(path, control);
29590
+ if (control instanceof FormGroup)
29591
+ this.collectControlInstances(control, tracked, path);
29592
+ });
29593
+ }
29594
+ restoreFormGroup(fg, snapshot) {
29595
+ Object.entries(fg.controls).forEach(([ctrlKey, ctrl]) => this.restoreControl(ctrl, snapshot[ctrlKey]));
29596
+ }
29597
+ restoreControl(ctrl, newValue) {
29598
+ if (ctrl instanceof FormArray && Array.isArray(newValue))
29599
+ this.resetFormArrayToValues(ctrl, newValue);
29600
+ else if (ctrl instanceof FormGroup && this.isPlainObject(newValue))
29601
+ this.restoreFormGroup(ctrl, newValue);
29602
+ else
29603
+ ctrl.reset(newValue);
29604
+ }
29605
+ isPlainObject(value) {
29606
+ return !!value && typeof value === 'object';
29262
29607
  }
29263
29608
  resetFormArrayToValues(array, newValues) {
29264
29609
  if (!Array.isArray(newValues))
29265
29610
  return;
29266
- const oldLen = array.length;
29267
- const newLen = newValues.length;
29268
- if (oldLen === 0 && newLen === 0)
29611
+ if (array.length === 0 && newValues.length === 0)
29269
29612
  return;
29270
- if (oldLen === 0 && newLen > 0)
29613
+ if (array.length === 0)
29271
29614
  return this.initFormArrayFromValues(array, newValues);
29272
- while (array.length < newLen)
29273
- array.push(this.deepCloneControl(array.at(0)));
29274
- while (array.length > newLen)
29275
- array.removeAt(array.length - 1);
29615
+ this.resizeFormArray(array, newValues.length);
29276
29616
  array.reset(newValues);
29277
29617
  }
29278
29618
  initFormArrayFromValues(array, values) {
@@ -29288,6 +29628,12 @@ class QdFormGroupManagerService {
29288
29628
  }
29289
29629
  array.reset(values);
29290
29630
  }
29631
+ resizeFormArray(array, length) {
29632
+ while (array.length < length)
29633
+ array.push(this.deepCloneControl(array.at(0)));
29634
+ while (array.length > length)
29635
+ array.removeAt(array.length - 1);
29636
+ }
29291
29637
  deepCloneControl(control) {
29292
29638
  if (control instanceof FormControl)
29293
29639
  return new FormControl(undefined, control.validator, control.asyncValidator);
@@ -29305,6 +29651,19 @@ class QdFormGroupManagerService {
29305
29651
  areFormGroupsValid(fg) {
29306
29652
  return Object.values(fg.controls).every(c => (c.disabled && !c.validator && !c.asyncValidator ? true : c.valid));
29307
29653
  }
29654
+ collectPendingControls(control) {
29655
+ const result = this.childControlsOf(control).flatMap(child => this.collectPendingControls(child));
29656
+ if (control.status === 'PENDING')
29657
+ result.push({ control, asyncValidator: control.asyncValidator });
29658
+ return result;
29659
+ }
29660
+ childControlsOf(control) {
29661
+ if (control instanceof FormGroup)
29662
+ return Object.values(control.controls);
29663
+ if (control instanceof FormArray)
29664
+ return control.controls;
29665
+ return [];
29666
+ }
29308
29667
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormGroupManagerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29309
29668
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormGroupManagerService });
29310
29669
  }
@@ -29333,7 +29692,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
29333
29692
  * - The page switches to view mode via `deactivate()`.
29334
29693
  *
29335
29694
  * The service has no concept of "pending actions" or bypass windows. Framework actions update the
29336
- * saved snapshot directly via `QdFormGroupManagerService.setFormGroupsSnapshot(...)`; cancel-discard
29695
+ * saved snapshot directly via `QdFormGroupManagerService.updateSavedSnapshotFromValues(...)`; cancel-discard
29337
29696
  * flows reset the form to the saved snapshot via `restoreFormGroupsFromSnapshot()`. Either way, the
29338
29697
  * interceptor only observes the resulting form state — there is no time window where a bypass is active.
29339
29698
  */
@@ -29483,6 +29842,7 @@ class QdPageObjectHeaderComponent {
29483
29842
  confirmationDialogService = inject(QdConfirmationDialogOpenerService);
29484
29843
  contextService = inject(QdContextService);
29485
29844
  resolverTriggerService = inject(QdResolverTriggerService);
29845
+ injector = inject(Injector);
29486
29846
  pageStoreService = inject(QdPageStoreService);
29487
29847
  config;
29488
29848
  hasNavigation = false;
@@ -29603,7 +29963,7 @@ class QdPageObjectHeaderComponent {
29603
29963
  this.setupResolverTrigger();
29604
29964
  this.updateCustomActions();
29605
29965
  this.subscribeToMetadataStream();
29606
- this.formGroupManagerService.takeFormGroupsSnapshot();
29966
+ this.formGroupManagerService.updateSavedSnapshotFromCurrentValues();
29607
29967
  this.initContexts();
29608
29968
  }
29609
29969
  ngOnChanges(changes) {
@@ -29628,7 +29988,7 @@ class QdPageObjectHeaderComponent {
29628
29988
  return this.config.headerFacets != null;
29629
29989
  }
29630
29990
  edit() {
29631
- this.formGroupManagerService.takeFormGroupsSnapshot();
29991
+ this.formGroupManagerService.updateSavedSnapshotFromCurrentValues();
29632
29992
  this.pageStoreService.toggleViewonly(false);
29633
29993
  if (this.editButton?.handler)
29634
29994
  this.editButton.handler();
@@ -29658,7 +30018,8 @@ class QdPageObjectHeaderComponent {
29658
30018
  onAfterSnapshot: () => {
29659
30019
  this.formGroupManagerService.cancelPendingAsyncValidation();
29660
30020
  this.pageStoreService.toggleViewonly(true);
29661
- }
30021
+ },
30022
+ scheduleFrameworkRebuildStop: () => afterNextRender(() => this.formGroupManagerService.stopAdoptingFrameworkRebuild(), { injector: this.injector })
29662
30023
  });
29663
30024
  }
29664
30025
  changeContext(context, selection, event) {
@@ -29686,7 +30047,7 @@ class QdPageObjectHeaderComponent {
29686
30047
  .pipe(takeUntil(this._destroyed$), filter(shouldTrigger => shouldTrigger), tap(() => this._isLoadingSubject.next(true)), switchMap(() => this.pageObjectResolver.resolve()), tap(objectData => {
29687
30048
  this._pageObjectDataSubject.next({ ...objectData, ...this._pendingMetadata });
29688
30049
  this._pendingMetadata = {};
29689
- }), tap(() => this._isLoadingSubject.next(false)), tap(() => this.formGroupManagerService.takeFormGroupsSnapshot()))
30050
+ }), tap(() => this._isLoadingSubject.next(false)), tap(() => this.formGroupManagerService.updateSavedSnapshotFromCurrentValues()))
29690
30051
  .subscribe();
29691
30052
  }
29692
30053
  initContexts() {
@@ -29877,7 +30238,7 @@ class QdPageStepperCancelDialogComponent {
29877
30238
  </button>
29878
30239
  <button qdButton (click)="close(true)">{{ 'i18n.qd.stepper.cancel.dialog.delete' | translate }}</button>
29879
30240
  </qd-dialog-action>
29880
- </qd-dialog> `, isInline: true, dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30241
+ </qd-dialog> `, isInline: true, dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "component", type: QdTextSectionComponent, selector: "qd-text-section" }, { kind: "component", type: QdTextSectionParagraphComponent, selector: "qd-text-section-paragraph" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29881
30242
  }
29882
30243
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageStepperCancelDialogComponent, decorators: [{
29883
30244
  type: Component,
@@ -31464,6 +31825,7 @@ class QdPageComponent {
31464
31825
  bottomOffset$ = inject(QD_SAFE_BOTTOM_OFFSET, { optional: true });
31465
31826
  dialogRef = inject(DialogRef, { optional: true });
31466
31827
  navigationInterceptor = inject(QdPageNavigationInterceptorService);
31828
+ injector = inject(Injector);
31467
31829
  confirmationDialogService = inject(QdConfirmationDialogOpenerService);
31468
31830
  /**
31469
31831
  * This property defines the configuration for the QdPage component, including the page type,
@@ -31660,7 +32022,10 @@ class QdPageComponent {
31660
32022
  QdPageCommitActionExecutor.execute(action, values, {
31661
32023
  formGroupManager: this.formGroupManagerService,
31662
32024
  navigationInterceptor: this.navigationInterceptor,
31663
- destroyed$: this._destroyed$
32025
+ destroyed$: this._destroyed$,
32026
+ scheduleFrameworkRebuildStop: () => afterNextRender(() => this.formGroupManagerService.stopAdoptingFrameworkRebuild(), {
32027
+ injector: this.injector
32028
+ })
31664
32029
  });
31665
32030
  };
31666
32031
  }
@@ -31772,6 +32137,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
31772
32137
  * - Snapshots store only raw values and are taken by the page/header workflow (e.g. on init, edit, save). The confirmation dialog may restore all registered form groups from the snapshot.
31773
32138
  * - FormArrays are restored with dynamic resizing (length is aligned to snapshot before values are reset).
31774
32139
  *
32140
+ * ### **Filling a form right after connecting it**
32141
+ * - You can fill a connected form right after registration — e.g. an `effect` that adds controls or pushes `FormArray` rows. This first fill is the form's starting point, not a user change.
32142
+ * - So loading data into a fresh form never triggers a false "unsaved changes" prompt. Only later edits count.
32143
+ * - This only covers fills that happen right after registration, in the same task. Data that arrives later — e.g. an HTTP response — counts as a user change. For async loads, render the form only once the data is there (e.g. with `@if`).
32144
+ *
31775
32145
  * ### **Page-Dialog (FullWidth) – Unsaved-Changes Close Contract**
31776
32146
  * - When a QdPage is embedded in a full-width page dialog, the directive’s registered form groups are also used to guard dialog closing.
31777
32147
  * - The page dialog can only close (e.g. via ESC or backdrop) if no unsaved changes are detected ($hasValuesChanged() is false).
@@ -31784,8 +32154,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
31784
32154
  * ```html
31785
32155
  * <qd-page [config]="pageConfig">
31786
32156
  * <qd-section [config]="sectionConfig">
31787
- * <qd-grid [formGroup]="myFormGroup" qdConnectFormStateToPage="myFormGroup">
31788
- * My Section
32157
+ * <qd-grid
32158
+ * qdConnectFormStateToPage="myFormGroup"
32159
+ * [formGroup]="myFormGroup">
32160
+ * My Section
31789
32161
  * </qd-grid>
31790
32162
  * </qd-section>
31791
32163
  * </qd-page>
@@ -31805,36 +32177,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
31805
32177
  class QdConnectFormStateToPageDirective {
31806
32178
  formGroupManagerService = inject(QdFormGroupManagerService, { optional: true });
31807
32179
  formGroupDirective = inject(FormGroupDirective, { host: true, optional: true });
32180
+ closeInitialBuildupHandle;
31808
32181
  /**
31809
32182
  * This key is used to manage and track the form state within the page. It has to be unique for each FormGroup Connector. Use the property name of the FormGroup in your component.
31810
32183
  */
31811
32184
  qdConnectFormStateToPage;
31812
32185
  ngOnInit() {
31813
- if (!this.isValid())
31814
- return;
31815
32186
  const formGroup = this.formGroupDirective?.control;
31816
- if (formGroup && this.qdConnectFormStateToPage) {
31817
- this.formGroupManagerService.setFormGroup(this.qdConnectFormStateToPage, formGroup);
31818
- }
31819
- }
31820
- ngOnDestroy() {
31821
- this.formGroupManagerService?.tryRemoveFormGroup(this.qdConnectFormStateToPage);
31822
- }
31823
- isValid() {
31824
- const hasFormGroup = this.formGroupDirective?.control;
31825
- if (!hasFormGroup) {
32187
+ if (!formGroup) {
31826
32188
  console.error('Quadrel Framework | QdConnectFormStateToPage - Either a [formGroup] binding or <qd-quick-edit> with a FormGroup is required.');
31827
- return false;
32189
+ return;
31828
32190
  }
31829
32191
  if (!this.formGroupManagerService) {
31830
32192
  console.error('Quadrel Framework | QdConnectFormStateToPage - The connector must be used within <qd-page>.');
31831
- return false;
32193
+ return;
31832
32194
  }
31833
32195
  if (!this.formGroupManagerService.isFormGroupKeyUnique(this.qdConnectFormStateToPage)) {
31834
32196
  console.error(`Quadrel Framework | QdConnectFormStateToPage - The FormGroup key "${this.qdConnectFormStateToPage}" is not unique.`);
31835
- return false;
32197
+ return;
31836
32198
  }
31837
- return true;
32199
+ this.formGroupManagerService.setFormGroup(this.qdConnectFormStateToPage, formGroup);
32200
+ this.scheduleInitialBaseline(this.formGroupManagerService);
32201
+ }
32202
+ ngOnDestroy() {
32203
+ if (this.closeInitialBuildupHandle)
32204
+ clearTimeout(this.closeInitialBuildupHandle);
32205
+ this.formGroupManagerService?.tryRemoveFormGroup(this.qdConnectFormStateToPage);
32206
+ }
32207
+ scheduleInitialBaseline(manager) {
32208
+ const key = this.qdConnectFormStateToPage;
32209
+ this.closeInitialBuildupHandle = setTimeout(() => manager.endInitialBuildup(key));
31838
32210
  }
31839
32211
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdConnectFormStateToPageDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
31840
32212
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdConnectFormStateToPageDirective, isStandalone: false, selector: "[qdConnectFormStateToPage]", inputs: { qdConnectFormStateToPage: "qdConnectFormStateToPage" }, ngImport: i0 });
@@ -33767,7 +34139,7 @@ class AddCommentDialogComponent {
33767
34139
  };
33768
34140
  }
33769
34141
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AddCommentDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: AddCommentDialogComponent, isStandalone: false, selector: "qd-comment-dialog", ngImport: i0, template: "<qd-dialog>\n <form [formGroup]=\"form\">\n <qd-input [config]=\"authorInputConfig\"></qd-input>\n <qd-dropdown\n *ngIf=\"customInputConfig\"\n [config]=\"customInputConfig\"\n [formControlName]=\"'custom'\"\n [attr.data-test-id]=\"'comment-custom'\"\n ></qd-dropdown>\n\n <qd-richtext [config]=\"richtextConfig\" #commentText [formControlName]=\"'comment'\"> </qd-richtext>\n </form>\n <qd-dialog-action>\n <button qdButton qdButtonGhost color=\"secondary\" (click)=\"close()\" [data-test-id]=\"'button-cancel'\">\n {{ \"i18n.qd.comments.add.dialog.cancel\" | translate }}\n </button>\n <button\n [disabled]=\"!commentText.value || commentText.hasError\"\n qdButton\n (click)=\"close('Yes')\"\n [data-test-id]=\"'button-submit'\"\n >\n {{ \"i18n.qd.comments.add.dialog.submit\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [".validation-message{margin-top:4px;color:red;font-size:.875em}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdRichtextComponent, selector: "qd-richtext", inputs: ["formControlName", "value", "config", "data-test-id"], outputs: ["valueChange", "clickHint", "clickReadonly", "clickViewonly"] }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
34142
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: AddCommentDialogComponent, isStandalone: false, selector: "qd-comment-dialog", ngImport: i0, template: "<qd-dialog>\n <form [formGroup]=\"form\">\n <qd-input [config]=\"authorInputConfig\"></qd-input>\n <qd-dropdown\n *ngIf=\"customInputConfig\"\n [config]=\"customInputConfig\"\n [formControlName]=\"'custom'\"\n [attr.data-test-id]=\"'comment-custom'\"\n ></qd-dropdown>\n\n <qd-richtext [config]=\"richtextConfig\" #commentText [formControlName]=\"'comment'\"> </qd-richtext>\n </form>\n <qd-dialog-action>\n <button qdButton qdButtonGhost color=\"secondary\" (click)=\"close()\" [data-test-id]=\"'button-cancel'\">\n {{ \"i18n.qd.comments.add.dialog.cancel\" | translate }}\n </button>\n <button\n [disabled]=\"!commentText.value || commentText.hasError\"\n qdButton\n (click)=\"close('Yes')\"\n [data-test-id]=\"'button-submit'\"\n >\n {{ \"i18n.qd.comments.add.dialog.submit\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [".validation-message{margin-top:4px;color:red;font-size:.875em}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "dropdownOpened", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdRichtextComponent, selector: "qd-richtext", inputs: ["formControlName", "value", "config", "data-test-id"], outputs: ["valueChange", "clickHint", "clickReadonly", "clickViewonly"] }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog", inputs: ["data-test-id"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33771
34143
  }
33772
34144
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AddCommentDialogComponent, decorators: [{
33773
34145
  type: Component,
@@ -35000,7 +35372,7 @@ class QdQuickEditComponent {
35000
35372
  this.controlContainer.control.valueChanges.pipe(tap(() => this.changeDetectorRef.detectChanges())).subscribe();
35001
35373
  }
35002
35374
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdQuickEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
35003
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdQuickEditComponent, isStandalone: false, selector: "qd-quick-edit", inputs: { config: "config", data: "data", testId: ["data-test-id", "testId"] }, outputs: { formGroupChange: "formGroupChange", addNewClicked: "addNewClicked" }, viewQueries: [{ propertyName: "customForDirective", first: true, predicate: QdCustomForDirective, descendants: true }, { propertyName: "focusables", predicate: QdFocusableDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"editable-actions\" *ngIf=\"showStandaloneCreate\">\n <button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n (click)=\"createRow()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n class=\"create-button-standalone\"\n >\n {{ config.standaloneCreateLabel?.i18n ?? \"i18n.qd.quick.edit.createButtonLabel\" | translate }}\n </button>\n</div>\n\n<div class=\"table\" [formGroup]=\"control\">\n <div class=\"table-header\" *ngIf=\"!config.canAdd || templateData.length > 0 || config.emptyStateView\">\n <div class=\"table-row\">\n <div class=\"table-cell\" *ngFor=\"let header of visibleColumns\">\n {{ header?.i18n | translate }}\n <qd-tooltip-icon [tooltip]=\"header?.tooltip\"></qd-tooltip-icon>\n </div>\n <div class=\"table-cell actions-column\" *ngIf=\"hasVisibleActions$ | async\">\n <button class=\"menu-button\">\n <qd-icon icon=\"overflowMenuHorizontal\"></qd-icon>\n </button>\n </div>\n </div>\n </div>\n <div class=\"table-body\">\n <div\n class=\"table-row\"\n *qdCustomFor=\"let row of templateData; let rowIndex = index; toggler: togglerDrawing\"\n [formGroupName]=\"rowIndex\"\n [attr.data-test-id]=\"testId + '-row-' + rowIndex\"\n >\n <ng-container *ngFor=\"let column of visibleColumns; trackBy: trackByColumnName\">\n <div class=\"table-cell\">\n <qd-dropdown\n [config]=\"{\n filter: column.filter,\n options: column.options,\n placeholder: column.placeholder,\n placeholderPrefix: column.placeholderPrefix,\n viewonly: (viewonly$ | async) === true || !column.isEditable(row, column.name)\n }\"\n [data-test-id]=\"column.name + rowIndex\"\n *ngIf=\"column.type === 'enum'; else otherTypes\"\n [dense]=\"true\"\n [formControl]=\"$any(control.controls[rowIndex])?.controls[column.name]\"\n qdFocusable\n class=\"dropdown\"\n >\n </qd-dropdown>\n\n <ng-template #otherTypes>\n <qd-input\n [data-test-id]=\"column.name + rowIndex\"\n [formControlName]=\"column.name\"\n *ngIf=\"column.type !== 'enum' && $any(control.controls[rowIndex])?.controls[column.name]\"\n [config]=\"{\n inputType: column.type === 'integer' ? 'number' : 'text',\n viewonly: (viewonly$ | async) === true || !column.isEditable(row, column.name)\n }\"\n qdFocusable\n ></qd-input>\n </ng-template>\n </div>\n </ng-container>\n <td\n *ngIf=\"hasVisibleActions$ | async\"\n class=\"table-cell actions\"\n [attr.data-test-id]=\"testId + '-cell-inline-actions'\"\n >\n <button\n type=\"button\"\n [qdPopoverOnClick]=\"menu\"\n [qdPopoverCloseStrategy]=\"'onEveryClick'\"\n [qdPopoverStopPropagation]=\"true\"\n class=\"menu-button\"\n data-test=\"secondary-actions-toggler\"\n >\n <qd-icon icon=\"overflowMenuHorizontal\"></qd-icon>\n </button>\n\n <ng-template #menu>\n <button\n *ngFor=\"let secondaryAction of actions$ | async\"\n class=\"secondary-actions\"\n [ngClass]=\"{ disabled: isActionDisabled(secondaryAction, row) }\"\n [attr.disabled]=\"isActionDisabled(secondaryAction, row) || null\"\n (click)=\"handleSecondaryAction(secondaryAction, rowIndex)\"\n >\n {{ secondaryAction.label.i18n | translate }}\n </button>\n <button\n *ngIf=\"canAdd && (viewonly$ | async) === false\"\n class=\"secondary-actions\"\n (click)=\"removeRow(rowIndex)\"\n >\n {{ \"i18n.qd.quick.edit.removeButtonLabel\" | translate }}\n </button>\n </ng-template>\n </td>\n </div>\n </div>\n <div class=\"empty-body\" *ngIf=\"config.emptyStateView && !config.emptyStateView.disabled && templateData.length === 0\">\n <p>{{ config.emptyStateView.i18n | translate }}</p>\n </div>\n</div>\n", styles: [".table{display:flex;width:100%;flex-direction:column;margin:1.25rem auto;background-color:#fff;font-size:.875rem}.table ::ng-deep .qd-input-input{margin-bottom:0!important}.table-header .table-row{padding-top:.125rem;padding-bottom:.125rem;background-color:#e5e5e5;font-weight:700}.table-header .table-row .actions-column{border-right:none;visibility:hidden}.table-header,.table-body{display:flex;flex-direction:column}.table-row{display:flex;flex-direction:row;padding:.25rem 1rem;border-bottom:.0625rem solid rgb(213,213,213);gap:1rem}.table-row ::ng-deep qd-form-label{display:none!important}.table-row ::ng-deep qd-input{min-width:0;margin-bottom:0!important}.table-body .table-row:hover{background-color:#f5f5f5}.table-cell{display:flex;min-width:0;height:37px;flex:1;align-items:center;text-align:left}.table-cell:has(.qd-input-error),.table-cell:has(.qd-dropdown-error){height:auto;align-items:flex-start}.table-cell:has(.qd-input-character-counter){height:auto;align-items:flex-start}.table-cell:has(.qd-input-character-counter) ::ng-deep qd-input{position:relative}.table-cell:has(.qd-input-character-counter) ::ng-deep qd-input .qd-input-character-counter{position:absolute;right:.25rem;bottom:.125rem;font-size:.625rem;line-height:1;pointer-events:none}.table-cell.actions,.table-cell.actions-column{min-width:auto;flex:0 0 auto}.table-row:last-child{border-bottom:none}.table-cell:last-child{border-right:none}.editable-actions{display:flex;justify-content:flex-end;margin-right:.625rem;gap:.625rem}.menu-button{display:flex;padding:0 .625rem 0 .375rem;background:unset;color:#454545;font-size:2rem;vertical-align:middle}.menu-button:hover,.menu-button:focus{color:#000;outline:0!important}.secondary-actions{display:block;width:100%;min-height:2rem;padding:0 1rem;background:#fff0;font-size:.75rem;text-align:left}.secondary-actions:hover{background-color:#f2f7fa}.secondary-actions.disabled{color:#b4b4b4;cursor:not-allowed}.secondary-actions.disabled:hover{background-color:#fff0}.dropdown{width:100%;min-width:0}.empty-body{padding:1.5rem;background:#fff}.empty-body p{margin:0 0 .5rem}\n"], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "directive", type: QdFocusableDirective, selector: "[qdFocusable]" }, { kind: "component", type: QdTooltipIconComponent, selector: "qd-tooltip-icon", inputs: ["tooltip"] }, { kind: "directive", type: QdCustomForDirective, selector: "[qdCustomFor]", inputs: ["qdCustomForOf", "qdCustomForToggler"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35375
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdQuickEditComponent, isStandalone: false, selector: "qd-quick-edit", inputs: { config: "config", data: "data", testId: ["data-test-id", "testId"] }, outputs: { formGroupChange: "formGroupChange", addNewClicked: "addNewClicked" }, viewQueries: [{ propertyName: "customForDirective", first: true, predicate: QdCustomForDirective, descendants: true }, { propertyName: "focusables", predicate: QdFocusableDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"editable-actions\" *ngIf=\"showStandaloneCreate\">\n <button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n (click)=\"createRow()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n class=\"create-button-standalone\"\n >\n {{ config.standaloneCreateLabel?.i18n ?? \"i18n.qd.quick.edit.createButtonLabel\" | translate }}\n </button>\n</div>\n\n<div class=\"table\" [formGroup]=\"control\">\n <div class=\"table-header\" *ngIf=\"!config.canAdd || templateData.length > 0 || config.emptyStateView\">\n <div class=\"table-row\">\n <div class=\"table-cell\" *ngFor=\"let header of visibleColumns\">\n {{ header?.i18n | translate }}\n <qd-tooltip-icon [tooltip]=\"header?.tooltip\"></qd-tooltip-icon>\n </div>\n <div class=\"table-cell actions-column\" *ngIf=\"hasVisibleActions$ | async\">\n <button class=\"menu-button\">\n <qd-icon icon=\"overflowMenuHorizontal\"></qd-icon>\n </button>\n </div>\n </div>\n </div>\n <div class=\"table-body\">\n <div\n class=\"table-row\"\n *qdCustomFor=\"let row of templateData; let rowIndex = index; toggler: togglerDrawing\"\n [formGroupName]=\"rowIndex\"\n [attr.data-test-id]=\"testId + '-row-' + rowIndex\"\n >\n <ng-container *ngFor=\"let column of visibleColumns; trackBy: trackByColumnName\">\n <div class=\"table-cell\">\n <qd-dropdown\n [config]=\"{\n filter: column.filter,\n options: column.options,\n placeholder: column.placeholder,\n placeholderPrefix: column.placeholderPrefix,\n viewonly: (viewonly$ | async) === true || !column.isEditable(row, column.name)\n }\"\n [data-test-id]=\"column.name + rowIndex\"\n *ngIf=\"column.type === 'enum'; else otherTypes\"\n [dense]=\"true\"\n [formControl]=\"$any(control.controls[rowIndex])?.controls[column.name]\"\n qdFocusable\n class=\"dropdown\"\n >\n </qd-dropdown>\n\n <ng-template #otherTypes>\n <qd-input\n [data-test-id]=\"column.name + rowIndex\"\n [formControlName]=\"column.name\"\n *ngIf=\"column.type !== 'enum' && $any(control.controls[rowIndex])?.controls[column.name]\"\n [config]=\"{\n inputType: column.type === 'integer' ? 'number' : 'text',\n viewonly: (viewonly$ | async) === true || !column.isEditable(row, column.name)\n }\"\n qdFocusable\n ></qd-input>\n </ng-template>\n </div>\n </ng-container>\n <td\n *ngIf=\"hasVisibleActions$ | async\"\n class=\"table-cell actions\"\n [attr.data-test-id]=\"testId + '-cell-inline-actions'\"\n >\n <button\n type=\"button\"\n [qdPopoverOnClick]=\"menu\"\n [qdPopoverCloseStrategy]=\"'onEveryClick'\"\n [qdPopoverStopPropagation]=\"true\"\n class=\"menu-button\"\n data-test=\"secondary-actions-toggler\"\n >\n <qd-icon icon=\"overflowMenuHorizontal\"></qd-icon>\n </button>\n\n <ng-template #menu>\n <button\n *ngFor=\"let secondaryAction of actions$ | async\"\n class=\"secondary-actions\"\n [ngClass]=\"{ disabled: isActionDisabled(secondaryAction, row) }\"\n [attr.disabled]=\"isActionDisabled(secondaryAction, row) || null\"\n (click)=\"handleSecondaryAction(secondaryAction, rowIndex)\"\n >\n {{ secondaryAction.label.i18n | translate }}\n </button>\n <button\n *ngIf=\"canAdd && (viewonly$ | async) === false\"\n class=\"secondary-actions\"\n (click)=\"removeRow(rowIndex)\"\n >\n {{ \"i18n.qd.quick.edit.removeButtonLabel\" | translate }}\n </button>\n </ng-template>\n </td>\n </div>\n </div>\n <div class=\"empty-body\" *ngIf=\"config.emptyStateView && !config.emptyStateView.disabled && templateData.length === 0\">\n <p>{{ config.emptyStateView.i18n | translate }}</p>\n </div>\n</div>\n", styles: [".table{display:flex;width:100%;flex-direction:column;margin:1.25rem auto;background-color:#fff;font-size:.875rem}.table ::ng-deep .qd-input-input{margin-bottom:0!important}.table-header .table-row{padding-top:.125rem;padding-bottom:.125rem;background-color:#e5e5e5;font-weight:700}.table-header .table-row .actions-column{border-right:none;visibility:hidden}.table-header,.table-body{display:flex;flex-direction:column}.table-row{display:flex;flex-direction:row;padding:.25rem 1rem;border-bottom:.0625rem solid rgb(213,213,213);gap:1rem}.table-row ::ng-deep qd-form-label{display:none!important}.table-row ::ng-deep qd-input{min-width:0;margin-bottom:0!important}.table-body .table-row:hover{background-color:#f5f5f5}.table-cell{display:flex;min-width:0;height:37px;flex:1;align-items:center;text-align:left}.table-cell:has(.qd-input-error),.table-cell:has(.qd-dropdown-error){height:auto;align-items:flex-start}.table-cell:has(.qd-input-character-counter){height:auto;align-items:flex-start}.table-cell:has(.qd-input-character-counter) ::ng-deep qd-input{position:relative}.table-cell:has(.qd-input-character-counter) ::ng-deep qd-input .qd-input-character-counter{position:absolute;right:.25rem;bottom:.125rem;font-size:.625rem;line-height:1;pointer-events:none}.table-cell.actions,.table-cell.actions-column{min-width:auto;flex:0 0 auto}.table-row:last-child{border-bottom:none}.table-cell:last-child{border-right:none}.editable-actions{display:flex;justify-content:flex-end;margin-right:.625rem;gap:.625rem}.menu-button{display:flex;padding:0 .625rem 0 .375rem;background:unset;color:#454545;font-size:2rem;vertical-align:middle}.menu-button:hover,.menu-button:focus{color:#000;outline:0!important}.secondary-actions{display:block;width:100%;min-height:2rem;padding:0 1rem;background:#fff0;font-size:.75rem;text-align:left}.secondary-actions:hover{background-color:#f2f7fa}.secondary-actions.disabled{color:#b4b4b4;cursor:not-allowed}.secondary-actions.disabled:hover{background-color:#fff0}.dropdown{width:100%;min-width:0}.empty-body{padding:1.5rem;background:#fff}.empty-body p{margin:0 0 .5rem}\n"], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdDropdownComponent, selector: "qd-dropdown", inputs: ["value", "id", "formControlName", "config", "data-test-id", "qdPopoverMaxHeight", "dense"], outputs: ["valueChange", "enterClick", "dropdownOpened", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "component", type: QdInputComponent, selector: "qd-input", inputs: ["formControlName", "value", "config", "isError", "data-test-id"], outputs: ["valueChange", "enterClick", "clickClear", "clickHint", "clickReadonly", "clickViewonly", "optionsResolved"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon", "status"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "qdPopoverPlacement", "qdPopoverOffsetX", "qdPopoverOffsetY", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl", "qdPopoverFlipIntoViewport"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "directive", type: QdFocusableDirective, selector: "[qdFocusable]" }, { kind: "component", type: QdTooltipIconComponent, selector: "qd-tooltip-icon", inputs: ["tooltip"] }, { kind: "directive", type: QdCustomForDirective, selector: "[qdCustomFor]", inputs: ["qdCustomForOf", "qdCustomForToggler"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35004
35376
  }
35005
35377
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdQuickEditComponent, decorators: [{
35006
35378
  type: Component,